Make MemTraceDriver generate word-sized requests

Try to model the core's behavior which accesses cache in word granularity.  This
also simplifies the coalescer design as coalescer no longer needs to uncoalesce
response data chunk into single bytes (and therefore fewer muxes).
This commit is contained in:
Hansung Kim
2023-04-22 21:04:45 -07:00
parent c5d722112b
commit 90a797e71a

View File

@@ -520,7 +520,6 @@ class InflightCoalReqTableEntry(
val size = UInt(sizeBits.W) val size = UInt(sizeBits.W)
} }
class PerLane extends Bundle { class PerLane extends Bundle {
// FIXME: if numPerLaneReqs != 2 ** sourceWidth, we need to store srcId as well
val reqs = Vec(numPerLaneReqs, new PerCoreReq) val reqs = Vec(numPerLaneReqs, new PerCoreReq)
} }
// sourceId of the coalesced response that just came back. This will be the // sourceId of the coalesced response that just came back. This will be the
@@ -674,7 +673,7 @@ trait HasTraceLine {
class TraceLine extends Bundle with HasTraceLine { class TraceLine extends Bundle with HasTraceLine {
val valid = Bool() val valid = Bool()
val source = UInt(32.W) val source = UInt(32.W)
val address = UInt(64.W) val address = UInt(64.W) // FIXME: in Verilog this is the same as data width
val is_store = Bool() val is_store = Bool()
val size = UInt(8.W) // this is log2(bytesize) as in TL A bundle val size = UInt(8.W) // this is log2(bytesize) as in TL A bundle
val data = UInt(64.W) val data = UInt(64.W)
@@ -683,9 +682,7 @@ class TraceLine extends Bundle with HasTraceLine {
class MemTraceDriverImp(outer: MemTraceDriver, numLanes: Int, traceFile: String) class MemTraceDriverImp(outer: MemTraceDriver, numLanes: Int, traceFile: String)
extends LazyModuleImp(outer) extends LazyModuleImp(outer)
with UnitTestModule { with UnitTestModule {
val sim = Module( val sim = Module(new SimMemTrace(traceFile, numLanes))
new SimMemTrace(traceFile, numLanes)
)
sim.io.clock := clock sim.io.clock := clock
sim.io.reset := reset.asBool sim.io.reset := reset.asBool
sim.io.trace_read.ready := true.B sim.io.trace_read.ready := true.B
@@ -720,21 +717,54 @@ class MemTraceDriverImp(outer: MemTraceDriver, numLanes: Int, traceFile: String)
Cat(8.U(4.W), addr(27, 0)) Cat(8.U(4.W), addr(27, 0))
} }
// Generate TL requests according to the trace line. // Generate TL requests corresponding to the trace lines
(outer.laneNodes zip laneReqs).foreach { case (node, req) => (outer.laneNodes zip laneReqs).foreach { case (node, req) =>
val (tlOut, edge) = node.out(0) // Core only makes accesses of granularity larger than a word, so we want
// the trace driver to act so as well.
// That means if req.size is smaller than word size, we need to pad data
// with zeros to generate a word-size request, and set mask accordingly.
val offsetInWord = req.address % WordSizeInBytes().U
val subword = req.size < log2Ceil(WordSizeInBytes()).U
val mask = Wire(UInt(WordSizeInBytes().W))
val wordData = Wire(UInt((WordSizeInBytes() * 8).W))
val sizeInBytes = Wire(UInt((sizeW + 1).W))
sizeInBytes := (1.U) << req.size
mask := Mux(subword, (~((~0.U(64.W)) << sizeInBytes)) << offsetInWord, ~0.U)
wordData := Mux(subword, req.data << (offsetInWord * 8.U), req.data)
val wordAlignedAddress = req.address & ~((1 << log2Ceil(WordSizeInBytes())) - 1).U(addrW.W)
assert(
req.size <= log2Ceil(WordSizeInBytes()).U,
s"trace driver currently does not support access sizes larger than word size (${WordSizeInBytes()})"
)
val wordAlignedSize = 2.U // FIXME: hardcoded
// when(req.valid && subword) {
// printf(
// "address=%x, size=%d, data=%x, addressMask=%x, wordAlignedAddress=%x, mask=%x, wordData=%x\n",
// req.address,
// req.size,
// req.data,
// ~((1 << log2Ceil(WordSizeInBytes())) - 1).U(addrW.W),
// wordAlignedAddress,
// mask,
// wordData
// )
// }
val (tlOut, edge) = node.out(0)
val (plegal, pbits) = edge.Put( val (plegal, pbits) = edge.Put(
fromSource = sourceIdCounter, fromSource = sourceIdCounter,
toAddress = hashToValidPhyAddr(req.address), toAddress = hashToValidPhyAddr(wordAlignedAddress),
lgSize = req.size, // trace line already holds log2(size) lgSize = wordAlignedSize, // trace line already holds log2(size)
// data should be aligned to beatBytes // data should be aligned to beatBytes
data = (req.data << (8.U * (req.address % edge.manager.beatBytes.U))) data = (wordData << (8.U * (wordAlignedAddress % edge.manager.beatBytes.U)))
) )
val (glegal, gbits) = edge.Get( val (glegal, gbits) = edge.Get(
fromSource = sourceIdCounter, fromSource = sourceIdCounter,
toAddress = hashToValidPhyAddr(req.address), toAddress = hashToValidPhyAddr(wordAlignedAddress),
lgSize = req.size lgSize = wordAlignedSize
) )
val legal = Mux(req.is_store, plegal, glegal) val legal = Mux(req.is_store, plegal, glegal)
val bits = Mux(req.is_store, pbits, gbits) val bits = Mux(req.is_store, pbits, gbits)
@@ -796,7 +826,7 @@ class SimMemTrace(filename: String, numLanes: Int)
// These names have to match declarations in the Verilog code, eg. // These names have to match declarations in the Verilog code, eg.
// trace_read_address. // trace_read_address.
val trace_read = new Bundle { // FIXME: can't use HasTraceLine because this doesn't have source val trace_read = new Bundle { // can't use HasTraceLine because this doesn't have source
val ready = Input(Bool()) val ready = Input(Bool())
val valid = Output(UInt(numLanes.W)) val valid = Output(UInt(numLanes.W))
// Chisel can't interface with Verilog 2D port, so flatten all lanes into // Chisel can't interface with Verilog 2D port, so flatten all lanes into