Skip to content

SpefReader: rescue findInstance/findNet for flat names with literal '/' or escaped specials#356

Merged
maliberty merged 4 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:sta_fix_spefrdr
Apr 30, 2026
Merged

SpefReader: rescue findInstance/findNet for flat names with literal '/' or escaped specials#356
maliberty merged 4 commits into
The-OpenROAD-Project:masterfrom
The-OpenROAD-Project-staging:sta_fix_spefrdr

Conversation

@openroad-ci
Copy link
Copy Markdown
Collaborator

Problem

SpefReader::findInstanceRelative and findNetRelative go through
Network::findInstanceRelative / findNetRelative, which always split the
incoming name at unescaped / and walk the design hierarchically via
findChild. That misses two name forms that show up routinely in flows
where the netlist is loaded from DEF rather than verilog:

  1. Flat names containing a literal / — e.g. CTS-inserted buffers
    named u_sx1_iq/g1496206. The DEF reader stores the bare string in
    OpenDB; the splitter parses it as parent u_sx1_iq + leaf g1496206,
    no such parent module exists, and the lookup fails. Manifests as
    STA-1648 instance ... not found.

  2. SPEF-spec-escaped names — e.g. bus\[0\] for bus bits or
    u_sx1_iq\/g1496206 for literal-slash names per the SPEF grammar.
    The escape-aware splitter correctly treats these as one segment, but
    the literal block_->findInst() lookup that follows then misses
    because the DEF reader stored the unescaped form. Manifests as the
    same STA-1648/1650 family.

dbNetwork::findInstance (the non-relative override) and
dbNetwork::findNet at top scope already have a flat
block_->find{Inst,Net}() fallback that the splitter-based path never
reaches.

Fix

In SpefReader::findInstanceRelative / findNetRelative, after the
existing strict + sdc-namespace lookups miss, fall through to:

  1. network_->findInstance(name) / network_->findNet(instance_, name)
    — bypasses the splitter, hits the flat-literal lookup that finds
    raw-/ names.
  2. Same call again with backslash-escapes stripped via a new
    stripped() helper — handles SPEF-spec \[, \], \/, \\ when
    OpenDB has the unescaped form.

The stripped path runs only when name.find('\\') != npos so the common
case (no escapes) does no allocation. Behavior is purely additive:
every lookup that previously hit the strict path still hits it on the
first attempt.

A spef_lookup debug category is added that emits one line per lookup
showing whether it found anything (level 1 prints; gate via
sta::set_debug spef_lookup 1).

Test

Regression added on the OpenROAD side at
src/dbSta/test/spef_def_names.{tcl,def,spef,ok}: a small flat design
where the DEF stores instances/nets with literal / and [], and a
SPEF references them with SPEF-spec escapes (\/, \[, \]). Without
this fix the test produces ~10 STA-1648/1650 warnings; with the fix it
runs clean.

Files

parasitics/SpefReader.cc
parasitics/SpefReaderPvt.hh

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Copy link
Copy Markdown

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

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 improves instance and net lookup in the SpefReader by adding a fallback mechanism for flat names containing literal slashes or escaped characters. I have provided feedback regarding the use of absolute lookups in findInstanceRelative, suggesting the use of findChild to maintain correct hierarchical context, as findInstance may incorrectly resolve names relative to the design top.

Comment thread parasitics/SpefReader.cc Outdated
Comment on lines +162 to +165
if (inst == nullptr)
inst = network_->findInstance(name);
if (inst == nullptr && name.find('\\') != std::string_view::npos)
inst = network_->findInstance(stripped(name));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The use of network_->findInstance(name) is problematic for hierarchical designs because it performs an absolute lookup starting from the design top. If instance_ is a sub-block and the SPEF name is relative to it, this will fail or return the wrong instance. Furthermore, the default implementation of Network::findInstance typically delegates to findInstanceRelative(top, name), which uses the same path-splitting logic that just failed in the first attempt.

To correctly perform a flat lookup that respects literal / characters and remains relative to the current instance_, you should use network_->findChild(instance_, name). This is also consistent with how findNet is handled in findNetRelative (using network_->findNet(instance_, name)).

  if (inst == nullptr)
    inst = network_->findChild(instance_, name);
  if (inst == nullptr && name.find('\\') != std::string_view::npos)
    inst = network_->findChild(instance_, stripped(name));

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
@maliberty
Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

@maliberty maliberty merged commit d503c0e into The-OpenROAD-Project:master Apr 30, 2026
7 checks passed
@openroad-ci openroad-ci deleted the sta_fix_spefrdr branch April 30, 2026 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants