Add missing PutPartial mask handling for coalesced writes

This commit is contained in:
Hansung Kim
2023-10-24 15:11:41 -07:00
parent 3fc3e91831
commit f0a401d72b

View File

@@ -177,12 +177,13 @@ class Request(sourceWidth: Int, sizeWidth: Int, addressWidth: Int, dataWidth: In
val mask = UInt((dataWidth / 8).W) // write only val mask = UInt((dataWidth / 8).W) // write only
val data = UInt(dataWidth.W) // write only val data = UInt(dataWidth.W) // write only
def toTLA(edgeOut: TLEdgeOut): TLBundleA = { def toTLA(edgeOut: TLEdgeOut): (Bool, TLBundleA) = {
val (plegal, pbits) = edgeOut.Put( val (plegal, pbits) = edgeOut.Put(
fromSource = this.source, fromSource = this.source,
toAddress = this.address, toAddress = this.address,
lgSize = this.size, lgSize = this.size,
data = this.data data = this.data,
mask = this.mask
) )
val (glegal, gbits) = edgeOut.Get( val (glegal, gbits) = edgeOut.Get(
fromSource = this.source, fromSource = this.source,
@@ -191,9 +192,7 @@ class Request(sourceWidth: Int, sizeWidth: Int, addressWidth: Int, dataWidth: In
) )
val legal = Mux(this.op.asBool, plegal, glegal) val legal = Mux(this.op.asBool, plegal, glegal)
val bits = Mux(this.op.asBool, pbits, gbits) val bits = Mux(this.op.asBool, pbits, gbits)
// FIXME: this needs to check valid bit as well (legal, bits)
// assert(legal, "unhandled illegal TL req gen")
bits
} }
} }
case class NonCoalescedRequest(config: CoalescerConfig) case class NonCoalescedRequest(config: CoalescerConfig)
@@ -721,8 +720,13 @@ class MultiCoalescer(
val data = Wire(Vec(maxWords, UInt((config.wordSizeInBytes * 8).W))) val data = Wire(Vec(maxWords, UInt((config.wordSizeInBytes * 8).W)))
val mask = Wire(Vec(maxWords, UInt(config.wordSizeInBytes.W))) val mask = Wire(Vec(maxWords, UInt(config.wordSizeInBytes.W)))
// Reconstruct data and mask bit of the coalesced request;
// important for coalesced writes
for (i <- 0 until maxWords) { for (i <- 0 until maxWords) {
val sel = flatReqs.zip(flatMatches).map { case (req, m) => // Construct select bits that represent per-lane requests that actually got
// coalesced into the current request, AND occupies the current i-th
// word-slot in the data/mask bits
val sel = (flatReqs zip flatMatches).map { case (req, m) =>
// note: ANDing against addrMask is to conform to active byte lanes requirements // note: ANDing against addrMask is to conform to active byte lanes requirements
// if aligning to LSB suffices, we should add the bitwise AND back // if aligning to LSB suffices, we should add the bitwise AND back
m && ((req.address( m && ((req.address(
@@ -733,13 +737,13 @@ class MultiCoalescer(
// TODO: SW uses priority encoder, not sure about behavior of MuxCase // TODO: SW uses priority encoder, not sure about behavior of MuxCase
data(i) := MuxCase( data(i) := MuxCase(
DontCare, DontCare,
flatReqs.zip(sel).map { case (req, s) => (flatReqs zip sel).map { case (req, s) =>
s -> req.data s -> req.data
} }
) )
mask(i) := MuxCase( mask(i) := MuxCase(
0.U, 0.U,
flatReqs.zip(sel).map { case (req, s) => (flatReqs zip sel).map { case (req, s) =>
s -> req.mask s -> req.mask
} }
) )
@@ -751,6 +755,7 @@ class MultiCoalescer(
// generation we also have to look at the responses coming back, which // generation we also have to look at the responses coming back, which
// is easier to do at the toplevel. // is easier to do at the toplevel.
io.coalReq.bits.source := DontCare io.coalReq.bits.source := DontCare
// Flatten data and mask Vecs into wide UInt
io.coalReq.bits.mask := mask.asUInt io.coalReq.bits.mask := mask.asUInt
io.coalReq.bits.data := data.asUInt io.coalReq.bits.data := data.asUInt
io.coalReq.bits.size := chosenSize io.coalReq.bits.size := chosenSize
@@ -886,7 +891,11 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig)
// Stall upstream core or memtrace driver when shiftqueue is not ready // Stall upstream core or memtrace driver when shiftqueue is not ready
tlIn.a.ready := enq.ready tlIn.a.ready := enq.ready
tlOut.a.valid := deq.valid tlOut.a.valid := deq.valid
tlOut.a.bits := deq.bits.toTLA(edgeOut) val (legal, tlBits) = deq.bits.toTLA(edgeOut)
tlOut.a.bits := tlBits
when(tlOut.a.fire) {
assert(legal, "unhandled illegal TL req gen")
}
// debug // debug
// when (tlIn.a.valid) { // when (tlIn.a.valid) {
@@ -944,7 +953,11 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig)
// TODO: custom <>? // TODO: custom <>?
inflightTable.io.outCoalReq.ready := tlCoal.a.ready inflightTable.io.outCoalReq.ready := tlCoal.a.ready
tlCoal.a.valid := coalReq.valid tlCoal.a.valid := coalReq.valid
tlCoal.a.bits := coalReq.bits.toTLA(edgeCoal) val (legal, tlBits) = coalReq.bits.toTLA(edgeCoal)
tlCoal.a.bits := tlBits
when(tlCoal.a.fire) {
assert(legal, "unhandled illegal TL req gen")
}
dontTouch(coalReq) dontTouch(coalReq)
tlCoal.b.ready := true.B tlCoal.b.ready := true.B
@@ -1207,8 +1220,8 @@ class InFlightTable(
// Need this to generate new entry for the table. // Need this to generate new entry for the table.
// TODO: duplicate type construction // TODO: duplicate type construction
val windowElts = Input(Vec(config.numLanes, Vec(config.queueDepth, nonCoalReqT))) val windowElts = Input(Vec(config.numLanes, Vec(config.queueDepth, nonCoalReqT)))
// InflightTable also handles sourceID allocation. This is the final // InflightTable simply passes through the inCoalReq to outCoalReq, only snooping
// coalesced request that goes to TileLink with a valid sourceId attached. // on its data to record what's necessary.
val outCoalReq = Decoupled(coalReqT) val outCoalReq = Decoupled(coalReqT)
// Lookup outputs // Lookup outputs
@@ -1276,15 +1289,16 @@ class InFlightTable(
newEntry newEntry
} }
io.outCoalReq <> io.inCoalReq // FIXME: do sourceId allocation io.outCoalReq <> io.inCoalReq
val enqReady = !full val enqReady = !full
// Make sure to respect downstream ready here as well; otherwise inCoalReq.valid // Make sure to respect downstream ready here as well; otherwise inCoalReq.valid
// might be up for multiple cycles waiting for outCoalReq.ready, writing bogus // might be up for multiple cycles waiting for downstream and write bogus
// data to the row // data to the row
val enqFire = enqReady && io.inCoalReq.valid && io.outCoalReq.ready val enqFire = enqReady && io.inCoalReq.valid && io.outCoalReq.ready
val enqSource = io.inCoalReq.bits.source val enqSource = io.inCoalReq.bits.source
when(enqFire) { when(enqFire) {
// Inflight table is indexed by coalReq's source id
val entryToWrite = table(enqSource) val entryToWrite = table(enqSource)
assert( assert(
!entryToWrite.valid, !entryToWrite.valid,
@@ -1536,7 +1550,7 @@ class MemTraceDriverImp(
val bits = Mux(req.is_store, pbits, gbits) val bits = Mux(req.is_store, pbits, gbits)
tlOut.a.valid := reqQ.io.deq.valid && syncedSourceGenValid tlOut.a.valid := reqQ.io.deq.valid && syncedSourceGenValid
when(tlOut.a.valid) { when(tlOut.a.fire) {
assert(legal, "illegal TL req gen") assert(legal, "illegal TL req gen")
} }
tlOut.a.bits := bits tlOut.a.bits := bits
@@ -2241,7 +2255,11 @@ class CoalescerXbarImpl(outer: CoalescerXbar,
val (tlOut, edgeOut) = node.out(0) val (tlOut, edgeOut) = node.out(0)
q.io.deq.ready := tlOut.a.ready q.io.deq.ready := tlOut.a.ready
tlOut.a.valid := q.io.deq.valid tlOut.a.valid := q.io.deq.valid
tlOut.a.bits := q.io.deq.bits.toTLA(edgeOut) val (legal, tlBits) = q.io.deq.bits.toTLA(edgeOut)
tlOut.a.bits := tlBits
when(tlOut.a.fire) {
assert(legal, "unhandled illegal TL req gen")
}
} }
//The XBar will take care of the rest //The XBar will take care of the rest