diff --git a/src/main/resources/csrc/SimMemFuzzer.c b/src/main/resources/csrc/SimMemFuzzer.c deleted file mode 100644 index fc26903..0000000 --- a/src/main/resources/csrc/SimMemFuzzer.c +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef NO_VPI -#include -#include -#endif -#include - -void memfuzz_init(void) { - printf("Hello from C!\n"); -} diff --git a/src/main/resources/csrc/SimMemFuzzer.cc b/src/main/resources/csrc/SimMemFuzzer.cc new file mode 100644 index 0000000..089f355 --- /dev/null +++ b/src/main/resources/csrc/SimMemFuzzer.cc @@ -0,0 +1,21 @@ +#ifndef NO_VPI +#include +#include +#endif +#include +#include + +extern "C" void memfuzz_generate_rs(uint8_t *vec_a_ready, uint8_t *vec_a_valid, + long long *vec_a_address, + uint8_t *vec_d_ready, uint8_t *finished); + +extern "C" void memfuzz_init(int num_lanes) { + printf("from C: num_lanes=%d\n", num_lanes); +} + +extern "C" void memfuzz_generate(uint8_t *vec_a_ready, uint8_t *vec_a_valid, + long long *vec_a_address, uint8_t *vec_d_ready, + uint8_t *finished) { + memfuzz_generate_rs(vec_a_ready, vec_a_valid, vec_a_address, vec_d_ready, + finished); +} diff --git a/src/main/resources/vsrc/SimMemFuzzer.v b/src/main/resources/vsrc/SimMemFuzzer.v index d67880c..0da7e37 100644 --- a/src/main/resources/vsrc/SimMemFuzzer.v +++ b/src/main/resources/vsrc/SimMemFuzzer.v @@ -1,103 +1,92 @@ -// FIXME hardcoded -`define MEMTRACE_DATA_WIDTH 64 -`define MAX_NUM_LANES 32 -`define MEMTRACE_LOGSIZE_WIDTH 8 +`include "SimDefaults.vh" import "DPI-C" function void memfuzz_init( + input longint num_lanes ); // Make sure to sync the parameters for: // (1) import "DPI-C" declaration // (2) C function declaration // (3) DPI function calls inside initial/always blocks -import "DPI-C" function void memtrace_query +import "DPI-C" function void memfuzz_generate ( - input bit trace_read_ready, - input longint trace_read_cycle, - input int trace_read_lane_id, - output bit trace_read_valid, - output longint trace_read_address, - output bit trace_read_is_store, - output byte trace_read_size, - output longint trace_read_data, - output bit trace_read_finished + input bit vec_a_ready[`MAX_NUM_LANES], + output bit vec_a_valid[`MAX_NUM_LANES], + output longint vec_a_address[`MAX_NUM_LANES], + output bit vec_d_ready[`MAX_NUM_LANES], + output bit finished ); -module SimMemFuzz #(parameter NUM_LANES = 4) ( +module SimMemFuzzer #(parameter NUM_LANES = 4) ( input clock, - input reset + input reset, - // input trace_read_ready, - // output [NUM_LANES-1:0] trace_read_valid, - // output [`MEMTRACE_DATA_WIDTH*NUM_LANES-1:0] trace_read_address, - // output [NUM_LANES-1:0] trace_read_is_store, - // output [`MEMTRACE_LOGSIZE_WIDTH*NUM_LANES-1:0] trace_read_size, - // output [`MEMTRACE_DATA_WIDTH*NUM_LANES-1:0] trace_read_data, - // output trace_read_finished + input [NUM_LANES-1:0] a_ready, + output [NUM_LANES-1:0] a_valid, + output [`SIMMEM_DATA_WIDTH*NUM_LANES-1:0] a_address, + output [NUM_LANES-1:0] a_is_store, + output [`SIMMEM_LOGSIZE_WIDTH*NUM_LANES-1:0] a_size, + output [`SIMMEM_DATA_WIDTH*NUM_LANES-1:0] a_data, + output [NUM_LANES-1:0] d_ready, + output finished ); + // need to be in ascending order to match with C indexing + // C array sizes are static, so need to use MAX_NUM_LANES + bit __out_a_ready [0:`MAX_NUM_LANES-1]; + bit __in_a_valid [0:`MAX_NUM_LANES-1]; + longint __in_a_address [0:`MAX_NUM_LANES-1]; + bit __in_a_is_store [0:`MAX_NUM_LANES-1]; + reg [`SIMMEM_LOGSIZE_WIDTH-1:0] __in_a_size [0:`MAX_NUM_LANES-1]; + longint __in_a_data [0:`MAX_NUM_LANES-1]; + bit __in_d_ready [0:`MAX_NUM_LANES-1]; + bit __in_finished; + + genvar g; + generate + for (g = 0; g < NUM_LANES; g = g + 1) begin + assign __out_a_ready[g] = a_ready[g]; + assign a_valid[g] = __in_a_valid[g]; + assign a_address[`SIMMEM_DATA_WIDTH*g +: `SIMMEM_DATA_WIDTH] = __in_a_address[g]; + + assign a_is_store[g] = __in_a_is_store[g]; + assign a_size[`SIMMEM_LOGSIZE_WIDTH*g +: `SIMMEM_LOGSIZE_WIDTH] = __in_a_size[g]; + assign a_data[`SIMMEM_DATA_WIDTH*g +: `SIMMEM_DATA_WIDTH] = __in_a_data[g]; + end + endgenerate + assign finished = __in_finished; initial begin - memfuzz_init(); + memfuzz_init(NUM_LANES); end - // bit __in_valid [NUM_LANES-1:0]; - // longint __in_address [NUM_LANES-1:0]; - // bit __in_is_store [NUM_LANES-1:0]; - // reg [`MEMTRACE_LOGSIZE_WIDTH-1:0] __in_size [NUM_LANES-1:0]; - // longint __in_data [NUM_LANES-1:0]; - // bit __in_finished; + always @(posedge clock) begin + if (reset) begin + for (integer tid = 0; tid < NUM_LANES; tid = tid + 1) begin + __in_a_valid[tid] = 1'b0; + __in_a_address[tid] = `SIMMEM_DATA_WIDTH'b0; - // genvar g; - // generate - // for (g = 0; g < NUM_LANES; g = g + 1) begin - // assign trace_read_valid[g] = __in_valid[g]; - // assign trace_read_address[`MEMTRACE_DATA_WIDTH*(g+1)-1:`MEMTRACE_DATA_WIDTH*g] = __in_address[g]; + __in_a_is_store[tid] = 1'b0; + __in_a_size[tid] = `SIMMEM_LOGSIZE_WIDTH'b0; + __in_a_data[tid] = `SIMMEM_DATA_WIDTH'b0; + __in_d_ready[tid] = 1'b0; + end + __in_finished = 1'b0; + end else begin + memfuzz_generate( + __out_a_ready, + __in_a_valid, + __in_a_address, + __in_d_ready, + __in_finished + ); + for (integer tid = 0; tid < NUM_LANES; tid = tid + 1) begin + $display("verilog: %04d valid[%d]=%d, address[%d]=%d", + $time, tid, __in_a_valid[tid], tid, __in_a_address[tid]); + end - // assign trace_read_is_store[g] = __in_is_store[g]; - // assign trace_read_size[`MEMTRACE_LOGSIZE_WIDTH*(g+1)-1:`MEMTRACE_LOGSIZE_WIDTH*g] = __in_size[g]; - // assign trace_read_data[`MEMTRACE_DATA_WIDTH*(g+1)-1:`MEMTRACE_DATA_WIDTH*g] = __in_data[g]; - // end - // endgenerate - // assign trace_read_finished = __in_finished; - - // initial begin - // /* $value$plusargs("uartlog=%s", __uartlog); */ - // memtrace_init(FILENAME, HAS_SOURCE); - // end - - // always @(posedge clock) begin - // if (reset) begin - // for (integer tid = 0; tid < NUM_LANES; tid = tid + 1) begin - // __in_valid[tid] = 1'b0; - // __in_address[tid] = `MEMTRACE_DATA_WIDTH'b0; - // - // __in_is_store[tid] = 1'b0; - // __in_size[tid] = `MEMTRACE_LOGSIZE_WIDTH'b0; - // __in_data[tid] = `MEMTRACE_DATA_WIDTH'b0; - // end - // __in_finished = 1'b0; - // end else begin - // // We have to write to __in_ regs only when trace_read_ready, or - // // otherwise we might overwrite lines that were previously valid - // // but the downstream missed by being not ready. - // if (trace_read_ready) begin - // for (integer tid = 0; tid < NUM_LANES; tid = tid + 1) begin - // memtrace_query( - // trace_read_ready, - // trace_read_cycle, - // tid, - - // __in_valid[tid], - // __in_address[tid], - - // __in_is_store[tid], - // __in_size[tid], - // __in_data[tid], - - // __in_finished - // ); - // end - // end - // end - // end + if ($time >= 32'd200000) begin + $finish; + end + end + end endmodule diff --git a/src/main/scala/radiance/memory/Coalescing.scala b/src/main/scala/radiance/memory/Coalescing.scala index 765379d..9faa512 100644 --- a/src/main/scala/radiance/memory/Coalescing.scala +++ b/src/main/scala/radiance/memory/Coalescing.scala @@ -848,6 +848,7 @@ class CoalescingUnitImp(outer: CoalescingUnit, config: CoalescerConfig) println(s"CoalescingUnit instantiated with config: {") println(s" enable: ${config.enable}") println(s" numLanes: ${config.numLanes}") + println(s" wordSizeInBytes: ${config.wordSizeInBytes}") println(s" coalLogSizes: ${config.coalLogSizes}") println(s" numOldSrcIds: ${config.numOldSrcIds}") println(s" numNewSrcIds: ${config.numNewSrcIds}") @@ -1695,18 +1696,6 @@ class MemTraceDriverImp( } } -class SimMemFuzzer extends BlackBox - with HasBlackBoxResource { - val io = IO(new Bundle { - val clock = Input(Clock()) - val reset = Input(Bool()) - }) - - addResource("/vsrc/SimDefaults.vh") - addResource("/vsrc/SimMemFuzzer.v") - addResource("/csrc/SimMemFuzzer.c") -} - class SimMemTrace(filename: String, numLanes: Int, traceHasSource: Boolean) extends BlackBox( Map( @@ -2081,10 +2070,14 @@ class MemFuzzerImp( val io = IO(new Bundle { val finished = Output(Bool()) }) - val sim = Module(new SimMemFuzzer) + val sim = Module(new SimMemFuzzer(config.numLanes)) sim.io.clock := clock sim.io.reset := reset.asBool + sim.io.a.ready := true.B // FIXME + + io.finished := sim.io.finished + // Read output from Verilog BlackBox // Split output of SimMemTrace, which is flattened across all lanes,back to each lane's. val laneReqs = Wire(Vec(config.numLanes, new TraceLine)) @@ -2092,18 +2085,12 @@ class MemFuzzerImp( val sizeW = laneReqs(0).size.getWidth val dataW = laneReqs(0).data.getWidth laneReqs.zipWithIndex.foreach { case (req, i) => - // req.valid := sim.io.trace_read.valid(i) - // req.source := 0.U // driver trace doesn't contain source id - // req.address := sim.io.trace_read.address(addrW * (i + 1) - 1, addrW * i) - // req.is_store := sim.io.trace_read.is_store(i) - // req.size := sim.io.trace_read.size(sizeW * (i + 1) - 1, sizeW * i) - // req.data := sim.io.trace_read.data(dataW * (i + 1) - 1, dataW * i) - req.valid := 0.U - req.source := 0.U // driver trace doesn't contain source id - req.address := 0.U - req.is_store := 0.U - req.size := 0.U - req.data := 0.U + req.valid := sim.io.a.valid(i) + req.source := 0.U // DPI fuzzer doesn't generate contain source id + req.address := sim.io.a.address(addrW * (i + 1) - 1, addrW * i) + req.is_store := sim.io.a.is_store(i) + req.size := sim.io.a.size(sizeW * (i + 1) - 1, sizeW * i) + req.data := sim.io.a.data(dataW * (i + 1) - 1, dataW * i) } val sourceGens = Seq.fill(config.numLanes)( @@ -2169,7 +2156,7 @@ class MemFuzzerImp( tlOut.a.bits := bits tlOut.b.ready := true.B tlOut.c.valid := false.B - tlOut.d.ready := true.B + tlOut.d.ready := sim.io.d.ready(lane) // FIXME tlOut.e.valid := false.B // debug @@ -2190,21 +2177,6 @@ class MemFuzzerImp( dontTouch(tlOut.d) } - // Give some slack time after trace EOF to get some outstanding responses - // back. - // val traceFinished = RegInit(false.B) - // when(sim.io.trace_read.finished) { - // traceFinished := true.B - // } - // io.finished := traceFinished - io.finished := true.B - - // FIXME: - // - // currently the .cc file ouptuts finished=true while it still need to issue one more request - // val noValidReqs = sim.io.trace_read.valid === 0.U - // val allReqReclaimed = !(sourceGens.map(_.io.inflight).reduce(_ || _)) - // when(traceFinished && allReqReclaimed && noValidReqs) { // assert( // false.B, @@ -2212,6 +2184,40 @@ class MemFuzzerImp( // ) // } } + +class SimMemFuzzer(numLanes: Int) extends BlackBox + with HasBlackBoxResource { + val traceLineT = new TraceLine + val addrW = traceLineT.address.getWidth + val sizeW = traceLineT.size.getWidth + val dataW = traceLineT.data.getWidth + val io = IO(new Bundle { + val clock = Input(Clock()) + val reset = Input(Bool()) + val finished = Output(Bool()) + + val a = + new Bundle { + val ready = Input(UInt(numLanes.W)) + val valid = Output(UInt(numLanes.W)) + // Chisel can't interface with Verilog 2D port, so flatten all lanes into + // single wide 1D array. + val address = Output(UInt((addrW * numLanes).W)) + val is_store = Output(UInt(numLanes.W)) + val size = Output(UInt((sizeW * numLanes).W)) + val data = Output(UInt((dataW * numLanes).W)) + } + val d = + new Bundle { + val ready = Output(UInt(numLanes.W)) + } + }) + + addResource("/vsrc/SimDefaults.vh") + addResource("/vsrc/SimMemFuzzer.v") + addResource("/csrc/SimMemFuzzer.cc") +} + // Synthesizable unit tests class DummyDriver(config: CoalescerConfig)(implicit p: Parameters)