Connect TL edge data to SimMemTraceLogger

TODO: since TileLink rounds all address down to a multiple of its beat
size (8 in the current code), we can't directly compare the memory trace
input to its output.  Need to take masks into account.
This commit is contained in:
Hansung Kim
2023-04-10 20:24:27 -07:00
parent af29acdcda
commit b53711965e
2 changed files with 55 additions and 24 deletions

View File

@@ -3,7 +3,7 @@
#include <svdpi.h>
#endif
#include <string>
#include <string.h>
#include <cstring>
#include <cstdio>
#include <cassert>
#include <unistd.h>
@@ -33,10 +33,10 @@ MemTraceLogger::~MemTraceLogger() {
// Parse trace file in its entirety and store it into internal structure.
// TODO: might block for a long time when the trace gets big, check if need to
// be broken down
void MemTraceReader::parse() {
void MemTraceLogger::parse() {
MemTraceLine line;
printf("MemTraceReader: started parsing\n");
printf("MemTraceLogger: started parsing\n");
while (infile >> line.cycle >> line.loadstore >> line.core_id >>
line.lane_id >> std::hex >> line.address >> line.data >> std::dec >>
@@ -46,13 +46,13 @@ void MemTraceReader::parse() {
}
read_pos = trace.cbegin();
printf("MemTraceReader: finished parsing\n");
printf("MemTraceLogger: finished parsing\n");
}
// Try to read a memory request that might have happened at a given cycle, on a
// given SIMD lane (= "thread"). In case no request happened at that point,
// return an empty line with .valid = false.
MemTraceLine MemTraceReader::read_trace_at(const long cycle,
MemTraceLine MemTraceLogger::read_trace_at(const long cycle,
const int lane_id) {
MemTraceLine line;
line.valid = false;
@@ -120,8 +120,17 @@ extern "C" void memtracelogger_init(const char *filename) {
}
// TODO: accept core_id as well
extern "C" void memtracelogger_log(unsigned char *trace_log_ready) {
extern "C" void memtracelogger_log(unsigned char trace_log_valid,
unsigned long trace_log_cycle,
unsigned long trace_log_address,
unsigned int trace_log_lane_id,
unsigned char *trace_log_ready) {
// printf("memtrace_query(cycle=%ld, tid=%d)\n", trace_read_cycle,
// trace_read_lane_id);
*trace_log_ready = 1;
if (trace_log_valid) {
printf("%s: [%lu] valid: address=0x%lx, tid=%u\n", __func__,
trace_log_cycle, trace_log_address, trace_log_lane_id);
}
}

View File

@@ -727,7 +727,9 @@ class SimMemTrace(filename: String, numLanes: Int)
addResource("/csrc/SimMemTrace.h")
}
class MemTraceLogger(numLanes: Int = 4, filename: String = "vecadd.core1.thread4.trace")(implicit p: Parameters) extends LazyModule {
class MemTraceLogger(numLanes: Int = 4, filename: String = "vecadd.core1.thread4.trace")(implicit
p: Parameters
) extends LazyModule {
val node = TLIdentityNode()
// val beatBytes = 8 // FIXME: hardcoded
@@ -751,11 +753,30 @@ class MemTraceLogger(numLanes: Int = 4, filename: String = "vecadd.core1.thread4
sim.io.clock := clock
sim.io.reset := reset.asBool
(node.in zip node.out).foreach { case ((tlIn, _), (tlOut, _)) =>
val laneReqs = Wire(Vec(numLanes, new TraceReq))
val laneValid = Wire(Vec(numLanes, Bool()))
val laneAddress = Wire(Vec(numLanes, UInt(64.W))) // FIXME: hardcoded
// snoop on the TileLink edges to log traffic
((node.in zip node.out) zip laneReqs).foreach { case (((tlIn, _), (tlOut, _)), req) =>
tlOut.a <> tlIn.a
tlIn.d <> tlOut.d
req.valid := tlIn.a.valid
req.address := tlIn.a.bits.address
req.data := tlIn.a.bits.data
req.is_store := false.B // FIXME: take is_store from TL
req.mask := tlIn.a.bits.mask
}
laneReqs.zipWithIndex.foreach { case (req, i) =>
laneValid(i) := req.valid.asUInt
laneAddress(i) := req.address
}
// flatten per-lane signals to the Verilog blackbox input
sim.io.trace_log.valid := laneValid.asUInt
sim.io.trace_log.address := laneAddress.asUInt
// io.finished := sim.io.trace_read.finished
}
}
@@ -769,18 +790,18 @@ class SimMemTraceLogger(filename: String, numLanes: Int)
val clock = Input(Clock())
val reset = Input(Bool())
// val trace_read = new Bundle {
// val ready = Input(Bool())
// val valid = Output(UInt(numLanes.W))
// // Chisel can't interface with Verilog 2D port, so flatten all lanes into
// // single wide 1D array.
// // TODO: assumes 64-bit address.
// val address = Output(UInt((64 * numLanes).W))
// val is_store = Output(UInt(numLanes.W))
// val store_mask = Output(UInt((8 * numLanes).W))
// val data = Output(UInt((64 * numLanes).W))
// val finished = Output(Bool())
// }
// Chisel can't interface with Verilog 2D port, so flatten all lanes into
// single wide 1D array.
val trace_log = new Bundle {
val valid = Input(UInt(numLanes.W))
val address = Input(UInt((64 * numLanes).W))
// val ready = Output(Bool())
// TODO: assumes 64-bit address.
// val is_store = Output(UInt(numLanes.W))
// val store_mask = Output(UInt((8 * numLanes).W))
// val data = Output(UInt((64 * numLanes).W))
// val finished = Output(Bool())
}
})
addResource("/vsrc/SimMemTraceLogger.v")
@@ -794,17 +815,18 @@ class SimMemTraceLogger(filename: String, numLanes: Int)
class TLRAMCoalescerLogger(implicit p: Parameters) extends LazyModule {
// TODO: use parameters for numLanes
val numLanes = 4
val coal = LazyModule(new CoalescingUnit(numLanes))
// val coal = LazyModule(new CoalescingUnit(numLanes))
val driver = LazyModule(new MemTraceDriver(numLanes))
val logger = LazyModule(new MemTraceLogger(numLanes + 1))
val rams = Seq.fill(numLanes + 1)( // +1 for coalesced edge
val logger = LazyModule(new MemTraceLogger(numLanes))
val rams = Seq.fill(numLanes)( // +1 for coalesced edge
LazyModule(
// FIXME: properly propagate beatBytes?
new TLRAM(address = AddressSet(0x0000, 0xffffff), beatBytes = 8)
)
)
logger.node :=* coal.node :=* driver.node
// logger.node :=* coal.node :=* driver.node
logger.node :=* driver.node
rams.foreach { r => r.node := logger.node }
lazy val module = new Impl