diff options
| author | jackkoenig | 2016-04-15 17:30:42 -0700 |
|---|---|---|
| committer | Andrew Waterman | 2016-04-16 18:32:03 -0700 |
| commit | f8e5c736908dadafc3eda30482d13ad37b81b24d (patch) | |
| tree | 4297cbf4792df51b02d81527f60cf57d4ed8c00c /src | |
| parent | 2e15d23a872188b3e50e0cba030b993f242c6710 (diff) | |
Add Namespace for thread-safe creation of names and temporary names
Replace use of gensym with local namespaces
Delete gensym
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/firrtl/Emitter.scala | 5 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Namespace.scala | 87 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Utils.scala | 19 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/Passes.scala | 19 |
4 files changed, 102 insertions, 28 deletions
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala index cfcf472d..59aee8c4 100644 --- a/src/main/scala/firrtl/Emitter.scala +++ b/src/main/scala/firrtl/Emitter.scala @@ -256,11 +256,12 @@ class VerilogEmitter extends Emitter { mname = m.name val netlist = LinkedHashMap[WrappedExpression,Expression]() val simlist = ArrayBuffer[Stmt]() + val namespace = Namespace(m) def build_netlist (s:Stmt) : Stmt = { s match { case (s:Connect) => netlist(s.loc) = s.exp case (s:IsInvalid) => { - val n = firrtl_gensym_module(mname) + val n = namespace.newTemp val e = wref(n,tpe(s.exp)) netlist(s.exp) = e } @@ -372,7 +373,7 @@ class VerilogEmitter extends Emitter { def delay (e:Expression, n:Int, clk:Expression) : Expression = { var ex = e for (i <- 0 until n) { - val name = firrtl_gensym_module(mname) + val name = namespace.newTemp declare("reg",name,tpe(e)) val exx = WRef(name,tpe(e),ExpKind(),UNKNOWNGENDER) update(exx,ex,clk,one) diff --git a/src/main/scala/firrtl/Namespace.scala b/src/main/scala/firrtl/Namespace.scala new file mode 100644 index 00000000..01cc59fd --- /dev/null +++ b/src/main/scala/firrtl/Namespace.scala @@ -0,0 +1,87 @@ +/* +Copyright (c) 2014 - 2016 The Regents of the University of +California (Regents). All Rights Reserved. Redistribution and use in +source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + two paragraphs of disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Regents nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, +ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF +REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF +ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION +TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. +*/ + +package firrtl + +import scala.collection.mutable.HashSet +import Mappers._ + +class Namespace private { + private val tempNamePrefix: String = "GEN" + // Begin with a tempNamePrefix in namespace so we always have a number suffix + private val namespace = HashSet[String](tempNamePrefix) + private var n = 0L + + def tryName(value: String): Boolean = { + if (!namespace.contains(value)) { + namespace += value + true + } else { + false + } + } + def newName(value: String): String = { + var str = value + while (!tryName(str)) { + str = s"${value}_$n" + n += 1 + } + str + } + def newTemp: String = newName(tempNamePrefix) +} + +object Namespace { + def apply(): Namespace = new Namespace + + // Initializes a namespace from a Module + def apply(m: Module): Namespace = { + val namespace = new Namespace + + def buildNamespaceStmt(s: Stmt): Stmt = + s map buildNamespaceStmt match { + case dec: IsDeclaration => + namespace.namespace += dec.name + dec + case x => x + } + def buildNamespacePort(p: Port): Port = p match { + case dec: IsDeclaration => + namespace.namespace += dec.name + dec + case x => x + } + m.ports map buildNamespacePort + m match { + case in: InModule => buildNamespaceStmt(in.body) + case _ => // Do nothing + } + + namespace + } +} + diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala index bcf75882..36652880 100644 --- a/src/main/scala/firrtl/Utils.scala +++ b/src/main/scala/firrtl/Utils.scala @@ -61,7 +61,6 @@ object Utils { def ceil_log2(x: Int): Int = scala.math.ceil(scala.math.log(x) / scala.math.log(2)).toInt val gen_names = Map[String,Int]() val delin = "_" - val sym_hash = LinkedHashMap[String,LinkedHashMap[String,Int]]() def BoolType () = { UIntType(IntWidth(1)) } val one = UIntValue(BigInt(1),IntWidth(1)) val zero = UIntValue(BigInt(0),IntWidth(1)) @@ -74,24 +73,6 @@ object Utils { val ix = if (i < 0) ((-1 * i) - 1) else i ceil_log2(ix + 1) + 1 } - def firrtl_gensym (s:String):String = { firrtl_gensym(s,LinkedHashMap[String,Int]()) } - def firrtl_gensym (sym_hash:LinkedHashMap[String,Int]):String = { firrtl_gensym("GEN",sym_hash) } - def firrtl_gensym_module (s:String):String = { - val sh = sym_hash.getOrElse(s,LinkedHashMap[String,Int]()) - val name = firrtl_gensym("GEN",sh) - sym_hash(s) = sh - name - } - def firrtl_gensym (s:String,sym_hash:LinkedHashMap[String,Int]):String = { - if (sym_hash contains s) { - val num = sym_hash(s) + 1 - sym_hash += (s -> num) - (s + delin + num) - } else { - sym_hash += (s -> 0) - (s + delin + 0) - } - } def AND (e1:WrappedExpression,e2:WrappedExpression) : Expression = { if (e1 == e2) e1.e1 else if ((e1 == we(zero)) | (e2 == we(zero))) zero diff --git a/src/main/scala/firrtl/passes/Passes.scala b/src/main/scala/firrtl/passes/Passes.scala index 777498d6..1d7aabcd 100644 --- a/src/main/scala/firrtl/passes/Passes.scala +++ b/src/main/scala/firrtl/passes/Passes.scala @@ -36,6 +36,7 @@ import scala.io.Source // Datastructures import scala.collection.mutable.LinkedHashMap +import scala.collection.mutable.HashMap import scala.collection.mutable.ArrayBuffer import firrtl._ @@ -185,7 +186,6 @@ object ResolveKinds extends Pass { object InferTypes extends Pass { private var mname = "" def name = "Infer Types" - val width_name_hash = LinkedHashMap[String,Int]() def set_type (s:Stmt,t:Type) : Stmt = { s match { case s:DefWire => DefWire(s.info,s.name,t) @@ -195,17 +195,19 @@ object InferTypes extends Pass { case s:DefPoison => DefPoison(s.info,s.name,t) } } - def remove_unknowns_w (w:Width):Width = { + def remove_unknowns_w (w:Width)(implicit namespace: Namespace):Width = { w match { - case w:UnknownWidth => VarWidth(firrtl_gensym("w",width_name_hash)) + case w:UnknownWidth => VarWidth(namespace.newName("w")) case w => w } } - def remove_unknowns (t:Type): Type = mapr(remove_unknowns_w _,t) + def remove_unknowns (t:Type)(implicit n: Namespace): Type = mapr(remove_unknowns_w _,t) def run (c:Circuit): Circuit = { val module_types = LinkedHashMap[String,Type]() + val module_wnamespaces = HashMap[String, Namespace]() def infer_types (m:Module) : Module = { val types = LinkedHashMap[String,Type]() + implicit val wnamespace = module_wnamespaces(m.name) def infer_types_e (e:Expression) : Expression = { e map (infer_types_e) match { case e:ValidIf => ValidIf(e.cond,e.value,tpe(e.value)) @@ -269,6 +271,8 @@ object InferTypes extends Pass { val modulesx = c.modules.map { m => { mname = m.name + implicit val wnamespace = Namespace() + module_wnamespaces += (m.name -> wnamespace) val portsx = m.ports.map(p => Port(p.info,p.name,p.direction,remove_unknowns(p.tpe))) m match { case m:InModule => InModule(m.info,m.name,portsx,m.body) @@ -854,12 +858,12 @@ object RemoveAccesses extends Pass { } def run (c:Circuit): Circuit = { def remove_m (m:InModule) : InModule = { - val sh = sym_hash + val namespace = Namespace(m) mname = m.name def remove_s (s:Stmt) : Stmt = { val stmts = ArrayBuffer[Stmt]() def create_temp (e:Expression) : Expression = { - val n = firrtl_gensym_module(mname) + val n = namespace.newTemp stmts += DefWire(info(s),n,tpe(e)) WRef(n,tpe(e),kind(e),gender(e)) } @@ -1224,11 +1228,12 @@ object SplitExp extends Pass { def name = "Split Expressions" var mname = "" def split_exp (m:InModule) : InModule = { + val namespace = Namespace(m) mname = m.name val v = ArrayBuffer[Stmt]() def split_exp_s (s:Stmt) : Stmt = { def split (e:Expression) : Expression = { - val n = firrtl_gensym_module(mname) + val n = namespace.newTemp v += DefNode(info(s),n,e) WRef(n,tpe(e),kind(e),gender(e)) } |
