summaryrefslogtreecommitdiff
path: root/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala
diff options
context:
space:
mode:
authorChick Markley2016-12-07 10:31:23 -0800
committerGitHub2016-12-07 10:31:23 -0800
commitad53161bbb9f67e16b88ca7a508a537f88d77e05 (patch)
treed041b864ff72f5a3f171e98780200361ea961f2c /src/test/scala/chiselTests/AnnotatingDiamondSpec.scala
parent9aba55e7452981058d069b3096544d45e730dba9 (diff)
Support for creating chisel annotations that are consumed by firrtl (#393)
* Support for creating chisel annotations that are consumed by firrtl Update annotation serialization in Driver Add DiamondAnnotation Spec that illustrates how to do simple annotations frontEnd must have dependency on firrtl Add annotation method to Module Circuit has extra optional parameter that is Seq of Annotations In Builder add annotation buffer to DynamicContext to store annotations created in modules Added explicit types on naming api methods to avoid type confusion Because some names are not available until elaboration create intermediate ChiselAnnotation that gets turned into a firrtl Annotation after elaboration In execute pass firrtl text and annotation to firrtl are now passed in through optionManager, though intermediate file .fir and .anno files are still created for inspection and/or later use * Somehow missed ChiselAnnotation * fixes for Jack's review of PR
Diffstat (limited to 'src/test/scala/chiselTests/AnnotatingDiamondSpec.scala')
-rw-r--r--src/test/scala/chiselTests/AnnotatingDiamondSpec.scala164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala
new file mode 100644
index 00000000..3886ddd6
--- /dev/null
+++ b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala
@@ -0,0 +1,164 @@
+// See LICENSE for license details.
+
+package chiselTests
+
+import chisel3._
+import chisel3.internal.InstanceId
+import chisel3.testers.BasicTester
+import firrtl.{CircuitForm, CircuitState, LowForm, Transform}
+import firrtl.annotations.{Annotation, ModuleName, Named}
+import org.scalatest._
+
+//scalastyle:off magic.number
+/**
+ * This and the Identity transform class are a highly schematic implementation of a
+ * library implementation of (i.e. code outside of firrtl itself)
+ */
+object IdentityAnnotation {
+ def apply(target: Named, value: String): Annotation = Annotation(target, classOf[IdentityTransform], value)
+
+ def unapply(a: Annotation): Option[(Named, String)] = a match {
+ case Annotation(named, t, value) if t == classOf[IdentityTransform] => Some((named, value))
+ case _ => None
+ }
+}
+
+class IdentityTransform extends Transform {
+ override def inputForm: CircuitForm = LowForm
+
+ override def outputForm: CircuitForm = LowForm
+
+ override def execute(state: CircuitState): CircuitState = {
+ getMyAnnotations(state) match {
+ case Nil => state
+ case myAnnotations =>
+ /* Do something useful with annotations here */
+ state
+ }
+ }
+}
+
+trait IdentityAnnotator {
+ self: Module =>
+ def identify(component: InstanceId, value: String): Unit = {
+ annotate(ChiselAnnotation(component, classOf[IdentityTransform], value))
+ }
+}
+/** A diamond circuit Top instantiates A and B and both A and B instantiate C
+ * Illustrations of annotations of various components and modules in both
+ * relative and absolute cases
+ *
+ * This is currently not much of a test, read the printout to see what annotations look like
+ */
+/**
+ * This class has parameterizable widths, it will generate different hardware
+ * @param widthC io width
+ */
+class ModC(widthC: Int) extends Module with IdentityAnnotator {
+ val io = IO(new Bundle {
+ val in = Input(UInt(widthC.W))
+ val out = Output(UInt(widthC.W))
+ })
+ io.out := io.in
+
+ identify(this, s"ModC($widthC)")
+
+ identify(io.out, s"ModC(ignore param)")
+}
+
+/**
+ * instantiates a C of a particular size, ModA does not generate different hardware
+ * based on it's parameter
+ * @param annoParam parameter is only used in annotation not in circuit
+ */
+class ModA(annoParam: Int) extends Module with IdentityAnnotator {
+ val io = IO(new Bundle {
+ val in = Input(UInt())
+ val out = Output(UInt())
+ })
+ val modC = Module(new ModC(16))
+ modC.io.in := io.in
+ io.out := modC.io.out
+
+ identify(this, s"ModA(ignore param)")
+
+ identify(io.out, s"ModA.io.out($annoParam)")
+ identify(io.out, s"ModA.io.out(ignore_param)")
+}
+
+class ModB(widthB: Int) extends Module with IdentityAnnotator{
+ val io = IO(new Bundle {
+ val in = Input(UInt(widthB.W))
+ val out = Output(UInt(widthB.W))
+ })
+ val modC = Module(new ModC(widthB))
+ modC.io.in := io.in
+ io.out := modC.io.out
+
+ identify(io.in, s"modB.io.in annotated from inside modB")
+}
+
+class TopOfDiamond extends Module with IdentityAnnotator {
+ val io = IO(new Bundle {
+ val in = Input(UInt(32.W))
+ val out = Output(UInt(32.W))
+ })
+ val x = Reg(UInt(32.W))
+ val y = Reg(UInt(32.W))
+
+ val modA = Module(new ModA(64))
+ val modB = Module(new ModB(32))
+
+ x := io.in
+ modA.io.in := x
+ modB.io.in := x
+
+ y := modA.io.out + modB.io.out
+ io.out := y
+
+ identify(this, s"TopOfDiamond\nWith\nSome new lines")
+
+ identify(modB.io.in, s"modB.io.in annotated from outside modB")
+}
+
+class DiamondTester extends BasicTester {
+ val dut = Module(new TopOfDiamond)
+
+ stop()
+}
+
+class AnnotatingDiamondSpec extends FreeSpec with Matchers {
+ def findAnno(as: Seq[Annotation], name: String): Option[Annotation] = {
+ as.find { a => a.targetString == name }
+ }
+
+ """
+ |Diamond is an example of a module that has two sub-modules A and B who both instantiate their
+ |own instances of module C. This highlights the difference between specific and general
+ |annotation scopes
+ """.stripMargin - {
+
+ """
+ |annotations are not resolved at after circuit elaboration,
+ |that happens only after emit has been called on circuit""".stripMargin in {
+
+ Driver.execute(Array.empty[String], () => new TopOfDiamond) match {
+ case ChiselExecutionSucccess(Some(circuit), emitted, _) =>
+ val annos = circuit.annotations
+ annos.length should be (10)
+
+ annos.count {
+ case Annotation(ModuleName(name, _), _, annoValue) => name == "ModC" && annoValue == "ModC(16)"
+ case _ => false
+ } should be (1)
+
+ annos.count {
+ case Annotation(ModuleName(name, _), _, annoValue) => name == "ModC_1" && annoValue == "ModC(32)"
+ case _ => false
+ } should be (1)
+ case _ =>
+ assert(false)
+ }
+ }
+ }
+} \ No newline at end of file