@@ -12,8 +12,8 @@ class CollectorRequest(
1212 val regs = Vec (numPorts, new Bundle {
1313 val enable = Bool ()
1414 val pReg = pRegT
15+ val tmask = Option .when(isWrite)(tmaskT)
1516 val data = Option .when(isWrite)(Vec (numLanes, regDataT))
16- // TODO: tmask
1717 })
1818 val rsEntryId = UInt (rsEntryIdWidth.W )
1919 val pc = Option .when(muonParams.debug)(pcT)
@@ -39,7 +39,6 @@ class CollectorResponse(
3939 val collEntry = UInt (collEntryWidth.W )
4040 val regs = Vec (numPorts, new Bundle {
4141 val enable = Bool ()
42- // TODO: tmask
4342 })
4443}
4544
@@ -58,14 +57,14 @@ class CollectorOperandRead(implicit p: Parameters) extends CoreBundle()(p) {
5857 val collEntry = UInt (collEntryWidth.W )
5958 val regs = Vec (Isa .maxNumRegs, new Bundle {
6059 val enable = Bool ()
60+ // TODO: tmask for @power
6161 })
6262 }))
6363 // same-cycle as `req`
6464 val resp = Valid (Vec (Isa .maxNumRegs, new Bundle {
6565 val enable = Bool ()
6666 val pReg = Option .when(hasPReg)(pRegT)
6767 val data = Vec (numLanes, regDataT)
68- // TODO: tmask
6968 }))
7069}
7170
@@ -92,7 +91,7 @@ class DuplicatedCollector(implicit p: Parameters) extends CoreModule()(p) {
9291
9392 def vecRegDataT = Vec (numLanes, regDataT)
9493 val vecZeros = 0 .U .asTypeOf(vecRegDataT)
95- val rfBanks = Seq .fill(Isa .maxNumRegs)(Seq .fill(muonParams.numRegBanks)(SRAM (
94+ val rfBanks = Seq .fill(Isa .maxNumRegs)(Seq .fill(muonParams.numRegBanks)(SRAM .masked (
9695 size = muonParams.numPhysRegs / muonParams.numRegBanks,
9796 tpe = vecRegDataT,
9897 numReadPorts = 1 ,
@@ -166,7 +165,13 @@ class DuplicatedCollector(implicit p: Parameters) extends CoreModule()(p) {
166165 val regOut = Mux (nextPReg =/= 0 .U ,
167166 VecInit (bankPorts.map(_.data))(nextBankId),
168167 vecZeros)
169- // TODO: @perf: Skip latching 0.U to collBank
168+
169+ // latch SRAM output to collector banks
170+ //
171+ // TODO: @power: Respect readReq.tmask, and latch 0.U for inactive lanes.
172+ // Currently the downstream EX does the right thing even when the
173+ // collector supplies garbage values for inactive lanes, but this is
174+ // better for power.
170175 collBank.zipWithIndex.foreach { case (entry, i) =>
171176 when (nextEn && (i.U === nextAllocId)) {
172177 entry := regOut
@@ -189,14 +194,19 @@ class DuplicatedCollector(implicit p: Parameters) extends CoreModule()(p) {
189194 io.writeReq.ready := true .B
190195 val writeEnable = io.writeReq.fire && io.writeReq.bits.regs.head.enable
191196 val writePReg = io.writeReq.bits.regs.head.pReg
197+ val writeTmask = io.writeReq.bits.regs.head.tmask.get
192198 val writeData = io.writeReq.bits.regs.head.data.get
193- // write to all of rs1/2/3 banks
199+ // broadcast write to all of rs1/2/3 banks
194200 rfBanks.foreach { case banks =>
195201 val bankWrites = VecInit (banks.map(_.writePorts.head))
196- bankWrites.foreach { b =>
197- b.address := regBankAddr(writePReg)
198- b.data := writeData
199- b.enable := false .B
202+ bankWrites.foreach { port =>
203+ port.address := regBankAddr(writePReg)
204+ port.data := writeData
205+ assert(port.mask.isDefined, " RegFile SRAM must be masked" )
206+ assert(port.mask.get.length == writeTmask.getWidth,
207+ " RegFile SRAM mask width does not match tmask width" )
208+ port.mask.get := VecInit (writeTmask.asBools)
209+ port.enable := false .B
200210 }
201211 bankWrites(regBankId(writePReg)).enable := writeEnable && (writePReg =/= 0 .U )
202212 }
0 commit comments