Merge remote-tracking branch 'opensta/master' into secure-sta-test-by-opus

# Conflicts:
#	liberty/TableModel.cc

Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
This commit is contained in:
Jaehyun Kim 2026-04-02 12:21:14 +09:00
commit ea22794652
8 changed files with 97 additions and 94 deletions

View File

@ -44,7 +44,6 @@
#include "TimingArc.hh" #include "TimingArc.hh"
#include "TableModel.hh" #include "TableModel.hh"
#include "Liberty.hh" #include "Liberty.hh"
#include "Network.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
#include "ArcDelayCalc.hh" #include "ArcDelayCalc.hh"
@ -78,11 +77,11 @@ exp2(double x);
class DmpError : public Exception class DmpError : public Exception
{ {
public: public:
DmpError(const char *what); DmpError(std::string_view what);
virtual const char *what() const noexcept { return what_; } virtual const char *what() const noexcept { return what_.c_str(); }
private: private:
const char *what_; std::string what_;
}; };
static double static double
@ -139,9 +138,9 @@ public:
double c2, double c2,
double rpi, double rpi,
double c1); double c1);
virtual void gateDelaySlew( // Return values. virtual void gateDelaySlew(// Return values.
double &delay, double &delay,
double &slew) = 0; double &slew) = 0;
virtual void loadDelaySlew(const Pin *load_pin, virtual void loadDelaySlew(const Pin *load_pin,
double elmore, double elmore,
// Return values. // Return values.
@ -685,9 +684,9 @@ public:
double c2, double c2,
double rpi, double rpi,
double c1) override; double c1) override;
void gateDelaySlew( // Return values. void gateDelaySlew(// Return values.
double &delay, double &delay,
double &slew) override; double &slew) override;
void loadDelaySlew(const Pin *, void loadDelaySlew(const Pin *,
double elmore, double elmore,
// Return values. // Return values.
@ -726,15 +725,15 @@ DmpCap::init(const LibertyLibrary *drvr_library,
double c1) double c1)
{ {
debugPrint(debug_, "dmp_ceff", 3, "Using DMP cap"); debugPrint(debug_, "dmp_ceff", 3, "Using DMP cap");
DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew, c2, rpi, DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew,
c1); c2, rpi, c1);
ceff_ = c1 + c2; ceff_ = c1 + c2;
} }
void void
DmpCap::gateDelaySlew( // Return values. DmpCap::gateDelaySlew(// Return values.
double &delay, double &delay,
double &slew) double &slew)
{ {
debugPrint(debug_, "dmp_ceff", 3, " ceff = {}", debugPrint(debug_, "dmp_ceff", 3, " ceff = {}",
units_->capacitanceUnit()->asString(ceff_)); units_->capacitanceUnit()->asString(ceff_));
@ -801,9 +800,9 @@ public:
double c2, double c2,
double rpi, double rpi,
double c1) override; double c1) override;
void gateDelaySlew( // Return values. void gateDelaySlew(// Return values.
double &delay, double &delay,
double &slew) override; double &slew) override;
void evalDmpEqns() override; void evalDmpEqns() override;
double voCrossingUpperBound() override; double voCrossingUpperBound() override;
@ -868,8 +867,8 @@ DmpPi::init(const LibertyLibrary *drvr_library,
double c1) double c1)
{ {
debugPrint(debug_, "dmp_ceff", 3, "Using DMP Pi"); debugPrint(debug_, "dmp_ceff", 3, "Using DMP Pi");
DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew, c2, rpi, DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew,
c1); c2, rpi, c1);
// Find poles/zeros. // Find poles/zeros.
z1_ = 1.0 / (rpi_ * c1_); z1_ = 1.0 / (rpi_ * c1_);
@ -893,9 +892,9 @@ DmpPi::init(const LibertyLibrary *drvr_library,
} }
void void
DmpPi::gateDelaySlew( // Return values. DmpPi::gateDelaySlew(// Return values.
double &delay, double &delay,
double &slew) double &slew)
{ {
driver_valid_ = false; driver_valid_ = false;
try { try {
@ -1127,9 +1126,9 @@ public:
double c2, double c2,
double rpi, double rpi,
double c1) override; double c1) override;
void gateDelaySlew( // Return values. void gateDelaySlew(// Return values.
double &delay, double &delay,
double &slew) override; double &slew) override;
private: private:
void V0(double t, void V0(double t,
@ -1176,8 +1175,8 @@ DmpZeroC2::init(const LibertyLibrary *drvr_library,
double c1) double c1)
{ {
debugPrint(debug_, "dmp_ceff", 3, "Using DMP C2=0"); debugPrint(debug_, "dmp_ceff", 3, "Using DMP C2=0");
DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew, c2, rpi, DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew,
c1); c2, rpi, c1);
ceff_ = c1; ceff_ = c1;
z1_ = 1.0 / (rpi_ * c1_); z1_ = 1.0 / (rpi_ * c1_);
@ -1275,8 +1274,10 @@ newtonRaphson(const int max_iter,
all_under_x_tol = false; all_under_x_tol = false;
x[i] += p[i]; x[i] += p[i];
} }
if (all_under_x_tol) if (all_under_x_tol) {
eval();
return; return;
}
} }
throw DmpError("Newton-Raphson max iterations exceeded"); throw DmpError("Newton-Raphson max iterations exceeded");
} }
@ -1557,8 +1558,8 @@ DmpCeffDelayCalc::setCeffAlgorithm(const LibertyLibrary *drvr_library,
} }
else else
dmp_alg_ = dmp_cap_; dmp_alg_ = dmp_cap_;
dmp_alg_->init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew, c2, rpi, dmp_alg_->init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew,
c1); c2, rpi, c1);
debugPrint(debug_, "dmp_ceff", 3, debugPrint(debug_, "dmp_ceff", 3,
" DMP in_slew = {} c2 = {} rpi = {} c1 = {} Rd = {} ({} alg)", " DMP in_slew = {} c2 = {} rpi = {} c1 = {} Rd = {} ({} alg)",
units_->timeUnit()->asString(in_slew), units_->timeUnit()->asString(in_slew),
@ -1667,10 +1668,10 @@ DmpCeffDelayCalc::copyState(const StaState *sta)
dmp_zero_c2_->copyState(sta); dmp_zero_c2_->copyState(sta);
} }
DmpError::DmpError(const char *what) : DmpError::DmpError(std::string_view what) :
what_(what) what_(what)
{ {
// printf("DmpError %s\n", what); //sta::print(stdout, "DmpError {}\n", what);
} }
// This saves about 2.5% in overall run time on designs with SPEF. // This saves about 2.5% in overall run time on designs with SPEF.

