Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
379abb4
[Threshold] enable fp32 thresholding
maltanar Dec 4, 2024
d9fc3b2
[Test] enable FP thresholding tests, many failures to fix as of yet
maltanar Dec 4, 2024
8995767
[Deps] update bitstring
maltanar Nov 26, 2024
f109216
Merge remote-tracking branch 'upstream/dev' into fp-thresholding
SpiritSeeker Sep 2, 2025
3a5fa94
[Thresholding] Add FP32 support for thresholding
SpiritSeeker Sep 3, 2025
ce75f36
[Thresholding Tests] Skip duplicate test
SpiritSeeker Sep 11, 2025
e9e7c15
[Thresholding] Handle cross int and float dtypes in code generation i…
SpiritSeeker Sep 11, 2025
a836e28
analytical fifo sizing
Sep 12, 2025
95a46d3
Merge pull request #1418 from SpiritSeeker/fp-thresholding
auphelia Sep 16, 2025
a3e4131
[Thresholding] Enable FP16 thresholding
SpiritSeeker Sep 16, 2025
648c3f2
[Thresholding Tests] Remove duplicate tests
SpiritSeeker Sep 17, 2025
9bc8504
[Elementwise] Add FP16 support for elementwise ops
SpiritSeeker Sep 19, 2025
2f6e302
[Tests] Fix thresholding tests kudos @fpjentzsch
auphelia Sep 22, 2025
391930b
Merge pull request #1427 from Xilinx/fix/thresholding_tests
auphelia Sep 22, 2025
507635d
[Docker] hotfix to limit netron version to 8.5.0, thanks @fpjentzsch
auphelia Sep 23, 2025
f766b43
Merge pull request #1422 from SpiritSeeker/feature/fp16-thresholding
auphelia Sep 23, 2025
56eb2b5
[Thresholding] Minimize thresholds only if inputs are integers
SpiritSeeker Sep 24, 2025
340d17a
Merge pull request #1436 from SpiritSeeker/minimize-acc-fp16
auphelia Sep 25, 2025
6e827ca
Allow memstream to select between parameter streams.
preusser Sep 30, 2025
54d3c80
[Memstream] Expose SETS variable to compiler
auphelia Sep 30, 2025
469f4d0
Merge pull request #1441 from Xilinx/feature/memstream_set
auphelia Sep 30, 2025
2137f35
Expose set index stream all the way through the instantiation wrapper.
preusser Sep 30, 2025
0c4f774
uncomment fifo splitting, was left for debugging purposes only
Sep 30, 2025
c5f204b
Run linting
auphelia Oct 1, 2025
6985dc4
[finn-rtllib] Add SET_BITS parameter to memstream template
auphelia Oct 1, 2025
7829628
[finn-rtllib] Cleanup spacing in memstream wrapper
auphelia Oct 1, 2025
19c9844
Merge pull request #1443 from Xilinx/feature/memstream_set
auphelia Oct 1, 2025
7fd375c
[Tests] Create test to reproduce float ooc bug
auphelia Oct 10, 2025
77a8cb8
[OOCsynth] Add additional argument to pass in tcl scripts to instanti…
auphelia Oct 14, 2025
841904b
[Deps] Temporarily change omx repo until PR is merged
auphelia Oct 14, 2025
1a70dc3
[Tests] Revert temporary changes elementwise test
auphelia Oct 15, 2025
6256de7
[Tests] Add new ooc synthesis test
auphelia Oct 15, 2025
daf0f24
[Deps] Update omx commit hash
auphelia Oct 15, 2025
bb73ece
Merge pull request #1454 from Xilinx/debug/float_ooc
auphelia Oct 15, 2025
5eaaee3
[finn-rtllib] Propagate SETS through memstream components
auphelia Oct 2, 2025
b197a3d
[rtlsim exec] Add reset after running prehook fct
auphelia Oct 21, 2025
54ede86
Merge pull request #1460 from Xilinx/fix/thresholding_memstream
auphelia Oct 21, 2025
3dc42fc
analytical fifo sizing
Sep 12, 2025
24c6dc4
Merge branch 'feature/analytical-fifo-sizing' of github.com:lstasytis…
Oct 24, 2025
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
3 changes: 2 additions & 1 deletion docker/Dockerfile.finn
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ RUN pip install matplotlib==3.7.0 --ignore-installed
RUN pip install pytest-dependency==0.5.1
RUN pip install pytest-xdist[setproctitle]==3.2.0
RUN pip install pytest-parallel==0.1.1
RUN pip install "netron>=5.0.0"
# Beyond version 8.5.0, subsequent Netron calls in a Jupyter notebook cause "Address already in use" errors
RUN pip install "netron>=5.0.0,<=8.5.0"
RUN pip install pandas==1.5.3
RUN pip install scikit-learn==1.2.1
RUN pip install tqdm==4.64.1
Expand Down
2 changes: 2 additions & 0 deletions docker/finn_entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ else
echo "See https://docs.xilinx.com/r/en-US/ug835-vivado-tcl-commands/Tcl-Initialization-Scripts"
fi

