diff options
| author | Kevin Laeufer | 2021-02-17 12:16:52 -0800 |
|---|---|---|
| committer | GitHub | 2021-02-17 20:16:52 +0000 |
| commit | 5a89fca6090948d0a99c217a09c692e58a20d1df (patch) | |
| tree | 7996829e3589205607862cbbf578a4e9a9d6e623 /src/main/scala/firrtl/transforms | |
| parent | 856226416cfa2d770c7205efad5331297c2e3a32 (diff) | |
Allow Side Effecting Statement to have Names (#2057)
* firrtl: add optional statement labels for stop, printf, assert, assume and cover
* test: parsing of statement labels
* ir: ensure that name is properly retained
* SymbolTable: add support for labled statements
* test: parsing statement labels
* test: lower types name collisions with named statements
* ignore empty names
* Inline: deal with named and unnamed statements
* RemoveWires: treat stop, printf and verification statements as "others"
* test: fix InlineInstance tests
* DeadCodeEliminations: statements are now als declarations
* CheckHighForm: ensure that statement names are not used as references
* CheckSpec: throw error if statement name collides
* add pass to automatically add missing statement names
* check: make sure that two statements cannot have the same name
* stmtLabel -> stmtName
* scalafmt
* add statement names to spec
* spec: meta data -> metadata
* EnsureStatementNames: explain naming algorithm
* remove returns
* better namespace use
* ir: add CanBeReferenced trait
* ir: add newline as jack requested
Diffstat (limited to 'src/main/scala/firrtl/transforms')
3 files changed, 49 insertions, 5 deletions
diff --git a/src/main/scala/firrtl/transforms/DeadCodeElimination.scala b/src/main/scala/firrtl/transforms/DeadCodeElimination.scala index 13173fdd..1d9bfd0e 100644 --- a/src/main/scala/firrtl/transforms/DeadCodeElimination.scala +++ b/src/main/scala/firrtl/transforms/DeadCodeElimination.scala @@ -258,6 +258,11 @@ class DeadCodeElimination extends Transform with RegisteredTransform with Depend renames.delete(inst.name) EmptyStmt } + case print: Print => deleteIfNotEnabled(print, print.en) + case stop: Stop => deleteIfNotEnabled(stop, stop.en) + case formal: Verification => deleteIfNotEnabled(formal, formal.en) + // Statements are also declarations and thus this case needs to come *after* checking the + // print, stop and verification statements. case decl: IsDeclaration => val node = LogicNode(mod.name, decl.name) if (deadNodes.contains(node)) { @@ -265,10 +270,7 @@ class DeadCodeElimination extends Transform with RegisteredTransform with Depend renames.delete(decl.name) EmptyStmt } else decl - case print: Print => deleteIfNotEnabled(print, print.en) - case stop: Stop => deleteIfNotEnabled(stop, stop.en) - case formal: Verification => deleteIfNotEnabled(formal, formal.en) - case con: Connect => + case con: Connect => val node = getDeps(con.loc) match { case Seq(elt) => elt } if (deadNodes.contains(node)) EmptyStmt else con case Attach(info, exprs) => // If any exprs are dead then all are diff --git a/src/main/scala/firrtl/transforms/EnsureNamedStatements.scala b/src/main/scala/firrtl/transforms/EnsureNamedStatements.scala new file mode 100644 index 00000000..a40409f9 --- /dev/null +++ b/src/main/scala/firrtl/transforms/EnsureNamedStatements.scala @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: Apache-2.0 + +package firrtl.transforms + +import firrtl._ +import firrtl.ir._ + +/** Adds default names to print, stop and verification statements if their name is empty. */ +object EnsureNamedStatements extends Transform with DependencyAPIMigration { + override def invalidates(a: Transform) = false + + override protected def execute(state: CircuitState): CircuitState = { + val c = state.circuit.mapModule(onModule) + state.copy(circuit = c) + } + + private def onModule(m: DefModule): DefModule = m match { + case e: ExtModule => e + case mod: Module => + val namespace = Namespace(mod) + // Ensure we always start with _0 suffix + val prefixes = Seq("cover", "assert", "assume", "print", "stop") + prefixes.filterNot(namespace.contains).foreach(namespace.newName) + mod.mapStmt(onStmt(namespace)) + } + + private def onStmt(namespace: Namespace)(stmt: Statement): Statement = stmt match { + case s: Print if s.name.isEmpty => s.withName(namespace.newName("print")) + case s: Stop if s.name.isEmpty => s.withName(namespace.newName("stop")) + case s: Verification if s.name.isEmpty => + val baseName = s.op match { + case Formal.Cover => "cover" + case Formal.Assert => "assert" + case Formal.Assume => "assume" + } + s.withName(namespace.newName(baseName)) + case other => other.mapStmt(onStmt(namespace)) + } +} diff --git a/src/main/scala/firrtl/transforms/RemoveWires.scala b/src/main/scala/firrtl/transforms/RemoveWires.scala index ee03ad30..f2907db2 100644 --- a/src/main/scala/firrtl/transforms/RemoveWires.scala +++ b/src/main/scala/firrtl/transforms/RemoveWires.scala @@ -115,7 +115,10 @@ class RemoveWires extends Transform with DependencyAPIMigration { val initDep = Some(reg.init).filter(we(WRef(reg)) != we(_)) // Dependency exists IF reg doesn't init itself regInfo(we(WRef(reg))) = reg netlist(we(WRef(reg))) = (Seq(reg.clock) ++ resetDep ++ initDep, reg.info) - case decl: IsDeclaration => // Keep all declarations except for nodes and non-Analog wires + case decl: CanBeReferenced => + // Keep all declarations except for nodes and non-Analog wires and "other" statements. + // Thus this is expected to match DefInstance and DefMemory which both do not connect to + // any signals directly (instead a separate Connect is used). decls += decl case con @ Connect(cinfo, lhs, rhs) => kind(lhs) match { |