View File

@ -426,7 +426,8 @@ GraphDelayCalc::seedDrvrSlew(Vertex *drvr_vertex,
if (from_port == nullptr) if (from_port == nullptr)
from_port = driveCellDefaultFromPort(drvr_cell, to_port); from_port = driveCellDefaultFromPort(drvr_cell, to_port);
findInputDriverDelay(drvr_cell, drvr_pin, drvr_vertex, rf, findInputDriverDelay(drvr_cell, drvr_pin, drvr_vertex, rf,
from_port, from_slews, to_port, scene, min_max); from_port, from_slews, to_port, scene, min_max,
arc_delay_calc);
} }
else else
seedNoDrvrCellSlew(drvr_vertex, drvr_pin, rf, drive, scene, min_max, seedNoDrvrCellSlew(drvr_vertex, drvr_pin, rf, drive, scene, min_max,
@ -601,7 +602,8 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell,
float *from_slews, float *from_slews,
const LibertyPort *to_port, const LibertyPort *to_port,
const Scene *scene, const Scene *scene,
const MinMax *min_max) const MinMax *min_max,
ArcDelayCalc *arc_delay_calc)
{ {
debugPrint(debug_, "delay_calc", 2, " driver cell {} {}", debugPrint(debug_, "delay_calc", 2, " driver cell {} {}",
drvr_cell->name(), drvr_cell->name(),
@ -610,11 +612,11 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell,
for (TimingArc *arc : arc_set->arcs()) { for (TimingArc *arc : arc_set->arcs()) {
if (arc->toEdge()->asRiseFall() == rf) { if (arc->toEdge()->asRiseFall() == rf) {
float from_slew = from_slews[arc->fromEdge()->index()]; float from_slew = from_slews[arc->fromEdge()->index()];
findInputArcDelay(drvr_pin, drvr_vertex, arc, from_slew, scene, min_max); findInputArcDelay(drvr_pin, drvr_vertex, arc, from_slew, scene, min_max,
arc_delay_calc);
} }
} }
} }
arc_delay_calc_->finishDrvrPin();
} }
// Driving cell delay is the load dependent delay, which is the gate // Driving cell delay is the load dependent delay, which is the gate
@ -626,7 +628,8 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin,
const TimingArc *arc, const TimingArc *arc,
float from_slew, float from_slew,
const Scene *scene, const Scene *scene,
const MinMax *min_max) const MinMax *min_max,
ArcDelayCalc *arc_delay_calc)
{ {
debugPrint(debug_, "delay_calc", 3, " {} {} -> {} {} ({})", debugPrint(debug_, "delay_calc", 3, " {} {} -> {} {} ({})",
arc->from()->name(), arc->from()->name(),
@ -640,20 +643,20 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin,
const Parasitic *parasitic; const Parasitic *parasitic;
float load_cap; float load_cap;
parasiticLoad(drvr_pin, drvr_rf, scene, min_max, nullptr, arc_delay_calc_, parasiticLoad(drvr_pin, drvr_rf, scene, min_max, nullptr, arc_delay_calc,
load_cap, parasitic); load_cap, parasitic);
LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex); LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
ArcDcalcResult intrinsic_result = ArcDcalcResult intrinsic_result =
arc_delay_calc_->gateDelay(drvr_pin, arc, Slew(from_slew), 0.0, nullptr, arc_delay_calc->gateDelay(drvr_pin, arc, Slew(from_slew), 0.0, nullptr,
load_pin_index_map, scene, min_max); load_pin_index_map, scene, min_max);
const ArcDelay &intrinsic_delay = intrinsic_result.gateDelay(); const ArcDelay &intrinsic_delay = intrinsic_result.gateDelay();
ArcDcalcResult gate_result = arc_delay_calc_->gateDelay(drvr_pin, arc, ArcDcalcResult gate_result = arc_delay_calc->gateDelay(drvr_pin, arc,
Slew(from_slew), load_cap, Slew(from_slew), load_cap,
parasitic, parasitic,
load_pin_index_map, load_pin_index_map,
scene, min_max); scene, min_max);
const ArcDelay &gate_delay = gate_result.gateDelay(); const ArcDelay &gate_delay = gate_result.gateDelay();
const Slew &gate_slew = gate_result.drvrSlew(); const Slew &gate_slew = gate_result.drvrSlew();
@ -666,7 +669,7 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin,
graph_->setSlew(drvr_vertex, drvr_rf, ap_index, gate_slew); graph_->setSlew(drvr_vertex, drvr_rf, ap_index, gate_slew);
annotateLoadDelays(drvr_vertex, drvr_rf, gate_result, load_pin_index_map, annotateLoadDelays(drvr_vertex, drvr_rf, gate_result, load_pin_index_map,
load_delay, false, scene, min_max); load_delay, false, scene, min_max);
arc_delay_calc_->finishDrvrPin(); arc_delay_calc->finishDrvrPin();
} }
} }
@ -1598,41 +1601,41 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge,
for (Scene *scene : scenes_) { for (Scene *scene : scenes_) {
for (const MinMax *min_max : MinMax::range()) { for (const MinMax *min_max : MinMax::range()) {
DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max); DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max);
if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) { if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) {
const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf, const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf,
scene, min_max); scene, min_max);
const Slew to_slew = graph_->slew(to_vertex, to_rf, ap_index); const Slew to_slew = graph_->slew(to_vertex, to_rf, ap_index);
debugPrint(debug_, "delay_calc", 3, debugPrint(debug_, "delay_calc", 3,
" {} {} -> {} {} ({}) scene:{}/{}", " {} {} -> {} {} ({}) scene:{}/{}",
arc_set->from()->name(), arc_set->from()->name(),
arc->fromEdge()->to_string(), arc->fromEdge()->to_string(),
arc_set->to()->name(), arc_set->to()->name(),
arc->toEdge()->to_string(), arc->toEdge()->to_string(),
arc_set->role()->to_string(), arc_set->role()->to_string(),
scene->name(), scene->name(),
min_max->to_string()); min_max->to_string());
debugPrint(debug_, "delay_calc", 3, debugPrint(debug_, "delay_calc", 3,
" from_slew = {} to_slew = {}", " from_slew = {} to_slew = {}",
delayAsString(from_slew, this), delayAsString(from_slew, this),
delayAsString(to_slew, this)); delayAsString(to_slew, this));
float related_out_cap = 0.0; float related_out_cap = 0.0;
if (related_out_pin) if (related_out_pin)
related_out_cap = loadCap(related_out_pin, to_rf,scene,min_max, related_out_cap = loadCap(related_out_pin, to_rf,scene,min_max,
arc_delay_calc); arc_delay_calc);
ArcDelay check_delay = arc_delay_calc->checkDelay(to_pin, arc, from_slew, ArcDelay check_delay = arc_delay_calc->checkDelay(to_pin, arc, from_slew,
to_slew, related_out_cap, to_slew, related_out_cap,
scene, min_max); scene, min_max);
debugPrint(debug_, "delay_calc", 3, debugPrint(debug_, "delay_calc", 3,
" check_delay = {}", " check_delay = {}",
delayAsString(check_delay, this)); delayAsString(check_delay, this));
graph_->setArcDelay(edge, arc, ap_index, check_delay); graph_->setArcDelay(edge, arc, ap_index, check_delay);
delay_changed = true; delay_changed = true;
arc_delay_calc_->finishDrvrPin(); arc_delay_calc_->finishDrvrPin();
} }
}
} }
} }
} }
}
if (delay_changed && observer_) if (delay_changed && observer_)
observer_->checkDelayChangedTo(to_vertex); observer_->checkDelayChangedTo(to_vertex);

