aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/passes/wiring/Wiring.scala
diff options
context:
space:
mode:
authorAdam Izraelevitz2016-10-27 13:00:02 -0700
committerGitHub2016-10-27 13:00:02 -0700
commit5b35f2d2722f72c81d2d6c507cd379be2a1476d8 (patch)
tree78dc2db9e12c6db52fcbf222e339a37b6ebc0b72 /src/main/scala/firrtl/passes/wiring/Wiring.scala
parent1c61a0e7102983891d99d8e9c49e331c8a2178a6 (diff)
Wiring (#348)
Added wiring pass and simple test
Diffstat (limited to 'src/main/scala/firrtl/passes/wiring/Wiring.scala')
-rw-r--r--src/main/scala/firrtl/passes/wiring/Wiring.scala162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/passes/wiring/Wiring.scala b/src/main/scala/firrtl/passes/wiring/Wiring.scala
new file mode 100644
index 00000000..d3f6f3dd
--- /dev/null
+++ b/src/main/scala/firrtl/passes/wiring/Wiring.scala
@@ -0,0 +1,162 @@
+package firrtl.passes
+package wiring
+
+import firrtl._
+import firrtl.ir._
+import firrtl.Utils._
+import firrtl.Mappers._
+import scala.collection.mutable
+import firrtl.Annotations._
+import WiringUtils._
+
+case class WiringException(msg: String) extends PassException(msg)
+
+case class WiringInfo(source: String, comp: String, sinks: Map[String, String], top: String)
+
+class Wiring(wi: WiringInfo) extends Pass {
+ def name = this.getClass.getSimpleName
+
+ /** Add pins to modules and wires a signal to them, under the scope of a specified top module
+ * Description:
+ * Adds a pin to each sink module
+ * Punches ports up from the source signal to the specified top module
+ * Punches ports down to each sink module
+ * Wires the source up and down, connecting to all sink modules
+ * Restrictions:
+ * - Can only have one source module instance under scope of the specified top
+ * - All instances of each sink module must be under the scope of the specified top
+ * Notes:
+ * - No module uniquification occurs (due to imposed restrictions)
+ */
+ def run(c: Circuit): Circuit = {
+ // Split out WiringInfo
+ val source = wi.source
+ val sinks = wi.sinks.keys.toSet
+ val compName = wi.comp
+
+ // Maps modules to children instances, i.e. (instance, module)
+ val childrenMap = getChildrenMap(c)
+
+ // Check restrictions
+ val nSources = countInstances(childrenMap, wi.top, source)
+ if(nSources != 1)
+ throw new WiringException(s"Cannot have $nSources instance of $source under ${wi.top}")
+ sinks.foreach { m =>
+ val total = countInstances(childrenMap, c.main, m)
+ val nTop = countInstances(childrenMap, c.main, wi.top)
+ val perTop = countInstances(childrenMap, wi.top, m)
+ if(total != nTop * perTop)
+ throw new WiringException(s"Module ${wi.top} does not contain all instances of $m.")
+ }
+
+ // Create valid port names for wiring that have no name conflicts
+ val portNames = c.modules.foldLeft(Map.empty[String, String]) { (map, m) =>
+ map + (m.name -> {
+ val ns = Namespace(m)
+ wi.sinks.get(m.name) match {
+ case Some(pin) => ns.newName(pin)
+ case None => ns.newName(tokenize(compName) filterNot ("[]." contains _) mkString "_")
+ }
+ })
+ }
+
+ // Create a lineage tree from children map
+ val lineages = getLineage(childrenMap, wi.top)
+
+ // Populate lineage tree with relationship information, i.e. who is source,
+ // sink, parent of source, etc.
+ val withFields = setSharedParent(wi.top)(setFields(sinks, source)(lineages))
+
+ // Populate lineage tree with what to instantiate, connect to/from, etc.
+ val withThings = setThings(portNames, compName)(withFields)
+
+ // Create a map from module name to lineage information
+ val map = pointToLineage(withThings)
+
+ // Obtain the source component type
+ val sourceComponentType = getType(c, source, compName)
+
+ // Return new circuit with correct wiring
+ val cx = c.copy(modules = c.modules map onModule(map, sourceComponentType))
+
+ // Replace inserted IR nodes with WIR nodes
+ ToWorkingIR.run(cx)
+ }
+
+ /** Return new module with correct wiring
+ */
+ private def onModule(map: Map[String, Lineage], t: Type)(m: DefModule) = {
+ map.get(m.name) match {
+ case None => m
+ case Some(l) =>
+ val stmts = mutable.ArrayBuffer[Statement]()
+ val ports = mutable.ArrayBuffer[Port]()
+ l.addPort match {
+ case None =>
+ case Some((s, dt)) => dt match {
+ case DecInput => ports += Port(NoInfo, s, Input, t)
+ case DecOutput => ports += Port(NoInfo, s, Output, t)
+ case DecWire =>
+ stmts += DefWire(NoInfo, s, t)
+ }
+ }
+ stmts ++= (l.cons map { case ((l, r)) =>
+ Connect(NoInfo, toExp(l), toExp(r))
+ })
+ def onStmt(s: Statement): Statement = Block(Seq(s) ++ stmts)
+ m match {
+ case Module(i, n, ps, s) => Module(i, n, ps ++ ports, Block(Seq(s) ++ stmts))
+ case ExtModule(i, n, ps, dn, p) => ExtModule(i, n, ps ++ ports, dn, p)
+ }
+ }
+ }
+
+ /** Returns the type of the component specified
+ */
+ private def getType(c: Circuit, module: String, comp: String) = {
+ def getRoot(e: Expression): String = e match {
+ case r: Reference => r.name
+ case i: SubIndex => getRoot(i.expr)
+ case a: SubAccess => getRoot(a.expr)
+ case f: SubField => getRoot(f.expr)
+ }
+ val eComp = toExp(comp)
+ val root = getRoot(eComp)
+ var tpe: Option[Type] = None
+ def getType(s: Statement): Statement = s match {
+ case DefRegister(_, n, t, _, _, _) if n == root =>
+ tpe = Some(t)
+ s
+ case DefWire(_, n, t) if n == root =>
+ tpe = Some(t)
+ s
+ case WDefInstance(_, n, m, t) if n == root =>
+ tpe = Some(t)
+ s
+ case DefNode(_, n, e) if n == root =>
+ tpe = Some(e.tpe)
+ s
+ case sx: DefMemory if sx.name == root =>
+ tpe = Some(MemPortUtils.memType(sx))
+ sx
+ case sx => sx map getType
+ }
+ val m = c.modules find (_.name == module) getOrElse error(s"Must have a module named $module")
+ tpe = m.ports find (_.name == root) map (_.tpe)
+ m match {
+ case Module(i, n, ps, b) => getType(b)
+ case e: ExtModule =>
+ }
+ tpe match {
+ case None => error(s"Didn't find $comp in $module!")
+ case Some(t) =>
+ def setType(e: Expression): Expression = e map setType match {
+ case ex: Reference => ex.copy(tpe = t)
+ case ex: SubField => ex.copy(tpe = field_type(ex.expr.tpe, ex.name))
+ case ex: SubIndex => ex.copy(tpe = sub_type(ex.expr.tpe))
+ case ex: SubAccess => ex.copy(tpe = sub_type(ex.expr.tpe))
+ }
+ setType(eComp).tpe
+ }
+ }
+}