export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$VITIS_PATH/lnx64/tools/fpo_v7_1"

export PATH=$PATH:$HOME/.local/bin
# execute the provided command(s) as root
exec "$@"
6 changes: 3 additions & 3 deletions fetch-repos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
QONNX_COMMIT="0630ceaee17799096d1750abcfb5bbe0a2877888"
FINN_EXP_COMMIT="0724be21111a21f0d81a072fccc1c446e053f851"
BREVITAS_COMMIT="4617f7bd136e96fa21c7f76e3c7e2e37fe563837"
CNPY_COMMIT="4e8810b1a8637695171ed346ce68f6984e585ef4"
CNPY_COMMIT="8c82362372ce600bbd1cf11d64661ab69d38d7de"
HLSLIB_COMMIT="5dde96382b84979c6caa6f34cdad2ac72fa28489"
OMX_COMMIT="0b59762f9e4c4f7e5aa535ee9bc29f292434ca7a"
OMX_COMMIT="a5d48f93309b235fdd21556d16e86e6ef5db6e2e"
AVNET_BDF_COMMIT="2d49cfc25766f07792c0b314489f21fe916b639b"
XIL_BDF_COMMIT="8cf4bb674a919ac34e3d99d8d71a9e60af93d14e"
RFSOC4x2_BDF_COMMIT="13fb6f6c02c7dfd7e4b336b18b959ad5115db696"
Expand All @@ -44,7 +44,7 @@ AUPZU3_BDF_COMMIT="b595ecdf37c7204129517de1773b0895bcdcc2ed"
QONNX_URL="https://github.com/fastmachinelearning/qonnx.git"
FINN_EXP_URL="https://github.com/Xilinx/finn-experimental.git"
BREVITAS_URL="https://github.com/Xilinx/brevitas.git"
CNPY_URL="https://github.com/rogersce/cnpy.git"
CNPY_URL="https://github.com/maltanar/cnpy.git"
HLSLIB_URL="https://github.com/Xilinx/finn-hlslib.git"
OMX_URL="https://github.com/maltanar/oh-my-xilinx.git"
AVNET_BDF_URL="https://github.com/Avnet/bdf.git"
Expand Down
284 changes: 163 additions & 121 deletions finn-rtllib/memstream/hdl/memstream.sv
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@
*/

module memstream #(
int unsigned SETS,
int unsigned DEPTH,
int unsigned WIDTH,

parameter INIT_FILE = "",
parameter RAM_STYLE = "auto",

localparam int unsigned ADDR_WIDTH0 = $clog2(DEPTH),
localparam int unsigned ADDR_WIDTH = ADDR_WIDTH0? ADDR_WIDTH0 : 1
localparam int unsigned ADDR_WIDTH0 = $clog2(SETS*DEPTH),
localparam int unsigned ADDR_WIDTH = ADDR_WIDTH0? ADDR_WIDTH0 : 1,
localparam int unsigned SET_BITS = SETS > 2? $clog2(SETS) : 1
)(
input logic clk,
input logic rst,
Expand All @@ -52,173 +54,213 @@ module memstream #(
output logic config_rack,
output logic [WIDTH-1:0] config_q0,

// Set selector stream (ignored for SETS = 1)
input logic [SET_BITS-1:0] sidx,
input logic svld,
output logic srdy,

// Continuous output stream
input logic ordy,
output logic ovld,
output logic [WIDTH-1:0] odat
);

//-----------------------------------------------------------------------
// Generation of the Primary Read Address Sequence
typedef logic [ADDR_WIDTH-1:0] addr_t;
typedef logic [WIDTH -1:0] data_t;

uwire en; // Pipeline enable
uwire rollback; // Rollback stream reads if backpressure would block read back
uwire addr_t ptr0;
uwire vld0;
uwire got0;
if(SETS < 2) begin : genSingleSet
// Increment for wrapping DEPTH-1 back to zero
localparam int unsigned WRAP_INC = 2**ADDR_WIDTH - DEPTH + 1;

// Counter with pre-computed last indication for val == DEPTH-1
typedef struct {
addr_t val;
logic lst;
} ptr_t;
addr_t Ptr = 0;
logic Lst = DEPTH < 2;
always_ff @(posedge clk) begin
if(rst) begin
Ptr <= 0;
Lst <= DEPTH < 2;
end
else if(got0) begin
Ptr <= Ptr + (Lst? WRAP_INC : 1);
Lst <= (DEPTH < 2) || (Ptr == DEPTH-2);
end
end
assign ptr0 = Ptr;
assign vld0 = 1;

// Counter history to facilitate pipeline rollback
ptr_t Ptr[3] = '{
0: '{ val: 0, lst: DEPTH<2 },
default: ptr_t'{ default: 'x }
};
end : genSingleSet
else begin : genMultiSets

//-----------------------------------------------------------------------
// Stage #0: Address & Op
logic Wr1 = 0; // Write
logic Rb1 = 0; // Read back
logic Rs1 = 0; // Read stream
data_t Data1 = 'x;
if(1) begin : blkStage1
// Increment for wrapping DEPTH-1 back to zero
localparam int unsigned WRAP_INC = 2**ADDR_WIDTH - DEPTH + 1;
// Stream Offsets through Lookup Table
typedef addr_t offset_table_t[SETS];
function offset_table_t INIT_OFFSET_TABLE();
automatic offset_table_t res;
foreach(res[i]) res[i] = i*DEPTH;
return res;
endfunction : INIT_OFFSET_TABLE
localparam offset_table_t OFFSET_TABLE = INIT_OFFSET_TABLE();

uwire ptr_t ptr_eff = rollback? Ptr[2] : Ptr[0];
uwire ptr_t ptr_nxt;
assign ptr_nxt.val = ptr_eff.val + (config_ce? 0 : !ptr_eff.lst? 1 : WRAP_INC);
assign ptr_nxt.lst =
DEPTH < 2? 1 :
config_ce? ptr_eff.lst :
ptr_eff.lst? 0 :
/* else */ ptr_eff.val == DEPTH-2;
uwire lst;
if(DEPTH < 2) assign lst = 1;
else begin
logic [$clog2(DEPTH-1):0] Cnt = 'x; // DEPTH-2, ..., 1, 0, -1 (lst)
always_ff @(posedge clk) begin
if(rst) Cnt <= 'x;
else begin
unique if(svld && srdy) Cnt <= DEPTH-2;
else if(got0 && !lst) Cnt <= Cnt - 1;
else begin end
end
end
assign lst = Cnt[$left(Cnt)];
end

addr_t Ptr = 'x;
logic Vld = 0;
assign srdy = !Vld || (lst && got0);
always_ff @(posedge clk) begin
if(rst) Ptr[0] <= '{ val: 0, lst: DEPTH<2 };
else if(en) Ptr[0] <= ptr_nxt;
if(rst) begin
Ptr <= 'x;
Vld <= 0;
end
else begin
unique if(svld && srdy) Ptr <= OFFSET_TABLE[sidx];
else if(got0 && !lst) Ptr <= Ptr + 1;
else begin end
Vld <= svld || !srdy;
end
end
assign ptr0 = Ptr;
assign vld0 = Vld;

end : genMultiSets

//-----------------------------------------------------------------------
// Memory Pipeline
// - free-running pipeline
// - credit-based feed of reads for streaming output
// - config interface always takes precedence
localparam int unsigned FULL_CREDIT = 8;
typedef logic [WIDTH-1:0] data_t;

//- Stage #1: Command Arbitration
uwire ogot = ovld && ordy;

logic Wr1 = 0;
logic Rb1 = 0;
logic Rs1 = 0;
addr_t Ptr1 = 'x;
data_t Dat1 = 'x;
if(1) begin : blkFeed

// Issue next Memory Operation
logic signed [$clog2(FULL_CREDIT):0] Credit = -FULL_CREDIT;

assign got0 = vld0 && Credit[$left(Credit)] && !config_ce;
always_ff @(posedge clk) begin
if(rst) begin
Credit <= -FULL_CREDIT;

Wr1 <= 0;
Rb1 <= 0;
Rs1 <= 0;
Ptr[1] <= '{ default : 'x };
Data1 <= 'x;
Ptr1 <= 'x;
Dat1 <= 'x;
end
else if(en) begin
Wr1 <= 0;
Rb1 <= 0;
Rs1 <= 0;
if(config_ce) begin
if(config_we) Wr1 <= 1;
else Rb1 <= 1;
Ptr[1] <= '{ val: config_address, lst: 'x };
Data1 <= config_d0;
end
else begin
Rs1 <= 1;
Ptr[1] <= ptr_eff;
Data1 <= 'x;
end
else begin
Credit <= Credit + (ogot == got0? 0 : got0? 1 : -1);

Wr1 <= config_ce && config_we;
Rb1 <= config_ce && !config_we;
Rs1 <= got0;
Ptr1 <= config_ce? config_address : ptr0;
Dat1 <= config_d0;
end
end
end : blkStage1
end : blkFeed

//-----------------------------------------------------------------------
// Stage #2: Memory Access
logic Rb2 = 0;
logic Rs2 = 0;
data_t Data2;
if(1) begin : blkStage2
// Stage #2+3: Memory Readout
logic Rb3 = 0;
logic Rs3 = 0;
data_t Dat3 = 'x; /* absorbed register */
if(1) begin : blkMem
(* RAM_STYLE = RAM_STYLE *)
data_t Mem[DEPTH];
data_t Mem[SETS*DEPTH];

// Optional Memory Initialization
if(INIT_FILE != "") initial $readmemh(INIT_FILE, Mem);

// Execute Memory Operation
uwire addr_t addr = Ptr[1].val;
data_t RdOut;
logic Rb2 = 0;
logic Rs2 = 0;
data_t Dat2 = 'x; /* absorbed register */
always_ff @(posedge clk) begin // Memory datapath without reset
if(Wr1) Mem[Ptr1] <= Dat1;
Dat2 <= Mem[Ptr1];
Dat3 <= Dat2;
end
always_ff @(posedge clk) begin
if(en) begin
// NO_CHANGE mode as READ and WRITE never happen together.
if(Wr1) Mem[addr] <= Data1;
else RdOut <= Mem[addr];
if(rst) begin
Rb2 <= 0;
Rs2 <= 0;
Rb3 <= 0;
Rs3 <= 0;
end
else begin
Rb2 <= Rb1;
Rs2 <= Rs1;
Rb3 <= Rb2;
Rs3 <= Rs2;
end
end
end : blkMem

// Stretch by Additional Pipeline Stages for Targetting URAM
localparam bit STRETCH = (RAM_STYLE == "ultra") || (RAM_STYLE == "ULTRA");
// Complete Readbacks
assign config_rack = Rb3;
assign config_q0 = Dat3;

uwire logic irb = Rb1;
uwire logic irs = Rs1 && !rollback;
uwire ptr_t iptr = Ptr[1];
uwire logic orb;
uwire logic ors;
uwire ptr_t optr;
// Stage #4+5: Output Credit Buffer
if(1) begin : blkStreamOut

if(!STRETCH) begin
assign orb = irb;
assign ors = irs;
assign optr = iptr;
uwire oload;

assign Data2 = RdOut;
// Stream Output SRL backing Credit Grant for Stream Reads in Flight
(* SHREG_EXTRACT = "yes" *)
data_t OSrl[FULL_CREDIT-1];
logic [$clog2(FULL_CREDIT):0] OPtr = -1;
always_ff @(posedge clk) begin
if(Rs3) OSrl <= { Dat3, OSrl[0:FULL_CREDIT-3] };
end
else begin
logic SRb = 0;
logic SRs = 0;
ptr_t SPtr = '{ default: 'x };
data_t SData = 'x;
always_ff @(posedge clk) begin
if(rst) begin
SRb <= 0;
SRs <= 0;
SPtr <= '{ default: 'x };
SData <= 'x;
end
else if(en) begin
SRb <= irb;
SRs <= irs;
SPtr <= iptr;
SData <= RdOut;
end
always_ff @(posedge clk) begin
if(rst) OPtr <= -1;
else begin
automatic logic up = Rs3;
automatic logic dn = oload && !OPtr[$left(OPtr)];
OPtr <= OPtr + (up == dn? 0 : up? 1 : -1);
end
assign orb = SRb;
assign ors = SRs && !rollback;
assign optr = SPtr;

assign Data2 = SData;
end

// Copy Output Designation
// Final Output Register
(* EXTRACT_ENABLE = "yes" *)
data_t ODat = 'x;
logic OVld = 0;
always_ff @(posedge clk) begin
if(rst) begin
Rb2 <= 0;
Rs2 <= 0;
Ptr[2] <= '{ default: 'x };
OVld <= 0;
ODat <= 'x;
end
else if(en) begin
Rb2 <= orb;
Rs2 <= ors;
Ptr[2] <= optr;
else if(oload) begin
OVld <= !OPtr[$left(OPtr)];
ODat <= OSrl[OPtr];
end
end
end : blkStage2

//-----------------------------------------------------------------------
// Output Interfaces
assign config_rack = Rb2;
assign config_q0 = Data2;
assign oload = ordy || !OVld;

assign ovld = Rs2;
assign odat = Data2;
assign odat = ODat;
assign ovld = OVld;

uwire backpressure = Rs2 && !ordy;
assign rollback = backpressure && (Rb1 || config_ce);
assign en = !backpressure || Rb1 || config_ce;
end : blkStreamOut

endmodule : memstream
Loading