summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/src/main/scala/chisel3/Annotation.scala11
-rw-r--r--core/src/main/scala/chisel3/internal/Builder.scala13
-rw-r--r--core/src/main/scala/chisel3/internal/firrtl/IR.scala37
-rw-r--r--src/test/scala/chiselTests/NewAnnotationsSpec.scala72
4 files changed, 127 insertions, 6 deletions
diff --git a/core/src/main/scala/chisel3/Annotation.scala b/core/src/main/scala/chisel3/Annotation.scala
index e08557eb..c350fb30 100644
--- a/core/src/main/scala/chisel3/Annotation.scala
+++ b/core/src/main/scala/chisel3/Annotation.scala
@@ -20,6 +20,14 @@ trait ChiselAnnotation {
def toFirrtl: Annotation
}
+/** Enhanced interface for Annotations in Chisel
+ *
+ * Defines a conversion to corresponding FIRRTL Annotation(s)
+ */
+trait ChiselMultiAnnotation {
+ def toFirrtl: Seq[Annotation]
+}
+
/** Mixin for [[ChiselAnnotation]] that instantiates an associated FIRRTL Transform when this Annotation is present
* during a run of
* [[Driver$.execute(args:Array[String],dut:()=>chisel3\.RawModule)* Driver.execute]].
@@ -34,6 +42,9 @@ object annotate {
def apply(anno: ChiselAnnotation): Unit = {
Builder.annotations += anno
}
+ def apply(annos: ChiselMultiAnnotation): Unit = {
+ Builder.newAnnotations += annos
+ }
}
/** Marks that a module to be ignored in Dedup Transform in Firrtl pass
diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala
index 35dd01ab..61f94f8f 100644
--- a/core/src/main/scala/chisel3/internal/Builder.scala
+++ b/core/src/main/scala/chisel3/internal/Builder.scala
@@ -404,6 +404,7 @@ private[chisel3] class DynamicContext(
val components = ArrayBuffer[Component]()
val annotations = ArrayBuffer[ChiselAnnotation]()
+ val newAnnotations = ArrayBuffer[ChiselMultiAnnotation]()
var currentModule: Option[BaseModule] = None
/** Contains a mapping from a elaborated module to their aspect
@@ -466,9 +467,13 @@ private[chisel3] object Builder extends LazyLogging {
def idGen: IdGen = chiselContext.get.idGen
- def globalNamespace: Namespace = dynamicContext.globalNamespace
- def components: ArrayBuffer[Component] = dynamicContext.components
- def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations
+ def globalNamespace: Namespace = dynamicContext.globalNamespace
+ def components: ArrayBuffer[Component] = dynamicContext.components
+ def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations
+
+ // TODO : Unify this with annotations in the future - done this way for backward compatability
+ def newAnnotations: ArrayBuffer[ChiselMultiAnnotation] = dynamicContext.newAnnotations
+
def annotationSeq: AnnotationSeq = dynamicContext.annotationSeq
def namingStack: NamingStack = dynamicContext.namingStack
def importDefinitionMap: Map[String, String] = dynamicContext.importDefinitionMap
@@ -770,7 +775,7 @@ private[chisel3] object Builder extends LazyLogging {
errors.checkpoint(logger)
logger.info("Done elaborating.")
- (Circuit(components.last.name, components.toSeq, annotations.toSeq, makeViewRenameMap), mod)
+ (Circuit(components.last.name, components.toSeq, annotations.toSeq, makeViewRenameMap, newAnnotations.toSeq), mod)
}
}
initializeSingletons()
diff --git a/core/src/main/scala/chisel3/internal/firrtl/IR.scala b/core/src/main/scala/chisel3/internal/firrtl/IR.scala
index 9327c29e..dc9ab027 100644
--- a/core/src/main/scala/chisel3/internal/firrtl/IR.scala
+++ b/core/src/main/scala/chisel3/internal/firrtl/IR.scala
@@ -861,7 +861,40 @@ case class DefBlackBox(
params: Map[String, Param])
extends Component
-case class Circuit(name: String, components: Seq[Component], annotations: Seq[ChiselAnnotation], renames: RenameMap) {
- def firrtlAnnotations: Iterable[Annotation] = annotations.flatMap(_.toFirrtl.update(renames))
+case class Circuit(
+ name: String,
+ components: Seq[Component],
+ @deprecated("Do not use annotations val of Circuit directly - use firrtlAnnotations instead. Will be removed in a future release",
+ "Chisel 3.5")
+ annotations: Seq[ChiselAnnotation],
+ renames: RenameMap,
+ @deprecated("Do not use newAnnotations val of Circuit directly - use firrtlAnnotations instead. Will be removed in a future release",
+ "Chisel 3.5")
+
+ newAnnotations: Seq[ChiselMultiAnnotation]) {
+
+ def this(name: String, components: Seq[Component], annotations: Seq[ChiselAnnotation], renames: RenameMap) =
+ this(name, components, annotations, renames, Seq.empty)
+
+ def firrtlAnnotations: Iterable[Annotation] =
+ annotations.flatMap(_.toFirrtl.update(renames)) ++ newAnnotations.flatMap(
+ _.toFirrtl.flatMap(_.update(renames))
+ )
+
+ def copy(
+ name: String = name,
+ components: Seq[Component] = components,
+ annotations: Seq[ChiselAnnotation] = annotations,
+ renames: RenameMap = renames
+ ) = Circuit(name, components, annotations, renames, newAnnotations)
+
+}
+object Circuit
+ extends scala.runtime.AbstractFunction4[String, Seq[Component], Seq[ChiselAnnotation], RenameMap, Circuit] {
+ def unapply(c: Circuit): Option[(String, Seq[Component], Seq[ChiselAnnotation], RenameMap)] = {
+ Some((c.name, c.components, c.annotations, c.renames))
+ }
+ def apply(name: String, components: Seq[Component], annotations: Seq[ChiselAnnotation], renames: RenameMap): Circuit =
+ new Circuit(name, components, annotations, renames)
}
diff --git a/src/test/scala/chiselTests/NewAnnotationsSpec.scala b/src/test/scala/chiselTests/NewAnnotationsSpec.scala
new file mode 100644
index 00000000..38e1c1d9
--- /dev/null
+++ b/src/test/scala/chiselTests/NewAnnotationsSpec.scala
@@ -0,0 +1,72 @@
+package chiselTests
+import chisel3._
+import chisel3.experimental.{annotate, ChiselMultiAnnotation}
+import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
+import firrtl.stage.FirrtlCircuitAnnotation
+import org.scalatest.freespec.AnyFreeSpec
+import org.scalatest.matchers.should.Matchers
+import firrtl.transforms.NoDedupAnnotation
+import firrtl.transforms.DontTouchAnnotation
+
+class NewAnnotationsSpec extends AnyFreeSpec with Matchers {
+
+ class MuchUsedModule extends Module {
+ val io = IO(new Bundle {
+ val in = Input(UInt(16.W))
+ val out = Output(UInt(16.W))
+ })
+ io.out := io.in +% 1.U
+ }
+
+ class UsesMuchUsedModule extends Module {
+ val io = IO(new Bundle {
+ val in = Input(UInt(16.W))
+ val out = Output(UInt(16.W))
+ })
+
+ val mod0 = Module(new MuchUsedModule)
+ val mod1 = Module(new MuchUsedModule)
+ val mod2 = Module(new MuchUsedModule)
+ val mod3 = Module(new MuchUsedModule)
+
+ mod0.io.in := io.in
+ mod1.io.in := mod0.io.out
+ mod2.io.in := mod1.io.out
+ mod3.io.in := mod2.io.out
+ io.out := mod3.io.out
+
+ // Give two annotations as single element of the seq - ensures previous API works by wrapping into a seq.
+ annotate(new ChiselMultiAnnotation { def toFirrtl = Seq(new NoDedupAnnotation(mod2.toNamed)) })
+ annotate(new ChiselMultiAnnotation { def toFirrtl = Seq(new NoDedupAnnotation(mod3.toNamed)) })
+
+ // Pass multiple annotations in the same seq - should get emitted out correctly.
+ annotate(new ChiselMultiAnnotation {
+ def toFirrtl =
+ Seq(new DontTouchAnnotation(mod1.io.in.toNamed), new DontTouchAnnotation(mod1.io.out.toNamed))
+ })
+ }
+
+ val stage = new ChiselStage
+ "Ensure all annotations continue to be passed / digested correctly with the new API" - {
+ "NoDedup and DontTouch work as expected" in {
+ val dutAnnos = stage
+ .execute(
+ Array("-X", "low", "--target-dir", "test_run_dir"),
+ Seq(ChiselGeneratorAnnotation(() => new UsesMuchUsedModule))
+ )
+
+ val dontTouchAnnos = dutAnnos.collect { case DontTouchAnnotation(target) => target.serialize }
+ val noDedupAnnos = dutAnnos.collect { case NoDedupAnnotation(target) => target.serialize }
+ require(dontTouchAnnos.size == 2, s"Exactly two DontTouch Annotations expected but got $dontTouchAnnos ")
+ require(noDedupAnnos.size == 2, s"Exactly two NoDedup Annotations expected but got $noDedupAnnos ")
+ val dontTouchAnnosCombined = dontTouchAnnos.mkString(",")
+ val noDedupAnnosCombined = noDedupAnnos.mkString(",")
+
+ noDedupAnnosCombined should include("~UsesMuchUsedModule|MuchUsedModule_2")
+ noDedupAnnosCombined should include("~UsesMuchUsedModule|MuchUsedModule_3")
+ dontTouchAnnosCombined should include("~UsesMuchUsedModule|UsesMuchUsedModule/mod1:MuchUsedModule>io_out")
+ dontTouchAnnosCombined should include("~UsesMuchUsedModule|UsesMuchUsedModule/mod1:MuchUsedModule>io_in")
+
+ }
+ }
+}