View File

@ -174,7 +174,8 @@ protected:
float *from_slews, float *from_slews,
const LibertyPort *to_port, const LibertyPort *to_port,
const Scene *scene, const Scene *scene,
const MinMax *min_max); const MinMax *min_max,
ArcDelayCalc *arc_delay_calc);
LibertyPort *driveCellDefaultFromPort(const LibertyCell *cell, LibertyPort *driveCellDefaultFromPort(const LibertyCell *cell,
const LibertyPort *to_port); const LibertyPort *to_port);
int findPortIndex(const LibertyCell *cell, int findPortIndex(const LibertyCell *cell,
@ -184,7 +185,8 @@ protected:
const TimingArc *arc, const TimingArc *arc,
float from_slew, float from_slew,
const Scene *scene, const Scene *scene,
const MinMax *min_max); const MinMax *min_max,
ArcDelayCalc *arc_delay_calc);
void findDriverDelays(Vertex *drvr_vertex, void findDriverDelays(Vertex *drvr_vertex,
ArcDelayCalc *arc_delay_calc, ArcDelayCalc *arc_delay_calc,
LoadPinIndexMap &load_pin_index_map); LoadPinIndexMap &load_pin_index_map);

View File

@ -108,19 +108,18 @@ GateTableModel::gateDelay(const Pvt *pvt,
float &gate_delay, float &gate_delay,
float &drvr_slew) const float &drvr_slew) const
{ {
if (delay_models_) if (delay_models_ && delay_models_->model())
gate_delay = findValue(pvt, delay_models_->model(), in_slew, load_cap, 0.0); gate_delay = findValue(pvt, delay_models_->model(), in_slew, load_cap, 0.0);
else else
gate_delay = 0.0; gate_delay = 0.0;
if (slew_models_) if (slew_models_ && slew_models_->model()) {
drvr_slew = findValue(pvt, slew_models_->model(), in_slew, load_cap, 0.0); drvr_slew = findValue(pvt, slew_models_->model(), in_slew, load_cap, 0.0);
// Clip negative slews to zero.
if (drvr_slew < 0.0)
drvr_slew = 0.0;
}
else else
drvr_slew = 0.0; drvr_slew = 0.0;
// TODO: Check for a better solution than clip negative delays and slews to zero.
//if (gate_delay < 0.0)
// gate_delay = 0.0;
if (drvr_slew < 0.0)
drvr_slew = 0.0;
} }
void void

