refactor find clocks

This commit is contained in:
James Cherry 2020-06-25 07:35:07 -07:00
parent 07e1262186
commit 41f8a97271
8 changed files with 172 additions and 21 deletions

View File

@ -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

View File

@ -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_;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

124
search/FindClkPins.cc Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
#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

View File

@ -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 *