diff options
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/scala/chiselTests/BitwiseOps.scala | 22 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/BundleWire.scala | 16 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/ChiselSpec.scala | 8 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/ComplexAssign.scala | 28 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/Counter.scala | 40 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/Decoder.scala | 20 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/GCD.scala | 26 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/Harness.scala | 75 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/MulLookup.scala | 16 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/Tbl.scala | 30 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/Vec.scala | 58 |
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) }) } } |
