aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjackkoenig2016-04-15 17:30:42 -0700
committerAndrew Waterman2016-04-16 18:32:03 -0700
commitf8e5c736908dadafc3eda30482d13ad37b81b24d (patch)
tree4297cbf4792df51b02d81527f60cf57d4ed8c00c /src
parent2e15d23a872188b3e50e0cba030b993f242c6710 (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.scala5
-rw-r--r--src/main/scala/firrtl/Namespace.scala87
-rw-r--r--src/main/scala/firrtl/Utils.scala19
-rw-r--r--src/main/scala/firrtl/passes/Passes.scala19
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))
}