diff options
| author | chick | 2020-08-14 19:47:53 -0700 |
|---|---|---|
| committer | Jack Koenig | 2020-08-14 19:47:53 -0700 |
| commit | 6fc742bfaf5ee508a34189400a1a7dbffe3f1cac (patch) | |
| tree | 2ed103ee80b0fba613c88a66af854ae9952610ce /src/main/scala/firrtl/transforms/TopWiring.scala | |
| parent | b516293f703c4de86397862fee1897aded2ae140 (diff) | |
All of src/ formatted with scalafmt
Diffstat (limited to 'src/main/scala/firrtl/transforms/TopWiring.scala')
| -rw-r--r-- | src/main/scala/firrtl/transforms/TopWiring.scala | 269 |
1 files changed, 145 insertions, 124 deletions
diff --git a/src/main/scala/firrtl/transforms/TopWiring.scala b/src/main/scala/firrtl/transforms/TopWiring.scala index f5a5e2a3..b35fed22 100644 --- a/src/main/scala/firrtl/transforms/TopWiring.scala +++ b/src/main/scala/firrtl/transforms/TopWiring.scala @@ -4,7 +4,7 @@ package TopWiring import firrtl._ import firrtl.ir._ -import firrtl.passes.{InferTypes, LowerTypes, ResolveKinds, ResolveFlows, ExpandConnects} +import firrtl.passes.{ExpandConnects, InferTypes, LowerTypes, ResolveFlows, ResolveKinds} import firrtl.annotations._ import firrtl.Mappers._ import firrtl.analyses.InstanceKeyGraph @@ -13,22 +13,21 @@ import firrtl.options.Dependency import collection.mutable -/** Annotation for optional output files, and what directory to put those files in (absolute path) **/ -case class TopWiringOutputFilesAnnotation(dirName: String, - outputFunction: (String,Seq[((ComponentName, Type, Boolean, - Seq[String],String), Int)], - CircuitState) => CircuitState) extends NoTargetAnnotation +/** Annotation for optional output files, and what directory to put those files in (absolute path) * */ +case class TopWiringOutputFilesAnnotation( + dirName: String, + outputFunction: (String, Seq[((ComponentName, Type, Boolean, Seq[String], String), Int)], + CircuitState) => CircuitState) + extends NoTargetAnnotation /** Annotation for indicating component to be wired, and what prefix to add to the ports that are generated */ -case class TopWiringAnnotation(target: ComponentName, prefix: String) extends - SingleTargetAnnotation[ComponentName] { +case class TopWiringAnnotation(target: ComponentName, prefix: String) extends SingleTargetAnnotation[ComponentName] { def duplicate(n: ComponentName) = this.copy(target = n) } - /** Punch out annotated ports out to the toplevel of the circuit. - This also has an option to pass a function as a parmeter to generate - custom output files as a result of the additional ports + * This also has an option to pass a function as a parmeter to generate + * custom output files as a result of the additional ports * @note This *does* work for deduped modules */ class TopWiringTransform extends Transform with DependencyAPIMigration { @@ -39,116 +38,133 @@ class TopWiringTransform extends Transform with DependencyAPIMigration { override def invalidates(a: Transform): Boolean = a match { case InferTypes | ResolveKinds | ResolveFlows | ExpandConnects => true - case _ => false + case _ => false } type InstPath = Seq[String] /** Get the names of the targets that need to be wired */ private def getSourceNames(state: CircuitState): Map[ComponentName, String] = { - state.annotations.collect { case TopWiringAnnotation(srcname,prefix) => - (srcname -> prefix) }.toMap.withDefaultValue("") + state.annotations.collect { + case TopWiringAnnotation(srcname, prefix) => + (srcname -> prefix) + }.toMap.withDefaultValue("") } - /** Get the names of the modules which include the targets that need to be wired */ private def getSourceModNames(state: CircuitState): Seq[String] = { - state.annotations.collect { case TopWiringAnnotation(ComponentName(_,ModuleName(srcmodname, _)),_) => srcmodname } + state.annotations.collect { case TopWiringAnnotation(ComponentName(_, ModuleName(srcmodname, _)), _) => srcmodname } } - - /** Get the Type of each wire to be connected * * Find the definition of each wire in sourceList, and get the type and whether or not it's a port * Update the results in sourceMap */ - private def getSourceTypes(sourceList: Map[ComponentName, String], - sourceMap: mutable.Map[String, Seq[(ComponentName, Type, Boolean, InstPath, String)]], - currentmodule: ModuleName, state: CircuitState)(s: Statement): Statement = s match { + private def getSourceTypes( + sourceList: Map[ComponentName, String], + sourceMap: mutable.Map[String, Seq[(ComponentName, Type, Boolean, InstPath, String)]], + currentmodule: ModuleName, + state: CircuitState + )(s: Statement + ): Statement = s match { // If target wire, add name and size to to sourceMap case w: IsDeclaration => if (sourceList.keys.toSeq.contains(ComponentName(w.name, currentmodule))) { - val (isport, tpe, prefix) = w match { - case d: DefWire => (false, d.tpe, sourceList(ComponentName(w.name,currentmodule))) - case d: DefNode => (false, d.value.tpe, sourceList(ComponentName(w.name,currentmodule))) - case d: DefRegister => (false, d.tpe, sourceList(ComponentName(w.name,currentmodule))) - case d: Port => (true, d.tpe, sourceList(ComponentName(w.name,currentmodule))) - case _ => throw new Exception(s"Cannot wire this type of declaration! ${w.serialize}") - } - sourceMap.get(currentmodule.name) match { - case Some(xs:Seq[(ComponentName, Type, Boolean, InstPath, String)]) => - sourceMap.update(currentmodule.name, xs :+( - (ComponentName(w.name,currentmodule), tpe, isport ,Seq[String](w.name), prefix) )) - case None => - sourceMap(currentmodule.name) = Seq((ComponentName(w.name,currentmodule), - tpe, isport ,Seq[String](w.name), prefix)) - } + val (isport, tpe, prefix) = w match { + case d: DefWire => (false, d.tpe, sourceList(ComponentName(w.name, currentmodule))) + case d: DefNode => (false, d.value.tpe, sourceList(ComponentName(w.name, currentmodule))) + case d: DefRegister => (false, d.tpe, sourceList(ComponentName(w.name, currentmodule))) + case d: Port => (true, d.tpe, sourceList(ComponentName(w.name, currentmodule))) + case _ => throw new Exception(s"Cannot wire this type of declaration! ${w.serialize}") + } + sourceMap.get(currentmodule.name) match { + case Some(xs: Seq[(ComponentName, Type, Boolean, InstPath, String)]) => + sourceMap.update( + currentmodule.name, + xs :+ ((ComponentName(w.name, currentmodule), tpe, isport, Seq[String](w.name), prefix)) + ) + case None => + sourceMap(currentmodule.name) = Seq( + (ComponentName(w.name, currentmodule), tpe, isport, Seq[String](w.name), prefix) + ) + } } w // Return argument unchanged (ok because DefWire has no Statement children) // If not, apply to all children Statement - case _ => s map getSourceTypes(sourceList, sourceMap, currentmodule, state) + case _ => s.map(getSourceTypes(sourceList, sourceMap, currentmodule, state)) } - - /** Get the Type of each port to be connected * * Similar to getSourceTypes, but specifically for ports since they are not found in statements. * Find the definition of each port in sourceList, and get the type and whether or not it's a port * Update the results in sourceMap */ - private def getSourceTypesPorts(sourceList: Map[ComponentName, String], sourceMap: mutable.Map[String, - Seq[(ComponentName, Type, Boolean, InstPath, String)]], - currentmodule: ModuleName, state: CircuitState)(s: Port): CircuitState = s match { + private def getSourceTypesPorts( + sourceList: Map[ComponentName, String], + sourceMap: mutable.Map[String, Seq[(ComponentName, Type, Boolean, InstPath, String)]], + currentmodule: ModuleName, + state: CircuitState + )(s: Port + ): CircuitState = s match { // If target port, add name and size to to sourceMap case w: IsDeclaration => if (sourceList.keys.toSeq.contains(ComponentName(w.name, currentmodule))) { - val (isport, tpe, prefix) = w match { - case d: Port => (true, d.tpe, sourceList(ComponentName(w.name,currentmodule))) - case _ => throw new Exception(s"Cannot wire this type of declaration! ${w.serialize}") - } - sourceMap.get(currentmodule.name) match { - case Some(xs:Seq[(ComponentName, Type, Boolean, InstPath, String)]) => - sourceMap.update(currentmodule.name, xs :+( - (ComponentName(w.name,currentmodule), tpe, isport ,Seq[String](w.name), prefix) )) - case None => - sourceMap(currentmodule.name) = Seq((ComponentName(w.name,currentmodule), - tpe, isport ,Seq[String](w.name), prefix)) - } + val (isport, tpe, prefix) = w match { + case d: Port => (true, d.tpe, sourceList(ComponentName(w.name, currentmodule))) + case _ => throw new Exception(s"Cannot wire this type of declaration! ${w.serialize}") + } + sourceMap.get(currentmodule.name) match { + case Some(xs: Seq[(ComponentName, Type, Boolean, InstPath, String)]) => + sourceMap.update( + currentmodule.name, + xs :+ ((ComponentName(w.name, currentmodule), tpe, isport, Seq[String](w.name), prefix)) + ) + case None => + sourceMap(currentmodule.name) = Seq( + (ComponentName(w.name, currentmodule), tpe, isport, Seq[String](w.name), prefix) + ) + } } state // Return argument unchanged (ok because DefWire has no Statement children) // If not, apply to all children Statement case _ => state } - /** Create a map of Module name to target wires under this module * * These paths are relative but cross module (they refer down through instance hierarchy) */ - private def getSourcesMap(state: CircuitState): Map[String,Seq[(ComponentName, Type, Boolean, InstPath, String)]] = { + private def getSourcesMap(state: CircuitState): Map[String, Seq[(ComponentName, Type, Boolean, InstPath, String)]] = { val sSourcesModNames = getSourceModNames(state) val sSourcesNames = getSourceNames(state) val instGraph = firrtl.analyses.InstanceKeyGraph(state.circuit) - val cMap = instGraph.getChildInstances.map{ case (m, wdis) => - (m -> wdis.map{ case wdi => (wdi.name, wdi.module) }.toSeq) }.toMap + val cMap = instGraph.getChildInstances.map { + case (m, wdis) => + (m -> wdis.map { case wdi => (wdi.name, wdi.module) }.toSeq) + }.toMap val topSort = instGraph.moduleOrder.reverse // Map of component name to relative instance paths that result in a debug wire val sourcemods: mutable.Map[String, Seq[(ComponentName, Type, Boolean, InstPath, String)]] = mutable.Map(sSourcesModNames.map(_ -> Seq()): _*) - state.circuit.modules.foreach { m => m map - getSourceTypes(sSourcesNames, sourcemods, ModuleName(m.name, CircuitName(state.circuit.main)) , state) } - state.circuit.modules.foreach { m => m.ports.foreach { - p => Seq(p) map - getSourceTypesPorts(sSourcesNames, sourcemods, ModuleName(m.name, CircuitName(state.circuit.main)) , state) }} + state.circuit.modules.foreach { m => + m.map(getSourceTypes(sSourcesNames, sourcemods, ModuleName(m.name, CircuitName(state.circuit.main)), state)) + } + state.circuit.modules.foreach { m => + m.ports.foreach { p => + Seq(p).map( + getSourceTypesPorts(sSourcesNames, sourcemods, ModuleName(m.name, CircuitName(state.circuit.main)), state) + ) + } + } for (mod <- topSort) { - val seqChildren: Seq[(ComponentName,Type,Boolean,InstPath,String)] = cMap(mod.name).flatMap { + val seqChildren: Seq[(ComponentName, Type, Boolean, InstPath, String)] = cMap(mod.name).flatMap { case (inst, module) => - sourcemods.get(module).map( _.map { case (a,b,c,path,p) => (a,b,c, inst +: path, p)}) + sourcemods.get(module).map(_.map { case (a, b, c, path, p) => (a, b, c, inst +: path, p) }) }.flatten if (seqChildren.nonEmpty) { sourcemods(mod.name) = sourcemods.getOrElse(mod.name, Seq()) ++ seqChildren @@ -158,108 +174,113 @@ class TopWiringTransform extends Transform with DependencyAPIMigration { sourcemods.toMap } - - /** Process a given DefModule * * For Modules that contain or are in the parent hierarchy to modules containing target wires * 1. Add ports for each target wire this module is parent to * 2. Connect these ports to ports of instances that are parents to some number of target wires */ - private def onModule(sources: Map[String, Seq[(ComponentName, Type, Boolean, InstPath, String)]], - portnamesmap : mutable.Map[String,String], - instgraph : firrtl.analyses.InstanceKeyGraph, - namespacemap : Map[String, Namespace]) - (module: DefModule): DefModule = { + private def onModule( + sources: Map[String, Seq[(ComponentName, Type, Boolean, InstPath, String)]], + portnamesmap: mutable.Map[String, String], + instgraph: firrtl.analyses.InstanceKeyGraph, + namespacemap: Map[String, Namespace] + )(module: DefModule + ): DefModule = { val namespace = namespacemap(module.name) sources.get(module.name) match { case Some(p) => - val newPorts = p.map{ case (ComponentName(cname,_), tpe, _ , path, prefix) => { - val newportname = portnamesmap.get(prefix + path.mkString("_")) match { - case Some(pn) => pn - case None => { - val npn = namespace.newName(prefix + path.mkString("_")) - portnamesmap(prefix + path.mkString("_")) = npn - npn - } + val newPorts = p.map { + case (ComponentName(cname, _), tpe, _, path, prefix) => { + val newportname = portnamesmap.get(prefix + path.mkString("_")) match { + case Some(pn) => pn + case None => { + val npn = namespace.newName(prefix + path.mkString("_")) + portnamesmap(prefix + path.mkString("_")) = npn + npn } - Port(NoInfo, newportname, Output, tpe) - } } + } + Port(NoInfo, newportname, Output, tpe) + } + } // Add connections to Module val childInstances = instgraph.getChildInstances.toMap module match { case m: Module => - val connections: Seq[Connect] = p.map { case (ComponentName(cname,_), _, _ , path, prefix) => + val connections: Seq[Connect] = p.map { + case (ComponentName(cname, _), _, _, path, prefix) => val modRef = portnamesmap.get(prefix + path.mkString("_")) match { - case Some(pn) => WRef(pn) - case None => { - portnamesmap(prefix + path.mkString("_")) = namespace.newName(prefix + path.mkString("_")) - WRef(portnamesmap(prefix + path.mkString("_"))) - } + case Some(pn) => WRef(pn) + case None => { + portnamesmap(prefix + path.mkString("_")) = namespace.newName(prefix + path.mkString("_")) + WRef(portnamesmap(prefix + path.mkString("_"))) + } } path.size match { - case 1 => { - val leafRef = WRef(path.head.mkString("")) - Connect(NoInfo, modRef, leafRef) - } - case _ => { - val instportname = portnamesmap.get(prefix + path.tail.mkString("_")) match { - case Some(ipn) => ipn - case None => { - val instmod = childInstances(module.name).collectFirst { - case wdi if wdi.name == path.head => wdi.module}.get - val instnamespace = namespacemap(instmod) - portnamesmap(prefix + path.tail.mkString("_")) = - instnamespace.newName(prefix + path.tail.mkString("_")) - portnamesmap(prefix + path.tail.mkString("_")) - } - } - val instRef = WSubField(WRef(path.head), instportname) - Connect(NoInfo, modRef, instRef) + case 1 => { + val leafRef = WRef(path.head.mkString("")) + Connect(NoInfo, modRef, leafRef) + } + case _ => { + val instportname = portnamesmap.get(prefix + path.tail.mkString("_")) match { + case Some(ipn) => ipn + case None => { + val instmod = childInstances(module.name).collectFirst { + case wdi if wdi.name == path.head => wdi.module + }.get + val instnamespace = namespacemap(instmod) + portnamesmap(prefix + path.tail.mkString("_")) = + instnamespace.newName(prefix + path.tail.mkString("_")) + portnamesmap(prefix + path.tail.mkString("_")) + } + } + val instRef = WSubField(WRef(path.head), instportname) + Connect(NoInfo, modRef, instRef) } } } - m.copy(ports = m.ports ++ newPorts, body = Block(Seq(m.body) ++ connections )) + m.copy(ports = m.ports ++ newPorts, body = Block(Seq(m.body) ++ connections)) case e: ExtModule => e.copy(ports = e.ports ++ newPorts) - } + } case None => module // unchanged if no paths } } - /** Dummy function that is currently unused. Can be used to fill an outputFunction requirment in the future */ - def topWiringDummyOutputFilesFunction(dir: String, - mapping: Seq[((ComponentName, Type, Boolean, InstPath, String), Int)], - state: CircuitState): CircuitState = { - state + /** Dummy function that is currently unused. Can be used to fill an outputFunction requirment in the future */ + def topWiringDummyOutputFilesFunction( + dir: String, + mapping: Seq[((ComponentName, Type, Boolean, InstPath, String), Int)], + state: CircuitState + ): CircuitState = { + state } - def execute(state: CircuitState): CircuitState = { - val outputTuples: Seq[(String, - (String,Seq[((ComponentName, Type, Boolean, InstPath, String), Int)], - CircuitState) => CircuitState)] = state.annotations.collect { - case TopWiringOutputFilesAnnotation(td,of) => (td, of) } + val outputTuples: Seq[ + (String, (String, Seq[((ComponentName, Type, Boolean, InstPath, String), Int)], CircuitState) => CircuitState) + ] = state.annotations.collect { + case TopWiringOutputFilesAnnotation(td, of) => (td, of) + } // Do actual work of this transform val sources = getSourcesMap(state) val (nstate, nmappings) = if (sources.nonEmpty) { - val portnamesmap: mutable.Map[String,String] = mutable.Map() + val portnamesmap: mutable.Map[String, String] = mutable.Map() val instgraph = InstanceKeyGraph(state.circuit) - val namespacemap = state.circuit.modules.map{ case m => (m.name -> Namespace(m)) }.toMap - val modulesx = state.circuit.modules map onModule(sources, portnamesmap, instgraph, namespacemap) + val namespacemap = state.circuit.modules.map { case m => (m.name -> Namespace(m)) }.toMap + val modulesx = state.circuit.modules.map(onModule(sources, portnamesmap, instgraph, namespacemap)) val newCircuit = state.circuit.copy(modules = modulesx) val mappings = sources(state.circuit.main).zipWithIndex val annosx = state.annotations.filter { case _: TopWiringAnnotation => false - case _ => true + case _ => true } (state.copy(circuit = newCircuit, annotations = annosx), mappings) - } - else { (state, List.empty) } + } else { (state, List.empty) } //Generate output files based on the mapping. outputTuples.map { case (dir, outputfunction) => outputfunction(dir, nmappings, nstate) } nstate |
