Write simple next-empty-entry finding logic
This commit is contained in:
@@ -13,7 +13,7 @@ import freechips.rocketchip.unittest._
|
|||||||
class CoalescingUnit(numLanes: Int = 1)(implicit p: Parameters)
|
class CoalescingUnit(numLanes: Int = 1)(implicit p: Parameters)
|
||||||
extends LazyModule {
|
extends LazyModule {
|
||||||
|
|
||||||
// Describes uncoalesced memory request that originated from a single lane
|
// Describes original, uncoalesced memory requests on each lane
|
||||||
class UncoalReq(val sourceWidth: Int, val addressWidth: Int) extends Bundle {
|
class UncoalReq(val sourceWidth: Int, val addressWidth: Int) extends Bundle {
|
||||||
val source = UInt(sourceWidth.W)
|
val source = UInt(sourceWidth.W)
|
||||||
val address = UInt(addressWidth.W)
|
val address = UInt(addressWidth.W)
|
||||||
@@ -21,8 +21,8 @@ class CoalescingUnit(numLanes: Int = 1)(implicit p: Parameters)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Identity node that captures the incoming TL requests and passes them
|
// Identity node that captures the incoming TL requests and passes them
|
||||||
// through the other end, dropping coalesced requests. This is what the
|
// through the other end, dropping coalesced requests. This node is what
|
||||||
// upstream node will connect to.
|
// will be visible from the external nodes.
|
||||||
val node = TLIdentityNode()
|
val node = TLIdentityNode()
|
||||||
|
|
||||||
// Number of maximum in-flight coalesced requests. The upper bound of this
|
// Number of maximum in-flight coalesced requests. The upper bound of this
|
||||||
@@ -30,8 +30,6 @@ class CoalescingUnit(numLanes: Int = 1)(implicit p: Parameters)
|
|||||||
val numInflightCoalRequests = 4
|
val numInflightCoalRequests = 4
|
||||||
|
|
||||||
// Master node that actually generates coalesced requests.
|
// Master node that actually generates coalesced requests.
|
||||||
// This and the IdentityNode will be the two outward-facing nodes that the
|
|
||||||
// downstream, either L1 or the system bus, will connect to.
|
|
||||||
protected val coalParam = Seq(
|
protected val coalParam = Seq(
|
||||||
TLMasterParameters.v1(
|
TLMasterParameters.v1(
|
||||||
name = "CoalescerNode",
|
name = "CoalescerNode",
|
||||||
@@ -137,26 +135,23 @@ class CoalescingUnit(numLanes: Int = 1)(implicit p: Parameters)
|
|||||||
new InflightCoalReqTable(numLanes, sourceWidth, numInflightCoalRequests)
|
new InflightCoalReqTable(numLanes, sourceWidth, numInflightCoalRequests)
|
||||||
)
|
)
|
||||||
val tableEntry = Wire(inflightCoalReqTableEntry)
|
val tableEntry = Wire(inflightCoalReqTableEntry)
|
||||||
// TODO: bogus fromLane
|
tableEntry.respSourceId := coalSourceId
|
||||||
|
// TODO: bogus fromLane. Take the lowest numLane bits off of coalSourceId
|
||||||
tableEntry.fromLane := coalSourceId & ((2 << numLanes) - 1).U
|
tableEntry.fromLane := coalSourceId & ((2 << numLanes) - 1).U
|
||||||
// FIXME: I'm positive this is not the right way to do this
|
// FIXME: I'm positive this is not the right way to do this
|
||||||
tableEntry.sourceIds(0) := 0.U
|
tableEntry.reqSourceIds(0) := 0.U
|
||||||
tableEntry.sourceIds(1) := 0.U
|
tableEntry.reqSourceIds(1) := 0.U
|
||||||
tableEntry.sourceIds(2) := 0.U
|
tableEntry.reqSourceIds(2) := 0.U
|
||||||
tableEntry.sourceIds(3) := 0.U
|
tableEntry.reqSourceIds(3) := 0.U
|
||||||
dontTouch(tableEntry)
|
dontTouch(tableEntry)
|
||||||
|
|
||||||
inflightCoalReqTable.io.enq.valid := coalReqValid
|
inflightCoalReqTable.io.enq.valid := coalReqValid
|
||||||
inflightCoalReqTable.io.enq.bits := tableEntry
|
inflightCoalReqTable.io.enq.bits := tableEntry
|
||||||
inflightCoalReqTable.io.deq.ready := false.B
|
|
||||||
|
|
||||||
dontTouch(inflightCoalReqTable.io.deq.valid)
|
// Look up the table with incoming coalesced responses
|
||||||
dontTouch(inflightCoalReqTable.io.deq.bits)
|
inflightCoalReqTable.io.lookup.valid := tlCoal.d.valid
|
||||||
|
inflightCoalReqTable.io.lookup.bits := tlCoal.d.bits.source
|
||||||
|
|
||||||
// Now, for the coalescer response flow, instantiate a reservation
|
|
||||||
// station-like structure that records for each unanswered coalesced
|
|
||||||
// requests which lane the request originated from, what their original
|
|
||||||
// sourceId were, etc.
|
|
||||||
// FIXME: Reuse ShiftQueue(coalRegEntry) for now, but swap out to actual
|
// FIXME: Reuse ShiftQueue(coalRegEntry) for now, but swap out to actual
|
||||||
// table structure
|
// table structure
|
||||||
// val inflightCoalReqTable = Reg(
|
// val inflightCoalReqTable = Reg(
|
||||||
@@ -189,32 +184,69 @@ class CoalescingUnit(numLanes: Int = 1)(implicit p: Parameters)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InflightCoalReqTable is a reservation station-like structure that records
|
||||||
|
// for each unanswered coalesced request which lane the request originated
|
||||||
|
// from, what their original sourceId were, etc. We use this info to split
|
||||||
|
// the coalesced response back to individual responses for each lanes with
|
||||||
|
// the right metadata.
|
||||||
class InflightCoalReqTable(
|
class InflightCoalReqTable(
|
||||||
val numLanes: Int,
|
val numLanes: Int,
|
||||||
val sourceWidth: Int,
|
val sourceWidth: Int,
|
||||||
val entries: Int = 4
|
val entries: Int
|
||||||
) extends Module {
|
) extends Module {
|
||||||
private val inflightCoalReqEntryT =
|
private val inflightCoalReqEntryT =
|
||||||
new InflightCoalReqTableEntry(numLanes, sourceWidth)
|
new InflightCoalReqTableEntry(numLanes, sourceWidth)
|
||||||
|
|
||||||
val io = IO(new Bundle {
|
val io = IO(new Bundle {
|
||||||
val enq = Flipped(EnqIO(inflightCoalReqEntryT))
|
val enq = Flipped(EnqIO(inflightCoalReqEntryT))
|
||||||
val deq = Flipped(DeqIO(inflightCoalReqEntryT))
|
val lookup = Flipped(Decoupled(UInt(sourceWidth.W)))
|
||||||
})
|
})
|
||||||
|
|
||||||
val table = Module(new Queue(inflightCoalReqEntryT, entries))
|
// val table = Module(new Queue(inflightCoalReqEntryT, entries))
|
||||||
table.io.enq <> io.enq
|
// table.io.enq <> io.enq
|
||||||
io.deq <> table.io.deq
|
// table.io.deq.ready := false.B
|
||||||
|
|
||||||
|
io.enq.ready := true.B
|
||||||
|
io.lookup.ready := true.B
|
||||||
|
|
||||||
|
val table = Mem(
|
||||||
|
entries,
|
||||||
|
new Bundle {
|
||||||
|
val valid = Bool()
|
||||||
|
val entry = new InflightCoalReqTableEntry(numLanes, sourceWidth)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
val full = Wire(Bool())
|
||||||
|
full := (0 until entries)
|
||||||
|
.map { i => table(i).valid }
|
||||||
|
.reduce { (v0, v1) => v0 & v1 }
|
||||||
|
|
||||||
|
// Instantiate simple cascade of muxes that indicate what is the current
|
||||||
|
// minimum index that has an empty spot in the table.
|
||||||
|
val cascadeMinIndex = Seq.tabulate(entries) { i => WireInit(i.U) }
|
||||||
|
(0 until entries - 1).reverse.foreach { i =>
|
||||||
|
val empty = !table(i).valid
|
||||||
|
assert(i + 1 < entries)
|
||||||
|
// If entry with a lower index is empty, it always takes priority
|
||||||
|
cascadeMinIndex(i) := Mux(empty, i.U, cascadeMinIndex(i + 1))
|
||||||
|
}
|
||||||
|
val chosenEmptyIndex = cascadeMinIndex(0)
|
||||||
|
dontTouch(chosenEmptyIndex)
|
||||||
|
dontTouch(full)
|
||||||
}
|
}
|
||||||
|
|
||||||
class InflightCoalReqTableEntry(val numLanes: Int, val sourceWidth: Int)
|
class InflightCoalReqTableEntry(val numLanes: Int, val sourceWidth: Int)
|
||||||
extends Bundle {
|
extends Bundle {
|
||||||
|
// sourceId of the coalesced response that just came back. This will be the
|
||||||
|
// key that queries the table.
|
||||||
|
val respSourceId = UInt(sourceWidth.W)
|
||||||
// Bit flags that show which lanes got coalesced into this request
|
// Bit flags that show which lanes got coalesced into this request
|
||||||
val fromLane = UInt(numLanes.W)
|
val fromLane = UInt(numLanes.W)
|
||||||
// sourceId of the original requests before getting coalesced. We need to
|
// sourceId of the original requests before getting coalesced. We need to
|
||||||
// know this in order to respond to the original per-lane TL requests with
|
// remember this in order to answer the right outstanding TL request on each
|
||||||
// matching sourceIds
|
// lane.
|
||||||
val sourceIds = Vec(numLanes, UInt(sourceWidth.W))
|
val reqSourceIds = Vec(numLanes, UInt(sourceWidth.W))
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemTraceDriver(numLanes: Int = 1)(implicit p: Parameters)
|
class MemTraceDriver(numLanes: Int = 1)(implicit p: Parameters)
|
||||||
|
|||||||
Reference in New Issue
Block a user