diff options
| -rw-r--r-- | src/test/scala/chiselTests/AnnotatingExample.scala | 102 |
1 files changed, 72 insertions, 30 deletions
diff --git a/src/test/scala/chiselTests/AnnotatingExample.scala b/src/test/scala/chiselTests/AnnotatingExample.scala index dc0d0421..073355fc 100644 --- a/src/test/scala/chiselTests/AnnotatingExample.scala +++ b/src/test/scala/chiselTests/AnnotatingExample.scala @@ -4,20 +4,31 @@ package chiselTests import chisel3._ import chisel3.core.Module -import chisel3.internal.Builder -import chisel3.internal.firrtl.{Emitter, Circuit} +import chisel3.internal.SignalId import chisel3.testers.BasicTester import org.scalatest._ -import org.scalatest.prop._ import scala.util.DynamicVariable -class SomeSubMod extends Module { +//scalastyle:off magic.number + +/** + * This Spec file illustrates use of Donggyu's component name API, it currently only + * uses three methods .signalName, .parentModName and .pathName + * + * This is also an illustration of how to implement an annotation system in chisel3 + * A local (my) Driver and Builder are created to provide thread-local access to + * an annotation map, and then a post elaboration annotation processor can resolve + * the keys and could serialize the annotations to a file for use by firrtl passes + */ + +class SomeSubMod(param1: Int, param2: Int) extends Module { val io = new Bundle { val in = UInt(INPUT, 16) val out = SInt(OUTPUT, 32) } - MyBuilder.myDynamicContext.annotationMap(AnnotationKey(io.in, AllRefs)) = "sub mod io.in" + MyBuilder.myDynamicContext.annotationMap(AnnotationKey(this, JustThisRef)) = s"SomeSubMod($param1, $param2)" + MyBuilder.myDynamicContext.annotationMap(AnnotationKey(io.in, AllRefs)) = "sub mod io.in" MyBuilder.myDynamicContext.annotationMap(AnnotationKey(io.out, JustThisRef)) = "sub mod io.out" } @@ -36,15 +47,17 @@ class AnnotatingExample extends Module { val x = Reg(UInt(width = 32)) val y = Reg(UInt(width = 32)) - val subModule1 = Module(new SomeSubMod) - val subModule2 = Module(new SomeSubMod) + val subModule1 = Module(new SomeSubMod(1, 2)) + val subModule2 = Module(new SomeSubMod(3, 4)) val annotate = MyBuilder.myDynamicContext.annotationMap + annotate(AnnotationKey(subModule2, AllRefs)) = s"SomeSubMod was used" + annotate(AnnotationKey(x, JustThisRef)) = "I am register X" annotate(AnnotationKey(io.a, JustThisRef)) = "I am io.a" - annotate(AnnotationKey(io.bun.nested_1, JustThisRef)) = "I am io.bun.nested_1" + annotate(AnnotationKey(io.bun.nested_1, AllRefs)) = "I am io.bun.nested_1" annotate(AnnotationKey(io.bun.nested_2, JustThisRef)) = "I am io.bun.nested_2" when (x > y) { x := x -% y } @@ -67,49 +80,78 @@ class AnnotatingExampleTester(a: Int, b: Int, z: Int) extends BasicTester { } } -class AnnotatingExampleSpec extends ChiselPropSpec { +class AnnotatingExampleSpec extends FlatSpec with Matchers { + behavior of "Annotating components of a circuit" - property("show node info") { - MyDriver.doStuff { () => new AnnotatingExampleTester(1, 2, 3) } + val annotationMap = MyDriver.doStuff { () => new AnnotatingExampleTester(1, 2, 3) } + it should "contain the following relative keys" in { + annotationMap.contains("SomeSubMod.io.in") should be(true) + annotationMap("SomeSubMod.io.in") should be("sub mod io.in") + } + it should "contain the following absolute keys" in { + annotationMap.contains("AnnotatingExampleTester.dut.subModule2.io.out") should be (true) + annotationMap("AnnotatingExampleTester.dut.subModule2.io.out") should be ("sub mod io.out") } - } trait AnnotationScope -case object Default extends AnnotationScope -case object AllRefs extends AnnotationScope +case object AllRefs extends AnnotationScope case object JustThisRef extends AnnotationScope -case class AnnotationKey(val component: Data, scope: AnnotationScope) +object AnnotationKey { + def apply(component: SignalId): AnnotationKey = { + AnnotationKey(component, AllRefs) + } +} +case class AnnotationKey(val component: SignalId, scope: AnnotationScope) { + override def toString: String = { + scope match { + case JustThisRef => + s"${component.pathName}" + case AllRefs => + s"${component.parentModName}.${component.signalName}" + case _ => + s"${component.toString}_unknown_scope" + } + } +} + +class AnnotationMap extends scala.collection.mutable.HashMap[AnnotationKey, String] class MyDynamicContext { - val annotationMap = new scala.collection.mutable.HashMap[AnnotationKey, String] + val annotationMap = new AnnotationMap } object MyBuilder { private val myDynamicContextVar = new DynamicVariable[Option[MyDynamicContext]](None) def myDynamicContext: MyDynamicContext = - myDynamicContextVar.value getOrElse (new MyDynamicContext) + myDynamicContextVar.value getOrElse new MyDynamicContext + + def processAnnotations(annotationMap: AnnotationMap): Map[String, String] = { + val list = annotationMap.map { case (k,v) => + k match { + case (AnnotationKey(signal, JustThisRef)) => + f"Just this ref $k%60s -> $v%40s component $signal" + case (AnnotationKey(signal, AllRefs)) => + f"All refs $k%60s -> $v%40s component $signal" + case _ => + s"Unknown annotation key $k" + } + }.toList.sorted.mkString("\n") + println(s"Sorted list of annotations\n$list") + + annotationMap.map { case (k,v) => k.toString -> v}.toMap + } - def build[T <: Module](f: => T): Unit = { + def build[T <: Module](f: => T): Map[String, String] = { myDynamicContextVar.withValue(Some(new MyDynamicContext)) { Driver.emit(() => f) - val list = myDynamicContextVar.value.get.annotationMap.map { case (k,v) => - k match { - case (AnnotationKey(signal, JustThisRef)) => - f"Just this ref ${signal.pathName + signal.signalName}%60s -> $v%30s component $signal" - case (AnnotationKey(signal, AllRefs)) => - f"All refs ${signal.signalName}%60s -> $v%30s component $signal" - case _ => - s"Unknown annotation key $k" - } - }.toList.sorted - println(list.mkString("\n")) + processAnnotations(myDynamicContextVar.value.get.annotationMap) } } } object MyDriver extends BackendCompilationUtilities { - def doStuff[T <: Module](gen: () => T): Unit = MyBuilder.build(Module(gen())) + def doStuff[T <: Module](gen: () => T): Map[String, String] = MyBuilder.build(Module(gen())) }
\ No newline at end of file |
