diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/chisel3/testers/TesterDriver.scala | 132 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/AnalogIntegrationSpec.scala | 14 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/AnalogSpec.scala | 20 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/BlackBox.scala | 40 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/BoringUtilsSpec.scala | 12 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/ExtModule.scala | 4 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/MultiClockSpec.scala | 2 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/aop/InjectionSpec.scala | 8 | ||||
| -rw-r--r-- | src/test/scala/examples/SimpleVendingMachine.scala | 6 |
9 files changed, 186 insertions, 52 deletions
diff --git a/src/main/scala/chisel3/testers/TesterDriver.scala b/src/main/scala/chisel3/testers/TesterDriver.scala index 03fb1899..e63e86e7 100644 --- a/src/main/scala/chisel3/testers/TesterDriver.scala +++ b/src/main/scala/chisel3/testers/TesterDriver.scala @@ -2,10 +2,9 @@ package chisel3.testers -import chisel3._ import java.io._ -import chisel3.aop.Aspect +import chisel3._ import chisel3.experimental.RunFirrtlTransform import chisel3.stage.phases.{AspectPhase, Convert, Elaborate, Emitter} import chisel3.stage.{ @@ -19,8 +18,34 @@ import firrtl.{Driver => _, _} import firrtl.options.{Dependency, Phase, PhaseManager} import firrtl.stage.{FirrtlCircuitAnnotation, FirrtlStage} import firrtl.transforms.BlackBoxSourceHelper.writeResourceToDirectory +import treadle.executable.StopException +import treadle.stage.TreadleTesterPhase +import treadle.{CallResetAtStartupAnnotation, TreadleTesterAnnotation, WriteVcdAnnotation} +//scalastyle:off magic.number method.length object TesterDriver extends BackendCompilationUtilities { + var MaxTreadleCycles = 10000L + + trait Backend extends NoTargetAnnotation with Unserializable + case object VerilatorBackend extends Backend + case object TreadleBackend extends Backend + case object NoBackend extends Backend + + /* + Currently the only mechanism for running with the Treadle backend is to edit this + statement locally. + */ + val defaultBackend: Backend = VerilatorBackend + + /** Use this to force a test to be run only with backends that are restricted to verilator backend + */ + def verilatorOnly: AnnotationSeq = { + if (defaultBackend == TreadleBackend) { + Seq(NoBackend) + } else { + Seq(defaultBackend) + } + } /** Set the target directory to the name of the top module after elaboration */ final class AddImplicitTesterDirectory extends Phase { @@ -41,9 +66,35 @@ object TesterDriver extends BackendCompilationUtilities { /** For use with modules that should successfully be elaborated by the * frontend, and which can be turned into executables with assertions. */ - def execute(t: () => BasicTester, + def execute(t: () => BasicTester, additionalVResources: Seq[String] = Seq(), - annotations: AnnotationSeq = Seq() + annotations: AnnotationSeq = Seq(), + nameHint: Option[String] = None): Boolean = { + + val backendAnnotations = annotations.collect { case anno: Backend => anno } + val backendAnnotation = if (backendAnnotations.length == 1) { + backendAnnotations.head + } else if (backendAnnotations.isEmpty) { + defaultBackend + } else { + throw new ChiselException(s"Only one backend annotation allowed, found: ${backendAnnotations.mkString(", ")}") + } + backendAnnotation match { + case TreadleBackend => + executeTreadle(t, additionalVResources, annotations, nameHint) + case VerilatorBackend => + executeVerilog(t, additionalVResources, annotations, nameHint) + case _ => + throw new ChiselException(s"Unknown backend specified: $backendAnnotation") + } + } + + /** For use with modules that should successfully be elaborated by the + * frontend, and which can be turned into executables with assertions. */ + def executeVerilog(t: () => BasicTester, + additionalVResources: Seq[String] = Seq(), + annotations: AnnotationSeq = Seq(), + nameHint: Option[String] = None ): Boolean = { val pm = new PhaseManager( targets = Seq(Dependency[AddImplicitTesterDirectory], @@ -76,15 +127,76 @@ object TesterDriver extends BackendCompilationUtilities { false } } + + //scalastyle:off cyclomatic.complexity method.length + def executeTreadle(t: () => BasicTester, + additionalVResources: Seq[String] = Seq(), + annotations: AnnotationSeq = Seq(), + nameHint: Option[String] = None): Boolean = { + val generatorAnnotation = chisel3.stage.ChiselGeneratorAnnotation(t) + + // This provides an opportunity to translate from top level generic flags to backend specific annos + var annotationSeq = annotations :+ WriteVcdAnnotation + + // This produces a chisel circuit annotation, a later pass will generate a firrtl circuit + // Can't do both at once currently because generating the latter deletes the former + annotationSeq = (new chisel3.stage.phases.Elaborate).transform(annotationSeq :+ generatorAnnotation) + + val circuit = annotationSeq.collect { case x: ChiselCircuitAnnotation => x }.head.circuit + + val targetName: File = createTestDirectory(circuit.name) + + if (!annotationSeq.exists(_.isInstanceOf[NoTargetAnnotation])) { + annotationSeq = annotationSeq :+ TargetDirAnnotation(targetName.getPath) + } + if (!annotationSeq.exists { case CallResetAtStartupAnnotation => true ; case _ => false }) { + annotationSeq = annotationSeq :+ CallResetAtStartupAnnotation + } + + // This generates the firrtl circuit needed by the TreadleTesterPhase + annotationSeq = (new ChiselStage).run( + annotationSeq ++ Seq(NoRunFirrtlCompilerAnnotation) + ) + + // This generates a TreadleTesterAnnotation with a treadle tester instance + annotationSeq = TreadleTesterPhase.transform(annotationSeq) + + val treadleTester = annotationSeq.collectFirst { case TreadleTesterAnnotation(t) => t }.getOrElse( + throw new Exception( + s"TreadleTesterPhase could not build a treadle tester from these annotations" + + annotationSeq.mkString("Annotations:\n", "\n ", "") + ) + ) + + try { + var cycle = 0L + while (cycle < MaxTreadleCycles) { + cycle += 1 + treadleTester.step() + } + throw new ChiselException(s"Treadle backend exceeded MaxTreadleCycles ($MaxTreadleCycles)") + } catch { + case _: StopException => + } + treadleTester.finish + + treadleTester.getStopResult match { + case None => true + case Some(0) => true + case _ => false + } + } + /** * Calls the finish method of an BasicTester or a class that extends it. * The finish method is a hook for code that augments the circuit built in the constructor. */ - def finishWrapper(test: () => BasicTester): () => BasicTester = { - () => { - val tester = test() - tester.finish() - tester - } + def finishWrapper(test: () => BasicTester): () => BasicTester = { () => + { + val tester = test() + tester.finish() + tester } + } + } diff --git a/src/test/scala/chiselTests/AnalogIntegrationSpec.scala b/src/test/scala/chiselTests/AnalogIntegrationSpec.scala index a3e6e643..d28c0ee1 100644 --- a/src/test/scala/chiselTests/AnalogIntegrationSpec.scala +++ b/src/test/scala/chiselTests/AnalogIntegrationSpec.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3._ import chisel3.util._ -import chisel3.testers.BasicTester +import chisel3.testers.{BasicTester, TesterDriver} import chisel3.experimental._ /* This test is different from AnalogSpec in that it uses more complicated black boxes that can each @@ -126,10 +126,18 @@ class AnalogIntegrationTester(mod: => AnalogDUTModule) extends BasicTester { class AnalogIntegrationSpec extends ChiselFlatSpec { behavior of "Verilator" it should "support simple bidirectional wires" in { - assertTesterPasses(new AnalogIntegrationTester(new AnalogSmallDUT), Seq("/chisel3/AnalogBlackBox.v")) + assertTesterPasses( + new AnalogIntegrationTester(new AnalogSmallDUT), + Seq("/chisel3/AnalogBlackBox.v"), + TesterDriver.verilatorOnly + ) } // Use this test once Verilator supports alias ignore should "support arbitrary bidirectional wires" in { - assertTesterPasses(new AnalogIntegrationTester(new AnalogDUT), Seq("/chisel3/AnalogBlackBox.v")) + assertTesterPasses( + new AnalogIntegrationTester(new AnalogDUT), + Seq("/chisel3/AnalogBlackBox.v"), + TesterDriver.verilatorOnly + ) } } diff --git a/src/test/scala/chiselTests/AnalogSpec.scala b/src/test/scala/chiselTests/AnalogSpec.scala index 7fca6b7b..1ae64d07 100644 --- a/src/test/scala/chiselTests/AnalogSpec.scala +++ b/src/test/scala/chiselTests/AnalogSpec.scala @@ -5,8 +5,8 @@ package chiselTests import chisel3._ import chisel3.stage.ChiselStage import chisel3.util._ -import chisel3.testers.BasicTester -import chisel3.experimental.{Analog, attach, BaseModule} +import chisel3.testers.{BasicTester, TesterDriver} +import chisel3.experimental.{Analog, BaseModule, attach} // IO for Modules that just connect bus to out class AnalogReaderIO extends Bundle { @@ -158,7 +158,7 @@ class AnalogSpec extends ChiselFlatSpec with Utils { val mod = Module(new AnalogReaderBlackBox) mod.io.bus <> writer.io.bus check(mod) - }, Seq("/chisel3/AnalogBlackBox.v")) + }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) } it should "error if any bulk connected more than once" in { @@ -221,7 +221,7 @@ class AnalogSpec extends ChiselFlatSpec with Utils { val mods = Seq.fill(2)(Module(new AnalogReaderBlackBox)) attach(writer.io.bus, mods(0).io.bus, mods(1).io.bus) mods.foreach(check(_)) - }, Seq("/chisel3/AnalogBlackBox.v")) + }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) } it should "work with 3 blackboxes separately attached via a wire" in { @@ -232,7 +232,7 @@ class AnalogSpec extends ChiselFlatSpec with Utils { attach(busWire, mods(0).io.bus) attach(mods(1).io.bus, busWire) mods.foreach(check(_)) - }, Seq("/chisel3/AnalogBlackBox.v")) + }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) } // This does not currently work in Verilator unless Firrtl does constant prop and dead code @@ -245,7 +245,7 @@ class AnalogSpec extends ChiselFlatSpec with Utils { attach(busWire(1), mod.io.bus) attach(busWire(0), busWire(1)) check(mod) - }, Seq("/chisel3/AnalogBlackBox.v")) + }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) } it should "work with blackboxes at different levels of the module hierarchy" in { @@ -254,7 +254,7 @@ class AnalogSpec extends ChiselFlatSpec with Utils { val busWire = Wire(writer.io.bus.cloneType) attach(writer.io.bus, mods(0).bus, mods(1).bus) mods.foreach(check(_)) - }, Seq("/chisel3/AnalogBlackBox.v")) + }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) } // This does not currently work in Verilator, but does work in VCS @@ -265,7 +265,7 @@ class AnalogSpec extends ChiselFlatSpec with Utils { connector.io.bus1 <> writer.io.bus reader.io.bus <> connector.io.bus2 check(reader) - }, Seq("/chisel3/AnalogBlackBox.v")) + }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) } it should "NOT support conditional connection of analog types" in { @@ -285,7 +285,7 @@ class AnalogSpec extends ChiselFlatSpec with Utils { val mod = Module(new VecAnalogReaderWrapper) mod.bus <> writer.io.bus check(mod) - }, Seq("/chisel3/AnalogBlackBox.v")) + }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) } it should "work with Vecs of Bundles of Analog" in { @@ -293,6 +293,6 @@ class AnalogSpec extends ChiselFlatSpec with Utils { val mod = Module(new VecBundleAnalogReaderWrapper) mod.bus <> writer.io.bus check(mod) - }, Seq("/chisel3/AnalogBlackBox.v")) + }, Seq("/chisel3/AnalogBlackBox.v"), TesterDriver.verilatorOnly) } } diff --git a/src/test/scala/chiselTests/BlackBox.scala b/src/test/scala/chiselTests/BlackBox.scala index d33355fd..f61fa36a 100644 --- a/src/test/scala/chiselTests/BlackBox.scala +++ b/src/test/scala/chiselTests/BlackBox.scala @@ -150,31 +150,41 @@ class BlackBoxWithParamsTester extends BasicTester { class BlackBoxSpec extends ChiselFlatSpec { "A BlackBoxed inverter" should "work" in { - assertTesterPasses({ new BlackBoxTester }, - Seq("/chisel3/BlackBoxTest.v")) + assertTesterPasses( + {new BlackBoxTester}, + Seq("/chisel3/BlackBoxTest.v"), + TesterDriver.verilatorOnly) } "A BlackBoxed with flipped IO" should "work" in { - assertTesterPasses({ new BlackBoxFlipTester }, - Seq("/chisel3/BlackBoxTest.v")) + assertTesterPasses( + {new BlackBoxFlipTester}, + Seq("/chisel3/BlackBoxTest.v"), + TesterDriver.verilatorOnly) } "Multiple BlackBoxes" should "work" in { - assertTesterPasses({ new MultiBlackBoxTester }, - Seq("/chisel3/BlackBoxTest.v")) + assertTesterPasses( + {new MultiBlackBoxTester}, + Seq("/chisel3/BlackBoxTest.v"), + TesterDriver.verilatorOnly) } "A BlackBoxed register" should "work" in { - assertTesterPasses({ new BlackBoxWithClockTester }, - Seq("/chisel3/BlackBoxTest.v")) + assertTesterPasses( + {new BlackBoxWithClockTester}, + Seq("/chisel3/BlackBoxTest.v"), + TesterDriver.verilatorOnly) } "BlackBoxes with parameters" should "work" in { - assertTesterPasses({ new BlackBoxWithParamsTester }, - Seq("/chisel3/BlackBoxTest.v")) + assertTesterPasses( + {new BlackBoxWithParamsTester}, + Seq("/chisel3/BlackBoxTest.v"), + TesterDriver.verilatorOnly) } "DataMirror.modulePorts" should "work with BlackBox" in { ChiselStage.elaborate(new Module { - val io = IO(new Bundle { }) - val m = Module(new BlackBoxPassthrough) - assert(DataMirror.modulePorts(m) == Seq( - "in" -> m.io.in, "out" -> m.io.out)) - }) + val io = IO(new Bundle {}) + val m = Module(new BlackBoxPassthrough) + assert(DataMirror.modulePorts(m) == Seq("in" -> m.io.in, "out" -> m.io.out)) + } + ) } } diff --git a/src/test/scala/chiselTests/BoringUtilsSpec.scala b/src/test/scala/chiselTests/BoringUtilsSpec.scala index 997466c0..ffc10c88 100644 --- a/src/test/scala/chiselTests/BoringUtilsSpec.scala +++ b/src/test/scala/chiselTests/BoringUtilsSpec.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3._ import chisel3.util.Counter -import chisel3.testers.BasicTester +import chisel3.testers.{BasicTester, TesterDriver} import chisel3.experimental.{BaseModule, ChiselAnnotation, RunFirrtlTransform} import chisel3.util.experimental.BoringUtils @@ -49,7 +49,8 @@ class BoringUtilsSpec extends ChiselFlatSpec with ChiselRunners { behavior of "BoringUtils.{addSink, addSource}" it should "connect two wires within a module" in { - runTester(new ShouldntAssertTester { val dut = Module(new BoringInverter) } ) should be (true) + runTester(new ShouldntAssertTester { val dut = Module(new BoringInverter) }, + annotations = TesterDriver.verilatorOnly) should be (true) } trait WireX { this: BaseModule => @@ -103,11 +104,12 @@ class BoringUtilsSpec extends ChiselFlatSpec with ChiselRunners { behavior of "BoringUtils.bore" it should "connect across modules using BoringUtils.bore" in { - runTester(new TopTester) should be (true) + runTester(new TopTester, annotations = TesterDriver.verilatorOnly) should be (true) } it should "throw an exception if NoDedupAnnotations are removed" in { - intercept[WiringException] { runTester(new TopTester with FailViaDedup) } + intercept[WiringException] { runTester(new TopTester with FailViaDedup, + annotations = Seq(TesterDriver.VerilatorBackend)) } .getMessage should startWith ("Unable to determine source mapping for sink") } @@ -125,7 +127,7 @@ class BoringUtilsSpec extends ChiselFlatSpec with ChiselRunners { } it should "work for an internal (same module) BoringUtils.bore" in { - runTester(new InternalBoreTester) should be (true) + runTester(new InternalBoreTester, annotations = TesterDriver.verilatorOnly) should be (true) } } diff --git a/src/test/scala/chiselTests/ExtModule.scala b/src/test/scala/chiselTests/ExtModule.scala index 582a05ae..39cd65dc 100644 --- a/src/test/scala/chiselTests/ExtModule.scala +++ b/src/test/scala/chiselTests/ExtModule.scala @@ -62,11 +62,11 @@ class MultiExtModuleTester extends BasicTester { class ExtModuleSpec extends ChiselFlatSpec { "A ExtModule inverter" should "work" in { assertTesterPasses({ new ExtModuleTester }, - Seq("/chisel3/BlackBoxTest.v")) + Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) } "Multiple ExtModules" should "work" in { assertTesterPasses({ new MultiExtModuleTester }, - Seq("/chisel3/BlackBoxTest.v")) + Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly) } "DataMirror.modulePorts" should "work with ExtModule" in { ChiselStage.elaborate(new Module { diff --git a/src/test/scala/chiselTests/MultiClockSpec.scala b/src/test/scala/chiselTests/MultiClockSpec.scala index 1a71570d..8b7fddb0 100644 --- a/src/test/scala/chiselTests/MultiClockSpec.scala +++ b/src/test/scala/chiselTests/MultiClockSpec.scala @@ -120,7 +120,7 @@ class MultiClockSpec extends ChiselFlatSpec { } it should "scope ports of memories" in { - assertTesterPasses(new MultiClockMemTest) + assertTesterPasses(new MultiClockMemTest, annotations = TesterDriver.verilatorOnly) } it should "return like a normal Scala block" in { diff --git a/src/test/scala/chiselTests/aop/InjectionSpec.scala b/src/test/scala/chiselTests/aop/InjectionSpec.scala index 6c022d60..7e09bd54 100644 --- a/src/test/scala/chiselTests/aop/InjectionSpec.scala +++ b/src/test/scala/chiselTests/aop/InjectionSpec.scala @@ -2,7 +2,7 @@ package chiselTests.aop -import chisel3.testers.BasicTester +import chisel3.testers.{BasicTester, TesterDriver} import chiselTests.ChiselFlatSpec import chisel3._ import chisel3.aop.injecting.InjectingAspect @@ -47,10 +47,12 @@ class InjectionSpec extends ChiselFlatSpec { assertTesterFails{ new AspectTester(Seq(9, 9, 9)) } } "Test" should "pass if pass wrong values, but correct with aspect" in { - assertTesterPasses({ new AspectTester(Seq(9, 9, 9))} , Nil, Seq(correctValueAspect)) + assertTesterPasses({ new AspectTester(Seq(9, 9, 9))} , Nil, Seq(correctValueAspect) ++ TesterDriver.verilatorOnly) } "Test" should "pass if pass wrong values, then wrong aspect, then correct aspect" in { - assertTesterPasses({ new AspectTester(Seq(9, 9, 9))} , Nil, Seq(wrongValueAspect, correctValueAspect)) + assertTesterPasses( + new AspectTester(Seq(9, 9, 9)), Nil, Seq(wrongValueAspect, correctValueAspect) ++ TesterDriver.verilatorOnly + ) } "Test" should "fail if pass wrong values, then correct aspect, then wrong aspect" in { assertTesterFails({ new AspectTester(Seq(9, 9, 9))} , Nil, Seq(correctValueAspect, wrongValueAspect)) diff --git a/src/test/scala/examples/SimpleVendingMachine.scala b/src/test/scala/examples/SimpleVendingMachine.scala index 2021ece8..49caa92c 100644 --- a/src/test/scala/examples/SimpleVendingMachine.scala +++ b/src/test/scala/examples/SimpleVendingMachine.scala @@ -3,7 +3,7 @@ package examples import chiselTests.ChiselFlatSpec -import chisel3.testers.BasicTester +import chisel3.testers.{BasicTester, TesterDriver} import chisel3._ import chisel3.util._ @@ -49,7 +49,7 @@ class FSMVendingMachine extends SimpleVendingMachine { } class VerilogVendingMachine extends BlackBox { - // Because this is a blackbox, we must explicity add clock and reset + // Because this is a blackbox, we must explicitly add clock and reset val io = IO(new SimpleVendingMachineIO { val clock = Input(Clock()) val reset = Input(Reset()) @@ -90,6 +90,6 @@ class SimpleVendingMachineSpec extends ChiselFlatSpec { } "An Verilog implementation of a vending machine" should "work" in { assertTesterPasses(new SimpleVendingMachineTester(new VerilogVendingMachineWrapper), - List("/chisel3/VerilogVendingMachine.v")) + List("/chisel3/VerilogVendingMachine.v"), annotations = TesterDriver.verilatorOnly) } } |
