Add missing PutPartial mask handling for coalesced writes
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user