diff --git a/src/main/resources/csrc/SimMemTrace.h b/src/main/resources/csrc/SimMemTrace.h index fef1ad8..adc5ef0 100644 --- a/src/main/resources/csrc/SimMemTrace.h +++ b/src/main/resources/csrc/SimMemTrace.h @@ -5,10 +5,11 @@ struct MemTraceLine { bool valid = false; long cycle = 0; - bool is_store = 0; int core_id = 0; int lane_id = 0; + int source = 0; unsigned long address = 0; + bool is_store = 0; unsigned long data = 0; int log_data_size = 0; }; @@ -50,8 +51,9 @@ extern "C" int memtracelogger_init(int is_response, const char *filename); extern "C" void memtracelogger_log(int handle, unsigned char trace_log_valid, unsigned long trace_log_cycle, - unsigned long trace_log_address, int trace_log_lane_id, + int trace_log_source, + unsigned long trace_log_address, unsigned char trace_log_is_store, int trace_log_size, unsigned long trace_log_data, diff --git a/src/main/resources/csrc/SimMemTraceLogger.cc b/src/main/resources/csrc/SimMemTraceLogger.cc index c4cfde9..75a1822 100644 --- a/src/main/resources/csrc/SimMemTraceLogger.cc +++ b/src/main/resources/csrc/SimMemTraceLogger.cc @@ -35,9 +35,9 @@ MemTraceWriter::~MemTraceWriter() { } void MemTraceWriter::write_line_to_trace(const MemTraceLine line) { - fprintf(outfile, "%ld %s %d %d 0x%lx 0x%lx %u\n", line.cycle, + fprintf(outfile, "%ld %s %d %d %d, 0x%lx 0x%lx %u\n", line.cycle, (line.is_store ? "STORE" : "LOAD"), line.core_id, line.lane_id, - line.address, line.data, (1u << line.log_data_size)); + line.source, line.address, line.data, (1u << line.log_data_size)); } // Returns the "handle" ID for this particular logger instance. @@ -70,13 +70,16 @@ extern "C" int memtracelogger_init(int is_response, const char *filename) { // This is used to log both TileLink A and D channels. // TODO: accept core_id as well -extern "C" void -memtracelogger_log(int handle, - unsigned char trace_log_valid, unsigned long trace_log_cycle, - unsigned long trace_log_address, 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) { +extern "C" void memtracelogger_log(int handle, + unsigned char trace_log_valid, + unsigned long trace_log_cycle, + int trace_log_lane_id, + int trace_log_source, + unsigned long trace_log_address, + unsigned char trace_log_is_store, + int trace_log_size, + unsigned long trace_log_data, + unsigned char *trace_log_ready) { // printf("memtrace_query(cycle=%ld, tid=%d)\n", trace_read_cycle, // trace_read_lane_id); *trace_log_ready = 1; @@ -90,10 +93,11 @@ memtracelogger_log(int handle, MemTraceLine line{.valid = (trace_log_valid == 1), .cycle = static_cast(trace_log_cycle), - .is_store = (trace_log_is_store == 1), .core_id = 0, // TODO support multicores .lane_id = trace_log_lane_id, + .source = trace_log_source, .address = trace_log_address, + .is_store = (trace_log_is_store == 1), .data = trace_log_data, .log_data_size = trace_log_size}; diff --git a/src/main/resources/vsrc/SimMemTrace.v b/src/main/resources/vsrc/SimMemTrace.v index a805130..f21aeec 100644 --- a/src/main/resources/vsrc/SimMemTrace.v +++ b/src/main/resources/vsrc/SimMemTrace.v @@ -15,7 +15,7 @@ import "DPI-C" function void memtrace_query ( input bit trace_read_ready, input longint trace_read_cycle, - input int trace_read_tid, + input int trace_read_lane_id, output bit trace_read_valid, output longint trace_read_address, output bit trace_read_is_store, @@ -32,7 +32,6 @@ module SimMemTrace #(parameter FILENAME = "undefined", NUM_LANES = 4) ( input trace_read_ready, output [NUM_LANES-1:0] trace_read_valid, output [`DATA_WIDTH*NUM_LANES-1:0] trace_read_address, - output [NUM_LANES-1:0] trace_read_is_store, output [`LOGSIZE_WIDTH*NUM_LANES-1:0] trace_read_size, output [`DATA_WIDTH*NUM_LANES-1:0] trace_read_data, diff --git a/src/main/resources/vsrc/SimMemTraceLogger.v b/src/main/resources/vsrc/SimMemTraceLogger.v index 8c358d2..2f6ddae 100644 --- a/src/main/resources/vsrc/SimMemTraceLogger.v +++ b/src/main/resources/vsrc/SimMemTraceLogger.v @@ -1,6 +1,7 @@ // FIXME hardcoded `define DATA_WIDTH 64 `define MAX_NUM_LANES 32 +`define SOURCEID_WIDTH 32 `define LOGSIZE_WIDTH 32 import "DPI-C" function int memtracelogger_init( @@ -17,8 +18,9 @@ import "DPI-C" function void memtracelogger_log input int handle, input bit trace_log_valid, input longint trace_log_cycle, + input int trace_log_lane_id, + input int trace_log_source, input longint trace_log_address, - input int trace_log_tid, input bit trace_log_is_store, input int trace_log_size, input longint trace_log_data, @@ -29,16 +31,17 @@ module SimMemTraceLogger #(parameter IS_RESPONSE = 0, FILENAME = "undefined", NUM_LANES = 4) ( - input clock, - input reset, + input clock, + input reset, // NOTE: LSB is lane 0 - input [NUM_LANES-1:0] trace_log_valid, - input [`DATA_WIDTH*NUM_LANES-1:0] trace_log_address, - input [NUM_LANES-1:0] trace_log_is_store, - input [`LOGSIZE_WIDTH*NUM_LANES-1:0] trace_log_size, - input [`DATA_WIDTH*NUM_LANES-1:0] trace_log_data, - output trace_log_ready + input [NUM_LANES-1:0] trace_log_valid, + input [`SOURCEID_WIDTH*NUM_LANES-1:0] trace_log_source, + input [`DATA_WIDTH*NUM_LANES-1:0] trace_log_address, + input [NUM_LANES-1:0] trace_log_is_store, + input [`LOGSIZE_WIDTH*NUM_LANES-1:0] trace_log_size, + input [`DATA_WIDTH*NUM_LANES-1:0] trace_log_data, + output trace_log_ready ); int logger_handle; bit __in_ready; @@ -51,6 +54,7 @@ module SimMemTraceLogger #(parameter // wires going into the DPC wire __valid [NUM_LANES-1:0]; + wire [`SOURCEID_WIDTH-1:0] __source [NUM_LANES-1:0]; wire [`DATA_WIDTH-1:0] __address [NUM_LANES-1:0]; wire __is_store [NUM_LANES-1:0]; wire [`LOGSIZE_WIDTH-1:0] __size [NUM_LANES-1:0]; @@ -63,6 +67,7 @@ module SimMemTraceLogger #(parameter for (g = 0; g < NUM_LANES; g = g + 1) begin // LSB is lane 0 assign __valid[g] = trace_log_valid[g]; + assign __source[g] = trace_log_source[`SOURCEID_WIDTH*(g+1)-1:`SOURCEID_WIDTH*g]; assign __address[g] = trace_log_address[`DATA_WIDTH*(g+1)-1:`DATA_WIDTH*g]; assign __is_store[g] = trace_log_is_store[g]; assign __size[g] = trace_log_size[`LOGSIZE_WIDTH*(g+1)-1:`LOGSIZE_WIDTH*g]; @@ -87,8 +92,9 @@ module SimMemTraceLogger #(parameter logger_handle, __valid[tid], cycle_counter, - __address[tid], tid, + __source[tid], + __address[tid], __is_store[tid], __size[tid], __data[tid], diff --git a/src/main/scala/tilelink/Coalescing.scala b/src/main/scala/tilelink/Coalescing.scala index 775cce8..4ff21dd 100644 --- a/src/main/scala/tilelink/Coalescing.scala +++ b/src/main/scala/tilelink/Coalescing.scala @@ -607,16 +607,19 @@ class MemTraceDriver(numLanes: Int = 4, filename: String = "vecadd.core1.thread4 lazy val module = new MemTraceDriverImp(this, numLanes, filename) } -trait HasTraceReq { +trait HasTraceLine { val valid: UInt + val source: UInt val address: UInt val is_store: UInt val size: UInt val data: UInt } -class TraceReq extends Bundle with HasTraceReq { +// used for both request and response. response had address set to 0 +class TraceLine extends Bundle with HasTraceLine { val valid = Bool() + val source = UInt(32.W) val address = UInt(64.W) val is_store = Bool() val size = UInt(32.W) // this is log2(bytesize) as in TL A bundle @@ -636,9 +639,11 @@ class MemTraceDriverImp(outer: MemTraceDriver, numLanes: Int, traceFile: String) // Split output of SimMemTrace, which is flattened across all lanes, // back to each lane's. - val laneReqs = Wire(Vec(numLanes, new TraceReq)) + val laneReqs = Wire(Vec(numLanes, new TraceLine)) laneReqs.zipWithIndex.foreach { case (req, i) => req.valid := sim.io.trace_read.valid(i) + // TODO: don't take source id from the original trace for now + req.source := 0.U req.address := sim.io.trace_read.address(64 * i + 63, 64 * i) req.is_store := sim.io.trace_read.is_store(i) req.size := sim.io.trace_read.size(32 * i + 31, 32 * i) @@ -728,7 +733,7 @@ class SimMemTrace(filename: String, numLanes: Int) // These names have to match declarations in the Verilog code, eg. // trace_read_address. - val trace_read = new Bundle with HasTraceReq { + val trace_read = new Bundle { // FIXME: can't use HasTraceLine because this doesn't have source val ready = Input(Bool()) val valid = Output(UInt(numLanes.W)) // Chisel can't interface with Verilog 2D port, so flatten all lanes into @@ -786,8 +791,8 @@ class MemTraceLogger( simResp.io.clock := clock simResp.io.reset := reset.asBool - val laneReqs = Wire(Vec(numLanes, new TraceReq)) - val laneResps = Wire(Vec(numLanes, new TraceReq)) + val laneReqs = Wire(Vec(numLanes, new TraceLine)) + val laneResps = Wire(Vec(numLanes, new TraceLine)) assert( numLanes == node.in.length, @@ -818,6 +823,7 @@ class MemTraceLogger( req.valid := tlIn.a.valid req.size := tlIn.a.bits.size req.is_store := tlAOpcodeIsStore(tlIn.a.bits.opcode) + req.source := tlIn.a.bits.source // TL always carries the exact unaligned address that the client // originally requested, so no postprocessing required req.address := tlIn.a.bits.address @@ -856,6 +862,7 @@ class MemTraceLogger( resp.valid := tlOut.d.valid resp.size := tlOut.d.bits.size resp.is_store := tlDOpcodeIsStore(tlOut.d.bits.opcode) + resp.source := tlOut.d.bits.source // NOTE: TL D channel doesn't carry address nor mask, so there's no easy // way to figure out which bytes the master actually use. Since we // don't care too much about addresses in the trace anyway, just store @@ -864,27 +871,31 @@ class MemTraceLogger( resp.data := tlOut.d.bits.data } + // Flatten per-lane signals to the Verilog blackbox input. // clunky workaround of the fact that Chisel doesn't allow partial // assignment to a bitfield range of a wide signal. - def flattenTrace(traceLogIO: Bundle with HasTraceReq, perLane: Vec[TraceReq]) = { - val laneValid = Wire(Vec(numLanes, Bool())) - val laneAddress = Wire(Vec(numLanes, chiselTypeOf(perLane(0).address))) - val laneIsStore = Wire(Vec(numLanes, chiselTypeOf(perLane(0).is_store))) - val laneSize = Wire(Vec(numLanes, chiselTypeOf(perLane(0).size))) - val laneData = Wire(Vec(numLanes, chiselTypeOf(perLane(0).data))) + def flattenTrace(traceLogIO: Bundle with HasTraceLine, perLane: Vec[TraceLine]) = { + // these will get optimized out + val vecValid = Wire(Vec(numLanes, Bool())) + val vecSource = Wire(Vec(numLanes, Bool())) + val vecAddress = Wire(Vec(numLanes, chiselTypeOf(perLane(0).address))) + val vecIsStore = Wire(Vec(numLanes, chiselTypeOf(perLane(0).is_store))) + val vecSize = Wire(Vec(numLanes, chiselTypeOf(perLane(0).size))) + val vecData = Wire(Vec(numLanes, chiselTypeOf(perLane(0).data))) perLane.zipWithIndex.foreach { case (req, i) => - laneValid(i) := req.valid - laneAddress(i) := req.address - laneIsStore(i) := req.is_store - laneSize(i) := req.size - laneData(i) := req.data + vecValid(i) := req.valid + vecSource(i) := req.source + vecAddress(i) := req.address + vecIsStore(i) := req.is_store + vecSize(i) := req.size + vecData(i) := req.data } - // flatten per-lane signals to the Verilog blackbox input - traceLogIO.valid := laneValid.asUInt - traceLogIO.address := laneAddress.asUInt - traceLogIO.is_store := laneIsStore.asUInt - traceLogIO.size := laneSize.asUInt - traceLogIO.data := laneData.asUInt + traceLogIO.valid := vecValid.asUInt + traceLogIO.source := vecSource.asUInt + traceLogIO.address := vecAddress.asUInt + traceLogIO.is_store := vecIsStore.asUInt + traceLogIO.size := vecSize.asUInt + traceLogIO.data := vecData.asUInt } flattenTrace(simReq.io.trace_log, laneReqs) @@ -892,25 +903,6 @@ class MemTraceLogger( assert(simReq.io.trace_log.ready === true.B, "MemTraceLogger is expected to be always ready") assert(simResp.io.trace_log.ready === true.B, "MemTraceLogger is expected to be always ready") - - // val laneValid = Wire(Vec(numLanes, Bool())) - // 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) => - // laneValid(i) := req.valid - // 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 - // simReq.io.trace_log.valid := laneValid.asUInt - // simReq.io.trace_log.address := laneAddress.asUInt - // simReq.io.trace_log.is_store := laneIsStore.asUInt - // simReq.io.trace_log.size := laneSize.asUInt - // simReq.io.trace_log.data := laneData.asUInt } } @@ -931,8 +923,9 @@ class SimMemTraceLogger(isResponse: Boolean, filename: String, numLanes: Int) val clock = Input(Clock()) val reset = Input(Bool()) - val trace_log = new Bundle with HasTraceReq { + val trace_log = new Bundle with HasTraceLine { val valid = Input(UInt(numLanes.W)) + val source = Input(UInt((32 * numLanes).W)) // Chisel can't interface with Verilog 2D port, so flatten all lanes into // single wide 1D array. // TODO: assumes 64-bit address.