Skip to content

opt_carry_select pass#189

Merged
akashlevy merged 1 commit into
mainfrom
opt_carry_select
Jun 18, 2026
Merged

opt_carry_select pass#189
akashlevy merged 1 commit into
mainfrom
opt_carry_select

Conversation

@akashlevy

Copy link
Copy Markdown

If your work is part of a larger effort, please discuss your general plans on Discourse first to align your vision with maintainers.

What are the reasons/motivation for this change?

Explain how this is achieved.

Make sure your change comes with tests. If not possible, share how a reviewer might evaluate it.

These template prompts can be deleted when you're done responding to them.

@greptile-apps

greptile-apps Bot commented Jun 18, 2026

Copy link
Copy Markdown

Greptile Summary

This PR introduces opt_carry_select, a new Yosys pass that rewrites unsigned $add cells of the form wide_early + narrow_late into a carry-select structure, reducing the critical-path depth for the late operand from a full-width ripple carry to a narrow add plus one mux. A companion guard is added to peepopt_muxorder.pmg to prevent the peephole optimizer from folding the emitted incrementer/mux back into a late-carry ripple adder.

  • opt_carry_select.cc: Builds a heuristic timing model (iterative DFS with explicit stack to avoid C-stack overflow), collects qualifying plans before mutating the netlist, decomposes each adder into a low add, a precomputed high increment, and a carry-select mux, and tags emitted cells with a carry_select attribute. Transformation is restricted to unsigned adders where the narrow operand verifiably arrives later.
  • peepopt_muxorder.pmg: Adds a filter !op->get_bool_attribute(\\carry_select) guard that correctly matches the C++ ID(carry_select) attribute name, preventing regression of the carry-select structure.
  • tests/silimate/opt_carry_select.ys: Covers functional equivalence via SAT miter (32-bit and 64-bit cases), structural cell-count checks, the peepopt guard, and five negative cases (early narrow, equal width, signed, below min-wide threshold).

Confidence Score: 4/5

Safe to merge; the carry-select decomposition is mathematically correct and the peepopt guard prevents regression. The only actionable items are non-blocking style gaps and a missing multi-adder test.

The transformation logic, arrival-time model, and peepopt guard are all correct. The SAT-based equivalence tests validate functional correctness for the 32- and 64-bit cases. The open items are: function-level comments absent from the two core routines (qualifies, apply), a minor formula divergence in log2p1 vs the sibling pass, silent acceptance of negative CLI arguments, and a missing multi-adder integration test. None of these cause incorrect netlists, but they could trip up future maintainers or hide misconfigured invocations.

passes/silimate/opt_carry_select.cc warrants a second look for the missing function comments and the argument-validation gap; tests/silimate/opt_carry_select.ys could benefit from an additional multi-adder test case.

Important Files Changed

Filename Overview
passes/silimate/opt_carry_select.cc New pass implementing carry-select decomposition for unsigned adders. Core logic (arrival estimation, plan collection, carry-select rewrite) is mathematically sound. Minor issues: missing function-level comments on qualifies()/apply(), log2p1 formula slightly diverges from opt_timing_balance sibling, and CLI argument parsing uses atoi/atof without bounds validation.
passes/opt/peepopt_muxorder.pmg Adds a guard filter !op->get_bool_attribute(\carry_select) to prevent peepopt -muxorder from folding carry-select incrementers back into late-carry ripple adders. Placement and attribute name match the C++ side exactly.
passes/silimate/Makefile.inc Adds opt_carry_select.o to OBJS in the correct position. No issues.
tests/silimate/opt_carry_select.ys Good coverage: functional equivalence via SAT miter, structural cell-count checks, peepopt guard verification, and five negative cases. Missing a multi-adder-per-module test to exercise the two-phase plan/apply logic.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["$add (wide_early A + narrow_late B)\nA_WIDTH=W, B_WIDTH=k, Y_WIDTH=w"]
    A -->|"opt_carry_select fires\narr_narrow > arr_wide"| B
    subgraph CarrySelect["Carry-Select Structure (tagged carry_select)"]
        B["cs_lo_add\nA[k-1:0] + B → losum[k:0]"]
        C["cs_hi_inc_add carry_select\nA[w-1:k] + 1 → hiinc[w-k-1:0]"]
        D["cs_hi_mux carry_select\ncarry ? hiinc : A[w-1:k]"]
        E["concat\n{ hi[w-k-1:0], losum[k-1:0] } → Y"]
        B -->|"losum[k-1:0] (low sum)"| E
        B -->|"losum[k] (carry)"| D
        C -->|"hiinc"| D
        D -->|"hi"| E
    end
    E --> F["Y (w bits)"]
    G["peepopt -muxorder\nwould fold cs_hi_inc_add + cs_hi_mux\nback into A[w-1:k] + carry"]
    D -.->|"carry_select attr blocks muxorder"| G
    C -.->|"carry_select attr blocks muxorder"| G
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["$add (wide_early A + narrow_late B)\nA_WIDTH=W, B_WIDTH=k, Y_WIDTH=w"]
    A -->|"opt_carry_select fires\narr_narrow > arr_wide"| B
    subgraph CarrySelect["Carry-Select Structure (tagged carry_select)"]
        B["cs_lo_add\nA[k-1:0] + B → losum[k:0]"]
        C["cs_hi_inc_add carry_select\nA[w-1:k] + 1 → hiinc[w-k-1:0]"]
        D["cs_hi_mux carry_select\ncarry ? hiinc : A[w-1:k]"]
        E["concat\n{ hi[w-k-1:0], losum[k-1:0] } → Y"]
        B -->|"losum[k-1:0] (low sum)"| E
        B -->|"losum[k] (carry)"| D
        C -->|"hiinc"| D
        D -->|"hi"| E
    end
    E --> F["Y (w bits)"]
    G["peepopt -muxorder\nwould fold cs_hi_inc_add + cs_hi_mux\nback into A[w-1:k] + carry"]
    D -.->|"carry_select attr blocks muxorder"| G
    C -.->|"carry_select attr blocks muxorder"| G
Loading

Reviews (1): Last reviewed commit: "opt_carry_select pass" | Re-trigger Greptile

Comment thread passes/silimate/opt_carry_select.cc
Comment thread passes/silimate/opt_carry_select.cc
Comment thread tests/silimate/opt_carry_select.ys
Comment thread passes/silimate/opt_carry_select.cc
@akashlevy akashlevy merged commit 9c80f14 into main Jun 18, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant