diff options
| author | Adam Izraelevitz | 2016-10-27 13:00:02 -0700 |
|---|---|---|
| committer | GitHub | 2016-10-27 13:00:02 -0700 |
| commit | 5b35f2d2722f72c81d2d6c507cd379be2a1476d8 (patch) | |
| tree | 78dc2db9e12c6db52fcbf222e339a37b6ebc0b72 /src/main/scala/firrtl/passes/wiring/Wiring.scala | |
| parent | 1c61a0e7102983891d99d8e9c49e331c8a2178a6 (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.scala | 162 |
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 + } + } +} |
