diff options
| author | Jack Koenig | 2020-08-21 13:05:38 -0700 |
|---|---|---|
| committer | GitHub | 2020-08-21 13:05:38 -0700 |
| commit | 266ac5fc32865d001409194f426b4126f5d9001b (patch) | |
| tree | 882b568677ed3578023bc8987ac0b4ee601c5db3 /src | |
| parent | 73868fc6e8110282ce545c296540d3ebbafadfeb (diff) | |
Deprecate Uniquify and move its useful utilities (#1856)
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/firrtl/Namespace.scala | 17 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Utils.scala | 41 | ||||
| -rw-r--r-- | src/main/scala/firrtl/annotations/analysis/DuplicationHelper.scala | 2 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/Inline.scala | 32 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/RemoveAccesses.scala | 4 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/Uniquify.scala | 75 | ||||
| -rw-r--r-- | src/main/scala/firrtl/transforms/RemoveKeywordCollisions.scala | 3 |
7 files changed, 98 insertions, 76 deletions
diff --git a/src/main/scala/firrtl/Namespace.scala b/src/main/scala/firrtl/Namespace.scala index 196539c8..c036b5f7 100644 --- a/src/main/scala/firrtl/Namespace.scala +++ b/src/main/scala/firrtl/Namespace.scala @@ -3,6 +3,7 @@ package firrtl import scala.collection.mutable +import scala.annotation.tailrec import firrtl.ir._ class Namespace private { @@ -80,4 +81,20 @@ object Namespace { namespace.namespace ++= names namespace } + + /** Appends delim to prefix until no collisions of prefix + elts in names We don't add an _ in the collision check + * because elts could be Seq("") In this case, we're just really checking if prefix itself collides + */ + def findValidPrefix( + prefix: String, + elts: Iterable[String], + namespace: String => Boolean + ): String = { + @tailrec + def rec(p: String): String = { + val found = elts.exists(elt => namespace(p + elt)) + if (found) rec(p + "_") else p + } + rec(prefix) + } } diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala index bc285ef3..e8a00518 100644 --- a/src/main/scala/firrtl/Utils.scala +++ b/src/main/scala/firrtl/Utils.scala @@ -709,6 +709,47 @@ object Utils extends LazyLogging { } } + /** Creates a Bundle Type from a Stmt */ + def stmtToType(s: Statement): BundleType = { + // Recursive helper + def recStmtToType(s: Statement): Seq[Field] = s match { + case sx: DefWire => Seq(Field(sx.name, Default, sx.tpe)) + case sx: DefRegister => Seq(Field(sx.name, Default, sx.tpe)) + case sx: WDefInstance => Seq(Field(sx.name, Default, sx.tpe)) + case sx: DefMemory => + sx.dataType match { + case (_: UIntType | _: SIntType | _: FixedType) => + Seq(Field(sx.name, Default, passes.MemPortUtils.memType(sx))) + case tpe: BundleType => + val newFields = tpe.fields + .map(f => + DefMemory( + sx.info, + f.name, + f.tpe, + sx.depth, + sx.writeLatency, + sx.readLatency, + sx.readers, + sx.writers, + sx.readwriters + ) + ) + .flatMap(recStmtToType) + Seq(Field(sx.name, Default, BundleType(newFields))) + case tpe: VectorType => + val newFields = + (0 until tpe.size).map(i => sx.copy(name = i.toString, dataType = tpe.tpe)).flatMap(recStmtToType) + Seq(Field(sx.name, Default, BundleType(newFields))) + } + case sx: DefNode => Seq(Field(sx.name, Default, sx.value.tpe)) + case sx: Conditionally => recStmtToType(sx.conseq) ++ recStmtToType(sx.alt) + case sx: Block => (sx.stmts.map(recStmtToType)).flatten + case sx => Seq() + } + BundleType(recStmtToType(s)) + } + // format: off val v_keywords = Set( "alias", "always", "always_comb", "always_ff", "always_latch", diff --git a/src/main/scala/firrtl/annotations/analysis/DuplicationHelper.scala b/src/main/scala/firrtl/annotations/analysis/DuplicationHelper.scala index 31d13139..d4bac8ba 100644 --- a/src/main/scala/firrtl/annotations/analysis/DuplicationHelper.scala +++ b/src/main/scala/firrtl/annotations/analysis/DuplicationHelper.scala @@ -72,7 +72,7 @@ case class DuplicationHelper(existingModules: Set[String]) { val prefix = path.last._2.value + "___" val postfix = top + "_" + path.map { case (i, m) => i.value }.mkString("_") val ns = mutable.HashSet(allModules.toSeq: _*) - val finalName = firrtl.passes.Uniquify.findValidPrefix(prefix, Seq(postfix), ns) + postfix + val finalName = firrtl.Namespace.findValidPrefix(prefix, Seq(postfix), ns) + postfix allModules += finalName cachedNames((top, path)) = finalName finalName diff --git a/src/main/scala/firrtl/passes/Inline.scala b/src/main/scala/firrtl/passes/Inline.scala index 316878fb..ad9c108f 100644 --- a/src/main/scala/firrtl/passes/Inline.scala +++ b/src/main/scala/firrtl/passes/Inline.scala @@ -20,11 +20,35 @@ case class InlineAnnotation(target: Named) extends SingleTargetAnnotation[Named] def duplicate(n: Named) = InlineAnnotation(n) } +object InlineInstances { + + /** Enumerates all possible names for a given type. For example: + * {{{ + * foo : { bar : { a, b }[2], c } + * => foo, foo bar, foo bar 0, foo bar 1, foo bar 0 a, foo bar 0 b, foo bar 1 a, foo bar 1 b, foo c + * }}} + */ + private def enumerateNames(tpe: Type): Seq[Seq[String]] = tpe match { + case t: BundleType => + t.fields.flatMap { f => + (enumerateNames(f.tpe).map(f.name +: _)) ++ Seq(Seq(f.name)) + } + case t: VectorType => + ((0 until t.size).map(i => Seq(i.toString))) ++ + ((0 until t.size).flatMap { i => + enumerateNames(t.tpe).map(i.toString +: _) + }) + case _ => Seq() + } + +} + /** Inline instances as indicated by existing [[InlineAnnotation]]s * @note Only use on legal Firrtl. Specifically, the restriction of instance loops must have been checked, or else this * pass can infinitely recurse. */ class InlineInstances extends Transform with DependencyAPIMigration with RegisteredTransform { + import InlineInstances._ override def prerequisites = Forms.LowForm override def optionalPrerequisites = Seq.empty @@ -296,16 +320,16 @@ class InlineInstances extends Transform with DependencyAPIMigration with Registe cache.getOrElseUpdate(module, Block(ports :+ toInline.body).map(onStmt(module))) } - val names = "" +: Uniquify - .enumerateNames(Uniquify.stmtToType(bodyx)(NoInfo, "")) - .map(_.mkString("_")) + val names = "" +: + enumerateNames(Utils.stmtToType(bodyx)) + .map(_.mkString("_")) /** The returned prefix will not be "prefix unique". It may be the same as other existing prefixes in the namespace. * However, prepending this prefix to all inlined components is guaranteed to not conflict with this module's * namespace. To make it prefix unique, this requires expanding all names in the namespace to include their * prefixes before calling findValidPrefix. */ - val safePrefix = Uniquify.findValidPrefix(instName + inlineDelim, names, ns.cloneUnderlying - instName) + val safePrefix = Namespace.findValidPrefix(instName + inlineDelim, names, ns.cloneUnderlying - instName) val prefixMap = mutable.HashMap.empty[String, String] val inlineTarget = currentModule.instOf(instName, modName) diff --git a/src/main/scala/firrtl/passes/RemoveAccesses.scala b/src/main/scala/firrtl/passes/RemoveAccesses.scala index 015346ff..d8d32b26 100644 --- a/src/main/scala/firrtl/passes/RemoveAccesses.scala +++ b/src/main/scala/firrtl/passes/RemoveAccesses.scala @@ -25,8 +25,8 @@ object RemoveAccesses extends Pass { ) ++ firrtl.stage.Forms.Deduped override def invalidates(a: Transform): Boolean = a match { - case Uniquify | ResolveKinds | ResolveFlows => true - case _ => false + case ResolveKinds | ResolveFlows => true + case _ => false } private def AND(e1: Expression, e2: Expression) = diff --git a/src/main/scala/firrtl/passes/Uniquify.scala b/src/main/scala/firrtl/passes/Uniquify.scala index bc48ebbc..57ef11fa 100644 --- a/src/main/scala/firrtl/passes/Uniquify.scala +++ b/src/main/scala/firrtl/passes/Uniquify.scala @@ -31,6 +31,7 @@ import MemPortUtils.memType * there WOULD be collisions in references a[0] and a_0 so we still have * to rename a */ +@deprecated("Uniquify is now part of LowerTypes", "FIRRTL 1.4.0") object Uniquify extends Transform with DependencyAPIMigration { override def prerequisites = @@ -51,77 +52,17 @@ object Uniquify extends Transform with DependencyAPIMigration { /** Appends delim to prefix until no collisions of prefix + elts in names We don't add an _ in the collision check * because elts could be Seq("") In this case, we're just really checking if prefix itself collides */ - @tailrec + @deprecated("Use firrtl.Namespace.findValidPrefix", "FIRRTL 1.4.0") def findValidPrefix( prefix: String, elts: Seq[String], namespace: collection.mutable.HashSet[String] - ): String = { - elts.find(elt => namespace.contains(prefix + elt)) match { - case Some(_) => findValidPrefix(prefix + "_", elts, namespace) - case None => prefix - } - } - - /** Enumerates all possible names for a given type. For example: - * {{{ - * foo : { bar : { a, b }[2], c } - * => foo, foo bar, foo bar 0, foo bar 1, foo bar 0 a, foo bar 0 b, foo bar 1 a, foo bar 1 b, foo c - * }}} - */ - private[firrtl] def enumerateNames(tpe: Type): Seq[Seq[String]] = tpe match { - case t: BundleType => - t.fields.flatMap { f => - (enumerateNames(f.tpe).map(f.name +: _)) ++ Seq(Seq(f.name)) - } - case t: VectorType => - ((0 until t.size).map(i => Seq(i.toString))) ++ - ((0 until t.size).flatMap { i => - enumerateNames(t.tpe).map(i.toString +: _) - }) - case _ => Seq() - } + ): String = Namespace.findValidPrefix(prefix, elts, namespace) /** Creates a Bundle Type from a Stmt */ - def stmtToType(s: Statement)(implicit sinfo: Info, mname: String): BundleType = { - // Recursive helper - def recStmtToType(s: Statement): Seq[Field] = s match { - case sx: DefWire => Seq(Field(sx.name, Default, sx.tpe)) - case sx: DefRegister => Seq(Field(sx.name, Default, sx.tpe)) - case sx: WDefInstance => Seq(Field(sx.name, Default, sx.tpe)) - case sx: DefMemory => - sx.dataType match { - case (_: UIntType | _: SIntType | _: FixedType) => - Seq(Field(sx.name, Default, memType(sx))) - case tpe: BundleType => - val newFields = tpe.fields - .map(f => - DefMemory( - sx.info, - f.name, - f.tpe, - sx.depth, - sx.writeLatency, - sx.readLatency, - sx.readers, - sx.writers, - sx.readwriters - ) - ) - .flatMap(recStmtToType) - Seq(Field(sx.name, Default, BundleType(newFields))) - case tpe: VectorType => - val newFields = - (0 until tpe.size).map(i => sx.copy(name = i.toString, dataType = tpe.tpe)).flatMap(recStmtToType) - Seq(Field(sx.name, Default, BundleType(newFields))) - } - case sx: DefNode => Seq(Field(sx.name, Default, sx.value.tpe)) - case sx: Conditionally => recStmtToType(sx.conseq) ++ recStmtToType(sx.alt) - case sx: Block => (sx.stmts.map(recStmtToType)).flatten - case sx => Seq() - } - BundleType(recStmtToType(s)) - } + @deprecated("Use firrtl.Utils.stmtToType", "FIRRTL 1.4.0") + def stmtToType(s: Statement)(implicit sinfo: Info, mname: String): BundleType = + Utils.stmtToType(s) // Accepts a Type and an initial namespace // Returns new Type with uniquified names @@ -136,7 +77,7 @@ object Uniquify extends Transform with DependencyAPIMigration { case tx: BundleType => // First add everything val newFieldsAndElts = tx.fields.map { f => - val newName = findValidPrefix(f.name, Seq(""), namespace) + val newName = Namespace.findValidPrefix(f.name, Seq(""), namespace) namespace += newName Field(newName, f.flip, f.tpe) }.map { f => @@ -146,7 +87,7 @@ object Uniquify extends Transform with DependencyAPIMigration { val (tpe, eltsx) = recUniquifyNames(f.tpe, collection.mutable.HashSet()) // Need leading _ for findValidPrefix, it doesn't add _ for checks val eltsNames: Seq[String] = eltsx.map(e => "_" + e) - val prefix = findValidPrefix(f.name, eltsNames, namespace) + val prefix = Namespace.findValidPrefix(f.name, eltsNames, namespace) // We added f.name in previous map, delete if we change it if (prefix != f.name) { namespace -= f.name diff --git a/src/main/scala/firrtl/transforms/RemoveKeywordCollisions.scala b/src/main/scala/firrtl/transforms/RemoveKeywordCollisions.scala index ae3bc693..216dd7c1 100644 --- a/src/main/scala/firrtl/transforms/RemoveKeywordCollisions.scala +++ b/src/main/scala/firrtl/transforms/RemoveKeywordCollisions.scala @@ -6,7 +6,6 @@ import firrtl._ import firrtl.Utils.v_keywords import firrtl.options.Dependency -import firrtl.passes.Uniquify /** Transform that removes collisions with reserved keywords * @param keywords a set of reserved words @@ -23,7 +22,7 @@ class RemoveKeywordCollisions(keywords: Set[String]) extends ManipulateNames { */ override def manipulate = (n: String, ns: Namespace) => keywords.contains(n) match { - case true => Some(Uniquify.findValidPrefix(n + inlineDelim, Seq(""), ns.cloneUnderlying ++ keywords)) + case true => Some(Namespace.findValidPrefix(n + inlineDelim, Seq(""), ns.cloneUnderlying ++ keywords)) case false => None } |