View File

@ -195,7 +195,7 @@ BfsIterator::visitParallel(Level to_level,
for (size_t k = 0; k < thread_count; k++) { for (size_t k = 0; k < thread_count; k++) {
// Last thread gets the left overs. // Last thread gets the left overs.
size_t to = (k == thread_count - 1) ? vertex_count : from + chunk_size; size_t to = (k == thread_count - 1) ? vertex_count : from + chunk_size;
dispatch_queue_->dispatch([=, this](int) { dispatch_queue_->dispatch([=, this](size_t) {
for (size_t i = from; i < to; i++) { for (size_t i = from; i < to; i++) {
Vertex *vertex = level_vertices[i]; Vertex *vertex = level_vertices[i];
if (vertex) { if (vertex) {

View File

@ -196,7 +196,7 @@ ClkSkews::findClkSkew(ConstClockSeq &clks,
std::vector<ClkSkewMap> partial_skews(thread_count_); std::vector<ClkSkewMap> partial_skews(thread_count_);
for (Vertex *src_vertex : graph_->regClkVertices()) { for (Vertex *src_vertex : graph_->regClkVertices()) {
if (hasClkPaths(src_vertex)) { if (hasClkPaths(src_vertex)) {
dispatch_queue_->dispatch([this, src_vertex, &partial_skews](int i) { dispatch_queue_->dispatch([this, src_vertex, &partial_skews](size_t i) {
findClkSkewFrom(src_vertex, partial_skews[i]); findClkSkewFrom(src_vertex, partial_skews[i]);
}); });
} }

View File

@ -1025,7 +1025,7 @@ PathGroups::makeGroupPathEnds(VertexSet &endpoints,
MakeEndpointPathEnds(visitor, Scene::sceneSet(scenes), MakeEndpointPathEnds(visitor, Scene::sceneSet(scenes),
min_max, this)); min_max, this));
for (const auto endpoint : endpoints) { for (const auto endpoint : endpoints) {
dispatch_queue_->dispatch( [endpoint, &visitors](int i) dispatch_queue_->dispatch( [endpoint, &visitors](size_t i)
{ visitors[i].visit(endpoint); } ); { visitors[i].visit(endpoint); } );
} }
dispatch_queue_->finishTasks(); dispatch_queue_->finishTasks();

View File

@ -1102,9 +1102,7 @@ Search::findArrivalsSeed()
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
ArrivalVisitor::ArrivalVisitor(const StaState *sta) : ArrivalVisitor::ArrivalVisitor(const StaState *sta) :
PathVisitor(nullptr, PathVisitor(nullptr, false, sta)
false,
sta)
{ {
init0(); init0();
init(true, false, nullptr); init(true, false, nullptr);
@ -1114,9 +1112,7 @@ ArrivalVisitor::ArrivalVisitor(const StaState *sta) :
ArrivalVisitor::ArrivalVisitor(bool always_to_endpoints, ArrivalVisitor::ArrivalVisitor(bool always_to_endpoints,
SearchPred *pred, SearchPred *pred,
const StaState *sta) : const StaState *sta) :
PathVisitor(pred, PathVisitor(pred, true, sta)
true,
sta)
{ {
init0(); init0();
init(always_to_endpoints, false, pred); init(always_to_endpoints, false, pred);
@ -1997,11 +1993,13 @@ PathVisitor::visitFaninPaths(Vertex *to_vertex)
VertexInEdgeIterator edge_iter(to_vertex, graph_); VertexInEdgeIterator edge_iter(to_vertex, graph_);
while (edge_iter.hasNext()) { while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next(); Edge *edge = edge_iter.next();
Vertex *from_vertex = edge->from(graph_); if (!edge->role()->isTimingCheck()) {
const Pin *from_pin = from_vertex->pin(); Vertex *from_vertex = edge->from(graph_);
const Pin *to_pin = to_vertex->pin(); const Pin *from_pin = from_vertex->pin();
if (!visitEdge(from_pin, from_vertex, edge, to_pin, to_vertex)) const Pin *to_pin = to_vertex->pin();
break; if (!visitEdge(from_pin, from_vertex, edge, to_pin, to_vertex))
break;
}
} }
} }