pickup changes from upstream, latest on 4/27

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
This commit is contained in:
dsengupta0628 2026-04-27 18:45:35 +00:00
commit ae37dc6238
28 changed files with 188 additions and 137 deletions

View File

@ -76,5 +76,7 @@ HeaderFilterRegex: '.*/(app|cmake|dcalc|graph|liberty|network|parasitics|power|s
# util/gzstream.hh # util/gzstream.hh
# util/FlexDisableRegister.hh # util/FlexDisableRegister.hh
# Bison-generated parser headers (build/{Liberty,Verilog,...}Parse.hh) # Bison-generated parser headers (build/{Liberty,Verilog,...}Parse.hh)
ExcludeHeaderFilterRegex: '(.*/)?(gzstream\.hh|FlexDisableRegister\.hh|(Liberty|Verilog|Sdf|Spef|Saif|LibExpr)Parse\.hh)$' # Homebrew and MacPorts third-party headers.
ExcludeHeaderFilterRegex: '(^/opt/(homebrew|local)/.*)|((.*/)?(gzstream\.hh|FlexDisableRegister\.hh|(Liberty|Verilog|Sdf|Spef|Saif|LibExpr)Parse\.hh)$)'
SystemHeaders: false
FormatStyle: none FormatStyle: none

View File

@ -0,0 +1,13 @@
---
description: Where OpenSTA regression tests live (pvt/test vs public test/)
alwaysApply: true
---
# OpenSTA tests and regression
- **Primary suite:** Most regression tests, Tcl drivers, and golden `.ok` files live under **`pvt/test/`** (private / separate repo, often opened as a second workspace root alongside `master`).
- **Public subset:** **`test/`** at the OpenSTA repo root holds a smaller set of tests shipped with the public tree (e.g. `test/regression`, `*.tcl`, `*.ok` there).
When searching for a test name, regression lists, or updating goldens, **check `pvt/test` first**, then `test/`.
Typical driver: `pvt/test/regression` (or `test/regression` for the public list). Built `sta` binary is usually `master/build/sta` relative to the main checkout.

View File

