硬件设计中的测试通常叫作testbench,直译过来叫作测试工作台,后面还是用testbench来表达。testbench会实例化一个待测件DUT(Design Under Test,待测设计),驱动输入接口并观察输出接口,比较输出是否复合预期。
Chisel中提供了两个测试的方法,分别是chiseltest
包中的ChiselTest
和iotesters
包中的PeekPokeTester
。不过iotesters
在Chisel 3.5版本开始已经被弃用了,本系列因为是基于Chisel 3.5的,所以就不打算介绍iotesters
相关内容了,只介绍ChiselTest
相关内容。
Chisel的一个强大之处在于它可以利用Scala的强大功能来写testbench。比如说我们可以在软件模拟器中编写期望的硬件功能,然后把硬件仿真和软件仿真进行比较。这种方法在测试处理器的实现时非常高效。
接下来几篇文章我们就分别介绍Chisel中可能用到的四个测试框架,首先从ScalaTest
开始。
ScalaTest是Scala的测试工具,Chisel的测试工具ChiselTest也是ScalaTest的拓展。因此,我们首先学习一个简单的ScalaTest的例子。
要使用ScalaTest,首先需要在build.sbt
中包含对应的库,我们可以直接在最后加上一句:
libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.4" % "test"
也可以在Chisel-template中build.sbt
的基础上进行修改(在序列中添加):
libraryDependencies ++= Seq(
"edu.berkeley.cs" %% "chisel3" % chiselVersion,
"edu.berkeley.cs" %% "chiseltest" % "0.5.1" % "test",
"org.scalatest" %% "scalatest" % "3.1.4" % "test"
),
测试通常会在src/test/scala
文件夹下编写,运行整个测试可以用下面的指令:
sbt test
下面写一个简单的测试,测试Scala中的整数加法和乘法:
import org.scalatest._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class ExampleTest extends AnyFlatSpec with Matchers {
"Integers" should "add" in {
val i = 2
val j = 3
i + j should be (5)
}
"Integers" should "multiply" in {
val i = 3
val j = 4
i * j should be (12)
}
}
看起来有点复杂,仔细一读感觉都是大白话,尤其是should
和should be
,不像是写代码,但确实浅显易懂好记忆。ScalaTest就是支持这种读起来向可执行的规范一样的简单的单元测试。上面的例子中包含了两个测试,测试运行的输出会展示我们给出的规范并展示测试是否通过,输出如下:
这个语法其实很简单,把三个相关的包导入,剩下的照葫芦画瓢就行,就不多解释了。
sbt test
这个命令会执行所有的测试,这在递归测试里面很好用。不过如果我们想要运行单个测试或单个测试套件的话,可以用这条命令:
sbt "testOnly ExampleTest"
这里ExampleTest
就是我们向运行的测试的类,如果我们不小心拼错了,或者说没这个类,那他也不会报一个红色的错误,只会悄悄输出一句白色的结果:
[info] No tests to run for Test / testOnly
测试是数字设计很关键的一环,必须要好好掌握。ScalaTest相关内容还是很简单的,下一篇文章的ChiselTest才是重头戏。这一篇提到ChiselTest其实就是ScalaTest的拓展,所以也大差不差,知识语法上稍微有些区别,下一篇我们共同学习。