fpu area optimization
This commit is contained in:
61
hw/rtl/libs/VX_find_first.v
Normal file
61
hw/rtl/libs/VX_find_first.v
Normal file
@@ -0,0 +1,61 @@
|
||||
`include "VX_platform.vh"
|
||||
|
||||
`TRACING_OFF
|
||||
module VX_find_first #(
|
||||
parameter N = 1,
|
||||
parameter DATAW = 1,
|
||||
parameter REVERSE = 0,
|
||||
localparam LOGN = $clog2(N)
|
||||
) (
|
||||
input wire [N-1:0][DATAW-1:0] data_i,
|
||||
input wire [N-1:0] valid_i,
|
||||
output wire [DATAW-1:0] data_o,
|
||||
output wire valid_o
|
||||
);
|
||||
if (N > 1) begin
|
||||
wire [N-1:0] valid_r;
|
||||
wire [N-1:0][DATAW-1:0] data_r;
|
||||
|
||||
for (genvar i = 0; i < N; ++i) begin
|
||||
assign valid_r[i] = REVERSE ? valid_i[N-1-i] : valid_i[i];
|
||||
assign data_r[i] = REVERSE ? data_i[N-1-i] : data_i[i];
|
||||
end
|
||||
|
||||
`IGNORE_WARNINGS_BEGIN
|
||||
wire [2**LOGN-1:0] s_n;
|
||||
wire [2**LOGN-1:0][DATAW-1:0] d_n;
|
||||
`IGNORE_WARNINGS_END
|
||||
|
||||
for (genvar i = 0; i < LOGN; ++i) begin
|
||||
if (i == (LOGN-1)) begin
|
||||
for (genvar j = 0; j < 2**i; ++j) begin
|
||||
if ((j*2) < (N-1)) begin
|
||||
assign s_n[2**i-1+j] = valid_r[j*2] | valid_r[j*2+1];
|
||||
assign d_n[2**i-1+j] = valid_r[j*2] ? data_r[j*2] : data_r[j*2+1];
|
||||
end
|
||||
if ((j*2) == (N-1)) begin
|
||||
assign s_n[2**i-1+j] = valid_r[j*2];
|
||||
assign d_n[2**i-1+j] = data_r[j*2];
|
||||
end
|
||||
if ((j*2) > (N-1)) begin
|
||||
assign s_n[2**i-1+j] = 0;
|
||||
assign d_n[2**i-1+j] = 'x;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
for (genvar j = 0; j < 2**i; ++j) begin
|
||||
assign s_n[2**i-1+j] = s_n[2**(i+1)-1+j*2] | s_n[2**(i+1)-1+j*2+1];
|
||||
assign d_n[2**i-1+j] = s_n[2**(i+1)-1+j*2] ? d_n[2**(i+1)-1+j*2] : d_n[2**(i+1)-1+j*2+1];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign valid_o = s_n[0];
|
||||
assign data_o = d_n[0];
|
||||
end else begin
|
||||
assign valid_o = valid_i;
|
||||
assign data_o = data_i[0];
|
||||
end
|
||||
|
||||
endmodule
|
||||
`TRACING_ON
|
||||
@@ -1,88 +1,31 @@
|
||||
`include "VX_platform.vh"
|
||||
|
||||
/// Modified port of lzc module from fpnew Libray
|
||||
/// reference: https://github.com/pulp-platform/fpnew
|
||||
/// A trailing zero counter / leading zero counter.
|
||||
/// Set MODE to 0 for trailing zero counter => cnt_o is the number of trailing zeros (from the LSB)
|
||||
/// Set MODE to 1 for leading zero counter => cnt_o is the number of leading zeros (from the MSB)
|
||||
/// If the input does not contain a zero, `empty_o` is asserted. Additionally `cnt_o` contains
|
||||
/// the maximum number of zeros - 1. For example:
|
||||
/// in_i = 000_0000, empty_o = 1, cnt_o = 6 (mode = 0)
|
||||
/// in_i = 000_0001, empty_o = 0, cnt_o = 0 (mode = 0)
|
||||
/// in_i = 000_1000, empty_o = 0, cnt_o = 3 (mode = 0)
|
||||
/// Furthermore, this unit contains a more efficient implementation for Verilator (simulation only).
|
||||
/// This speeds up simulation significantly.
|
||||
|
||||
`TRACING_OFF
|
||||
module VX_lzc #(
|
||||
/// The width of the input vector.
|
||||
parameter int unsigned WIDTH = 2,
|
||||
parameter bit MODE = 1'b0 // 0 -> trailing zero, 1 -> leading zero
|
||||
parameter N = 2,
|
||||
parameter MODE = 0, // 0 -> trailing zero, 1 -> leading zero
|
||||
localparam LOGN = $clog2(N)
|
||||
) (
|
||||
input logic [WIDTH-1:0] in_i,
|
||||
output logic [$clog2(WIDTH)-1:0] cnt_o,
|
||||
output logic valid_o
|
||||
input wire [N-1:0] in_i,
|
||||
output wire [LOGN-1:0] cnt_o,
|
||||
output wire valid_o
|
||||
);
|
||||
`IGNORE_WARNINGS_BEGIN
|
||||
wire [N-1:0][LOGN-1:0] indices;
|
||||
|
||||
localparam int unsigned NUM_LEVELS = $clog2(WIDTH);
|
||||
|
||||
// pragma translate_off
|
||||
initial begin
|
||||
assert(WIDTH > 0) else $fatal("input must be at least one bit wide");
|
||||
end
|
||||
// pragma translate_on
|
||||
|
||||
logic [WIDTH-1:0][NUM_LEVELS-1:0] index_lut;
|
||||
logic [2**NUM_LEVELS-1:0] sel_nodes;
|
||||
logic [2**NUM_LEVELS-1:0][NUM_LEVELS-1:0] index_nodes;
|
||||
|
||||
logic [WIDTH-1:0] in_tmp;
|
||||
|
||||
// reverse vector if required
|
||||
always_comb begin : flip_vector
|
||||
for (int unsigned i = 0; i < WIDTH; i++) begin
|
||||
in_tmp[i] = (MODE) ? in_i[WIDTH-1-i] : in_i[i];
|
||||
end
|
||||
for (genvar i = 0; i < N; ++i) begin
|
||||
assign indices[i] = MODE ? LOGN'(N-1-i) : LOGN'(i);
|
||||
end
|
||||
|
||||
for (genvar j = 0; unsigned'(j) < WIDTH; j++) begin : g_index_lut
|
||||
assign index_lut[j] = NUM_LEVELS'(unsigned'(j));
|
||||
end
|
||||
|
||||
for (genvar level = 0; unsigned'(level) < NUM_LEVELS; level++) begin : g_levels
|
||||
if (unsigned'(level) == NUM_LEVELS-1) begin : g_last_level
|
||||
for (genvar k = 0; k < 2**level; k++) begin : g_level
|
||||
// if two successive indices are still in the vector...
|
||||
if (unsigned'(k) * 2 < WIDTH-1) begin
|
||||
assign sel_nodes[2**level-1+k] = in_tmp[k*2] | in_tmp[k*2+1];
|
||||
assign index_nodes[2**level-1+k] = (in_tmp[k*2] == 1'b1) ? index_lut[k*2] :
|
||||
index_lut[k*2+1];
|
||||
end
|
||||
// if only the first index is still in the vector...
|
||||
if (unsigned'(k) * 2 == WIDTH-1) begin
|
||||
assign sel_nodes[2**level-1+k] = in_tmp[k*2];
|
||||
assign index_nodes[2**level-1+k] = index_lut[k*2];
|
||||
end
|
||||
// if index is out of range
|
||||
if (unsigned'(k) * 2 > WIDTH-1) begin
|
||||
assign sel_nodes[2**level-1+k] = 1'b0;
|
||||
assign index_nodes[2**level-1+k] = '0;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
for (genvar l = 0; l < 2**level; l++) begin : g_level
|
||||
assign sel_nodes[2**level-1+l] = sel_nodes[2**(level+1)-1+l*2] | sel_nodes[2**(level+1)-1+l*2+1];
|
||||
assign index_nodes[2**level-1+l] = (sel_nodes[2**(level+1)-1+l*2] == 1'b1) ? index_nodes[2**(level+1)-1+l*2] :
|
||||
index_nodes[2**(level+1)-1+l*2+1];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign cnt_o = NUM_LEVELS > unsigned'(0) ? index_nodes[0] : $clog2(WIDTH)'(0);
|
||||
assign valid_o = NUM_LEVELS > unsigned'(0) ? sel_nodes[0] : (|in_i);
|
||||
|
||||
`IGNORE_WARNINGS_END
|
||||
VX_find_first #(
|
||||
.N (N),
|
||||
.DATAW (LOGN),
|
||||
.REVERSE (MODE)
|
||||
) find_first (
|
||||
.data_i (indices),
|
||||
.valid_i (in_i),
|
||||
.data_o (cnt_o),
|
||||
.valid_o (valid_o)
|
||||
);
|
||||
|
||||
endmodule
|
||||
`TRACING_ON
|
||||
Reference in New Issue
Block a user