Skip to content

est: delete the parasitic network when its dbNet is destroyed - #11227

Merged
eder-matheus merged 2 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:delete_para_anno_fix
Aug 25, 2026
Merged

est: delete the parasitic network when its dbNet is destroyed#11227
eder-matheus merged 2 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:delete_para_anno_fix

Conversation

@dsengupta0628

Copy link
Copy Markdown
Contributor

Summary

Fixes #11192. Fixes the crashes reported in #11178.

Problem

sta::Net* is the dbNet* (dbNetwork::dbToSta is a reinterpret_cast), and ConcreteParasitics keys parasitic_network_map_ by it. Destroying a dbNet only disconnected the parasitic network's pin nodes — the network itself stayed annotated on the dead net, because EstimateParasitics::eraseParasitics() only erased the net from parasitics_invalid_.

odb recycles dbNet slots, so the next net created lands on the same sta::Net* and inherits a network that has wire nodes but no node for its driver pin.

flowchart TD
    A["repair_timing edits netlist<br/>dbNet::destroy()"] --> B["inDbNetDestroy() fires"]
    B --> C["eraseParasitics() clears only<br/>the parasitics_invalid_ marker"]
    C --> D["Network stays in parasitic_network_map_,<br/>pin nodes already disconnected"]
    D --> E["odb recycles the dbNet slot"]
    E --> F["New net = same sta::Net*<br/>inherits a driver-less network"]
    F --> G{"Delay calculator"}
    G -->|table| H["Reduces it to pi-Elmore.<br/>Silently wrong, no crash."]
    G -->|prima| I["No driver node<br/>node_count_ == 0"]
    I --> J["Zero-node circuit:<br/>empty threshold_times_,<br/>singular matrix → SIGSEGV"]
Loading

Only CCS/prima runs crash. The table calculator reduces the stale network and never inspects individual nodes, so it just uses wrong numbers.

Both stacks in #11178 reach this through the same middle section — the incremental router re-entering the timer — differing only in the resizer entry point:

rsz::Resizer::repairSetup -> SetupLegacyPolicy::repairEndpoint  \
rsz::Resizer::repairHold  -> RepairHold::makeHoldDelay          /
  -> est::EstimateParasitics::updateParasitics
    -> grt::GlobalRouter::updateDirtyRoutes -> FastRouteCore::layerAssignment
      -> updateSlacks -> sta::Sta::slack -> ... -> PrimaDelayCalc::simulate1

Why this fix is in OpenROAD, not OpenSTA

  • The premise is OpenROAD's. sta::Net*-is-dbNet* is a dbSta invention and slot recycling is odb's. Upstream OpenSTA has no notion of one net pointer later meaning a different net; teaching it that would export an OpenROAD-specific representation upstream.
  • est owns these annotations. They are produced by estimate_parasitics, not read from SPEF. est already had a net-destroy hook, eraseParasitics(), meant for exactly this cleanup — it just did too little. sta::Parasitics is a passive store.

Fix

eraseParasitics() now deletes the annotation across all scenes, min and max.

It calls deleteParasiticNetwork() and not deleteParasitics(): the latter resolves drivers(net), and dbNet::destroy() has already disconnected every iterm by the time inDbNetDestroy() fires, so that lookup finds no driver and re-populates dbNetwork's driver cache with an empty entry keyed on a dbNet that is about to be freed.

Test

src/est/test/prima_net_recycle - 6 instances, one net destroyed and rebuilt with an identical pin set. Crashes before the fix in PrimaDelayCalc::measureThresholds-->simulate1; passes after this fix.

Two conditions needed to be met, and hence commented in the test:

  • prima must be selected before estimate_parasitics, or the default calculator reduces each network to pi-Elmore and deletes it, leaving nothing to inherit.
  • the driven net needs >= 1.44 fF (the CCS tables' lowest total_output_net_capacitance), or PrimaDelayCalc::checkArgs() falls back to the table calculator and the test is vacuous. Hence the extra inverter loads.

Adds test/asap7/asap7_small_ccs.lib.gz with public filegroups //test:asap7_ccs_data and //test:asap7_data. OpenROAD had no asap7 CCS liberty outside the src/sta submodule, and the shared asap7 libs are NLDM only, so prima could not be exercised from a module test before this.

Type of Change

  • Bug fix

Impact

[How does this change the tool's behavior?]

Verification

  • I have verified that the local build succeeds (./etc/Build.sh).
  • I have run the relevant tests and they pass.
  • My code follows the repository's formatting guidelines.
  • I have included tests to prevent regressions.
  • I have signed my commits (DCO).

Related Issues

#11178
#11192

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
@dsengupta0628 dsengupta0628 self-assigned this Aug 25, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request ensures that destroying a dbNet properly deletes its associated parasitic network annotation. Previously, dbNet::destroy() only disconnected pin nodes, leaving a driver-less network on the dead net, which could then be inherited by a new net when the dbNet slot was recycled. The fix explicitly deletes the parasitic network in EstimateParasitics::eraseParasitics. A new regression test prima_net_recycle has been added to verify this behavior, along with its corresponding test files and build targets. There are no review comments, and the implementation is clean and well-tested.

@dsengupta0628
dsengupta0628 marked this pull request as ready for review August 25, 2026 03:46
@dsengupta0628
dsengupta0628 requested review from a team as code owners August 25, 2026 03:46

@eder-matheus eder-matheus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dsengupta0628 Does it need a secure-ci run? You mentioned wrong values being calculated on the NLDM path. Perhaps this could affect some designs.

@dsengupta0628

Copy link
Copy Markdown
Contributor Author

@dsengupta0628 Does it need a secure-ci run? You mentioned wrong values being calculated on the NLDM path. Perhaps this could affect some designs.

Hi Eder. Yes I plan to run the full ORFS. I didn’t do it yet as it was very late last night by the time I filed this PR :)

@dsengupta0628

dsengupta0628 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

@dsengupta0628 Does it need a secure-ci run? You mentioned wrong values being calculated on the NLDM path. Perhaps this could affect some designs.

The-OpenROAD-Project/OpenROAD-flow-scripts#4472 shows all clean
secure ci http://secure-ci:8080/job/SB/job/secure-est_fix/ looks passed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EST: Reusing sta::Net* with annotated parasitic network after undoing buffer insertion then inserting new buffer

2 participants