test: validate parametric 32x4 layer with parallelism 8
This commit is contained in:
+83
@@ -0,0 +1,83 @@
|
|||||||
|
module layer #(
|
||||||
|
parameter DATA_WIDTH = 16,
|
||||||
|
parameter FRAC_BITS = 8,
|
||||||
|
parameter N_INPUTS = 64,
|
||||||
|
parameter N_NEURONS = 8,
|
||||||
|
parameter PARALLEL = 8,
|
||||||
|
parameter ACC_WIDTH = 40
|
||||||
|
)(
|
||||||
|
input clk,
|
||||||
|
input rst,
|
||||||
|
input start,
|
||||||
|
|
||||||
|
input signed [DATA_WIDTH*N_INPUTS-1:0] x_bus,
|
||||||
|
|
||||||
|
input signed [DATA_WIDTH*N_INPUTS*N_NEURONS-1:0]
|
||||||
|
weights_bus,
|
||||||
|
|
||||||
|
input signed [DATA_WIDTH*N_NEURONS-1:0]
|
||||||
|
bias_bus,
|
||||||
|
|
||||||
|
output signed [DATA_WIDTH*N_NEURONS-1:0]
|
||||||
|
y_bus,
|
||||||
|
|
||||||
|
output busy,
|
||||||
|
output done
|
||||||
|
);
|
||||||
|
|
||||||
|
wire [N_NEURONS-1:0] neuron_busy;
|
||||||
|
wire [N_NEURONS-1:0] neuron_done;
|
||||||
|
|
||||||
|
genvar n;
|
||||||
|
|
||||||
|
generate
|
||||||
|
|
||||||
|
for (n = 0; n < N_NEURONS; n = n + 1) begin : GEN_NEURON
|
||||||
|
|
||||||
|
neuron_parallel #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.FRAC_BITS(FRAC_BITS),
|
||||||
|
.N_INPUTS(N_INPUTS),
|
||||||
|
.PARALLEL(PARALLEL),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) u_neuron (
|
||||||
|
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.start(start),
|
||||||
|
|
||||||
|
.x_bus(x_bus),
|
||||||
|
|
||||||
|
.w_bus(
|
||||||
|
weights_bus[
|
||||||
|
n*N_INPUTS*DATA_WIDTH
|
||||||
|
+: N_INPUTS*DATA_WIDTH
|
||||||
|
]
|
||||||
|
),
|
||||||
|
|
||||||
|
.bias(
|
||||||
|
bias_bus[
|
||||||
|
n*DATA_WIDTH
|
||||||
|
+: DATA_WIDTH
|
||||||
|
]
|
||||||
|
),
|
||||||
|
|
||||||
|
.y(
|
||||||
|
y_bus[
|
||||||
|
n*DATA_WIDTH
|
||||||
|
+: DATA_WIDTH
|
||||||
|
]
|
||||||
|
),
|
||||||
|
|
||||||
|
.busy(neuron_busy[n]),
|
||||||
|
.done(neuron_done[n])
|
||||||
|
);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign busy = |neuron_busy;
|
||||||
|
assign done = &neuron_done;
|
||||||
|
|
||||||
|
endmodule
|
||||||
+122
@@ -0,0 +1,122 @@
|
|||||||
|
module mac8 #(
|
||||||
|
parameter DATA_WIDTH = 16,
|
||||||
|
parameter ACC_WIDTH = 40
|
||||||
|
)(
|
||||||
|
input signed [DATA_WIDTH*8-1:0] x_bus,
|
||||||
|
input signed [DATA_WIDTH*8-1:0] w_bus,
|
||||||
|
input signed [ACC_WIDTH-1:0] acc_in,
|
||||||
|
output signed [ACC_WIDTH-1:0] acc_out
|
||||||
|
);
|
||||||
|
|
||||||
|
wire signed [ACC_WIDTH-1:0] m0;
|
||||||
|
wire signed [ACC_WIDTH-1:0] m1;
|
||||||
|
wire signed [ACC_WIDTH-1:0] m2;
|
||||||
|
wire signed [ACC_WIDTH-1:0] m3;
|
||||||
|
wire signed [ACC_WIDTH-1:0] m4;
|
||||||
|
wire signed [ACC_WIDTH-1:0] m5;
|
||||||
|
wire signed [ACC_WIDTH-1:0] m6;
|
||||||
|
wire signed [ACC_WIDTH-1:0] m7;
|
||||||
|
|
||||||
|
wire signed [ACC_WIDTH-1:0] s0;
|
||||||
|
wire signed [ACC_WIDTH-1:0] s1;
|
||||||
|
wire signed [ACC_WIDTH-1:0] s2;
|
||||||
|
wire signed [ACC_WIDTH-1:0] s3;
|
||||||
|
|
||||||
|
wire signed [ACC_WIDTH-1:0] s4;
|
||||||
|
wire signed [ACC_WIDTH-1:0] s5;
|
||||||
|
|
||||||
|
wire signed [ACC_WIDTH-1:0] sum;
|
||||||
|
|
||||||
|
mac_unit #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) mac0 (
|
||||||
|
.x(x_bus[0*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.w(w_bus[0*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.acc_in({ACC_WIDTH{1'b0}}),
|
||||||
|
.acc_out(m0)
|
||||||
|
);
|
||||||
|
|
||||||
|
mac_unit #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) mac1 (
|
||||||
|
.x(x_bus[1*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.w(w_bus[1*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.acc_in({ACC_WIDTH{1'b0}}),
|
||||||
|
.acc_out(m1)
|
||||||
|
);
|
||||||
|
|
||||||
|
mac_unit #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) mac2 (
|
||||||
|
.x(x_bus[2*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.w(w_bus[2*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.acc_in({ACC_WIDTH{1'b0}}),
|
||||||
|
.acc_out(m2)
|
||||||
|
);
|
||||||
|
|
||||||
|
mac_unit #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) mac3 (
|
||||||
|
.x(x_bus[3*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.w(w_bus[3*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.acc_in({ACC_WIDTH{1'b0}}),
|
||||||
|
.acc_out(m3)
|
||||||
|
);
|
||||||
|
|
||||||
|
mac_unit #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) mac4 (
|
||||||
|
.x(x_bus[4*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.w(w_bus[4*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.acc_in({ACC_WIDTH{1'b0}}),
|
||||||
|
.acc_out(m4)
|
||||||
|
);
|
||||||
|
|
||||||
|
mac_unit #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) mac5 (
|
||||||
|
.x(x_bus[5*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.w(w_bus[5*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.acc_in({ACC_WIDTH{1'b0}}),
|
||||||
|
.acc_out(m5)
|
||||||
|
);
|
||||||
|
|
||||||
|
mac_unit #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) mac6 (
|
||||||
|
.x(x_bus[6*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.w(w_bus[6*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.acc_in({ACC_WIDTH{1'b0}}),
|
||||||
|
.acc_out(m6)
|
||||||
|
);
|
||||||
|
|
||||||
|
mac_unit #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) mac7 (
|
||||||
|
.x(x_bus[7*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.w(w_bus[7*DATA_WIDTH +: DATA_WIDTH]),
|
||||||
|
.acc_in({ACC_WIDTH{1'b0}}),
|
||||||
|
.acc_out(m7)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign s0 = m0 + m1;
|
||||||
|
assign s1 = m2 + m3;
|
||||||
|
assign s2 = m4 + m5;
|
||||||
|
assign s3 = m6 + m7;
|
||||||
|
|
||||||
|
assign s4 = s0 + s1;
|
||||||
|
assign s5 = s2 + s3;
|
||||||
|
|
||||||
|
assign sum = s4 + s5;
|
||||||
|
|
||||||
|
assign acc_out = acc_in + sum;
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
module mac_unit #(
|
||||||
|
parameter DATA_WIDTH = 16,
|
||||||
|
parameter ACC_WIDTH = 40
|
||||||
|
)(
|
||||||
|
input signed [DATA_WIDTH-1:0] x,
|
||||||
|
input signed [DATA_WIDTH-1:0] w,
|
||||||
|
input signed [ACC_WIDTH-1:0] acc_in,
|
||||||
|
output signed [ACC_WIDTH-1:0] acc_out
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam PROD_WIDTH = 2 * DATA_WIDTH;
|
||||||
|
|
||||||
|
wire signed [PROD_WIDTH-1:0] product;
|
||||||
|
wire signed [ACC_WIDTH-1:0] product_ext;
|
||||||
|
|
||||||
|
assign product = x * w;
|
||||||
|
|
||||||
|
assign product_ext =
|
||||||
|
{{(ACC_WIDTH-PROD_WIDTH){product[PROD_WIDTH-1]}}, product};
|
||||||
|
|
||||||
|
assign acc_out = acc_in + product_ext;
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
module neuron_parallel #(
|
||||||
|
parameter DATA_WIDTH = 16,
|
||||||
|
parameter FRAC_BITS = 8,
|
||||||
|
parameter N_INPUTS = 64,
|
||||||
|
parameter PARALLEL = 8,
|
||||||
|
parameter ACC_WIDTH = 40
|
||||||
|
)(
|
||||||
|
input clk,
|
||||||
|
input rst,
|
||||||
|
input start,
|
||||||
|
|
||||||
|
input signed [DATA_WIDTH*N_INPUTS-1:0] x_bus,
|
||||||
|
input signed [DATA_WIDTH*N_INPUTS-1:0] w_bus,
|
||||||
|
input signed [DATA_WIDTH-1:0] bias,
|
||||||
|
|
||||||
|
output reg signed [DATA_WIDTH-1:0] y,
|
||||||
|
output reg busy,
|
||||||
|
output reg done
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam GROUPS = N_INPUTS / PARALLEL;
|
||||||
|
localparam GROUP_INDEX_WIDTH =
|
||||||
|
(GROUPS <= 1) ? 1 : $clog2(GROUPS);
|
||||||
|
|
||||||
|
reg [GROUP_INDEX_WIDTH-1:0] group_index;
|
||||||
|
|
||||||
|
reg signed [ACC_WIDTH-1:0] acc;
|
||||||
|
|
||||||
|
wire signed [DATA_WIDTH*PARALLEL-1:0] x_group;
|
||||||
|
wire signed [DATA_WIDTH*PARALLEL-1:0] w_group;
|
||||||
|
|
||||||
|
wire signed [ACC_WIDTH-1:0] acc_next;
|
||||||
|
|
||||||
|
wire signed [DATA_WIDTH-1:0] bias_ext_small;
|
||||||
|
wire signed [ACC_WIDTH-1:0] bias_ext;
|
||||||
|
|
||||||
|
wire signed [ACC_WIDTH-1:0] final_acc;
|
||||||
|
wire signed [ACC_WIDTH-1:0] final_value;
|
||||||
|
|
||||||
|
assign x_group =
|
||||||
|
x_bus[group_index*PARALLEL*DATA_WIDTH
|
||||||
|
+: PARALLEL*DATA_WIDTH];
|
||||||
|
|
||||||
|
assign w_group =
|
||||||
|
w_bus[group_index*PARALLEL*DATA_WIDTH
|
||||||
|
+: PARALLEL*DATA_WIDTH];
|
||||||
|
|
||||||
|
mac8 #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) u_mac8 (
|
||||||
|
.x_bus(x_group),
|
||||||
|
.w_bus(w_group),
|
||||||
|
.acc_in(acc),
|
||||||
|
.acc_out(acc_next)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign bias_ext_small = bias;
|
||||||
|
|
||||||
|
assign bias_ext =
|
||||||
|
{{(ACC_WIDTH-DATA_WIDTH){bias_ext_small[DATA_WIDTH-1]}},
|
||||||
|
bias_ext_small};
|
||||||
|
|
||||||
|
assign final_acc =
|
||||||
|
acc_next + (bias_ext <<< FRAC_BITS);
|
||||||
|
|
||||||
|
assign final_value =
|
||||||
|
final_acc >>> FRAC_BITS;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
|
||||||
|
if (rst) begin
|
||||||
|
|
||||||
|
group_index <= 0;
|
||||||
|
acc <= 0;
|
||||||
|
y <= 0;
|
||||||
|
busy <= 0;
|
||||||
|
done <= 0;
|
||||||
|
|
||||||
|
end else begin
|
||||||
|
|
||||||
|
done <= 0;
|
||||||
|
|
||||||
|
if (start && !busy) begin
|
||||||
|
|
||||||
|
group_index <= 0;
|
||||||
|
acc <= 0;
|
||||||
|
busy <= 1;
|
||||||
|
|
||||||
|
end else if (busy) begin
|
||||||
|
|
||||||
|
if (group_index == GROUPS-1) begin
|
||||||
|
|
||||||
|
acc <= final_acc;
|
||||||
|
|
||||||
|
if (final_value <= 0) begin
|
||||||
|
y <= 0;
|
||||||
|
end
|
||||||
|
else if (final_value > 32767) begin
|
||||||
|
y <= 16'sh7FFF;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
y <= final_value[DATA_WIDTH-1:0];
|
||||||
|
end
|
||||||
|
|
||||||
|
busy <= 0;
|
||||||
|
done <= 1;
|
||||||
|
|
||||||
|
end else begin
|
||||||
|
|
||||||
|
acc <= acc_next;
|
||||||
|
group_index <= group_index + 1'b1;
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
+3592
File diff suppressed because one or more lines are too long
Executable
+3916
File diff suppressed because it is too large
Load Diff
+240
@@ -0,0 +1,240 @@
|
|||||||
|
module tb;
|
||||||
|
|
||||||
|
parameter DATA_WIDTH = 16;
|
||||||
|
parameter FRAC_BITS = 8;
|
||||||
|
parameter N_INPUTS = 64;
|
||||||
|
parameter N_NEURONS = 8;
|
||||||
|
parameter PARALLEL = 8;
|
||||||
|
parameter ACC_WIDTH = 40;
|
||||||
|
|
||||||
|
reg clk;
|
||||||
|
reg rst;
|
||||||
|
reg start;
|
||||||
|
|
||||||
|
reg signed [DATA_WIDTH*N_INPUTS-1:0] x_bus;
|
||||||
|
|
||||||
|
reg signed [DATA_WIDTH*N_INPUTS*N_NEURONS-1:0]
|
||||||
|
weights_bus;
|
||||||
|
|
||||||
|
reg signed [DATA_WIDTH*N_NEURONS-1:0]
|
||||||
|
bias_bus;
|
||||||
|
|
||||||
|
wire signed [DATA_WIDTH*N_NEURONS-1:0]
|
||||||
|
y_bus;
|
||||||
|
|
||||||
|
wire busy;
|
||||||
|
wire done;
|
||||||
|
|
||||||
|
integer i;
|
||||||
|
integer n;
|
||||||
|
integer errors;
|
||||||
|
|
||||||
|
layer #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.FRAC_BITS(FRAC_BITS),
|
||||||
|
.N_INPUTS(N_INPUTS),
|
||||||
|
.N_NEURONS(N_NEURONS),
|
||||||
|
.PARALLEL(PARALLEL),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) dut (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.start(start),
|
||||||
|
.x_bus(x_bus),
|
||||||
|
.weights_bus(weights_bus),
|
||||||
|
.bias_bus(bias_bus),
|
||||||
|
.y_bus(y_bus),
|
||||||
|
.busy(busy),
|
||||||
|
.done(done)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
clk = 0;
|
||||||
|
forever #5 clk = ~clk;
|
||||||
|
end
|
||||||
|
|
||||||
|
function signed [15:0] q8_8;
|
||||||
|
input real value;
|
||||||
|
begin
|
||||||
|
q8_8 = $rtoi(value * 256.0);
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
task run_layer;
|
||||||
|
begin
|
||||||
|
@(posedge clk);
|
||||||
|
start = 1;
|
||||||
|
|
||||||
|
@(posedge clk);
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
wait(done == 1);
|
||||||
|
|
||||||
|
@(posedge clk);
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
|
||||||
|
$dumpfile("sim/layer.vcd");
|
||||||
|
$dumpvars(0, tb);
|
||||||
|
|
||||||
|
rst = 1;
|
||||||
|
start = 0;
|
||||||
|
x_bus = 0;
|
||||||
|
weights_bus = 0;
|
||||||
|
bias_bus = 0;
|
||||||
|
errors = 0;
|
||||||
|
|
||||||
|
repeat (2) @(posedge clk);
|
||||||
|
|
||||||
|
rst = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Input vector:
|
||||||
|
* all inputs = 1.0
|
||||||
|
*/
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
x_bus[i*DATA_WIDTH +: DATA_WIDTH] = q8_8(1.0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 0:
|
||||||
|
* weights = 1.0
|
||||||
|
* bias = 0
|
||||||
|
* result = 64
|
||||||
|
*/
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
weights_bus[
|
||||||
|
0*N_INPUTS*DATA_WIDTH +
|
||||||
|
i*DATA_WIDTH +:
|
||||||
|
DATA_WIDTH
|
||||||
|
] = q8_8(1.0);
|
||||||
|
|
||||||
|
bias_bus[0*DATA_WIDTH +: DATA_WIDTH] = q8_8(0.0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 1:
|
||||||
|
* weights = 0.5
|
||||||
|
* result = 32
|
||||||
|
*/
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
weights_bus[
|
||||||
|
1*N_INPUTS*DATA_WIDTH +
|
||||||
|
i*DATA_WIDTH +:
|
||||||
|
DATA_WIDTH
|
||||||
|
] = q8_8(0.5);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 2:
|
||||||
|
* weights = -0.5
|
||||||
|
* result = -32 -> ReLU = 0
|
||||||
|
*/
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
weights_bus[
|
||||||
|
2*N_INPUTS*DATA_WIDTH +
|
||||||
|
i*DATA_WIDTH +:
|
||||||
|
DATA_WIDTH
|
||||||
|
] = q8_8(-0.5);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 3:
|
||||||
|
* weights = 2.0
|
||||||
|
* result = 128 -> saturation = 127.996...
|
||||||
|
*/
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
weights_bus[
|
||||||
|
3*N_INPUTS*DATA_WIDTH +
|
||||||
|
i*DATA_WIDTH +:
|
||||||
|
DATA_WIDTH
|
||||||
|
] = q8_8(2.0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 4:
|
||||||
|
* weights = 0
|
||||||
|
* bias = +1
|
||||||
|
* result = 1
|
||||||
|
*/
|
||||||
|
bias_bus[4*DATA_WIDTH +: DATA_WIDTH] = q8_8(1.0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 5:
|
||||||
|
* weights = 0
|
||||||
|
* bias = -1
|
||||||
|
* ReLU = 0
|
||||||
|
*/
|
||||||
|
bias_bus[5*DATA_WIDTH +: DATA_WIDTH] = q8_8(-1.0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 6:
|
||||||
|
* weights = 1.0
|
||||||
|
* bias = -1.0
|
||||||
|
* result = 63
|
||||||
|
*/
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
weights_bus[
|
||||||
|
6*N_INPUTS*DATA_WIDTH +
|
||||||
|
i*DATA_WIDTH +:
|
||||||
|
DATA_WIDTH
|
||||||
|
] = q8_8(1.0);
|
||||||
|
|
||||||
|
bias_bus[6*DATA_WIDTH +: DATA_WIDTH] = q8_8(-1.0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 7:
|
||||||
|
* weights = 0.25
|
||||||
|
* bias = +1
|
||||||
|
* result = 16 + 1 = 17
|
||||||
|
*/
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
weights_bus[
|
||||||
|
7*N_INPUTS*DATA_WIDTH +
|
||||||
|
i*DATA_WIDTH +:
|
||||||
|
DATA_WIDTH
|
||||||
|
] = q8_8(0.25);
|
||||||
|
|
||||||
|
bias_bus[7*DATA_WIDTH +: DATA_WIDTH] = q8_8(1.0);
|
||||||
|
|
||||||
|
$display("");
|
||||||
|
$display("==============================");
|
||||||
|
$display("LAYER TEST");
|
||||||
|
$display("==============================");
|
||||||
|
|
||||||
|
run_layer;
|
||||||
|
|
||||||
|
$display("Neuron 0 = %5d expected = 16384", y_bus[0*16 +: 16]);
|
||||||
|
$display("Neuron 1 = %5d expected = 8192", y_bus[1*16 +: 16]);
|
||||||
|
$display("Neuron 2 = %5d expected = 0", y_bus[2*16 +: 16]);
|
||||||
|
$display("Neuron 3 = %5d expected = 32767", y_bus[3*16 +: 16]);
|
||||||
|
$display("Neuron 4 = %5d expected = 256", y_bus[4*16 +: 16]);
|
||||||
|
$display("Neuron 5 = %5d expected = 0", y_bus[5*16 +: 16]);
|
||||||
|
$display("Neuron 6 = %5d expected = 16128", y_bus[6*16 +: 16]);
|
||||||
|
$display("Neuron 7 = %5d expected = 4352", y_bus[7*16 +: 16]);
|
||||||
|
|
||||||
|
if (y_bus[0*16 +: 16] !== 16'sd16384) errors = errors + 1;
|
||||||
|
if (y_bus[1*16 +: 16] !== 16'sd8192) errors = errors + 1;
|
||||||
|
if (y_bus[2*16 +: 16] !== 16'sd0) errors = errors + 1;
|
||||||
|
if (y_bus[3*16 +: 16] !== 16'sd32767) errors = errors + 1;
|
||||||
|
if (y_bus[4*16 +: 16] !== 16'sd256) errors = errors + 1;
|
||||||
|
if (y_bus[5*16 +: 16] !== 16'sd0) errors = errors + 1;
|
||||||
|
if (y_bus[6*16 +: 16] !== 16'sd16128) errors = errors + 1;
|
||||||
|
if (y_bus[7*16 +: 16] !== 16'sd4352) errors = errors + 1;
|
||||||
|
|
||||||
|
$display("busy = %0d", busy);
|
||||||
|
$display("done = %0d", done);
|
||||||
|
|
||||||
|
$display("");
|
||||||
|
$display("==============================");
|
||||||
|
|
||||||
|
if (errors == 0)
|
||||||
|
$display("PASS - ALL 8 NEURONS");
|
||||||
|
else
|
||||||
|
$display("FAIL - %0d ERRORS", errors);
|
||||||
|
|
||||||
|
$display("==============================");
|
||||||
|
$display("LAYER TEST FINISHED");
|
||||||
|
$display("");
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,286 @@
|
|||||||
|
`timescale 1ns/1ps
|
||||||
|
|
||||||
|
module tb;
|
||||||
|
|
||||||
|
parameter DATA_WIDTH = 16;
|
||||||
|
parameter FRAC_BITS = 8;
|
||||||
|
parameter N_INPUTS = 64;
|
||||||
|
parameter PARALLEL = 8;
|
||||||
|
parameter ACC_WIDTH = 40;
|
||||||
|
|
||||||
|
reg clk;
|
||||||
|
reg rst;
|
||||||
|
reg start;
|
||||||
|
|
||||||
|
reg signed [DATA_WIDTH*N_INPUTS-1:0] x_bus;
|
||||||
|
reg signed [DATA_WIDTH*N_INPUTS-1:0] w_bus;
|
||||||
|
reg signed [DATA_WIDTH-1:0] bias;
|
||||||
|
|
||||||
|
wire signed [DATA_WIDTH-1:0] y;
|
||||||
|
wire busy;
|
||||||
|
wire done;
|
||||||
|
|
||||||
|
integer i;
|
||||||
|
integer errors;
|
||||||
|
|
||||||
|
neuron_parallel #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.FRAC_BITS(FRAC_BITS),
|
||||||
|
.N_INPUTS(N_INPUTS),
|
||||||
|
.PARALLEL(PARALLEL),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) dut (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.start(start),
|
||||||
|
.x_bus(x_bus),
|
||||||
|
.w_bus(w_bus),
|
||||||
|
.bias(bias),
|
||||||
|
.y(y),
|
||||||
|
.busy(busy),
|
||||||
|
.done(done)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Clock: 10 ns
|
||||||
|
initial begin
|
||||||
|
clk = 0;
|
||||||
|
forever #5 clk = ~clk;
|
||||||
|
end
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// Helper: convert real value to Q8.8
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
function signed [15:0] q8_8;
|
||||||
|
input real value;
|
||||||
|
begin
|
||||||
|
q8_8 = $rtoi(value * 256.0);
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// Start neuron and wait for completion
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
task run_neuron;
|
||||||
|
begin
|
||||||
|
@(posedge clk);
|
||||||
|
start = 1;
|
||||||
|
|
||||||
|
@(posedge clk);
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
wait(done == 1);
|
||||||
|
|
||||||
|
@(posedge clk);
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// TEST 1
|
||||||
|
//
|
||||||
|
// Diverse vector:
|
||||||
|
//
|
||||||
|
// x0 = 1.5 w0 = 2.0 -> 3.0
|
||||||
|
// x1 = 2.0 w1 = -1.0 -> -2.0
|
||||||
|
// x2 = 0.5 w2 = 0.25 -> 0.125
|
||||||
|
//
|
||||||
|
// bias = 0.609375
|
||||||
|
//
|
||||||
|
// total = 1.734375
|
||||||
|
// Q8.8 = 444
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
task test_1;
|
||||||
|
begin
|
||||||
|
$display("");
|
||||||
|
$display("TEST 1: DIVERSE VECTOR");
|
||||||
|
|
||||||
|
x_bus = 0;
|
||||||
|
w_bus = 0;
|
||||||
|
bias = q8_8(0.609375);
|
||||||
|
|
||||||
|
x_bus[0*16 +: 16] = q8_8(1.5);
|
||||||
|
w_bus[0*16 +: 16] = q8_8(2.0);
|
||||||
|
|
||||||
|
x_bus[1*16 +: 16] = q8_8(2.0);
|
||||||
|
w_bus[1*16 +: 16] = q8_8(-1.0);
|
||||||
|
|
||||||
|
x_bus[2*16 +: 16] = q8_8(0.5);
|
||||||
|
w_bus[2*16 +: 16] = q8_8(0.25);
|
||||||
|
|
||||||
|
run_neuron;
|
||||||
|
|
||||||
|
$display("RTL = %0d", y);
|
||||||
|
$display("EXPECTED = 444");
|
||||||
|
|
||||||
|
if (y !== 16'sd444) begin
|
||||||
|
$display("FAIL - TEST 1");
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("PASS - TEST 1");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// TEST 2
|
||||||
|
//
|
||||||
|
// All products negative.
|
||||||
|
// ReLU must force output to zero.
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
task test_2;
|
||||||
|
begin
|
||||||
|
$display("");
|
||||||
|
$display("TEST 2: RELU");
|
||||||
|
|
||||||
|
x_bus = 0;
|
||||||
|
w_bus = 0;
|
||||||
|
bias = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1) begin
|
||||||
|
x_bus[i*16 +: 16] = q8_8(1.0);
|
||||||
|
w_bus[i*16 +: 16] = q8_8(-1.0);
|
||||||
|
end
|
||||||
|
|
||||||
|
run_neuron;
|
||||||
|
|
||||||
|
$display("RTL = %0d", y);
|
||||||
|
$display("EXPECTED = 0");
|
||||||
|
|
||||||
|
if (y !== 16'sd0) begin
|
||||||
|
$display("FAIL - TEST 2");
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("PASS - TEST 2");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// TEST 3
|
||||||
|
//
|
||||||
|
// Large positive result.
|
||||||
|
// Must saturate to +32767.
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
task test_3;
|
||||||
|
begin
|
||||||
|
$display("");
|
||||||
|
$display("TEST 3: POSITIVE SATURATION");
|
||||||
|
|
||||||
|
x_bus = 0;
|
||||||
|
w_bus = 0;
|
||||||
|
bias = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1) begin
|
||||||
|
x_bus[i*16 +: 16] = q8_8(127.0);
|
||||||
|
w_bus[i*16 +: 16] = q8_8(2.0);
|
||||||
|
end
|
||||||
|
|
||||||
|
run_neuron;
|
||||||
|
|
||||||
|
$display("RTL = %0d", y);
|
||||||
|
$display("EXPECTED = 32767");
|
||||||
|
|
||||||
|
if (y !== 16'sd32767) begin
|
||||||
|
$display("FAIL - TEST 3");
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("PASS - TEST 3");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// TEST 4
|
||||||
|
//
|
||||||
|
// Mixed positive/negative products.
|
||||||
|
//
|
||||||
|
// 32 x (+1)
|
||||||
|
// 32 x (-1)
|
||||||
|
// sum = 0
|
||||||
|
// bias = -1
|
||||||
|
//
|
||||||
|
// ReLU -> 0
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
task test_4;
|
||||||
|
begin
|
||||||
|
$display("");
|
||||||
|
$display("TEST 4: MIXED VALUES + NEGATIVE BIAS");
|
||||||
|
|
||||||
|
x_bus = 0;
|
||||||
|
w_bus = 0;
|
||||||
|
bias = q8_8(-1.0);
|
||||||
|
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1) begin
|
||||||
|
if ((i % 2) == 0) begin
|
||||||
|
x_bus[i*16 +: 16] = q8_8(2.0);
|
||||||
|
w_bus[i*16 +: 16] = q8_8(0.5);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
x_bus[i*16 +: 16] = q8_8(-1.0);
|
||||||
|
w_bus[i*16 +: 16] = q8_8(1.0);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
run_neuron;
|
||||||
|
|
||||||
|
$display("RTL = %0d", y);
|
||||||
|
$display("EXPECTED = 0");
|
||||||
|
|
||||||
|
if (y !== 16'sd0) begin
|
||||||
|
$display("FAIL - TEST 4");
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("PASS - TEST 4");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// MAIN
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
initial begin
|
||||||
|
|
||||||
|
$dumpfile("sim/neuron_parallel.vcd");
|
||||||
|
$dumpvars(0, tb);
|
||||||
|
|
||||||
|
rst = 1;
|
||||||
|
start = 0;
|
||||||
|
x_bus = 0;
|
||||||
|
w_bus = 0;
|
||||||
|
bias = 0;
|
||||||
|
errors = 0;
|
||||||
|
|
||||||
|
repeat (2) @(posedge clk);
|
||||||
|
|
||||||
|
rst = 0;
|
||||||
|
|
||||||
|
$display("");
|
||||||
|
$display("==============================");
|
||||||
|
$display("NEURON_PARALLEL TESTBENCH");
|
||||||
|
$display("==============================");
|
||||||
|
|
||||||
|
test_1;
|
||||||
|
test_2;
|
||||||
|
test_3;
|
||||||
|
test_4;
|
||||||
|
|
||||||
|
$display("");
|
||||||
|
$display("==============================");
|
||||||
|
|
||||||
|
if (errors == 0) begin
|
||||||
|
$display("ALL TESTS PASSED");
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
$display("FAILURES = %0d", errors);
|
||||||
|
end
|
||||||
|
|
||||||
|
$display("==============================");
|
||||||
|
$display("");
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Executable
+822
@@ -0,0 +1,822 @@
|
|||||||
|
#! /opt/homebrew/Cellar/icarus-verilog/13.0/bin/vvp
|
||||||
|
:ivl_version "13.0 (stable)" "(v13_0)";
|
||||||
|
:ivl_delay_selection "TYPICAL";
|
||||||
|
:vpi_time_precision - 12;
|
||||||
|
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/system.vpi";
|
||||||
|
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/vhdl_sys.vpi";
|
||||||
|
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/vhdl_textio.vpi";
|
||||||
|
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/v2005_math.vpi";
|
||||||
|
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/va_math.vpi";
|
||||||
|
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/v2009.vpi";
|
||||||
|
S_0x1012719d0 .scope package, "$unit" "$unit" 2 1;
|
||||||
|
.timescale 0 0;
|
||||||
|
S_0x1012716f0 .scope module, "tb" "tb" 3 3;
|
||||||
|
.timescale -9 -12;
|
||||||
|
P_0x7e30a43c0 .param/l "ACC_WIDTH" 0 3 9, +C4<00000000000000000000000000101000>;
|
||||||
|
P_0x7e30a4400 .param/l "DATA_WIDTH" 0 3 5, +C4<00000000000000000000000000010000>;
|
||||||
|
P_0x7e30a4440 .param/l "FRAC_BITS" 0 3 6, +C4<00000000000000000000000000001000>;
|
||||||
|
P_0x7e30a4480 .param/l "N_INPUTS" 0 3 7, +C4<00000000000000000000000001000000>;
|
||||||
|
P_0x7e30a44c0 .param/l "PARALLEL" 0 3 8, +C4<00000000000000000000000000001000>;
|
||||||
|
v0x7e30b9040_0 .var/s "bias", 15 0;
|
||||||
|
v0x7e30b90e0_0 .net "busy", 0 0, v0x7e30b86e0_0; 1 drivers
|
||||||
|
v0x7e30b9180_0 .var "clk", 0 0;
|
||||||
|
v0x7e30b9220_0 .net "done", 0 0, v0x7e30b8820_0; 1 drivers
|
||||||
|
v0x7e30b92c0_0 .var/i "errors", 31 0;
|
||||||
|
v0x7e30b9360_0 .var/i "i", 31 0;
|
||||||
|
v0x7e30b9400_0 .var "rst", 0 0;
|
||||||
|
v0x7e30b94a0_0 .var "start", 0 0;
|
||||||
|
v0x7e30b9540_0 .var/s "w_bus", 1023 0;
|
||||||
|
v0x7e30b95e0_0 .var/s "x_bus", 1023 0;
|
||||||
|
v0x7e30b9680_0 .net/s "y", 15 0, v0x7e30b8e60_0; 1 drivers
|
||||||
|
S_0x1012679f0 .scope module, "dut" "neuron_parallel" 3 32, 4 1 0, S_0x1012716f0;
|
||||||
|
.timescale 0 0;
|
||||||
|
.port_info 0 /INPUT 1 "clk";
|
||||||
|
.port_info 1 /INPUT 1 "rst";
|
||||||
|
.port_info 2 /INPUT 1 "start";
|
||||||
|
.port_info 3 /INPUT 1024 "x_bus";
|
||||||
|
.port_info 4 /INPUT 1024 "w_bus";
|
||||||
|
.port_info 5 /INPUT 16 "bias";
|
||||||
|
.port_info 6 /OUTPUT 16 "y";
|
||||||
|
.port_info 7 /OUTPUT 1 "busy";
|
||||||
|
.port_info 8 /OUTPUT 1 "done";
|
||||||
|
P_0x101267b70 .param/l "ACC_WIDTH" 0 4 6, +C4<00000000000000000000000000101000>;
|
||||||
|
P_0x101267bb0 .param/l "DATA_WIDTH" 0 4 2, +C4<00000000000000000000000000010000>;
|
||||||
|
P_0x101267bf0 .param/l "FRAC_BITS" 0 4 3, +C4<00000000000000000000000000001000>;
|
||||||
|
P_0x101267c30 .param/l "GROUPS" 1 4 21, +C4<00000000000000000000000000001000>;
|
||||||
|
P_0x101267c70 .param/l "GROUP_INDEX_WIDTH" 1 4 22, +C4<00000000000000000000000000000011>;
|
||||||
|
P_0x101267cb0 .param/l "N_INPUTS" 0 4 4, +C4<00000000000000000000000001000000>;
|
||||||
|
P_0x101267cf0 .param/l "PARALLEL" 0 4 5, +C4<00000000000000000000000000001000>;
|
||||||
|
L_0x7e2c2c2a0 .functor BUFZ 16, v0x7e30b9040_0, C4<0000000000000000>, C4<0000000000000000>, C4<0000000000000000>;
|
||||||
|
v0x7e30b7840_0 .net *"_ivl_0", 31 0, L_0x7e30b9720; 1 drivers
|
||||||
|
v0x7e30b78e0_0 .net *"_ivl_11", 31 0, L_0x7e30b9860; 1 drivers
|
||||||
|
v0x7e30b7980_0 .net *"_ivl_14", 31 0, L_0x7e30b9900; 1 drivers
|
||||||
|
L_0x7e28540e8 .functor BUFT 1, C4<00000000000000000000000000000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b7a20_0 .net *"_ivl_17", 28 0, L_0x7e28540e8; 1 drivers
|
||||||
|
L_0x7e2854130 .functor BUFT 1, C4<00000000000000000000000000001000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b7ac0_0 .net/2u *"_ivl_18", 31 0, L_0x7e2854130; 1 drivers
|
||||||
|
v0x7e30b7b60_0 .net *"_ivl_21", 31 0, L_0x7e30b99a0; 1 drivers
|
||||||
|
L_0x7e2854178 .functor BUFT 1, C4<00000000000000000000000000010000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b7c00_0 .net/2u *"_ivl_22", 31 0, L_0x7e2854178; 1 drivers
|
||||||
|
v0x7e30b7ca0_0 .net *"_ivl_25", 31 0, L_0x7e30b9a40; 1 drivers
|
||||||
|
L_0x7e2854010 .functor BUFT 1, C4<00000000000000000000000000000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b7d40_0 .net *"_ivl_3", 28 0, L_0x7e2854010; 1 drivers
|
||||||
|
v0x7e30b7de0_0 .net *"_ivl_31", 0 0, L_0x7e2c857c0; 1 drivers
|
||||||
|
v0x7e30b7e80_0 .net *"_ivl_33", 23 0, L_0x7e2c85860; 1 drivers
|
||||||
|
v0x7e30b7f20_0 .net *"_ivl_36", 39 0, L_0x7e30baf80; 1 drivers
|
||||||
|
v0x7e30b8000_0 .net *"_ivl_38", 31 0, L_0x7e2c85900; 1 drivers
|
||||||
|
L_0x7e2854058 .functor BUFT 1, C4<00000000000000000000000000001000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b80a0_0 .net/2u *"_ivl_4", 31 0, L_0x7e2854058; 1 drivers
|
||||||
|
L_0x7e2854400 .functor BUFT 1, C4<00000000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b8140_0 .net *"_ivl_40", 7 0, L_0x7e2854400; 1 drivers
|
||||||
|
v0x7e30b81e0_0 .net *"_ivl_46", 31 0, L_0x7e2c859a0; 1 drivers
|
||||||
|
v0x7e30b8280_0 .net *"_ivl_7", 31 0, L_0x7e30b97c0; 1 drivers
|
||||||
|
L_0x7e28540a0 .functor BUFT 1, C4<00000000000000000000000000010000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b8320_0 .net/2u *"_ivl_8", 31 0, L_0x7e28540a0; 1 drivers
|
||||||
|
v0x7e30b83c0_0 .var/s "acc", 39 0;
|
||||||
|
v0x7e30b8460_0 .net/s "acc_next", 39 0, L_0x7e2c590e0; 1 drivers
|
||||||
|
v0x7e30b8500_0 .net/s "bias", 15 0, v0x7e30b9040_0; 1 drivers
|
||||||
|
v0x7e30b85a0_0 .net/s "bias_ext", 39 0, L_0x7e30baee0; 1 drivers
|
||||||
|
v0x7e30b8640_0 .net/s "bias_ext_small", 15 0, L_0x7e2c2c2a0; 1 drivers
|
||||||
|
v0x7e30b86e0_0 .var "busy", 0 0;
|
||||||
|
v0x7e30b8780_0 .net "clk", 0 0, v0x7e30b9180_0; 1 drivers
|
||||||
|
v0x7e30b8820_0 .var "done", 0 0;
|
||||||
|
v0x7e30b88c0_0 .net/s "final_acc", 39 0, L_0x7e2c59180; 1 drivers
|
||||||
|
v0x7e30b8960_0 .net/s "final_value", 39 0, L_0x7e30bb020; 1 drivers
|
||||||
|
v0x7e30b8a00_0 .var "group_index", 2 0;
|
||||||
|
v0x7e30b8aa0_0 .net "rst", 0 0, v0x7e30b9400_0; 1 drivers
|
||||||
|
v0x7e30b8b40_0 .net "start", 0 0, v0x7e30b94a0_0; 1 drivers
|
||||||
|
v0x7e30b8be0_0 .net/s "w_bus", 1023 0, v0x7e30b9540_0; 1 drivers
|
||||||
|
v0x7e30b8c80_0 .net/s "w_group", 127 0, L_0x7e2c84320; 1 drivers
|
||||||
|
v0x7e30b8d20_0 .net/s "x_bus", 1023 0, v0x7e30b95e0_0; 1 drivers
|
||||||
|
v0x7e30b8dc0_0 .net/s "x_group", 127 0, L_0x7e2c84280; 1 drivers
|
||||||
|
v0x7e30b8e60_0 .var/s "y", 15 0;
|
||||||
|
E_0x7e2c81380 .event posedge, v0x7e30b8780_0;
|
||||||
|
L_0x7e30b9720 .concat [ 3 29 0 0], v0x7e30b8a00_0, L_0x7e2854010;
|
||||||
|
L_0x7e30b97c0 .arith/mult 32, L_0x7e30b9720, L_0x7e2854058;
|
||||||
|
L_0x7e30b9860 .arith/mult 32, L_0x7e30b97c0, L_0x7e28540a0;
|
||||||
|
L_0x7e2c84280 .part/v v0x7e30b95e0_0, L_0x7e30b9860, 128;
|
||||||
|
L_0x7e30b9900 .concat [ 3 29 0 0], v0x7e30b8a00_0, L_0x7e28540e8;
|
||||||
|
L_0x7e30b99a0 .arith/mult 32, L_0x7e30b9900, L_0x7e2854130;
|
||||||
|
L_0x7e30b9a40 .arith/mult 32, L_0x7e30b99a0, L_0x7e2854178;
|
||||||
|
L_0x7e2c84320 .part/v v0x7e30b9540_0, L_0x7e30b9a40, 128;
|
||||||
|
L_0x7e2c857c0 .part L_0x7e2c2c2a0, 15, 1;
|
||||||
|
L_0x7e2c85860 .repeat 24, 24, L_0x7e2c857c0;
|
||||||
|
L_0x7e30baee0 .concat [ 16 24 0 0], L_0x7e2c2c2a0, L_0x7e2c85860;
|
||||||
|
L_0x7e2c85900 .part L_0x7e30baee0, 0, 32;
|
||||||
|
L_0x7e30baf80 .concat [ 8 32 0 0], L_0x7e2854400, L_0x7e2c85900;
|
||||||
|
L_0x7e2c59180 .arith/sum 40, L_0x7e2c590e0, L_0x7e30baf80;
|
||||||
|
L_0x7e2c859a0 .part L_0x7e2c59180, 8, 32;
|
||||||
|
L_0x7e30bb020 .extend/s 40, L_0x7e2c859a0;
|
||||||
|
S_0x101263710 .scope module, "u_mac8" "mac8" 4 51, 5 1 0, S_0x1012679f0;
|
||||||
|
.timescale 0 0;
|
||||||
|
.port_info 0 /INPUT 128 "x_bus";
|
||||||
|
.port_info 1 /INPUT 128 "w_bus";
|
||||||
|
.port_info 2 /INPUT 40 "acc_in";
|
||||||
|
.port_info 3 /OUTPUT 40 "acc_out";
|
||||||
|
P_0x7e3070b00 .param/l "ACC_WIDTH" 0 5 3, +C4<00000000000000000000000000101000>;
|
||||||
|
P_0x7e3070b40 .param/l "DATA_WIDTH" 0 5 2, +C4<00000000000000000000000000010000>;
|
||||||
|
v0x7e30b6c60_0 .net/s "acc_in", 39 0, v0x7e30b83c0_0; 1 drivers
|
||||||
|
v0x7e30b6d00_0 .net/s "acc_out", 39 0, L_0x7e2c590e0; alias, 1 drivers
|
||||||
|
v0x7e30b6da0_0 .net/s "m0", 39 0, L_0x7e2c58780; 1 drivers
|
||||||
|
v0x7e30b6e40_0 .net/s "m1", 39 0, L_0x7e2c58820; 1 drivers
|
||||||
|
v0x7e30b6ee0_0 .net/s "m2", 39 0, L_0x7e2c588c0; 1 drivers
|
||||||
|
v0x7e30b6f80_0 .net/s "m3", 39 0, L_0x7e2c58960; 1 drivers
|
||||||
|
v0x7e30b7020_0 .net/s "m4", 39 0, L_0x7e2c58a00; 1 drivers
|
||||||
|
v0x7e30b70c0_0 .net/s "m5", 39 0, L_0x7e2c58aa0; 1 drivers
|
||||||
|
v0x7e30b7160_0 .net/s "m6", 39 0, L_0x7e2c58b40; 1 drivers
|
||||||
|
v0x7e30b7200_0 .net/s "m7", 39 0, L_0x7e2c58be0; 1 drivers
|
||||||
|
v0x7e30b72a0_0 .net/s "s0", 39 0, L_0x7e2c58c80; 1 drivers
|
||||||
|
v0x7e30b7340_0 .net/s "s1", 39 0, L_0x7e2c58d20; 1 drivers
|
||||||
|
v0x7e30b73e0_0 .net/s "s2", 39 0, L_0x7e2c58dc0; 1 drivers
|
||||||
|
v0x7e30b7480_0 .net/s "s3", 39 0, L_0x7e2c58e60; 1 drivers
|
||||||
|
v0x7e30b7520_0 .net/s "s4", 39 0, L_0x7e2c58f00; 1 drivers
|
||||||
|
v0x7e30b75c0_0 .net/s "s5", 39 0, L_0x7e2c58fa0; 1 drivers
|
||||||
|
v0x7e30b7660_0 .net/s "sum", 39 0, L_0x7e2c59040; 1 drivers
|
||||||
|
v0x7e30b7700_0 .net/s "w_bus", 127 0, L_0x7e2c84320; alias, 1 drivers
|
||||||
|
v0x7e30b77a0_0 .net/s "x_bus", 127 0, L_0x7e2c84280; alias, 1 drivers
|
||||||
|
L_0x7e2c84500 .part L_0x7e2c84280, 0, 16;
|
||||||
|
L_0x7e2c845a0 .part L_0x7e2c84320, 0, 16;
|
||||||
|
L_0x7e2c84780 .part L_0x7e2c84280, 16, 16;
|
||||||
|
L_0x7e2c84820 .part L_0x7e2c84320, 16, 16;
|
||||||
|
L_0x7e2c84a00 .part L_0x7e2c84280, 32, 16;
|
||||||
|
L_0x7e2c84aa0 .part L_0x7e2c84320, 32, 16;
|
||||||
|
L_0x7e2c84c80 .part L_0x7e2c84280, 48, 16;
|
||||||
|
L_0x7e2c84d20 .part L_0x7e2c84320, 48, 16;
|
||||||
|
L_0x7e2c84f00 .part L_0x7e2c84280, 64, 16;
|
||||||
|
L_0x7e2c84fa0 .part L_0x7e2c84320, 64, 16;
|
||||||
|
L_0x7e2c85180 .part L_0x7e2c84280, 80, 16;
|
||||||
|
L_0x7e2c85220 .part L_0x7e2c84320, 80, 16;
|
||||||
|
L_0x7e2c85400 .part L_0x7e2c84280, 96, 16;
|
||||||
|
L_0x7e2c854a0 .part L_0x7e2c84320, 96, 16;
|
||||||
|
L_0x7e2c85680 .part L_0x7e2c84280, 112, 16;
|
||||||
|
L_0x7e2c85720 .part L_0x7e2c84320, 112, 16;
|
||||||
|
L_0x7e2c58c80 .arith/sum 40, L_0x7e2c58780, L_0x7e2c58820;
|
||||||
|
L_0x7e2c58d20 .arith/sum 40, L_0x7e2c588c0, L_0x7e2c58960;
|
||||||
|
L_0x7e2c58dc0 .arith/sum 40, L_0x7e2c58a00, L_0x7e2c58aa0;
|
||||||
|
L_0x7e2c58e60 .arith/sum 40, L_0x7e2c58b40, L_0x7e2c58be0;
|
||||||
|
L_0x7e2c58f00 .arith/sum 40, L_0x7e2c58c80, L_0x7e2c58d20;
|
||||||
|
L_0x7e2c58fa0 .arith/sum 40, L_0x7e2c58dc0, L_0x7e2c58e60;
|
||||||
|
L_0x7e2c59040 .arith/sum 40, L_0x7e2c58f00, L_0x7e2c58fa0;
|
||||||
|
L_0x7e2c590e0 .arith/sum 40, v0x7e30b83c0_0, L_0x7e2c59040;
|
||||||
|
S_0x101263890 .scope module, "mac0" "mac_unit" 5 33, 6 1 0, S_0x101263710;
|
||||||
|
.timescale 0 0;
|
||||||
|
.port_info 0 /INPUT 16 "x";
|
||||||
|
.port_info 1 /INPUT 16 "w";
|
||||||
|
.port_info 2 /INPUT 40 "acc_in";
|
||||||
|
.port_info 3 /OUTPUT 40 "acc_out";
|
||||||
|
P_0x7e30b0000 .param/l "ACC_WIDTH" 0 6 3, +C4<00000000000000000000000000101000>;
|
||||||
|
P_0x7e30b0040 .param/l "DATA_WIDTH" 0 6 2, +C4<00000000000000000000000000010000>;
|
||||||
|
P_0x7e30b0080 .param/l "PROD_WIDTH" 1 6 11, +C4<0000000000000000000000000000000000000000000000000000000000100000>;
|
||||||
|
v0x101271870_0 .net/s *"_ivl_0", 31 0, L_0x7e30b9ae0; 1 drivers
|
||||||
|
v0x101271b50_0 .net/s *"_ivl_2", 31 0, L_0x7e30b9b80; 1 drivers
|
||||||
|
v0x10126f830_0 .net *"_ivl_7", 0 0, L_0x7e2c843c0; 1 drivers
|
||||||
|
v0x101271ff0_0 .net *"_ivl_9", 7 0, L_0x7e2c84460; 1 drivers
|
||||||
|
L_0x7e28541c0 .functor BUFT 1, C4<0000000000000000000000000000000000000000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x101271e50_0 .net/s "acc_in", 39 0, L_0x7e28541c0; 1 drivers
|
||||||
|
v0x101271cb0_0 .net/s "acc_out", 39 0, L_0x7e2c58780; alias, 1 drivers
|
||||||
|
v0x1012714b0_0 .net/s "product", 31 0, L_0x7e30b9c20; 1 drivers
|
||||||
|
v0x1012712d0_0 .net/s "product_ext", 39 0, L_0x7e30b9cc0; 1 drivers
|
||||||
|
v0x101271090_0 .net/s "w", 15 0, L_0x7e2c845a0; 1 drivers
|
||||||
|
v0x7e30b4000_0 .net/s "x", 15 0, L_0x7e2c84500; 1 drivers
|
||||||
|
L_0x7e30b9ae0 .extend/s 32, L_0x7e2c84500;
|
||||||
|
L_0x7e30b9b80 .extend/s 32, L_0x7e2c845a0;
|
||||||
|
L_0x7e30b9c20 .arith/mult 32, L_0x7e30b9ae0, L_0x7e30b9b80;
|
||||||
|
L_0x7e2c843c0 .part L_0x7e30b9c20, 31, 1;
|
||||||
|
L_0x7e2c84460 .repeat 8, 8, L_0x7e2c843c0;
|
||||||
|
L_0x7e30b9cc0 .concat [ 32 8 0 0], L_0x7e30b9c20, L_0x7e2c84460;
|
||||||
|
L_0x7e2c58780 .arith/sum 40, L_0x7e28541c0, L_0x7e30b9cc0;
|
||||||
|
S_0x10125c9b0 .scope module, "mac1" "mac_unit" 5 43, 6 1 0, S_0x101263710;
|
||||||
|
.timescale 0 0;
|
||||||
|
.port_info 0 /INPUT 16 "x";
|
||||||
|
.port_info 1 /INPUT 16 "w";
|
||||||
|
.port_info 2 /INPUT 40 "acc_in";
|
||||||
|
.port_info 3 /OUTPUT 40 "acc_out";
|
||||||
|
P_0x7e30b00c0 .param/l "ACC_WIDTH" 0 6 3, +C4<00000000000000000000000000101000>;
|
||||||
|
P_0x7e30b0100 .param/l "DATA_WIDTH" 0 6 2, +C4<00000000000000000000000000010000>;
|
||||||
|
P_0x7e30b0140 .param/l "PROD_WIDTH" 1 6 11, +C4<0000000000000000000000000000000000000000000000000000000000100000>;
|
||||||
|
v0x7e30b40a0_0 .net/s *"_ivl_0", 31 0, L_0x7e30b9d60; 1 drivers
|
||||||
|
v0x7e30b4140_0 .net/s *"_ivl_2", 31 0, L_0x7e30b9e00; 1 drivers
|
||||||
|
v0x7e30b41e0_0 .net *"_ivl_7", 0 0, L_0x7e2c84640; 1 drivers
|
||||||
|
v0x7e30b4280_0 .net *"_ivl_9", 7 0, L_0x7e2c846e0; 1 drivers
|
||||||
|
L_0x7e2854208 .functor BUFT 1, C4<0000000000000000000000000000000000000000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b4320_0 .net/s "acc_in", 39 0, L_0x7e2854208; 1 drivers
|
||||||
|
v0x7e30b43c0_0 .net/s "acc_out", 39 0, L_0x7e2c58820; alias, 1 drivers
|
||||||
|
v0x7e30b4460_0 .net/s "product", 31 0, L_0x7e30b9ea0; 1 drivers
|
||||||
|
v0x7e30b4500_0 .net/s "product_ext", 39 0, L_0x7e30b9f40; 1 drivers
|
||||||
|
v0x7e30b45a0_0 .net/s "w", 15 0, L_0x7e2c84820; 1 drivers
|
||||||
|
v0x7e30b4640_0 .net/s "x", 15 0, L_0x7e2c84780; 1 drivers
|
||||||
|
L_0x7e30b9d60 .extend/s 32, L_0x7e2c84780;
|
||||||
|
L_0x7e30b9e00 .extend/s 32, L_0x7e2c84820;
|
||||||
|
L_0x7e30b9ea0 .arith/mult 32, L_0x7e30b9d60, L_0x7e30b9e00;
|
||||||
|
L_0x7e2c84640 .part L_0x7e30b9ea0, 31, 1;
|
||||||
|
L_0x7e2c846e0 .repeat 8, 8, L_0x7e2c84640;
|
||||||
|
L_0x7e30b9f40 .concat [ 32 8 0 0], L_0x7e30b9ea0, L_0x7e2c846e0;
|
||||||
|
L_0x7e2c58820 .arith/sum 40, L_0x7e2854208, L_0x7e30b9f40;
|
||||||
|
S_0x10125cb30 .scope module, "mac2" "mac_unit" 5 53, 6 1 0, S_0x101263710;
|
||||||
|
.timescale 0 0;
|
||||||
|
.port_info 0 /INPUT 16 "x";
|
||||||
|
.port_info 1 /INPUT 16 "w";
|
||||||
|
.port_info 2 /INPUT 40 "acc_in";
|
||||||
|
.port_info 3 /OUTPUT 40 "acc_out";
|
||||||
|
P_0x7e30b0180 .param/l "ACC_WIDTH" 0 6 3, +C4<00000000000000000000000000101000>;
|
||||||
|
P_0x7e30b01c0 .param/l "DATA_WIDTH" 0 6 2, +C4<00000000000000000000000000010000>;
|
||||||
|
P_0x7e30b0200 .param/l "PROD_WIDTH" 1 6 11, +C4<0000000000000000000000000000000000000000000000000000000000100000>;
|
||||||
|
v0x7e30b46e0_0 .net/s *"_ivl_0", 31 0, L_0x7e30b9fe0; 1 drivers
|
||||||
|
v0x7e30b4780_0 .net/s *"_ivl_2", 31 0, L_0x7e30ba080; 1 drivers
|
||||||
|
v0x7e30b4820_0 .net *"_ivl_7", 0 0, L_0x7e2c848c0; 1 drivers
|
||||||
|
v0x7e30b48c0_0 .net *"_ivl_9", 7 0, L_0x7e2c84960; 1 drivers
|
||||||
|
L_0x7e2854250 .functor BUFT 1, C4<0000000000000000000000000000000000000000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b4960_0 .net/s "acc_in", 39 0, L_0x7e2854250; 1 drivers
|
||||||
|
v0x7e30b4a00_0 .net/s "acc_out", 39 0, L_0x7e2c588c0; alias, 1 drivers
|
||||||
|
v0x7e30b4aa0_0 .net/s "product", 31 0, L_0x7e30ba120; 1 drivers
|
||||||
|
v0x7e30b4b40_0 .net/s "product_ext", 39 0, L_0x7e30ba1c0; 1 drivers
|
||||||
|
v0x7e30b4be0_0 .net/s "w", 15 0, L_0x7e2c84aa0; 1 drivers
|
||||||
|
v0x7e30b4c80_0 .net/s "x", 15 0, L_0x7e2c84a00; 1 drivers
|
||||||
|
L_0x7e30b9fe0 .extend/s 32, L_0x7e2c84a00;
|
||||||
|
L_0x7e30ba080 .extend/s 32, L_0x7e2c84aa0;
|
||||||
|
L_0x7e30ba120 .arith/mult 32, L_0x7e30b9fe0, L_0x7e30ba080;
|
||||||
|
L_0x7e2c848c0 .part L_0x7e30ba120, 31, 1;
|
||||||
|
L_0x7e2c84960 .repeat 8, 8, L_0x7e2c848c0;
|
||||||
|
L_0x7e30ba1c0 .concat [ 32 8 0 0], L_0x7e30ba120, L_0x7e2c84960;
|
||||||
|
L_0x7e2c588c0 .arith/sum 40, L_0x7e2854250, L_0x7e30ba1c0;
|
||||||
|
S_0x10125f110 .scope module, "mac3" "mac_unit" 5 63, 6 1 0, S_0x101263710;
|
||||||
|
.timescale 0 0;
|
||||||
|
.port_info 0 /INPUT 16 "x";
|
||||||
|
.port_info 1 /INPUT 16 "w";
|
||||||
|
.port_info 2 /INPUT 40 "acc_in";
|
||||||
|
.port_info 3 /OUTPUT 40 "acc_out";
|
||||||
|
P_0x7e30b0240 .param/l "ACC_WIDTH" 0 6 3, +C4<00000000000000000000000000101000>;
|
||||||
|
P_0x7e30b0280 .param/l "DATA_WIDTH" 0 6 2, +C4<00000000000000000000000000010000>;
|
||||||
|
P_0x7e30b02c0 .param/l "PROD_WIDTH" 1 6 11, +C4<0000000000000000000000000000000000000000000000000000000000100000>;
|
||||||
|
v0x7e30b4d20_0 .net/s *"_ivl_0", 31 0, L_0x7e30ba260; 1 drivers
|
||||||
|
v0x7e30b4dc0_0 .net/s *"_ivl_2", 31 0, L_0x7e30ba300; 1 drivers
|
||||||
|
v0x7e30b4e60_0 .net *"_ivl_7", 0 0, L_0x7e2c84b40; 1 drivers
|
||||||
|
v0x7e30b4f00_0 .net *"_ivl_9", 7 0, L_0x7e2c84be0; 1 drivers
|
||||||
|
L_0x7e2854298 .functor BUFT 1, C4<0000000000000000000000000000000000000000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b4fa0_0 .net/s "acc_in", 39 0, L_0x7e2854298; 1 drivers
|
||||||
|
v0x7e30b5040_0 .net/s "acc_out", 39 0, L_0x7e2c58960; alias, 1 drivers
|
||||||
|
v0x7e30b50e0_0 .net/s "product", 31 0, L_0x7e30ba3a0; 1 drivers
|
||||||
|
v0x7e30b5180_0 .net/s "product_ext", 39 0, L_0x7e30ba440; 1 drivers
|
||||||
|
v0x7e30b5220_0 .net/s "w", 15 0, L_0x7e2c84d20; 1 drivers
|
||||||
|
v0x7e30b52c0_0 .net/s "x", 15 0, L_0x7e2c84c80; 1 drivers
|
||||||
|
L_0x7e30ba260 .extend/s 32, L_0x7e2c84c80;
|
||||||
|
L_0x7e30ba300 .extend/s 32, L_0x7e2c84d20;
|
||||||
|
L_0x7e30ba3a0 .arith/mult 32, L_0x7e30ba260, L_0x7e30ba300;
|
||||||
|
L_0x7e2c84b40 .part L_0x7e30ba3a0, 31, 1;
|
||||||
|
L_0x7e2c84be0 .repeat 8, 8, L_0x7e2c84b40;
|
||||||
|
L_0x7e30ba440 .concat [ 32 8 0 0], L_0x7e30ba3a0, L_0x7e2c84be0;
|
||||||
|
L_0x7e2c58960 .arith/sum 40, L_0x7e2854298, L_0x7e30ba440;
|
||||||
|
S_0x10125f290 .scope module, "mac4" "mac_unit" 5 73, 6 1 0, S_0x101263710;
|
||||||
|
.timescale 0 0;
|
||||||
|
.port_info 0 /INPUT 16 "x";
|
||||||
|
.port_info 1 /INPUT 16 "w";
|
||||||
|
.port_info 2 /INPUT 40 "acc_in";
|
||||||
|
.port_info 3 /OUTPUT 40 "acc_out";
|
||||||
|
P_0x7e30b0300 .param/l "ACC_WIDTH" 0 6 3, +C4<00000000000000000000000000101000>;
|
||||||
|
P_0x7e30b0340 .param/l "DATA_WIDTH" 0 6 2, +C4<00000000000000000000000000010000>;
|
||||||
|
P_0x7e30b0380 .param/l "PROD_WIDTH" 1 6 11, +C4<0000000000000000000000000000000000000000000000000000000000100000>;
|
||||||
|
v0x7e30b5360_0 .net/s *"_ivl_0", 31 0, L_0x7e30ba4e0; 1 drivers
|
||||||
|
v0x7e30b5400_0 .net/s *"_ivl_2", 31 0, L_0x7e30ba580; 1 drivers
|
||||||
|
v0x7e30b54a0_0 .net *"_ivl_7", 0 0, L_0x7e2c84dc0; 1 drivers
|
||||||
|
v0x7e30b5540_0 .net *"_ivl_9", 7 0, L_0x7e2c84e60; 1 drivers
|
||||||
|
L_0x7e28542e0 .functor BUFT 1, C4<0000000000000000000000000000000000000000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b55e0_0 .net/s "acc_in", 39 0, L_0x7e28542e0; 1 drivers
|
||||||
|
v0x7e30b5680_0 .net/s "acc_out", 39 0, L_0x7e2c58a00; alias, 1 drivers
|
||||||
|
v0x7e30b5720_0 .net/s "product", 31 0, L_0x7e30ba620; 1 drivers
|
||||||
|
v0x7e30b57c0_0 .net/s "product_ext", 39 0, L_0x7e30ba6c0; 1 drivers
|
||||||
|
v0x7e30b5860_0 .net/s "w", 15 0, L_0x7e2c84fa0; 1 drivers
|
||||||
|
v0x7e30b5900_0 .net/s "x", 15 0, L_0x7e2c84f00; 1 drivers
|
||||||
|
L_0x7e30ba4e0 .extend/s 32, L_0x7e2c84f00;
|
||||||
|
L_0x7e30ba580 .extend/s 32, L_0x7e2c84fa0;
|
||||||
|
L_0x7e30ba620 .arith/mult 32, L_0x7e30ba4e0, L_0x7e30ba580;
|
||||||
|
L_0x7e2c84dc0 .part L_0x7e30ba620, 31, 1;
|
||||||
|
L_0x7e2c84e60 .repeat 8, 8, L_0x7e2c84dc0;
|
||||||
|
L_0x7e30ba6c0 .concat [ 32 8 0 0], L_0x7e30ba620, L_0x7e2c84e60;
|
||||||
|
L_0x7e2c58a00 .arith/sum 40, L_0x7e28542e0, L_0x7e30ba6c0;
|
||||||
|
S_0x101272590 .scope module, "mac5" "mac_unit" 5 83, 6 1 0, S_0x101263710;
|
||||||
|
.timescale 0 0;
|
||||||
|
.port_info 0 /INPUT 16 "x";
|
||||||
|
.port_info 1 /INPUT 16 "w";
|
||||||
|
.port_info 2 /INPUT 40 "acc_in";
|
||||||
|
.port_info 3 /OUTPUT 40 "acc_out";
|
||||||
|
P_0x7e30b03c0 .param/l "ACC_WIDTH" 0 6 3, +C4<00000000000000000000000000101000>;
|
||||||
|
P_0x7e30b0400 .param/l "DATA_WIDTH" 0 6 2, +C4<00000000000000000000000000010000>;
|
||||||
|
P_0x7e30b0440 .param/l "PROD_WIDTH" 1 6 11, +C4<0000000000000000000000000000000000000000000000000000000000100000>;
|
||||||
|
v0x7e30b59a0_0 .net/s *"_ivl_0", 31 0, L_0x7e30ba760; 1 drivers
|
||||||
|
v0x7e30b5a40_0 .net/s *"_ivl_2", 31 0, L_0x7e30ba800; 1 drivers
|
||||||
|
v0x7e30b5ae0_0 .net *"_ivl_7", 0 0, L_0x7e2c85040; 1 drivers
|
||||||
|
v0x7e30b5b80_0 .net *"_ivl_9", 7 0, L_0x7e2c850e0; 1 drivers
|
||||||
|
L_0x7e2854328 .functor BUFT 1, C4<0000000000000000000000000000000000000000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b5c20_0 .net/s "acc_in", 39 0, L_0x7e2854328; 1 drivers
|
||||||
|
v0x7e30b5cc0_0 .net/s "acc_out", 39 0, L_0x7e2c58aa0; alias, 1 drivers
|
||||||
|
v0x7e30b5d60_0 .net/s "product", 31 0, L_0x7e30ba8a0; 1 drivers
|
||||||
|
v0x7e30b5e00_0 .net/s "product_ext", 39 0, L_0x7e30ba940; 1 drivers
|
||||||
|
v0x7e30b5ea0_0 .net/s "w", 15 0, L_0x7e2c85220; 1 drivers
|
||||||
|
v0x7e30b5f40_0 .net/s "x", 15 0, L_0x7e2c85180; 1 drivers
|
||||||
|
L_0x7e30ba760 .extend/s 32, L_0x7e2c85180;
|
||||||
|
L_0x7e30ba800 .extend/s 32, L_0x7e2c85220;
|
||||||
|
L_0x7e30ba8a0 .arith/mult 32, L_0x7e30ba760, L_0x7e30ba800;
|
||||||
|
L_0x7e2c85040 .part L_0x7e30ba8a0, 31, 1;
|
||||||
|
L_0x7e2c850e0 .repeat 8, 8, L_0x7e2c85040;
|
||||||
|
L_0x7e30ba940 .concat [ 32 8 0 0], L_0x7e30ba8a0, L_0x7e2c850e0;
|
||||||
|
L_0x7e2c58aa0 .arith/sum 40, L_0x7e2854328, L_0x7e30ba940;
|
||||||
|
S_0x1012700f0 .scope module, "mac6" "mac_unit" 5 93, 6 1 0, S_0x101263710;
|
||||||
|
.timescale 0 0;
|
||||||
|
.port_info 0 /INPUT 16 "x";
|
||||||
|
.port_info 1 /INPUT 16 "w";
|
||||||
|
.port_info 2 /INPUT 40 "acc_in";
|
||||||
|
.port_info 3 /OUTPUT 40 "acc_out";
|
||||||
|
P_0x7e30b0480 .param/l "ACC_WIDTH" 0 6 3, +C4<00000000000000000000000000101000>;
|
||||||
|
P_0x7e30b04c0 .param/l "DATA_WIDTH" 0 6 2, +C4<00000000000000000000000000010000>;
|
||||||
|
P_0x7e30b0500 .param/l "PROD_WIDTH" 1 6 11, +C4<0000000000000000000000000000000000000000000000000000000000100000>;
|
||||||
|
v0x7e30b5fe0_0 .net/s *"_ivl_0", 31 0, L_0x7e30ba9e0; 1 drivers
|
||||||
|
v0x7e30b6080_0 .net/s *"_ivl_2", 31 0, L_0x7e30baa80; 1 drivers
|
||||||
|
v0x7e30b6120_0 .net *"_ivl_7", 0 0, L_0x7e2c852c0; 1 drivers
|
||||||
|
v0x7e30b61c0_0 .net *"_ivl_9", 7 0, L_0x7e2c85360; 1 drivers
|
||||||
|
L_0x7e2854370 .functor BUFT 1, C4<0000000000000000000000000000000000000000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b6260_0 .net/s "acc_in", 39 0, L_0x7e2854370; 1 drivers
|
||||||
|
v0x7e30b6300_0 .net/s "acc_out", 39 0, L_0x7e2c58b40; alias, 1 drivers
|
||||||
|
v0x7e30b63a0_0 .net/s "product", 31 0, L_0x7e30bab20; 1 drivers
|
||||||
|
v0x7e30b6440_0 .net/s "product_ext", 39 0, L_0x7e30babc0; 1 drivers
|
||||||
|
v0x7e30b64e0_0 .net/s "w", 15 0, L_0x7e2c854a0; 1 drivers
|
||||||
|
v0x7e30b6580_0 .net/s "x", 15 0, L_0x7e2c85400; 1 drivers
|
||||||
|
L_0x7e30ba9e0 .extend/s 32, L_0x7e2c85400;
|
||||||
|
L_0x7e30baa80 .extend/s 32, L_0x7e2c854a0;
|
||||||
|
L_0x7e30bab20 .arith/mult 32, L_0x7e30ba9e0, L_0x7e30baa80;
|
||||||
|
L_0x7e2c852c0 .part L_0x7e30bab20, 31, 1;
|
||||||
|
L_0x7e2c85360 .repeat 8, 8, L_0x7e2c852c0;
|
||||||
|
L_0x7e30babc0 .concat [ 32 8 0 0], L_0x7e30bab20, L_0x7e2c85360;
|
||||||
|
L_0x7e2c58b40 .arith/sum 40, L_0x7e2854370, L_0x7e30babc0;
|
||||||
|
S_0x101270270 .scope module, "mac7" "mac_unit" 5 103, 6 1 0, S_0x101263710;
|
||||||
|
.timescale 0 0;
|
||||||
|
.port_info 0 /INPUT 16 "x";
|
||||||
|
.port_info 1 /INPUT 16 "w";
|
||||||
|
.port_info 2 /INPUT 40 "acc_in";
|
||||||
|
.port_info 3 /OUTPUT 40 "acc_out";
|
||||||
|
P_0x7e30b0540 .param/l "ACC_WIDTH" 0 6 3, +C4<00000000000000000000000000101000>;
|
||||||
|
P_0x7e30b0580 .param/l "DATA_WIDTH" 0 6 2, +C4<00000000000000000000000000010000>;
|
||||||
|
P_0x7e30b05c0 .param/l "PROD_WIDTH" 1 6 11, +C4<0000000000000000000000000000000000000000000000000000000000100000>;
|
||||||
|
v0x7e30b6620_0 .net/s *"_ivl_0", 31 0, L_0x7e30bac60; 1 drivers
|
||||||
|
v0x7e30b66c0_0 .net/s *"_ivl_2", 31 0, L_0x7e30bad00; 1 drivers
|
||||||
|
v0x7e30b6760_0 .net *"_ivl_7", 0 0, L_0x7e2c85540; 1 drivers
|
||||||
|
v0x7e30b6800_0 .net *"_ivl_9", 7 0, L_0x7e2c855e0; 1 drivers
|
||||||
|
L_0x7e28543b8 .functor BUFT 1, C4<0000000000000000000000000000000000000000>, C4<0>, C4<0>, C4<0>;
|
||||||
|
v0x7e30b68a0_0 .net/s "acc_in", 39 0, L_0x7e28543b8; 1 drivers
|
||||||
|
v0x7e30b6940_0 .net/s "acc_out", 39 0, L_0x7e2c58be0; alias, 1 drivers
|
||||||
|
v0x7e30b69e0_0 .net/s "product", 31 0, L_0x7e30bada0; 1 drivers
|
||||||
|
v0x7e30b6a80_0 .net/s "product_ext", 39 0, L_0x7e30bae40; 1 drivers
|
||||||
|
v0x7e30b6b20_0 .net/s "w", 15 0, L_0x7e2c85720; 1 drivers
|
||||||
|
v0x7e30b6bc0_0 .net/s "x", 15 0, L_0x7e2c85680; 1 drivers
|
||||||
|
L_0x7e30bac60 .extend/s 32, L_0x7e2c85680;
|
||||||
|
L_0x7e30bad00 .extend/s 32, L_0x7e2c85720;
|
||||||
|
L_0x7e30bada0 .arith/mult 32, L_0x7e30bac60, L_0x7e30bad00;
|
||||||
|
L_0x7e2c85540 .part L_0x7e30bada0, 31, 1;
|
||||||
|
L_0x7e2c855e0 .repeat 8, 8, L_0x7e2c85540;
|
||||||
|
L_0x7e30bae40 .concat [ 32 8 0 0], L_0x7e30bada0, L_0x7e2c855e0;
|
||||||
|
L_0x7e2c58be0 .arith/sum 40, L_0x7e28543b8, L_0x7e30bae40;
|
||||||
|
S_0x7e2ca0000 .scope function.vec4.u16, "q8_8" "q8_8" 3 53, 3 53 0, S_0x1012716f0;
|
||||||
|
.timescale -9 -12;
|
||||||
|
; Variable q8_8 is vec4 return value of scope S_0x7e2ca0000
|
||||||
|
v0x7e30b8fa0_0 .var/real "value", 0 0;
|
||||||
|
TD_tb.q8_8 ;
|
||||||
|
%load/real v0x7e30b8fa0_0;
|
||||||
|
%pushi/real 1073741824, 4074; load=256.000
|
||||||
|
%mul/wr;
|
||||||
|
%vpi_func 3 56 "$rtoi" 32, W<0,r> {0 1 0};
|
||||||
|
%pad/s 16;
|
||||||
|
%ret/vec4 0, 0, 16; Assign to q8_8 (store_vec4_to_lval)
|
||||||
|
%end;
|
||||||
|
S_0x7e2ca0180 .scope task, "run_neuron" "run_neuron" 3 63, 3 63 0, S_0x1012716f0;
|
||||||
|
.timescale -9 -12;
|
||||||
|
E_0x7e2c81600 .event anyedge, v0x7e30b8820_0;
|
||||||
|
TD_tb.run_neuron ;
|
||||||
|
%wait E_0x7e2c81380;
|
||||||
|
%pushi/vec4 1, 0, 1;
|
||||||
|
%store/vec4 v0x7e30b94a0_0, 0, 1;
|
||||||
|
%wait E_0x7e2c81380;
|
||||||
|
%pushi/vec4 0, 0, 1;
|
||||||
|
%store/vec4 v0x7e30b94a0_0, 0, 1;
|
||||||
|
T_1.0 ;
|
||||||
|
%load/vec4 v0x7e30b9220_0;
|
||||||
|
%pad/u 32;
|
||||||
|
%pushi/vec4 1, 0, 32;
|
||||||
|
%cmp/e;
|
||||||
|
%flag_get/vec4 4;
|
||||||
|
%cmpi/ne 1, 0, 1;
|
||||||
|
%jmp/0xz T_1.1, 6;
|
||||||
|
%wait E_0x7e2c81600;
|
||||||
|
%jmp T_1.0;
|
||||||
|
T_1.1 ;
|
||||||
|
%wait E_0x7e2c81380;
|
||||||
|
%end;
|
||||||
|
S_0x7e2ca0300 .scope task, "test_1" "test_1" 3 91, 3 91 0, S_0x1012716f0;
|
||||||
|
.timescale -9 -12;
|
||||||
|
TD_tb.test_1 ;
|
||||||
|
%vpi_call/w 3 93 "$display", "\000" {0 0 0};
|
||||||
|
%vpi_call/w 3 94 "$display", "TEST 1: DIVERSE VECTOR" {0 0 0};
|
||||||
|
%pushi/vec4 0, 0, 1024;
|
||||||
|
%store/vec4 v0x7e30b95e0_0, 0, 1024;
|
||||||
|
%pushi/vec4 0, 0, 1024;
|
||||||
|
%store/vec4 v0x7e30b9540_0, 0, 1024;
|
||||||
|
%pushi/real 1308622848, 4065; load=0.609375
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%store/vec4 v0x7e30b9040_0, 0, 16;
|
||||||
|
%pushi/real 1610612736, 4066; load=1.50000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%ix/load 4, 0, 0;
|
||||||
|
%flag_set/imm 4, 0;
|
||||||
|
%store/vec4 v0x7e30b95e0_0, 4, 16;
|
||||||
|
%pushi/real 1073741824, 4067; load=2.00000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%ix/load 4, 0, 0;
|
||||||
|
%flag_set/imm 4, 0;
|
||||||
|
%store/vec4 v0x7e30b9540_0, 4, 16;
|
||||||
|
%pushi/real 1073741824, 4067; load=2.00000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%ix/load 4, 16, 0;
|
||||||
|
%flag_set/imm 4, 0;
|
||||||
|
%store/vec4 v0x7e30b95e0_0, 4, 16;
|
||||||
|
%pushi/real 1073741824, 20450; load=-1.00000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%ix/load 4, 16, 0;
|
||||||
|
%flag_set/imm 4, 0;
|
||||||
|
%store/vec4 v0x7e30b9540_0, 4, 16;
|
||||||
|
%pushi/real 1073741824, 4065; load=0.500000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%ix/load 4, 32, 0;
|
||||||
|
%flag_set/imm 4, 0;
|
||||||
|
%store/vec4 v0x7e30b95e0_0, 4, 16;
|
||||||
|
%pushi/real 1073741824, 4064; load=0.250000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%ix/load 4, 32, 0;
|
||||||
|
%flag_set/imm 4, 0;
|
||||||
|
%store/vec4 v0x7e30b9540_0, 4, 16;
|
||||||
|
%fork TD_tb.run_neuron, S_0x7e2ca0180;
|
||||||
|
%join;
|
||||||
|
%vpi_call/w 3 111 "$display", "RTL = %0d", v0x7e30b9680_0 {0 0 0};
|
||||||
|
%vpi_call/w 3 112 "$display", "EXPECTED = 444" {0 0 0};
|
||||||
|
%load/vec4 v0x7e30b9680_0;
|
||||||
|
%cmpi/ne 444, 0, 16;
|
||||||
|
%jmp/0xz T_2.2, 6;
|
||||||
|
%vpi_call/w 3 115 "$display", "FAIL - TEST 1" {0 0 0};
|
||||||
|
%load/vec4 v0x7e30b92c0_0;
|
||||||
|
%addi 1, 0, 32;
|
||||||
|
%store/vec4 v0x7e30b92c0_0, 0, 32;
|
||||||
|
%jmp T_2.3;
|
||||||
|
T_2.2 ;
|
||||||
|
%vpi_call/w 3 119 "$display", "PASS - TEST 1" {0 0 0};
|
||||||
|
T_2.3 ;
|
||||||
|
%end;
|
||||||
|
S_0x7e2ca0480 .scope task, "test_2" "test_2" 3 130, 3 130 0, S_0x1012716f0;
|
||||||
|
.timescale -9 -12;
|
||||||
|
TD_tb.test_2 ;
|
||||||
|
%vpi_call/w 3 132 "$display", "\000" {0 0 0};
|
||||||
|
%vpi_call/w 3 133 "$display", "TEST 2: RELU" {0 0 0};
|
||||||
|
%pushi/vec4 0, 0, 1024;
|
||||||
|
%store/vec4 v0x7e30b95e0_0, 0, 1024;
|
||||||
|
%pushi/vec4 0, 0, 1024;
|
||||||
|
%store/vec4 v0x7e30b9540_0, 0, 1024;
|
||||||
|
%pushi/vec4 0, 0, 16;
|
||||||
|
%store/vec4 v0x7e30b9040_0, 0, 16;
|
||||||
|
%pushi/vec4 0, 0, 32;
|
||||||
|
%store/vec4 v0x7e30b9360_0, 0, 32;
|
||||||
|
T_3.4 ; Top of for-loop
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%cmpi/s 64, 0, 32;
|
||||||
|
%jmp/0xz T_3.5, 5;
|
||||||
|
%pushi/real 1073741824, 4066; load=1.00000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%muli 16, 0, 32;
|
||||||
|
%ix/vec4/s 4;
|
||||||
|
%store/vec4 v0x7e30b95e0_0, 4, 16;
|
||||||
|
%pushi/real 1073741824, 20450; load=-1.00000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%muli 16, 0, 32;
|
||||||
|
%ix/vec4/s 4;
|
||||||
|
%store/vec4 v0x7e30b9540_0, 4, 16;
|
||||||
|
T_3.6 ; for-loop step statement
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%addi 1, 0, 32;
|
||||||
|
%store/vec4 v0x7e30b9360_0, 0, 32;
|
||||||
|
%jmp T_3.4;
|
||||||
|
T_3.5 ; for-loop exit label
|
||||||
|
%fork TD_tb.run_neuron, S_0x7e2ca0180;
|
||||||
|
%join;
|
||||||
|
%vpi_call/w 3 146 "$display", "RTL = %0d", v0x7e30b9680_0 {0 0 0};
|
||||||
|
%vpi_call/w 3 147 "$display", "EXPECTED = 0" {0 0 0};
|
||||||
|
%load/vec4 v0x7e30b9680_0;
|
||||||
|
%cmpi/ne 0, 0, 16;
|
||||||
|
%jmp/0xz T_3.7, 6;
|
||||||
|
%vpi_call/w 3 150 "$display", "FAIL - TEST 2" {0 0 0};
|
||||||
|
%load/vec4 v0x7e30b92c0_0;
|
||||||
|
%addi 1, 0, 32;
|
||||||
|
%store/vec4 v0x7e30b92c0_0, 0, 32;
|
||||||
|
%jmp T_3.8;
|
||||||
|
T_3.7 ;
|
||||||
|
%vpi_call/w 3 154 "$display", "PASS - TEST 2" {0 0 0};
|
||||||
|
T_3.8 ;
|
||||||
|
%end;
|
||||||
|
S_0x7e2ca0600 .scope task, "test_3" "test_3" 3 165, 3 165 0, S_0x1012716f0;
|
||||||
|
.timescale -9 -12;
|
||||||
|
TD_tb.test_3 ;
|
||||||
|
%vpi_call/w 3 167 "$display", "\000" {0 0 0};
|
||||||
|
%vpi_call/w 3 168 "$display", "TEST 3: POSITIVE SATURATION" {0 0 0};
|
||||||
|
%pushi/vec4 0, 0, 1024;
|
||||||
|
%store/vec4 v0x7e30b95e0_0, 0, 1024;
|
||||||
|
%pushi/vec4 0, 0, 1024;
|
||||||
|
%store/vec4 v0x7e30b9540_0, 0, 1024;
|
||||||
|
%pushi/vec4 0, 0, 16;
|
||||||
|
%store/vec4 v0x7e30b9040_0, 0, 16;
|
||||||
|
%pushi/vec4 0, 0, 32;
|
||||||
|
%store/vec4 v0x7e30b9360_0, 0, 32;
|
||||||
|
T_4.9 ; Top of for-loop
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%cmpi/s 64, 0, 32;
|
||||||
|
%jmp/0xz T_4.10, 5;
|
||||||
|
%pushi/real 2130706432, 4072; load=127.000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%muli 16, 0, 32;
|
||||||
|
%ix/vec4/s 4;
|
||||||
|
%store/vec4 v0x7e30b95e0_0, 4, 16;
|
||||||
|
%pushi/real 1073741824, 4067; load=2.00000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%muli 16, 0, 32;
|
||||||
|
%ix/vec4/s 4;
|
||||||
|
%store/vec4 v0x7e30b9540_0, 4, 16;
|
||||||
|
T_4.11 ; for-loop step statement
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%addi 1, 0, 32;
|
||||||
|
%store/vec4 v0x7e30b9360_0, 0, 32;
|
||||||
|
%jmp T_4.9;
|
||||||
|
T_4.10 ; for-loop exit label
|
||||||
|
%fork TD_tb.run_neuron, S_0x7e2ca0180;
|
||||||
|
%join;
|
||||||
|
%vpi_call/w 3 181 "$display", "RTL = %0d", v0x7e30b9680_0 {0 0 0};
|
||||||
|
%vpi_call/w 3 182 "$display", "EXPECTED = 32767" {0 0 0};
|
||||||
|
%load/vec4 v0x7e30b9680_0;
|
||||||
|
%cmpi/ne 32767, 0, 16;
|
||||||
|
%jmp/0xz T_4.12, 6;
|
||||||
|
%vpi_call/w 3 185 "$display", "FAIL - TEST 3" {0 0 0};
|
||||||
|
%load/vec4 v0x7e30b92c0_0;
|
||||||
|
%addi 1, 0, 32;
|
||||||
|
%store/vec4 v0x7e30b92c0_0, 0, 32;
|
||||||
|
%jmp T_4.13;
|
||||||
|
T_4.12 ;
|
||||||
|
%vpi_call/w 3 189 "$display", "PASS - TEST 3" {0 0 0};
|
||||||
|
T_4.13 ;
|
||||||
|
%end;
|
||||||
|
S_0x7e2ca0780 .scope task, "test_4" "test_4" 3 206, 3 206 0, S_0x1012716f0;
|
||||||
|
.timescale -9 -12;
|
||||||
|
TD_tb.test_4 ;
|
||||||
|
%vpi_call/w 3 208 "$display", "\000" {0 0 0};
|
||||||
|
%vpi_call/w 3 209 "$display", "TEST 4: MIXED VALUES + NEGATIVE BIAS" {0 0 0};
|
||||||
|
%pushi/vec4 0, 0, 1024;
|
||||||
|
%store/vec4 v0x7e30b95e0_0, 0, 1024;
|
||||||
|
%pushi/vec4 0, 0, 1024;
|
||||||
|
%store/vec4 v0x7e30b9540_0, 0, 1024;
|
||||||
|
%pushi/real 1073741824, 20450; load=-1.00000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%store/vec4 v0x7e30b9040_0, 0, 16;
|
||||||
|
%pushi/vec4 0, 0, 32;
|
||||||
|
%store/vec4 v0x7e30b9360_0, 0, 32;
|
||||||
|
T_5.14 ; Top of for-loop
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%cmpi/s 64, 0, 32;
|
||||||
|
%jmp/0xz T_5.15, 5;
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%pushi/vec4 2, 0, 32;
|
||||||
|
%mod/s;
|
||||||
|
%cmpi/e 0, 0, 32;
|
||||||
|
%jmp/0xz T_5.17, 4;
|
||||||
|
%pushi/real 1073741824, 4067; load=2.00000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%muli 16, 0, 32;
|
||||||
|
%ix/vec4/s 4;
|
||||||
|
%store/vec4 v0x7e30b95e0_0, 4, 16;
|
||||||
|
%pushi/real 1073741824, 4065; load=0.500000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%muli 16, 0, 32;
|
||||||
|
%ix/vec4/s 4;
|
||||||
|
%store/vec4 v0x7e30b9540_0, 4, 16;
|
||||||
|
%jmp T_5.18;
|
||||||
|
T_5.17 ;
|
||||||
|
%pushi/real 1073741824, 20450; load=-1.00000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%muli 16, 0, 32;
|
||||||
|
%ix/vec4/s 4;
|
||||||
|
%store/vec4 v0x7e30b95e0_0, 4, 16;
|
||||||
|
%pushi/real 1073741824, 4066; load=1.00000
|
||||||
|
%store/real v0x7e30b8fa0_0;
|
||||||
|
%callf/vec4 TD_tb.q8_8, S_0x7e2ca0000;
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%muli 16, 0, 32;
|
||||||
|
%ix/vec4/s 4;
|
||||||
|
%store/vec4 v0x7e30b9540_0, 4, 16;
|
||||||
|
T_5.18 ;
|
||||||
|
T_5.16 ; for-loop step statement
|
||||||
|
%load/vec4 v0x7e30b9360_0;
|
||||||
|
%addi 1, 0, 32;
|
||||||
|
%store/vec4 v0x7e30b9360_0, 0, 32;
|
||||||
|
%jmp T_5.14;
|
||||||
|
T_5.15 ; for-loop exit label
|
||||||
|
%fork TD_tb.run_neuron, S_0x7e2ca0180;
|
||||||
|
%join;
|
||||||
|
%vpi_call/w 3 228 "$display", "RTL = %0d", v0x7e30b9680_0 {0 0 0};
|
||||||
|
%vpi_call/w 3 229 "$display", "EXPECTED = 0" {0 0 0};
|
||||||
|
%load/vec4 v0x7e30b9680_0;
|
||||||
|
%cmpi/ne 0, 0, 16;
|
||||||
|
%jmp/0xz T_5.19, 6;
|
||||||
|
%vpi_call/w 3 232 "$display", "FAIL - TEST 4" {0 0 0};
|
||||||
|
%load/vec4 v0x7e30b92c0_0;
|
||||||
|
%addi 1, 0, 32;
|
||||||
|
%store/vec4 v0x7e30b92c0_0, 0, 32;
|
||||||
|
%jmp T_5.20;
|
||||||
|
T_5.19 ;
|
||||||
|
%vpi_call/w 3 236 "$display", "PASS - TEST 4" {0 0 0};
|
||||||
|
T_5.20 ;
|
||||||
|
%end;
|
||||||
|
.scope S_0x1012679f0;
|
||||||
|
T_6 ;
|
||||||
|
%wait E_0x7e2c81380;
|
||||||
|
%load/vec4 v0x7e30b8aa0_0;
|
||||||
|
%flag_set/vec4 8;
|
||||||
|
%jmp/0xz T_6.0, 8;
|
||||||
|
%pushi/vec4 0, 0, 3;
|
||||||
|
%assign/vec4 v0x7e30b8a00_0, 0;
|
||||||
|
%pushi/vec4 0, 0, 40;
|
||||||
|
%assign/vec4 v0x7e30b83c0_0, 0;
|
||||||
|
%pushi/vec4 0, 0, 16;
|
||||||
|
%assign/vec4 v0x7e30b8e60_0, 0;
|
||||||
|
%pushi/vec4 0, 0, 1;
|
||||||
|
%assign/vec4 v0x7e30b86e0_0, 0;
|
||||||
|
%pushi/vec4 0, 0, 1;
|
||||||
|
%assign/vec4 v0x7e30b8820_0, 0;
|
||||||
|
%jmp T_6.1;
|
||||||
|
T_6.0 ;
|
||||||
|
%pushi/vec4 0, 0, 1;
|
||||||
|
%assign/vec4 v0x7e30b8820_0, 0;
|
||||||
|
%load/vec4 v0x7e30b8b40_0;
|
||||||
|
%flag_set/vec4 9;
|
||||||
|
%flag_get/vec4 9;
|
||||||
|
%jmp/0 T_6.4, 9;
|
||||||
|
%load/vec4 v0x7e30b86e0_0;
|
||||||
|
%nor/r;
|
||||||
|
%and;
|
||||||
|
T_6.4;
|
||||||
|
%flag_set/vec4 8;
|
||||||
|
%jmp/0xz T_6.2, 8;
|
||||||
|
%pushi/vec4 0, 0, 3;
|
||||||
|
%assign/vec4 v0x7e30b8a00_0, 0;
|
||||||
|
%pushi/vec4 0, 0, 40;
|
||||||
|
%assign/vec4 v0x7e30b83c0_0, 0;
|
||||||
|
%pushi/vec4 1, 0, 1;
|
||||||
|
%assign/vec4 v0x7e30b86e0_0, 0;
|
||||||
|
%jmp T_6.3;
|
||||||
|
T_6.2 ;
|
||||||
|
%load/vec4 v0x7e30b86e0_0;
|
||||||
|
%flag_set/vec4 8;
|
||||||
|
%jmp/0xz T_6.5, 8;
|
||||||
|
%load/vec4 v0x7e30b8a00_0;
|
||||||
|
%pad/u 32;
|
||||||
|
%cmpi/e 7, 0, 32;
|
||||||
|
%jmp/0xz T_6.7, 4;
|
||||||
|
%load/vec4 v0x7e30b88c0_0;
|
||||||
|
%assign/vec4 v0x7e30b83c0_0, 0;
|
||||||
|
%load/vec4 v0x7e30b8960_0;
|
||||||
|
%cmpi/s 0, 0, 40;
|
||||||
|
%flag_or 5, 4;
|
||||||
|
%jmp/0xz T_6.9, 5;
|
||||||
|
%pushi/vec4 0, 0, 16;
|
||||||
|
%assign/vec4 v0x7e30b8e60_0, 0;
|
||||||
|
%jmp T_6.10;
|
||||||
|
T_6.9 ;
|
||||||
|
%load/vec4 v0x7e30b8960_0;
|
||||||
|
%cmpi/s 32767, 0, 40;
|
||||||
|
%flag_or 5, 4; GT is !LE
|
||||||
|
%flag_inv 5;
|
||||||
|
%jmp/0xz T_6.11, 5;
|
||||||
|
%pushi/vec4 32767, 0, 16;
|
||||||
|
%assign/vec4 v0x7e30b8e60_0, 0;
|
||||||
|
%jmp T_6.12;
|
||||||
|
T_6.11 ;
|
||||||
|
%load/vec4 v0x7e30b8960_0;
|
||||||
|
%parti/s 16, 0, 2;
|
||||||
|
%assign/vec4 v0x7e30b8e60_0, 0;
|
||||||
|
T_6.12 ;
|
||||||
|
T_6.10 ;
|
||||||
|
%pushi/vec4 0, 0, 1;
|
||||||
|
%assign/vec4 v0x7e30b86e0_0, 0;
|
||||||
|
%pushi/vec4 1, 0, 1;
|
||||||
|
%assign/vec4 v0x7e30b8820_0, 0;
|
||||||
|
%jmp T_6.8;
|
||||||
|
T_6.7 ;
|
||||||
|
%load/vec4 v0x7e30b8460_0;
|
||||||
|
%assign/vec4 v0x7e30b83c0_0, 0;
|
||||||
|
%load/vec4 v0x7e30b8a00_0;
|
||||||
|
%addi 1, 0, 3;
|
||||||
|
%assign/vec4 v0x7e30b8a00_0, 0;
|
||||||
|
T_6.8 ;
|
||||||
|
T_6.5 ;
|
||||||
|
T_6.3 ;
|
||||||
|
T_6.1 ;
|
||||||
|
%jmp T_6;
|
||||||
|
.thread T_6;
|
||||||
|
.scope S_0x1012716f0;
|
||||||
|
T_7 ;
|
||||||
|
%pushi/vec4 0, 0, 1;
|
||||||
|
%store/vec4 v0x7e30b9180_0, 0, 1;
|
||||||
|
T_7.0 ;
|
||||||
|
%delay 5000, 0;
|
||||||
|
%load/vec4 v0x7e30b9180_0;
|
||||||
|
%inv;
|
||||||
|
%store/vec4 v0x7e30b9180_0, 0, 1;
|
||||||
|
%jmp T_7.0;
|
||||||
|
T_7.1 ;
|
||||||
|
%end;
|
||||||
|
.thread T_7;
|
||||||
|
.scope S_0x1012716f0;
|
||||||
|
T_8 ;
|
||||||
|
%vpi_call/w 3 246 "$dumpfile", "sim/neuron_parallel.vcd" {0 0 0};
|
||||||
|
%vpi_call/w 3 247 "$dumpvars", 32'sb00000000000000000000000000000000, S_0x1012716f0 {0 0 0};
|
||||||
|
%pushi/vec4 1, 0, 1;
|
||||||
|
%store/vec4 v0x7e30b9400_0, 0, 1;
|
||||||
|
%pushi/vec4 0, 0, 1;
|
||||||
|
%store/vec4 v0x7e30b94a0_0, 0, 1;
|
||||||
|
%pushi/vec4 0, 0, 1024;
|
||||||
|
%store/vec4 v0x7e30b95e0_0, 0, 1024;
|
||||||
|
%pushi/vec4 0, 0, 1024;
|
||||||
|
%store/vec4 v0x7e30b9540_0, 0, 1024;
|
||||||
|
%pushi/vec4 0, 0, 16;
|
||||||
|
%store/vec4 v0x7e30b9040_0, 0, 16;
|
||||||
|
%pushi/vec4 0, 0, 32;
|
||||||
|
%store/vec4 v0x7e30b92c0_0, 0, 32;
|
||||||
|
%pushi/vec4 2, 0, 32;
|
||||||
|
T_8.0 %dup/vec4;
|
||||||
|
%cmpi/s 0, 0, 32;
|
||||||
|
%jmp/1xz T_8.1, 5;
|
||||||
|
%jmp/1 T_8.1, 4;
|
||||||
|
%subi 1, 0, 32;
|
||||||
|
%wait E_0x7e2c81380;
|
||||||
|
%jmp T_8.0;
|
||||||
|
T_8.1 ;
|
||||||
|
%pop/vec4 1;
|
||||||
|
%pushi/vec4 0, 0, 1;
|
||||||
|
%store/vec4 v0x7e30b9400_0, 0, 1;
|
||||||
|
%vpi_call/w 3 260 "$display", "\000" {0 0 0};
|
||||||
|
%vpi_call/w 3 261 "$display", "==============================" {0 0 0};
|
||||||
|
%vpi_call/w 3 262 "$display", "NEURON_PARALLEL TESTBENCH" {0 0 0};
|
||||||
|
%vpi_call/w 3 263 "$display", "==============================" {0 0 0};
|
||||||
|
%fork TD_tb.test_1, S_0x7e2ca0300;
|
||||||
|
%join;
|
||||||
|
%fork TD_tb.test_2, S_0x7e2ca0480;
|
||||||
|
%join;
|
||||||
|
%fork TD_tb.test_3, S_0x7e2ca0600;
|
||||||
|
%join;
|
||||||
|
%fork TD_tb.test_4, S_0x7e2ca0780;
|
||||||
|
%join;
|
||||||
|
%vpi_call/w 3 270 "$display", "\000" {0 0 0};
|
||||||
|
%vpi_call/w 3 271 "$display", "==============================" {0 0 0};
|
||||||
|
%load/vec4 v0x7e30b92c0_0;
|
||||||
|
%cmpi/e 0, 0, 32;
|
||||||
|
%jmp/0xz T_8.2, 4;
|
||||||
|
%vpi_call/w 3 274 "$display", "ALL TESTS PASSED" {0 0 0};
|
||||||
|
%jmp T_8.3;
|
||||||
|
T_8.2 ;
|
||||||
|
%vpi_call/w 3 277 "$display", "FAILURES = %0d", v0x7e30b92c0_0 {0 0 0};
|
||||||
|
T_8.3 ;
|
||||||
|
%vpi_call/w 3 280 "$display", "==============================" {0 0 0};
|
||||||
|
%vpi_call/w 3 281 "$display", "\000" {0 0 0};
|
||||||
|
%vpi_call/w 3 283 "$finish" {0 0 0};
|
||||||
|
%end;
|
||||||
|
.thread T_8;
|
||||||
|
# The file index is used to find the file name in the following table.
|
||||||
|
:file_names 7;
|
||||||
|
"N/A";
|
||||||
|
"<interactive>";
|
||||||
|
"-";
|
||||||
|
"sim/neuron_parallel_tb.v";
|
||||||
|
"rtl/neuron_parallel.v";
|
||||||
|
"rtl/mac8.v";
|
||||||
|
"rtl/mac_unit.v";
|
||||||
+1838
File diff suppressed because it is too large
Load Diff
Executable
+2118
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,352 @@
|
|||||||
|
`timescale 1ns/1ps
|
||||||
|
|
||||||
|
module tb;
|
||||||
|
|
||||||
|
parameter DATA_WIDTH = 16;
|
||||||
|
parameter FRAC_BITS = 8;
|
||||||
|
parameter N_INPUTS = 32;
|
||||||
|
parameter N_NEURONS = 4;
|
||||||
|
parameter PARALLEL = 8;
|
||||||
|
parameter ACC_WIDTH = 40;
|
||||||
|
|
||||||
|
reg clk;
|
||||||
|
reg rst;
|
||||||
|
reg start;
|
||||||
|
|
||||||
|
reg signed [DATA_WIDTH*N_INPUTS-1:0] x_bus;
|
||||||
|
|
||||||
|
reg signed [DATA_WIDTH*N_INPUTS*N_NEURONS-1:0]
|
||||||
|
weights_bus;
|
||||||
|
|
||||||
|
reg signed [DATA_WIDTH*N_NEURONS-1:0]
|
||||||
|
bias_bus;
|
||||||
|
|
||||||
|
wire signed [DATA_WIDTH*N_NEURONS-1:0]
|
||||||
|
y_bus;
|
||||||
|
|
||||||
|
wire busy;
|
||||||
|
wire done;
|
||||||
|
|
||||||
|
integer i;
|
||||||
|
integer n;
|
||||||
|
integer errors;
|
||||||
|
integer expected;
|
||||||
|
|
||||||
|
layer #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.FRAC_BITS(FRAC_BITS),
|
||||||
|
.N_INPUTS(N_INPUTS),
|
||||||
|
.N_NEURONS(N_NEURONS),
|
||||||
|
.PARALLEL(PARALLEL),
|
||||||
|
.ACC_WIDTH(ACC_WIDTH)
|
||||||
|
) dut (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.start(start),
|
||||||
|
.x_bus(x_bus),
|
||||||
|
.weights_bus(weights_bus),
|
||||||
|
.bias_bus(bias_bus),
|
||||||
|
.y_bus(y_bus),
|
||||||
|
.busy(busy),
|
||||||
|
.done(done)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
clk = 0;
|
||||||
|
forever #5 clk = ~clk;
|
||||||
|
end
|
||||||
|
|
||||||
|
function signed [15:0] q8_8;
|
||||||
|
input real value;
|
||||||
|
begin
|
||||||
|
q8_8 = $rtoi(value * 256.0);
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
task run_layer;
|
||||||
|
begin
|
||||||
|
@(posedge clk);
|
||||||
|
start = 1;
|
||||||
|
|
||||||
|
@(posedge clk);
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
wait(done == 1);
|
||||||
|
|
||||||
|
@(posedge clk);
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
|
||||||
|
$dumpfile("sim/parametric.vcd");
|
||||||
|
$dumpvars(0, tb);
|
||||||
|
|
||||||
|
rst = 1;
|
||||||
|
start = 0;
|
||||||
|
x_bus = 0;
|
||||||
|
weights_bus = 0;
|
||||||
|
bias_bus = 0;
|
||||||
|
errors = 0;
|
||||||
|
|
||||||
|
repeat (2) @(posedge clk);
|
||||||
|
|
||||||
|
rst = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All inputs = 1.0
|
||||||
|
*/
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
x_bus[i*DATA_WIDTH +: DATA_WIDTH] = q8_8(1.0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 0: weight = 1.0
|
||||||
|
* result = N_INPUTS
|
||||||
|
*/
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
weights_bus[
|
||||||
|
0*N_INPUTS*DATA_WIDTH +
|
||||||
|
i*DATA_WIDTH +:
|
||||||
|
DATA_WIDTH
|
||||||
|
] = q8_8(1.0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 1: weight = 0.5
|
||||||
|
* result = N_INPUTS / 2
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 1)
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
weights_bus[
|
||||||
|
1*N_INPUTS*DATA_WIDTH +
|
||||||
|
i*DATA_WIDTH +:
|
||||||
|
DATA_WIDTH
|
||||||
|
] = q8_8(0.5);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 2: weight = -0.5
|
||||||
|
* ReLU -> 0
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 2)
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
weights_bus[
|
||||||
|
2*N_INPUTS*DATA_WIDTH +
|
||||||
|
i*DATA_WIDTH +:
|
||||||
|
DATA_WIDTH
|
||||||
|
] = q8_8(-0.5);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 3: weight = 2.0
|
||||||
|
* Large positive result -> saturation
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 3)
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
weights_bus[
|
||||||
|
3*N_INPUTS*DATA_WIDTH +
|
||||||
|
i*DATA_WIDTH +:
|
||||||
|
DATA_WIDTH
|
||||||
|
] = q8_8(2.0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 4: zero weights + bias +1
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 4)
|
||||||
|
bias_bus[4*DATA_WIDTH +: DATA_WIDTH] = q8_8(1.0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 5: zero weights + bias -1
|
||||||
|
* ReLU -> 0
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 5)
|
||||||
|
bias_bus[5*DATA_WIDTH +: DATA_WIDTH] = q8_8(-1.0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 6: weight 1.0 + bias -1.0
|
||||||
|
* result = N_INPUTS - 1
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 6) begin
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
weights_bus[
|
||||||
|
6*N_INPUTS*DATA_WIDTH +
|
||||||
|
i*DATA_WIDTH +:
|
||||||
|
DATA_WIDTH
|
||||||
|
] = q8_8(1.0);
|
||||||
|
|
||||||
|
bias_bus[6*DATA_WIDTH +: DATA_WIDTH] = q8_8(-1.0);
|
||||||
|
end
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 7: weight 0.25 + bias 1
|
||||||
|
* result = N_INPUTS/4 + 1
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 7) begin
|
||||||
|
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||||
|
weights_bus[
|
||||||
|
7*N_INPUTS*DATA_WIDTH +
|
||||||
|
i*DATA_WIDTH +:
|
||||||
|
DATA_WIDTH
|
||||||
|
] = q8_8(0.25);
|
||||||
|
|
||||||
|
bias_bus[7*DATA_WIDTH +: DATA_WIDTH] = q8_8(1.0);
|
||||||
|
end
|
||||||
|
|
||||||
|
$display("");
|
||||||
|
$display("========================================");
|
||||||
|
$display("PARAMETRIC LAYER TEST");
|
||||||
|
$display("N_INPUTS = %0d", N_INPUTS);
|
||||||
|
$display("N_NEURONS = %0d", N_NEURONS);
|
||||||
|
$display("PARALLEL = %0d", PARALLEL);
|
||||||
|
$display("========================================");
|
||||||
|
|
||||||
|
run_layer;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 0
|
||||||
|
*/
|
||||||
|
expected = N_INPUTS * 256;
|
||||||
|
|
||||||
|
if (y_bus[0*16 +: 16] !== expected[15:0]) begin
|
||||||
|
$display("FAIL N0: got %0d expected %0d",
|
||||||
|
y_bus[0*16 +: 16], expected);
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
$display("PASS N0: %0d", y_bus[0*16 +: 16]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 1
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 1) begin
|
||||||
|
expected = (N_INPUTS * 128);
|
||||||
|
|
||||||
|
if (y_bus[1*16 +: 16] !== expected[15:0]) begin
|
||||||
|
$display("FAIL N1: got %0d expected %0d",
|
||||||
|
y_bus[1*16 +: 16], expected);
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
$display("PASS N1: %0d", y_bus[1*16 +: 16]);
|
||||||
|
end
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 2
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 2) begin
|
||||||
|
expected = 0;
|
||||||
|
|
||||||
|
if (y_bus[2*16 +: 16] !== 16'sd0) begin
|
||||||
|
$display("FAIL N2: got %0d expected 0",
|
||||||
|
y_bus[2*16 +: 16]);
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
$display("PASS N2: 0 (ReLU)");
|
||||||
|
end
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 3:
|
||||||
|
* weight = 2.0
|
||||||
|
* result = N_INPUTS * 2.0
|
||||||
|
*
|
||||||
|
* Saturation only occurs when result > 127.996...
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 3) begin
|
||||||
|
|
||||||
|
expected = N_INPUTS * 2 * 256;
|
||||||
|
|
||||||
|
if (expected > 32767)
|
||||||
|
expected = 32767;
|
||||||
|
|
||||||
|
if (y_bus[3*16 +: 16] !== expected[15:0]) begin
|
||||||
|
$display("FAIL N3: got %0d expected %0d",
|
||||||
|
y_bus[3*16 +: 16], expected);
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if (expected == 32767)
|
||||||
|
$display("PASS N3: %0d (saturation)", y_bus[3*16 +: 16]);
|
||||||
|
else
|
||||||
|
$display("PASS N3: %0d", y_bus[3*16 +: 16]);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 4
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 4) begin
|
||||||
|
if (y_bus[4*16 +: 16] !== 16'sd256) begin
|
||||||
|
$display("FAIL N4: got %0d expected 256",
|
||||||
|
y_bus[4*16 +: 16]);
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
$display("PASS N4: 256 (bias)");
|
||||||
|
end
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 5
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 5) begin
|
||||||
|
if (y_bus[5*16 +: 16] !== 16'sd0) begin
|
||||||
|
$display("FAIL N5: got %0d expected 0",
|
||||||
|
y_bus[5*16 +: 16]);
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
$display("PASS N5: 0 (negative bias + ReLU)");
|
||||||
|
end
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 6
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 6) begin
|
||||||
|
expected = (N_INPUTS - 1) * 256;
|
||||||
|
|
||||||
|
if (y_bus[6*16 +: 16] !== expected[15:0]) begin
|
||||||
|
$display("FAIL N6: got %0d expected %0d",
|
||||||
|
y_bus[6*16 +: 16], expected);
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
$display("PASS N6: %0d", y_bus[6*16 +: 16]);
|
||||||
|
end
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Neuron 7
|
||||||
|
*/
|
||||||
|
if (N_NEURONS > 7) begin
|
||||||
|
expected = (N_INPUTS / 4 + 1) * 256;
|
||||||
|
|
||||||
|
if (y_bus[7*16 +: 16] !== expected[15:0]) begin
|
||||||
|
$display("FAIL N7: got %0d expected %0d",
|
||||||
|
y_bus[7*16 +: 16], expected);
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
$display("PASS N7: %0d", y_bus[7*16 +: 16]);
|
||||||
|
end
|
||||||
|
|
||||||
|
if (busy !== 0) begin
|
||||||
|
$display("FAIL: busy still active");
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (done !== 1) begin
|
||||||
|
$display("FAIL: done not asserted");
|
||||||
|
errors = errors + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
$display("");
|
||||||
|
$display("========================================");
|
||||||
|
|
||||||
|
if (errors == 0)
|
||||||
|
$display("PARAMETRIC TEST PASSED");
|
||||||
|
else
|
||||||
|
$display("PARAMETRIC TEST FAILED: %0d errors", errors);
|
||||||
|
|
||||||
|
$display("========================================");
|
||||||
|
$display("");
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
module top;
|
||||||
|
|
||||||
|
reg clk;
|
||||||
|
reg rst;
|
||||||
|
reg start;
|
||||||
|
|
||||||
|
reg signed [1023:0] x_bus;
|
||||||
|
reg signed [1023:0] w_bus;
|
||||||
|
reg signed [15:0] bias;
|
||||||
|
|
||||||
|
wire signed [15:0] y;
|
||||||
|
wire busy;
|
||||||
|
wire done;
|
||||||
|
|
||||||
|
neuron_parallel #(
|
||||||
|
.DATA_WIDTH(16),
|
||||||
|
.FRAC_BITS(8),
|
||||||
|
.N_INPUTS(64),
|
||||||
|
.PARALLEL(8),
|
||||||
|
.ACC_WIDTH(40)
|
||||||
|
) dut (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.start(start),
|
||||||
|
.x_bus(x_bus),
|
||||||
|
.w_bus(w_bus),
|
||||||
|
.bias(bias),
|
||||||
|
.y(y),
|
||||||
|
.busy(busy),
|
||||||
|
.done(done)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
||||||
Reference in New Issue
Block a user