Summary
Two asap7 liteeth variants currently set SKIP_CTS_REPAIR_TIMING: "1" in their
BUILD.bazel to work around a deterministic OpenROAD crash in the post-CTS
hold-repair pass. This issue tracks reverting the workaround (and re-validating
QoR) once the upstream bug is fixed.
| Design |
Workaround commit |
PR |
designs/asap7/liteeth/liteeth_udp_stream_sgmii |
f5d940b1 (squashed) |
#76 |
designs/asap7/liteeth/liteeth_udp_usp_gth_sgmii |
(TBD, pending #105) |
#105 |
The bug
During cts.tcl stage 4_1_cts, OpenROAD's repair_timing aborts with:
[INFO RSZ-0100] Repair move sequence: UnbufferMove SizeUpMove SwapPinsMove BufferMove CloneMove SplitLoadMove
[INFO RSZ-0098] No setup violations found
[INFO RSZ-0046] Found 347 endpoints with hold violations.
...
[ERROR ODB-1200] InsertBufferBeforeLoads: Load pin '<x>/SN' is not connected to net '<y>'.
Error: cts.tcl, 82 ODB-1200
Tested against OpenROAD commits 5f1bd87f37fd… (HighTide #71) and
578be38ad229… (HighTide #103). The new RSZ-0100 move sequence places
UnbufferMove first; on these two netlists an unbuffer step orphans a
load pin before a subsequent InsertBufferBeforeLoads pass tries to
reference it.
Why these designs only
Originally only liteeth_udp_stream_sgmii failed (PR #76). When the
OpenROAD pin moved forward in PR #103 (5f1bd87f → 578be38a), the
trigger window widened and liteeth_udp_usp_gth_sgmii started failing
too with the same signature. Other liteeth variants on the same OR pin
still pass — different netlist shape / placement steers the deterministic
move sequence away from the buggy iteration. See PR #76 thread for the
detailed asymmetry analysis.
Things that did NOT work (for the record)
set_dont_touch [get_nets -hierarchical *udpcore_int_rst*] — net name
doesn't survive Yosys flat-synth; no-op, same crash.
set_false_path -from [get_ports sys_reset] + set_false_path -through
on reset candidates — STA hold-endpoint count only dropped 347 → 346.
The 346 other violations are datapath, not reset. Same crash net.
Only SKIP_CTS_REPAIR_TIMING=1 bypasses the bug. GRT and detailed
route still perform their own hold-repair passes, so final QoR is
still reasonable (e.g. udp_stream_sgmii: 41 % util, 14886 µm² on asap7,
clean 6_final).
To re-enable
- Confirm upstream OpenROAD has fixed the
InsertBufferBeforeLoads /
UnbufferMove interaction. Candidate filter:
git log OpenROAD/src/rsz | grep -iE 'InsertBufferBeforeLoads|UnbufferMove'
- Bump
bazel-orfs submodule and the OpenROAD pin in MODULE.bazel.
- Remove
SKIP_CTS_REPAIR_TIMING and its comment block from both:
designs/asap7/liteeth/liteeth_udp_stream_sgmii/BUILD.bazel
designs/asap7/liteeth/liteeth_udp_usp_gth_sgmii/BUILD.bazel
- Run:
bazel build //designs/asap7/liteeth/liteeth_udp_stream_sgmii:liteeth_udp_stream_sgmii_final
bazel build //designs/asap7/liteeth/liteeth_udp_usp_gth_sgmii:liteeth_udp_usp_gth_sgmii_final
and verify cts.tcl completes without the ODB-1200 error.
- Compare QoR before/after — the workaround skips a real hold-fix step,
so re-enabling should improve hold TNS at finish.
Upstream issue
Not yet filed against The-OpenROAD-Project/OpenROAD. Worth doing once we
can produce a minimized testcase — current repro requires the full
liteeth UDP SGMII netlists + this specific placement.
Related
Summary
Two
asap7liteeth variants currently setSKIP_CTS_REPAIR_TIMING: "1"in theirBUILD.bazelto work around a deterministic OpenROAD crash in the post-CTShold-repair pass. This issue tracks reverting the workaround (and re-validating
QoR) once the upstream bug is fixed.
designs/asap7/liteeth/liteeth_udp_stream_sgmiif5d940b1(squashed)designs/asap7/liteeth/liteeth_udp_usp_gth_sgmiiThe bug
During
cts.tclstage4_1_cts, OpenROAD'srepair_timingaborts with:Tested against OpenROAD commits
5f1bd87f37fd…(HighTide #71) and578be38ad229…(HighTide #103). The newRSZ-0100move sequence placesUnbufferMovefirst; on these two netlists an unbuffer step orphans aload pin before a subsequent
InsertBufferBeforeLoadspass tries toreference it.
Why these designs only
Originally only
liteeth_udp_stream_sgmiifailed (PR #76). When theOpenROAD pin moved forward in PR #103 (
5f1bd87f→578be38a), thetrigger window widened and
liteeth_udp_usp_gth_sgmiistarted failingtoo with the same signature. Other liteeth variants on the same OR pin
still pass — different netlist shape / placement steers the deterministic
move sequence away from the buggy iteration. See PR #76 thread for the
detailed asymmetry analysis.
Things that did NOT work (for the record)
set_dont_touch [get_nets -hierarchical *udpcore_int_rst*]— net namedoesn't survive Yosys flat-synth; no-op, same crash.
set_false_path -from [get_ports sys_reset]+set_false_path -throughon reset candidates — STA hold-endpoint count only dropped 347 → 346.
The 346 other violations are datapath, not reset. Same crash net.
Only
SKIP_CTS_REPAIR_TIMING=1bypasses the bug. GRT and detailedroute still perform their own hold-repair passes, so final QoR is
still reasonable (e.g. udp_stream_sgmii: 41 % util, 14886 µm² on asap7,
clean 6_final).
To re-enable
InsertBufferBeforeLoads/UnbufferMoveinteraction. Candidate filter:git log OpenROAD/src/rsz | grep -iE 'InsertBufferBeforeLoads|UnbufferMove'bazel-orfssubmodule and the OpenROAD pin inMODULE.bazel.SKIP_CTS_REPAIR_TIMINGand its comment block from both:designs/asap7/liteeth/liteeth_udp_stream_sgmii/BUILD.bazeldesigns/asap7/liteeth/liteeth_udp_usp_gth_sgmii/BUILD.bazelcts.tclcompletes without the ODB-1200 error.so re-enabling should improve hold TNS at finish.
Upstream issue
Not yet filed against The-OpenROAD-Project/OpenROAD. Worth doing once we
can produce a minimized testcase — current repro requires the full
liteeth UDP SGMII netlists + this specific placement.
Related
liteeth_udp_stream_sgmii: PR liteeth_udp_stream_sgmii: work around OpenROAD ODB-1200 in CTS hold-repair #76liteeth_udp_usp_gth_sgmii: PR liteeth: fix two failing variants after the bazel-orfs upgrade #105