Repository navigation
synth: SYNTH_ABC_PARTITION, one abc call per register group - #4731
dvanblerkom wants to merge 2 commits into
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Daniel Van Blerkom <vanblerkom@gmail.com>
There was a problem hiding this comment.
Code Review
This pull request introduces the SYNTH_ABC_PARTITION feature, which allows mapping the top module with one ABC call per register group to optimize each group against its own critical delay. This is implemented via a new Tcl script synth_abc_partition.tcl and integrated into the synthesis flow, with corresponding updates to documentation and variable configurations. The review feedback suggests making the Tcl script more robust by normalizing cell names to handle leading backslashes, initializing variables n and left before regexp calls to prevent stale values, and explicitly defining the variable type as an integer in both the JSON and YAML configuration files.
| set top $::env(DESIGN_NAME) | ||
| set groups [dict create] | ||
| foreach cell [tee -q -s result.string select -list "$top/t:*" "$top/t:\$*" %d] { | ||
| set name [string range $cell [string length "$top/"] end] |
There was a problem hiding this comment.
Normalizing $top and $cell by stripping any leading backslash before computing the substring range makes the cell name extraction much more robust against different naming formats in Yosys/RTLIL.
set top $::env(DESIGN_NAME)
regsub {^\\} $top {} top_norm
set groups [dict create]
foreach cell [tee -q -s result.string select -list "$top/t:*" "$top/t:\\$*" %d] {
regsub {^\\} $cell {} cell_norm
set name [string range $cell_norm [string length "$top_norm/"] end]
| regexp {[0-9]+} [tee -q -s result.string select -count \ | ||
| @abc_partition_group %ci1 %cie* "$top/t:\$_*" %i] n |
There was a problem hiding this comment.
| select -set abc_partition_group {*}$sel | ||
| select -set abc_partition_cone \ | ||
| @abc_partition_group %ci1 %cie* "$top/t:\$_*" %i | ||
| regexp {[0-9]+} [tee -q -s result.string select -count @abc_partition_cone] left |
| "stages": [ | ||
| "synth" | ||
| ] |
| stages: | ||
| - synth | ||
| default: 0 |
- Initialize n and left before regexp, so a failed match cannot reuse the previous group's count. - Declare the variable as type int. - Explain the effect as ABC lacking timing context (no SDC, no arrival times at cells mapped before it, such as extract_fa's adders), which can make the critical path it maps against the wrong one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Daniel Van Blerkom <vanblerkom@gmail.com>
TL;DR: ABC sees no SDC: no clocks, no false paths, and no arrival times at cells mapped before it, such as
extract_fa's adders. It maps each run against that run's own critical path and area-recovers every cone that is faster. When that critical path is the wrong one, the real cones are rebuilt smaller and slower, andrepair_timingcan resize and buffer them but not restructure them.SYNTH_ABC_PARTITION=<n>maps the top module with oneabccall per register group, so a wrong critical path only affects one group. It is a workaround, not a fix, and it is off by default (0).Why the critical path ABC sees can be wrong
facells and anha, then a final adder built by ABC. ABC sees the adder-cell outputs as arriving at t=0. In one run its critical delay is 2.2 ns, while the real path is 6.6 ns, so the final adder looks non-critical and is mapped 9 gates deep. With one call per group it is 6 gates deep.ADDER_MAP_FILE=, OpenSTA without wires, 4 ns clock), declaring the multiply a 2-cycle path makes it pass in both netlists. The cone then has −0.61 ns slack with stock synthesis and +2.01 ns withSYNTH_ABC_PARTITION=20.ABC_LIBERTY_ARGS="-a -G 250"(synth: ABC_LIBERTY_ARGS, extra arguments for ABC's read_lib #4730). On sky130hd/aes nearly all of the gain comes from synth: ABC_LIBERTY_ARGS, extra arguments for ABC's read_lib #4730 and little from this PR. On jpeg it is the other way round.With one shared clock and no exceptions the effect is smaller: there, the path ABC relaxes against usually does set the period. Test case and scripts: https://github.com/dvanblerkom/yosys-abc-partition.
How it works
synth_abc_partition.tcl, called in place oflog_cmd abc {*}$abc_args, works in four steps:$_DFF...suffix removed. These are liberty cells afterdfflibmap.%ci1 %cie* t:$_* %i.abccall each. Logic shared by several groups goes to the first group that reaches it.abccall maps whatever is left.abcmaps only the selected cells, so there are no hierarchy changes.Results
Setup WNS / TNS in ns at CTS, area relative to master. One run per configuration.
SYNTH_ABC_PARTITION=50ABC_AREA=1)ABC_AREA=1)The large gain on sky130hd/jpeg comes from the pre-mapped adders described above. The CPUs are roughly neutral, and the option costs area with the area script.
Combined with
ABC_LIBERTY_ARGS="-a -G 250"(#4730), sky130hd/riscv32i reaches -0.070 / -0.21 (+3.3%) and sky130hd/jpeg -0.049 / -0.05 (+9.4%).Limitations
SYNTH_HIERARCHICAL=0.abc_newpath (SWAP_ARITH_OPERATORS,SYNTH_WRAPPED_OPERATORS), likeABC_SCRIPT.Status
This is a draft. ABC already accepts per-input arrival and per-output required times (
read_constr -n), and&nfuses the input arrivals, but Yosys'sabc -constrpasses only the driving cell and the load. If Yosys gains a way to pass that timing context, that is the better fix, and this PR would become a stopgap or be closed.How this was tested
Testing was the same as in #4730:
make synthused this branch's scripts on master cca3a71, with the Yosys fromopenroad/orfs:26Q4-102-gef421749a. Floorplan to CTS ran in that image's ORFS on the netlist viaSYNTH_NETLIST_FILES.🤖 Generated with Claude Code