Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 43 additions & 31 deletions src/mase_cocotb/interfaces/streaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,50 +238,62 @@ def _check(self, got, exp):
self.log.debug("Passed | Got: %20s Exp: %20s Err: %10s" % (g, e, err))


class MultiSignalStreamDriver(Driver):
def __init__(self, clk, data, valid, ready) -> None:
super().__init__()
self.clk = clk
self.data = data
self.valid = valid
self.ready = ready
self.valid_prob = 1.0

def set_valid_prob(self, prob):
assert prob >= 0.0 and prob <= 1.0
self.valid_prob = prob

async def _driver_send(self, data) -> None:
class MultiSignalStreamDriver(StreamDriver):
async def _driver_send(self, transaction) -> None:
while True:
await RisingEdge(self.clk)
for hardware_target, item in zip(self.data, data):
hardware_target.value = item

if type(self.data) == tuple:
# Drive multiple data bus
for wire, val in zip(self.data, transaction):
wire.value = val
else:
# Drive single data
self.data.value = transaction
if random.random() > self.valid_prob:
self.valid.value = 0
continue # Try roll random valid again at next clock
self.valid.value = 1
await ReadOnly()
if self.ready.value == 1:
self.log.debug(f"Sent {data}")
if type(self.data) == tuple:
# Drive multiple data bus
for t in transaction:
self.log.debug("Sent %s" % t)
else:
self.log.debug("Sent %s" % transaction)
if self.record_num_beats:
self.num_beats += 1
break

# Load extra
# self.load_driver

if self.send_queue.empty():
await RisingEdge(self.clk)
self.valid.value = 0


class MultiSignalStreamMonitor(Monitor):
def __init__(self, clk, data, valid, ready, check=True):
super().__init__(clk)
self.clk = clk
self.data = data
self.valid = valid
self.ready = ready
self.check = check

def _trigger(self):
return self.valid.value == 1 and self.ready.value == 1

# async def _driver_send(self, data) -> None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just delete this?

# while True:
# await RisingEdge(self.clk)
# print(self.data, data)
# for hardware_target, item in zip(self.data, data):
# print(hardware_target, item)
# hardware_target.value = item

# if random.random() > self.valid_prob:
# self.valid.value = 0
# continue # Try roll random valid again at next clock
# self.valid.value = 1
# await ReadOnly()
# if self.ready.value == 1:
# self.log.debug(f"Sent {data}")
# break
# if self.send_queue.empty():
# await RisingEdge(self.clk)
# self.valid.value = 0


class MultiSignalStreamMonitor(StreamMonitor):
def _recv(self):
def cast_data(value):
if type(value) == list:
Expand Down
8 changes: 4 additions & 4 deletions src/mase_cocotb/testbench.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ def get_parameter(self, parameter_name):
parameter = getattr(self.dut, parameter_name)
return int(parameter)

def get_parameter(self, parameter_name):
parameter = getattr(self.dut, parameter_name)
return int(parameter)

async def reset(self, active_high=True):
if self.rst is None:
raise Exception(
Expand All @@ -53,6 +49,10 @@ async def reset(self, active_high=True):
self.rst.value = 1 if active_high else 0
await RisingEdge(self.clk)
self.rst.value = 0 if active_high else 1
for monitor in self.output_monitors.values():
monitor.ready.value = 1
for driver in self.input_drivers.values():
driver.valid.value = 0
await RisingEdge(self.clk)

async def initialize(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,41 @@ module log2_max_abs #(
input logic clk,
input logic rst,
/* verilator lint_on UNUSEDSIGNAL */
input logic [ IN_WIDTH-1:0] data_in [IN_SIZE-1:0],
input logic data_in_valid,
output logic data_in_ready,
output logic [OUT_WIDTH-1:0] data_out,
output logic data_out_valid,
input logic data_out_ready
input logic [ IN_WIDTH-1:0] data_in_0 [IN_SIZE-1:0],
input logic data_in_0_valid,
output logic data_in_0_ready,
output logic [OUT_WIDTH-1:0] data_out_0,
output logic data_out_0_valid,
input logic data_out_0_ready
);
logic [IN_WIDTH - 1:0] or_result;
logic [IN_WIDTH - 1:0] abs_data_in[IN_SIZE - 1:0];
for (genvar i = 0; i < IN_SIZE; i++) begin
abs #(
.IN_WIDTH(IN_WIDTH)
) abs_i (
.data_in (data_in[i]),
.data_in (data_in_0[i]),
.data_out(abs_data_in[i])
);
end
or_tree #(
.IN_SIZE (IN_SIZE),
.IN_WIDTH(IN_WIDTH),
) max_bas_i (
.IN_WIDTH(IN_WIDTH)
) or_tree_i (
.clk,
.rst,
.data_in(abs_data_in),
.data_in_valid(data_in_valid),
.data_in_ready(data_in_ready),
.data_in_valid(data_in_0_valid),
.data_in_ready(data_in_0_ready),
.data_out(or_result),
.data_out_valid(data_out_valid),
.data_out_ready(data_out_ready)
.data_out_valid(data_out_0_valid),
.data_out_ready(data_out_0_ready)
);
log2_value #(
.IN_WIDTH(IN_WIDTH),
.IN_WIDTH(IN_WIDTH)
) log2_i (
.data_in (or_result),
.data_out(data_out)
.data_out(data_out_0)
);

endmodule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ Description : The accumulator for mxint.
When inputing different exponent, the mantissa will cast to the same bitwidth then accumulate.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a lossy behaviour? If it is, it might worth to add a few more lines to explain its behaviour? I assume this is the module that aligns the exponent first?

*/
module mxint_accumulator #(
parameter DATA_IN_0_PRECISION_0 = 8,
parameter DATA_IN_0_PRECISION_1 = 4,
// precision_0 = mantissa_width
// precision_1 = exponent_width
parameter DATA_IN_0_PRECISION_0 = 4,
parameter DATA_IN_0_PRECISION_1 = 8,
parameter BLOCK_SIZE = 4,
parameter IN_DEPTH = 2,
parameter DATA_OUT_0_PRECISION_0 = DATA_IN_0_PRECISION_0 + 2 ** DATA_IN_0_PRECISION_1 + $clog2(
IN_DEPTH
),
parameter DATA_OUT_0_PRECISION_0 = DATA_IN_0_PRECISION_0 + $clog2(IN_DEPTH),
parameter DATA_OUT_0_PRECISION_1 = DATA_IN_0_PRECISION_1
) (
input logic clk,
Expand All @@ -37,15 +37,23 @@ module mxint_accumulator #(
assign data_out_0_valid = (counter == IN_DEPTH);
/* verilator lint_on WIDTH */

// mantissa shift
logic [DATA_OUT_0_PRECISION_0 - 1:0] shifted_mdata_in_0[BLOCK_SIZE - 1:0];
// lossless shift
logic [DATA_IN_0_PRECISION_0 - 1:0] shifted_mdata_in_0[BLOCK_SIZE - 1:0];
logic [DATA_OUT_0_PRECISION_0 - 1:0] shifted_mdata_out_0[BLOCK_SIZE - 1:0];

logic no_value_in_register;
logic [DATA_IN_0_PRECISION_1 - 1:0] exp_min;
logic [DATA_IN_0_PRECISION_1 - 1:0] exp_max;

logic [DATA_IN_0_PRECISION_1 - 1:0] mdata_in_shift_value;
logic [DATA_IN_0_PRECISION_1 - 1:0] mdata_in_real_shift_value;
logic [DATA_IN_0_PRECISION_1 - 1:0] mdata_out_shift_value;
logic [DATA_IN_0_PRECISION_1 - 1:0] mdata_out_real_shift_value;

logic [DATA_IN_0_PRECISION_0 - 1:0] shifted_mdata_in_list [BLOCK_SIZE - 1:0][DATA_IN_0_PRECISION_0 - 1:0];
logic [DATA_OUT_0_PRECISION_0 - 1:0] shifted_mdata_out_list [BLOCK_SIZE - 1:0][DATA_OUT_0_PRECISION_0 - 1:0];

assign no_value_in_register =(counter == 0 || (data_out_0_valid && data_out_0_ready && data_in_0_valid));
assign exp_min = ($signed(edata_out_0) > $signed(edata_in_0)) ? edata_in_0 : edata_out_0;
assign exp_max = ($signed(edata_out_0) < $signed(edata_in_0)) ? edata_in_0 : edata_out_0;
// counter
always_ff @(posedge clk)
if (rst) counter <= 0;
Expand All @@ -58,43 +66,51 @@ module mxint_accumulator #(
end else if (data_in_0_valid && data_in_0_ready) counter <= counter + 1;
end
// mantissa
always_comb begin
mdata_in_shift_value = $signed(exp_max) - $signed(edata_in_0);
mdata_in_real_shift_value = (mdata_in_shift_value < DATA_IN_0_PRECISION_0)? mdata_in_shift_value: DATA_IN_0_PRECISION_0 - 1;
mdata_out_shift_value = $signed(exp_max) - $signed(edata_out_0);
mdata_out_real_shift_value = (mdata_out_shift_value < DATA_OUT_0_PRECISION_0)? mdata_out_shift_value: DATA_OUT_0_PRECISION_0 - 1;
end

for (genvar i = 0; i < BLOCK_SIZE; i++) begin : mantissa_block
// mantissa shift
for (genvar j = 0; j < 2 ** DATA_IN_0_PRECISION_1; j++) begin : static_shift
for (genvar i = 0; i < BLOCK_SIZE; i++) begin : optimize_variable_shift
for (genvar j = 0; j < DATA_IN_0_PRECISION_0; j++) begin : data_in_shift
always_comb begin
shifted_mdata_in_list[i][j] = no_value_in_register ? $signed(mdata_in_0[i]) :
$signed(mdata_in_0[i]) >>> j;
end
end
for (genvar k = 0; k < DATA_OUT_0_PRECISION_0; k++) begin : data_out_shift
always_comb begin
if (($signed(edata_in_0) - $signed(exp_min)) == j)
shifted_mdata_in_0[i] = no_value_in_register ? $signed(
mdata_in_0[i]
) : $signed(
mdata_in_0[i]
) <<< j;
if (($signed(edata_out_0) - $signed(exp_min)) == j)
shifted_mdata_out_0[i] = $signed(mdata_out_0[i]) <<< j;
shifted_mdata_out_list[i][k] = $signed(mdata_out_0[i]) >>> k;
end
end
// mantissa out
assign shifted_mdata_in_0[i] = shifted_mdata_in_list[i][mdata_in_real_shift_value];
assign shifted_mdata_out_0[i] = shifted_mdata_out_list[i][mdata_out_real_shift_value];
end

for (genvar i = 0; i < BLOCK_SIZE; i++) begin : mantissa_block
always_ff @(posedge clk)
if (rst) mdata_out_0[i] <= '0;
else begin
if (data_out_0_valid) begin
if (data_out_0_ready) begin
if (data_in_0_valid) mdata_out_0[i] <= shifted_mdata_in_0[i];
if (data_in_0_valid) mdata_out_0[i] <= $signed(shifted_mdata_in_0[i]);
else mdata_out_0[i] <= '0;
end
end else if (data_in_0_valid && data_in_0_ready)
mdata_out_0[i] <= $signed(shifted_mdata_out_0[i]) + $signed(shifted_mdata_in_0[i]);
end
end
localparam signed [DATA_IN_0_PRECISION_1 - 1:0] MAXIMUM_EXPONENTIAL = 2**(DATA_IN_0_PRECISION_1 - 1) - 1;
localparam signed [DATA_IN_0_PRECISION_1 - 1:0] MINIMUM_EXPONENTIAL = - 2**(DATA_IN_0_PRECISION_1 - 1);
// exponent
always_ff @(posedge clk)
if (rst) edata_out_0 <= MAXIMUM_EXPONENTIAL;
if (rst) edata_out_0 <= MINIMUM_EXPONENTIAL;
else if (data_out_0_valid) begin
if (data_out_0_ready) begin
if (data_in_0_valid) edata_out_0 <= edata_in_0;
else edata_out_0 <= MAXIMUM_EXPONENTIAL;
else edata_out_0 <= MINIMUM_EXPONENTIAL;
end
end else if (data_in_0_valid && data_in_0_ready) edata_out_0 <= exp_min;
end else if (data_in_0_valid && data_in_0_ready) edata_out_0 <= exp_max;

endmodule
Loading