From 1d4b51623985153a879290195d036d404dc6fda0 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 31 Mar 2026 13:59:59 -0700 Subject: [PATCH 1/5] GraphDelayCalc::findInputArcDelay thread issue Signed-off-by: James Cherry --- dcalc/GraphDelayCalc.cc | 30 +++++++++++++++++------------- include/sta/GraphDelayCalc.hh | 6 ++++-- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index bcfb9cc0..d421665e 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -426,7 +426,8 @@ GraphDelayCalc::seedDrvrSlew(Vertex *drvr_vertex, if (from_port == nullptr) from_port = driveCellDefaultFromPort(drvr_cell, to_port); 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 seedNoDrvrCellSlew(drvr_vertex, drvr_pin, rf, drive, scene, min_max, @@ -601,7 +602,8 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell, float *from_slews, const LibertyPort *to_port, const Scene *scene, - const MinMax *min_max) + const MinMax *min_max, + ArcDelayCalc *arc_delay_calc) { debugPrint(debug_, "delay_calc", 2, " driver cell {} {}", drvr_cell->name(), @@ -610,7 +612,8 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell, for (TimingArc *arc : arc_set->arcs()) { if (arc->toEdge()->asRiseFall() == rf) { 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); } } } @@ -626,7 +629,8 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin, const TimingArc *arc, float from_slew, const Scene *scene, - const MinMax *min_max) + const MinMax *min_max, + ArcDelayCalc *arc_delay_calc) { debugPrint(debug_, "delay_calc", 3, " {} {} -> {} {} ({})", arc->from()->name(), @@ -640,20 +644,20 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin, const Parasitic *parasitic; 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); LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex); ArcDcalcResult intrinsic_result = - arc_delay_calc_->gateDelay(drvr_pin, arc, Slew(from_slew), 0.0, nullptr, - load_pin_index_map, scene, min_max); + arc_delay_calc->gateDelay(drvr_pin, arc, Slew(from_slew), 0.0, nullptr, + load_pin_index_map, scene, min_max); const ArcDelay &intrinsic_delay = intrinsic_result.gateDelay(); - ArcDcalcResult gate_result = arc_delay_calc_->gateDelay(drvr_pin, arc, - Slew(from_slew), load_cap, - parasitic, - load_pin_index_map, - scene, min_max); + ArcDcalcResult gate_result = arc_delay_calc->gateDelay(drvr_pin, arc, + Slew(from_slew), load_cap, + parasitic, + load_pin_index_map, + scene, min_max); const ArcDelay &gate_delay = gate_result.gateDelay(); const Slew &gate_slew = gate_result.drvrSlew(); @@ -666,7 +670,7 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin, graph_->setSlew(drvr_vertex, drvr_rf, ap_index, gate_slew); annotateLoadDelays(drvr_vertex, drvr_rf, gate_result, load_pin_index_map, load_delay, false, scene, min_max); - arc_delay_calc_->finishDrvrPin(); + arc_delay_calc->finishDrvrPin(); } } diff --git a/include/sta/GraphDelayCalc.hh b/include/sta/GraphDelayCalc.hh index 60c12d43..85d198c6 100644 --- a/include/sta/GraphDelayCalc.hh +++ b/include/sta/GraphDelayCalc.hh @@ -174,7 +174,8 @@ protected: float *from_slews, const LibertyPort *to_port, const Scene *scene, - const MinMax *min_max); + const MinMax *min_max, + ArcDelayCalc *arc_delay_calc); LibertyPort *driveCellDefaultFromPort(const LibertyCell *cell, const LibertyPort *to_port); int findPortIndex(const LibertyCell *cell, @@ -184,7 +185,8 @@ protected: const TimingArc *arc, float from_slew, const Scene *scene, - const MinMax *min_max); + const MinMax *min_max, + ArcDelayCalc *arc_delay_calc); void findDriverDelays(Vertex *drvr_vertex, ArcDelayCalc *arc_delay_calc, LoadPinIndexMap &load_pin_index_map); From 9eb9edb0b37e58cdb4114a8e8bf83b374f09be4c Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 31 Mar 2026 14:20:50 -0700 Subject: [PATCH 2/5] GateTableModel::gateDelay do not clip delays Signed-off-by: James Cherry --- liberty/TableModel.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/liberty/TableModel.cc b/liberty/TableModel.cc index 09f80ee8..676d29af 100644 --- a/liberty/TableModel.cc +++ b/liberty/TableModel.cc @@ -108,19 +108,18 @@ GateTableModel::gateDelay(const Pvt *pvt, float &gate_delay, 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); else 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); + // Clip negative slews to zero. + if (drvr_slew < 0.0) + drvr_slew = 0.0; + } else drvr_slew = 0.0; - // 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 From 8c1ebce6955852fe80e353d8d251d4b237cad4eb Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 31 Mar 2026 16:37:38 -0700 Subject: [PATCH 3/5] GraphDelayCalc::findInputDriverDelay rm finishDrvrPin Signed-off-by: James Cherry --- dcalc/GraphDelayCalc.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index d421665e..3057e1d4 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -617,7 +617,6 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell, } } } - arc_delay_calc_->finishDrvrPin(); } // Driving cell delay is the load dependent delay, which is the gate From 638ffa57d4648a49143862e1f415f085957007c9 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 31 Mar 2026 16:45:47 -0700 Subject: [PATCH 4/5] cleanup Signed-off-by: James Cherry --- dcalc/DmpCeff.cc | 67 +++++++++++++++++++++-------------------- dcalc/GraphDelayCalc.cc | 48 ++++++++++++++--------------- 2 files changed, 58 insertions(+), 57 deletions(-) diff --git a/dcalc/DmpCeff.cc b/dcalc/DmpCeff.cc index 577bce5c..6828aa67 100644 --- a/dcalc/DmpCeff.cc +++ b/dcalc/DmpCeff.cc @@ -44,7 +44,6 @@ #include "TimingArc.hh" #include "TableModel.hh" #include "Liberty.hh" -#include "Network.hh" #include "Sdc.hh" #include "Parasitics.hh" #include "ArcDelayCalc.hh" @@ -78,11 +77,11 @@ exp2(double x); class DmpError : public Exception { public: - DmpError(const char *what); - virtual const char *what() const noexcept { return what_; } + DmpError(std::string_view what); + virtual const char *what() const noexcept { return what_.c_str(); } private: - const char *what_; + std::string what_; }; static double @@ -139,9 +138,9 @@ public: double c2, double rpi, double c1); - virtual void gateDelaySlew( // Return values. - double &delay, - double &slew) = 0; + virtual void gateDelaySlew(// Return values. + double &delay, + double &slew) = 0; virtual void loadDelaySlew(const Pin *load_pin, double elmore, // Return values. @@ -685,9 +684,9 @@ public: double c2, double rpi, double c1) override; - void gateDelaySlew( // Return values. - double &delay, - double &slew) override; + void gateDelaySlew(// Return values. + double &delay, + double &slew) override; void loadDelaySlew(const Pin *, double elmore, // Return values. @@ -726,15 +725,15 @@ DmpCap::init(const LibertyLibrary *drvr_library, double c1) { debugPrint(debug_, "dmp_ceff", 3, "Using DMP cap"); - DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew, c2, rpi, - c1); + DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew, + c2, rpi, c1); ceff_ = c1 + c2; } void -DmpCap::gateDelaySlew( // Return values. - double &delay, - double &slew) +DmpCap::gateDelaySlew(// Return values. + double &delay, + double &slew) { debugPrint(debug_, "dmp_ceff", 3, " ceff = {}", units_->capacitanceUnit()->asString(ceff_)); @@ -801,9 +800,9 @@ public: double c2, double rpi, double c1) override; - void gateDelaySlew( // Return values. - double &delay, - double &slew) override; + void gateDelaySlew(// Return values. + double &delay, + double &slew) override; void evalDmpEqns() override; double voCrossingUpperBound() override; @@ -868,8 +867,8 @@ DmpPi::init(const LibertyLibrary *drvr_library, double c1) { debugPrint(debug_, "dmp_ceff", 3, "Using DMP Pi"); - DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew, c2, rpi, - c1); + DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew, + c2, rpi, c1); // Find poles/zeros. z1_ = 1.0 / (rpi_ * c1_); @@ -893,9 +892,9 @@ DmpPi::init(const LibertyLibrary *drvr_library, } void -DmpPi::gateDelaySlew( // Return values. - double &delay, - double &slew) +DmpPi::gateDelaySlew(// Return values. + double &delay, + double &slew) { driver_valid_ = false; try { @@ -1127,9 +1126,9 @@ public: double c2, double rpi, double c1) override; - void gateDelaySlew( // Return values. - double &delay, - double &slew) override; + void gateDelaySlew(// Return values. + double &delay, + double &slew) override; private: void V0(double t, @@ -1176,8 +1175,8 @@ DmpZeroC2::init(const LibertyLibrary *drvr_library, double c1) { debugPrint(debug_, "dmp_ceff", 3, "Using DMP C2=0"); - DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew, c2, rpi, - c1); + DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew, + c2, rpi, c1); ceff_ = c1; z1_ = 1.0 / (rpi_ * c1_); @@ -1275,8 +1274,10 @@ newtonRaphson(const int max_iter, all_under_x_tol = false; x[i] += p[i]; } - if (all_under_x_tol) + if (all_under_x_tol) { + eval(); return; + } } throw DmpError("Newton-Raphson max iterations exceeded"); } @@ -1557,8 +1558,8 @@ DmpCeffDelayCalc::setCeffAlgorithm(const LibertyLibrary *drvr_library, } else dmp_alg_ = dmp_cap_; - dmp_alg_->init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew, c2, rpi, - c1); + dmp_alg_->init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew, + c2, rpi, c1); debugPrint(debug_, "dmp_ceff", 3, " DMP in_slew = {} c2 = {} rpi = {} c1 = {} Rd = {} ({} alg)", units_->timeUnit()->asString(in_slew), @@ -1667,10 +1668,10 @@ DmpCeffDelayCalc::copyState(const StaState *sta) dmp_zero_c2_->copyState(sta); } -DmpError::DmpError(const char *what) : +DmpError::DmpError(std::string_view 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. diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index 3057e1d4..f8984474 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -1601,41 +1601,41 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge, for (Scene *scene : scenes_) { for (const MinMax *min_max : MinMax::range()) { DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max); - if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) { - const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf, + if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) { + const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf, scene, min_max); const Slew to_slew = graph_->slew(to_vertex, to_rf, ap_index); - debugPrint(debug_, "delay_calc", 3, + debugPrint(debug_, "delay_calc", 3, " {} {} -> {} {} ({}) scene:{}/{}", - arc_set->from()->name(), - arc->fromEdge()->to_string(), - arc_set->to()->name(), - arc->toEdge()->to_string(), - arc_set->role()->to_string(), + arc_set->from()->name(), + arc->fromEdge()->to_string(), + arc_set->to()->name(), + arc->toEdge()->to_string(), + arc_set->role()->to_string(), scene->name(), min_max->to_string()); - debugPrint(debug_, "delay_calc", 3, - " from_slew = {} to_slew = {}", - delayAsString(from_slew, this), - delayAsString(to_slew, this)); - float related_out_cap = 0.0; - if (related_out_pin) + debugPrint(debug_, "delay_calc", 3, + " from_slew = {} to_slew = {}", + delayAsString(from_slew, this), + delayAsString(to_slew, this)); + float related_out_cap = 0.0; + if (related_out_pin) related_out_cap = loadCap(related_out_pin, to_rf,scene,min_max, arc_delay_calc); - ArcDelay check_delay = arc_delay_calc->checkDelay(to_pin, arc, from_slew, - to_slew, related_out_cap, + ArcDelay check_delay = arc_delay_calc->checkDelay(to_pin, arc, from_slew, + to_slew, related_out_cap, scene, min_max); - debugPrint(debug_, "delay_calc", 3, - " check_delay = {}", - delayAsString(check_delay, this)); - graph_->setArcDelay(edge, arc, ap_index, check_delay); - delay_changed = true; - arc_delay_calc_->finishDrvrPin(); - } + debugPrint(debug_, "delay_calc", 3, + " check_delay = {}", + delayAsString(check_delay, this)); + graph_->setArcDelay(edge, arc, ap_index, check_delay); + delay_changed = true; + arc_delay_calc_->finishDrvrPin(); + } + } } } } - } if (delay_changed && observer_) observer_->checkDelayChangedTo(to_vertex); From 70659c2328dcdc64b8498813bf148e15ee4642e0 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 31 Mar 2026 21:03:55 -0700 Subject: [PATCH 5/5] PathVisitor::visitFaninPaths filter check edges Signed-off-by: James Cherry --- search/Bfs.cc | 2 +- search/ClkSkew.cc | 2 +- search/PathGroup.cc | 2 +- search/Search.cc | 20 +++++++++----------- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/search/Bfs.cc b/search/Bfs.cc index 559cabb7..d13f9700 100644 --- a/search/Bfs.cc +++ b/search/Bfs.cc @@ -194,7 +194,7 @@ BfsIterator::visitParallel(Level to_level, for (size_t k = 0; k < thread_count; k++) { // Last thread gets the left overs. 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++) { Vertex *vertex = level_vertices[i]; if (vertex) { diff --git a/search/ClkSkew.cc b/search/ClkSkew.cc index 97626ca5..89eab1ea 100644 --- a/search/ClkSkew.cc +++ b/search/ClkSkew.cc @@ -196,7 +196,7 @@ ClkSkews::findClkSkew(ConstClockSeq &clks, std::vector partial_skews(thread_count_); for (Vertex *src_vertex : graph_->regClkVertices()) { 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]); }); } diff --git a/search/PathGroup.cc b/search/PathGroup.cc index 1d3e6cd0..e2e20a80 100644 --- a/search/PathGroup.cc +++ b/search/PathGroup.cc @@ -1025,7 +1025,7 @@ PathGroups::makeGroupPathEnds(VertexSet &endpoints, MakeEndpointPathEnds(visitor, Scene::sceneSet(scenes), min_max, this)); for (const auto endpoint : endpoints) { - dispatch_queue_->dispatch( [endpoint, &visitors](int i) + dispatch_queue_->dispatch( [endpoint, &visitors](size_t i) { visitors[i].visit(endpoint); } ); } dispatch_queue_->finishTasks(); diff --git a/search/Search.cc b/search/Search.cc index f1a9658c..246d5dd6 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -1102,9 +1102,7 @@ Search::findArrivalsSeed() //////////////////////////////////////////////////////////////// ArrivalVisitor::ArrivalVisitor(const StaState *sta) : - PathVisitor(nullptr, - false, - sta) + PathVisitor(nullptr, false, sta) { init0(); init(true, false, nullptr); @@ -1114,9 +1112,7 @@ ArrivalVisitor::ArrivalVisitor(const StaState *sta) : ArrivalVisitor::ArrivalVisitor(bool always_to_endpoints, SearchPred *pred, const StaState *sta) : - PathVisitor(pred, - true, - sta) + PathVisitor(pred, true, sta) { init0(); init(always_to_endpoints, false, pred); @@ -1997,11 +1993,13 @@ PathVisitor::visitFaninPaths(Vertex *to_vertex) VertexInEdgeIterator edge_iter(to_vertex, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - Vertex *from_vertex = edge->from(graph_); - const Pin *from_pin = from_vertex->pin(); - const Pin *to_pin = to_vertex->pin(); - if (!visitEdge(from_pin, from_vertex, edge, to_pin, to_vertex)) - break; + if (!edge->role()->isTimingCheck()) { + Vertex *from_vertex = edge->from(graph_); + const Pin *from_pin = from_vertex->pin(); + const Pin *to_pin = to_vertex->pin(); + if (!visitEdge(from_pin, from_vertex, edge, to_pin, to_vertex)) + break; + } } }