@ -69,7 +69,6 @@ class rcmodel : public ConcreteParasitic,
public arnoldi1 public arnoldi1
{ {
public: public:
rcmodel();
~rcmodel() override; ~rcmodel() override;
float capacitance() const override; float capacitance() const override;
PinSet unannotatedLoads(const Pin *drvr_pin, PinSet unannotatedLoads(const Pin *drvr_pin,

View File

@ -43,12 +43,11 @@ namespace sta {
// This is legacy C-style code. // This is legacy C-style code.
// NOLINTBEGIN(modernize-avoid-c-style-cast, bugprone-multi-level-implicit-pointer-conversion, bugprone-implicit-widening-of-multiplication-result) // NOLINTBEGIN(modernize-avoid-c-style-cast, bugprone-multi-level-implicit-pointer-conversion, bugprone-implicit-widening-of-multiplication-result)
rcmodel::rcmodel() rcmodel::~rcmodel()
{ {
free(pinV);
} }
rcmodel::~rcmodel() { free(pinV); }
float float
rcmodel::capacitance() const rcmodel::capacitance() const
{ {

View File

@ -121,7 +121,7 @@ DelayOpsNormal::greater(const Delay &delay1,
const StaState *sta) const const StaState *sta) const
{ {
return fuzzyGreater(delayAsFloat(delay1, EarlyLate::late(), sta), return fuzzyGreater(delayAsFloat(delay1, EarlyLate::late(), sta),
delayAsFloat(delay2, EarlyLate::late(), sta)); delayAsFloat(delay2, EarlyLate::late(), sta));
} }
bool bool
@ -130,7 +130,7 @@ DelayOpsNormal::greaterEqual(const Delay &delay1,
const StaState *sta) const const StaState *sta) const
{ {
return fuzzyGreaterEqual(delayAsFloat(delay1, EarlyLate::late(), sta), return fuzzyGreaterEqual(delayAsFloat(delay1, EarlyLate::late(), sta),
delayAsFloat(delay2, EarlyLate::late(), sta)); delayAsFloat(delay2, EarlyLate::late(), sta));
} }
Delay Delay
@ -138,7 +138,7 @@ DelayOpsNormal::sum(const Delay &delay1,
const Delay &delay2) const const Delay &delay2) const
{ {
return Delay(delay1.mean() + delay2.mean(), return Delay(delay1.mean() + delay2.mean(),
delay1.stdDev2() + delay2.stdDev2()); delay1.stdDev2() + delay2.stdDev2());
} }
Delay Delay
@ -146,7 +146,7 @@ DelayOpsNormal::sum(const Delay &delay1,
float delay2) const float delay2) const
{ {
return Delay(delay1.mean() + delay2, return Delay(delay1.mean() + delay2,
delay1.stdDev2()); delay1.stdDev2());
} }
Delay Delay

View File

@ -142,8 +142,10 @@ LumpedCapDelayCalc::gateDelay(const Pin *drvr_pin,
float gate_delay, drvr_slew; float gate_delay, drvr_slew;
float in_slew1 = delayAsFloat(in_slew); float in_slew1 = delayAsFloat(in_slew);
// NaNs cause seg faults during table lookup. // NaNs cause seg faults during table lookup.
if (std::isnan(load_cap) || std::isnan(in_slew.mean())) if (std::isnan(load_cap))
report_->error(1350, "gate delay input variable is NaN"); report_->error(1350, "gate delay load cap is NaN");
if (std::isnan(in_slew.mean()))
report_->error(1351, "gate delay input slew is NaN");
const Pvt *pvt = pinPvt(drvr_pin, scene, min_max); const Pvt *pvt = pinPvt(drvr_pin, scene, min_max);
model->gateDelay(pvt, in_slew1, load_cap, gate_delay, drvr_slew); model->gateDelay(pvt, in_slew1, load_cap, gate_delay, drvr_slew);

View File

@ -90,7 +90,7 @@ public:
// Return values. // Return values.
float &slew, float &slew,
bool &exists) const; bool &exists) const;
ClockUncertainties *uncertainties() const { return uncertainties_; } const ClockUncertainties &uncertainties() const { return uncertainties_; }
void uncertainty(const SetupHold *setup_hold, void uncertainty(const SetupHold *setup_hold,
// Return values. // Return values.
float &uncertainty, float &uncertainty,
@ -180,7 +180,7 @@ protected:
bool is_propagated_{false}; bool is_propagated_{false};
RiseFallMinMax slews_; RiseFallMinMax slews_;
RiseFallMinMax slew_limits_[path_clk_or_data_count]; RiseFallMinMax slew_limits_[path_clk_or_data_count];
ClockUncertainties *uncertainties_{nullptr}; ClockUncertainties uncertainties_;
bool is_generated_{false}; bool is_generated_{false};
// Generated clock variables. // Generated clock variables.
Pin *src_pin_{nullptr}; Pin *src_pin_{nullptr};

View File

@ -169,6 +169,11 @@ public:
static int cmp(const MinMaxValues *values1, static int cmp(const MinMaxValues *values1,
const MinMaxValues *values2) const MinMaxValues *values2)
{ {
if (!values1->exists_[MinMax::minIndex()]
&& !values2->exists_[MinMax::minIndex()]
&& !values1->exists_[MinMax::maxIndex()]
&& !values2->exists_[MinMax::maxIndex()])
return 0;
if (!values1->exists_[MinMax::minIndex()] if (!values1->exists_[MinMax::minIndex()]
&& values2->exists_[MinMax::minIndex()]) && values2->exists_[MinMax::minIndex()])
return -1; return -1;

View File

@ -99,25 +99,25 @@ public:
// return PropertyValue("bar"); // return PropertyValue("bar");
// }); // });
void defineProperty(std::string_view property, void defineProperty(std::string_view property,
PropertyRegistry<const Library *>::PropertyHandler &handler); const PropertyRegistry<const Library *>::PropertyHandler &handler);
void defineProperty(std::string_view property, void defineProperty(std::string_view property,
PropertyRegistry<const LibertyLibrary *>::PropertyHandler &handler); const PropertyRegistry<const LibertyLibrary *>::PropertyHandler &handler);
void defineProperty(std::string_view property, void defineProperty(std::string_view property,
PropertyRegistry<const Cell *>::PropertyHandler &handler); const PropertyRegistry<const Cell *>::PropertyHandler &handler);
void defineProperty(std::string_view property, void defineProperty(std::string_view property,
PropertyRegistry<const LibertyCell *>::PropertyHandler &handler); const PropertyRegistry<const LibertyCell *>::PropertyHandler &handler);
void defineProperty(std::string_view property, void defineProperty(std::string_view property,
PropertyRegistry<const Port *>::PropertyHandler &handler); const PropertyRegistry<const Port *>::PropertyHandler &handler);
void defineProperty(std::string_view property, void defineProperty(std::string_view property,
PropertyRegistry<const LibertyPort *>::PropertyHandler &handler); const PropertyRegistry<const LibertyPort *>::PropertyHandler &handler);
void defineProperty(std::string_view property, void defineProperty(std::string_view property,
PropertyRegistry<const Instance *>::PropertyHandler &handler); const PropertyRegistry<const Instance *>::PropertyHandler &handler);
void defineProperty(std::string_view property, void defineProperty(std::string_view property,
PropertyRegistry<const Pin *>::PropertyHandler &handler); const PropertyRegistry<const Pin *>::PropertyHandler &handler);
void defineProperty(std::string_view property, void defineProperty(std::string_view property,
PropertyRegistry<const Net *>::PropertyHandler &handler); const PropertyRegistry<const Net *>::PropertyHandler &handler);
void defineProperty(std::string_view property, void defineProperty(std::string_view property,
PropertyRegistry<const Clock *>::PropertyHandler &handler); const PropertyRegistry<const Clock *>::PropertyHandler &handler);
protected: protected:
PropertyValue portSlew(const Port *port, PropertyValue portSlew(const Port *port,

View File

@ -89,7 +89,7 @@ protected:
std::string name_; std::string name_;
size_t index_; size_t index_;
Mode *mode_; Mode *mode_;
LibertySeq liberty_[MinMax::index_count]; std::array<LibertySeq, MinMax::index_count> liberty_;
std::array<Parasitics*, MinMax::index_count> parasitics_; std::array<Parasitics*, MinMax::index_count> parasitics_;
friend class Scenes; friend class Scenes;

View File

@ -409,6 +409,11 @@ public:
void saveEnumPath(Path *path); void saveEnumPath(Path *path);
bool isSrchRoot(Vertex *vertex, bool isSrchRoot(Vertex *vertex,
const Mode *mode) const; const Mode *mode) const;
DelaysWrtClks arrivalsWrtClks(Vertex *vertex,
const Scene *scene);
DelaysWrtClks delaysWrtClks(Vertex *vertex,
const Scene *scene,
const PathDelayFunc &get_path_delay);
protected: protected:
void initVars(); void initVars();

View File

@ -24,14 +24,18 @@
#pragma once #pragma once
#include <functional>
#include <limits> #include <limits>
#include <map> #include <map>
#include <vector> #include <vector>
#include "Delay.hh" #include "Delay.hh"
#include "GraphClass.hh" #include "GraphClass.hh"
#include "LibertyClass.hh"
#include "MinMaxValues.hh" #include "MinMaxValues.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
#include "RiseFallMinMaxDelay.hh"
#include "SdcClass.hh"
#include "VectorMap.hh" #include "VectorMap.hh"
namespace sta { namespace sta {
@ -111,6 +115,9 @@ using SlackSeq = std::vector<Slack>;
using Crpr = Delay; using Crpr = Delay;
using PathSeq = std::vector<Path*>; using PathSeq = std::vector<Path*>;
using ConstPathSeq = std::vector<const Path*>; using ConstPathSeq = std::vector<const Path*>;
// Path::slack/arrival/required function.
using PathDelayFunc = std::function<Delay (const Path *path)>;
using DelaysWrtClks = std::map<const ClockEdge*, RiseFallMinMaxDelay>;
enum class ReportPathFormat { full, enum class ReportPathFormat { full,
full_clock, full_clock,

View File

@ -24,7 +24,7 @@
#pragma once #pragma once
#include <functional> #include <map>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
@ -82,8 +82,6 @@ using CheckError = StringSeq;
using CheckErrorSeq = std::vector<CheckError*>; using CheckErrorSeq = std::vector<CheckError*>;
enum class CmdNamespace { sta, sdc }; enum class CmdNamespace { sta, sdc };
using ParasiticsNameMap = std::map<std::string, Parasitics*, std::less<>>; using ParasiticsNameMap = std::map<std::string, Parasitics*, std::less<>>;
// Path::slack/arrival/required function.
using PathDelayFunc = std::function<Delay (const Path *path)>;
using GraphLoopSeq = std::vector<GraphLoop*>; using GraphLoopSeq = std::vector<GraphLoop*>;
// Initialize sta functions that are not part of the Sta class. // Initialize sta functions that are not part of the Sta class.
@ -1531,16 +1529,10 @@ protected:
int digits, int digits,
bool find_required, bool find_required,
const PathDelayFunc &get_path_delay); const PathDelayFunc &get_path_delay);
void reportDelaysWrtClks(Vertex *vertex, void reportDelaysWrtClks(const ClockEdge *clk_edge,
const ClockEdge *clk_edge,
const Scene *scene,
bool report_variance, bool report_variance,
int digits, int digits,
const PathDelayFunc &get_path_delay); DelaysWrtClks &clk_delays);
RiseFallMinMaxDelay findDelaysWrtClks(Vertex *vertex,
const ClockEdge *clk_edge,
const Scene *scene,
const PathDelayFunc &get_path_delay);
std::string formatDelay(const RiseFall *rf, std::string formatDelay(const RiseFall *rf,
const MinMax *min_max, const MinMax *min_max,
const RiseFallMinMaxDelay &delays, const RiseFallMinMaxDelay &delays,
@ -1616,6 +1608,7 @@ protected:
Mode *mode, Mode *mode,
Parasitics *parasitics); Parasitics *parasitics);
void deleteScenes(); void deleteScenes();
void checkLibrarayPocv();
Scene *cmd_scene_{nullptr}; Scene *cmd_scene_{nullptr};
CmdNamespace cmd_namespace_{CmdNamespace::sdc}; CmdNamespace cmd_namespace_{CmdNamespace::sdc};

View File

@ -724,21 +724,21 @@ LibertyLibrary::makeSceneMap(LibertyLibrary *lib,
// Map a cell linked in the network to the corresponding liberty cell // Map a cell linked in the network to the corresponding liberty cell
// to use for delay calculation at a scene. // to use for delay calculation at a scene.
void void
LibertyLibrary::makeSceneMap(LibertyCell *cell1, LibertyLibrary::makeSceneMap(LibertyCell *link_cell,
LibertyCell *cell2, LibertyCell *scene_cell,
Scene *scene, Scene *scene,
const MinMaxAll *min_max, const MinMaxAll *min_max,
Report *report) Report *report)
{ {
for (const MinMax *mm : min_max->range()) { for (const MinMax *mm : min_max->range()) {
size_t lib_ap_index = scene->libertyIndex(mm); size_t lib_ap_index = scene->libertyIndex(mm);
cell1->setSceneCell(cell2, lib_ap_index); link_cell->setSceneCell(scene_cell, lib_ap_index);
} }
LibertyCellPortBitIterator port_iter1(cell1); LibertyCellPortBitIterator port_iter1(link_cell);
while (port_iter1.hasNext()) { while (port_iter1.hasNext()) {
LibertyPort *port1 = port_iter1.next(); LibertyPort *port1 = port_iter1.next();
LibertyPort *port2 = cell2->findLibertyPort(port1->name()); LibertyPort *port2 = scene_cell->findLibertyPort(port1->name());
if (port2) { if (port2) {
for (const MinMax *mm : min_max->range()) { for (const MinMax *mm : min_max->range()) {
size_t lib_ap_index = scene->libertyIndex(mm); size_t lib_ap_index = scene->libertyIndex(mm);
@ -747,15 +747,15 @@ LibertyLibrary::makeSceneMap(LibertyCell *cell1,
} }
else else
report->warn(1110, "cell {}/{} port {} not found in cell {}/{}.", report->warn(1110, "cell {}/{} port {} not found in cell {}/{}.",
cell1->library()->name(), link_cell->library()->name(),
cell1->name(), link_cell->name(),
port1->name(), port1->name(),
cell2->library()->name(), scene_cell->library()->name(),
cell2->name()); scene_cell->name());
} }
for (TimingArcSet *arc_set1 : cell1->timing_arc_sets_) { for (TimingArcSet *arc_set1 : link_cell->timing_arc_sets_) {
TimingArcSet *arc_set2 = cell2->findTimingArcSet(arc_set1); TimingArcSet *arc_set2 = scene_cell->findTimingArcSet(arc_set1);
if (arc_set2) { if (arc_set2) {
const TimingArcSeq &arcs1 = arc_set1->arcs(); const TimingArcSeq &arcs1 = arc_set1->arcs();
const TimingArcSeq &arcs2 = arc_set2->arcs(); const TimingArcSeq &arcs2 = arc_set2->arcs();
@ -775,13 +775,13 @@ LibertyLibrary::makeSceneMap(LibertyCell *cell1,
} }
else else
report->warn(1111, "cell {}/{} {} -> {} timing group {} not found in cell {}/{}.", report->warn(1111, "cell {}/{} {} -> {} timing group {} not found in cell {}/{}.",
cell1->library()->name(), link_cell->library()->name(),
cell1->name(), link_cell->name(),
arc_set1->from() ? arc_set1->from()->name() : "", arc_set1->from() ? arc_set1->from()->name() : "",
arc_set1->to()->name(), arc_set1->to()->name(),
arc_set1->role()->to_string(), arc_set1->role()->to_string(),
cell2->library()->name(), scene_cell->library()->name(),
cell2->name()); scene_cell->name());
} }
} }

View File

@ -134,16 +134,16 @@ Network::readLibertyAfter(LibertyLibrary *)
LibertyCell * LibertyCell *
Network::findLibertyCell(std::string_view name) const Network::findLibertyCell(std::string_view name) const
{ {
LibertyLibraryIterator *iter = libertyLibraryIterator(); LibertyLibraryIterator *lib_iter = libertyLibraryIterator();
while (iter->hasNext()) { while (lib_iter->hasNext()) {
LibertyLibrary *lib = iter->next(); LibertyLibrary *lib = lib_iter->next();
LibertyCell *cell = lib->findLibertyCell(name); LibertyCell *cell = lib->findLibertyCell(name);
if (cell) { if (cell) {
delete iter; delete lib_iter;
return cell; return cell;
} }
} }
delete iter; delete lib_iter;
return nullptr; return nullptr;
} }

View File

@ -73,11 +73,11 @@ FLOAT {DECIMAL}|{FRACTION}|{EXP}
HCHAR "."|"/"|"|"|":" HCHAR "."|"/"|"|"|":"
PREFIX_BUS_DELIM "["|"{"|"("|"<" PREFIX_BUS_DELIM "["|"{"|"("|"<"
SUFFIX_BUS_DELIM "]"|"}"|")"|">" SUFFIX_BUS_DELIM "]"|"}"|")"|">"
SPECIAL_CHAR "!"|"#"|"$"|"%"|"&"|"`"|"("|")"|"*"|"+"|","|"-"|"."|"/"|":"|";"|"<"|"="|">"|"?"|"@"|"["|"\\"|"]"|"^"|"'"|"{"|"|"|"}"|"~" SPECIAL_CHAR "#"|"$"|"%"|"&"|"`"|"("|")"|"*"|"+"|","|"-"|"."|"/"|":"|";"|"<"|"="|">"|"?"|"@"|"["|"\\"|"]"|"^"|"'"|"{"|"|"|"}"|"~"
ESCAPED_CHAR_SET {SPECIAL_CHAR}|\" ESCAPED_CHAR_SET {SPECIAL_CHAR}|\"
ESCAPED_CHAR \\{ESCAPED_CHAR_SET} ESCAPED_CHAR \\{ESCAPED_CHAR_SET}
IDENT_ACHAR {ESCAPED_CHAR}|{ALPHA}|"_" IDENT_ACHAR {ESCAPED_CHAR}|{ALPHA}|"_"
IDENT_CHAR {IDENT_ACHAR}|{DIGIT} IDENT_CHAR {IDENT_ACHAR}|{DIGIT}|"!"
ID {IDENT_ACHAR}{IDENT_CHAR}* ID {IDENT_ACHAR}{IDENT_CHAR}*
BUS_SUB {DIGIT}|{ALPHA}|"_" BUS_SUB {DIGIT}|{ALPHA}|"_"
BIT_IDENT {ID}({PREFIX_BUS_DELIM}{BUS_SUB}+{SUFFIX_BUS_DELIM})+ BIT_IDENT {ID}({PREFIX_BUS_DELIM}{BUS_SUB}+{SUFFIX_BUS_DELIM})+

View File

@ -240,42 +240,27 @@ Clock::uncertainty(const SetupHold *setup_hold,
float &uncertainty, float &uncertainty,
bool &exists) const bool &exists) const
{ {
if (uncertainties_) uncertainties_.value(setup_hold, uncertainty, exists);
uncertainties_->value(setup_hold, uncertainty, exists);
else {
uncertainty = 0.0F;
exists = false;
}
} }
void void
Clock::setUncertainty(const SetupHoldAll *setup_hold, Clock::setUncertainty(const SetupHoldAll *setup_hold,
float uncertainty) float uncertainty)
{ {
if (uncertainties_ == nullptr) uncertainties_.setValue(setup_hold, uncertainty);
uncertainties_ = new ClockUncertainties;
uncertainties_->setValue(setup_hold, uncertainty);
} }
void void
Clock::setUncertainty(const SetupHold *setup_hold, Clock::setUncertainty(const SetupHold *setup_hold,
float uncertainty) float uncertainty)
{ {
if (uncertainties_ == nullptr) uncertainties_.setValue(setup_hold, uncertainty);
uncertainties_ = new ClockUncertainties;
uncertainties_->setValue(setup_hold, uncertainty);
} }
void void
Clock::removeUncertainty(const SetupHoldAll *setup_hold) Clock::removeUncertainty(const SetupHoldAll *setup_hold)
{ {
if (uncertainties_) { uncertainties_.removeValue(setup_hold);
uncertainties_->removeValue(setup_hold);
if (uncertainties_->empty()) {
delete uncertainties_;
uncertainties_ = nullptr;
}
}
} }
void void

View File

@ -231,7 +231,7 @@ MakeTimingModel::checkClock(Clock *clk)
{ {
for (const Pin *pin : clk->leafPins()) { for (const Pin *pin : clk->leafPins()) {
if (!network_->isTopLevelPort(pin)) if (!network_->isTopLevelPort(pin))
report_->warn(1355, "clock {} pin {} is inside model block.", clk->name(), report_->warn(1380, "clock {} pin {} is inside model block.", clk->name(),
network_->pathName(pin)); network_->pathName(pin));
} }
} }

View File

@ -379,7 +379,7 @@ PathEnd::checkTgtClkUncertainty(const Path *tgt_clk_path,
if (tgt_clk_path && tgt_clk_path->isClock(sta)) if (tgt_clk_path && tgt_clk_path->isClock(sta))
uncertainties = tgt_clk_path->clkInfo(sta)->uncertainties(); uncertainties = tgt_clk_path->clkInfo(sta)->uncertainties();
else if (tgt_clk_edge) else if (tgt_clk_edge)
uncertainties = tgt_clk_edge->clock()->uncertainties(); uncertainties = &tgt_clk_edge->clock()->uncertainties();
float uncertainty = 0.0; float uncertainty = 0.0;
if (uncertainties) { if (uncertainties) {
bool exists; bool exists;

View File

@ -1265,70 +1265,70 @@ Properties::capacitancePropertyValue(float cap)
void void
Properties::defineProperty(std::string_view property, Properties::defineProperty(std::string_view property,
PropertyRegistry<const Library *>::PropertyHandler &handler) const PropertyRegistry<const Library *>::PropertyHandler &handler)
{ {
registry_library_.defineProperty(property, handler); registry_library_.defineProperty(property, handler);
} }
void void
Properties::defineProperty(std::string_view property, Properties::defineProperty(std::string_view property,
PropertyRegistry<const LibertyLibrary *>::PropertyHandler &handler) const PropertyRegistry<const LibertyLibrary *>::PropertyHandler &handler)
{ {
registry_liberty_library_.defineProperty(property, handler); registry_liberty_library_.defineProperty(property, handler);
} }
void void
Properties::defineProperty(std::string_view property, Properties::defineProperty(std::string_view property,
PropertyRegistry<const Cell *>::PropertyHandler &handler) const PropertyRegistry<const Cell *>::PropertyHandler &handler)
{ {
registry_cell_.defineProperty(property, handler); registry_cell_.defineProperty(property, handler);
} }
void void
Properties::defineProperty(std::string_view property, Properties::defineProperty(std::string_view property,
PropertyRegistry<const LibertyCell *>::PropertyHandler &handler) const PropertyRegistry<const LibertyCell *>::PropertyHandler &handler)
{ {
registry_liberty_cell_.defineProperty(property, handler); registry_liberty_cell_.defineProperty(property, handler);
} }
void void
Properties::defineProperty(std::string_view property, Properties::defineProperty(std::string_view property,
PropertyRegistry<const Port *>::PropertyHandler &handler) const PropertyRegistry<const Port *>::PropertyHandler &handler)
{ {
registry_port_.defineProperty(property, handler); registry_port_.defineProperty(property, handler);
} }
void void
Properties::defineProperty(std::string_view property, Properties::defineProperty(std::string_view property,
PropertyRegistry<const LibertyPort *>::PropertyHandler &handler) const PropertyRegistry<const LibertyPort *>::PropertyHandler &handler)
{ {
registry_liberty_port_.defineProperty(property, handler); registry_liberty_port_.defineProperty(property, handler);
} }
void void
Properties::defineProperty(std::string_view property, Properties::defineProperty(std::string_view property,
PropertyRegistry<const Instance *>::PropertyHandler &handler) const PropertyRegistry<const Instance *>::PropertyHandler &handler)
{ {
registry_instance_.defineProperty(property, handler); registry_instance_.defineProperty(property, handler);
} }
void void
Properties::defineProperty(std::string_view property, Properties::defineProperty(std::string_view property,
PropertyRegistry<const Pin *>::PropertyHandler &handler) const PropertyRegistry<const Pin *>::PropertyHandler &handler)
{ {
registry_pin_.defineProperty(property, handler); registry_pin_.defineProperty(property, handler);
} }
void void
Properties::defineProperty(std::string_view property, Properties::defineProperty(std::string_view property,
PropertyRegistry<const Net *>::PropertyHandler &handler) const PropertyRegistry<const Net *>::PropertyHandler &handler)
{ {
registry_net_.defineProperty(property, handler); registry_net_.defineProperty(property, handler);
} }
void void
Properties::defineProperty(std::string_view property, Properties::defineProperty(std::string_view property,
PropertyRegistry<const Clock *>::PropertyHandler &handler) const PropertyRegistry<const Clock *>::PropertyHandler &handler)
{ {
registry_clock_.defineProperty(property, handler); registry_clock_.defineProperty(property, handler);
} }
@ -1355,7 +1355,7 @@ void
PropertyRegistry<TYPE>::defineProperty(std::string_view property, PropertyRegistry<TYPE>::defineProperty(std::string_view property,
PropertyHandler handler) PropertyHandler handler)
{ {
registry_[std::string(property)] = std::move(std::move(std::move(std::move(std::move(std::move(std::move(std::move(std::move(std::move(handler)))))))))); registry_[std::string(property)] = std::move(handler);
} }
} // namespace sta } // namespace sta

View File

@ -57,6 +57,7 @@
#include "PortDelay.hh" #include "PortDelay.hh"
#include "PortDirection.hh" #include "PortDirection.hh"
#include "Report.hh" #include "Report.hh"
#include "RiseFallMinMaxDelay.hh"
#include "Scene.hh" #include "Scene.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "SdcClass.hh" #include "SdcClass.hh"
@ -1546,7 +1547,7 @@ Search::seedClkArrival(const Pin *pin,
const ClockUncertainties *uncertainties = sdc->clockUncertainties(pin); const ClockUncertainties *uncertainties = sdc->clockUncertainties(pin);
if (uncertainties == nullptr) if (uncertainties == nullptr)
uncertainties = clk->uncertainties(); uncertainties = &clk->uncertainties();
// Propagate liberty "pulse_clock" transition to transitive fanout. // Propagate liberty "pulse_clock" transition to transitive fanout.
LibertyPort *port = network_->libertyPort(pin); LibertyPort *port = network_->libertyPort(pin);
const RiseFall *pulse_clk_sense = (port ? port->pulseClkSense() : nullptr); const RiseFall *pulse_clk_sense = (port ? port->pulseClkSense() : nullptr);
@ -1913,13 +1914,13 @@ Search::inputDelayTag(const Pin *pin,
const Pin *clk_pin = nullptr; const Pin *clk_pin = nullptr;
const RiseFall *clk_rf = nullptr; const RiseFall *clk_rf = nullptr;
bool is_propagated = false; bool is_propagated = false;
ClockUncertainties *clk_uncertainties = nullptr; const ClockUncertainties *clk_uncertainties = nullptr;
if (clk_edge) { if (clk_edge) {
clk = clk_edge->clock(); clk = clk_edge->clock();
clk_rf = clk_edge->transition(); clk_rf = clk_edge->transition();
clk_pin = clk->defaultPin(); clk_pin = clk->defaultPin();
is_propagated = clk->isPropagated(); is_propagated = clk->isPropagated();
clk_uncertainties = clk->uncertainties(); clk_uncertainties = &clk->uncertainties();
} }
Sdc *sdc = scene->sdc(); Sdc *sdc = scene->sdc();
@ -3997,4 +3998,37 @@ Search::wnsSlack(Vertex *vertex,
return slacks[path_ap_index]; return slacks[path_ap_index];
} }
////////////////////////////////////////////////////////////////
DelaysWrtClks
Search::arrivalsWrtClks(Vertex *vertex,
const Scene *scene)
{
return delaysWrtClks(vertex, scene,
[] (const Path *path) {
return path->arrival();
});
}
DelaysWrtClks
Search::delaysWrtClks(Vertex *vertex,
const Scene *scene,
const PathDelayFunc &get_path_delay)
{
DelaysWrtClks delays_wrt_clks;
VertexPathIterator path_iter(vertex, scene, nullptr, nullptr, this);
while (path_iter.hasNext()) {
Path *path = path_iter.next();
Delay delay = get_path_delay(path);
if (!delayInf(delay, this)) {
const RiseFall *rf = path->transition(this);
const MinMax *min_max = path->minMax(this);
const ClockEdge *clk_edge = path->clkEdge(this);
RiseFallMinMaxDelay &delays = delays_wrt_clks[clk_edge];
delays.mergeValue(rf, min_max, delay, this);
}
}
return delays_wrt_clks;
}
} // namespace sta } // namespace sta

View File

@ -237,7 +237,7 @@ endpoint_slack(const Pin *pin,
sta->ensureLibLinked(); sta->ensureLibLinked();
if (!path_group_name.empty() if (!path_group_name.empty()
&& !sta->isPathGroupName(path_group_name, sta->cmdSdc())) { && !sta->isPathGroupName(path_group_name, sta->cmdSdc())) {
sta->report()->error(1577, "{} is not a known path group name.", sta->report()->error(1590, "{} is not a known path group name.",
path_group_name); path_group_name);
return INF; return INF;
} }
@ -438,7 +438,7 @@ set_report_path_field_properties(const char *field_name,
if (field) if (field)
field->setProperties(title, width, left_justify); field->setProperties(title, width, left_justify);
else else
sta->report()->warn(1575, "unknown report path field {}", field_name); sta->report()->warn(1591, "unknown report path field {}", field_name);
} }
void void
@ -963,7 +963,7 @@ set_crpr_mode(std::string mode)
else if (stringEqual(mode, "same_transition")) else if (stringEqual(mode, "same_transition"))
sta->setCrprMode(CrprMode::same_transition); sta->setCrprMode(CrprMode::same_transition);
else else
sta->report()->error(1573, "unknown common clk pessimism mode."); sta->report()->error(1592, "unknown common clk pessimism mode.");
} }
const std::string & const std::string &

View File

@ -26,6 +26,7 @@
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
#include <map>
#include <string> #include <string>
#include "ArcDelayCalc.hh" #include "ArcDelayCalc.hh"
@ -2281,9 +2282,11 @@ Sta::setPocvMode(PocvMode mode)
delay_ops_ = new DelayOpsScalar(); delay_ops_ = new DelayOpsScalar();
break; break;
case PocvMode::normal: case PocvMode::normal:
checkLibrarayPocv();
delay_ops_ = new DelayOpsNormal(); delay_ops_ = new DelayOpsNormal();
break; break;
case PocvMode::skew_normal: case PocvMode::skew_normal:
checkLibrarayPocv();
delay_ops_ = new DelayOpsSkewNormal(); delay_ops_ = new DelayOpsSkewNormal();
break; break;
} }
@ -2292,6 +2295,33 @@ Sta::setPocvMode(PocvMode mode)
} }
} }
void
Sta::checkLibrarayPocv()
{
LibertyLibraryIterator *lib_iter = network_->libertyLibraryIterator();
while (lib_iter->hasNext()) {
LibertyLibrary *lib = lib_iter->next();
LibertyCellIterator cell_iter(lib);
while (cell_iter.hasNext()) {
LibertyCell *cell = cell_iter.next();
for (const TimingArcSet *arc_set : cell->timingArcSets()) {
for (const TimingArc *arc : arc_set->arcs()) {
GateTableModel *gate_model = arc->gateTableModel();
if (gate_model) {
const TableModels *models = gate_model->delayModels();
if (models->sigma(EarlyLate::early()) != nullptr) {
delete lib_iter;
return;
}
}
}
}
}
}
delete lib_iter;
report_->warn(1578, "No liberty POCV/LVF models found.");
}
float float
Sta::pocvQuantile() Sta::pocvQuantile()
{ {
@ -3353,29 +3383,25 @@ Sta::reportDelaysWrtClks(Vertex *vertex,
else else
search_->findArrivals(vertex->level()); search_->findArrivals(vertex->level());
const Sdc *sdc = scene->sdc(); const Sdc *sdc = scene->sdc();
reportDelaysWrtClks(vertex, nullptr, scene, report_variance, digits, get_path_delay); DelaysWrtClks clk_delays = search_->delaysWrtClks(vertex, scene, get_path_delay);
reportDelaysWrtClks(nullptr, report_variance, digits, clk_delays);
const ClockEdge *default_clk_edge = sdc->defaultArrivalClock()->edge(RiseFall::rise()); const ClockEdge *default_clk_edge = sdc->defaultArrivalClock()->edge(RiseFall::rise());
reportDelaysWrtClks(vertex, default_clk_edge, scene, report_variance, reportDelaysWrtClks(default_clk_edge, report_variance, digits, clk_delays);
digits, get_path_delay);
for (const Clock *clk : sdc->sortedClocks()) { for (const Clock *clk : sdc->sortedClocks()) {
for (const RiseFall *rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
const ClockEdge *clk_edge = clk->edge(rf); const ClockEdge *clk_edge = clk->edge(rf);
reportDelaysWrtClks(vertex, clk_edge, scene, report_variance, digits, reportDelaysWrtClks(clk_edge, report_variance, digits, clk_delays);
get_path_delay);
} }
} }
} }
void void
Sta::reportDelaysWrtClks(Vertex *vertex, Sta::reportDelaysWrtClks(const ClockEdge *clk_edge,
const ClockEdge *clk_edge,
const Scene *scene,
bool report_variance, bool report_variance,
int digits, int digits,
const PathDelayFunc &get_path_delay) DelaysWrtClks &clk_delays)
{ {
RiseFallMinMaxDelay delays = const RiseFallMinMaxDelay &delays = clk_delays[clk_edge];
findDelaysWrtClks(vertex, clk_edge, scene, get_path_delay);
if (!delays.empty()) { if (!delays.empty()) {
std::string clk_name; std::string clk_name;
if (clk_edge) if (clk_edge)
@ -3392,27 +3418,6 @@ Sta::reportDelaysWrtClks(Vertex *vertex,
} }
} }
RiseFallMinMaxDelay
Sta::findDelaysWrtClks(Vertex *vertex,
const ClockEdge *clk_edge,
const Scene *scene,
const PathDelayFunc &get_path_delay)
{
RiseFallMinMaxDelay delays;
VertexPathIterator path_iter(vertex, scene, nullptr, nullptr, this);
while (path_iter.hasNext()) {
Path *path = path_iter.next();
Delay delay = get_path_delay(path);
const RiseFall *rf = path->transition(this);
const MinMax *min_max = path->minMax(this);
const ClockEdge *path_clk_edge = path->clkEdge(this);
if (path_clk_edge == clk_edge
&& !delayInf(delay, this))
delays.mergeValue(rf, min_max, delay, this);
}
return delays;
}
std::string std::string
Sta::formatDelay(const RiseFall *rf, Sta::formatDelay(const RiseFall *rf,
const MinMax *min_max, const MinMax *min_max,

View File

@ -311,7 +311,7 @@ TagGroupBldr::copyPaths(TagGroup *tag_group,
if (exists2) if (exists2)
paths[path_index2] = paths_[path_index1]; paths[path_index2] = paths_[path_index1];
else else
sta_->report()->critical(1351, "tag group missing tag"); sta_->report()->critical(1360, "tag group missing tag");
} }
} }

View File

@ -193,7 +193,7 @@ WritePathSpice::WritePathSpice(const Path *path,
void void
WritePathSpice::writeSpice() WritePathSpice::writeSpice()
{ {
spice_stream_.open(std::string(spice_filename_)); spice_stream_.open(spice_filename_);
if (spice_stream_.is_open()) { if (spice_stream_.is_open()) {
path_expanded_.expand(path_, true); path_expanded_.expand(path_, true);
// Find subckt port names as a side-effect of writeSubckts. // Find subckt port names as a side-effect of writeSubckts.

View File

@ -165,12 +165,12 @@ protected:
std::string replaceFileExt(std::string_view filename, std::string replaceFileExt(std::string_view filename,
std::string_view ext); std::string_view ext);
const std::string_view spice_filename_; const std::string spice_filename_;
const std::string_view subckt_filename_; const std::string subckt_filename_;
const std::string_view lib_subckt_filename_; const std::string lib_subckt_filename_;
const std::string_view model_filename_; const std::string model_filename_;
const std::string_view power_name_; const std::string power_name_;
const std::string_view gnd_name_; const std::string gnd_name_;
CircuitSim ckt_sim_; CircuitSim ckt_sim_;
const Scene *scene_; const Scene *scene_;
const MinMax *min_max_; const MinMax *min_max_;

View File

@ -26,7 +26,9 @@
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <cerrno>
#include <charconv> #include <charconv>
#include <cstdlib>
#include <system_error> #include <system_error>
#include <version> #include <version>

View File

@ -1490,12 +1490,12 @@ VerilogReader::linkNetwork(std::string_view top_cell_name,
return top_instance; return top_instance;
} }
else { else {
report_->error(1398, "{} is not a verilog module.", top_cell_name); report_->error(1390, "{} is not a verilog module.", top_cell_name);
return nullptr; return nullptr;
} }
} }
else { else {
report_->error(1399, "{} is not a verilog module.", top_cell_name); report_->error(1391, "{} is not a verilog module.", top_cell_name);
return nullptr; return nullptr;
} }
} }