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/passes | |
| 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/passes')
| -rw-r--r-- | src/main/scala/firrtl/passes/CheckHighForm.scala | 27 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/Inline.scala | 27 |
2 files changed, 38 insertions, 16 deletions
diff --git a/src/main/scala/firrtl/passes/CheckHighForm.scala b/src/main/scala/firrtl/passes/CheckHighForm.scala index e3468c4e..05635d00 100644 --- a/src/main/scala/firrtl/passes/CheckHighForm.scala +++ b/src/main/scala/firrtl/passes/CheckHighForm.scala @@ -22,6 +22,10 @@ trait CheckHighFormLike { this: Pass => moduleNS += name scopes.head += name } + // ensures that the name cannot be used again, but prevent references to this name + def addToNamespace(name: String): Unit = { + moduleNS += name + } def expandMPortVisibility(port: CDefMPort): Unit = { // Legacy CHIRRTL ports are visible in any scope where their parent memory is visible scopes.find(_.contains(port.mem)).getOrElse(scopes.head) += port.name @@ -250,10 +254,19 @@ trait CheckHighFormLike { this: Pass => e.foreach(checkHighFormE(info, mname, names)) } - def checkName(info: Info, mname: String, names: ScopeView)(name: String): Unit = { - if (!names.legalDecl(name)) - errors.append(new NotUniqueException(info, mname, name)) - names.declare(name) + def checkName(info: Info, mname: String, names: ScopeView, canBeReference: Boolean)(name: String): Unit = { + // Empty names are allowed for backwards compatibility reasons and + // indicate that the entity has essentially no name. + if (name.isEmpty) { assert(!canBeReference, "A statement with an empty name cannot be used as a reference!") } + else { + if (!names.legalDecl(name)) + errors.append(new NotUniqueException(info, mname, name)) + if (canBeReference) { + names.declare(name) + } else { + names.addToNamespace(name) + } + } } def checkInstance(info: Info, child: String, parent: String): Unit = { @@ -270,7 +283,11 @@ trait CheckHighFormLike { this: Pass => case NoInfo => minfo case x => x } - s.foreach(checkName(info, mname, names)) + val canBeReference = s match { + case _: CanBeReferenced => true + case _ => false + } + s.foreach(checkName(info, mname, names, canBeReference)) s match { case DefRegister(info, name, tpe, _, reset, init) => if (hasFlip(tpe)) diff --git a/src/main/scala/firrtl/passes/Inline.scala b/src/main/scala/firrtl/passes/Inline.scala index 4eba5d59..912acf8e 100644 --- a/src/main/scala/firrtl/passes/Inline.scala +++ b/src/main/scala/firrtl/passes/Inline.scala @@ -187,18 +187,23 @@ class InlineInstances extends Transform with DependencyAPIMigration with Registe renameMap: RenameMap )(s: Statement ): Statement = { - def onName(ofModuleOpt: Option[String])(name: String) = { - if (prefix.nonEmpty && !ns.tryName(prefix + name)) { - throw new Exception(s"Inlining failed. Inlined name '${prefix + name}' already exists") - } - ofModuleOpt match { - case None => - renameMap.record(currentModule.ref(name), nextModule.ref(prefix + name)) - case Some(ofModule) => - renameMap.record(currentModule.instOf(name, ofModule), nextModule.instOf(prefix + name, ofModule)) + def onName(ofModuleOpt: Option[String])(name: String): String = { + // Empty names are allowed for backwards compatibility reasons and + // indicate that the entity has essentially no name and thus cannot be prefixed. + if (name.isEmpty) { name } + else { + if (prefix.nonEmpty && !ns.tryName(prefix + name)) { + throw new Exception(s"Inlining failed. Inlined name '${prefix + name}' already exists") + } + ofModuleOpt match { + case None => + renameMap.record(currentModule.ref(name), nextModule.ref(prefix + name)) + case Some(ofModule) => + renameMap.record(currentModule.instOf(name, ofModule), nextModule.instOf(prefix + name, ofModule)) + } + renames(name) = prefix + name + prefix + name } - renames(name) = prefix + name - prefix + name } s match { |
