est: Filter ideal clock net invalidation#10571
Conversation
Skip adding ideal clock nets to the estimated-parasitic invalidation set because ideal clock arrivals do not depend on RC. This avoids repeatedly seeding large ideal clock networks during placement-stage ECO repair while preserving normal invalidation for propagated clock and signal nets. Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
Update rsz golden logs for ideal clock net filtering. The repair_clk_nets1 output now keeps the CLOCK net type while preserving the reported inserted buffer wire lengths. The repair_setup_gcd output reflects the deterministic power value produced after skipping ideal clock parasitic invalidation. Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
Move ideal clock net filtering out of the ODB invalidation callback and into the incremental parasitic update path. This avoids rebuilding the STA clock network while repair_clock_nets is in the middle of disconnecting and reconnecting clock path pins. Add a small helper to classify ideal clock driver pins across modes, and restore the affected regression outputs to the stable clock-network behavior. Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
Replace the duplicate all-mode ideal clock loop in Steiner parasitic estimation with the shared ideal clock pin helper. The helper keeps the mode-aware behavior that ignores modes where the pin is not a clock. Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
Add C++ regressions for EstimateParasitics incremental invalidation of ideal clock nets. The tests cover DFF resize invalidating an ideal clock net and a scan clock that is ideal only in test mode while absent from function mode. Register the new regression in both CMake and Bazel so the ideal clock filtering behavior is covered by unit test infrastructure. Tested: clang-tidy src/est/test/cpp/TestEstimateParasitics.cc -p build Tested: cmake --build build --target TestEstimateParasitics -j16 Tested: ctest -R TestEstimateParasitics --output-on-failure Tested: bazel test //src/est/test:TestEstimateParasitics Co-authored-by: OmX <omx@oh-my-codex.dev> Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
There was a problem hiding this comment.
Code Review
This pull request optimizes the parasitic update process by skipping RC re-estimation and STA delay invalidation for ideal clock nets, particularly handling multi-mode designs like scan clocks correctly. It also introduces a C++ unit test suite to verify these changes. The review feedback correctly identifies a memory leak in the newly added isIdealClockNet function, where the dynamically allocated PinSet returned by network_->drivers is not freed, and provides a clean suggestion to use std::unique_ptr to manage its lifetime.
| #include "sta/GraphDelayCalc.hh" | ||
| #include "sta/Search.hh" | ||
| #undef protected | ||
| #undef private |
| // modes. Ignore modes where the pin is not a clock at all. | ||
| // e.g., scan clock pin may not be defined as clock in function mode. | ||
| if (!sta_->isClock(pin, mode)) { | ||
| continue; |
There was a problem hiding this comment.
@eder-matheus isClock() check is newly added to handle the Problem 2 in the PR description.
| if (parasitics_src_ != ParasiticsSrc::kNone) { | ||
| for (const sta::Net* net : parasitics_invalid_) { | ||
| if (isIdealClockNet(net)) { | ||
| continue; |
There was a problem hiding this comment.
This is the main performance fix.
It does not retrigger the redundant update of all DFFs connected to an ideal clock net.
| // DFF resizing may mark the clock net parasitics invalid. For an ideal clock, | ||
| // those parasitics do not contribute to clock arrival/slew, so updateParasitics | ||
| // should skip both RC re-estimation and delaysInvalidFromFanin() for that net. | ||
| TEST_F(TestEstimateParasitics, IdealClockNetSkipsStaInvalidation) |
There was a problem hiding this comment.
New test case for Problem 1.
| // test mode: the scan pin is not a clock in function mode, so that mode must be | ||
| // ignored. The fixed logic first checks isClock(pin, mode), then requires ideal | ||
| // status only in modes where the pin is actually a clock. | ||
| TEST_F(TestEstimateParasitics, ScanClockIdealOnlyInTestMode) |
There was a problem hiding this comment.
New test case for Problem 2.
|
@minjukim55 This is another |
|
@codex review |
|
Codex Review: Didn't find any major issues. What shall we delve into next? ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
🥳 |
|
any examples of impact on run times? |
|
@oharboe I tested the fix w/ the long-tail design that you shared originally. Long-tail design
|
|
🤯 @ovebryne FYI |
| return false; | ||
| } | ||
|
|
||
| const Pin* drvr_pin = *drivers->begin(); |
There was a problem hiding this comment.
Is there a check somewhere upfront that clock nets cannot be multidriven nets? Maybe just add a comment here about that. Even an assert might work!
There was a problem hiding this comment.
I let Codex & Claude search the detector for multiple drivers in clock network, but they couldn't find it.
Typically, clock network does not have multiple drivers except for clock mesh design.
I am not sure if OpenROAD supports the clock mesh design, but it seems unlikely.
If there are multiple clock drivers, this API retrieves only the first driver and check if it is an ideal clock.
This logic works even if multiple drivers are present because the multiple drivers have the identical clock type (there will be no such case that one of the multiple drivers is an ideal clock while another clock driver is not).
There was a problem hiding this comment.
There has been some discussion of adding clock mesh support but it hasn't gone anywhere so far.
eder-matheus
left a comment
There was a problem hiding this comment.
LGTM. Please address @dsengupta0628's comment before merging.
Summary
EstimateParasitics::updateParasitics().Problem
Problem 1 (MAJOR): Ideal clock-net invalidation can increase incremental STA runtime
repair_design, DFF resizing can mark the DFF CK net as parasitics-invalid.updateParasitics()path treated every invalid net the same, so an ideal clock net could trigger RC re-estimation andsta_->delaysInvalidFromFanin(clock_net).delaysInvalidFromFanin(clock_net)invalidates the top clock port and every CK load vertex, which can make the next incremental STA update much larger than the actual ECO requires.Problem 2 (minor): Scan clocks can be ideal only in test mode
isIdealClock(pin, mode)for every mode.scan_clkis created only in test mode, the scan clock pin is not a clock in function mode.isIdealClock(scan_clk_pin, function_mode)is false because the pin is not a function-mode clock, not because it is a propagated or RC-dependent clock.Solution
Problem 1 Fix: Skip ideal clock nets in updateParasitics()
for (const sta::Net* net : parasitics_invalid_) { + if (isIdealClockNet(net)) { + continue; + } estimateWireParasitic(net); } for (const sta::Net* net : parasitics_invalid_) { + if (isIdealClockNet(net)) { + continue; + } sta_->delaysInvalidFromFanin(net); }Problem 2 Fix: Ignore modes where the pin is not a clock
EstimateParasitics::isIdealClockPin()to classify a pin as ideal only if it is a clock in at least one mode and ideal in every mode where it is a clock.sta_->isClock(pin, mode)is false, which handles scan clocks that are only defined in test mode.EstimateParasitics::isIdealClockNet()to classify invalid nets by looking up the net driver and applying the ideal-clock pin check.parasiticsInvalid()behavior simple by still recording the flat invalid net, so callers and callbacks do not need special ideal-clock handling.updateParasitics(), skip ideal clock nets in the placement RC refresh loop, the routed RC refresh loop, and the bulksta_->delaysInvalidFromFanin()loop.TestEstimateParasitics.IdealClockNetSkipsStaInvalidationto prove an ideal clock net inparasitics_invalid_does not invalidate STA delay or arrival state.TestEstimateParasitics.ScanClockIdealOnlyInTestModeto prove a scan clock absent from function mode but ideal in test mode is still filtered correctly.flowchart TD A["parasitics_invalid_<br/>contains net"] --> B{"isIdealClockNet<br/>(net)?"} B -->|"yes"| C["Skip RC<br/>refresh"] C --> D["Skip delaysInvalidFromFanin<br/>(net)"] D --> E["No STA fanout<br/>invalidation"] B -->|"no"| F["Refresh<br/>estimated RC"] F --> G["Call delaysInvalidFromFanin<br/>(net)"] G --> H["Normal incremental STA<br/>invalidation"] classDef fix fill:#d9fbe5,stroke:#2f9e44,color:#0b3d20; class B,C,D,E fix;Impact
repair_designruntime by avoiding RC refresh and STA fanout invalidation for high-fanout ideal clock nets.EstimateParasitics, so callers need no special handling.Testing
ctest -R TestEstimateParasitics --output-on-failure: Passed,2/2.73ab73903351a102bf8b92c9ac5fda7ab5c483dd: Both new tests fail, with ideal clock CK vertices entering STA invalidation sets.e98fb4f4f7) vs TEST(1f7bc1d224) on 10 small designs: Final setup WNS/TNS, hold WNS/TNS, instance area/count, and total/internal/switching/leakage power matched exactly.Related