Skip to content

search: POCV per-stage sigma holder + LVF variance injection + LVF-library gate (stacks on #383)#385

Open
saurav-fermions wants to merge 7 commits into
The-OpenROAD-Project:masterfrom
Fermions-ASI:feat/pocv-lvf
Open

search: POCV per-stage sigma holder + LVF variance injection + LVF-library gate (stacks on #383)#385
saurav-fermions wants to merge 7 commits into
The-OpenROAD-Project:masterfrom
Fermions-ASI:feat/pocv-lvf

Conversation

@saurav-fermions

Copy link
Copy Markdown

Summary

Adds a parametric statistical-OCV (POCV / LVF) capability in three layered, default-OFF slices. With POCV inactive, timing is byte-identical to upstream.

1. POCV per-stage sigma state holder (Search.hh)

Adds a default-OFF Search::PocvSigma state holder (enabled, per-stage sigma fraction, n_sigma, active()) plus inline pocvSigma()/setPocvSigma() accessors and a pocv_sigma_ member. Read only by an external report-only POCV command; no forward-search code reads it. Parametric POCV variation combines in quadrature (root-sum-square), which does not compose with the additive arrival sum the search propagates, so this holder is intentionally not a propagation hook.

2. LVF propagation-time variance injection (Search.cc, Search.hh)

Injects the synthetic per-stage POCV sigma (k*d_i)^2 into combinational data-path arc delays inside deratedDelayData when PocvSigma is in -propagate mode. The native statistical delay-ops (DelayOpsNormal) then accumulate the variance in quadrature through delaySum during the forward search, reporting arrival ± n_sigma·sqrt(variance). Factors the scalar (mean) data-path derate into deratedDelayDataMean; layers variance on top without changing the mean. Default OFF → zero variance → byte-identical baseline.

3. LVF-lib library-driven POCV gate (Search.hh)

Adds PocvSigma::from_liberty so set_pocv_sigma -from_liberty sources the per-stage delay sigma from real Liberty LVF ocv_sigma_* tables via the native statistical delay calc (GateTableModel::gateDelayPocv under PocvMode::normal) instead of the synthetic global per_stage. In this mode propagateActive() returns false so the synthetic (k*d) injection is suppressed and cannot overwrite the library-derived stdDev. Default from_liberty=false keeps the -propagate/-sigma behavior and a byte-identical flag-off baseline.

⚠️ Depends on #383 (AOCV depth-derate + SI-window)

This is a stacked PR on top of #383. It layers directly on the deratedDelayData hook that #383 introduces (patch 2 splits it into deratedDelayDataMean + variance). GitHub will show the two #383 commits here until that PR merges; after it merges I'll rebase this onto master and only the three POCV commits will remain. Please review/merge #383 first.

Testing

  • Full OpenSTA ctest suite: 6083/6084 pass. The single failure (tcl.power.vcd_detailed) is a pre-existing last-digit floating-point rounding diff in the power module that fails identically on unmodified master (unrelated to this change).
  • POCV report-only: worst_slack/WNS/TNS byte-identical POCV-on vs off; quadrature direction proven (sqrt-of-N). LVF-propagate: real sqrt(N) de-pessimism; default-OFF byte-identical after propagate+reset. LVF-from-Liberty: sources per-cell/per-arc sigma from Liberty LVF tables; from_liberty=false byte-identical baseline.

Notes

  • clang-format intentionally not run on src/sta/* per project convention.
  • All three slices are default-off; no behavior change for existing users.

Add a flag-gated hook (AocvDepthDerate interface + Search::deratedDelayData)
so the OCV derate applied to data-path combinational arcs during forward
arrival propagation can be selected by the path's accumulated combinational
depth instead of the flat SDC factor.

When no hook is installed (the default) deratedDelayData forwards verbatim to
deratedDelay, so timing is byte-identical to upstream. Only data-path
combinational cell arcs are depth-derated; clock/reg/latch/check arcs keep the
flat derate. Depth is the count of combinational arcs on the live from_path
prev chain + 1.

All edits marked // OpenROAD-fork: AOCV. clang-format not run on src/sta/*.




Signed-off-by: Saurav Singh <saurav.singh@fermions.co>
Add Parasitics::setCapacitorValue (default no-op) and a ConcreteParasitics
override / ConcreteParasiticDevice::setValue so the OpenROAD timing-window
aware coupling derate can scale individual coupling caps. Only invoked from
the OpenROAD window path; stock OpenSTA behavior is unchanged.




Signed-off-by: Saurav Singh <saurav.singh@fermions.co>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@gemini-code-assist

Copy link
Copy Markdown

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

… review)

Return early on a null ParasiticCapacitor instead of dereferencing it.


Signed-off-by: Saurav Singh <saurav.singh@fermions.co>
Add a default-OFF Search::PocvSigma state holder (enabled, per-stage sigma
fraction, n_sigma, active()) plus inline pocvSigma()/setPocvSigma() accessors
and a pocv_sigma_ member. This is read ONLY by the OpenROAD-side report-only
POCV command (report_checks_pocv / pocvAdjustPathEnd in src/dbSta); no
forward-search / arrival-propagation code reads it, so with POCV inactive (the
default) timing is byte-identical to upstream.

Parametric POCV variation combines in quadrature (root-sum-square), which does
not compose with the additive arrival sum the search propagates, so POCV is
intentionally NOT a propagation hook (unlike AOCV). See POCV_INVESTIGATION.md.

Header-only edit, marked // OpenROAD-fork: POCV. clang-format not run on
src/sta/*.



Signed-off-by: Saurav Singh <saurav.singh@fermions.co>
…ce injection

Inject the synthetic per-stage POCV sigma (k*d_i)^2 into combinational
data-path arc delays inside deratedDelayData when PocvSigma is in -propagate
mode. The native statistical delay-ops (DelayOpsNormal) then accumulate the
variance in quadrature through delaySum during the forward search, and report
arrival +/- n_sigma*sqrt(variance) at the checks.

- Search.hh: add PocvSigma::propagate flag + propagateActive() gate.
- Search.cc: factor the scalar (mean) data-path derate into
  deratedDelayDataMean; deratedDelayData layers the synthetic variance on top
  without changing the mean.

Default OFF (propagate=false) and scalar PocvMode => zero variance => timing is
byte-identical to baseline.



Signed-off-by: Saurav Singh <saurav.singh@fermions.co>
Add PocvSigma::from_liberty so set_pocv_sigma -from_liberty sources the
per-stage delay sigma from the real Liberty LVF ocv_sigma_* tables via
the native statistical delay calc (GateTableModel::gateDelayPocv under
PocvMode::normal) instead of the synthetic global per_stage. In this
mode propagateActive() returns false so the synthetic (k*d) injection
in Search::deratedDelayData is suppressed and cannot overwrite the
library-derived stdDev. Default from_liberty=false keeps the existing
-propagate/-sigma behaviour and a byte-identical flag-off baseline.



Signed-off-by: Saurav Singh <saurav.singh@fermions.co>
@saurav-fermions

Copy link
Copy Markdown
Author

/gemini review

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

Copy link
Copy Markdown

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 introduces support for OpenROAD-fork specific features, including SI-window aware coupling capacitor value adjustments, depth-dependent OCV derating (AOCV), and parametric OCV (POCV/LVF) parameters with propagation-time synthetic variance injection. The review feedback suggests several improvements: ensuring that POCV/LVF activation checks strictly require positive coefficients (> 0.0f) to prevent negative values, adding an early return for infinite delays in deratedDelayData to avoid potential NaN or undefined behavior, and optimizing a redundant delayAsFloat call within a critical timing loop.

Comment thread include/sta/Search.hh Outdated
Comment on lines +432 to +435
bool active() const { return enabled && per_stage != 0.0f && n_sigma != 0.0f; }
// OpenROAD-fork: LVF-lib -- library-driven mode gate. Independent of the
// synthetic per_stage; needs only enabled + a sign-off quantile (n_sigma).
bool libertyActive() const { return enabled && from_liberty && n_sigma != 0.0f; }

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

Using != 0.0f to check if per_stage and n_sigma are active can allow negative or invalid values to pass through, which could lead to incorrect statistical calculations (e.g., negative standard deviation). It is safer and more robust to ensure these coefficients are strictly positive (> 0.0f) before activating the POCV/LVF logic.

Suggested change
bool active() const { return enabled && per_stage != 0.0f && n_sigma != 0.0f; }
// OpenROAD-fork: LVF-lib -- library-driven mode gate. Independent of the
// synthetic per_stage; needs only enabled + a sign-off quantile (n_sigma).
bool libertyActive() const { return enabled && from_liberty && n_sigma != 0.0f; }
bool active() const { return enabled && per_stage > 0.0f && n_sigma > 0.0f; }
// OpenROAD-fork: LVF-lib -- library-driven mode gate. Independent of the
// synthetic per_stage; needs only enabled + a sign-off quantile (n_sigma).
bool libertyActive() const { return enabled && from_liberty && n_sigma > 0.0f; }

Comment thread search/Search.cc
Comment on lines +3067 to +3070
ArcDelay delay = deratedDelayDataMean(from_path, from_vertex, arc, edge,
min_max, dcalc_ap, sdc);

// OpenROAD-fork: LVF -- propagation-time POCV variance injection.

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

If the computed mean delay is infinite (e.g., representing an unconstrained or blocked path), performing float operations on it or passing it to makeDelay is unnecessary and could potentially lead to NaN or other undefined behavior. It is safer to check if the delay is infinite using delayInf and return early.

  ArcDelay delay = deratedDelayDataMean(from_path, from_vertex, arc, edge,
                                        min_max, dcalc_ap, sdc);

  if (delayInf(delay, this))
    return delay;

  // OpenROAD-fork: LVF -- propagation-time POCV variance injection.

Comment thread search/Search.cc Outdated
Comment on lines +3081 to +3089
const float d = delayAsFloat(delay); // nominal stage delay mean
if (d > 0.0f) {
const float stage_sigma = k * d; // per-stage sigma = k * d_i
// makeDelay(mean, std_dev) stores std_dev^2 == (k*d_i)^2 as the variance,
// which is exactly the per-stage contribution the path accumulates in
// quadrature. The mean is preserved so the nominal arrival is unchanged.
// Any prior arc variance (e.g. from LVF liberty) is replaced by the
// synthetic model on purpose -- they are mutually exclusive configs.
delay = makeDelay(delayAsFloat(delay), stage_sigma);

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

Since delayAsFloat(delay) is already computed and stored in d, we can reuse d instead of calling delayAsFloat(delay) again. This avoids a redundant function call/conversion in a critical timing propagation loop.

    const float d = delayAsFloat(delay);  // nominal stage delay mean
    if (d > 0.0f) {
      const float stage_sigma = k * d;  // per-stage sigma = k * d_i
      // makeDelay(mean, std_dev) stores std_dev^2 == (k*d_i)^2 as the variance,
      // which is exactly the per-stage contribution the path accumulates in
      // quadrature. The mean is preserved so the nominal arrival is unchanged.
      // Any prior arc variance (e.g. from LVF liberty) is replaced by the
      // synthetic model on purpose -- they are mutually exclusive configs.
      delay = makeDelay(d, stage_sigma);

- PocvSigma::active()/libertyActive(): require per_stage/n_sigma > 0.0f
  (reject negative/invalid values, not just != 0).
- Variance injection: guard against non-finite stage delay (std::isfinite)
  and reuse the already-computed mean 'd' instead of recomputing delayAsFloat.

Signed-off-by: Saurav Singh <saurav.singh@fermions.co>
@saurav-fermions

Copy link
Copy Markdown
Author

Thanks — addressed the review (gemini review re-ran fine after the earlier error):

  • active() / libertyActive(): now require per_stage > 0.0f / n_sigma > 0.0f instead of != 0.0f, so negative/invalid values don't count as active.
  • Variance injection: guard the stage delay with std::isfinite(d) (skip non-finite means), and reuse the already-computed mean d in makeDelay(d, stage_sigma) instead of recomputing delayAsFloat(delay).

search/sdc/derate/crpr/multicorner + pocv/lvf suites pass (118/118). (Still a draft — stacks on #383.)

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.

2 participants