Relay full trace line info to DPI
This commit is contained in:
@@ -124,14 +124,18 @@ extern "C" void memtracelogger_init(const char *filename) {
|
|||||||
extern "C" void memtracelogger_log(unsigned char trace_log_valid,
|
extern "C" void memtracelogger_log(unsigned char trace_log_valid,
|
||||||
unsigned long trace_log_cycle,
|
unsigned long trace_log_cycle,
|
||||||
unsigned long trace_log_address,
|
unsigned long trace_log_address,
|
||||||
unsigned int trace_log_lane_id,
|
int trace_log_lane_id,
|
||||||
|
unsigned char trace_log_is_store,
|
||||||
|
int trace_log_size,
|
||||||
|
unsigned long trace_log_data,
|
||||||
unsigned char *trace_log_ready) {
|
unsigned char *trace_log_ready) {
|
||||||
// printf("memtrace_query(cycle=%ld, tid=%d)\n", trace_read_cycle,
|
// printf("memtrace_query(cycle=%ld, tid=%d)\n", trace_read_cycle,
|
||||||
// trace_read_lane_id);
|
// trace_read_lane_id);
|
||||||
*trace_log_ready = 1;
|
*trace_log_ready = 1;
|
||||||
|
|
||||||
if (trace_log_valid) {
|
if (trace_log_valid) {
|
||||||
printf("%s: [%lu] valid: address=0x%lx, tid=%u\n", __func__,
|
printf("%s: [%lu] valid: address=%lx, tid=%u, size=%d\n", __func__,
|
||||||
trace_log_cycle, trace_log_address, trace_log_lane_id);
|
trace_log_cycle, trace_log_address, trace_log_lane_id,
|
||||||
|
trace_log_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIXME hardcoded
|
||||||
`define DATA_WIDTH 64
|
`define DATA_WIDTH 64
|
||||||
`define MAX_NUM_LANES 32
|
`define MAX_NUM_LANES 32
|
||||||
`define LOGSIZE_WIDTH 32
|
`define LOGSIZE_WIDTH 32
|
||||||
@@ -81,7 +82,6 @@ module SimMemTrace #(parameter FILENAME = "undefined", NUM_LANES = 4) (
|
|||||||
memtrace_init(FILENAME);
|
memtrace_init(FILENAME);
|
||||||
end
|
end
|
||||||
|
|
||||||
// Evaluate the signals on the positive edge
|
|
||||||
always @(posedge clock) begin
|
always @(posedge clock) begin
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
for (integer tid = 0; tid < NUM_LANES; tid = tid + 1) begin
|
for (integer tid = 0; tid < NUM_LANES; tid = tid + 1) begin
|
||||||
|
|||||||
@@ -607,6 +607,8 @@ class MemTraceDriver(numLanes: Int = 4, filename: String = "vecadd.core1.thread4
|
|||||||
lazy val module = new MemTraceDriverImp(this, numLanes, filename)
|
lazy val module = new MemTraceDriverImp(this, numLanes, filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this is replicated in sim.io.trace_read and sim.io.trace_log; make it
|
||||||
|
// into a trait
|
||||||
class TraceReq extends Bundle {
|
class TraceReq extends Bundle {
|
||||||
val valid = Bool()
|
val valid = Bool()
|
||||||
val address = UInt(64.W)
|
val address = UInt(64.W)
|
||||||
@@ -664,7 +666,7 @@ class MemTraceDriverImp(outer: MemTraceDriver, numLanes: Int, traceFile: String)
|
|||||||
val (glegal, gbits) = edge.Get(
|
val (glegal, gbits) = edge.Get(
|
||||||
fromSource = sourceIdCounter,
|
fromSource = sourceIdCounter,
|
||||||
toAddress = hashToValidPhyAddr(req.address),
|
toAddress = hashToValidPhyAddr(req.address),
|
||||||
lgSize = Log2(size),
|
lgSize = Log2(size)
|
||||||
)
|
)
|
||||||
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)
|
||||||
@@ -755,6 +757,11 @@ class MemTraceLogger(numLanes: Int = 4, filename: String = "vecadd.core1.thread4
|
|||||||
|
|
||||||
val laneReqs = Wire(Vec(numLanes, new TraceReq))
|
val laneReqs = Wire(Vec(numLanes, new TraceReq))
|
||||||
|
|
||||||
|
assert(
|
||||||
|
numLanes == node.in.length,
|
||||||
|
"`numLanes` does not match the number of TL edges connected to the MemTraceLogger"
|
||||||
|
)
|
||||||
|
|
||||||
// snoop on the TileLink edges to log traffic
|
// snoop on the TileLink edges to log traffic
|
||||||
((node.in zip node.out) zip laneReqs).foreach { case (((tlIn, _), (tlOut, _)), req) =>
|
((node.in zip node.out) zip laneReqs).foreach { case (((tlIn, _), (tlOut, _)), req) =>
|
||||||
tlOut.a <> tlIn.a
|
tlOut.a <> tlIn.a
|
||||||
@@ -765,7 +772,7 @@ class MemTraceLogger(numLanes: Int = 4, filename: String = "vecadd.core1.thread4
|
|||||||
req.address := tlIn.a.bits.address
|
req.address := tlIn.a.bits.address
|
||||||
req.data := tlIn.a.bits.data
|
req.data := tlIn.a.bits.data
|
||||||
req.is_store := false.B
|
req.is_store := false.B
|
||||||
when (tlIn.a.bits.opcode === 0.U || tlIn.a.bits.opcode === 1.U) {
|
when(tlIn.a.bits.opcode === 0.U || tlIn.a.bits.opcode === 1.U) {
|
||||||
// 0: PutFullData, 1: PutPartialData
|
// 0: PutFullData, 1: PutPartialData
|
||||||
req.is_store := true.B
|
req.is_store := true.B
|
||||||
}.elsewhen(tlIn.a.bits.opcode === 4.U) {
|
}.elsewhen(tlIn.a.bits.opcode === 4.U) {
|
||||||
@@ -777,19 +784,36 @@ class MemTraceLogger(numLanes: Int = 4, filename: String = "vecadd.core1.thread4
|
|||||||
}
|
}
|
||||||
req.size := tlIn.a.bits.size
|
req.size := tlIn.a.bits.size
|
||||||
|
|
||||||
// responses on TL D channel
|
when(req.valid) {
|
||||||
// TODO
|
printf("======== MemTraceLogger: req.size=%d\n", req.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// responses on TL D channel
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clunky workaround of the fact that Chisel doesn't allow partial
|
||||||
|
// assignment to a bitfield range of a wide signal.
|
||||||
val laneValid = Wire(Vec(numLanes, Bool()))
|
val laneValid = Wire(Vec(numLanes, Bool()))
|
||||||
val laneAddress = Wire(Vec(numLanes, UInt(64.W))) // FIXME: hardcoded
|
val laneAddress = Wire(Vec(numLanes, chiselTypeOf(laneReqs(0).address)))
|
||||||
|
val laneIsStore = Wire(Vec(numLanes, chiselTypeOf(laneReqs(0).is_store)))
|
||||||
|
val laneSize = Wire(Vec(numLanes, chiselTypeOf(laneReqs(0).size)))
|
||||||
|
val laneData = Wire(Vec(numLanes, chiselTypeOf(laneReqs(0).data)))
|
||||||
laneReqs.zipWithIndex.foreach { case (req, i) =>
|
laneReqs.zipWithIndex.foreach { case (req, i) =>
|
||||||
laneValid(i) := req.valid
|
laneValid(i) := req.valid
|
||||||
laneAddress(i) := req.address
|
laneAddress(i) := req.address
|
||||||
|
laneIsStore(i) := req.is_store
|
||||||
|
laneSize(i) := req.size
|
||||||
|
laneData(i) := req.data
|
||||||
}
|
}
|
||||||
// flatten per-lane signals to the Verilog blackbox input
|
// flatten per-lane signals to the Verilog blackbox input
|
||||||
sim.io.trace_log.valid := laneValid.asUInt
|
sim.io.trace_log.valid := laneValid.asUInt
|
||||||
sim.io.trace_log.address := laneAddress.asUInt
|
sim.io.trace_log.address := laneAddress.asUInt
|
||||||
|
sim.io.trace_log.is_store := laneIsStore.asUInt
|
||||||
|
sim.io.trace_log.size := laneSize.asUInt
|
||||||
|
sim.io.trace_log.data := laneData.asUInt
|
||||||
|
|
||||||
|
assert(sim.io.trace_log.ready === true.B, "MemTraceLogger is expected to be always ready")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -802,17 +826,16 @@ class SimMemTraceLogger(filename: String, numLanes: Int)
|
|||||||
val clock = Input(Clock())
|
val clock = Input(Clock())
|
||||||
val reset = Input(Bool())
|
val reset = Input(Bool())
|
||||||
|
|
||||||
// Chisel can't interface with Verilog 2D port, so flatten all lanes into
|
|
||||||
// single wide 1D array.
|
|
||||||
val trace_log = new Bundle {
|
val trace_log = new Bundle {
|
||||||
val valid = Input(UInt(numLanes.W))
|
val valid = Input(UInt(numLanes.W))
|
||||||
val address = Input(UInt((64 * numLanes).W))
|
// Chisel can't interface with Verilog 2D port, so flatten all lanes into
|
||||||
// val ready = Output(Bool())
|
// single wide 1D array.
|
||||||
// TODO: assumes 64-bit address.
|
// TODO: assumes 64-bit address.
|
||||||
// val is_store = Output(UInt(numLanes.W))
|
val address = Input(UInt((64 * numLanes).W))
|
||||||
// val size = Output(UInt((8 * numLanes).W))
|
val is_store = Input(UInt(numLanes.W))
|
||||||
// val data = Output(UInt((64 * numLanes).W))
|
val size = Input(UInt((32 * numLanes).W))
|
||||||
// val finished = Output(Bool())
|
val data = Input(UInt((64 * numLanes).W))
|
||||||
|
val ready = Output(Bool())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user