rcx: fix bench_wires segfault on duplicate pattern names - #11154
Open
gadfort wants to merge 2 commits into
Open
Conversation
bench_wires names each pattern after its widths and spacings rounded onto a coarse integer nm grid: setTargetParams floors the coupling spacing to 10nm, and mkNet_prefix then rescales it by 1000/dbunit with integer division. Two entries of the spacing table built in benchDB_WS can therefore land on the same pattern name while being distinct as doubles. When that happened the second pattern asked odb for a net name that already existed, got a null back with warning RCX-0409, and rcx dereferenced it: odb::dbNet::get1stBTerm() rcx::extMeasure::createNetSingleWire() rcx::extRCModel::writeBenchWires_DB_res() rcx::extRCModel::benchDB_WS() rcx::extRCModel::linesOverBench() 788fca1 addressed one instance of this by comparing SPACING against PITCH-WIDTH at DBL_EPSILON, but that only guards a single hardcoded pair, and an absolute DBL_EPSILON tolerance is only meaningful for values near 1.0 - a technology with thick top metal and a coarse database unit collides at one ULP of a much larger value and slips through. Spacings that are several nm apart can also collide, since the name is quantized to 10nm, which no floating point tolerance can catch. Dedupe on the generated name instead, which is the value that actually has to be unique, and make a null net a hard error rather than a segfault. The solver pattern flow built its extMeasure with a null logger, so pass the model logger there to keep that error reportable. Fixes The-OpenROAD-Project#7897 Signed-off-by: Peter Gadfort <gadfort@zeroasic.com>
Contributor
There was a problem hiding this comment.
Code Review
This pull request addresses a crash caused by duplicate pattern names during bench wire generation by tracking generated pattern names in a set and skipping duplicates. It also updates extMeasure to use the proper logger and adds error logging when net creation fails. The review feedback highlights critical safety issues where the code still dereferences potentially null net pointers immediately after logging the error, which would lead to crashes. Additionally, the feedback recommends adding null checks for _wireDirName and logger_ to prevent undefined behavior and crashes in legacy execution paths.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reopens #7897 — the merged fix
788fca19f1is narrower than the bug.Symptom
bench_wires -allon a technology with thick top metal and a coarse databaseunit emits a duplicate-net warning and then dies:
Symbolized:
Root cause
The pattern name is doubly quantized before it reaches the net name:
setTargetParamsfloors the coupling spacing to a 10nm grid(
n2 = (n2 / 10) * 10)mkNet_prefixthen rescales by(1000 * s_nm) / dbunitwith integerdivision
So two entries of the spacing table built in
benchDB_WScollide whenever theyland in the same bucket, even though they are distinct as doubles.
Concretely, on a layer with
WIDTH 2.200 / SPACING 1.800 / PITCH 4.000andDATABASE MICRONS 2000, the table holds bothSPACINGandPITCH - WIDTH.Those are equal in exact arithmetic, differ by exactly one ULP as doubles, and
both round to
1800in the name.788fca19f1guarded this withstd::fabs(spacing - s1) > DBL_EPSILON. That isinsufficient in two ways:
s1ands2entries added bythe later loop iterations are never compared against anything.
DBL_EPSILONis an absolute tolerance, meaningful only for values near1.0. One ULP of 3.6 is
4.44e-16, which is> DBL_EPSILON, so the guarddoes not fire and both values enter the table.
More fundamentally, because the name is quantized to 10nm, two spacings that
are genuinely several nm apart can also collide. No floating point tolerance
can catch that.
Fix
benchDB_WSnow skips any(width, spacing, spacing2) combination whose pattern name was already
emitted, keyed on
_wireDirNameitself. That is the value that actually hasto be unique, so it covers both collision mechanisms and any future one. The
set is local to one
benchDB_WScall, which is correct — the name embedsthe pattern kind and the metal/under-metal pair, so those cannot alias
across calls.
extMeasure::create*NetSingleWire*wrappers dereferenced the null that
dbCreateNetUtil::createNetSingleWirereturns. They now report
RCX-529/RCX-530/RCX-531. Reaching this isa bug, so it should fail loudly rather than crash or silently drop wires.
extRCModel::lines*patterngenerators built their
extMeasurewith a null logger, and one of themreaches
createDiagNetSingleWire. Passing the model logger keeps the newerror reportable instead of turning into another null dereference.
The
DBL_EPSILONguard is left in place. It is now redundant, but removing itwould add entries to the spacing table and change pattern output for every
technology where it currently fires — out of scope for a crash fix.
Testing
New regression
src/rcx/test/dup_pattern_names, registered in both CMake andBazel. It ships a minimal hand-written routing-only tech LEF (no vendor file)
carrying the geometry that triggers the collision, and asserts the colliding
pattern is generated exactly once with all of its wires. Before this change the
test reproduces the reported crash with the identical net name.
bazel test //src/rcx/test/...— 18/18 pass.generate_patternis unchanged,confirming the dedupe does not over-fire on technologies that were already
fine.
Type of Change
Impact
No segfault on bench creation
Verification
./etc/Build.sh).Related Issues
#7897