Skip to content

Commit 19d04ab

Browse files
committed
collector: Fix per-reg dequeueing of collBanks
1 parent 6a969b1 commit 19d04ab

2 files changed

Lines changed: 38 additions & 25 deletions

File tree

src/main/scala/radiance/muon/Collector.scala

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,12 @@ object CollectorResponse {
5252
class 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

src/main/scala/radiance/muon/ReservationStation.scala

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,10 @@ class ReservationStation(implicit p: Parameters) extends CoreModule()(p) {
237237
// issue
238238
// -----
239239

240-
def issueArbBundleT = new Bundle {
240+
def issueBundleT = new Bundle {
241241
val entry = chiselTypeOf(io.issue.bits)
242242
val entryId = UInt(log2Ceil(numEntries).W)
243+
val hasOps = chiselTypeOf(hasOpTable.head)
243244
}
244245

245246
// check issue eligiblity after collection finished & RAW settled
@@ -270,10 +271,11 @@ class ReservationStation(implicit p: Parameters) extends CoreModule()(p) {
270271

271272
eligibleTable(i) := eligible
272273

273-
val candidate = Wire(Decoupled(issueArbBundleT))
274+
val candidate = Wire(Decoupled(issueBundleT))
274275
candidate.valid := eligible
275276
candidate.bits.entry := instTable(i)
276277
candidate.bits.entryId := i.U
278+
candidate.bits.hasOps := hasOps
277279

278280
// deregister upon issue
279281
when (candidate.fire) {
@@ -292,14 +294,6 @@ class ReservationStation(implicit p: Parameters) extends CoreModule()(p) {
292294
(issueScheduler.io.in zip eligibles).foreach { case (s, e) => s <> e }
293295
val issueScheduled = issueScheduler.io.out
294296

295-
// drive collector's operand serve port upon issue, for use in EX
296-
// make sure to line this up with EX fire, so that collector data gets
297-
// consumed when it's used
298-
io.collector.readData.req.valid := io.issue.valid
299-
io.collector.readData.req.bits.collEntry := 0.U // fixed for DuplicatedCollector, TODO
300-
io.collector.readData.resp.ready := io.issue.fire
301-
assert(useCollector, "FIXME: !useCollector is broken currently")
302-
303297
val issuedId = WireDefault(issueScheduler.io.out.bits.entryId)
304298
// FIXME: Old bypass-specific code; remove
305299
//
@@ -338,12 +332,12 @@ class ReservationStation(implicit p: Parameters) extends CoreModule()(p) {
338332
// latch the issue at the output to cut timing before EX (which currently
339333
// does not latch its input), and also to stage it when EX is !ready.
340334
val issueStaged = Module(
341-
new Queue(gen = chiselTypeOf(io.issue.bits), entries = 1, pipe = true)
335+
new Queue(gen = issueBundleT, entries = 1, pipe = true)
342336
)
343-
issueStaged.io.enq.valid := issueScheduler.io.out.valid
344-
issueStaged.io.enq.bits := issueScheduler.io.out.bits.entry
345-
issueScheduler.io.out.ready := issueStaged.io.enq.ready
346-
io.issue <> issueStaged.io.deq
337+
issueStaged.io.enq <> issueScheduler.io.out
338+
io.issue.valid := issueStaged.io.deq.valid
339+
io.issue.bits := issueStaged.io.deq.bits.entry
340+
issueStaged.io.deq.ready := io.issue.ready
347341

348342
if (muonParams.debug) {
349343
when (io.issue.fire) {
@@ -352,6 +346,16 @@ class ReservationStation(implicit p: Parameters) extends CoreModule()(p) {
352346
}
353347
}
354348

349+
// drive collector's operand serve port upon issue, for use in EX
350+
// make sure to line this up with EX fire, so that collector data gets
351+
// consumed when it's used
352+
io.collector.readData.req.valid := io.issue.valid
353+
(io.collector.readData.req.bits zip issueStaged.io.deq.bits.hasOps).foreach { case (req, hasOp) =>
354+
req.enable := io.issue.fire && hasOp
355+
req.collEntry := 0.U // fixed for DuplicatedCollector, TODO
356+
}
357+
358+
assert(useCollector, "FIXME: !useCollector is broken currently")
355359

356360
// ---------
357361
// writeback

0 commit comments

Comments
 (0)