我正在努力想出一個更好的標題。
我是 Chisel 和 Scala 的新手。下面是定義和測驗模塊的 Chisel 代碼。
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)) 回傳一個TestBuilder[T]withapply方法:
class TestBuilder[T <: Module](...) {
...
def apply(testFn: T => Unit): TestResult = {
runTest(defaults.createDefaultTester(dutGen, finalAnnos))(testFn)
}
...
}
那么,dut => {...}是函式(T) => Unit嗎?但它看起來不像標準的 lambda ( (x:T) => {...})?或者是別的什么?
scala中的這種語法到底是什么?
uj5u.com熱心網友回復:
考慮以下具有類似結構的簡化版本:
def test[A](testedThing: A)(testBody: A => Unit): Unit = testBody(testedThing)
它本質上做的是獲取一個值x: A和一個函式f: A => Unit,并f應用于x獲取f(x)。
以下是您可以如何使用它:
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帶有一些花里胡哨的值(在這種情況下,“注釋”串列 - 以下示例中的純字串):
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添加一些配置,一旦你添加了一個body { thingUnderTest => /* assertStuff */ },你就會得到一個完整的Test,然后你可以run得到一些結果(TestOutcomes,在這種情況下)。因此,上面的代碼片段產生
TestOutcome(List(size of hello should be 5),true)
TestOutcome(List(size of hello should be 42),false)
uj5u.com熱心網友回復:
我想我沒有注意到有時我們可以在 lambda 中省略型別宣告。
class tester{
def apply( fn: (Int) => Int):Int = fn(5)
}
我們可以寫(new tester)(x => {x 1})而不是(new tester)((x:Int) => {x 1}).
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/519540.html
標籤:斯卡拉凿凿子测试
