diff options
| author | alonamid | 2018-05-11 14:50:05 -0700 |
|---|---|---|
| committer | Adam Izraelevitz | 2018-05-11 14:50:05 -0700 |
| commit | abcb22d6c34eb51749e7bc848b437a165bc5b330 (patch) | |
| tree | b63d8bc97bd6b750d36dcacc913816f095b1db1f /src | |
| parent | 77cfdbf05cafa78946a5684a0e4a530ebecd6547 (diff) | |
TopWiring Transform (#798)
* top wiring transform
* fixup comments
* TopWiring cosmetics
* move prefix into TopWiringAnnotation
* remove test function from transform file
* add ChildrenMap to InstanceGraph API
* use namespaces
* remove wiringUtils from TopWiring pass
* enable multiple output functions
* TopWiring cosmetics, tests and lowform
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/firrtl/analyses/InstanceGraph.scala | 10 | ||||
| -rw-r--r-- | src/main/scala/firrtl/transforms/TopWiring.scala | 269 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/transforms/TopWiringTest.scala | 442 |
3 files changed, 720 insertions, 1 deletions
diff --git a/src/main/scala/firrtl/analyses/InstanceGraph.scala b/src/main/scala/firrtl/analyses/InstanceGraph.scala index c6e590af..91cf8d44 100644 --- a/src/main/scala/firrtl/analyses/InstanceGraph.scala +++ b/src/main/scala/firrtl/analyses/InstanceGraph.scala @@ -18,7 +18,7 @@ import firrtl.Mappers._ */ class InstanceGraph(c: Circuit) { - private val moduleMap = c.modules.map({m => (m.name,m) }).toMap + val moduleMap = c.modules.map({m => (m.name,m) }).toMap private val instantiated = new mutable.HashSet[String] private val childInstances = new mutable.HashMap[String,mutable.Set[WDefInstance]] @@ -93,6 +93,14 @@ class InstanceGraph(c: Circuit) { def moduleOrder: Seq[DefModule] = { graph.transformNodes(_.module).linearize.map(moduleMap(_)) } + + + /** Given a circuit, returns a map from module name to children + * instance/module definitions + */ + def getChildrenInstances: scala.collection.Map[String,mutable.Set[WDefInstance]] = childInstances + + } object InstanceGraph { diff --git a/src/main/scala/firrtl/transforms/TopWiring.scala b/src/main/scala/firrtl/transforms/TopWiring.scala new file mode 100644 index 00000000..b698cda6 --- /dev/null +++ b/src/main/scala/firrtl/transforms/TopWiring.scala @@ -0,0 +1,269 @@ +// See LICENSE for license details. +package firrtl.transform +package TopWiring + +import firrtl._ +import firrtl.ir._ +import firrtl.passes.{Pass, + InferTypes, + ResolveKinds, + ResolveGenders + } +import firrtl.annotations._ +import firrtl.Mappers._ +import firrtl.graph._ + +import java.io._ +import scala.io.Source +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 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] { + 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 + * @note This *does* work for deduped modules + */ +class TopWiringTransform extends Transform { + def inputForm: CircuitForm = LowForm + def outputForm: CircuitForm = LowForm + + 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("") + } + + + /** 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 } + } + + + + /** 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 { + // 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}") + } + val name = w.name + 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) + } + + + + /** 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 { + // 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}") + } + val name = w.name + 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)]] = { + val sSourcesModNames = getSourceModNames(state) + val sSourcesNames = getSourceNames(state) + val instGraph = new firrtl.analyses.InstanceGraph(state.circuit) + val cMap = instGraph.getChildrenInstances.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) }} + + for (mod <- topSort) { + 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)}) + }.flatten + if (seqChildren.nonEmpty) { + sourcemods(mod.name) = seqChildren + } + } + + 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.InstanceGraph, + 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 + } + } + Port(NoInfo, newportname, Output, tpe) + } } + + // Add connections to Module + module match { + case m: Module => + 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("_"))) + } + } + 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 = instgraph.getChildrenInstances(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 )) + case e: ExtModule => + e.copy(ports = e.ports ++ newPorts) + } + case None => module // unchanged if no paths + } + } + + /** Run passes to fix up the circuit of making the new connections */ + private def fixupCircuit(circuit: Circuit): Circuit = { + val passes = Seq( + InferTypes, + ResolveKinds, + ResolveGenders + ) + passes.foldLeft(circuit) { case (c: Circuit, p: Pass) => p.run(c) } + } + + + /** 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) } + + // Do actual work of this transform + val sources = getSourcesMap(state) + val portnamesmap : mutable.Map[String,String] = mutable.Map() + val instgraph = new firrtl.analyses.InstanceGraph(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 newCircuit = state.circuit.copy(modules = modulesx) + val fixedCircuit = fixupCircuit(newCircuit) + val mappings = sources(state.circuit.main).zipWithIndex + //Generate output files based on the mapping. + outputTuples.map { case (dir, outputfunction) => outputfunction(dir, mappings, state) } + // fin. + state.copy(circuit = fixedCircuit) + } +} diff --git a/src/test/scala/firrtlTests/transforms/TopWiringTest.scala b/src/test/scala/firrtlTests/transforms/TopWiringTest.scala new file mode 100644 index 00000000..25d36edb --- /dev/null +++ b/src/test/scala/firrtlTests/transforms/TopWiringTest.scala @@ -0,0 +1,442 @@ +// See LICENSE for license details. + +package firrtlTests +package transform + +import org.scalatest.FlatSpec +import org.scalatest.Matchers +import org.scalatest.junit.JUnitRunner +import scala.io.Source +import java.io._ + +import firrtl._ +import firrtl.ir.{Circuit, Type, GroundType, IntWidth} +import firrtl.Parser +import firrtl.passes.PassExceptions +import firrtl.annotations.{ + Named, + CircuitName, + ModuleName, + ComponentName, + Annotation +} +import firrtl.transform.TopWiring._ + + +/** + * Tests TopWiring transformation + */ +class TopWiringTests extends LowTransformSpec { + + def topWiringDummyOutputFilesFunction(dir: String, + mapping: Seq[((ComponentName, Type, Boolean, Seq[String], String), Int)], + state: CircuitState): CircuitState = { + state + } + + def topWiringTestOutputFilesFunction(dir: String, + mapping: Seq[((ComponentName, Type, Boolean, Seq[String], String), Int)], + state: CircuitState): CircuitState = { + val testOutputFile = new PrintWriter(new File(dir, "TopWiringOutputTest.txt" )) + mapping map { + case ((_, tpe, _, path, prefix), index) => { + val portwidth = tpe match { case GroundType(IntWidth(w)) => w } + val portnum = index + val portname = prefix + path.mkString("_") + testOutputFile.append(s"new top level port $portnum : $portname, with width $portwidth \n") + } + } + testOutputFile.close() + state + } + + def transform = new TopWiringTransform + "The signal x in module C" should "be connected to Top port with topwiring prefix and outputfile in /tmp" in { + val input = + """circuit Top : + | module Top : + | inst a1 of A + | inst a2 of A_ + | module A : + | output x: UInt<1> + | x <= UInt(1) + | inst b1 of B + | module A_ : + | output x: UInt<1> + | x <= UInt(1) + | module B : + | output x: UInt<1> + | x <= UInt(1) + | inst c1 of C + | module C: + | output x: UInt<1> + | x <= UInt(0) + """.stripMargin + val topwiringannos = Seq(TopWiringAnnotation(ComponentName(s"x", + ModuleName(s"C", CircuitName(s"Top"))), + s"topwiring_"), + TopWiringOutputFilesAnnotation(s"/tmp", topWiringTestOutputFilesFunction)) + val check = + """circuit Top : + | module Top : + | output topwiring_a1_b1_c1_x: UInt<1> + | inst a1 of A + | inst a2 of A_ + | topwiring_a1_b1_c1_x <= a1.topwiring_b1_c1_x + | module A : + | output x: UInt<1> + | output topwiring_b1_c1_x: UInt<1> + | inst b1 of B + | x <= UInt(1) + | topwiring_b1_c1_x <= b1.topwiring_c1_x + | module A_ : + | output x: UInt<1> + | x <= UInt(1) + | module B : + | output x: UInt<1> + | output topwiring_c1_x: UInt<1> + | inst c1 of C + | x <= UInt(1) + | topwiring_c1_x <= c1.topwiring_x + | module C: + | output x: UInt<1> + | output topwiring_x: UInt<1> + | x <= UInt(0) + | topwiring_x <= x + """.stripMargin + execute(input, check, topwiringannos) + } + + "The signal x in module C inst c1 and c2" should + "be connected to Top port with topwiring prefix and outfile in /tmp" in { + val input = + """circuit Top : + | module Top : + | inst a1 of A + | inst a2 of A_ + | module A : + | output x: UInt<1> + | x <= UInt(1) + | inst b1 of B + | module A_ : + | output x: UInt<1> + | x <= UInt(1) + | module B : + | output x: UInt<1> + | x <= UInt(1) + | inst c1 of C + | inst c2 of C + | module C: + | output x: UInt<1> + | x <= UInt(0) + """.stripMargin + val topwiringannos = Seq(TopWiringAnnotation(ComponentName(s"x", + ModuleName(s"C", CircuitName(s"Top"))), s"topwiring_"), + TopWiringOutputFilesAnnotation(s"/tmp", topWiringTestOutputFilesFunction)) + val check = + """circuit Top : + | module Top : + | output topwiring_a1_b1_c1_x: UInt<1> + | output topwiring_a1_b1_c2_x: UInt<1> + | inst a1 of A + | inst a2 of A_ + | topwiring_a1_b1_c1_x <= a1.topwiring_b1_c1_x + | topwiring_a1_b1_c2_x <= a1.topwiring_b1_c2_x + | module A : + | output x: UInt<1> + | output topwiring_b1_c1_x: UInt<1> + | output topwiring_b1_c2_x: UInt<1> + | inst b1 of B + | x <= UInt(1) + | topwiring_b1_c1_x <= b1.topwiring_c1_x + | topwiring_b1_c2_x <= b1.topwiring_c2_x + | module A_ : + | output x: UInt<1> + | x <= UInt(1) + | module B : + | output x: UInt<1> + | output topwiring_c1_x: UInt<1> + | output topwiring_c2_x: UInt<1> + | inst c1 of C + | inst c2 of C + | x <= UInt(1) + | topwiring_c1_x <= c1.topwiring_x + | topwiring_c2_x <= c2.topwiring_x + | module C: + | output x: UInt<1> + | output topwiring_x: UInt<1> + | x <= UInt(0) + | topwiring_x <= x + """.stripMargin + execute(input, check, topwiringannos) + } + + "The signal x in module C" should + "be connected to Top port with topwiring prefix and outputfile in /tmp, after name colission" in { + val input = + """circuit Top : + | module Top : + | inst a1 of A + | inst a2 of A_ + | wire topwiring_a1_b1_c1_x : UInt<1> + | topwiring_a1_b1_c1_x <= UInt(0) + | module A : + | output x: UInt<1> + | x <= UInt(1) + | inst b1 of B + | wire topwiring_b1_c1_x : UInt<1> + | topwiring_b1_c1_x <= UInt(0) + | module A_ : + | output x: UInt<1> + | x <= UInt(1) + | module B : + | output x: UInt<1> + | x <= UInt(1) + | inst c1 of C + | module C: + | output x: UInt<1> + | x <= UInt(0) + """.stripMargin + val topwiringannos = Seq(TopWiringAnnotation(ComponentName(s"x", + ModuleName(s"C", CircuitName(s"Top"))), + s"topwiring_"), + TopWiringOutputFilesAnnotation(s"/tmp", topWiringTestOutputFilesFunction)) + val check = + """circuit Top : + | module Top : + | output topwiring_a1_b1_c1_x_0: UInt<1> + | inst a1 of A + | inst a2 of A_ + | node topwiring_a1_b1_c1_x = UInt<1>("h0") + | topwiring_a1_b1_c1_x_0 <= a1.topwiring_b1_c1_x_0 + | module A : + | output x: UInt<1> + | output topwiring_b1_c1_x_0: UInt<1> + | inst b1 of B + | node topwiring_b1_c1_x = UInt<1>("h0") + | x <= UInt(1) + | topwiring_b1_c1_x_0 <= b1.topwiring_c1_x + | module A_ : + | output x: UInt<1> + | x <= UInt(1) + | module B : + | output x: UInt<1> + | output topwiring_c1_x: UInt<1> + | inst c1 of C + | x <= UInt(1) + | topwiring_c1_x <= c1.topwiring_x + | module C: + | output x: UInt<1> + | output topwiring_x: UInt<1> + | x <= UInt(0) + | topwiring_x <= x + """.stripMargin + execute(input, check, topwiringannos) + } + + "The signal x in module C" should + "be connected to Top port with topwiring prefix and no output function" in { + val input = + """circuit Top : + | module Top : + | inst a1 of A + | inst a2 of A_ + | module A : + | output x: UInt<1> + | x <= UInt(1) + | inst b1 of B + | module A_ : + | output x: UInt<1> + | x <= UInt(1) + | module B : + | output x: UInt<1> + | x <= UInt(1) + | inst c1 of C + | module C: + | output x: UInt<1> + | x <= UInt(0) + """.stripMargin + val topwiringannos = Seq(TopWiringAnnotation(ComponentName(s"x", + ModuleName(s"C", CircuitName(s"Top"))), + s"topwiring_")) + val check = + """circuit Top : + | module Top : + | output topwiring_a1_b1_c1_x: UInt<1> + | inst a1 of A + | inst a2 of A_ + | topwiring_a1_b1_c1_x <= a1.topwiring_b1_c1_x + | module A : + | output x: UInt<1> + | output topwiring_b1_c1_x: UInt<1> + | inst b1 of B + | x <= UInt(1) + | topwiring_b1_c1_x <= b1.topwiring_c1_x + | module A_ : + | output x: UInt<1> + | x <= UInt(1) + | module B : + | output x: UInt<1> + | output topwiring_c1_x: UInt<1> + | inst c1 of C + | x <= UInt(1) + | topwiring_c1_x <= c1.topwiring_x + | module C: + | output x: UInt<1> + | output topwiring_x: UInt<1> + | x <= UInt(0) + | topwiring_x <= x + """.stripMargin + execute(input, check, topwiringannos) + } + + "The signal x in module C inst c1 and c2 and signal y in module A_" should + "be connected to Top port with topwiring prefix and outfile in /tmp" in { + val input = + """circuit Top : + | module Top : + | inst a1 of A + | inst a2 of A_ + | module A : + | output x: UInt<1> + | x <= UInt(1) + | inst b1 of B + | module A_ : + | output x: UInt<1> + | wire y : UInt<1> + | y <= UInt(1) + | x <= UInt(1) + | module B : + | output x: UInt<1> + | x <= UInt(1) + | inst c1 of C + | inst c2 of C + | module C: + | output x: UInt<1> + | x <= UInt(0) + """.stripMargin + val topwiringannos = Seq(TopWiringAnnotation(ComponentName(s"x", + ModuleName(s"C", CircuitName(s"Top"))), + s"topwiring_"), + TopWiringAnnotation(ComponentName(s"y", + ModuleName(s"A_", CircuitName(s"Top"))), + s"topwiring_"), + TopWiringOutputFilesAnnotation(s"/tmp", topWiringTestOutputFilesFunction)) + val check = + """circuit Top : + | module Top : + | output topwiring_a1_b1_c1_x: UInt<1> + | output topwiring_a1_b1_c2_x: UInt<1> + | output topwiring_a2_y: UInt<1> + | inst a1 of A + | inst a2 of A_ + | topwiring_a1_b1_c1_x <= a1.topwiring_b1_c1_x + | topwiring_a1_b1_c2_x <= a1.topwiring_b1_c2_x + | topwiring_a2_y <= a2.topwiring_y + | module A : + | output x: UInt<1> + | output topwiring_b1_c1_x: UInt<1> + | output topwiring_b1_c2_x: UInt<1> + | inst b1 of B + | x <= UInt(1) + | topwiring_b1_c1_x <= b1.topwiring_c1_x + | topwiring_b1_c2_x <= b1.topwiring_c2_x + | module A_ : + | output x: UInt<1> + | output topwiring_y: UInt<1> + | node y = UInt<1>("h1") + | x <= UInt(1) + | topwiring_y <= y + | module B : + | output x: UInt<1> + | output topwiring_c1_x: UInt<1> + | output topwiring_c2_x: UInt<1> + | inst c1 of C + | inst c2 of C + | x <= UInt(1) + | topwiring_c1_x <= c1.topwiring_x + | topwiring_c2_x <= c2.topwiring_x + | module C: + | output x: UInt<1> + | output topwiring_x: UInt<1> + | x <= UInt(0) + | topwiring_x <= x + """.stripMargin + execute(input, check, topwiringannos) + } + + "The signal x in module C inst c1 and c2 and signal y in module A_" should + "be connected to Top port with topwiring and top2wiring prefix and outfile in /tmp" in { + val input = + """circuit Top : + | module Top : + | inst a1 of A + | inst a2 of A_ + | module A : + | output x: UInt<1> + | x <= UInt(1) + | inst b1 of B + | module A_ : + | output x: UInt<1> + | wire y : UInt<1> + | y <= UInt(1) + | x <= UInt(1) + | module B : + | output x: UInt<1> + | x <= UInt(1) + | inst c1 of C + | inst c2 of C + | module C: + | output x: UInt<1> + | x <= UInt(0) + """.stripMargin + val topwiringannos = Seq(TopWiringAnnotation(ComponentName(s"x", + ModuleName(s"C", CircuitName(s"Top"))), + s"topwiring_"), + TopWiringAnnotation(ComponentName(s"y", + ModuleName(s"A_", CircuitName(s"Top"))), + s"top2wiring_"), + TopWiringOutputFilesAnnotation(s"/tmp", topWiringTestOutputFilesFunction)) + val check = + """circuit Top : + | module Top : + | output topwiring_a1_b1_c1_x: UInt<1> + | output topwiring_a1_b1_c2_x: UInt<1> + | output top2wiring_a2_y: UInt<1> + | inst a1 of A + | inst a2 of A_ + | topwiring_a1_b1_c1_x <= a1.topwiring_b1_c1_x + | topwiring_a1_b1_c2_x <= a1.topwiring_b1_c2_x + | top2wiring_a2_y <= a2.top2wiring_y + | module A : + | output x: UInt<1> + | output topwiring_b1_c1_x: UInt<1> + | output topwiring_b1_c2_x: UInt<1> + | inst b1 of B + | x <= UInt(1) + | topwiring_b1_c1_x <= b1.topwiring_c1_x + | topwiring_b1_c2_x <= b1.topwiring_c2_x + | module A_ : + | output x: UInt<1> + | output top2wiring_y: UInt<1> + | node y = UInt<1>("h1") + | x <= UInt(1) + | top2wiring_y <= y + | module B : + | output x: UInt<1> + | output topwiring_c1_x: UInt<1> + | output topwiring_c2_x: UInt<1> + | inst c1 of C + | inst c2 of C + | x <= UInt(1) + | topwiring_c1_x <= c1.topwiring_x + | topwiring_c2_x <= c2.topwiring_x + | module C: + | output x: UInt<1> + | output topwiring_x: UInt<1> + | x <= UInt(0) + | topwiring_x <= x + """.stripMargin + execute(input, check, topwiringannos) + } +} |
