Log source ID in the trace
This commit is contained in:
@@ -5,10 +5,11 @@
|
|||||||
struct MemTraceLine {
|
struct MemTraceLine {
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
long cycle = 0;
|
long cycle = 0;
|
||||||
bool is_store = 0;
|
|
||||||
int core_id = 0;
|
int core_id = 0;
|
||||||
int lane_id = 0;
|
int lane_id = 0;
|
||||||
|
int source = 0;
|
||||||
unsigned long address = 0;
|
unsigned long address = 0;
|
||||||
|
bool is_store = 0;
|
||||||
unsigned long data = 0;
|
unsigned long data = 0;
|
||||||
int log_data_size = 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,
|
extern "C" void memtracelogger_log(int handle,
|
||||||
unsigned char trace_log_valid,
|
unsigned char trace_log_valid,
|
||||||
unsigned long trace_log_cycle,
|
unsigned long trace_log_cycle,
|
||||||
unsigned long trace_log_address,
|
|
||||||
int trace_log_lane_id,
|
int trace_log_lane_id,
|
||||||
|
int trace_log_source,
|
||||||
|
unsigned long trace_log_address,
|
||||||
unsigned char trace_log_is_store,
|
unsigned char trace_log_is_store,
|
||||||
int trace_log_size,
|
int trace_log_size,
|
||||||
unsigned long trace_log_data,
|
unsigned long trace_log_data,
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ MemTraceWriter::~MemTraceWriter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MemTraceWriter::write_line_to_trace(const MemTraceLine line) {
|
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.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.
|
// 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.
|
// This is used to log both TileLink A and D channels.
|
||||||
// TODO: accept core_id as well
|
// TODO: accept core_id as well
|
||||||
extern "C" void
|
extern "C" void memtracelogger_log(int handle,
|
||||||
memtracelogger_log(int handle,
|
unsigned char trace_log_valid,
|
||||||
unsigned char trace_log_valid, unsigned long trace_log_cycle,
|
unsigned long trace_log_cycle,
|
||||||
unsigned long trace_log_address, int trace_log_lane_id,
|
int trace_log_lane_id,
|
||||||
unsigned char trace_log_is_store, int trace_log_size,
|
int trace_log_source,
|
||||||
unsigned long trace_log_data,
|
unsigned long trace_log_address,
|
||||||
unsigned char *trace_log_ready) {
|
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,
|
// 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;
|
||||||
@@ -90,10 +93,11 @@ memtracelogger_log(int handle,
|
|||||||
|
|
||||||
MemTraceLine line{.valid = (trace_log_valid == 1),
|
MemTraceLine line{.valid = (trace_log_valid == 1),
|
||||||
.cycle = static_cast<long>(trace_log_cycle),
|
.cycle = static_cast<long>(trace_log_cycle),
|
||||||
.is_store = (trace_log_is_store == 1),
|
|
||||||
.core_id = 0, // TODO support multicores
|
.core_id = 0, // TODO support multicores
|
||||||
.lane_id = trace_log_lane_id,
|
.lane_id = trace_log_lane_id,
|
||||||
|
.source = trace_log_source,
|
||||||
.address = trace_log_address,
|
.address = trace_log_address,
|
||||||
|
.is_store = (trace_log_is_store == 1),
|
||||||
.data = trace_log_data,
|
.data = trace_log_data,
|
||||||
.log_data_size = trace_log_size};
|
.log_data_size = trace_log_size};
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import "DPI-C" function void memtrace_query
|
|||||||
(
|
(
|
||||||
input bit trace_read_ready,
|
input bit trace_read_ready,
|
||||||
input longint trace_read_cycle,
|
input longint trace_read_cycle,
|
||||||
input int trace_read_tid,
|
input int trace_read_lane_id,
|
||||||
output bit trace_read_valid,
|
output bit trace_read_valid,
|
||||||
output longint trace_read_address,
|
output longint trace_read_address,
|
||||||
output bit trace_read_is_store,
|
output bit trace_read_is_store,
|
||||||
@@ -32,7 +32,6 @@ module SimMemTrace #(parameter FILENAME = "undefined", NUM_LANES = 4) (
|
|||||||
input trace_read_ready,
|
input trace_read_ready,
|
||||||
output [NUM_LANES-1:0] trace_read_valid,
|
output [NUM_LANES-1:0] trace_read_valid,
|
||||||
output [`DATA_WIDTH*NUM_LANES-1:0] trace_read_address,
|
output [`DATA_WIDTH*NUM_LANES-1:0] trace_read_address,
|
||||||
|
|
||||||
output [NUM_LANES-1:0] trace_read_is_store,
|
output [NUM_LANES-1:0] trace_read_is_store,
|
||||||
output [`LOGSIZE_WIDTH*NUM_LANES-1:0] trace_read_size,
|
output [`LOGSIZE_WIDTH*NUM_LANES-1:0] trace_read_size,
|
||||||
output [`DATA_WIDTH*NUM_LANES-1:0] trace_read_data,
|
output [`DATA_WIDTH*NUM_LANES-1:0] trace_read_data,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// FIXME hardcoded
|
// FIXME hardcoded
|
||||||
`define DATA_WIDTH 64
|
`define DATA_WIDTH 64
|
||||||
`define MAX_NUM_LANES 32
|
`define MAX_NUM_LANES 32
|
||||||
|
`define SOURCEID_WIDTH 32
|
||||||
`define LOGSIZE_WIDTH 32
|
`define LOGSIZE_WIDTH 32
|
||||||
|
|
||||||
import "DPI-C" function int memtracelogger_init(
|
import "DPI-C" function int memtracelogger_init(
|
||||||
@@ -17,8 +18,9 @@ import "DPI-C" function void memtracelogger_log
|
|||||||
input int handle,
|
input int handle,
|
||||||
input bit trace_log_valid,
|
input bit trace_log_valid,
|
||||||
input longint trace_log_cycle,
|
input longint trace_log_cycle,
|
||||||
|
input int trace_log_lane_id,
|
||||||
|
input int trace_log_source,
|
||||||
input longint trace_log_address,
|
input longint trace_log_address,
|
||||||
input int trace_log_tid,
|
|
||||||
input bit trace_log_is_store,
|
input bit trace_log_is_store,
|
||||||
input int trace_log_size,
|
input int trace_log_size,
|
||||||
input longint trace_log_data,
|
input longint trace_log_data,
|
||||||
@@ -29,16 +31,17 @@ module SimMemTraceLogger #(parameter
|
|||||||
IS_RESPONSE = 0,
|
IS_RESPONSE = 0,
|
||||||
FILENAME = "undefined",
|
FILENAME = "undefined",
|
||||||
NUM_LANES = 4) (
|
NUM_LANES = 4) (
|
||||||
input clock,
|
input clock,
|
||||||
input reset,
|
input reset,
|
||||||
|
|
||||||
// NOTE: LSB is lane 0
|
// NOTE: LSB is lane 0
|
||||||
input [NUM_LANES-1:0] trace_log_valid,
|
input [NUM_LANES-1:0] trace_log_valid,
|
||||||
input [`DATA_WIDTH*NUM_LANES-1:0] trace_log_address,
|
input [`SOURCEID_WIDTH*NUM_LANES-1:0] trace_log_source,
|
||||||
input [NUM_LANES-1:0] trace_log_is_store,
|
input [`DATA_WIDTH*NUM_LANES-1:0] trace_log_address,
|
||||||
input [`LOGSIZE_WIDTH*NUM_LANES-1:0] trace_log_size,
|
input [NUM_LANES-1:0] trace_log_is_store,
|
||||||
input [`DATA_WIDTH*NUM_LANES-1:0] trace_log_data,
|
input [`LOGSIZE_WIDTH*NUM_LANES-1:0] trace_log_size,
|
||||||
output trace_log_ready
|
input [`DATA_WIDTH*NUM_LANES-1:0] trace_log_data,
|
||||||
|
output trace_log_ready
|
||||||
);
|
);
|
||||||
int logger_handle;
|
int logger_handle;
|
||||||
bit __in_ready;
|
bit __in_ready;
|
||||||
@@ -51,6 +54,7 @@ module SimMemTraceLogger #(parameter
|
|||||||
|
|
||||||
// wires going into the DPC
|
// wires going into the DPC
|
||||||
wire __valid [NUM_LANES-1:0];
|
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 [`DATA_WIDTH-1:0] __address [NUM_LANES-1:0];
|
||||||
wire __is_store [NUM_LANES-1:0];
|
wire __is_store [NUM_LANES-1:0];
|
||||||
wire [`LOGSIZE_WIDTH-1:0] __size [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
|
for (g = 0; g < NUM_LANES; g = g + 1) begin
|
||||||
// LSB is lane 0
|
// LSB is lane 0
|
||||||
assign __valid[g] = trace_log_valid[g];
|
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 __address[g] = trace_log_address[`DATA_WIDTH*(g+1)-1:`DATA_WIDTH*g];
|
||||||
assign __is_store[g] = trace_log_is_store[g];
|
assign __is_store[g] = trace_log_is_store[g];
|
||||||
assign __size[g] = trace_log_size[`LOGSIZE_WIDTH*(g+1)-1:`LOGSIZE_WIDTH*g];
|
assign __size[g] = trace_log_size[`LOGSIZE_WIDTH*(g+1)-1:`LOGSIZE_WIDTH*g];
|
||||||
@@ -87,8 +92,9 @@ module SimMemTraceLogger #(parameter
|
|||||||
logger_handle,
|
logger_handle,
|
||||||
__valid[tid],
|
__valid[tid],
|
||||||
cycle_counter,
|
cycle_counter,
|
||||||
__address[tid],
|
|
||||||
tid,
|
tid,
|
||||||
|
__source[tid],
|
||||||
|
__address[tid],
|
||||||
__is_store[tid],
|
__is_store[tid],
|
||||||
__size[tid],
|
__size[tid],
|
||||||
__data[tid],
|
__data[tid],
|
||||||
|
|||||||
@@ -607,16 +607,19 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasTraceReq {
|
trait HasTraceLine {
|
||||||
val valid: UInt
|
val valid: UInt
|
||||||
|
val source: UInt
|
||||||
val address: UInt
|
val address: UInt
|
||||||
val is_store: UInt
|
val is_store: UInt
|
||||||
val size: UInt
|
val size: UInt
|
||||||
val data: 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 valid = Bool()
|
||||||
|
val source = UInt(32.W)
|
||||||
val address = UInt(64.W)
|
val address = UInt(64.W)
|
||||||
val is_store = Bool()
|
val is_store = Bool()
|
||||||
val size = UInt(32.W) // this is log2(bytesize) as in TL A bundle
|
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,
|
// Split output of SimMemTrace, which is flattened across all lanes,
|
||||||
// back to each lane's.
|
// 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) =>
|
laneReqs.zipWithIndex.foreach { case (req, i) =>
|
||||||
req.valid := sim.io.trace_read.valid(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.address := sim.io.trace_read.address(64 * i + 63, 64 * i)
|
||||||
req.is_store := sim.io.trace_read.is_store(i)
|
req.is_store := sim.io.trace_read.is_store(i)
|
||||||
req.size := sim.io.trace_read.size(32 * i + 31, 32 * 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.
|
// These names have to match declarations in the Verilog code, eg.
|
||||||
// trace_read_address.
|
// 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 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
|
||||||
@@ -786,8 +791,8 @@ class MemTraceLogger(
|
|||||||
simResp.io.clock := clock
|
simResp.io.clock := clock
|
||||||
simResp.io.reset := reset.asBool
|
simResp.io.reset := reset.asBool
|
||||||
|
|
||||||
val laneReqs = Wire(Vec(numLanes, new TraceReq))
|
val laneReqs = Wire(Vec(numLanes, new TraceLine))
|
||||||
val laneResps = Wire(Vec(numLanes, new TraceReq))
|
val laneResps = Wire(Vec(numLanes, new TraceLine))
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
numLanes == node.in.length,
|
numLanes == node.in.length,
|
||||||
@@ -818,6 +823,7 @@ class MemTraceLogger(
|
|||||||
req.valid := tlIn.a.valid
|
req.valid := tlIn.a.valid
|
||||||
req.size := tlIn.a.bits.size
|
req.size := tlIn.a.bits.size
|
||||||
req.is_store := tlAOpcodeIsStore(tlIn.a.bits.opcode)
|
req.is_store := tlAOpcodeIsStore(tlIn.a.bits.opcode)
|
||||||
|
req.source := tlIn.a.bits.source
|
||||||
// TL always carries the exact unaligned address that the client
|
// TL always carries the exact unaligned address that the client
|
||||||
// originally requested, so no postprocessing required
|
// originally requested, so no postprocessing required
|
||||||
req.address := tlIn.a.bits.address
|
req.address := tlIn.a.bits.address
|
||||||
@@ -856,6 +862,7 @@ class MemTraceLogger(
|
|||||||
resp.valid := tlOut.d.valid
|
resp.valid := tlOut.d.valid
|
||||||
resp.size := tlOut.d.bits.size
|
resp.size := tlOut.d.bits.size
|
||||||
resp.is_store := tlDOpcodeIsStore(tlOut.d.bits.opcode)
|
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
|
// 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
|
// 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
|
// 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
|
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
|
// clunky workaround of the fact that Chisel doesn't allow partial
|
||||||
// assignment to a bitfield range of a wide signal.
|
// assignment to a bitfield range of a wide signal.
|
||||||
def flattenTrace(traceLogIO: Bundle with HasTraceReq, perLane: Vec[TraceReq]) = {
|
def flattenTrace(traceLogIO: Bundle with HasTraceLine, perLane: Vec[TraceLine]) = {
|
||||||
val laneValid = Wire(Vec(numLanes, Bool()))
|
// these will get optimized out
|
||||||
val laneAddress = Wire(Vec(numLanes, chiselTypeOf(perLane(0).address)))
|
val vecValid = Wire(Vec(numLanes, Bool()))
|
||||||
val laneIsStore = Wire(Vec(numLanes, chiselTypeOf(perLane(0).is_store)))
|
val vecSource = Wire(Vec(numLanes, Bool()))
|
||||||
val laneSize = Wire(Vec(numLanes, chiselTypeOf(perLane(0).size)))
|
val vecAddress = Wire(Vec(numLanes, chiselTypeOf(perLane(0).address)))
|
||||||
val laneData = Wire(Vec(numLanes, chiselTypeOf(perLane(0).data)))
|
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) =>
|
perLane.zipWithIndex.foreach { case (req, i) =>
|
||||||
laneValid(i) := req.valid
|
vecValid(i) := req.valid
|
||||||
laneAddress(i) := req.address
|
vecSource(i) := req.source
|
||||||
laneIsStore(i) := req.is_store
|
vecAddress(i) := req.address
|
||||||
laneSize(i) := req.size
|
vecIsStore(i) := req.is_store
|
||||||
laneData(i) := req.data
|
vecSize(i) := req.size
|
||||||
|
vecData(i) := req.data
|
||||||
}
|
}
|
||||||
// flatten per-lane signals to the Verilog blackbox input
|
traceLogIO.valid := vecValid.asUInt
|
||||||
traceLogIO.valid := laneValid.asUInt
|
traceLogIO.source := vecSource.asUInt
|
||||||
traceLogIO.address := laneAddress.asUInt
|
traceLogIO.address := vecAddress.asUInt
|
||||||
traceLogIO.is_store := laneIsStore.asUInt
|
traceLogIO.is_store := vecIsStore.asUInt
|
||||||
traceLogIO.size := laneSize.asUInt
|
traceLogIO.size := vecSize.asUInt
|
||||||
traceLogIO.data := laneData.asUInt
|
traceLogIO.data := vecData.asUInt
|
||||||
}
|
}
|
||||||
|
|
||||||
flattenTrace(simReq.io.trace_log, laneReqs)
|
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(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")
|
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 clock = Input(Clock())
|
||||||
val reset = Input(Bool())
|
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 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
|
// Chisel can't interface with Verilog 2D port, so flatten all lanes into
|
||||||
// single wide 1D array.
|
// single wide 1D array.
|
||||||
// TODO: assumes 64-bit address.
|
// TODO: assumes 64-bit address.
|
||||||
|
|||||||
Reference in New Issue
Block a user