Skip to content

Commit 5f46c1f

Browse files
authored
Merge pull request #1358 from Xilinx/bugfix/binary_thresholding
[BugFix] Harden thresholding to work for binary case with a single threshold.
2 parents 9c6946d + f047a55 commit 5f46c1f

2 files changed

Lines changed: 24 additions & 24 deletions

File tree

finn-rtllib/thresholding/hdl/thresholding.sv

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -150,31 +150,27 @@ module thresholding #(
150150

151151
// PE Configuration Address Decoding
152152
logic cfg_sel[PE];
153-
logic cfg_oob;
154-
logic [$clog2(N)-1:0] cfg_ofs;
153+
logic cfg_oob; // Map readbacks from padded rows (non-existent PEs) to padded highest threshold index of first PE
155154
if(PE == 1) begin
156155
assign cfg_sel[0] = 1;
157156
assign cfg_oob = 0;
158-
assign cfg_ofs = cfg_a[0+:$clog2(N)];
159157
end
160158
else begin
161159
uwire [$clog2(PE)-1:0] cfg_pe = cfg_a[$clog2(N)+:$clog2(PE)];
162160
always_comb begin
163161
foreach(cfg_sel[pe]) begin
164162
cfg_sel[pe] = USE_CONFIG && cfg_en && (cfg_pe == pe);
165163
end
166-
cfg_oob = (cfg_pe >= PE);
167-
cfg_ofs = cfg_a[0+:$clog2(N)];
168-
if(cfg_oob && !cfg_we) begin
169-
// Map readbacks from padded rows (non-existent PEs) to padded highest threshold index of first PE
170-
cfg_sel[0] = 1;
171-
cfg_ofs = '1;
172-
end
164+
cfg_oob = (cfg_pe >= PE) && !cfg_we;
165+
if(cfg_oob) cfg_sel[0] = 1;
173166
end
174167
end
168+
uwire [M-1:0] cfg_ofs; // Zero-extend for N = 2^k
169+
if($clog2(N) < M) assign cfg_ofs[M-1] = cfg_oob;
170+
if( N > 1) assign cfg_ofs[0+:$clog2(N)] = cfg_oob? {($clog2(N)){1'b1}} : cfg_a[0+:$clog2(N)];
175171

176172
uwire ptr_t iptr;
177-
assign iptr[0+:M] = cfg_ofs; // Zero-extend Expand for N = 2^k
173+
assign iptr[0+:M] = cfg_ofs;
178174
if(CF > 1) begin
179175
// Channel Fold Rotation
180176
logic [$clog2(CF)-1:0] CnlCnt = 0;

finn-rtllib/thresholding/sim/thresholding_tb.sv

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ module thresholding_tb;
4747
bit deep_pipeline;
4848
bit throttled; // throttle input and output interfaces occasionally
4949
} testcfg_t;
50-
localparam int unsigned TEST_CNT = 3;
50+
localparam int unsigned TEST_CNT = 4;
5151
localparam testcfg_t TESTS[TEST_CNT] = '{
52+
testcfg_t'{ k: 5, n: 1, c: 1, pe: 1, sign: 0, fparg: 0, deep_pipeline: 0, throttled: 0 },
5253
testcfg_t'{ k: 10, n: 8, c: 12, pe: 3, sign: 1, fparg: 0, deep_pipeline: 1, throttled: 1 },
5354
testcfg_t'{ k: 8, n: 3, c: 8, pe: 4, sign: 0, fparg: 0, deep_pipeline: 0, throttled: 1 },
5455
testcfg_t'{ k: 17, n: 9, c: 10, pe: 5, sign: 1, fparg: 1, deep_pipeline: 1, throttled: 0 }
@@ -122,14 +123,27 @@ module thresholding_tb;
122123
.ordy, .ovld, .odat
123124
);
124125

126+
// Expected Ordering
127+
function val_t reord(input val_t x);
128+
automatic val_t res = x;
129+
if(SIGNED) begin
130+
if(FPARG && x[K-1]) res[K-2:0] = ~x[K-2:0];
131+
res[K-1] = !x[K-1];
132+
end
133+
return res;
134+
endfunction : reord
135+
125136
//- Threshold Definition --------
126137
typedef val_t threshs_t[C][N];
127138
threshs_t THRESHS;
128139
initial begin
140+
static val_t row[N];
141+
129142
// Generate thresholds
130-
void'(std::randomize(THRESHS));
131143
foreach(THRESHS[c]) begin
132-
val_t row[N] = THRESHS[c];
144+
static val_t [N-1:0] r;
145+
void'(std::randomize(r));
146+
foreach(row[i]) row[i] = r[i];
133147
row.sort with (reord(item));
134148
THRESHS[c] = row;
135149
end
@@ -143,16 +157,6 @@ module thresholding_tb;
143157
end
144158
end
145159

146-
// Expected Ordering
147-
function val_t reord(input val_t x);
148-
automatic val_t res = x;
149-
if(SIGNED) begin
150-
if(FPARG && x[K-1]) res[K-2:0] = ~x[K-2:0];
151-
res[K-1] = !x[K-1];
152-
end
153-
return res;
154-
endfunction : reord
155-
156160
//- Stimulus Driver -------------
157161
input_t QW[$]; // Input tracing
158162
addr_t QC[$]; // Readback tracking

0 commit comments

Comments
 (0)