diff options
14 files changed, 199 insertions, 143 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Annotation.scala b/chiselFrontend/src/main/scala/chisel3/core/Annotation.scala new file mode 100644 index 00000000..cfee67cb --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/Annotation.scala @@ -0,0 +1,90 @@ +// See LICENSE for license details. + +package chisel3.core + +import scala.language.existentials + +import chisel3.internal.{Builder, InstanceId} +import firrtl.Transform +import firrtl.annotations.{Annotation, CircuitName, ComponentName, ModuleName} +import firrtl.transforms.DontTouchAnnotation + +/** Interface for Annotations in Chisel + * + * Defines a conversion to a corresponding FIRRTL Annotation + */ +trait ChiselAnnotation { + /** Conversion to FIRRTL Annotation */ + def toFirrtl: Annotation +} +object ChiselAnnotation { + @deprecated("Write a custom ChiselAnnotation subclass instead", "3.1") + def apply(component: InstanceId, transformClass: Class[_ <: Transform], value: String) = + ChiselLegacyAnnotation(component, transformClass, value) + @deprecated("Write a custom ChiselAnnotation subclass instead", "3.1") + def unapply(anno: ChiselAnnotation): Option[(InstanceId, Class[_ <: Transform], String)] = + anno match { + case ChiselLegacyAnnotation(c, t, v) => Some(c, t, v) + case _ => None + } +} + +/** Mixin for [[ChiselAnnotation]] that instantiates an associated FIRRTL Transform when this + * Annotation is present during a run of [[chisel3.Driver.execute]]. Automatic Transform + * instantiation is *not* supported when the Circuit and Annotations are serialized before invoking + * FIRRTL. + */ +// TODO There should be a FIRRTL API for this instead +trait RunFirrtlTransform extends ChiselAnnotation { + def transformClass: Class[_ <: Transform] +} + +// This exists for implementation reasons, we don't want people using this type directly +final case class ChiselLegacyAnnotation private[chisel3] ( + component: InstanceId, + transformClass: Class[_ <: Transform], + value: String) extends ChiselAnnotation with RunFirrtlTransform { + def toFirrtl: Annotation = Annotation(component.toNamed, transformClass, value) +} +private[chisel3] object ChiselLegacyAnnotation + +object annotate { // scalastyle:ignore object.name + def apply(anno: ChiselAnnotation): Unit = { + Builder.annotations += anno + } +} + +/** Marks that a signal should not be removed by Chisel and Firrtl optimization passes + * + * @example {{{ + * class MyModule extends Module { + * val io = IO(new Bundle { + * val a = Input(UInt(32.W)) + * val b = Output(UInt(32.W)) + * }) + * io.b := io.a + * val dead = io.a +% 1.U // normally dead would be pruned by DCE + * dontTouch(dead) // Marking it as such will preserve it + * } + * }}} + * + * @note Calling this on [[Data]] creates an annotation that Chisel emits to a separate annotations + * file. This file must be passed to FIRRTL independently of the `.fir` file. The execute methods + * in [[chisel3.Driver]] will pass the annotations to FIRRTL automatically. + */ +object dontTouch { // scalastyle:ignore object.name + /** Marks a signal to be preserved in Chisel and Firrtl + * + * @note Requires the argument to be bound to hardware + * @param data The signal to be marked + * @return Unmodified signal `data` + */ + def apply[T <: Data](data: T)(implicit compileOptions: CompileOptions): T = { + if (compileOptions.checkSynthesizable) { + requireIsHardware(data, "Data marked dontTouch") + } + annotate(new ChiselAnnotation { def toFirrtl = DontTouchAnnotation(data.toNamed) }) + data + } +} + diff --git a/chiselFrontend/src/main/scala/chisel3/core/ChiselAnnotation.scala b/chiselFrontend/src/main/scala/chisel3/core/ChiselAnnotation.scala deleted file mode 100644 index 98253ce5..00000000 --- a/chiselFrontend/src/main/scala/chisel3/core/ChiselAnnotation.scala +++ /dev/null @@ -1,69 +0,0 @@ -// See LICENSE for license details. - -package chisel3.core - -import scala.language.existentials - -import chisel3.internal.{Builder, InstanceId} -import firrtl.Transform -import firrtl.annotations.{Annotation, CircuitName, ComponentName, ModuleName} - -/** - * This is a stand-in for the firrtl.Annotations.Annotation because at the time this annotation - * is created the component cannot be resolved, into a targetString. Resolution can only - * happen after the circuit is elaborated - * @param component A chisel thingy to be annotated, could be module, wire, reg, etc. - * @param transformClass A fully-qualified class name of the transformation pass - * @param value A string value to be used by the transformation pass - */ -case class ChiselAnnotation(component: InstanceId, transformClass: Class[_ <: Transform], value: String) { - def toFirrtl: Annotation = { - val circuitName = CircuitName(component.pathName.split("""\.""").head) - component match { - case m: BaseModule => - Annotation( - ModuleName(m.name, circuitName), transformClass, value) - case _ => - Annotation( - ComponentName( - component.instanceName, ModuleName(component.parentModName, circuitName)), transformClass, value) - } - } -} - -/** Marks that a signal should not be removed by Chisel and Firrtl optimization passes - * - * @example {{{ - * class MyModule extends Module { - * val io = IO(new Bundle { - * val a = Input(UInt(32.W)) - * val b = Output(UInt(32.W)) - * }) - * io.b := io.a - * val dead = io.a +% 1.U // normally dead would be pruned by DCE - * dontTouch(dead) // Marking it as such will preserve it - * } - * }}} - * - * @note Calling this on [[Data]] creates an annotation that Chisel emits to a separate annotations - * file. This file must be passed to FIRRTL independently of the `.fir` file. The execute methods - * in [[chisel3.Driver]] will pass the annotations to FIRRTL automatically. - */ -object dontTouch { // scalastyle:ignore object.name - /** Marks a signal to be preserved in Chisel and Firrtl - * - * @note Requires the argument to be bound to hardware - * @param data The signal to be marked - * @return Unmodified signal `data` - */ - def apply[T <: Data](data: T)(implicit compileOptions: CompileOptions): T = { - if (compileOptions.checkSynthesizable) { - requireIsHardware(data, "Data marked dontTouch") - } - // TODO unify with firrtl.transforms.DontTouchAnnotation - val anno = ChiselAnnotation(data, classOf[firrtl.Transform], "DONTtouch!") - Builder.annotations += anno - data - } -} - diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 40781490..65f89cc1 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -198,7 +198,7 @@ object Flipped { * time) of bits, and must have methods to pack / unpack structured data to / * from bits. */ -abstract class Data extends HasId { +abstract class Data extends HasId with NamedComponent { // This is a bad API that punches through object boundaries. @deprecated("pending removal once all instances replaced", "chisel3") private[chisel3] def flatten: IndexedSeq[Element] = { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index c9208030..3fe78010 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -31,7 +31,7 @@ object Mem { } } -sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId { +sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId with NamedComponent { // REVIEW TODO: make accessors (static/dynamic, read/write) combinations consistent. /** Creates a read accessor into the memory with static addressing. See the diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 5ba6dbc8..5a4f6abb 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -13,6 +13,8 @@ import chisel3.internal.Builder._ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{InstTransform, SourceInfo} +import _root_.firrtl.annotations.{CircuitName, ModuleName} + object Module { /** A wrapper method that all Module instantiations must be wrapped in * (necessary to help Chisel track internal state). @@ -139,6 +141,11 @@ abstract class BaseModule extends HasId { /** Legalized name of this module. */ final val name = Builder.globalNamespace.name(desiredName) + /** Returns a FIRRTL ModuleName that references this object + * @note Should not be called until circuit elaboration is complete + */ + final def toNamed: ModuleName = ModuleName(this.name, CircuitName(this.circuitName)) + /** Called at the Module.apply(...) level after this Module has finished elaborating. * Returns a map of nodes -> names, for named nodes. * @@ -196,6 +203,7 @@ abstract class BaseModule extends HasId { // // BaseModule User API functions // + @deprecated("Use chisel3.experimental.annotate instead", "3.1") protected def annotate(annotation: ChiselAnnotation): Unit = { Builder.annotations += annotation } diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index 5c5c690e..2cb206d4 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -8,6 +8,7 @@ import scala.collection.mutable.{ArrayBuffer, HashMap} import chisel3._ import core._ import firrtl._ +import _root_.firrtl.annotations.{CircuitName, ComponentName, ModuleName, Named} private[chisel3] class Namespace(keywords: Set[String]) { private val names = collection.mutable.HashMap[String, Long]() @@ -66,6 +67,9 @@ trait InstanceId { def pathName: String def parentPathName: String def parentModName: String + /** Returns a FIRRTL Named that refers to this object in the elaborated hardware graph */ + def toNamed: Named + } private[chisel3] trait HasId extends InstanceId { @@ -129,6 +133,11 @@ private[chisel3] trait HasId extends InstanceId { case Some(p) => p.name case None => throwException(s"$instanceName doesn't have a parent") } + // TODO Should this be public? + protected def circuitName: String = _parent match { + case None => instanceName + case Some(p) => p.circuitName + } private[chisel3] def getPublicFields(rootClass: Class[_]): Seq[java.lang.reflect.Method] = { // Suggest names to nodes using runtime reflection @@ -142,6 +151,14 @@ private[chisel3] trait HasId extends InstanceId { this.getClass.getMethods.sortWith(_.getName < _.getName).filter(isPublicVal(_)) } } +/** Holds the implementation of toNamed for Data and MemBase */ +private[chisel3] trait NamedComponent extends HasId { + /** Returns a FIRRTL ComponentName that references this object + * @note Should not be called until circuit elaboration is complete + */ + final def toNamed: ComponentName = + ComponentName(this.instanceName, ModuleName(this.parentModName, CircuitName(this.circuitName))) +} private[chisel3] class DynamicContext() { val idGen = new IdGen @@ -277,7 +294,7 @@ private[chisel3] object Builder { errors.checkpoint() errors.info("Done elaborating.") - Circuit(components.last.name, components, annotations.map(_.toFirrtl)) + Circuit(components.last.name, components, annotations) } } initializeSingletons() diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala index b499c2b1..6b555a82 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -7,8 +7,6 @@ import core._ import chisel3.internal._ import chisel3.internal.sourceinfo.{SourceInfo, NoSourceInfo} -import _root_.firrtl.annotations.Annotation - case class PrimOp(val name: String) { override def toString: String = name } @@ -278,4 +276,4 @@ abstract class Component extends Arg { case class DefModule(id: UserModule, name: String, ports: Seq[Port], commands: Seq[Command]) extends Component case class DefBlackBox(id: BaseBlackBox, name: String, ports: Seq[Port], topDir: SpecifiedDirection, params: Map[String, Param]) extends Component -case class Circuit(name: String, components: Seq[Component], annotations: Seq[Annotation] = Seq.empty) +case class Circuit(name: String, components: Seq[Component], annotations: Seq[ChiselAnnotation] = Seq.empty) diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index dae921ab..25d25425 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -3,13 +3,14 @@ package chisel3 import chisel3.internal.firrtl.Emitter -import chisel3.experimental.RawModule +import chisel3.experimental.{RawModule, RunFirrtlTransform} import java.io._ import net.jcazevedo.moultingyaml._ import internal.firrtl._ import firrtl._ +import firrtl.annotations.{Annotation, JsonProtocol} import firrtl.util.{ BackendCompilationUtilities => FirrtlBackendCompilationUtilities } import _root_.firrtl.annotations.AnnotationYamlProtocol._ @@ -153,9 +154,10 @@ object Driver extends BackendCompilationUtilities { w.write(firrtlString) w.close() - val annotationFile = new File(optionsManager.getBuildFileName("anno")) + val annotationFile = new File(optionsManager.getBuildFileName("anno.json")) val af = new FileWriter(annotationFile) - af.write(circuit.annotations.toArray.toYaml.prettyPrint) + val firrtlAnnos = circuit.annotations.map(_.toFirrtl) + af.write(JsonProtocol.serialize(firrtlAnnos)) af.close() /** Find the set of transform classes associated with annotations then @@ -164,16 +166,16 @@ object Driver extends BackendCompilationUtilities { * transform being instantiated */ val transforms = circuit.annotations - .map(_.transform) - .distinct - .filterNot(_ == classOf[firrtl.Transform]) - .map { transformClass: Class[_ <: Transform] => - transformClass.newInstance() - } + .collect { case anno: RunFirrtlTransform => anno.transformClass } + .distinct + .filterNot(_ == classOf[firrtl.Transform]) + .map { transformClass: Class[_ <: Transform] => + transformClass.newInstance() + } /* This passes the firrtl source and annotations directly to firrtl */ optionsManager.firrtlOptions = optionsManager.firrtlOptions.copy( firrtlSource = Some(firrtlString), - annotations = optionsManager.firrtlOptions.annotations ++ circuit.annotations.toList, + annotations = optionsManager.firrtlOptions.annotations ++ firrtlAnnos, customTransforms = optionsManager.firrtlOptions.customTransforms ++ transforms.toList) val firrtlExecutionResult = if(chiselOptions.runFirrtlCompiler) { diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 973ad026..b3a9f54b 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -439,6 +439,9 @@ package object chisel3 { // scalastyle:ignore package.object.name type ChiselAnnotation = chisel3.core.ChiselAnnotation val ChiselAnnotation = chisel3.core.ChiselAnnotation + type RunFirrtlTransform = chisel3.core.RunFirrtlTransform + + val annotate = chisel3.core.annotate val DataMirror = chisel3.core.DataMirror val requireIsHardware = chisel3.core.requireIsHardware diff --git a/src/main/scala/chisel3/util/BlackBoxUtils.scala b/src/main/scala/chisel3/util/BlackBoxUtils.scala index fbcf4a59..fa62184a 100644 --- a/src/main/scala/chisel3/util/BlackBoxUtils.scala +++ b/src/main/scala/chisel3/util/BlackBoxUtils.scala @@ -3,14 +3,18 @@ package chisel3.util import chisel3._ -import chisel3.core.ChiselAnnotation -import firrtl.transforms.{BlackBoxInline, BlackBoxResource, BlackBoxSourceHelper} +import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform} +import firrtl.transforms.{BlackBoxResourceAnno, BlackBoxInlineAnno, BlackBoxSourceHelper} trait HasBlackBoxResource extends BlackBox { self: BlackBox => def setResource(blackBoxResource: String): Unit = { - annotate(ChiselAnnotation(self, classOf[BlackBoxSourceHelper], BlackBoxResource(blackBoxResource).serialize)) + val anno = new ChiselAnnotation with RunFirrtlTransform { + def toFirrtl = BlackBoxResourceAnno(self.toNamed, blackBoxResource) + def transformClass = classOf[BlackBoxSourceHelper] + } + chisel3.experimental.annotate(anno) } } @@ -18,7 +22,10 @@ trait HasBlackBoxInline extends BlackBox { self: BlackBox => def setInline(blackBoxName: String, blackBoxInline: String): Unit = { - annotate(ChiselAnnotation( - self, classOf[BlackBoxSourceHelper], BlackBoxInline(blackBoxName, blackBoxInline).serialize)) + val anno = new ChiselAnnotation with RunFirrtlTransform { + def toFirrtl = BlackBoxInlineAnno(self.toNamed, blackBoxName, blackBoxInline) + def transformClass = classOf[BlackBoxSourceHelper] + } + chisel3.experimental.annotate(anno) } } diff --git a/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala index f792c56f..e88d475e 100644 --- a/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala +++ b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala @@ -3,47 +3,50 @@ package chiselTests import chisel3._ -import chisel3.experimental.ChiselAnnotation +import chisel3.experimental.{annotate, ChiselAnnotation, RunFirrtlTransform} import chisel3.internal.InstanceId import chisel3.testers.BasicTester -import firrtl.{CircuitForm, CircuitState, LowForm, Transform} -import firrtl.annotations.{Annotation, ModuleName, Named} +import firrtl.{CircuitState, LowForm, Transform} +import firrtl.annotations.{ + Annotation, + SingleTargetAnnotation, + 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) +/** These annotations and the IdentityTransform class serve as an example of how to write a + * Chisel/Firrtl library */ -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 +case class IdentityAnnotation(target: Named, value: String) extends SingleTargetAnnotation[Named] { + def duplicate(n: Named) = this.copy(target = n) +} +/** ChiselAnnotation that corresponds to the above FIRRTL annotation */ +case class IdentityChiselAnnotation(target: InstanceId, value: String) + extends ChiselAnnotation with RunFirrtlTransform { + def toFirrtl = IdentityAnnotation(target.toNamed, value) + def transformClass = classOf[IdentityTransform] +} +object identify { + def apply(component: InstanceId, value: String): Unit = { + val anno = IdentityChiselAnnotation(component, value) + annotate(anno) } } class IdentityTransform extends Transform { - override def inputForm: CircuitForm = LowForm + def inputForm = LowForm + def outputForm = LowForm - override def outputForm: CircuitForm = LowForm - - override def execute(state: CircuitState): CircuitState = { - getMyAnnotations(state) match { - case Nil => state - case myAnnotations => - state + def execute(state: CircuitState): CircuitState = { + val annosx = state.annotations.map { + case IdentityAnnotation(t, value) => IdentityAnnotation(t, value + ":seen") + case other => other } + state.copy(annotations = annosx) } } -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 @@ -54,7 +57,7 @@ trait IdentityAnnotator { * This class has parameterizable widths, it will generate different hardware * @param widthC io width */ -class ModC(widthC: Int) extends Module with IdentityAnnotator { +class ModC(widthC: Int) extends Module { val io = IO(new Bundle { val in = Input(UInt(widthC.W)) val out = Output(UInt(widthC.W)) @@ -71,7 +74,7 @@ class ModC(widthC: Int) extends Module with IdentityAnnotator { * based on it's parameter * @param annoParam parameter is only used in annotation not in circuit */ -class ModA(annoParam: Int) extends Module with IdentityAnnotator { +class ModA(annoParam: Int) extends Module { val io = IO(new Bundle { val in = Input(UInt()) val out = Output(UInt()) @@ -86,7 +89,7 @@ class ModA(annoParam: Int) extends Module with IdentityAnnotator { identify(io.out, s"ModA.io.out(ignore_param)") } -class ModB(widthB: Int) extends Module with IdentityAnnotator{ +class ModB(widthB: Int) extends Module { val io = IO(new Bundle { val in = Input(UInt(widthB.W)) val out = Output(UInt(widthB.W)) @@ -98,7 +101,7 @@ class ModB(widthB: Int) extends Module with IdentityAnnotator{ identify(io.in, s"modB.io.in annotated from inside modB") } -class TopOfDiamond extends Module with IdentityAnnotator { +class TopOfDiamond extends Module { val io = IO(new Bundle { val in = Input(UInt(32.W)) val out = Output(UInt(32.W)) @@ -128,9 +131,6 @@ class DiamondTester extends BasicTester { } 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 @@ -144,16 +144,16 @@ class AnnotatingDiamondSpec extends FreeSpec with Matchers { Driver.execute(Array("--target-dir", "test_run_dir"), () => new TopOfDiamond) match { case ChiselExecutionSuccess(Some(circuit), emitted, _) => - val annos = circuit.annotations - annos.length should be (10) + val annos = circuit.annotations.map(_.toFirrtl) + annos.count(_.isInstanceOf[IdentityAnnotation]) should be (10) annos.count { - case Annotation(ModuleName(name, _), _, annoValue) => name == "ModC" && annoValue == "ModC(16)" + case IdentityAnnotation(ModuleName("ModC", _), "ModC(16)") => true case _ => false } should be (1) annos.count { - case Annotation(ModuleName(name, _), _, annoValue) => name == "ModC_1" && annoValue == "ModC(32)" + case IdentityAnnotation(ModuleName("ModC_1", _), "ModC(32)") => true case _ => false } should be (1) case _ => @@ -161,4 +161,4 @@ class AnnotatingDiamondSpec extends FreeSpec with Matchers { } } } -}
\ No newline at end of file +} diff --git a/src/test/scala/chiselTests/AnnotationNoDedup.scala b/src/test/scala/chiselTests/AnnotationNoDedup.scala index 93167f69..d93da31f 100644 --- a/src/test/scala/chiselTests/AnnotationNoDedup.scala +++ b/src/test/scala/chiselTests/AnnotationNoDedup.scala @@ -3,16 +3,14 @@ package chiselTests import chisel3._ -import chisel3.experimental.ChiselAnnotation +import chisel3.experimental.{annotate, ChiselAnnotation} import firrtl.FirrtlExecutionSuccess -import firrtl.transforms.DedupModules +import firrtl.transforms.NoDedupAnnotation import org.scalatest.{FreeSpec, Matchers} -trait NoDedupAnnotator { - self: Module => - - def doNotDedup(module: Module): Unit = { - annotate(ChiselAnnotation(module, classOf[DedupModules], "nodedup!")) +object doNotDedup { + def apply(module: Module): Unit = { + annotate(new ChiselAnnotation { def toFirrtl = NoDedupAnnotation(module.toNamed) }) } } @@ -24,7 +22,7 @@ class MuchUsedModule extends Module { io.out := io.in +% 1.U } -class UsesMuchUsedModule(addAnnos: Boolean) extends Module with NoDedupAnnotator{ +class UsesMuchUsedModule(addAnnos: Boolean) extends Module { val io = IO(new Bundle { val in = Input(UInt(16.W)) val out = Output(UInt(16.W)) @@ -49,7 +47,7 @@ class UsesMuchUsedModule(addAnnos: Boolean) extends Module with NoDedupAnnotator class AnnotationNoDedup extends FreeSpec with Matchers { "Firrtl provides transform that reduces identical modules to a single instance" - { - "Annotations can be added which will defeat this deduplication for specific modules instances" in { + "Annotations can be added which will prevent this deduplication for specific modules instances" in { Driver.execute(Array("-X", "low", "--target-dir", "test_run_dir"), () => new UsesMuchUsedModule(addAnnos = true)) match { case ChiselExecutionSuccess(_, _, Some(firrtlResult: FirrtlExecutionSuccess)) => val lowFirrtl = firrtlResult.emitted @@ -62,7 +60,7 @@ class AnnotationNoDedup extends FreeSpec with Matchers { case _ => } } - "Turning off these nnotations dedup all the occurrences" in { + "Turning off these annotations dedups all the occurrences" in { Driver.execute(Array("-X", "low", "--target-dir", "test_run_dir"), () => new UsesMuchUsedModule(addAnnos = false)) match { case ChiselExecutionSuccess(_, _, Some(firrtlResult: FirrtlExecutionSuccess)) => val lowFirrtl = firrtlResult.emitted diff --git a/src/test/scala/chiselTests/ChiselSpec.scala b/src/test/scala/chiselTests/ChiselSpec.scala index 14672d68..661cf00e 100644 --- a/src/test/scala/chiselTests/ChiselSpec.scala +++ b/src/test/scala/chiselTests/ChiselSpec.scala @@ -16,9 +16,10 @@ import firrtl.{ FirrtlExecutionSuccess, FirrtlExecutionFailure } +import firrtl.util.BackendCompilationUtilities /** Common utility functions for Chisel unit tests. */ -trait ChiselRunners extends Assertions { +trait ChiselRunners extends Assertions with BackendCompilationUtilities { def runTester(t: => BasicTester, additionalVResources: Seq[String] = Seq()): Boolean = { TesterDriver.execute(() => t, additionalVResources) } @@ -43,9 +44,10 @@ trait ChiselRunners extends Assertions { * @return the Verilog code as a string. */ def compile(t: => RawModule): String = { + val testDir = createTestDirectory(this.getClass.getSimpleName) val manager = new ExecutionOptionsManager("compile") with HasFirrtlOptions with HasChiselExecutionOptions { - commonOptions = CommonOptions(targetDirName = "test_run_dir") + commonOptions = CommonOptions(targetDirName = testDir.toString) } Driver.execute(manager, () => t) match { diff --git a/src/test/scala/chiselTests/DriverSpec.scala b/src/test/scala/chiselTests/DriverSpec.scala index 796668e3..612bdef2 100644 --- a/src/test/scala/chiselTests/DriverSpec.scala +++ b/src/test/scala/chiselTests/DriverSpec.scala @@ -25,7 +25,7 @@ class DriverSpec extends FreeSpec with Matchers { val targetDir = "." Driver.execute(Array.empty[String], () => new DummyModule) match { case ChiselExecutionSuccess(_, _, Some(_: FirrtlExecutionSuccess)) => - val exts = List("anno", "fir", "v") + val exts = List("anno.json", "fir", "v") for (ext <- exts) { val dummyOutput = new File(targetDir, "DummyModule" + "." + ext) dummyOutput.exists() should be(true) @@ -41,7 +41,7 @@ class DriverSpec extends FreeSpec with Matchers { val targetDir = "local-build" Driver.execute(Array("-tn", "dm", "-td", targetDir), () => new DummyModule) match { case ChiselExecutionSuccess(_, _, Some(_: FirrtlExecutionSuccess)) => - val exts = List("anno", "fir", "v") + val exts = List("anno.json", "fir", "v") for (ext <- exts) { val dummyOutput = new File(targetDir, "dm" + "." + ext) dummyOutput.exists() should be(true) |
