From 117054bb4cdc3c5abf34ba5c99f61bcd590871f0 Mon Sep 17 00:00:00 2001 From: Kevin Laeufer Date: Tue, 15 Jun 2021 16:36:50 -0700 Subject: make PresetRegAnnotation public (#2254) * make PresetRegAnnotation public this annotation is useful outside the firrtl compiler: - to implement a pass that creates registers which need to be initialized at the beginning of simulation (e.g., for formal verification) - to support preset registers in treadle * add PresetRegAnnotation test and deal with annotation correctly in RemoveReset pass--- .../firrtlTests/PresetRegAnnotationSpec.scala | 81 ++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/test/scala/firrtlTests/PresetRegAnnotationSpec.scala (limited to 'src/test') diff --git a/src/test/scala/firrtlTests/PresetRegAnnotationSpec.scala b/src/test/scala/firrtlTests/PresetRegAnnotationSpec.scala new file mode 100644 index 00000000..5cd0f764 --- /dev/null +++ b/src/test/scala/firrtlTests/PresetRegAnnotationSpec.scala @@ -0,0 +1,81 @@ +package firrtlTests + +import firrtl._ +import firrtl.annotations.{CircuitTarget, PresetRegAnnotation} +import firrtl.options.Dependency +import firrtl.testutils.LeanTransformSpec +import firrtl.transforms.PropagatePresetAnnotations +import logger.{LogLevel, LogLevelAnnotation, Logger} + +import scala.collection.mutable + +/** Tests the use of the [[firrtl.annotations.PresetRegAnnotation]] + * from a pass that needs to create a register with an initial value. + */ +class PresetRegAnnotationSpec + extends LeanTransformSpec(Seq(Dependency(MakePresetRegs), Dependency[SystemVerilogEmitter])) { + behavior.of("PresetRegAnnotation") + + val src = + """circuit test: + | module test: + | input clock : Clock + | output out : UInt<8> + | + | reg r : UInt<8>, clock with : + | reset => (UInt(0), UInt<8>("h7b")) + | out <= r + |""".stripMargin + + val ll = LogLevel.Error + + it should "allow passes to mark registers to be initialized" in { + val result = Logger.makeScope(Seq(LogLevelAnnotation(ll))) { compile(src) } + val verilog = result.getEmittedCircuit.value + val lines = verilog.split('\n').map(_.trim).toSet + + // the register should be assigned its initial value + assert(lines.contains("reg [7:0] r = 8'h7b;")) + assert(lines.contains("assign out = r;")) + + // no asynchronous reset should be emitted + assert(!lines.contains("if (reset) begin")) + assert(!lines.contains("always @(posedge clock or posedge reset) begin")) + } +} + +/** Adds preset reg annotations for all registers that have: + * 1. reset = false + * 2. init = a literal + */ +private object MakePresetRegs extends Transform with DependencyAPIMigration { + // run on lowered firrtl + override def prerequisites = Seq(Dependency(firrtl.passes.ExpandWhens), Dependency(firrtl.passes.LowerTypes)) + override def invalidates(a: Transform) = false + // since we generate PresetRegAnnotations, we need to run after preset propagation + override def optionalPrerequisites = Seq(Dependency[PropagatePresetAnnotations]) + // we want to run before the actual Verilog is emitted + // we want to look at the reset value, which may be removed by the RemoveReset transform. + override def optionalPrerequisiteOf = Seq(Dependency[SystemVerilogEmitter], Dependency(firrtl.transforms.RemoveReset)) + + override def execute(state: CircuitState): CircuitState = { + val c = CircuitTarget(state.circuit.main) + val newAnnos = state.circuit.modules.flatMap(onModule(c, _)) + state.copy(annotations = newAnnos ++: state.annotations) + } + + private def onModule(c: CircuitTarget, m: ir.DefModule): List[PresetRegAnnotation] = m match { + case mod: ir.Module => + val regs = mutable.ListBuffer[String]() + mod.foreachStmt(onStmt(_, regs)) + val m = c.module(mod.name) + regs.map(r => PresetRegAnnotation(m.ref(r))).toList + case _ => List() + } + + private def onStmt(s: ir.Statement, regs: mutable.ListBuffer[String]): Unit = s match { + case ir.DefRegister(_, name, _, _, reset, init) if reset == Utils.False() && Utils.isLiteral(init) => + regs.append(name) + case other => other.foreachStmt(onStmt(_, regs)) + } +} -- cgit v1.2.3