Skip to content

mvu_4sx4u.sv: part-select p3[52:21] out of range [47:0] for ACCU_WIDTH>27 (SIMD=1/PE=2) breaks synthesis #1681

Description

@bong-water-water-bong

Summary

finn-rtllib/mvu/mvu_4sx4u.sv fails synthesis with "part select index out of range" for configurations whose ACCU_WIDTH > 27 (reproduced with SIMD=1/PE=2, ACCU_WIDTH=32, on Vivado 2025.2 and 2026.1, multiple parts). The offending part-select is p3[52:21] on a [47:0] bus.

Root cause (source-level)

Stage #4's cross-SIMD reduction iterates all four lanes unconditionally:

uwire [47:0] p3[SIMD];            // line ~139
...
for(genvar i = 0; i < 4; i++) begin   // line ~514
  ...
  if(i < PE_REM) assign lo4[i] = '0;
  else begin : genLo
    localparam int unsigned LO_WIDTH = lo_width(i);       // OFFSETS[i+1]-OFFSETS[i]
    ...
    for(genvar s = 0; s < SIMD; s++)
      assign tree[SIMD-1+s] = p3[s][OFFSETS[i]+:LO_WIDTH];  // line 556

sliceLanes() (VERSION=1, NARROW_WEIGHTS) returns OFFSETS = {ACCU_WIDTH+21, 21, 14, 7, 0}, so for lane i=3:
LO_WIDTH = OFFSETS[4]-OFFSETS[3] = ACCU_WIDTH, and the part-select becomes p3[21 +: ACCU_WIDTH].

p3 is only 48 bits wide, so any ACCU_WIDTH > 27 (48-21) makes the part-select exceed the bus:

  • ACCU_WIDTH=32 -> p3[52:21] -> Vivado: "part select index [52:21] out of range [47:0]".

The if(i < PE_REM) guard does not protect lane 3 for PE < 4 (e.g. PE=2 gives PE_REM=2, and i=3 takes the genLo branch).

Repro

  • FINN MVAU config: SIMD=1, PE=2 (ACCU_WIDTH resolves to 32); any config with ACCU_WIDTH >= 28 should hit the same error.
  • Run Vivado synthesis on the generated mvu_4sx4u.sv (e.g. synth_design on the MVAU wrapper): fails with part-select out of range; genLo block at line ~556 (plus the corresponding p3 write at line ~501 and the X3/pp slice at ~492 in the same lane-3 path).

Suggested fix

Guard the lane-3 low-part reduction on the actual PE count / lane width (the loop processes i=0..3 but only lanes < PE are real; lane 3's wide slice must not be emitted when the configuration doesn't use it), or clamp LO_WIDTH/OFFSETS for lane 3 to ACCU_WIDTH only when the lane is populated.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions