diff --git a/src/main/scala/chisel3/experimental/inlinetest/InlineTest.scala b/src/main/scala/chisel3/experimental/inlinetest/InlineTest.scala index 592d319cdb5..fdd1d267811 100644 --- a/src/main/scala/chisel3/experimental/inlinetest/InlineTest.scala +++ b/src/main/scala/chisel3/experimental/inlinetest/InlineTest.scala @@ -19,7 +19,9 @@ class TestParameters[M <: RawModule, R] private[inlinetest] ( /** A Definition of the DUT module. */ val dutDefinition: Definition[M], /** The body for this test, returns a result. */ - val testBody: Instance[M] => R + val testBody: Instance[M] => R, + /** The reset type of the DUT module. */ + val resetType: Option[Module.ResetType.Type] ) { final def desiredTestModuleName = s"test_${dutName}_${testName}" } @@ -50,7 +52,11 @@ object TestHarness { * @tparam R the type of the result returned by the test body */ trait Module[M <: ChiselRawModule, R] extends RawModule[M, R] { this: ChiselModule => - override def resetType = Module.ResetType.Synchronous + override def resetType = test.resetType match { + case Some(rt @ Module.ResetType.Synchronous) => rt + case Some(rt @ Module.ResetType.Asynchronous) => rt + case _ => Module.ResetType.Synchronous + } } } @@ -110,7 +116,11 @@ trait HasTests[M <: RawModule] { module: M => testName: String )(testBody: Instance[M] => R)(implicit th: TestHarnessGenerator[M, R]): Unit = elaborateParentModule { moduleDefinition => - val test = new TestParameters[M, R](desiredName, testName, moduleDefinition, testBody) + val resetType = module match { + case module: Module => Some(module.resetType) + case _ => None + } + val test = new TestParameters[M, R](desiredName, testName, moduleDefinition, testBody, resetType) th.generate(test) } } diff --git a/src/test/scala/chiselTests/experimental/InlineTestSpec.scala b/src/test/scala/chiselTests/experimental/InlineTestSpec.scala index 95e1d8fa533..ad3e514f9c0 100644 --- a/src/test/scala/chiselTests/experimental/InlineTestSpec.scala +++ b/src/test/scala/chiselTests/experimental/InlineTestSpec.scala @@ -10,6 +10,8 @@ import circt.stage.ChiselStage import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers +import circt.stage.ChiselStage.emitCHIRRTL + class TestResultBundle extends Bundle { val finish = Output(Bool()) val code = Output(UInt(8.W)) @@ -67,7 +69,10 @@ class ProtocolMonitor(bundleType: ProtocolBundle) extends Module { } @instantiable -class ModuleWithTests(ioWidth: Int = 32) extends Module with HasMonitorSocket with HasTests[ModuleWithTests] { +class ModuleWithTests(ioWidth: Int = 32, override val resetType: Module.ResetType.Type = Module.ResetType.Synchronous) + extends Module + with HasMonitorSocket + with HasTests[ModuleWithTests] { @public val io = IO(new ProtocolBundle(ioWidth)) override val monProbe = makeProbe(io) @@ -112,34 +117,42 @@ class ModuleWithTests(ioWidth: Int = 32) extends Module with HasMonitorSocket wi } } -class InlineTestSpec extends AnyFlatSpec with Matchers with FileCheck { +@instantiable +class RawModuleWithTests(ioWidth: Int = 32) extends RawModule with HasTests[RawModuleWithTests] { + @public val io = IO(new ProtocolBundle(ioWidth)) + io.out := io.in + test("foo") { instance => + instance.io.in := 3.U(ioWidth.W) + assert(instance.io.out === 3.U): Unit + } +} + +class InlineTestSpec extends AnyFlatSpec with FileCheck { it should "generate a public module for each test" in { - ChiselStage - .emitCHIRRTL(new ModuleWithTests) - .fileCheck()( - """ + emitCHIRRTL(new ModuleWithTests).fileCheck()( + """ | CHECK: module ModuleWithTests | CHECK: output monProbe : Probe<{ in : UInt<32>, out : UInt<32>}> | | CHECK: public module test_ModuleWithTests_foo | CHECK-NEXT: input clock : Clock - | CHECK-NEXT: input reset : UInt<1> + | CHECK-NEXT: input reset | CHECK: inst dut of ModuleWithTests | | CHECK: public module test_ModuleWithTests_bar | CHECK-NEXT: input clock : Clock - | CHECK-NEXT: input reset : UInt<1> + | CHECK-NEXT: input reset | CHECK: inst dut of ModuleWithTests | | CHECK: public module test_ModuleWithTests_with_result | CHECK-NEXT: input clock : Clock - | CHECK-NEXT: input reset : UInt<1> + | CHECK-NEXT: input reset | CHECK-NEXT: output result : { finish : UInt<1>, code : UInt<8>} | CHECK: inst dut of ModuleWithTests | | CHECK: public module test_ModuleWithTests_with_monitor | CHECK-NEXT: input clock : Clock - | CHECK-NEXT: input reset : UInt<1> + | CHECK-NEXT: input reset | CHECK: inst dut of ModuleWithTests | CHECK: inst monitor of ProtocolMonitor | CHECK-NEXT: connect monitor.clock, clock @@ -147,7 +160,7 @@ class InlineTestSpec extends AnyFlatSpec with Matchers with FileCheck { | CHECK-NEXT: connect monitor.io.out, read(dut.monProbe).out | CHECK-NEXT: connect monitor.io.in, read(dut.monProbe).in """ - ) + ) } it should "compile to verilog" in { @@ -163,4 +176,50 @@ class InlineTestSpec extends AnyFlatSpec with Matchers with FileCheck { """ ) } + + it should "emit the correct reset types" in { + def fileCheckString(resetType: String) = + s""" + | CHECK: module ModuleWithTests + | CHECK-NEXT: input clock : Clock + | CHECK-NEXT: input reset : ${resetType} + | + | CHECK: public module test_ModuleWithTests_foo + | CHECK-NEXT: input clock : Clock + | CHECK-NEXT: input reset : ${resetType} + | + | CHECK: public module test_ModuleWithTests_bar + | CHECK-NEXT: input clock : Clock + | CHECK-NEXT: input reset : ${resetType} + | + | CHECK: public module test_ModuleWithTests_with_result + | CHECK-NEXT: input clock : Clock + | CHECK-NEXT: input reset : ${resetType} + | + | CHECK: public module test_ModuleWithTests_with_monitor + | CHECK-NEXT: input clock : Clock + | CHECK-NEXT: input reset : ${resetType} + """ + + emitCHIRRTL(new ModuleWithTests(resetType = Module.ResetType.Synchronous)).fileCheck()( + fileCheckString("UInt<1>") + ) + emitCHIRRTL(new ModuleWithTests(resetType = Module.ResetType.Asynchronous)).fileCheck()( + fileCheckString("AsyncReset") + ) + emitCHIRRTL(new ModuleWithTests(resetType = Module.ResetType.Default)).fileCheck()( + fileCheckString("UInt<1>") + ) + + emitCHIRRTL(new RawModuleWithTests()).fileCheck()( + """ + | CHECK: module RawModuleWithTests + | CHECK-NEXT: output io + | + | CHECK: public module test_RawModuleWithTests_foo + | CHECK-NEXT: input clock : Clock + | CHECK-NEXT: input reset : UInt<1> + """ + ) + } }