Generalize Req/RespQueueEntry into Response/Request bundle

This commit is contained in:
Hansung Kim
2023-05-11 15:42:23 -07:00
parent 300eff4f9a
commit 5fed3ef823

View File

@@ -135,7 +135,10 @@ class CoalescingUnit(config: CoalescerConfig)(implicit p: Parameters) extends La
lazy val module = new CoalescingUnitImp(this, config) lazy val module = new CoalescingUnitImp(this, config)
} }
class ReqQueueEntry(sourceWidth: Int, sizeWidth: Int, addressWidth: Int, dataWidth: Int) extends Bundle { // Protocol-agnostic bundles that represent a request and a response to the
// coalescer.
class Request(sourceWidth: Int, sizeWidth: Int, addressWidth: Int, dataWidth: Int) extends Bundle {
require(dataWidth % 8 == 0, s"dataWidth (${dataWidth} bits) is not multiple of 8") require(dataWidth % 8 == 0, s"dataWidth (${dataWidth} bits) is not multiple of 8")
val op = UInt(1.W) // 0=READ 1=WRITE val op = UInt(1.W) // 0=READ 1=WRITE
val address = UInt(addressWidth.W) val address = UInt(addressWidth.W)
@@ -163,7 +166,7 @@ class ReqQueueEntry(sourceWidth: Int, sizeWidth: Int, addressWidth: Int, dataWid
} }
} }
class RespQueueEntry(sourceWidth: Int, sizeWidth: Int, dataWidth: Int) extends Bundle { class Response(sourceWidth: Int, sizeWidth: Int, dataWidth: Int) extends Bundle {
val op = UInt(1.W) // 0=READ 1=WRITE val op = UInt(1.W) // 0=READ 1=WRITE
val size = UInt(sizeWidth.W) val size = UInt(sizeWidth.W)
val source = UInt(sourceWidth.W) val source = UInt(sourceWidth.W)
@@ -192,6 +195,15 @@ class RespQueueEntry(sourceWidth: Int, sizeWidth: Int, dataWidth: Int) extends B
} }
} }
class NonCoalescedResponse(config: CoalescerConfig)
extends Response(sourceWidth = log2Ceil(config.numOldSrcIds),
sizeWidth = config.wordSizeWidth,
dataWidth = config.wordSizeInBytes * 8)
class CoalescedResponse(config: CoalescerConfig)
extends Response(sourceWidth = log2Ceil(config.numNewSrcIds),
sizeWidth = log2Ceil(config.maxCoalLogSize),
dataWidth = (8 * (1 << config.maxCoalLogSize)))
// If `ignoreInUse`, just keep giving out new IDs without checking if it is in // If `ignoreInUse`, just keep giving out new IDs without checking if it is in
// use. // use.
class RoundRobinSourceGenerator(sourceWidth: Int, ignoreInUse: Boolean = true) extends Module { class RoundRobinSourceGenerator(sourceWidth: Int, ignoreInUse: Boolean = true) extends Module {
@@ -340,7 +352,7 @@ class CoalShiftQueue[T <: Data](gen: T, entries: Int, config: CoalescerConfig) e
} }
// Software model: coalescer.py // Software model: coalescer.py
class MonoCoalescer(coalLogSize: Int, windowT: CoalShiftQueue[ReqQueueEntry], class MonoCoalescer(coalLogSize: Int, windowT: CoalShiftQueue[Request],
config: CoalescerConfig) extends Module { config: CoalescerConfig) extends Module {
val io = IO(new Bundle { val io = IO(new Bundle {
val window = Input(windowT.io.cloneType) val window = Input(windowT.io.cloneType)
@@ -376,7 +388,7 @@ class MonoCoalescer(coalLogSize: Int, windowT: CoalShiftQueue[ReqQueueEntry],
val size = coalLogSize val size = coalLogSize
val addrMask = (((1 << config.addressWidth) - 1) - ((1 << size) - 1)).U val addrMask = (((1 << config.addressWidth) - 1) - ((1 << size) - 1)).U
def canMatch(req0: ReqQueueEntry, req0v: Bool, req1: ReqQueueEntry, req1v: Bool): Bool = { def canMatch(req0: Request, req0v: Bool, req1: Request, req1v: Bool): Bool = {
(req0.op === req1.op) && (req0.op === req1.op) &&
(req0v && req1v) && (req0v && req1v) &&
((req0.address & this.addrMask) === (req1.address & this.addrMask)) ((req0.address & this.addrMask) === (req1.address & this.addrMask))
@@ -471,7 +483,7 @@ class MonoCoalescer(coalLogSize: Int, windowT: CoalShiftQueue[ReqQueueEntry],
// coalesced request out of all possible combinations. // coalesced request out of all possible combinations.
// //
// Software model: coalescer.py // Software model: coalescer.py
class MultiCoalescer(windowT: CoalShiftQueue[ReqQueueEntry], coalReqT: ReqQueueEntry, class MultiCoalescer(windowT: CoalShiftQueue[Request], coalReqT: Request,
config: CoalescerConfig) extends Module { config: CoalescerConfig) extends Module {
val io = IO(new Bundle { val io = IO(new Bundle {
// coalescing window, connected to the contents of the request queues // coalescing window, connected to the contents of the request queues
@@ -612,11 +624,11 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends
val sourceWidth = outer.cpuNode.in.head._1.params.sourceBits val sourceWidth = outer.cpuNode.in.head._1.params.sourceBits
// note we are using word size. assuming all coalescer inputs are word sized // note we are using word size. assuming all coalescer inputs are word sized
val reqQueueEntryT = new ReqQueueEntry(sourceWidth, config.wordSizeWidth, val reqQueueEntryT = new Request(sourceWidth, config.wordSizeWidth,
config.addressWidth, (config.wordSizeInBytes * 8)) config.addressWidth, (config.wordSizeInBytes * 8))
val reqQueues = Module(new CoalShiftQueue(reqQueueEntryT, config.queueDepth, config)) val reqQueues = Module(new CoalShiftQueue(reqQueueEntryT, config.queueDepth, config))
val coalReqT = new ReqQueueEntry(log2Ceil(config.numNewSrcIds), log2Ceil(config.maxCoalLogSize), val coalReqT = new Request(log2Ceil(config.numNewSrcIds), log2Ceil(config.maxCoalLogSize),
config.addressWidth, (1 << config.maxCoalLogSize) * 8) config.addressWidth, (1 << config.maxCoalLogSize) * 8)
val coalescer = Module(new MultiCoalescer(reqQueues, coalReqT, config)) val coalescer = Module(new MultiCoalescer(reqQueues, coalReqT, config))
coalescer.io.window := reqQueues.io coalescer.io.window := reqQueues.io
@@ -703,7 +715,8 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends
// coalesced request. Upper bound is min(DEPTH, 2**sourceWidth). // coalesced request. Upper bound is min(DEPTH, 2**sourceWidth).
val numPerLaneReqs = config.queueDepth val numPerLaneReqs = config.queueDepth
val respQueueEntryT = new RespQueueEntry(sourceWidth, log2Ceil(config.maxCoalLogSize), // FIXME: no need to contain maxCoalLogSize data
val respQueueEntryT = new Response(sourceWidth, log2Ceil(config.maxCoalLogSize),
(1 << config.maxCoalLogSize) * 8) (1 << config.maxCoalLogSize) * 8)
val respQueues = Seq.tabulate(config.numLanes) { _ => val respQueues = Seq.tabulate(config.numLanes) { _ =>
Module( Module(
@@ -821,8 +834,7 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends
uncoalescer.io.newEntry := newEntry uncoalescer.io.newEntry := newEntry
// Cleanup: custom <>? // Cleanup: custom <>?
uncoalescer.io.coalResp.valid := tlCoal.d.valid uncoalescer.io.coalResp.valid := tlCoal.d.valid
uncoalescer.io.coalResp.bits.source := tlCoal.d.bits.source uncoalescer.io.coalResp.bits.fromTLD(tlCoal.d.bits)
uncoalescer.io.coalResp.bits.data := tlCoal.d.bits.data
tlCoal.d.ready := uncoalescer.io.coalResp.ready tlCoal.d.ready := uncoalescer.io.coalResp.ready
// Connect uncoalescer results back into each lane's response queue // Connect uncoalescer results back into each lane's response queue
@@ -853,24 +865,6 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) extends
dontTouch(tlCoal.d) dontTouch(tlCoal.d)
} }
// Protocol-agnostic bundle that represents a coalesced response.
//
// Having this makes it easier to:
// * do unit tests -- no need to deal with TileLink in the chiseltest code
// * adapt coalescer to custom protocols like a custom L1 cache interface.
//
// FIXME: overlaps with RespQueueEntry. Trait-ify
class CoalescedResponseBundle(config: CoalescerConfig) extends Bundle {
val source = UInt(log2Ceil(config.numNewSrcIds).W)
val data = UInt((8 * (1 << config.maxCoalLogSize)).W)
def fromTLD(bundle:TLBundleD): Unit = {
this.source := bundle.source
this.data := bundle.data
}
}
class Uncoalescer(config: CoalescerConfig) extends Module { class Uncoalescer(config: CoalescerConfig) extends Module {
// notes to hansung: // notes to hansung:
// val numLanes: Int, <-> config.NUM_LANES // val numLanes: Int, <-> config.NUM_LANES
@@ -884,15 +878,14 @@ class Uncoalescer(config: CoalescerConfig) extends Module {
val coalReqValid = Input(Bool()) val coalReqValid = Input(Bool())
// FIXME: receive ReqQueueEntry and construct newEntry inside uncoalescer // FIXME: receive ReqQueueEntry and construct newEntry inside uncoalescer
val newEntry = Input(inflightTable.entryT.cloneType) val newEntry = Input(inflightTable.entryT.cloneType)
val coalResp = Flipped(Decoupled(new CoalescedResponseBundle(config))) val coalResp = Flipped(Decoupled(new CoalescedResponse(config)))
val uncoalResps = Output( val uncoalResps = Output(
Vec( Vec(
config.numLanes, config.numLanes,
Vec( Vec(
config.queueDepth, config.queueDepth,
ValidIO( ValidIO(
new RespQueueEntry(log2Ceil(config.numOldSrcIds), config.wordSizeWidth, new NonCoalescedResponse(config)
config.wordSizeInBytes * 8)
) )
) )
) )
@@ -1853,25 +1846,20 @@ class CoalescerXbar(config: CoalescerConfig) (implicit p: Parameters) extends La
val node = TLIdentityNode() val node = TLIdentityNode()
node :=* outputXbar.node node :=* outputXbar.node
val nonCoalEntryT = new ReqQueueEntry( val nonCoalEntryT = new Request(
log2Ceil(config.numOldSrcIds), log2Ceil(config.numOldSrcIds),
config.wordSizeWidth, config.wordSizeWidth,
config.addressWidth, config.addressWidth,
config.wordSizeInBytes * 8 config.wordSizeInBytes * 8
) )
val coalEntryT = new ReqQueueEntry( val coalEntryT = new Request(
log2Ceil(config.numOldSrcIds), log2Ceil(config.numOldSrcIds),
log2Ceil(config.maxCoalLogSize), log2Ceil(config.maxCoalLogSize),
config.addressWidth, config.addressWidth,
(1 << config.maxCoalLogSize) * 8 (1 << config.maxCoalLogSize) * 8
) )
val respNonCoalEntryT = new RespQueueEntry( val respNonCoalEntryT = new NonCoalescedResponse(config)
log2Ceil(config.numOldSrcIds), val respCoalBundleT = new CoalescedResponse(config)
config.wordSizeWidth,
config.wordSizeInBytes * 8
)
val respCoalBundleT = new CoalescedResponseBundle(config)
lazy val module = new CoalescerXbarImpl( lazy val module = new CoalescerXbarImpl(
@@ -1883,10 +1871,10 @@ class CoalescerXbar(config: CoalescerConfig) (implicit p: Parameters) extends La
class CoalescerXbarImpl(outer: CoalescerXbar, class CoalescerXbarImpl(outer: CoalescerXbar,
config: CoalescerConfig, config: CoalescerConfig,
nonCoalEntryT: ReqQueueEntry, nonCoalEntryT: Request,
coalEntryT: ReqQueueEntry, coalEntryT: Request,
respNonCoalEntryT: RespQueueEntry, respNonCoalEntryT: Response,
respCoalBundleT: CoalescedResponseBundle respCoalBundleT: CoalescedResponse
) extends LazyModuleImp(outer){ ) extends LazyModuleImp(outer){