Skip to content

Case insensitive object matching#62

Merged
akashlevy merged 1 commit into
mainfrom
case_insensitive_matching
Jun 9, 2026
Merged

Case insensitive object matching#62
akashlevy merged 1 commit into
mainfrom
case_insensitive_matching

Conversation

@akashlevy

Copy link
Copy Markdown

No description provided.

@greptile-apps

greptile-apps Bot commented Jun 9, 2026

Copy link
Copy Markdown

Greptile Summary

Introduces a new Tcl variable sta_case_insensitive_matching that, when set, makes all get_* and find_*_matching commands match port, instance, net, cell, clock, and library names case-insensitively. The feature is wired end-to-end through a C++ Variables flag, SWIG bindings, a Tcl trace, and updated matching logic in both PatternMatch and FilterObjects.

  • C++ layer (Variables.hh, Sta.hh/cc, Search.i): adds a case_insensitive_matching_ bool with the standard accessor/mutator pattern, exposed to Tcl via SWIG following the same convention as enable_collections.
  • Matching logic (PatternMatch.cc, FilterObjects.cc): hasWildcards() returns true when the flag is set (forcing linear iteration instead of hash lookup), match() and matchNoCase() pass nocase to patternMatchNoCase, and the ==/!=/=~/!~ filter operators in filterObjects respect the flag; find_liberty_libraries_matching in Sdc.tcl uses string match -nocase / regexp -nocase accordingly.
  • Tests (test/case_insensitive_matching.tcl/.ok): covers all major object types with the flag on and off, including filter expressions, and verifies that case-sensitivity is restored when the variable is reset to 0.

Confidence Score: 4/5

Safe to merge; the feature is well-contained, covered by a new regression test, and follows existing conventions throughout the codebase.

The glob-pattern path correctly reads the case-insensitive flag at call time in match(). The regexp path compiles the regexp eagerly in the constructor, so a regexp-mode PatternMatch created before the flag is set will iterate correctly (because hasWildcards() reads the flag lazily) but will still use a case-sensitive compiled regexp — the two halves can disagree if the flag is toggled between object construction and first use. Normal command-level usage is unaffected because commands create fresh PatternMatch objects after the flag is already set.

util/PatternMatch.cc — the interaction between eager regexp compilation and the lazy caseInsensitiveMatching() reads in hasWildcards() and match() deserves a second look.

Important Files Changed

Filename Overview
util/PatternMatch.cc Adds global caseInsensitiveMatching() helper and wires it into hasWildcards(), match(), and matchNoCase(); glob paths read the flag lazily but the regexp is compiled eagerly in the constructor, creating a potential inconsistency.
sdc/FilterObjects.cc Adds case-insensitive exact/glob comparisons using stringEqual and patternMatchNoCase for the ==/!=/=~/!~ filter operators; implementation is consistent and correct.
sdc/Sdc.tcl Extends find_liberty_libraries_matching to honour sta_case_insensitive_matching by forwarding to string match -nocase / regexp -nocase; logic is correct for all four regexp × nocase combinations.
include/sta/Variables.hh Adds case_insensitive_matching_ boolean member and its inline accessor/mutator; follows the established pattern for other Silimate-added variables.
sdc/Variables.tcl Registers a Tcl trace on ::sta_case_insensitive_matching that delegates to the new C++ getter/setter pair via trace_boolean_var; consistent with the pattern used by sta_enable_collections.
search/Sta.cc Adds caseInsensitiveMatching() and setCaseInsensitiveMatching() delegating to variables_; straightforward passthrough.
search/Search.i Exposes the new C++ getter/setter to the Tcl SWIG layer; follows the identical pattern used for enable_collections.
include/sta/Sta.hh Declares the two new public methods; placed correctly next to enableCollections.
test/case_insensitive_matching.tcl New regression test covering ports, cells, pins, nets, clocks, lib-cells, lib-pins, and filter expressions with the flag on/off; verifies restored case-sensitivity after resetting the variable.
test/case_insensitive_matching.ok Expected output for the new regression; results look correct — objects are found by case-insensitive pattern and returned under their original (lower-case) names.
test/regression_vars.tcl Registers the new test in the public test suite; no issues.

Sequence Diagram

sequenceDiagram
    participant TCL as Tcl Script
    participant Trace as trace_case_insensitive_matching
    participant SWIG as Search.i (SWIG)
    participant Sta as Sta / Variables
    participant PM as PatternMatch
    participant FO as FilterObjects

    TCL->>Trace: set sta_case_insensitive_matching 1
    Trace->>SWIG: set_case_insensitive_matching(true)
    SWIG->>Sta: setCaseInsensitiveMatching(true)
    Sta->>Sta: "variables_->case_insensitive_matching_ = true"

    TCL->>SWIG: "get_cells -quiet U*"
    SWIG->>PM: "PatternMatch(U*, false, false, interp)"
    Note over PM: is_regexp_=false, no compileRegexp()
    SWIG->>PM: hasWildcards()
    PM->>Sta: caseInsensitiveMatching() → true
    PM-->>SWIG: true (forces linear scan)
    loop each candidate cell
        SWIG->>PM: match(cell_name)
        PM->>Sta: caseInsensitiveMatching() → true
        PM->>PM: "patternMatchNoCase(U*, name, true)"
        PM-->>SWIG: matched?
    end
    SWIG-->>TCL: matching cells

    TCL->>SWIG: "get_cells -filter full_name==R1"
    SWIG->>FO: "filterObjects(full_name, ==, R1, all, sta)"
    FO->>Sta: caseInsensitiveMatching() → true
    FO->>FO: "eq = stringEqual(prop, R1) [case-insensitive]"
    FO-->>SWIG: filtered set
    SWIG-->>TCL: matching cells
Loading

Comments Outside Diff (1)

  1. util/PatternMatch.cc, line 87-103 (link)

    P2 Regexp compiled eagerly, contradicting the "lazy" comment

    compileRegexp() is called inside the constructor and captures caseInsensitiveMatching() at construction time. This means if sta_case_insensitive_matching is toggled after a regexp-mode PatternMatch is created but before match() is called, the compiled regexp will carry the stale case-sensitivity flag. The module-level comment on the helper says "Read lazily so that toggling the variable takes effect immediately" — but that property only holds for glob patterns (where match() re-calls the helper at call time). A PatternMatch with is_regexp=true created before the flag is set would iterate correctly (because hasWildcards() re-reads the flag lazily) yet match case-sensitively (because the compiled regexp was never recompiled with TCL_REG_NOCASE). Consider either recompiling the regexp inside match() when the live flag differs from the compile-time flag, or narrowing the comment to reflect that the lazy guarantee applies only to glob patterns.

Reviews (1): Last reviewed commit: "Case insensitive object matching" | Re-trigger Greptile

@akashlevy akashlevy merged commit eb4ab4c into main Jun 9, 2026
8 checks passed
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.

1 participant