summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorHenry Cook2015-11-04 09:21:07 -0800
committerHenry Cook2015-11-04 09:21:07 -0800
commita3c9680d1e2b84693759747a4779341ba80c4a50 (patch)
treee97ab1d8394b0463ec7f600fce7ba278bd68d93a /src/test
parent23d15d166d2ed32f8bd9a153a806c09982659011 (diff)
Remove Parameters library and refactor Driver.
In addition to removing all the extraneous Driver invocations that created various top-level Parameters instances, this commit also lays the groundwork for stanza-firrtl/verilator based testing of Modules that extend BasicTester. The execution-based tests have been updated accordingly. They will only succeed if firrtl and verilator binaries have been installed. Further work is needed on individual tests to use assertions instead of .io.error.
Diffstat (limited to 'src/test')
-rw-r--r--src/test/scala/chiselTests/BitwiseOps.scala22
-rw-r--r--src/test/scala/chiselTests/BundleWire.scala16
-rw-r--r--src/test/scala/chiselTests/ChiselSpec.scala8
-rw-r--r--src/test/scala/chiselTests/ComplexAssign.scala28
-rw-r--r--src/test/scala/chiselTests/Counter.scala40
-rw-r--r--src/test/scala/chiselTests/Decoder.scala20
-rw-r--r--src/test/scala/chiselTests/GCD.scala26
-rw-r--r--src/test/scala/chiselTests/Harness.scala75
-rw-r--r--src/test/scala/chiselTests/MulLookup.scala16
-rw-r--r--src/test/scala/chiselTests/Tbl.scala30
-rw-r--r--src/test/scala/chiselTests/Vec.scala58
11 files changed, 206 insertions, 133 deletions
diff --git a/src/test/scala/chiselTests/BitwiseOps.scala b/src/test/scala/chiselTests/BitwiseOps.scala
index 86c7131b..d180c11e 100644
--- a/src/test/scala/chiselTests/BitwiseOps.scala
+++ b/src/test/scala/chiselTests/BitwiseOps.scala
@@ -7,18 +7,18 @@ import org.scalatest._
import org.scalatest.prop._
import Chisel.testers.BasicTester
-class BitwiseOpsSpec extends ChiselPropSpec {
+class BitwiseOpsTester(w: Int, _a: Int, _b: Int) extends BasicTester {
+ io.done := Bool(true)
+ val mask = (1 << w) - 1
+ val a = UInt(_a)
+ val b = UInt(_b)
+ when(~a != UInt(mask & ~_a)) { io.error := UInt(1) }
+ when((a & b) != UInt(mask & (_a & _b))) { io.error := UInt(2) }
+ when((a | b) != UInt(mask & (_a | _b))) { io.error := UInt(3) }
+ when((a ^ b) != UInt(mask & (_a ^ _b))) { io.error := UInt(4) }
+}
- class BitwiseOpsTester(w: Int, _a: Int, _b: Int) extends BasicTester {
- io.done := Bool(true)
- val mask = (1 << w) - 1
- val a = UInt(_a)
- val b = UInt(_b)
- when(~a != UInt(mask & ~_a)) { io.error := UInt(1) }
- when((a & b) != UInt(mask & (_a & _b))) { io.error := UInt(2) }
- when((a | b) != UInt(mask & (_a | _b))) { io.error := UInt(3) }
- when((a ^ b) != UInt(mask & (_a ^ _b))) { io.error := UInt(4) }
- }
+class BitwiseOpsSpec extends ChiselPropSpec {
property("All bit-wise ops should return the correct result") {
forAll(safeUIntPair) { case(w: Int, a: Int, b: Int) =>
diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala
index 99dc665f..5beed039 100644
--- a/src/test/scala/chiselTests/BundleWire.scala
+++ b/src/test/scala/chiselTests/BundleWire.scala
@@ -23,15 +23,15 @@ class BundleWire(n: Int) extends Module {
}
}
-class BundleWireSpec extends ChiselPropSpec {
+class BundleWireTester(n: Int, x: Int, y: Int) extends BasicTester {
+ val dut = Module(new BundleWire(n))
+ io.done := Bool(true)
+ dut.io.in.x := UInt(x)
+ dut.io.in.y := UInt(y)
+ io.error := dut.io.outs.map(o => o.x != UInt(x) || o.y != UInt(y)).foldLeft(UInt(0))(_##_)
+}
- class BundleWireTester(n: Int, x: Int, y: Int) extends BasicTester {
- val dut = Module(new BundleWire(n))
- io.done := Bool(true)
- dut.io.in.x := UInt(x)
- dut.io.in.y := UInt(y)
- io.error := dut.io.outs.map(o => o.x != UInt(x) || o.y != UInt(y)).foldLeft(UInt(0))(_##_)
- }
+class BundleWireSpec extends ChiselPropSpec {
property("All vec elems should match the inputs") {
forAll(vecSizes, safeUInts, safeUInts) { (n: Int, x: Int, y: Int) =>
diff --git a/src/test/scala/chiselTests/ChiselSpec.scala b/src/test/scala/chiselTests/ChiselSpec.scala
index 1fe77a0e..88aaf06c 100644
--- a/src/test/scala/chiselTests/ChiselSpec.scala
+++ b/src/test/scala/chiselTests/ChiselSpec.scala
@@ -10,8 +10,8 @@ import Chisel.testers._
/** Common utility functions for Chisel unit tests. */
trait ChiselRunners {
- def execute(t: => BasicTester): Boolean = TesterDriver.execute(t)
- def elaborate(t: => Module): Circuit = TesterDriver.elaborate(t)
+ def execute(t: => BasicTester): Boolean = TesterDriver.execute(() => t)
+ def elaborate(t: => Module): Circuit = Driver.elaborate(() => t)
}
/** Spec base class for BDD-style testers. */
@@ -19,11 +19,9 @@ class ChiselFlatSpec extends FlatSpec with ChiselRunners with Matchers
/** Spec base class for property-based testers. */
class ChiselPropSpec extends PropSpec with ChiselRunners with PropertyChecks {
- /** Returns the number of 1s in the binary representation of the input. */
- def popCount(n: Long): Int = n.toBinaryString.count(_ == '1')
// Generator for small positive integers.
- val smallPosInts = Gen.choose(1, 7)
+ val smallPosInts = Gen.choose(1, 4)
// Generator for widths considered "safe".
val safeUIntWidth = Gen.choose(1, 30)
diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala
index 09743e04..64fc8bda 100644
--- a/src/test/scala/chiselTests/ComplexAssign.scala
+++ b/src/test/scala/chiselTests/ComplexAssign.scala
@@ -29,23 +29,23 @@ class ComplexAssign(w: Int) extends Module {
}
}
+class ComplexAssignTester(enList: List[Boolean], re: Int, im: Int) extends BasicTester {
+ val (cnt, wrap) = Counter(Bool(true), enList.size)
+ val dut = Module(new ComplexAssign(32))
+ dut.io.in.re := UInt(re)
+ dut.io.in.im := UInt(im)
+ dut.io.e := Vec(enList.map(Bool(_)))(cnt)
+ val re_correct = dut.io.out.re === Mux(dut.io.e, dut.io.in.re, UInt(0))
+ val im_correct = dut.io.out.im === Mux(dut.io.e, dut.io.in.im, UInt(0))
+ when(!re_correct || !im_correct) {
+ io.done := Bool(true); io.error := cnt
+ } .elsewhen(wrap) { io.done := Bool(true) }
+}
+
class ComplexAssignSpec extends ChiselPropSpec {
- class ComplexAssignTester(enList: List[Boolean], re: Int, im: Int) extends BasicTester {
- val (cnt, wrap) = Counter(Bool(true), enList.size)
- val dut = Module(new ComplexAssign(32))
- dut.io.in.re := UInt(re)
- dut.io.in.im := UInt(im)
- dut.io.e := Vec(enList.map(Bool(_)))(cnt)
- val re_correct = dut.io.out.re === Mux(dut.io.e, dut.io.in.re, UInt(0))
- val im_correct = dut.io.out.im === Mux(dut.io.e, dut.io.in.im, UInt(0))
- when(!re_correct || !im_correct) {
- io.done := Bool(true); io.error := cnt
- } .elsewhen(wrap) { io.done := Bool(true) }
- }
-
property("All complex assignments should return the correct result") {
- forAll(enSequence(4), safeUInts, safeUInts) { (en: List[Boolean], re: Int, im: Int) =>
+ forAll(enSequence(2), safeUInts, safeUInts) { (en: List[Boolean], re: Int, im: Int) =>
assert(execute{ new ComplexAssignTester(en, re, im) })
}
}
diff --git a/src/test/scala/chiselTests/Counter.scala b/src/test/scala/chiselTests/Counter.scala
index 0e8601b3..080130df 100644
--- a/src/test/scala/chiselTests/Counter.scala
+++ b/src/test/scala/chiselTests/Counter.scala
@@ -6,37 +6,37 @@ import org.scalatest._
import org.scalatest.prop._
import Chisel.testers.BasicTester
-class CounterSpec extends ChiselPropSpec {
+class CountTester(max: Int) extends BasicTester {
+ val cnt = Counter(max)
+ when(cnt.value === UInt(max)) { io.done := Bool(true) }
+}
- class CountTester(max: Int) extends BasicTester {
- val cnt = Counter(max)
- when(cnt.value === UInt(max)) { io.done := Bool(true) }
+class EnableTester(seed: Int) extends BasicTester {
+ val ens = Reg(init = UInt(seed))
+ ens := ens >> 1
+ val (cntEn, cntWrap) = Counter(ens(0), 32)
+ val cnt = Counter(32)
+ when(cnt.value === UInt(31)) {
+ io.done := Bool(true)
+ io.error := cnt.value != UInt(popCount(seed))
}
+}
+
+class WrapTester(max: Int) extends BasicTester {
+ val (cnt, wrap) = Counter(Bool(true), max)
+ when(wrap) { io.done := Bool(true); io.error := cnt != UInt(max) }
+}
+
+class CounterSpec extends ChiselPropSpec {
property("Counter should count up") {
forAll(smallPosInts) { (max: Int) => assert(execute{ new CountTester(max) }) }
}
- class EnableTester(seed: Int) extends BasicTester {
- val ens = Reg(init = UInt(seed))
- ens := ens >> 1
- val (cntEn, cntWrap) = Counter(ens(0), 32)
- val cnt = Counter(32)
- when(cnt.value === UInt(31)) {
- io.done := Bool(true)
- io.error := cnt.value != UInt(popCount(seed))
- }
- }
-
property("Counter can be en/disabled") {
forAll(safeUInts) { (seed: Int) => assert(execute{ new EnableTester(seed) }) }
}
- class WrapTester(max: Int) extends BasicTester {
- val (cnt, wrap) = Counter(Bool(true), max)
- when(wrap) { io.done := Bool(true); io.error := cnt != UInt(max) }
- }
-
property("Counter should wrap") {
forAll(smallPosInts) { (max: Int) => assert(execute{ new WrapTester(max) }) }
}
diff --git a/src/test/scala/chiselTests/Decoder.scala b/src/test/scala/chiselTests/Decoder.scala
index 9ac0a3b7..7751804b 100644
--- a/src/test/scala/chiselTests/Decoder.scala
+++ b/src/test/scala/chiselTests/Decoder.scala
@@ -15,16 +15,16 @@ class Decoder(bitpats: List[String]) extends Module {
io.matched := Vec(bitpats.map(BitPat(_) === io.inst)).reduce(_||_)
}
-class DecoderSpec extends ChiselPropSpec {
+class DecoderTester(pairs: List[(String, String)]) extends BasicTester {
+ val (insts, bitpats) = pairs.unzip
+ val (cnt, wrap) = Counter(Bool(true), pairs.size)
+ val dut = Module(new Decoder(bitpats))
+ dut.io.inst := Vec(insts.map(UInt(_)))(cnt)
+ when(!dut.io.matched) { io.done := Bool(true); io.error := cnt }
+ when(wrap) { io.done := Bool(true) }
+}
- class DecoderTester(pairs: List[(String, String)]) extends BasicTester {
- val (insts, bitpats) = pairs.unzip
- val (cnt, wrap) = Counter(Bool(true), pairs.size)
- val dut = Module(new Decoder(bitpats))
- dut.io.inst := Vec(insts.map(UInt(_)))(cnt)
- when(!dut.io.matched) { io.done := Bool(true); io.error := cnt }
- when(wrap) { io.done := Bool(true) }
- }
+class DecoderSpec extends ChiselPropSpec {
// Use a single Int to make both a specific instruction and a BitPat that will match it
val bitpatPair = for(seed <- Arbitrary.arbitrary[Int]) yield {
@@ -36,7 +36,7 @@ class DecoderSpec extends ChiselPropSpec {
private def nPairs(n: Int) = Gen.containerOfN[List, (String,String)](n,bitpatPair)
property("BitPat wildcards should be usable in decoding") {
- forAll(nPairs(16)){ (pairs: List[(String, String)]) =>
+ forAll(nPairs(4)){ (pairs: List[(String, String)]) =>
assert(execute{ new DecoderTester(pairs) })
}
}
diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala
index 48a96f0d..acc1e84e 100644
--- a/src/test/scala/chiselTests/GCD.scala
+++ b/src/test/scala/chiselTests/GCD.scala
@@ -24,21 +24,21 @@ class GCD extends Module {
io.v := y === UInt(0)
}
-class GCDSpec extends ChiselPropSpec {
-
- class GCDTester(a: Int, b: Int, z: Int) extends BasicTester {
- val dut = Module(new GCD)
- val first = Reg(init=Bool(true))
- dut.io.a := UInt(a)
- dut.io.b := UInt(b)
- dut.io.e := first
- when(first) { first := Bool(false) }
- when(dut.io.v) {
- io.done := Bool(true)
- io.error := (dut.io.z != UInt(z)).toUInt
- }
+class GCDTester(a: Int, b: Int, z: Int) extends BasicTester {
+ val dut = Module(new GCD)
+ val first = Reg(init=Bool(true))
+ dut.io.a := UInt(a)
+ dut.io.b := UInt(b)
+ dut.io.e := first
+ when(first) { first := Bool(false) }
+ when(dut.io.v) {
+ io.done := Bool(true)
+ io.error := (dut.io.z != UInt(z)).toUInt
}
+}
+class GCDSpec extends ChiselPropSpec {
+
//TODO: use generators and this function to make z's
def gcd(a: Int, b: Int): Int = if(b == 0) a else gcd(b, a%b)
diff --git a/src/test/scala/chiselTests/Harness.scala b/src/test/scala/chiselTests/Harness.scala
new file mode 100644
index 00000000..98ad3b11
--- /dev/null
+++ b/src/test/scala/chiselTests/Harness.scala
@@ -0,0 +1,75 @@
+package chiselTests
+import Chisel.testers.BasicTester
+import org.scalatest._
+import org.scalatest.prop._
+import java.io.File
+
+class HarnessSpec extends ChiselPropSpec
+ with Chisel.BackendCompilationUtilities {
+
+ def makeTrivialVerilog = makeHarness((prefix: String) => s"""
+module ${prefix};
+ initial begin
+ $$display("$prefix!");
+ $$finish;
+ end
+endmodule
+""", ".v") _
+
+ def makeFailingVerilog = makeHarness((prefix: String) => s"""
+module $prefix;
+ initial begin
+ assert (1 == 0) else $$error("My specific, expected error message!");
+ $$display("$prefix!");
+ $$finish;
+ end
+endmodule
+""", ".v") _
+
+ def makeCppHarness = makeHarness((prefix: String) => s"""
+#include "V$prefix.h"
+#include "verilated.h"
+
+vluint64_t main_time = 0;
+double sc_time_stamp () { return main_time; }
+
+int main(int argc, char **argv, char **env) {
+ Verilated::commandArgs(argc, argv);
+ V${prefix}* top = new V${prefix};
+ while (!Verilated::gotFinish()) { top->eval(); }
+ delete top;
+ exit(0);
+}
+""", ".cpp") _
+
+ val dir = new File(System.getProperty("java.io.tmpdir"))
+
+ def simpleHarnessBackend(make: File => File): String = {
+ val target = "test"
+ val fname = File.createTempFile(target, "")
+ val path = fname.getParentFile.toString
+ val prefix = fname.toString.split("/").last
+ val vDut = make(fname)
+ val vH = new File(path + "/V" + prefix + ".h")
+ val cppHarness = makeCppHarness(fname)
+ verilogToCpp(target, dir, vDut, cppHarness, vH).!
+ cppToExe(prefix, dir).!
+ prefix
+ }
+
+ property("Test making trivial verilog harness and executing") {
+ val prefix = simpleHarnessBackend(makeTrivialVerilog)
+
+ assert(executeExpectingSuccess(prefix, dir))
+ }
+
+ property("Test that assertion failues in Verilog are caught") {
+ val prefix = simpleHarnessBackend(makeFailingVerilog)
+
+ assert(!executeExpectingSuccess(prefix, dir))
+ assert(executeExpectingFailure(prefix, dir))
+ assert(executeExpectingFailure(prefix, dir, "My specific, expected error message!"))
+ assert(!executeExpectingFailure(prefix, dir, "A string that doesn't match any test output"))
+ }
+}
+
diff --git a/src/test/scala/chiselTests/MulLookup.scala b/src/test/scala/chiselTests/MulLookup.scala
index 18dcc431..93917a4e 100644
--- a/src/test/scala/chiselTests/MulLookup.scala
+++ b/src/test/scala/chiselTests/MulLookup.scala
@@ -22,15 +22,15 @@ class MulLookup(val w: Int) extends Module {
io.z := tbl(((io.x << w) | io.y))
}
-class MulLookupSpec extends ChiselPropSpec {
+class MulLookupTester(w: Int, x: Int, y: Int) extends BasicTester {
+ val dut = Module(new MulLookup(w))
+ dut.io.x := UInt(x)
+ dut.io.y := UInt(y)
+ io.done := Bool(true)
+ io.error := dut.io.z != UInt(x * y)
+}
- class MulLookupTester(w: Int, x: Int, y: Int) extends BasicTester {
- val dut = Module(new MulLookup(w))
- dut.io.x := UInt(x)
- dut.io.y := UInt(y)
- io.done := Bool(true)
- io.error := dut.io.z != UInt(x * y)
- }
+class MulLookupSpec extends ChiselPropSpec {
property("Mul lookup table should return the correct result") {
forAll(smallPosInts, smallPosInts) { (x: Int, y: Int) =>
diff --git a/src/test/scala/chiselTests/Tbl.scala b/src/test/scala/chiselTests/Tbl.scala
index 072f993f..40f71c69 100644
--- a/src/test/scala/chiselTests/Tbl.scala
+++ b/src/test/scala/chiselTests/Tbl.scala
@@ -23,22 +23,22 @@ class Tbl(w: Int, n: Int) extends Module {
}
}
-class TblSpec extends ChiselPropSpec {
+class TblTester(w: Int, n: Int, idxs: List[Int], values: List[Int]) extends BasicTester {
+ val (cnt, wrap) = Counter(Bool(true), idxs.size)
+ val dut = Module(new Tbl(w, n))
+ val vvalues = Vec(values.map(UInt(_)))
+ val vidxs = Vec(idxs.map(UInt(_)))
+ val prev_idx = vidxs(cnt - UInt(1))
+ val prev_value = vvalues(cnt - UInt(1))
+ dut.io.wi := vidxs(cnt)
+ dut.io.ri := prev_idx
+ dut.io.we := Bool(true) //TODO enSequence
+ dut.io.d := vvalues(cnt)
+ when(cnt > UInt(0) && dut.io.o != prev_value) { io.done := Bool(true); io.error := prev_idx }
+ when(wrap) { io.done := Bool(true) }
+}
- class TblTester(w: Int, n: Int, idxs: List[Int], values: List[Int]) extends BasicTester {
- val (cnt, wrap) = Counter(Bool(true), idxs.size)
- val dut = Module(new Tbl(w, n))
- val vvalues = Vec(values.map(UInt(_)))
- val vidxs = Vec(idxs.map(UInt(_)))
- val prev_idx = vidxs(cnt - UInt(1))
- val prev_value = vvalues(cnt - UInt(1))
- dut.io.wi := vidxs(cnt)
- dut.io.ri := prev_idx
- dut.io.we := Bool(true) //TODO enSequence
- dut.io.d := vvalues(cnt)
- when(cnt > UInt(0) && dut.io.o != prev_value) { io.done := Bool(true); io.error := prev_idx }
- when(wrap) { io.done := Bool(true) }
- }
+class TblSpec extends ChiselPropSpec {
property("All table reads should return the previous write") {
forAll(safeUIntPairN(8)) { case(w: Int, pairs: List[(Int, Int)]) =>
diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala
index ea670f37..4430ab66 100644
--- a/src/test/scala/chiselTests/Vec.scala
+++ b/src/test/scala/chiselTests/Vec.scala
@@ -7,15 +7,36 @@ import org.scalatest._
import org.scalatest.prop._
import Chisel.testers.BasicTester
-class VecSpec extends ChiselPropSpec {
+class ValueTester(w: Int, values: List[Int]) extends BasicTester {
+ io.done := Bool(true)
+ val v = Vec(values.map(UInt(_, width = w))) // TODO: does this need a Wire? Why no error?
+ io.error := v.zip(values).map { case(a,b) =>
+ a != UInt(b)
+ }.foldLeft(UInt(0))(_##_)
+}
- class ValueTester(w: Int, values: List[Int]) extends BasicTester {
- io.done := Bool(true)
- val v = Vec(values.map(UInt(_, width = w))) // TODO: does this need a Wire? Why no error?
- io.error := v.zip(values).map { case(a,b) =>
- a != UInt(b)
- }.foldLeft(UInt(0))(_##_)
- }
+class TabulateTester(n: Int) extends BasicTester {
+ io.done := Bool(true)
+ val v = Vec(Range(0, n).map(i => UInt(i * 2)))
+ val x = Vec(Array.tabulate(n){ i => UInt(i * 2) })
+ val u = Vec.tabulate(n)(i => UInt(i*2))
+ when(v.toBits != x.toBits) { io.error := UInt(1) }
+ when(v.toBits != u.toBits) { io.error := UInt(2) }
+ when(x.toBits != u.toBits) { io.error := UInt(3) }
+}
+
+class ShiftRegisterTester(n: Int) extends BasicTester {
+ val (cnt, wrap) = Counter(Bool(true), n*2)
+ when(wrap) { io.done := Bool(true) }
+
+ val shifter = Vec(Reg(UInt(width = log2Up(n))), n)
+ (shifter, shifter drop 1).zipped.foreach(_ := _)
+ shifter(n-1) := cnt
+ val expected = cnt - UInt(n)
+ when(cnt >= UInt(n) && expected != shifter(0)) { io.done := Bool(true); io.error := expected }
+}
+
+class VecSpec extends ChiselPropSpec {
property("Vecs should be assignable") {
forAll(safeUIntN(8)) { case(w: Int, v: List[Int]) =>
@@ -23,31 +44,10 @@ class VecSpec extends ChiselPropSpec {
}
}
- class TabulateTester(n: Int) extends BasicTester {
- io.done := Bool(true)
- val v = Vec(Range(0, n).map(i => UInt(i * 2)))
- val x = Vec(Array.tabulate(n){ i => UInt(i * 2) })
- val u = Vec.tabulate(n)(i => UInt(i*2))
- when(v.toBits != x.toBits) { io.error := UInt(1) }
- when(v.toBits != u.toBits) { io.error := UInt(2) }
- when(x.toBits != u.toBits) { io.error := UInt(3) }
- }
-
property("Vecs should tabulate correctly") {
forAll(smallPosInts) { (n: Int) => assert(execute{ new TabulateTester(n) }) }
}
- class ShiftRegisterTester(n: Int) extends BasicTester {
- val (cnt, wrap) = Counter(Bool(true), n*2)
- when(wrap) { io.done := Bool(true) }
-
- val shifter = Vec(Reg(UInt(width = log2Up(n))), n)
- (shifter, shifter drop 1).zipped.foreach(_ := _)
- shifter(n-1) := cnt
- val expected = cnt - UInt(n)
- when(cnt >= UInt(n) && expected != shifter(0)) { io.done := Bool(true); io.error := expected }
- }
-
property("Vecs of regs should be usable as shift registers") {
forAll(smallPosInts) { (n: Int) => assert(execute{ new ShiftRegisterTester(n) }) }
}