From bc4f64020b8115d04af00e92bf9a7c68d9b35443 Mon Sep 17 00:00:00 2001 From: chick Date: Wed, 17 Aug 2016 16:12:33 -0700 Subject: Add annotating example to test new signal name api --- src/test/scala/chiselTests/AnnotatingExample.scala | 115 +++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/test/scala/chiselTests/AnnotatingExample.scala (limited to 'src/test') diff --git a/src/test/scala/chiselTests/AnnotatingExample.scala b/src/test/scala/chiselTests/AnnotatingExample.scala new file mode 100644 index 00000000..dc0d0421 --- /dev/null +++ b/src/test/scala/chiselTests/AnnotatingExample.scala @@ -0,0 +1,115 @@ +// See LICENSE for license details. + +package chiselTests + +import chisel3._ +import chisel3.core.Module +import chisel3.internal.Builder +import chisel3.internal.firrtl.{Emitter, Circuit} +import chisel3.testers.BasicTester +import org.scalatest._ +import org.scalatest.prop._ + +import scala.util.DynamicVariable + +class SomeSubMod 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(io.out, JustThisRef)) = "sub mod io.out" +} + +class AnnotatingExample extends Module { + val io = new Bundle { + val a = UInt(INPUT, 32) + val b = UInt(INPUT, 32) + val e = Bool(INPUT) + val z = UInt(OUTPUT, 32) + val v = Bool(OUTPUT) + val bun = new Bundle { + val nested_1 = UInt(INPUT, 12) + val nested_2 = Bool(OUTPUT) + } + } + val x = Reg(UInt(width = 32)) + val y = Reg(UInt(width = 32)) + + val subModule1 = Module(new SomeSubMod) + val subModule2 = Module(new SomeSubMod) + + + val annotate = MyBuilder.myDynamicContext.annotationMap + + 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_2, JustThisRef)) = "I am io.bun.nested_2" + + when (x > y) { x := x -% y } + .otherwise { y := y -% x } + when (io.e) { x := io.a; y := io.b } + io.z := x + io.v := y === UInt(0) +} + +class AnnotatingExampleTester(a: Int, b: Int, z: Int) extends BasicTester { + val dut = Module(new AnnotatingExample) + val first = Reg(init=Bool(true)) + dut.io.a := UInt(a) + dut.io.b := UInt(b) + dut.io.e := first + when(first) { first := Bool(false) } + when(!first && dut.io.v) { + assert(dut.io.z === UInt(z)) + stop() + } +} + +class AnnotatingExampleSpec extends ChiselPropSpec { + + property("show node info") { + MyDriver.doStuff { () => new AnnotatingExampleTester(1, 2, 3) } + } + +} + +trait AnnotationScope +case object Default extends AnnotationScope +case object AllRefs extends AnnotationScope +case object JustThisRef extends AnnotationScope + +case class AnnotationKey(val component: Data, scope: AnnotationScope) + +class MyDynamicContext { + val annotationMap = new scala.collection.mutable.HashMap[AnnotationKey, String] +} + +object MyBuilder { + private val myDynamicContextVar = new DynamicVariable[Option[MyDynamicContext]](None) + + def myDynamicContext: MyDynamicContext = + myDynamicContextVar.value getOrElse (new MyDynamicContext) + + def build[T <: Module](f: => T): Unit = { + 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")) + } + } +} + +object MyDriver extends BackendCompilationUtilities { + def doStuff[T <: Module](gen: () => T): Unit = MyBuilder.build(Module(gen())) +} \ No newline at end of file -- cgit v1.2.3 From 3f771ee67b9f8fa0d92ce00af1ea062c5a2605b2 Mon Sep 17 00:00:00 2001 From: chick Date: Thu, 18 Aug 2016 13:03:16 -0700 Subject: Add AnnotationSpec file which provides an example of a way to implement generation of annotations in a chisel circuit that could be used by custom firrtl passes This spec also shows and tests in a limited way the new API of .signalName, .pathName, parentModName which allows access to the various path information of a chisel component (something that subclasses SignalId, most prominently SubClasses of Data and Module --- src/test/scala/chiselTests/AnnotatingExample.scala | 102 +++++++++++++++------ 1 file changed, 72 insertions(+), 30 deletions(-) (limited to 'src/test') 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 -- cgit v1.2.3 From a177f40f1ff2482ba268a27e0af02b57713e781a Mon Sep 17 00:00:00 2001 From: chick Date: Fri, 19 Aug 2016 12:28:35 -0700 Subject: AnnotatingExample: Removed extraneous logic Renamed doStuff to buildAnnotatedCircuit Removed println's --- src/test/scala/chiselTests/AnnotatingExample.scala | 54 +++++++++------------- 1 file changed, 21 insertions(+), 33 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/AnnotatingExample.scala b/src/test/scala/chiselTests/AnnotatingExample.scala index 073355fc..a252309d 100644 --- a/src/test/scala/chiselTests/AnnotatingExample.scala +++ b/src/test/scala/chiselTests/AnnotatingExample.scala @@ -27,9 +27,11 @@ class SomeSubMod(param1: Int, param2: Int) extends Module { val in = UInt(INPUT, 16) val out = SInt(OUTPUT, 32) } - 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" + val annotate = MyBuilder.myDynamicContext.annotationMap + + annotate(AnnotationKey(this, JustThisRef)) = s"SomeSubMod($param1, $param2)" + annotate(AnnotationKey(io.in, AllRefs)) = "sub mod io.in" + annotate(AnnotationKey(io.out, JustThisRef)) = "sub mod io.out" } class AnnotatingExample extends Module { @@ -56,40 +58,35 @@ class AnnotatingExample extends Module { annotate(AnnotationKey(subModule2, AllRefs)) = s"SomeSubMod was used" annotate(AnnotationKey(x, JustThisRef)) = "I am register X" + annotate(AnnotationKey(y, AllRefs)) = "I am register Y" annotate(AnnotationKey(io.a, JustThisRef)) = "I am io.a" 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 } - .otherwise { y := y -% x } - when (io.e) { x := io.a; y := io.b } - io.z := x - io.v := y === UInt(0) } -class AnnotatingExampleTester(a: Int, b: Int, z: Int) extends BasicTester { +class AnnotatingExampleTester extends BasicTester { val dut = Module(new AnnotatingExample) - val first = Reg(init=Bool(true)) - dut.io.a := UInt(a) - dut.io.b := UInt(b) - dut.io.e := first - when(first) { first := Bool(false) } - when(!first && dut.io.v) { - assert(dut.io.z === UInt(z)) - stop() - } + + stop() } class AnnotatingExampleSpec extends FlatSpec with Matchers { behavior of "Annotating components of a circuit" - val annotationMap = MyDriver.doStuff { () => new AnnotatingExampleTester(1, 2, 3) } it should "contain the following relative keys" in { + val annotationMap = MyDriver.buildAnnotatedCircuit { () => new AnnotatingExampleTester } + annotationMap.contains("SomeSubMod.io.in") should be(true) + annotationMap.contains("AnnotatingExample.y") should be(true) + annotationMap("SomeSubMod.io.in") should be("sub mod io.in") } it should "contain the following absolute keys" in { + val annotationMap = MyDriver.buildAnnotatedCircuit { () => new AnnotatingExampleTester } + annotationMap.contains("AnnotatingExampleTester.dut.subModule2.io.out") should be (true) + annotationMap.contains("AnnotatingExampleTester.dut.x") should be (true) + annotationMap("AnnotatingExampleTester.dut.subModule2.io.out") should be ("sub mod io.out") } } @@ -129,18 +126,6 @@ object MyBuilder { 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 } @@ -153,5 +138,8 @@ object MyBuilder { } object MyDriver extends BackendCompilationUtilities { - def doStuff[T <: Module](gen: () => T): Map[String, String] = MyBuilder.build(Module(gen())) + /** + * illustrates a chisel3 style driver that, annotations can only processed within this structure + */ + def buildAnnotatedCircuit[T <: Module](gen: () => T): Map[String, String] = MyBuilder.build(Module(gen())) } \ No newline at end of file -- cgit v1.2.3 From f5e9a6c6e55ba19a7c1f2353d0207189062db1c9 Mon Sep 17 00:00:00 2001 From: chick Date: Wed, 24 Aug 2016 17:09:41 -0700 Subject: Per Chisel meeting. signalName -> instanceName SignalId -> InstanceId Based on Stephen's comments on PR --- src/test/scala/chiselTests/AnnotatingExample.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/test') diff --git a/src/test/scala/chiselTests/AnnotatingExample.scala b/src/test/scala/chiselTests/AnnotatingExample.scala index a252309d..c84edf86 100644 --- a/src/test/scala/chiselTests/AnnotatingExample.scala +++ b/src/test/scala/chiselTests/AnnotatingExample.scala @@ -4,7 +4,7 @@ package chiselTests import chisel3._ import chisel3.core.Module -import chisel3.internal.SignalId +import chisel3.internal.InstanceId import chisel3.testers.BasicTester import org.scalatest._ @@ -96,17 +96,17 @@ case object AllRefs extends AnnotationScope case object JustThisRef extends AnnotationScope object AnnotationKey { - def apply(component: SignalId): AnnotationKey = { + def apply(component: InstanceId): AnnotationKey = { AnnotationKey(component, AllRefs) } } -case class AnnotationKey(val component: SignalId, scope: AnnotationScope) { +case class AnnotationKey(val component: InstanceId, scope: AnnotationScope) { override def toString: String = { scope match { case JustThisRef => s"${component.pathName}" case AllRefs => - s"${component.parentModName}.${component.signalName}" + s"${component.parentModName}.${component.instanceName}" case _ => s"${component.toString}_unknown_scope" } -- cgit v1.2.3