From 41f8a97271f89772d0ac02813536389f67fcd6bb Mon Sep 17 00:00:00 2001 From: James Cherry Date: Thu, 25 Jun 2020 07:35:07 -0700 Subject: [PATCH] refactor find clocks --- CMakeLists.txt | 1 + include/sta/Sta.hh | 16 ++++ search/CheckCapacitanceLimits.cc | 11 +-- search/CheckCapacitanceLimits.hh | 7 +- search/CheckFanoutLimits.cc | 9 +-- search/CheckFanoutLimits.hh | 7 +- search/FindClkPins.cc | 124 +++++++++++++++++++++++++++++++ search/Sta.cc | 18 +++-- 8 files changed, 172 insertions(+), 21 deletions(-) create mode 100644 search/FindClkPins.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 07ccac05..fa6dd609 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -180,6 +180,7 @@ set(STA_SOURCE search/ReportPath.cc search/Search.cc search/SearchPred.cc + search/FindClkPins.cc search/Sim.cc search/Sta.cc search/StaState.cc diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index e4e911a1..150d9610 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -1189,6 +1189,13 @@ public: //////////////////////////////////////////////////////////////// + void ensureClkPins(); + bool isIdealClock(Pin *pin) const; + bool isClock(Pin *pin) const; + void clkPinsInvalid(); + +//////////////////////////////////////////////////////////////// + void setTclInterp(Tcl_Interp *interp); Tcl_Interp *tclInterp(); void ensureLevelized(); @@ -1367,6 +1374,11 @@ protected: void replaceCell(Instance *inst, Cell *to_cell, LibertyCell *to_lib_cell); + void clkPinsConnectPinAfter(Vertex *vertex); + void clkPinsDisconnectPinBefore(Vertex *vertex); + void findClkPins(); + void findClkPins(bool ideal_only, + PinSet &clk_pins); CmdNamespace cmd_namespace_; Instance *current_instance_; @@ -1385,6 +1397,10 @@ protected: bool link_make_black_boxes_; bool update_genclks_; EquivCells *equiv_cells_; + // findClkPins + PinSet clk_pins_; + PinSet ideal_clk_pins_; + bool clk_pins_valid_; // Singleton sta used by tcl command interpreter. static Sta *sta_; diff --git a/search/CheckCapacitanceLimits.cc b/search/CheckCapacitanceLimits.cc index ced71a7d..65c53a4b 100644 --- a/search/CheckCapacitanceLimits.cc +++ b/search/CheckCapacitanceLimits.cc @@ -82,7 +82,7 @@ PinCapacitanceLimitSlackLess::operator()(Pin *pin1, //////////////////////////////////////////////////////////////// -CheckCapacitanceLimits::CheckCapacitanceLimits(const StaState *sta) : +CheckCapacitanceLimits::CheckCapacitanceLimits(const Sta *sta) : sta_(sta) { } @@ -205,7 +205,8 @@ CheckCapacitanceLimits::checkCapacitance(const Pin *pin, { const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max); const OperatingConditions *op_cond = dcalc_ap->operatingConditions(); - float cap = sta_->graphDelayCalc()->loadCap(pin, dcalc_ap); + GraphDelayCalc *dcalc = sta_->graphDelayCalc(); + float cap = dcalc->loadCap(pin, dcalc_ap); float slack1 = (min_max == MinMax::max()) ? limit1 - cap : cap - limit1; @@ -313,18 +314,18 @@ CheckCapacitanceLimits::pinMinCapacitanceLimitSlack(Instance *inst, } bool -CheckCapacitanceLimits::checkPin(const Pin *pin) +CheckCapacitanceLimits::checkPin(Pin *pin) { const Network *network = sta_->network(); const Sim *sim = sta_->sim(); const Sdc *sdc = sta_->sdc(); const Graph *graph = sta_->graph(); - GraphDelayCalc *dcalc = sta_->graphDelayCalc(); + Search *search = sta_->search(); Vertex *vertex = graph->pinLoadVertex(pin); return network->direction(pin)->isAnyOutput() && !sim->logicZeroOne(pin) && !sdc->isDisabled(pin) - && !(vertex && sta_->graphDelayCalc()->isIdealClk(vertex)); + && !(vertex && sta_->isIdealClock(pin)); } } // namespace diff --git a/search/CheckCapacitanceLimits.hh b/search/CheckCapacitanceLimits.hh index 39e03789..0dc4fa97 100644 --- a/search/CheckCapacitanceLimits.hh +++ b/search/CheckCapacitanceLimits.hh @@ -20,6 +20,7 @@ #include "Transition.hh" #include "NetworkClass.hh" #include "SdcClass.hh" +#include "Sta.hh" namespace sta { @@ -29,7 +30,7 @@ class Corner; class CheckCapacitanceLimits { public: - CheckCapacitanceLimits(const StaState *sta); + CheckCapacitanceLimits(const Sta *sta); // corner=nullptr checks all corners. void checkCapacitance(const Pin *pin, const Corner *corner1, @@ -84,9 +85,9 @@ protected: // Return values. Pin *&min_slack_pin, float &min_slack); - bool checkPin(const Pin *pin); + bool checkPin(Pin *pin); - const StaState *sta_; + const Sta *sta_; }; } // namespace diff --git a/search/CheckFanoutLimits.cc b/search/CheckFanoutLimits.cc index 352482f2..cda77d9c 100644 --- a/search/CheckFanoutLimits.cc +++ b/search/CheckFanoutLimits.cc @@ -23,7 +23,7 @@ #include "Sim.hh" #include "PortDirection.hh" #include "Graph.hh" -#include "GraphDelayCalc.hh" +#include "Search.hh" namespace sta { @@ -70,7 +70,7 @@ PinFanoutLimitSlackLess::operator()(Pin *pin1, //////////////////////////////////////////////////////////////// -CheckFanoutLimits::CheckFanoutLimits(const StaState *sta) : +CheckFanoutLimits::CheckFanoutLimits(const Sta *sta) : sta_(sta) { } @@ -282,18 +282,17 @@ CheckFanoutLimits::pinMinFanoutLimitSlack(Instance *inst, } bool -CheckFanoutLimits::checkPin(const Pin *pin) +CheckFanoutLimits::checkPin(Pin *pin) { const Network *network = sta_->network(); const Sim *sim = sta_->sim(); const Sdc *sdc = sta_->sdc(); const Graph *graph = sta_->graph(); - GraphDelayCalc *dcalc = sta_->graphDelayCalc(); Vertex *vertex = graph->pinLoadVertex(pin); return network->direction(pin)->isAnyOutput() && !sim->logicZeroOne(pin) && !sdc->isDisabled(pin) - && !(vertex && dcalc->isIdealClk(vertex)); + && !(vertex && sta_->isIdealClock(pin)); } } // namespace diff --git a/search/CheckFanoutLimits.hh b/search/CheckFanoutLimits.hh index 280cb9b8..164455cc 100644 --- a/search/CheckFanoutLimits.hh +++ b/search/CheckFanoutLimits.hh @@ -19,6 +19,7 @@ #include "MinMax.hh" #include "NetworkClass.hh" #include "SdcClass.hh" +#include "Sta.hh" namespace sta { @@ -27,7 +28,7 @@ class StaState; class CheckFanoutLimits { public: - CheckFanoutLimits(const StaState *sta); + CheckFanoutLimits(const Sta *sta); void checkFanout(const Pin *pin, const MinMax *min_max, // Return values. @@ -59,9 +60,9 @@ protected: Pin *&min_slack_pin, float &min_slack); float fanoutLoad(const Pin *pin) const; - bool checkPin(const Pin *pin); + bool checkPin(Pin *pin); - const StaState *sta_; + const Sta *sta_; }; } // namespace diff --git a/search/FindClkPins.cc b/search/FindClkPins.cc new file mode 100644 index 00000000..e497e067 --- /dev/null +++ b/search/FindClkPins.cc @@ -0,0 +1,124 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2020, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "Sta.hh" + +#include "Network.hh" +#include "Graph.hh" +#include "Bfs.hh" +#include "Sdc.hh" +#include "SearchPred.hh" +#include "Search.hh" + +namespace sta { + +void +Sta::ensureClkPins() +{ + if (!clk_pins_valid_) { + ensureLevelized(); + findClkPins(); + clk_pins_valid_ = true; + } +} + +void +Sta::clkPinsInvalid() +{ + clk_pins_valid_ = false; + clk_pins_.clear(); + ideal_clk_pins_.clear(); +} + +void +Sta::clkPinsDisconnectPinBefore(Vertex *vertex) +{ + // If the pin is in the clock network but not a clock endpoint + // everything downstream is invalid. + if (clk_pins_.hasKey(vertex->pin()) + && !isClkEnd(vertex, graph_)) + clk_pins_valid_ = false; +} + +void +Sta::clkPinsConnectPinAfter(Vertex *vertex) +{ + // If the pin fanin is part of the clock network + VertexInEdgeIterator edge_iter(vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + Vertex *from = edge->from(graph_); + if (clk_pins_.hasKey(from->pin())) { + clk_pins_valid_ = false; + break; + } + } +} + +// Find clock network pins. +// This is not as reliable as Search::isClock but is much cheaper. +void +Sta::findClkPins() +{ + // Use two passes to find ideal and propagated clock network pins. + findClkPins(false, clk_pins_); + findClkPins(true, ideal_clk_pins_); +} + +void +Sta::findClkPins(bool ideal_only, + PinSet &clk_pins) +{ + ClkArrivalSearchPred srch_pred(this); + BfsFwdIterator bfs(BfsIndex::other, &srch_pred, this); + for (Clock *clk : sdc_->clks()) { + if (!ideal_only + || !clk->isPropagated()) { + for (Pin *pin : clk->leafPins()) { + if (!ideal_only + || !sdc_->isPropagatedClock(pin)) { + Vertex *vertex, *bidirect_drvr_vertex; + graph_->pinVertices(pin, vertex, bidirect_drvr_vertex); + bfs.enqueue(vertex); + if (bidirect_drvr_vertex) + bfs.enqueue(bidirect_drvr_vertex); + } + } + } + } + while (bfs.hasNext()) { + Vertex *vertex = bfs.next(); + Pin *pin = vertex->pin(); + if (!sdc_->isPropagatedClock(pin)) { + clk_pins.insert(pin); + bfs.enqueueAdjacentVertices(vertex); + } + } +} + +bool +Sta::isClock(Pin *pin) const +{ + return clk_pins_.hasKey(pin); +} + +bool +Sta::isIdealClock(Pin *pin) const +{ + return ideal_clk_pins_.hasKey(pin); +} + +} // namespace diff --git a/search/Sta.cc b/search/Sta.cc index 42e42b14..2d7868cb 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -268,7 +268,8 @@ Sta::Sta() : power_(nullptr), link_make_black_boxes_(true), update_genclks_(false), - equiv_cells_(nullptr) + equiv_cells_(nullptr), + clk_pins_valid_(false) { } @@ -532,6 +533,7 @@ Sta::~Sta() void Sta::clear() { + clkPinsInvalid(); // Constraints reference search filter, so clear search first. search_->clear(); sdc_->clear(); @@ -1136,6 +1138,7 @@ Sta::setPropagatedClock(Clock *clk) sdc_->setPropagatedClock(clk); graph_delay_calc_->delaysInvalid(); search_->arrivalsInvalid(); + clkPinsInvalid(); } void @@ -1144,6 +1147,7 @@ Sta::removePropagatedClock(Clock *clk) sdc_->removePropagatedClock(clk); graph_delay_calc_->delaysInvalid(); search_->arrivalsInvalid(); + clkPinsInvalid(); } void @@ -1152,6 +1156,7 @@ Sta::setPropagatedClock(Pin *pin) sdc_->setPropagatedClock(pin); graph_delay_calc_->delaysInvalid(); search_->arrivalsInvalid(); + clkPinsInvalid(); } void @@ -1160,6 +1165,7 @@ Sta::removePropagatedClock(Pin *pin) sdc_->removePropagatedClock(pin); graph_delay_calc_->delaysInvalid(); search_->arrivalsInvalid(); + clkPinsInvalid(); } void @@ -4024,6 +4030,7 @@ Sta::connectDrvrPinAfter(Vertex *vertex) graph_delay_calc_->delayInvalid(vertex); search_->requiredInvalid(vertex); search_->endpointInvalid(vertex); + clkPinsConnectPinAfter(vertex); levelize_->invalidFrom(vertex); } @@ -4044,6 +4051,7 @@ Sta::connectLoadPinAfter(Vertex *vertex) levelize_->invalidFrom(vertex); search_->arrivalInvalid(vertex); search_->endpointInvalid(vertex); + clkPinsConnectPinAfter(vertex); } void @@ -4063,6 +4071,7 @@ Sta::disconnectPinBefore(Pin *pin) if (edge->role()->isWire()) deleteEdge(edge); } + clkPinsDisconnectPinBefore(vertex); } } if (network_->isLoad(pin)) { @@ -4075,6 +4084,7 @@ Sta::disconnectPinBefore(Pin *pin) if (edge->role()->isWire()) deleteEdge(edge); } + clkPinsDisconnectPinBefore(vertex); } } if (network_->isHierarchical(pin)) { @@ -4907,8 +4917,7 @@ Sta::checkFanoutLimitPreamble() { if (check_fanout_limits_ == nullptr) makeCheckFanoutLimits(); - // For sim values and ideal clocks. - findDelays(); + ensureClkPins(); } Pin * @@ -4974,8 +4983,7 @@ Sta::checkCapacitanceLimitPreamble() { if (check_capacitance_limits_ == nullptr) makeCheckCapacitanceLimits(); - // For sim values and ideal clocks. - findDelays(); + ensureClkPins(); } Pin *