对于从事软件开发的小伙伴来说,软件的测试框架琳琅满目。对于RTL设计验证而言,验证方式也尤为重要,本文将就在SpinalHDL里通过借助Scala的测试框架进行仿真验证进行说明。
SpinalHDL—基于Scala的测试框架
test case的组织
当我们对设计进行验证时,根据带测试模块的功能,我们会根据功能点来组织testcase,以上次提到的简单的加法器为例:
这里我们可以把测试case分为三类:
-
data1为0,data2取0至最大值之间的随机值。
-
data1为最大值,data2取0至最大值之间的随机值。
-
data2取0,data1取0值至最大值之间的随机值。
-
data2取最大值,data1取0值至最大值之间的随机值。
-
data1,data2随机取值。
用scala写测试
用scala写测试,有很多选择,从已被广泛认可的java工具,比如JUnit和tesetNG,到用scala编写的工具,比如scalaTest,specs2和ScalaCheck等等。
ScalaTest是最灵活的Scala测试框架,可以很容易的定制它来解决不同的问题。我们在进行仿真测试时引入ScalaTest测试框架需要在build.sbt中引入依赖项:
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % "test"
通过sbt工具构建完成后在我们的工程下引入了scalatest的jar包:
FunSuite
可以轻松编写描述性测试名称,自然地编写集中测试,并生成类似规范的输出:
import org.scalatest.FunSuite
//ScalaTest提供了名为FunSuite的特质重载了execute方法从而可以用函数值的方式,而不是方法定义测试
class SetSuite extends FunSuite {
/**
* test后面圆括号()内为测试名称,可以使用任何字符串,不需要传统的驼峰形式命名。
* !!!!!!!但是名称需要唯一!!!!!!!!!!!
* 圆括号后面的大括号{}之内定义的为测试代码。被作为传名参数传递给test函数,由test登记备用
*/
test("An empty Set should have size 0") {
assert(Set.empty.size == 0)
}
test("Invoking head on an empty Set should produce NoSuchElementException") {
assertThrows[NoSuchElementException] {
//intercept[NoSuchElementException] { 旧版本使用,现在仍可用
Set.empty.head
}
}
}
用scala写测试
引入scalatest测试框架,在我们上文所搭建好的addSImEnv,我们可以这么来组织我们的test case:
import org.scalatest._
import scala.util.Random._
import spinal.core.sim._
class addSimTb extends FunSuite {
val dut=SimConfig.withWave.withCoverage.compile(addSimEnv(10,8))
test("data1为0,data2取0至最大值之间的随机值"){
}
test("data1为最大值,data2取0至最大值之间的随机值"){
}
test("data2取0,data1取0值至最大值之间的随机值"){
}
test("data2取最大值,data1取0值至最大值之间的随机值"){
}
test("data1,data2随机取值"){
}
}
每个case的组织如下:
测试运行与报告生成
在Idea中,我们所编写的每个test可以单独运行,也可以回归全部运行,通过"Run addSImTb",我们可以运行所有的testCase:
除此之外,我们在测试完成之后,还可以生成html版的测试报告:
通过图中红框位置可生成测试报告addSImTb.html: