Skip to content

Commit 4c7bdf3

Browse files
Fix N <= Height (#62)
* Fix case of N<=8 This commit introduces changes to the scheduler, tiler to fix the non-working case of N<=8. Specifically, this case is treated, from an internal control perspective, "as if" it was of a minimal size equal to 16. Inputs and outputs are gated so that this does not cause any additional written data. The performance cost is reasonable given that anyways N<=8 cases should be not considered a "sweet spot" of the accelerator. * Tune-down overzealous AI-generated comments * Cleanup, moving MinimumSizeN to a localparam defined from MinimumSizeNFactor = 2 multiplied by Height * Add new regression tests * Make verible happy
1 parent dca57a3 commit 4c7bdf3

4 files changed

Lines changed: 89 additions & 5 deletions

File tree

rtl/redmule_pkg.sv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package redmule_pkg;
1616
parameter int unsigned MaxDepth = MaxDim * MaxPipeRegs;
1717
parameter int unsigned MaxDataW = MaxDepth * 16;
1818
parameter int unsigned MisalignedAccessSupportDefault = 0; // default to 0 for compatibility with Snitch
19+
parameter int unsigned MinimumSizeNFactor = 2;
1920

2021
parameter int unsigned NumStreamSources = 3; // X, W, Y
2122

rtl/redmule_scheduler.sv

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,16 @@ module redmule_scheduler
175175

176176
assign x_done_en = /*flgs_streamer_i.x_stream_source_flags.ready_start &&*/ x_rows_iter_en && x_rows_iter_q == x_config.x_rows_iter-1 && x_w_iters_q == x_config.w_cols_iter-1 && x_cols_iter_q == x_config.x_cols_iter-1;
177177

178+
// For N <= Height, the "internal N" is promoted to a full N-tile (MinimumSizeN steps) by the tiler
179+
// (see redmule_tiler.sv). The X buffer must then iterate a full D-deep tile so its refill / M-block
180+
// row-advance stays in step with the promoted N; otherwise it would serve only
181+
// x_buffer_slots (= n_size rounded up to Height, = Height for N <= Height) columns and never advance
182+
// to the next M-block's X rows (the trailing output tile would reuse the first block's X).
183+
logic small_n_promoted_x;
184+
assign small_n_promoted_x = (x_config.n_size <= H);
178185
assign cntrl_x_buffer_o.height = x_cols_iter_q == x_config.x_cols_iter-1 && x_config.x_cols_lftovr != '0 ? x_config.x_cols_lftovr : D;
179-
assign cntrl_x_buffer_o.slots = x_cols_iter_q == x_config.x_cols_iter-1 && x_config.x_cols_lftovr != '0 ? x_config.x_buffer_slots : D;
186+
assign cntrl_x_buffer_o.slots = small_n_promoted_x ? D
187+
: (x_cols_iter_q == x_config.x_cols_iter-1 && x_config.x_cols_lftovr != '0 ? x_config.x_buffer_slots : D);
180188
assign cntrl_x_buffer_o.width = x_rows_iter_q == x_config.x_rows_iter-1 && x_config.x_rows_lftovr != '0 ? x_config.x_rows_lftovr : W;
181189

182190
/******************************
@@ -360,7 +368,17 @@ module redmule_scheduler
360368

361369
assign w_done_en = w_mat_iters_en && w_mat_iters_q == w_config.x_rows_iter-1;
362370

363-
assign cntrl_w_buffer_o.height = w_rows_iter_q >= w_config.w_rows_iter-(NumPipeRegs+1) && w_config.w_rows_lftovr != '0 ? w_config.w_rows_lftovr : H;
371+
// When N <= Height the tiler promotes the W-row loop to MinimumSizeN (a full N-tile) so the
372+
// W-load pacing is not too fast, causing races and hangs. The extra padded N rows
373+
// [n_size .. MinimumSizeN-1] must be zeroed at the W-buffer input: rows with a global
374+
// N index >= real n_size are gated to zero. Since real N <= H, all valid rows fall in
375+
// the first Height-deep buffer pass (w_rows_iter_q < H, valid depth = n_size); the second pass
376+
// (w_rows_iter_q >= H) is fully invalid (valid depth = 0).
377+
logic small_n_promoted;
378+
assign small_n_promoted = (w_config.n_size <= H);
379+
assign cntrl_w_buffer_o.height = small_n_promoted
380+
? (w_rows_iter_q < H ? w_config.n_size[$clog2(MaxDim)-1:0] : '0)
381+
: (w_rows_iter_q >= w_config.w_rows_iter-(NumPipeRegs+1) && w_config.w_rows_lftovr != '0 ? w_config.w_rows_lftovr : H);
364382
assign cntrl_w_buffer_o.width = w_cols_iter_q == w_config.w_cols_iter-1 && w_config.w_cols_lftovr != '0 ? w_config.w_cols_lftovr : D;
365383

366384
assign cntrl_w_buffer_o.load = current_state == LOAD_W && ~stall_engine && ~w_done;

rtl/redmule_tiler.sv

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ module redmule_tiler
3030
output redmule_config_t config_o
3131
);
3232

33+
// Minimum size N handled by the internal control. Any job with n_size <= Height is run "as if"
34+
// N = MinimumSizeN for the purpose of the W-load loop / scheduler / z_buffer timing (see
35+
// redmule_tiler.sv), while the input operands for the padded N rows [n_size .. MinimumSizeN-1]
36+
// are gated to zero so the result is unaffected. This is necessary to enable the controller to
37+
// work properly in these corner cases.
38+
// The minimum size is defined as MinimumSizeN = MinimumSizeNFactor * Height (e.g., 2*Height)
39+
localparam int unsigned MinimumSizeN = MinimumSizeNFactor * Height;
40+
3341
logic clk_en;
3442
logic clk_int;
3543

@@ -61,7 +69,18 @@ assign config_d.w_addr = config_i.w_addr;
6169
assign config_d.z_addr = config_i.z_addr;
6270
assign config_d.m_size = config_i.m_size;
6371
assign config_d.k_size = config_i.k_size;
64-
assign config_d.n_size = config_i.n_size;
72+
assign config_d.n_size = config_i.n_size; // real N is carried downstream unchanged (used for operand gating)
73+
74+
// Effective N size used ONLY for the W-row loop length / streamer length: any job with
75+
// N <= Height is promoted to MinimumSizeN so the W-load takes as long as a full N-tile, restoring
76+
// the large-N scheduler/z_buffer pacing that fixes the small-N multi-block hang. The X-column
77+
// tiling and the store geometry deliberately keep the real config_d.n_size here (X rows are only
78+
// n_size wide, so over-reading X would misalign the addresses); the X buffer is instead promoted to
79+
// a full D-deep tile in redmule_scheduler.sv (cntrl_x_buffer_o.slots) so it advances M-block rows in
80+
// step with the promoted N, and both padded operands are zeroed (X via x_cols_lftovr,
81+
// W via the cntrl_w_buffer_o.height gating in redmule_scheduler.sv).
82+
logic [15:0] n_size_eff;
83+
assign n_size_eff = (config_i.n_size <= Height) ? MinimumSizeN[15:0] : config_i.n_size;
6584
assign config_d.gemm_ops = config_i.gemm_ops;
6685
assign config_d.gemm_input_fmt = config_i.gemm_input_fmt;
6786
assign config_d.gemm_output_fmt = config_i.gemm_output_fmt;
@@ -85,14 +104,14 @@ logic [15:0] w_rows_iter_lftovr,
85104
w_rows_iter_nolftovr;
86105
assign w_cols_iter_nolftovr = config_d.k_size/(Height*(PipeRegs + 1));
87106
assign w_rows_iter_lftovr = w_rows_iter_nolftovr + Height - config_d.w_rows_lftovr;
88-
assign w_rows_iter_nolftovr = config_d.n_size;
107+
assign w_rows_iter_nolftovr = n_size_eff; // promoted N: W-row loop runs for a full N-tile when N <= Height
89108

90109
// Calculating the residuals along the input dimensions
91110
assign config_d.x_rows_lftovr = config_d.m_size - (x_rows_iter_nolftovr*Width);
92111
assign config_d.x_cols_lftovr = config_d.n_size - (x_cols_iter_nolftovr*(Height*(PipeRegs + 1)));
93112

94113
// Calculating the residuals along the weight dimensions
95-
assign config_d.w_rows_lftovr = config_d.n_size - (Height*(config_d.n_size/Height));
114+
assign config_d.w_rows_lftovr = n_size_eff - (Height*(n_size_eff/Height)); // promoted N (0 when N <= Height -> full W-row loop)
96115
assign config_d.w_cols_lftovr = config_d.k_size - (w_cols_iter_nolftovr*(Height*(PipeRegs + 1)));
97116

98117
// Calculate w_cols, x_cols, x_rows iterations

scripts/regression.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,49 @@ redmule_regression:
246246
M8_N32_K8:
247247
path: .
248248
command: make golden M=8 N=32 K=8 && make sw-clean sw-build M=8 N=32 K=8 REDMULE_COMPLEX=0 Gcc= && make hw-run M=8 N=32 K=8 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_8_32_8 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_8_32_8
249+
# Small N <= Height promoted to MinimumSizeN (previously HUNG on multi-block).
250+
M16_N8_K16: # N=Height, 2 M-blocks -> was the canonical hang
251+
path: .
252+
command: make golden M=16 N=8 K=16 && make sw-clean sw-build M=16 N=8 K=16 REDMULE_COMPLEX=0 Gcc= && make hw-run M=16 N=8 K=16 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_16_8_16 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_16_8_16
253+
M24_N8_K16: # N=Height, 3 M-blocks
254+
path: .
255+
command: make golden M=24 N=8 K=16 && make sw-clean sw-build M=24 N=8 K=16 REDMULE_COMPLEX=0 Gcc= && make hw-run M=24 N=8 K=16 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_24_8_16 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_24_8_16
256+
M32_N8_K16: # N=Height, 4 M-blocks
257+
path: .
258+
command: make golden M=32 N=8 K=16 && make sw-clean sw-build M=32 N=8 K=16 REDMULE_COMPLEX=0 Gcc= && make hw-run M=32 N=8 K=16 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_32_8_16 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_32_8_16
259+
M16_N8_K24: # N=Height, 2 M-blocks + 2 K-tiles (K-leftover)
260+
path: .
261+
command: make golden M=16 N=8 K=24 && make sw-clean sw-build M=16 N=8 K=24 REDMULE_COMPLEX=0 Gcc= && make hw-run M=16 N=8 K=24 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_16_8_24 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_16_8_24
262+
M16_N4_K16: # N < Height (padded rows [4..15] gated to zero)
263+
path: .
264+
command: make golden M=16 N=4 K=16 && make sw-clean sw-build M=16 N=4 K=16 REDMULE_COMPLEX=0 Gcc= && make hw-run M=16 N=4 K=16 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_16_4_16 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_16_4_16
265+
M16_N1_K16:
266+
path: .
267+
command: make golden M=16 N=1 K=16 && make sw-clean sw-build M=16 N=1 K=16 REDMULE_COMPLEX=0 Gcc= && make hw-run M=16 N=1 K=16 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_16_1_16 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_16_1_16
268+
M16_N2_K16:
269+
path: .
270+
command: make golden M=16 N=2 K=16 && make sw-clean sw-build M=16 N=2 K=16 REDMULE_COMPLEX=0 Gcc= && make hw-run M=16 N=2 K=16 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_16_2_16 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_16_2_16
271+
M16_N3_K16:
272+
path: .
273+
command: make golden M=16 N=3 K=16 && make sw-clean sw-build M=16 N=3 K=16 REDMULE_COMPLEX=0 Gcc= && make hw-run M=16 N=3 K=16 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_16_3_16 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_16_3_16
274+
M16_N4_K16:
275+
path: .
276+
command: make golden M=16 N=4 K=16 && make sw-clean sw-build M=16 N=4 K=16 REDMULE_COMPLEX=0 Gcc= && make hw-run M=16 N=4 K=16 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_16_4_16 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_16_4_16
277+
M1_N1_K1:
278+
path: .
279+
command: make golden M=1 N=1 K=1 && make sw-clean sw-build M=1 N=1 K=1 REDMULE_COMPLEX=0 Gcc= && make hw-run M=1 N=1 K=1 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_1_1_1 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_1_1_1
280+
M1_N2_K1:
281+
path: .
282+
command: make golden M=1 N=2 K=1 && make sw-clean sw-build M=1 N=2 K=1 REDMULE_COMPLEX=0 Gcc= && make hw-run M=1 N=2 K=1 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_1_2_1 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_1_2_1
283+
M1_N3_K1:
284+
path: .
285+
command: make golden M=1 N=3 K=1 && make sw-clean sw-build M=1 N=3 K=1 REDMULE_COMPLEX=0 Gcc= && make hw-run M=1 N=3 K=1 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_1_3_1 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_1_3_1
286+
M1_N4_K1:
287+
path: .
288+
command: make golden M=1 N=4 K=1 && make sw-clean sw-build M=1 N=4 K=1 REDMULE_COMPLEX=0 Gcc= && make hw-run M=1 N=4 K=1 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_1_4_1 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_1_4_1
289+
M17_N17_K17:
290+
path: .
291+
command: make golden M=17 N=17 K=17 && make sw-clean sw-build M=17 N=17 K=17 REDMULE_COMPLEX=0 Gcc= && make hw-run M=17 N=17 K=17 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_17_17_17 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_17_17_17
292+
M33_N33_K33:
293+
path: .
294+
command: make golden M=33 N=33 K=33 && make sw-clean sw-build M=33 N=33 K=33 REDMULE_COMPLEX=0 Gcc= && make hw-run M=33 N=33 K=33 REDMULE_COMPLEX=0 target=$Target | tee target/sim/$Target/transcript_33_33_33 && grep -q '\[TB\] - Success!' target/sim/$Target/transcript_33_33_33

0 commit comments

Comments
 (0)