首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Chisel测试中,dut是在哪里定义的?(关于Scala语法)

在Chisel测试中,dut是在哪里定义的?(关于Scala语法)
EN

Stack Overflow用户
提问于 2022-10-25 09:01:42
回答 2查看 51关注 0票数 1

我正努力想出一个更好的头衔。

我是奇塞尔和斯卡拉的新人。下面是定义和测试模块的Chisel代码。

代码语言:javascript
复制
import chisel3._
import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec

class DeviceUnderTest extends Module {
  val io = IO(new Bundle {
    val a = Input(UInt(2.W))
    val b = Input(UInt(2.W))
    val out = Output(UInt(2.W))
  })
  io.out := io.a & io.b
}

class WaveformTestWithIteration extends AnyFlatSpec with ChiselScalatestTester {
  "WaveformIteration" should "pass" in {
    test(new DeviceUnderTest)
      .withAnnotations(Seq(WriteVcdAnnotation)) ( dut => // ???
        {
          for (a <- 0 until 4; b <- 0 until 4) {
            dut.io.a.poke(a.U)
            dut.io.b.poke(b.U)
            dut.clock.step()
          }
        }
      )
  }
}

注释???的代码行使我感到非常困惑。变量dut在哪里定义?这似乎是对new DeviceUnderTest获得的实例的引用。

test(new DeviceUnderTest).withAnnotations(Seq(WriteVcdAnnotation))apply方法返回TestBuilder[T]

代码语言:javascript
复制
  class TestBuilder[T <: Module](...) {
    ...
    def apply(testFn: T => Unit): TestResult = {
      runTest(defaults.createDefaultTester(dutGen, finalAnnos))(testFn)
    }
    ...
  }

那么,dut => {...}是一个函数(T) => Unit吗?但是它看起来不像标准的lambda ((x:T) => {...})?或者是别的什么?

scala中的这个语法到底是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-10-25 10:08:02

考虑具有类似结构的以下简化版本:

代码语言:javascript
复制
def test[A](testedThing: A)(testBody: A => Unit): Unit = testBody(testedThing)

本质上,它所做的是获取一个值x: A和一个函数f: A => Unit,并将f应用于x以获得f(x)

下面是您如何使用它:

代码语言:javascript
复制
test("foo"){ x => 
  println(if x == "foo" then "Success" else "Failure")
} // Success

test("bar"){ x => 
  println(if x == "baz" then "Success" else "Failure")
} // Failure

在这两种情况下,“正在测试的字符串”被简单地传递到“测试”的主体。

现在,您可以在被测试的值的创建和主体的规范之间引入更多的步骤。例如,您可以创建一个TestBuilder[A],它本质上只是一个带有一些铃铛和哨声的值a (在本例中,“注释”列表--以下示例中的简单字符串):

代码语言:javascript
复制
type Annotation = String

case class TestOutcome(annotations: List[Annotation], successful: Boolean)

trait Test:
  def run: TestOutcome

// This simply captures the value under test of type `A`
case class TestBuilder[A](
  theThingUnderTest: A,
  annotations: List[Annotation]
):
  // Bells and whistles: adding some metadata
  def withAnnotations(moreAnnotations: List[Annotation]): TestBuilder[A] =
    TestBuilder(theThingUnderTest, annotations ++ moreAnnotations)

  // Combining the value under test with the body of the test produces the
  // actual test
  def apply(testBody: A => Unit): Test = new Test:
    def run =
      try {
        testBody(theThingUnderTest)
        TestOutcome(annotations, true)
      } catch {
        case t: Throwable => TestOutcome(annotations, false)
      }

// This constructs the thing that's being tested, and creates a TestBuilder around it
def test[A](thingUnderTest: A) = TestBuilder(thingUnderTest, Nil)

println(
  test("hello")
    .withAnnotations(List("size of hello should be 5")){ h =>
      assert(h.size == 5)
    }
    .run
)

println(
  test("hello")
    .withAnnotations(List("size of hello should be 42")){ h =>
      assert(h.size == 42)
    }
    .run
)

原理是一样的:test(a)保存测试值a,然后TestBuilder添加一些配置,一旦向它添加了一个TestBuilder { thingUnderTest => /* assertStuff */ },就可以得到一个完整的Test,然后可以通过run获得一些结果(在本例中是TestOutcome)。因此,上面的片段会产生

代码语言:javascript
复制
TestOutcome(List(size of hello should be 5),true)
TestOutcome(List(size of hello should be 42),false)
票数 1
EN

Stack Overflow用户

发布于 2022-10-25 10:08:16

我想我没有注意到有时我们可以省略lambda中的类型声明。

代码语言:javascript
复制
class tester{
  def  apply( fn: (Int) => Int):Int = fn(5)
}

我们可以编写(new tester)(x => {x+1})而不是(new tester)((x:Int) => {x+1})

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74191562

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档