summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
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) }) }
}