diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index 25405f34..9b34acbe 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -579,13 +579,17 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex, else { if (network_->isLeaf(pin)) { if (vertex->isDriver(network_)) { - bool delay_changed = findDriverDelays(vertex, arc_delay_calc); + LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(vertex); + DrvrLoadSlews prev_load_slews = loadSlews(load_pin_index_map); + findDriverDelays(vertex, arc_delay_calc, load_pin_index_map); if (propagate) { if (network_->direction(pin)->isInternal()) enqueueTimingChecksEdges(vertex); - // Enqueue adjacent vertices even if the delays did not + bool load_slews_changed = loadSlewsChanged(prev_load_slews, + load_pin_index_map); + // Enqueue adjacent vertices even if the load slews did not // change when non-incremental to stride past annotations. - if (delay_changed || !incremental_) + if (load_slews_changed || !incremental_) iter_->enqueueAdjacentVertices(vertex); } } @@ -605,6 +609,37 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex, } } +DrvrLoadSlews +GraphDelayCalc::loadSlews(LoadPinIndexMap &load_pin_index_map) +{ + DrvrLoadSlews load_slews(load_pin_index_map.size()); + for (auto const [pin, index] : load_pin_index_map) { + Vertex *load_vertex = graph_->pinLoadVertex(pin); + load_slews[index] = graph_->slews(load_vertex); + } + return load_slews; +} + +bool +GraphDelayCalc::loadSlewsChanged(DrvrLoadSlews &prev_load_slews, + LoadPinIndexMap &load_pin_index_map) +{ + for (auto const [pin, index] : load_pin_index_map) { + Vertex *load_vertex = graph_->pinLoadVertex(pin); + const SlewSeq load_slews = graph_->slews(load_vertex); + const SlewSeq &prev_slews = prev_load_slews[index]; + for (size_t i = 0; i < load_slews.size(); i++) { + const Slew &slew = delayAsFloat(load_slews[i]); + const Slew &prev_slew = delayAsFloat(prev_slews[i]); + if ((prev_slew == 0.0 && slew != 0.0) + || (prev_slew != 0.0 + && abs((slew - prev_slew) / prev_slew) > incremental_delay_tolerance_)) + return true; + } + } + return false; +} + void GraphDelayCalc::enqueueTimingChecksEdges(Vertex *vertex) { @@ -639,21 +674,20 @@ GraphDelayCalc::enqueueTimingChecksEdges(Vertex *vertex) } } -bool +void GraphDelayCalc::findDriverDelays(Vertex *drvr_vertex, - ArcDelayCalc *arc_delay_calc) + ArcDelayCalc *arc_delay_calc, + LoadPinIndexMap &load_pin_index_map) { - bool delay_changed = false; MultiDrvrNet *multi_drvr = findMultiDrvrNet(drvr_vertex); if (multi_drvr == nullptr || (multi_drvr && (!multi_drvr->parallelGates(network_) || drvr_vertex == multi_drvr->dcalcDrvr()))) { initLoadSlews(drvr_vertex); - delay_changed |= findDriverDelays1(drvr_vertex, multi_drvr, arc_delay_calc); + findDriverDelays1(drvr_vertex, multi_drvr, arc_delay_calc, load_pin_index_map); } arc_delay_calc_->finishDrvrPin(); - return delay_changed; } MultiDrvrNet * @@ -782,7 +816,8 @@ GraphDelayCalc::initLoadSlews(Vertex *drvr_vertex) bool GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex, MultiDrvrNet *multi_drvr, - ArcDelayCalc *arc_delay_calc) + ArcDelayCalc *arc_delay_calc, + LoadPinIndexMap &load_pin_index_map) { initSlew(drvr_vertex); if (multi_drvr @@ -806,7 +841,8 @@ GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex, && search_pred_->searchThru(edge) && !edge->role()->isLatchDtoQ()) delay_changed |= findDriverEdgeDelays(drvr_vertex, multi_drvr, edge, - arc_delay_calc, delay_exists); + arc_delay_calc, load_pin_index_map, + delay_exists); } for (auto rf : RiseFall::range()) { if (!delay_exists[rf->index()]) @@ -841,8 +877,10 @@ GraphDelayCalc::findLatchEdgeDelays(Edge *edge) debugPrint(debug_, "delay_calc", 2, "find latch D->Q %s", sdc_network_->pathName(drvr_inst)); array delay_exists = {false, false}; + LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex); bool delay_changed = findDriverEdgeDelays(drvr_vertex, nullptr, edge, - arc_delay_calc_, delay_exists); + arc_delay_calc_, load_pin_index_map, + delay_exists); if (delay_changed && observer_) observer_->delayChangedTo(drvr_vertex); } @@ -852,17 +890,18 @@ GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex, const MultiDrvrNet *multi_drvr, Edge *edge, ArcDelayCalc *arc_delay_calc, + LoadPinIndexMap &load_pin_index_map, + // Return value. array &delay_exists) { Vertex *from_vertex = edge->from(graph_); const TimingArcSet *arc_set = edge->timingArcSet(); bool delay_changed = false; - LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex); for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (const TimingArc *arc : arc_set->arcs()) { delay_changed |= findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc, - load_pin_index_map, dcalc_ap, - arc_delay_calc); + dcalc_ap, arc_delay_calc, + load_pin_index_map); delay_exists[arc->toEdge()->asRiseFall()->index()] = true; } } @@ -873,6 +912,7 @@ GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex, return delay_changed; } +// External API. void GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex, Edge *edge, @@ -882,9 +922,8 @@ GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex, { MultiDrvrNet *multi_drvr = multiDrvrNet(drvr_vertex); LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex); - findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc, - load_pin_index_map, dcalc_ap, - arc_delay_calc); + findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc, dcalc_ap, + arc_delay_calc, load_pin_index_map); } bool @@ -892,9 +931,9 @@ GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex, const MultiDrvrNet *multi_drvr, Edge *edge, const TimingArc *arc, - LoadPinIndexMap &load_pin_index_map, const DcalcAnalysisPt *dcalc_ap, - ArcDelayCalc *arc_delay_calc) + ArcDelayCalc *arc_delay_calc, + LoadPinIndexMap &load_pin_index_map) { bool delay_changed = false; const RiseFall *from_rf = arc->fromEdge()->asRiseFall(); diff --git a/graph/Graph.cc b/graph/Graph.cc index 3db3e4da..c341434d 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -741,6 +741,20 @@ Graph::setSlew(Vertex *vertex, } } +SlewSeq +Graph::slews(Vertex *vertex) +{ + SlewSeq slews; + VertexId vertex_id = id(vertex); + DcalcAPIndex rf_ap_count = slew_rf_count_ * ap_count_; + for (DcalcAPIndex i = 0; i < rf_ap_count; i++) { + DelayTable *table = slew_tables_[i]; + Slew &slew = table->ref(vertex_id); + slews.push_back(slew); + } + return slews; +} + //////////////////////////////////////////////////////////////// Edge * diff --git a/include/sta/Graph.hh b/include/sta/Graph.hh index 3ac640f4..812fdbb7 100644 --- a/include/sta/Graph.hh +++ b/include/sta/Graph.hh @@ -130,6 +130,7 @@ public: const RiseFall *rf, DcalcAPIndex ap_index, const Slew &slew); + SlewSeq slews(Vertex *vertex); // Edge functions. virtual Edge *edge(EdgeId edge_index) const; diff --git a/include/sta/GraphClass.hh b/include/sta/GraphClass.hh index 834ee2aa..0cde7b59 100644 --- a/include/sta/GraphClass.hh +++ b/include/sta/GraphClass.hh @@ -23,9 +23,12 @@ #include "Vector.hh" #include "MinMax.hh" #include "Transition.hh" +#include "Delay.hh" namespace sta { +using std::vector; + // Class declarations for pointer references. class Graph; class Vertex; @@ -46,6 +49,7 @@ typedef int Level; typedef int DcalcAPIndex; typedef int TagGroupIndex; typedef Vector GraphLoopSeq; +typedef vector SlewSeq; static constexpr int level_max = std::numeric_limits::max(); diff --git a/include/sta/GraphDelayCalc.hh b/include/sta/GraphDelayCalc.hh index 1ed9bea3..e34a2f55 100644 --- a/include/sta/GraphDelayCalc.hh +++ b/include/sta/GraphDelayCalc.hh @@ -26,7 +26,6 @@ #include "SearchClass.hh" #include "DcalcAnalysisPt.hh" #include "StaState.hh" -#include "Delay.hh" #include "ArcDelayCalc.hh" namespace sta { @@ -41,6 +40,7 @@ class FindVertexDelays; class NetCaps; typedef Map MultiDrvrNetMap; +typedef vector DrvrLoadSlews; // This class traverses the graph calling the arc delay calculator and // annotating delays on graph edges. @@ -163,8 +163,9 @@ protected: const TimingArc *arc, float from_slew, const DcalcAnalysisPt *dcalc_ap); - bool findDriverDelays(Vertex *drvr_vertex, - ArcDelayCalc *arc_delay_calc); + void findDriverDelays(Vertex *drvr_vertex, + ArcDelayCalc *arc_delay_calc, + LoadPinIndexMap &load_pin_index_map); MultiDrvrNet *multiDrvrNet(const Vertex *drvr_vertex) const; MultiDrvrNet *findMultiDrvrNet(Vertex *drvr_pin); MultiDrvrNet *makeMultiDrvrNet(Vertex *drvr_vertex); @@ -172,20 +173,23 @@ protected: Vertex *firstLoad(Vertex *drvr_vertex); bool findDriverDelays1(Vertex *drvr_vertex, MultiDrvrNet *multi_drvr, - ArcDelayCalc *arc_delay_calc); + ArcDelayCalc *arc_delay_calc, + LoadPinIndexMap &load_pin_index_map); void initLoadSlews(Vertex *drvr_vertex); bool findDriverEdgeDelays(Vertex *drvr_vertex, - const MultiDrvrNet *multi_drvr, - Edge *edge, - ArcDelayCalc *arc_delay_calc, + const MultiDrvrNet *multi_drvr, + Edge *edge, + ArcDelayCalc *arc_delay_calc, + LoadPinIndexMap &load_pin_index_map, + // Return value. array &delay_exists); bool findDriverArcDelays(Vertex *drvr_vertex, const MultiDrvrNet *multi_drvr, Edge *edge, const TimingArc *arc, - LoadPinIndexMap &load_pin_index_map, const DcalcAnalysisPt *dcalc_ap, - ArcDelayCalc *arc_delay_calc); + ArcDelayCalc *arc_delay_calc, + LoadPinIndexMap &load_pin_index_map); ArcDcalcArgSeq makeArcDcalcArgs(Vertex *drvr_vertex, const MultiDrvrNet *multi_drvr, Edge *edge, @@ -205,6 +209,9 @@ protected: void findVertexDelay(Vertex *vertex, ArcDelayCalc *arc_delay_calc, bool propagate); + DrvrLoadSlews loadSlews(LoadPinIndexMap &load_pin_index_map); + bool loadSlewsChanged(DrvrLoadSlews &prev_load_slews, + LoadPinIndexMap &load_pin_index_map); void enqueueTimingChecksEdges(Vertex *vertex); bool annotateDelaysSlews(Edge *edge, const TimingArc *arc, diff --git a/search/Sta.cc b/search/Sta.cc index 82df5af3..daea9eb4 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -5625,6 +5625,9 @@ Sta::writeTimingModel(const char *lib_name, const Corner *corner, const bool scalar) { + if (network()->defaultLibertyLibrary() == nullptr) { + report_->error(2141, "No liberty libraries found."); + } LibertyLibrary *library = makeTimingModel(lib_name, cell_name, filename, corner, scalar, this); writeLiberty(library, filename, this);