Missing para dbmodnet#9745
Conversation
There was a problem hiding this comment.
Code Review
This pull request addresses a bug in parasitic extraction for hierarchical designs by ensuring highestConnectedNet correctly resolves a dbModNet to its corresponding flat dbNet. The logic in dbNetwork.cc is sound and directly fixes the described issue. The addition of the parasitics_annotated helper function in dbSta.i is a useful addition for testing and scripting. The minor suggestion in dbNetwork.cc to improve code clarity and conciseness remains valid.
| dbNet* db_net = nullptr; | ||
| odb::dbModNet* db_modnet = nullptr; | ||
| staToDb(net, db_net, db_modnet); | ||
| if (db_modnet) { | ||
| dbNet* flat_net = db_modnet->findRelatedNet(); | ||
| if (flat_net) { | ||
| return dbToSta(flat_net); | ||
| } | ||
| } | ||
| return net; |
There was a problem hiding this comment.
This implementation is correct. It can be slightly refactored for conciseness and to clarify intent regarding an unused variable. The db_net variable is required for the staToDb call but is not used thereafter. Renaming it to db_net_unused makes this explicit. Additionally, the nested if can be simplified using a C++17 if-statement with an initializer, which also scopes the flat_net variable more tightly.
dbNet* db_net_unused = nullptr;
odb::dbModNet* db_modnet = nullptr;
staToDb(net, db_net_unused, db_modnet);
if (db_modnet) {
if (dbNet* flat_net = db_modnet->findRelatedNet()) {
return dbToSta(flat_net);
}
}
return net;There was a problem hiding this comment.
Net* dbNetwork::findFlatNet(const Net* net) does the same thing.
You can simply call it.
There was a problem hiding this comment.
Thank you. I think I did this because of the difference in fallback logic. But there is a simple change that can fix that and use findFlatNet instead, just uploaded it now.
|
clang-tidy review says "All clean, LGTM! 👍" |
maliberty
left a comment
There was a problem hiding this comment.
Looks fine but I think worth a secure-CI run as it may affect parasiti
| @@ -228,6 +228,11 @@ void check_axioms_cmd() | |||
| sta->checkSanity(); | |||
| } | |||
|
|
|||
| bool parasitics_annotated(Pin *pin, Scene *scene) { | |||
There was a problem hiding this comment.
I dropped this commit- it was from Martin
Secure-CI ongoing https://jenkins.openroad.tools/job/OpenROAD-flow-scripts-Private/job/secure-fix_missing_para_dbmodnet/ |
There was a problem hiding this comment.
The objective of Network::highestConnectedNet(Net* net) is to retrieve the hierarchical net in the highest module.
But the this dbNetwork::highestConnectedNet(Net* net) finds the corresponding flat net for the given hier net, which is a different behavior.
Fortunately, there is only one caller Parasitics::findParasiticNet(const Pin *pin). So the current fix works.
But if Network::highestConnectedNet(Net* net) is used by another caller for a different purpose later, this fix can make a trouble.
I don't have a better idea about how to solve this issue.
But let's leave a comment to describe this issue.
e.g.,
// Caution:
// - `Network::highestConnectedNet(Net *net)` retrieves the highest hierarchical net connected to the given net.
// - But `dbNetwork::highestConnectedNet(Net* net)` retrieves the corresponding flat net for the given net.
// It behaves differently to cope with the issue #9724.
// - This redefinition may cause another issue later when `Network::highestConnectedNet(Net *net)` is used elsewhere.
There was a problem hiding this comment.
I don't have a better idea about how to solve this issue.
To me the clean solution is to only ever expose hierarchical nets to STA since that seems to be what it's expecting and that's how ConcreteNetwork implements Network
There was a problem hiding this comment.
Unfortunately that isn't possible with the way hierarchy was implemented in odb. For a net that is local to a single module we only create the flat net and skip the hierarchical one (since it would be equivalent as the net doesn't span a boundary). That complicates the API but does save memory on a flat design. The tradeoff could be revisited.
There was a problem hiding this comment.
@maliberty in that case shouldn't we expose dbNet to STA only for those nets local to a module, and use dbModNet otherwise? That would match ConcreteNetwork as far as STA could tell
There was a problem hiding this comment.
This is what my
To me the clean solution is to only ever expose hierarchical nets...
comment was referring to. We don't consistently use dbModNet for nets which have them, which is a source of perpetual trouble.
There was a problem hiding this comment.
I consider that a bug but the model remains as I stated it. I agree it would be simpler if we always allocated the modnet even if it was a duplicate of the dbNet. The downside is for a flat design it would double the net memory usage.
There was a problem hiding this comment.
I'm not advocating for allocating dbmodnet in the trivial case but pointing out the bug. I understand the model.
There was a problem hiding this comment.
Maybe I didn't understand "in that case shouldn't we expose dbNet to STA only for those nets local to a module, and use dbModNet otherwise?" - were you asking about the model or pointing out a bug?
There was a problem hiding this comment.
It's because of the context of the thread (what should highestConnectedNet do) that I thought the bug is implied
…tails Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
|
clang-tidy review says "All clean, LGTM! 👍" |
fb1b762 to
09730f1
Compare
|
clang-tidy review says "All clean, LGTM! 👍" |
I see some concerning things in this CI. There is a crash in a design (asap/swerv_wrapper), plus one design still triggered Martin's missing parasitics check (ihp-sg13g2/i2c-gpio-extender). So I will need to debug this a bit more before this PR can be merged |
|
There were secure-CI failures with this change- please do not merge this before I review those. Thanks |
|
Does this need a metrics update? |
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
|
There is a crash in asap7/werv_wrapper with current change. The crash is a threshold_times_ out-of-bounds access in PrimaDelayCalc::measureThresholds, triggered because node_count_ = 0 for certain nets in swerv_wrapper after this fix enables PRIMA to run on nets it never touched before. This happens because the highestConnectedNet change while correct to solve the null return for findParasiticNetwork, exposes a secondary bug: the isExternal flag in parasitic pin nodes was set incorrectly during SPEF loading for hierarchical nets. Now every pin node in the parasitic network for a hierarchically-connected net is flagged external. Before my fixfindParasiticNetwork(pin) → findParasiticNet(pin) → highestConnectedNet(net) → returned mod net → parasitic_network_map_.find(mod_net) → null → findParasitic() returns null → gateDelays() hits failed = true → falls back to tableDcalcResults(). PRIMA never ran. No crash. I am exploring what best additional fix needed to take care of this. |
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
|
clang-tidy review says "All clean, LGTM! 👍" |
|
clang-tidy review says "All clean, LGTM! 👍" |
dsengupta0628
left a comment
There was a problem hiding this comment.
will likely need ORFS rebasing. check
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
|
@codex review |
|
clang-tidy review says "All clean, LGTM! 👍" |
|
Codex Review: Didn't find any major issues. Already looking forward to the next diff. ℹ️ 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". |
|
ORFS PR: The-OpenROAD-Project/OpenROAD-flow-scripts#4050 |
dsengupta0628
left a comment
There was a problem hiding this comment.
Codex did not find any issue
|
clang-tidy review says "All clean, LGTM! 👍" |
dsengupta0628
left a comment
There was a problem hiding this comment.
I am the author so I approve my change (though we may need GHA change to not require my review on my authored PRs)
|
any metrics update required? |
Yes. Already added the metrics PR in the excel doc. ORFS PR: The-OpenROAD-Project/OpenROAD-flow-scripts#4050 |
OpenROAD's ODB maintains two net representations simultaneously for hierarchical designs:
A flat dbITerm (leaf cell pin) can be connected to both. dbNetwork::net(pin) returns the modnet wrapper first
The bug (before fix)
highestConnectedNet is called by findParasiticNet to get the canonical lookup key for the parasitic map:
findParasiticNet(driver_pin)
→ network_->net(driver_pin) # returns modnet STA wrapper (priority)
→ network_->highestConnectedNet() # OLD: trivially returns net unchanged
→ parasitic_network_map_.find(modnet_key) # MISS — SPEF stored under flat net key
→ nullptr
SPEF is a flat format — when read, parasitics are always stored keyed by the flat dbNet STA wrapper. But the lookup was being done with the modnet STA wrapper → cache miss → parasitic = nullptr → LumpedCap fallback → And this was hitting the bug in LumpedCapDelayCalc::makeResult (tracked separately with James Cherry)
With the fix, findRelatedNet() walks the modnet's connected flat dbITerm objects and returns the first iterm->getNet() it finds — which is the flat dbNet that the SPEF parasitic is keyed under.