summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.sbt4
-rw-r--r--build.sc8
-rw-r--r--src/main/scala/chisel3/testers/TesterDriver.scala180
-rw-r--r--src/test/scala/chisel3/testers/TestUtils.scala12
-rw-r--r--src/test/scala/chisel3/testers/TreadleBackend.scala77
-rw-r--r--src/test/scala/chiselTests/ChiselSpec.scala8
6 files changed, 152 insertions, 137 deletions
diff --git a/build.sbt b/build.sbt
index 84e0efda..60ded729 100644
--- a/build.sbt
+++ b/build.sbt
@@ -29,8 +29,7 @@ def javacOptionsVersion(scalaVersion: String): Seq[String] = {
}
val defaultVersions = Seq(
- "edu.berkeley.cs" %% "firrtl" % "1.4-SNAPSHOT",
- "edu.berkeley.cs" %% "treadle" % "1.3-SNAPSHOT"
+ "edu.berkeley.cs" %% "firrtl" % "1.4-SNAPSHOT"
)
lazy val commonSettings = Seq (
@@ -110,6 +109,7 @@ lazy val chiselSettings = Seq (
"junit" % "junit" % "4.13" % "test",
"org.scalatest" %% "scalatest" % "3.1.2" % "test",
"org.scalatestplus" %% "scalacheck-1-14" % "3.1.1.1" % "test",
+ "edu.berkeley.cs" %% "treadle" % "1.3-SNAPSHOT" % "test",
"com.github.scopt" %% "scopt" % "3.7.1"
),
javacOptions ++= javacOptionsVersion(scalaVersion.value)
diff --git a/build.sc b/build.sc
index 47ca01c8..89cf7464 100644
--- a/build.sc
+++ b/build.sc
@@ -97,9 +97,7 @@ class chisel3CrossModule(crossVersionValue: String) extends CommonModule with Pu
def mainClass = Some("chisel3.stage.ChiselMain")
- def ivyDeps = super.ivyDeps() ++ treadleIvyDeps
-
- override def moduleDeps = super.moduleDeps ++ Seq(macros, core) ++ treadleModule
+ override def moduleDeps = super.moduleDeps ++ Seq(macros, core) ++ firrtlModule
object test extends Tests {
private def ivyCrossDeps = majorVersion match {
@@ -111,7 +109,9 @@ class chisel3CrossModule(crossVersionValue: String) extends CommonModule with Pu
ivy"org.scalatest::scalatest:3.1.2",
ivy"org.scalatestplus::scalacheck-1-14:3.1.1.1",
ivy"com.github.scopt::scopt:3.7.1"
- ) ++ ivyCrossDeps
+ ) ++ ivyCrossDeps ++ m.treadleIvyDeps
+
+ override def moduleDeps = super.moduleDeps ++ treadleModule
def testFrameworks = Seq("org.scalatest.tools.Framework")
diff --git a/src/main/scala/chisel3/testers/TesterDriver.scala b/src/main/scala/chisel3/testers/TesterDriver.scala
index 2a66526c..70dd4999 100644
--- a/src/main/scala/chisel3/testers/TesterDriver.scala
+++ b/src/main/scala/chisel3/testers/TesterDriver.scala
@@ -7,39 +7,67 @@ import java.io._
import chisel3._
import chisel3.stage.phases.{Convert, Elaborate, Emitter}
import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation, ChiselStage, NoRunFirrtlCompilerAnnotation}
-import treadle.stage.TreadleTesterPhase
import firrtl.AnnotationSeq
import firrtl.annotations.NoTargetAnnotation
import firrtl.options.{Dependency, Phase, PhaseManager, TargetDirAnnotation, Unserializable}
import firrtl.stage.{FirrtlCircuitAnnotation, FirrtlStage}
import firrtl.transforms.BlackBoxSourceHelper.writeResourceToDirectory
-import treadle.executable.StopException
-import treadle.{CallResetAtStartupAnnotation, TreadleTesterAnnotation, WriteVcdAnnotation}
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. To:
- `val defaultBackend: Backend = TreadleBackend`
- */
+
+ private[chisel3] trait Backend extends NoTargetAnnotation with Unserializable {
+ def execute(t: () => BasicTester,
+ additionalVResources: Seq[String] = Seq(),
+ annotations: AnnotationSeq = Seq(),
+ nameHint: Option[String] = None
+ ): Boolean
+ }
+ case object VerilatorBackend extends Backend {
+ /** 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,
+ additionalVResources: Seq[String] = Seq(),
+ annotations: AnnotationSeq = Seq(),
+ nameHint: Option[String] = None
+ ): Boolean = {
+ val pm = new PhaseManager(
+ targets = Seq(Dependency[AddImplicitTesterDirectory],
+ Dependency[Emitter],
+ Dependency[Convert]))
+
+ val annotationsx = pm.transform(ChiselGeneratorAnnotation(finishWrapper(t)) +: annotations)
+
+ val target: String = annotationsx.collectFirst { case FirrtlCircuitAnnotation(cir) => cir.main }.get
+ val path = annotationsx.collectFirst { case TargetDirAnnotation(dir) => dir }.map(new File(_)).get
+
+ // Copy CPP harness and other Verilog sources from resources into files
+ val cppHarness = new File(path, "top.cpp")
+ copyResourceToFile("/chisel3/top.cpp", cppHarness)
+ // NOTE: firrtl.Driver.execute() may end up copying these same resources in its BlackBoxSourceHelper code.
+ // As long as the same names are used for the output files, and we avoid including duplicate files
+ // in BackendCompilationUtilities.verilogToCpp(), we should be okay.
+ // To that end, we use the same method to write the resource to the target directory.
+ val additionalVFiles = additionalVResources.map((name: String) => {
+ writeResourceToDirectory(name, path)
+ })
+
+ (new FirrtlStage).execute(Array("--compiler", "verilog"), annotationsx)
+
+ // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe
+ if ((verilogToCpp(target, path, additionalVFiles, cppHarness) #&&
+ cppToExe(target, path)).! == 0) {
+ executeExpectingSuccess(target, path)
+ } else {
+ false
+ }
+ }
+ }
+
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)
- }
- }
+ def verilatorOnly: AnnotationSeq = Seq(VerilatorBackend)
/** Set the target directory to the name of the top module after elaboration */
final class AddImplicitTesterDirectory extends Phase {
@@ -73,113 +101,7 @@ object TesterDriver extends BackendCompilationUtilities {
} 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 NoBackend =>
- true
- 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],
- Dependency[Emitter],
- Dependency[Convert]))
-
- val annotationsx = pm.transform(ChiselGeneratorAnnotation(finishWrapper(t)) +: annotations)
-
- val target: String = annotationsx.collectFirst { case FirrtlCircuitAnnotation(cir) => cir.main }.get
- val path = annotationsx.collectFirst { case TargetDirAnnotation(dir) => dir }.map(new File(_)).get
-
- // Copy CPP harness and other Verilog sources from resources into files
- val cppHarness = new File(path, "top.cpp")
- copyResourceToFile("/chisel3/top.cpp", cppHarness)
- // NOTE: firrtl.Driver.execute() may end up copying these same resources in its BlackBoxSourceHelper code.
- // As long as the same names are used for the output files, and we avoid including duplicate files
- // in BackendCompilationUtilities.verilogToCpp(), we should be okay.
- // To that end, we use the same method to write the resource to the target directory.
- val additionalVFiles = additionalVResources.map((name: String) => {
- writeResourceToDirectory(name, path)
- })
-
- (new FirrtlStage).execute(Array("--compiler", "verilog"), annotationsx)
-
- // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe
- if ((verilogToCpp(target, path, additionalVFiles, cppHarness) #&&
- cppToExe(target, path)).! == 0) {
- executeExpectingSuccess(target, path)
- } else {
- false
- }
- }
-
- 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 = (new 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
- }
+ backendAnnotation.execute(t, additionalVResources, annotations, nameHint)
}
/**
diff --git a/src/test/scala/chisel3/testers/TestUtils.scala b/src/test/scala/chisel3/testers/TestUtils.scala
new file mode 100644
index 00000000..97cf9190
--- /dev/null
+++ b/src/test/scala/chisel3/testers/TestUtils.scala
@@ -0,0 +1,12 @@
+// See LICENSE for license details.
+
+package chisel3.testers
+
+import TesterDriver.Backend
+import firrtl.AnnotationSeq
+
+object TestUtils {
+ // Useful because TesterDriver.Backend is chisel3 package private
+ def containsBackend(annos: AnnotationSeq): Boolean =
+ annos.collectFirst { case b: Backend => b }.isDefined
+}
diff --git a/src/test/scala/chisel3/testers/TreadleBackend.scala b/src/test/scala/chisel3/testers/TreadleBackend.scala
new file mode 100644
index 00000000..e432ce35
--- /dev/null
+++ b/src/test/scala/chisel3/testers/TreadleBackend.scala
@@ -0,0 +1,77 @@
+// See LICENSE for license details.
+
+package chisel3.testers
+
+import TesterDriver.createTestDirectory
+import chisel3._
+import chisel3.stage._
+import firrtl.AnnotationSeq
+import firrtl.annotations.NoTargetAnnotation
+import firrtl.options.TargetDirAnnotation
+import treadle.stage.TreadleTesterPhase
+import treadle.executable.StopException
+import treadle.{CallResetAtStartupAnnotation, TreadleTesterAnnotation, WriteVcdAnnotation}
+
+import java.io.File
+
+case object TreadleBackend extends TesterDriver.Backend {
+ val MaxTreadleCycles = 10000L
+
+ def execute(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 = (new 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
+ }
+ }
+}
diff --git a/src/test/scala/chiselTests/ChiselSpec.scala b/src/test/scala/chiselTests/ChiselSpec.scala
index e50f26e8..eb3ec3e6 100644
--- a/src/test/scala/chiselTests/ChiselSpec.scala
+++ b/src/test/scala/chiselTests/ChiselSpec.scala
@@ -10,7 +10,7 @@ import chisel3._
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
import chisel3.testers._
import firrtl.{AnnotationSeq, CommonOptions, EmittedVerilogCircuitAnnotation, ExecutionOptionsManager, FirrtlExecutionFailure, FirrtlExecutionSuccess, HasFirrtlOptions}
-import firrtl.annotations.DeletedAnnotation
+import firrtl.annotations.{Annotation, DeletedAnnotation}
import firrtl.util.BackendCompilationUtilities
import java.io.ByteArrayOutputStream
import java.security.Permission
@@ -26,7 +26,11 @@ trait ChiselRunners extends Assertions with BackendCompilationUtilities {
additionalVResources: Seq[String] = Seq(),
annotations: AnnotationSeq = Seq()
): Boolean = {
- TesterDriver.execute(() => t, additionalVResources, annotations)
+ // Change this to enable Treadle as a backend
+ val defaultBackend = chisel3.testers.TesterDriver.defaultBackend
+ val hasBackend = TestUtils.containsBackend(annotations)
+ val annos: Seq[Annotation] = if (hasBackend) annotations else defaultBackend +: annotations
+ TesterDriver.execute(() => t, additionalVResources, annos)
}
def assertTesterPasses(t: => BasicTester,
additionalVResources: Seq[String] = Seq(),