@@ -52,10 +52,12 @@ object CollectorResponse {
5252class CollectorOperandRead (implicit p : Parameters ) extends CoreBundle ()(p) {
5353 val collEntryWidth = log2Up(muonParams.numCollectorEntries)
5454 val hasPReg = ! muonParams.useCollector
55- val req = Flipped (Valid (new Bundle {
55+ val req = Flipped (Valid (Vec (Isa .maxNumRegs, new Bundle {
56+ val enable = Bool ()
5657 val collEntry = UInt (collEntryWidth.W )
57- }))
58- val resp = Decoupled (Vec (Isa .maxNumRegs, new Bundle {
58+ })))
59+ // same-cycle as `req`
60+ val resp = Valid (Vec (Isa .maxNumRegs, new Bundle {
5961 val enable = Bool ()
6062 val pReg = Option .when(hasPReg)(pRegT)
6163 val data = Vec (numLanes, regDataT)
@@ -103,7 +105,7 @@ class DuplicatedCollector(implicit p: Parameters) extends CoreModule()(p) {
103105 }
104106
105107 // collector banks, i.e. flip-flops that stage collected register data until
106- // EX consumes them
108+ // EX consumes them. Separate per-reg, enq/deq drifts need care.
107109 val collBankEntries = 2
108110 val collBanks = Seq .fill(Isa .maxNumRegs)(Module (
109111 new Queue (gen = vecRegDataT, entries = collBankEntries, pipe = true )
@@ -117,22 +119,23 @@ class DuplicatedCollector(implicit p: Parameters) extends CoreModule()(p) {
117119 val readPRegs = io.readReq.bits.regs.map(_.pReg)
118120 (readEns lazyZip readPRegs lazyZip rfBanks lazyZip collBanks)
119121 .foreach { case (en, pReg, banks, collBank) =>
120- val bankEn = io.readReq.fire && en && (pReg =/= 0 . U )
122+ val bankEn = io.readReq.fire && en
121123 val bankPorts = VecInit (banks.map(_.readPorts.head))
122124 val bankId = regBankId(pReg)
123125 val nextBankId = RegNext (bankId, 0 .U )
124126 val nextEn = RegNext (bankEn, false .B )
125127 val nextPReg = RegNext (pReg, 0 .U )
126128
127129 bankPorts.foreach(_.enable := false .B )
128- bankPorts(bankId).enable := bankEn
130+ bankPorts(bankId).enable := bankEn && (pReg =/= 0 . U )
129131 bankPorts.foreach(_.address := regBankAddr(pReg))
130132
131- val bankOut = Mux (nextPReg =/= 0 .U ,
133+ val regOut = Mux (nextPReg =/= 0 .U ,
132134 VecInit (bankPorts.map(_.data))(nextBankId),
133135 vecZeros)
136+ // TODO: @perf: Skip latching 0.U to collBank
134137 collBank.io.enq.valid := nextEn
135- collBank.io.enq.bits := bankOut
138+ collBank.io.enq.bits := regOut
136139 }
137140
138141 // read response
@@ -164,13 +167,19 @@ class DuplicatedCollector(implicit p: Parameters) extends CoreModule()(p) {
164167 io.writeResp.ports.head.bits.collEntry := 0 .U // duplicated collector has no collector entry
165168
166169 // operand serve (readData)
170+ // currently, collector drives response with valid data regardless of EX req
167171 io.readData.resp.valid := collBanks.map(_.io.deq.valid).reduce(_ || _)
168172 (io.readData.resp.bits zip collBanks).foreach { case (opnd, collBank) =>
173+ // FIXME: this doesn't work when collBanks drift!!
169174 opnd.enable := collBank.io.deq.valid
170175 opnd.data := collBank.io.deq.bits
171176 assert(opnd.pReg.isEmpty)
172- // dequeue. Note: should be fire to consider EX back-pressure
173- collBank.io.deq.ready := io.readData.resp.fire
177+ }
178+ // dequeue collector bank on successful serve
179+ (io.readData.req.bits zip collBanks).foreach { case (req, collBank) =>
180+ assert(! req.enable || io.readData.req.valid,
181+ " collector: reg.enable set when request is invalid?" )
182+ collBank.io.deq.ready := req.enable
174183 }
175184}
176185
0 commit comments