diff options
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/scala/firrtlTests/MemoryInitSpec.scala | 203 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/execution/VerilogExecution.scala | 6 |
2 files changed, 208 insertions, 1 deletions
diff --git a/src/test/scala/firrtlTests/MemoryInitSpec.scala b/src/test/scala/firrtlTests/MemoryInitSpec.scala new file mode 100644 index 00000000..0826746b --- /dev/null +++ b/src/test/scala/firrtlTests/MemoryInitSpec.scala @@ -0,0 +1,203 @@ +// See LICENSE for license details. + +package firrtlTests + +import firrtl._ +import firrtl.annotations._ +import firrtl.testutils.FirrtlCheckers.containLine +import firrtl.testutils.FirrtlFlatSpec +import firrtlTests.execution._ + +class MemInitSpec extends FirrtlFlatSpec { + def input(tpe: String): String = + s""" + |circuit MemTest: + | module MemTest: + | input clock : Clock + | input rAddr : UInt<5> + | input rEnable : UInt<1> + | input wAddr : UInt<5> + | input wData : $tpe + | input wEnable : UInt<1> + | output rData : $tpe + | + | mem m: + | data-type => $tpe + | depth => 32 + | reader => r + | writer => w + | read-latency => 1 + | write-latency => 1 + | read-under-write => new + | + | m.r.clk <= clock + | m.r.addr <= rAddr + | m.r.en <= rEnable + | rData <= m.r.data + | + | m.w.clk <= clock + | m.w.addr <= wAddr + | m.w.en <= wEnable + | m.w.data <= wData + | m.w.mask is invalid + | + |""".stripMargin + + val mRef = CircuitTarget("MemTest").module("MemTest").ref("m") + def compile(annos: AnnotationSeq, tpe: String = "UInt<32>"): CircuitState = { + (new VerilogCompiler).compileAndEmit(CircuitState(parse(input(tpe)), ChirrtlForm, annos)) + } + + "NoAnnotation" should "create a randomized initialization" in { + val annos = Seq() + val result = compile(annos) + result should containLine (" m[initvar] = _RAND_0[31:0];") + } + + "MemoryRandomInitAnnotation" should "create a randomized initialization" in { + val annos = Seq(MemoryRandomInitAnnotation(mRef)) + val result = compile(annos) + result should containLine (" m[initvar] = _RAND_0[31:0];") + } + + "MemoryScalarInitAnnotation w/ 0" should "create an initialization with all zeros" in { + val annos = Seq(MemoryScalarInitAnnotation(mRef, 0)) + val result = compile(annos) + result should containLine(" m[initvar] = 0;") + } + + Seq(1, 3, 30, 400, 12345).foreach { value => + s"MemoryScalarInitAnnotation w/ $value" should + s"create an initialization with all values set to $value" in { + val annos = Seq(MemoryScalarInitAnnotation(mRef, value)) + val result = compile(annos) + result should containLine(s" m[initvar] = $value;") + } + } + + "MemoryArrayInitAnnotation" should "initialize all addresses" in { + val values = Seq.tabulate(32)(ii => 2 * ii + 5).map(BigInt(_)) + val annos = Seq(MemoryArrayInitAnnotation(mRef, values)) + val result = compile(annos) + values.zipWithIndex.foreach { case (value, addr) => + result should containLine(s" m[$addr] = $value;") + } + } + + "MemoryScalarInitAnnotation" should "fail for a negative value" in { + assertThrows[EmitterException] { + compile(Seq(MemoryScalarInitAnnotation(mRef, -1))) + } + } + + "MemoryScalarInitAnnotation" should "fail for a value that is too large" in { + assertThrows[EmitterException] { + compile(Seq(MemoryScalarInitAnnotation(mRef, BigInt(1) << 32))) + } + } + + "MemoryArrayInitAnnotation" should "fail for a negative value" in { + assertThrows[EmitterException] { + val values = Seq.tabulate(32)(_ => BigInt(-1)) + compile(Seq(MemoryArrayInitAnnotation(mRef, values))) + } + } + + "MemoryArrayInitAnnotation" should "fail for a value that is too large" in { + assertThrows[EmitterException] { + val values = Seq.tabulate(32)(_ => BigInt(1) << 32) + compile(Seq(MemoryArrayInitAnnotation(mRef, values))) + } + } + + "MemoryArrayInitAnnotation" should "fail if the number of values is too small" in { + assertThrows[EmitterException] { + val values = Seq.tabulate(31)(_ => BigInt(1)) + compile(Seq(MemoryArrayInitAnnotation(mRef, values))) + } + } + + "MemoryArrayInitAnnotation" should "fail if the number of values is too large" in { + assertThrows[EmitterException] { + val values = Seq.tabulate(33)(_ => BigInt(1)) + compile(Seq(MemoryArrayInitAnnotation(mRef, values))) + } + } + + "MemoryScalarInitAnnotation on Memory with Vector type" should "fail" in { + val caught = intercept[Exception] { + val annos = Seq(MemoryScalarInitAnnotation(mRef, 0)) + compile(annos, "UInt<32>[2]") + } + assert(caught.getMessage.endsWith("[module MemTest] Cannot initialize memory of non ground type UInt<32>[2]")) + } + + "MemoryScalarInitAnnotation on Memory with Bundle type" should "fail" in { + val caught = intercept[Exception] { + val annos = Seq(MemoryScalarInitAnnotation(mRef, 0)) + compile(annos, "{real: SInt<10>, imag: SInt<10>}") + } + assert(caught.getMessage.endsWith("[module MemTest] Cannot initialize memory of non ground type { real : SInt<10>, imag : SInt<10>}")) + } + + private def jsonAnno(name: String, suffix: String): String = + s"""[{"class": "firrtl.annotations.$name", "target": "~MemTest|MemTest>m"$suffix}]""" + + "MemoryRandomInitAnnotation" should "load from JSON" in { + val json = jsonAnno("MemoryRandomInitAnnotation", "") + val annos = JsonProtocol.deserialize(json) + assert(annos == Seq(MemoryRandomInitAnnotation(mRef))) + } + + "MemoryScalarInitAnnotation" should "load from JSON" in { + val json = jsonAnno("MemoryScalarInitAnnotation", """, "value": 1234567890""") + val annos = JsonProtocol.deserialize(json) + assert(annos == Seq(MemoryScalarInitAnnotation(mRef, 1234567890))) + } + + "MemoryArrayInitAnnotation" should "load from JSON" in { + val json = jsonAnno("MemoryArrayInitAnnotation", """, "values": [10000000000, 20000000000]""") + val annos = JsonProtocol.deserialize(json) + val largeSeq = Seq(BigInt("10000000000"), BigInt("20000000000")) + assert(annos == Seq(MemoryArrayInitAnnotation(mRef, largeSeq))) + } + +} + +abstract class MemInitExecutionSpec(values: Seq[Int], init: ReferenceTarget => Annotation) + extends SimpleExecutionTest with VerilogExecution { + override val body: String = + s""" + |mem m: + | data-type => UInt<32> + | depth => ${values.length} + | reader => r + | read-latency => 1 + | write-latency => 1 + | read-under-write => new + |m.r.clk <= clock + |m.r.en <= UInt<1>(1) + |""".stripMargin + + val mRef = CircuitTarget("dut").module("dut").ref("m") + override val customAnnotations: AnnotationSeq = Seq(init(mRef)) + + override def commands: Seq[SimpleTestCommand] = (Seq(-1) ++ values).zipWithIndex.map { case (value, addr) => + if(value == -1) { Seq(Poke("m.r.addr", addr)) } + else if(addr >= values.length) { Seq(Expect("m.r.data", value)) } + else { Seq(Poke("m.r.addr", addr), Expect("m.r.data", value)) } + }.flatMap(_ ++ Seq(Step(1))) +} + +class MemScalarInit0ExecutionSpec extends MemInitExecutionSpec( + Seq.tabulate(31)(_ => 0), r => MemoryScalarInitAnnotation(r, 0) +) {} + +class MemScalarInit17ExecutionSpec extends MemInitExecutionSpec( + Seq.tabulate(31)(_ => 17), r => MemoryScalarInitAnnotation(r, 17) +) {} + +class MemArrayInitExecutionSpec extends MemInitExecutionSpec( + Seq.tabulate(31)(ii => ii * 5 + 7), + r => MemoryArrayInitAnnotation(r, Seq.tabulate(31)(ii => ii * 5 + 7).map(BigInt(_))) +) {} diff --git a/src/test/scala/firrtlTests/execution/VerilogExecution.scala b/src/test/scala/firrtlTests/execution/VerilogExecution.scala index f80a5ee6..bf3d1461 100644 --- a/src/test/scala/firrtlTests/execution/VerilogExecution.scala +++ b/src/test/scala/firrtlTests/execution/VerilogExecution.scala @@ -13,11 +13,15 @@ import firrtl.options.TargetDirAnnotation */ trait VerilogExecution extends TestExecution { this: SimpleExecutionTest => + + /** can be overwritten to mix-in custom annotations */ + val customAnnotations: AnnotationSeq = Seq() + def runEmittedDUT(c: Circuit, testDir: File): Unit = { // Run FIRRTL, emit Verilog file val cAnno = FirrtlCircuitAnnotation(c) val tdAnno = TargetDirAnnotation(testDir.getAbsolutePath) - (new FirrtlStage).run(AnnotationSeq(Seq(cAnno, tdAnno))) + (new FirrtlStage).run(AnnotationSeq(Seq(cAnno, tdAnno) ++ customAnnotations)) // Copy harness resource to test directory val harness = new File(testDir, s"top.cpp") |
