diff --git a/macros/src/main/scala/SynFlops.scala b/macros/src/main/scala/SynFlops.scala index e005196a..d33ca43c 100644 --- a/macros/src/main/scala/SynFlops.scala +++ b/macros/src/main/scala/SynFlops.scala @@ -31,13 +31,13 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa dataType, lib.src.depth, 1, // writeLatency - 0, // readLatency - (lib.readers ++ lib.readwriters).indices map (i => s"R_$i"), - (lib.writers ++ lib.readwriters).indices map (i => s"W_$i"), - Nil + 1, // readLatency + lib.readers.indices map (i => s"R_$i"), + lib.writers.indices map (i => s"W_$i"), + lib.readwriters.indices map (i => s"RW_$i") ) - val readConnects = (lib.readers ++ lib.readwriters).zipWithIndex flatMap { case (r, i) => + val readConnects = lib.readers.zipWithIndex flatMap { case (r, i) => val clock = portToExpression(r.src.clock) val address = portToExpression(r.src.address) val enable = (r.src chipEnable, r.src readEnable) match { @@ -54,18 +54,15 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa WSubIndex(data, k, tpe, UNKNOWNGENDER))).reverse) case _: UIntType => data } - val addrReg = WRef(s"R_${i}_addr_reg", r.addrType, RegKind) Seq( - DefRegister(NoInfo, addrReg.name, r.addrType, clock, zero, addrReg), Connect(NoInfo, memPortField(mem, s"R_$i", "clk"), clock), - Connect(NoInfo, memPortField(mem, s"R_$i", "addr"), addrReg), + Connect(NoInfo, memPortField(mem, s"R_$i", "addr"), address), Connect(NoInfo, memPortField(mem, s"R_$i", "en"), enable), - Connect(NoInfo, WRef(r.src.output.get.name), read), - Connect(NoInfo, addrReg, Mux(enable, address, addrReg, UnknownType)) + Connect(NoInfo, WRef(r.src.output.get.name), read) ) } - val writeConnects = (lib.writers ++ lib.readwriters).zipWithIndex flatMap { case (w, i) => + val writeConnects = lib.writers.zipWithIndex flatMap { case (w, i) => val clock = portToExpression(w.src.clock) val address = portToExpression(w.src.address) val enable = (w.src.chipEnable, w.src.writeEnable) match { @@ -96,15 +93,55 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa Seq(Connect(NoInfo, data, write), Connect(NoInfo, mask, one)) }) } - lib.module(Block(mem +: (readConnects ++ writeConnects))) + + val readwriteConnects = lib.readwriters.zipWithIndex flatMap { case (rw, i) => + val clock = portToExpression(rw.src.clock) + val address = portToExpression(rw.src.address) + val wmode = rw.src.writeEnable match { + case Some(we) => portToExpression(we) + case None => zero // is it possible? + } + val enable = (rw.src.chipEnable, rw.src.readEnable) match { + case (Some(en), Some(re)) => + and(portToExpression(en), or(portToExpression(re), wmode)) + case (Some(en), None) => portToExpression(en) + case (None, Some(re)) => or(portToExpression(re), wmode) + case (None, None) => one + } + val wmask = memPortField(mem, s"RW_$i", "wmask") + val wdata = memPortField(mem, s"RW_$i", "wdata") + val rdata = memPortField(mem, s"RW_$i", "rdata") + val write = portToExpression(rw.src.input.get) + val read = (dataType: @unchecked) match { + case VectorType(tpe, size) => cat(((0 until size) map (k => + WSubIndex(rdata, k, tpe, UNKNOWNGENDER))).reverse) + case _: UIntType => rdata + } + Seq( + Connect(NoInfo, memPortField(mem, s"RW_$i", "clk"), clock), + Connect(NoInfo, memPortField(mem, s"RW_$i", "addr"), address), + Connect(NoInfo, memPortField(mem, s"RW_$i", "en"), enable), + Connect(NoInfo, memPortField(mem, s"RW_$i", "wmode"), wmode), + Connect(NoInfo, WRef(rw.src.output.get.name), read) + ) ++ (dataType match { + case VectorType(tpe, size) => + val width = bitWidth(tpe).toInt + ((0 until size) map (k => + Connect(NoInfo, WSubIndex(wdata, k, tpe, UNKNOWNGENDER), + bits(write, (k + 1) * width - 1, k * width)))) ++ + ((0 until size) map (k => + Connect(NoInfo, WSubIndex(wmask, k, BoolType, UNKNOWNGENDER), + bits(WRef(rw.src.maskPort.get.name), k)))) + case _: UIntType => + Seq(Connect(NoInfo, wdata, write), Connect(NoInfo, wmask, one)) + }) + } + + lib.module(Block(mem +: (readConnects ++ writeConnects ++ readwriteConnects))) }}).toMap def run(c: Circuit): Circuit = { if (!synflops) c - else { - val circuit = c.copy(modules = (c.modules map (m => libMods getOrElse (m.name, m)))) - // print(circuit.serialize) - circuit - } + else c.copy(modules = (c.modules map (m => libMods getOrElse (m.name, m)))) } } diff --git a/macros/src/main/scala/Utils.scala b/macros/src/main/scala/Utils.scala index 5c41ef8b..450a33a4 100644 --- a/macros/src/main/scala/Utils.scala +++ b/macros/src/main/scala/Utils.scala @@ -75,6 +75,8 @@ object Utils { def and(e1: Expression, e2: Expression) = DoPrim(PrimOps.And, Seq(e1, e2), Nil, e1.tpe) + def or(e1: Expression, e2: Expression) = + DoPrim(PrimOps.Or, Seq(e1, e2), Nil, e1.tpe) def bits(e: Expression, high: BigInt, low: BigInt): Expression = DoPrim(PrimOps.Bits, Seq(e), Seq(high, low), UIntType(IntWidth(high-low+1))) def bits(e: Expression, idx: BigInt): Expression = bits(e, idx, idx)