diff options
| author | jackkoenig | 2015-12-07 01:11:10 -0800 |
|---|---|---|
| committer | jackkoenig | 2015-12-07 01:11:10 -0800 |
| commit | d7642f786882a0b4cb5d7c62d28b3711327d82e7 (patch) | |
| tree | 7380499fe4757991c7523d174911299240f7ca5f /src | |
| parent | c5cac5227cd164b17f2a6f02227a71dc89f8cde4 (diff) | |
The transformation works! Kind of, it works fine when everything is alwasy ready, has some weird issues when they're not, but also kind of works in that the hardware verifier still reports the right answer, it seems to go to half duty cycle and then do every token twice
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/firrtl/Driver.scala | 6 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Utils.scala | 8 | ||||
| -rw-r--r-- | src/main/scala/midas/Fame.scala | 220 | ||||
| -rw-r--r-- | src/main/scala/midas/Utils.scala | 303 |
4 files changed, 362 insertions, 175 deletions
diff --git a/src/main/scala/firrtl/Driver.scala b/src/main/scala/firrtl/Driver.scala index ce8d2b1d..e8ad8d56 100644 --- a/src/main/scala/firrtl/Driver.scala +++ b/src/main/scala/firrtl/Driver.scala @@ -83,9 +83,9 @@ object Driver writer.write(ast3.serialize()) writer.close() - //val postCmd = Seq("firrtl-stanza", "-i", temp2, "-o", output, "-b", "firrtl") ++ stanzaPostTransform.flatMap(Seq("-x", _)) - //println(postCmd.mkString(" ")) - //postCmd.! + val postCmd = Seq("firrtl-stanza", "-i", temp2, "-o", output, "-X", "verilog") + println(postCmd.mkString(" ")) + postCmd.! } private def verilog(input: String, output: String)(implicit logger: Logger) diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala index 73799765..d767f027 100644 --- a/src/main/scala/firrtl/Utils.scala +++ b/src/main/scala/firrtl/Utils.scala @@ -196,6 +196,13 @@ object Utils { } s + debug(dir) } + def flip(): FieldDir = { + dir match { + case Reverse => Default + case Default => Reverse + } + } + def toPortDir(): PortDir = { dir match { case Default => Output @@ -207,6 +214,7 @@ object Utils { implicit class FieldUtils(field: Field) { def serialize(implicit flags: FlagMap = FlagMap): String = s"${field.dir.serialize} ${field.name} : ${field.tpe.serialize}" + debug(field) + def flip(): Field = Field(field.name, field.dir.flip, field.tpe) def getType(): Type = field.tpe def toPort(): Port = Port(NoInfo, field.name, field.dir.toPortDir, field.tpe) diff --git a/src/main/scala/midas/Fame.scala b/src/main/scala/midas/Fame.scala index f53ab56d..49cdb613 100644 --- a/src/main/scala/midas/Fame.scala +++ b/src/main/scala/midas/Fame.scala @@ -30,16 +30,22 @@ import firrtl.Utils._ * - All and only instances in NewTop are sim tagged * - No black boxes in design * 2. Simulation Transformation - * a. Iteratively transform each inst in Top (see example firrtl in dram_midas top dir) + * a. Perform Decoupled Transformation on every RTL Module + * i. Add targetFire signal input + * ii. Find all DefInst nodes and propogate targetFire to the instances + * iii. Find all registers and add when statement connecting regIn to regOut when !targetFire + * b. Iteratively transform each inst in Top (see example firrtl in dram_midas top dir) * i. Create wrapper class * ii. Create input and output (ready, valid) pairs for every other sim module this module connects to * * Note that TopIO counts as a "sim module" - * iii. Create simFire as AND of inputs.valid and outputs.ready - * iv. Create [target] simClock as AND of simFire and [host] clock + * iii. Create targetFire as AND of inputs.valid and outputs.ready + * iv. Connect targetFire to targetFire input of target rtl inst * v. Connect target IO to wrapper IO, except connect target clock to simClock * * TODO + * - Change from clock gating to reg enable, dont' forget to change sequential memory read enable * - Implement Flatten RTL + * - Refactor important strings/naming to API (eg. "topIO" needs to be a constant defined somewhere or something) * - Check that circuit is in LowFIRRTL? * * NOTES @@ -61,49 +67,35 @@ import firrtl.Utils._ */ object Fame1 { - private def getDefInsts(s: Stmt): Seq[DefInst] = { - s match { - case i: DefInst => Seq(i) - case b: Block => b.stmts.map(getDefInsts).flatten - case _ => Seq() - } - } - private def getDefInsts(m: Module): Seq[DefInst] = getDefInsts(m.stmt) + // Constants, common nodes, and common types used throughout + private type PortMap = Map[String, Seq[String]] + private val PortMap = Map[String, Seq[String]]() + private type ConnMap = Map[String, PortMap] + private val ConnMap = Map[String, PortMap]() + private type SimQMap = Map[(String, String), Module] + private val SimQMap = Map[(String, String), Module]() - private def getDefInstRef(inst: DefInst): Ref = { - inst.module match { - case ref: Ref => ref - case _ => throw new Exception("Invalid module expression for DefInst: " + inst.serialize) - } - } + private val hostReady = Field("hostReady", Reverse, UIntType(IntWidth(1))) + private val hostValid = Field("hostValid", Default, UIntType(IntWidth(1))) + private val hostClock = Port(NoInfo, "hostClock", Input, ClockType) + private val hostReset = Port(NoInfo, "hostReset", Input, UIntType(IntWidth(1))) + private val targetFire = Port(NoInfo, "targetFire", Input, UIntType(IntWidth(1))) - // DefInsts have an Expression for the module, this expression should be a reference this - // reference has a tpe that should be a bundle representing the IO of that module class - private def getDefInstType(inst: DefInst): BundleType = { - val ref = getDefInstRef(inst) - ref.tpe match { - case b: BundleType => b - case _ => throw new Exception("Invalid reference type for DefInst: " + inst.serialize) - } - } + private def wrapName(name: String): String = s"SimWrap_${name}" + private def unwrapName(name: String): String = name.stripPrefix("SimWrap_") + private def queueName(src: String, dst: String): String = s"SimQueue_${src}_${dst}" + private def instName(name: String): String = s"inst_${name}" + private def unInstName(name: String): String = name.stripPrefix("inst_") - private def getModuleFromDefInst(nameToModule: Map[String, Module], inst: DefInst): Module = { - val instModule = getDefInstRef(inst) - if(!nameToModule.contains(instModule.name)) - throw new Exception(s"Module ${instModule.name} not found in circuit!") - else - nameToModule(instModule.name) + private def genHostDecoupled(fields: Seq[Field]): BundleType = { + BundleType(Seq(hostReady, hostValid) :+ Field("hostBits", Default, BundleType(fields))) } - // ***** findPortConn ***** + // ********** findPortConn ********** // This takes lowFIRRTL top module that follows invariants described above and returns a connection Map // of instanceName -> (instanctPorts -> portEndpoint) // It honestly feels kind of brittle given it assumes there will be no intermediate nodes or anything in // the way of direct connections between IO of module instances - private type PortMap = Map[String, Seq[String]] - private val PortMap = Map[String, Seq[String]]() - private type ConnMap = Map[String, PortMap] - private val ConnMap = Map[String, PortMap]() private def processConnectExp(exp: Exp): (String, String) = { val unsupportedExp = new Exception("Unsupported Exp for finding port connections: " + exp) exp match { @@ -143,27 +135,33 @@ object Fame1 { findPortConn(initConnMap, topStmts) } - // ***** Name Translation functions to help make naming consistent and easy to change ***** - private def wrapName(name: String): String = s"SimWrap_${name}" - private def unwrapName(name: String): String = name.stripPrefix("SimWrap_") - private def queueName(src: String, dst: String): String = s"SimQueue_${src}_${dst}" - private def instName(name: String): String = s"inst_${name}" - private def unInstName(name: String): String = name.stripPrefix("inst_") - - // ***** genWrapperModule ***** - // Generates FAME-1 Decoupled wrappers for simulation module instances - private val hostReady = Field("hostReady", Reverse, UIntType(IntWidth(1))) - private val hostValid = Field("hostValid", Default, UIntType(IntWidth(1))) - private val hostClock = Port(NoInfo, "hostClock", Input, ClockType) - private val hostReset = Port(NoInfo, "hostReset", Input, UIntType(IntWidth(1))) + // Removes clocks from a portmap + private def scrubClocks(ports: Seq[Port], portMap: PortMap): PortMap = { + val clocks = ports filter (_.tpe == ClockType) map (_.name) + portMap filter { case (portName, _) => !clocks.contains(portName) } + } - private def genHostDecoupled(fields: Seq[Field]): BundleType = { - BundleType(Seq(hostReady, hostValid) :+ Field("hostBits", Default, BundleType(fields))) + // ********** transformRTL ********** + // Takes an RTL module and give it targetFire input, propogates targetFire to all child instances, + // puts targetFire on regEnable for all registers + // TODO + // - Add smem support + private def transformRTL(m: Module): Module = { + val ports = m.ports :+ targetFire + val instProp = getDefInsts(m) map { inst => + Connect(NoInfo, buildExp(Seq(inst.name, targetFire.name)), buildExp(targetFire.name)) + } + val regEn = getDefRegs(m) map { reg => + When(NoInfo, DoPrimop(Not, Seq(buildExp(targetFire.name)), Seq(), UnknownType), + Connect(NoInfo, buildExp(reg.name), buildExp(reg.name)), EmptyStmt) + } + Module(m.info, m.name, ports, Block(m.stmt +: (instProp ++ regEn))) } + // ********** genWrapperModule ********** + // Generates FAME-1 Decoupled wrappers for simulation module instances private def genWrapperModule(inst: DefInst, portMap: PortMap): Module = { - println(s"Wrapping ${inst.name}") - println(portMap) + val instIO = getDefInstType(inst) val nameToField = (instIO.fields map (f => f.name -> f)).toMap @@ -181,7 +179,7 @@ object Fame1 { else Seq(Field("hostIn", Reverse, genHostDecoupled(inputSet))) ) ++ (if (outputSet.isEmpty) Seq() - else Seq(Field("hostOut", Default, genHostDecoupled(inputSet))) + else Seq(Field("hostOut", Default, genHostDecoupled(outputSet))) ) )) } @@ -198,11 +196,8 @@ object Fame1 { } }).flatten - val targetFire = DefNode(inst.info, "targetFire", genPrimopReduce(And, targetFireInputs)) - // targetClock is the simple AND of targetFire and the hostClock so that the rtl module only executes when data - // is available and outputs are ready - val targetClock = DefNode(inst.info, "targetClock", DoPrimop(And, - Seq(buildExp(targetFire.name), buildExp(hostClock.name)), Seq(), UnknownType)) + val defTargetFire = DefNode(inst.info, targetFire.name, genPrimopReduce(And, targetFireInputs)) + val connectTargetFire = Connect(NoInfo, buildExp(Seq(inst.name, targetFire.name)), buildExp(targetFire.name)) // As a simple RTL module, we're always ready val inputsReady = (connPorts map { port => @@ -224,37 +219,33 @@ object Fame1 { val instIOConnect = (connectedInstIOFields map { field => field.tpe match { case ClockType => Seq(Connect(inst.info, buildExp(Seq(inst.name, field.name)), - Ref(targetClock.name, ClockType))) + Ref(hostClock.name, ClockType))) case _ => field.dir match { case Default => portMap(field.name) map { endpoint => - Connect(inst.info, buildExp(Seq(endpoint, "hostOut", field.name)), + Connect(inst.info, buildExp(Seq(endpoint, "hostOut", "hostBits", field.name)), buildExp(Seq(inst.name, field.name))) } case Reverse => { if (portMap(field.name).length > 1) throw new Exception("It is illegal to have more than 1 connection to a single input" + field) Seq(Connect(inst.info, buildExp(Seq(inst.name, field.name)), - buildExp(Seq(portMap(field.name).head, "hostIn", field.name)))) + buildExp(Seq(portMap(field.name).head, "hostIn", "hostBits", field.name)))) } } } }).flatten - //val stmts = Block(Seq(simFire, simClock, inst) ++ inputsReady ++ outputsValid ++ instIOConnect) - val stmts = Block(Seq(targetFire, targetClock) ++ inputsReady ++ outputsValid ++ Seq(inst) ++ instIOConnect) + val stmts = Block(Seq(defTargetFire) ++ inputsReady ++ outputsValid ++ Seq(inst) ++ + Seq(connectTargetFire) ++ instIOConnect) Module(inst.info, wrapName(inst.name), ports, stmts) } - - - // ***** generateSimQueues ***** + // ********** generateSimQueues ********** // Takes Seq of SimWrapper modules // Returns Map of (src, dest) -> SimQueue // To prevent duplicates, instead of creating a map with (src, dest) as the key, we could instead // only one direction of the queue for each simport of each module. The only problem with this is // it won't create queues for TopIO since that isn't a real module - private type SimQMap = Map[(String, String), Module] - private val SimQMap = Map[(String, String), Module]() private def generateSimQueues(wrappers: Seq[Module]): SimQMap = { def rec(wrappers: Seq[Module], map: SimQMap): SimQMap = { if (wrappers.isEmpty) map @@ -274,58 +265,101 @@ object Fame1 { rec(wrappers, SimQMap) } - // ***** generateSimTop ***** + // ********** generateSimTop ********** // Creates the Simulation Top module where all sim modules and sim queues are instantiated and connected - private def generateSimTop(wrappers: Seq[Module], simQueues: SimQMap, rtlTop: Module): Module = { + private def transformTopIO(ports: Seq[Port]): Seq[Port] = { + val noClock = ports filter (_.tpe != ClockType) + val inputs = noClock filter (_.dir == Input) map (_.toField.flip) // Flip because wrapping port is input + val outputs = noClock filter (_.dir == Output) map (_.toField) + + Seq(Port(NoInfo, "io", Output, BundleType(Seq(Field("hostIn", Reverse, genHostDecoupled(inputs)), + Field("hostOut", Default, genHostDecoupled(outputs)))))) + } + private def generateSimTop(wrappers: Seq[Module], simQueues: SimQMap, portMap: PortMap, rtlTop: Module): Module = { val insts = (wrappers map { m => DefInst(NoInfo, instName(m.name), buildExp(m.name)) }) ++ (simQueues.values map { m => DefInst(NoInfo, instName(m.name), buildExp(m.name)) }) val connectClocks = (wrappers ++ simQueues.values) map { m => - Connect(NoInfo, buildExp(Seq(m.name, hostClock.name)), buildExp(hostClock.name)) + Connect(NoInfo, buildExp(Seq(instName(m.name), hostClock.name)), buildExp(hostClock.name)) } val connectResets = (wrappers ++ simQueues.values) map { m => - Connect(NoInfo, buildExp(Seq(m.name, hostReset.name)), buildExp(hostReset.name)) - } - val connectQueues = simQueues map { case (key, queue) => - (key._1, key._2) match { - //case (src, "topIO") => EmptyStmt - //case ("topIO", dst) => EmptyStmt - case (src, dst) => Block(Seq(BulkConnect(NoInfo, buildExp(Seq(queue.name, "io", "enq")), - buildExp(Seq(instName(wrapName(src)), dst, "hostOut"))), - BulkConnect(NoInfo, buildExp(Seq(queue.name, "io", "deq")), - buildExp(Seq(instName(wrapName(dst)), src, "hostIn"))))) - } + Connect(NoInfo, buildExp(Seq(instName(m.name), hostReset.name)), buildExp(hostReset.name)) } - val stmts = Block(insts ++ connectClocks ++ connectResets ++ connectQueues) - val ports = Seq(hostClock, hostReset) ++ rtlTop.ports + // Connect queues to simulation modules (excludes IO) + val connectQueues = (simQueues map { case ((src, dst), queue) => + (if (src == "topIO") Seq() + else Seq(BulkConnect(NoInfo, buildExp(Seq(instName(queue.name), "io", "enq")), + buildExp(Seq(instName(wrapName(src)), dst, "hostOut")))) + ) ++ + (if (dst == "topIO") Seq() + else Seq(BulkConnect(NoInfo, buildExp(Seq(instName(wrapName(dst)), src, "hostIn")), + buildExp(Seq(instName(queue.name), "io", "deq")))) + ) + }).flatten + // Connect IO queues, Src means input, Dst means output (ie. the outside word is the Src or Dst) + val ioSrcQueues = (simQueues filter {case ((src, dst), _) => src == "topIO"} map {case (_, queue) => queue}).toSeq + val ioDstQueues = (simQueues filter {case ((src, dst), _) => dst == "topIO"} map {case (_, queue) => queue}).toSeq + val ioSrcSignals = rtlTop.ports filter (sig => sig.tpe != ClockType && sig.dir == Input) map (_.name) + val ioDstSignals = rtlTop.ports filter (sig => sig.tpe != ClockType && sig.dir == Output) map (_.name) + + val ioSrcQueueConnect = if (ioSrcQueues.length > 0) { + val readySignals = ioSrcQueues map (queue => buildExp(Seq(instName(queue.name), "io", "enq", hostReady.name))) + val validSignals = ioSrcQueues map (queue => buildExp(Seq(instName(queue.name), "io", "enq", hostValid.name))) + + (ioSrcSignals map { sig => + (portMap(sig) map { dst => + Connect(NoInfo, buildExp(Seq(instName(queueName("topIO", dst)), "io", "enq", "hostBits", sig)), + buildExp(Seq("io", "hostIn", "hostBits", sig))) + }) + }).flatten ++ + (validSignals map (sig => Connect(NoInfo, buildExp(sig), buildExp(Seq("io", "hostIn", hostValid.name))))) :+ + Connect(NoInfo, buildExp(Seq("io", "hostIn", hostReady.name)), genPrimopReduce(And, readySignals)) + } else Seq(EmptyStmt) + + val ioDstQueueConnect = if (ioDstQueues.length > 0) { + val readySignals = ioDstQueues map (queue => buildExp(Seq(instName(queue.name), "io", "deq", hostReady.name))) + val validSignals = ioDstQueues map (queue => buildExp(Seq(instName(queue.name), "io", "deq", hostValid.name))) + + (ioDstSignals map { sig => + (portMap(sig) map { src => + Connect(NoInfo, buildExp(Seq("io", "hostOut", "hostBits", sig)), + buildExp(Seq(instName(queueName(src, "topIO")), "io", "deq", "hostBits", sig))) + }) + }).flatten ++ + (readySignals map (sig => Connect(NoInfo, buildExp(sig), buildExp(Seq("io", "hostOut", hostReady.name))))) :+ + Connect(NoInfo, buildExp(Seq("io", "hostOut", hostValid.name)), genPrimopReduce(And, validSignals)) + } else Seq(EmptyStmt) + + val stmts = Block(insts ++ connectClocks ++ connectResets ++ connectQueues ++ ioSrcQueueConnect ++ ioDstQueueConnect) + val ports = Seq(hostClock, hostReset) ++ transformTopIO(rtlTop.ports) Module(NoInfo, "SimTop", ports, stmts) } - // ***** transform ***** + // ********** transform ********** // Perform FAME-1 Transformation for MIDAS def transform(c: Circuit): Circuit = { // We should check that the invariants mentioned above are true val nameToModule = (c.modules map (m => m.name -> m))(collection.breakOut): Map[String, Module] val top = nameToModule(c.name) + val rtlModules = c.modules filter (_.name != top.name) map (transformRTL) + val insts = getDefInsts(top) val portConn = findPortConn(top, insts) + // Check that port Connections include all ports for each instance? - println(portConn) val simWrappers = insts map (inst => genWrapperModule(inst, portConn(inst.name))) val simQueues = generateSimQueues(simWrappers) - // Remove duplicate simWrapper and simQueue modules + // Remove duplicate simWrapper and simQueue modules? - val simTop = generateSimTop(simWrappers, simQueues, top) + val simTop = generateSimTop(simWrappers, simQueues, portConn("topIO"), top) - val modules = (c.modules filter (_.name != top.name)) ++ simWrappers ++ simQueues.values.toSeq ++ Seq(simTop) + val modules = rtlModules ++ simWrappers ++ simQueues.values.toSeq ++ Seq(simTop) - println(simTop.serialize) Circuit(c.info, simTop.name, modules) - //c } } diff --git a/src/main/scala/midas/Utils.scala b/src/main/scala/midas/Utils.scala index b9006b59..003f22bb 100644 --- a/src/main/scala/midas/Utils.scala +++ b/src/main/scala/midas/Utils.scala @@ -19,6 +19,58 @@ object Utils { } } + // This doesn't work because of Type Erasure >.< + //private def getStmts[A <: Stmt](s: Stmt): Seq[A] = { + // s match { + // case a: A => Seq(a) + // case b: Block => b.stmts.map(getStmts[A]).flatten + // case _ => Seq() + // } + //} + //private def getStmts[A <: Stmt](m: Module): Seq[A] = getStmts[A](m.stmt) + + def getDefRegs(s: Stmt): Seq[DefReg] = { + s match { + case r: DefReg => Seq(r) + case b: Block => b.stmts.map(getDefRegs).flatten + case _ => Seq() + } + } + def getDefRegs(m: Module): Seq[DefReg] = getDefRegs(m.stmt) + + def getDefInsts(s: Stmt): Seq[DefInst] = { + s match { + case i: DefInst => Seq(i) + case b: Block => b.stmts.map(getDefInsts).flatten + case _ => Seq() + } + } + def getDefInsts(m: Module): Seq[DefInst] = getDefInsts(m.stmt) + + def getDefInstRef(inst: DefInst): Ref = { + inst.module match { + case ref: Ref => ref + case _ => throw new Exception("Invalid module expression for DefInst: " + inst.serialize) + } + } + + // DefInsts have an Expression for the module, this expression should be a reference this + // reference has a tpe that should be a bundle representing the IO of that module class + def getDefInstType(inst: DefInst): BundleType = { + val ref = getDefInstRef(inst) + ref.tpe match { + case b: BundleType => b + case _ => throw new Exception("Invalid reference type for DefInst: " + inst.serialize) + } + } + + def getModuleFromDefInst(nameToModule: Map[String, Module], inst: DefInst): Module = { + val instModule = getDefInstRef(inst) + if(!nameToModule.contains(instModule.name)) + throw new Exception(s"Module ${instModule.name} not found in circuit!") + else + nameToModule(instModule.name) + } // Takes a set of strings or ints and returns equivalent expression node // Strings correspond to subfields/references, ints correspond to indexes @@ -46,8 +98,10 @@ object Utils { } def buildExp(name: Any): Exp = buildExp(Seq(name)) - def genPrimopReduce(op: Primop, args: Seq[Exp]): DoPrimop = { - if( args.length == 2 ) DoPrimop(op, Seq(args.head, args.last), Seq(), UnknownType) + def genPrimopReduce(op: Primop, args: Seq[Exp]): Exp = { + if( args.length == 0 ) throw new Exception("genPrimopReduce called on empty sequence!") + else if( args.length == 1 ) args.head + else if( args.length == 2 ) DoPrimop(op, Seq(args.head, args.last), Seq(), UnknownType) else DoPrimop(op, Seq(args.head, genPrimopReduce(op, args.tail)), Seq(), UnknownType) } @@ -95,88 +149,179 @@ object Utils { } } + // Recursively iterates through firrtl.Type returning sequence of names to address signals + // * Intended for use with recursive bundle types + def enumerateMembers(tpe: Type): Seq[Seq[Any]] = { + def rec(tpe: Type, path: Seq[Any], members: Seq[Seq[Any]]): Seq[Seq[Any]] = { + tpe match { + case b: BundleType => (b.fields map ( f => rec(f.tpe, path :+ f.name, members) )).flatten + case v: VectorType => (Seq.tabulate(v.size.toInt) ( i => rec(v.tpe, path :+ i, members) )).flatten + case _ => members :+ path + } + } + rec(tpe, Seq[Any](), Seq[Seq[Any]]()) + } + // Queue + // TODO + // - Insert null tokens upon hostReset (or should this be elsewhere?) def buildSimQueue(name: String, tpe: Type): Module = { - val templatedQueue = + val scopeSpaces = " " * 4 // Spaces before lines in module scope, for default assignments + val templatedQueue = +// """ +// circuit `NAME: +// module `NAME : +// input hostClock : Clock +// input hostReset : UInt<1> +// output io : {flip enq : {flip hostReady : UInt<1>, hostValid : UInt<1>, hostBits : `TYPE}, deq : {flip hostReady : UInt<1>, hostValid : UInt<1>, hostBits : `TYPE}, count : UInt<3>} +// +// io.count := UInt<1>("h00") +// `DEFAULT_ASSIGN +// io.deq.hostValid := UInt<1>("h00") +// io.enq.hostReady := UInt<1>("h00") +// cmem ram : `TYPE[4], hostClock +// reg T_80 : UInt<2>, hostClock, hostReset +// onreset T_80 := UInt<2>("h00") +// reg T_82 : UInt<2>, hostClock, hostReset +// onreset T_82 := UInt<2>("h00") +// reg maybe_full : UInt<1>, hostClock, hostReset +// onreset maybe_full := UInt<1>("h00") +// node ptr_match = eq(T_80, T_82) +// node T_87 = eq(maybe_full, UInt<1>("h00")) +// node empty = and(ptr_match, T_87) +// node full = and(ptr_match, maybe_full) +// node maybe_flow = and(UInt<1>("h00"), empty) +// node do_flow = and(maybe_flow, io.deq.hostReady) +// node T_93 = and(io.enq.hostReady, io.enq.hostValid) +// node T_95 = eq(do_flow, UInt<1>("h00")) +// node do_enq = and(T_93, T_95) +// node T_97 = and(io.deq.hostReady, io.deq.hostValid) +// node T_99 = eq(do_flow, UInt<1>("h00")) +// node do_deq = and(T_97, T_99) +// when do_enq : +// infer accessor T_101 = ram[T_80] +// T_101 <> io.enq.hostBits +// node T_109 = eq(T_80, UInt<2>("h03")) +// node T_111 = and(UInt<1>("h00"), T_109) +// node T_114 = addw(T_80, UInt<1>("h01")) +// node T_115 = mux(T_111, UInt<1>("h00"), T_114) +// T_80 := T_115 +// skip +// when do_deq : +// node T_117 = eq(T_82, UInt<2>("h03")) +// node T_119 = and(UInt<1>("h00"), T_117) +// node T_122 = addw(T_82, UInt<1>("h01")) +// node T_123 = mux(T_119, UInt<1>("h00"), T_122) +// T_82 := T_123 +// skip +// node T_124 = neq(do_enq, do_deq) +// when T_124 : +// maybe_full := do_enq +// skip +// node T_126 = eq(empty, UInt<1>("h00")) +// node T_128 = and(UInt<1>("h00"), io.enq.hostValid) +// node T_129 = or(T_126, T_128) +// io.deq.hostValid := T_129 +// node T_131 = eq(full, UInt<1>("h00")) +// node T_133 = and(UInt<1>("h00"), io.deq.hostReady) +// node T_134 = or(T_131, T_133) +// io.enq.hostReady := T_134 +// infer accessor T_135 = ram[T_82] +// wire T_149 : `TYPE +// T_149 <> T_135 +// when maybe_flow : +// T_149 <> io.enq.hostBits +// skip +// io.deq.hostBits <> T_149 +// node ptr_diff = subw(T_80, T_82) +// node T_157 = and(maybe_full, ptr_match) +// node T_158 = cat(T_157, ptr_diff) +// io.count := T_158 +// """ """ - circuit `NAME: - module `NAME : - input hostClock : Clock - input hostReset : UInt<1> - output io : {flip enq : {flip hostReady : UInt<1>, hostValid : UInt<1>, hostBits : `TYPE}, deq : {flip hostReady : UInt<1>, hostValid : UInt<1>, hostBits : `TYPE}, count : UInt<3>} - - io.count := UInt<1>("h00") - //io.deq.hostBits.surprise.no := UInt<1>("h00") - //io.deq.hostBits.surprise.yes := UInt<1>("h00") - //io.deq.hostBits.store := UInt<1>("h00") - //io.deq.hostBits.data := UInt<1>("h00") - //io.deq.hostBits.addr := UInt<1>("h00") - io.deq.hostValid := UInt<1>("h00") - io.enq.hostReady := UInt<1>("h00") - cmem ram : `TYPE[4], hostClock - reg T_80 : UInt<2>, hostClock, hostReset - onreset T_80 := UInt<2>("h00") - reg T_82 : UInt<2>, hostClock, hostReset - onreset T_82 := UInt<2>("h00") - reg maybe_full : UInt<1>, hostClock, hostReset - onreset maybe_full := UInt<1>("h00") - node ptr_match = eq(T_80, T_82) - node T_87 = eq(maybe_full, UInt<1>("h00")) - node empty = and(ptr_match, T_87) - node full = and(ptr_match, maybe_full) - node maybe_flow = and(UInt<1>("h00"), empty) - node do_flow = and(maybe_flow, io.deq.hostReady) - node T_93 = and(io.enq.hostReady, io.enq.hostValid) - node T_95 = eq(do_flow, UInt<1>("h00")) - node do_enq = and(T_93, T_95) - node T_97 = and(io.deq.hostReady, io.deq.hostValid) - node T_99 = eq(do_flow, UInt<1>("h00")) - node do_deq = and(T_97, T_99) - when do_enq : - infer accessor T_101 = ram[T_80] - T_101 <> io.enq.hostBits - node T_109 = eq(T_80, UInt<2>("h03")) - node T_111 = and(UInt<1>("h00"), T_109) - node T_114 = addw(T_80, UInt<1>("h01")) - node T_115 = mux(T_111, UInt<1>("h00"), T_114) - T_80 := T_115 - skip - when do_deq : - node T_117 = eq(T_82, UInt<2>("h03")) - node T_119 = and(UInt<1>("h00"), T_117) - node T_122 = addw(T_82, UInt<1>("h01")) - node T_123 = mux(T_119, UInt<1>("h00"), T_122) - T_82 := T_123 - skip - node T_124 = neq(do_enq, do_deq) - when T_124 : - maybe_full := do_enq - skip - node T_126 = eq(empty, UInt<1>("h00")) - node T_128 = and(UInt<1>("h00"), io.enq.hostValid) - node T_129 = or(T_126, T_128) - io.deq.hostValid := T_129 - node T_131 = eq(full, UInt<1>("h00")) - node T_133 = and(UInt<1>("h00"), io.deq.hostReady) - node T_134 = or(T_131, T_133) - io.enq.hostReady := T_134 - infer accessor T_135 = ram[T_82] - wire T_149 : `TYPE - T_149 <> T_135 - when maybe_flow : - T_149 <> io.enq.hostBits - skip - io.deq.hostBits <> T_149 - node ptr_diff = subw(T_80, T_82) - node T_157 = and(maybe_full, ptr_match) - node T_158 = cat(T_157, ptr_diff) - io.count := T_158 +circuit `NAME: + module `NAME : + input hostClock : Clock + input hostReset : UInt<1> + output io : {flip enq : {flip hostReady : UInt<1>, hostValid : UInt<1>, hostBits : `TYPE}, deq : {flip hostReady : UInt<1>, hostValid : UInt<1>, hostBits : `TYPE}, count : UInt<3>} + + io.count := UInt<1>("h00") + `DEFAULT_ASSIGN + io.deq.hostValid := UInt<1>("h00") + io.enq.hostReady := UInt<1>("h00") + cmem ram : `TYPE[4], hostClock + reg T_404 : UInt<2>, hostClock, hostReset + onreset T_404 := UInt<2>("h00") + reg T_406 : UInt<2>, hostClock, hostReset + onreset T_406 := UInt<2>("h00") + reg maybe_full : UInt<1>, hostClock, hostReset + onreset maybe_full := UInt<1>("h00") + reg add_token_on_reset : UInt<1>, hostClock, hostReset + onreset add_token_on_reset := UInt<1>("h01") + add_token_on_reset := UInt<1>("h00") + node ptr_match = eq(T_404, T_406) + node T_414 = eq(maybe_full, UInt<1>("h00")) + node empty = and(ptr_match, T_414) + node full = and(ptr_match, maybe_full) + node maybe_flow = and(UInt<1>("h00"), empty) + node do_flow = and(maybe_flow, io.deq.hostReady) + node T_420 = and(io.enq.hostReady, io.enq.hostValid) + node T_422 = eq(do_flow, UInt<1>("h00")) + node do_enq = and(T_420, T_422) + node T_424 = and(io.deq.hostReady, io.deq.hostValid) + node T_426 = eq(do_flow, UInt<1>("h00")) + node do_deq = and(T_424, T_426) + node T_428 = or(do_enq, add_token_on_reset) + when T_428 : + infer accessor T_443 = ram[T_404] + T_443 := io.enq.hostBits + node T_473 = eq(T_404, UInt<2>("h03")) + node T_475 = and(UInt<1>("h00"), T_473) + node T_478 = addw(T_404, UInt<1>("h01")) + node T_479 = mux(T_475, UInt<1>("h00"), T_478) + T_404 := T_479 + skip + when do_deq : + node T_481 = eq(T_406, UInt<2>("h03")) + node T_483 = and(UInt<1>("h00"), T_481) + node T_486 = addw(T_406, UInt<1>("h01")) + node T_487 = mux(T_483, UInt<1>("h00"), T_486) + T_406 := T_487 + skip + node T_488 = neq(do_enq, do_deq) + when T_488 : + maybe_full := do_enq + skip + node T_490 = eq(empty, UInt<1>("h00")) + node T_492 = and(UInt<1>("h00"), io.enq.hostValid) + node T_493 = or(T_490, T_492) + io.deq.hostValid := T_493 + node T_495 = eq(full, UInt<1>("h00")) + node T_497 = and(UInt<1>("h00"), io.deq.hostReady) + node T_498 = or(T_495, T_497) + io.enq.hostReady := T_498 + infer accessor T_513 = ram[T_406] + wire T_599 : `TYPE + T_599 := T_513 + when maybe_flow : + T_599 := io.enq.hostBits + skip + io.deq.hostBits := T_599 + node ptr_diff = subw(T_404, T_406) + node T_629 = and(maybe_full, ptr_match) + node T_630 = cat(T_629, ptr_diff) + io.count := T_630 """ - //def buildQueue(name: String, tpe: Type): Module = { - val concreteQueue = templatedQueue.replaceAllLiterally("`NAME", name). - replaceAllLiterally("`TYPE", tpe.serialize) // Generate initial values - //val bitsField = Field("bits", Default, tpe) + val signals = enumerateMembers(tpe) map ( Seq("io", "deq", "hostBits") ++ _ ) + val defaultAssign = signals map { sig => + scopeSpaces + Connect(NoInfo, buildExp(sig), UIntValue(0, UnknownWidth)).serialize + } + + val concreteQueue = templatedQueue.replaceAllLiterally("`NAME", name). + replaceAllLiterally("`TYPE", tpe.serialize). + replaceAllLiterally(scopeSpaces+"`DEFAULT_ASSIGN", defaultAssign.mkString("\n")) + val ast = firrtl.Parser.parse(concreteQueue.split("\n")) ast.modules.head } |
