diff options
| author | Alejandro Soto <alejandro@34project.org> | 2024-03-14 23:05:08 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2024-03-14 23:05:08 -0600 |
| commit | eb49b6d871825eaea4e93d47a4368df368b7101a (patch) | |
| tree | 1621ca431325af0f70a5b193e3c2926e5b07c174 | |
| parent | 2034e0a7bc2099e43739dc9f47b25369051307c6 (diff) | |
platform/wavelet3d: implement fixed-point multiply-add and dot-add
| -rw-r--r-- | platform/wavelet3d/gfx_fixed_dotadd.sv | 55 | ||||
| -rw-r--r-- | platform/wavelet3d/gfx_fixed_muladd.sv | 77 | ||||
| -rw-r--r-- | platform/wavelet3d/gfx_pkg.sv | 23 |
3 files changed, 153 insertions, 2 deletions
diff --git a/platform/wavelet3d/gfx_fixed_dotadd.sv b/platform/wavelet3d/gfx_fixed_dotadd.sv new file mode 100644 index 0000000..fdd5ffd --- /dev/null +++ b/platform/wavelet3d/gfx_fixed_dotadd.sv @@ -0,0 +1,55 @@ +module gfx_fixed_dotadd +( + input logic clk, + + input gfx::fixed a0, + b0, + a1, + b1, + c, + input logic stall, + + output gfx::fixed q +); + + import gfx::*; + + fixed q0, a1_hold, b1_hold; + + gfx_fixed_muladd muladd_0 + ( + .clk, + .a(a0), + .b(b0), + .c, + .q(q0), + .stall + ); + + gfx_pipes #(.WIDTH($bits(fixed)), .DEPTH(FIXED_MULADD_DEPTH)) a_pipes + ( + .clk, + .in(a1), + .out(a1_hold), + .stall + ); + + gfx_pipes #(.WIDTH($bits(fixed)), .DEPTH(FIXED_MULADD_DEPTH)) b_pipes + ( + .clk, + .in(b1), + .out(b1_hold), + .stall + ); + + gfx_fixed_muladd muladd_1 + ( + .clk, + .a(a1_hold), + .b(b1_hold), + .c(q0), + .q, + .stall + ); + +endmodule diff --git a/platform/wavelet3d/gfx_fixed_muladd.sv b/platform/wavelet3d/gfx_fixed_muladd.sv new file mode 100644 index 0000000..22b7247 --- /dev/null +++ b/platform/wavelet3d/gfx_fixed_muladd.sv @@ -0,0 +1,77 @@ +module gfx_fixed_muladd +( + input logic clk, + + input gfx::fixed a, + b, + c, + input logic stall, + + output gfx::fixed q +); + + import gfx::*; + +`ifndef VERILATOR + logic[2 * $bits(fixed) - $bits(fixed_frac) - 1:0] q_ext; + + assign q = q_ext[$bits(fixed) - 1:0]; + + lpm_mult mult + ( + .aclr(0), + .clock(clk), + .clken(!stall), + + .sum({c, {`FIXED_FRAC{1'b0}}}), + .dataa(a), + .datab(b), + .result(q_ext) + ); + + defparam + mult.lpm_widtha = $bits(fixed), + mult.lpm_widthb = $bits(fixed), + mult.lpm_widths = $bits(fixed) + $bits(fixed_frac), + /* Esto es crucial. No está documentado en ningún lado (aparte de un + * comentario en r/fpga). Si lpm_widthp < lpm_widtha + lpm_widthb, + * entonces result contiene los lpm_widthp bits más significativos + * del producto, no los menos significativos como tendría sentido. + */ + mult.lpm_widthp = 2 * $bits(fixed) - $bits(fixed_frac), + mult.lpm_representation = "SIGNED", + mult.lpm_pipeline = FIXED_MULADD_DEPTH; +`else + logic[$bits(fixed) + $bits(fixed_frac) - 1:0] q_ext; + + fixed a_hold, b_hold, c_hold; + + assign q = q_ext[$bits(fixed) + $bits(fixed_frac) - 1:$bits(fixed_frac)] + c_hold; + assign q_ext = a_hold * b_hold; + + gfx_pipes #(.WIDTH($bits(a)), .DEPTH(FIXED_MULADD_DEPTH)) a_pipes + ( + .clk, + .in(a), + .out(a_hold), + .stall + ); + + gfx_pipes #(.WIDTH($bits(b)), .DEPTH(FIXED_MULADD_DEPTH)) b_pipes + ( + .clk, + .in(b), + .out(b_hold), + .stall + ); + + gfx_pipes #(.WIDTH($bits(c)), .DEPTH(FIXED_MULADD_DEPTH)) c_pipes + ( + .clk, + .in(c), + .out(c_hold), + .stall + ); +`endif + +endmodule diff --git a/platform/wavelet3d/gfx_pkg.sv b/platform/wavelet3d/gfx_pkg.sv index 72c8f80..53bb8cd 100644 --- a/platform/wavelet3d/gfx_pkg.sv +++ b/platform/wavelet3d/gfx_pkg.sv @@ -3,11 +3,17 @@ package gfx; localparam int SHADER_LANES = 4; typedef logic[31:0] word; - typedef logic[63:0] dword; localparam int SUBWORD_BITS = $clog2($bits(word)) - $clog2($bits(byte)); localparam int BYTES_PER_WORD = 1 << SUBWORD_BITS; + typedef word uword; + typedef logic signed[$bits(word) - 1:0] sword; + typedef logic[$bits(word) / 2 - 1:0] uhword; + typedef logic signed[$bits(word) / 2 - 1:0] shword; + typedef logic[2 * $bits(word) - 1:0] udword; + typedef logic signed[2 * $bits(word) - 1:0] sdword; + typedef logic[7:0] float_exp; typedef logic[$bits(word) - $bits(float_exp) - 2:0] float_mant; typedef logic[$bits(float_mant):0] float_mant_full; // Incluye '1.' explícito @@ -112,7 +118,7 @@ package gfx; float_exp exp; float_class a_class, b_class; - dword product; + udword product; logic sign, overflow; } fpint_mulclass_mnorm; @@ -224,6 +230,19 @@ package gfx; overflow; } fpint_rnorm_encode; + // Q22.10 + typedef logic[9:0] fixed_frac; + typedef logic[$bits(word) - $bits(fixed_frac) - 1:0] fixed_int; + + typedef struct packed signed + { + fixed_int fint; // 'int' es una keyword + fixed_frac frac; + } fixed; + + localparam int FIXED_MULADD_DEPTH = 5; + localparam int FIXED_DOTADD_DEPTH = 2 * FIXED_MULADD_DEPTH; + localparam int SCHED_BRAM_WORDS = 2048; // 8KiB typedef word irq_lines; |
