PathVisitor is-a StaState instead of haa-a

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2022-08-11 18:17:46 -07:00
parent c43cd616db
commit 0448425fae
6 changed files with 229 additions and 273 deletions

View File

@ -637,7 +637,7 @@ public:
// Class for visiting fanin/fanout paths of a vertex.
// This used by forward/backward search to find arrival/required path times.
class PathVisitor : public VertexVisitor
class PathVisitor : public VertexVisitor, public StaState
{
public:
// Uses search->evalPred() for search predicate.
@ -691,7 +691,6 @@ protected:
const MinMax *min_max,
const PathAnalysisPt *path_ap) = 0;
SearchPred *pred_;
const StaState *sta_;
};
// Visitor called during forward search to record an

View File

@ -856,26 +856,22 @@ VertexVisitor *
GenclkSrcArrivalVisitor::copy() const
{
return new GenclkSrcArrivalVisitor(gclk_, insert_iter_, genclk_info_,
always_to_endpoints_, pred_, sta_);
always_to_endpoints_, pred_, this);
}
void
GenclkSrcArrivalVisitor::visit(Vertex *vertex)
{
const Debug *debug = sta_->debug();
const Network *sdc_network = sta_->sdcNetwork();
const Graph *graph = sta_->graph();
Search *search = sta_->search();
Genclks *genclks = search->genclks();
debugPrint(debug, "genclk", 2, "find gen clk insert arrival %s",
vertex->name(sdc_network));
Genclks *genclks = search_->genclks();
debugPrint(debug_, "genclk", 2, "find gen clk insert arrival %s",
vertex->name(sdc_network_));
tag_bldr_->init(vertex);
has_fanin_one_ = graph->hasFaninOne(vertex);
has_fanin_one_ = graph_->hasFaninOne(vertex);
genclks->copyGenClkSrcPaths(vertex, tag_bldr_);
visitFaninPaths(vertex);
// Propagate beyond the clock tree to reach generated clk roots.
insert_iter_->enqueueAdjacentVertices(vertex, &srch_pred_);
search->setVertexArrivals(vertex, tag_bldr_);
search_->setVertexArrivals(vertex, tag_bldr_);
}
void
@ -1191,19 +1187,15 @@ PllArrivalVisitor::PllArrivalVisitor(const StaState *sta,
void
PllArrivalVisitor::visit(Vertex *vertex)
{
const Debug *debug = sta_->debug();
const Network *sdc_network = sta_->network();
Graph *graph = sta_->graph();
Search *search = sta_->search();
Genclks *genclks = search->genclks();
debugPrint(debug, "genclk", 2, "find gen clk pll arrival %s",
vertex->name(sdc_network));
Genclks *genclks = search_->genclks();
debugPrint(debug_, "genclk", 2, "find gen clk pll arrival %s",
vertex->name(sdc_network_));
tag_bldr_->init(vertex);
genclks->copyGenClkSrcPaths(vertex, tag_bldr_);
has_fanin_one_ = graph->hasFaninOne(vertex);
has_fanin_one_ = graph_->hasFaninOne(vertex);
visitFaninPaths(vertex);
pll_iter_.enqueueAdjacentVertices(vertex);
search->setVertexArrivals(vertex, tag_bldr_);
search_->setVertexArrivals(vertex, tag_bldr_);
}
void

View File

@ -276,15 +276,15 @@ PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end,
PathEnum *path_enum) :
PathVisitor(path_enum),
path_end_(path_end),
path_end_slack_(path_end->slack(sta_)),
path_end_slack_(path_end->slack(this)),
before_div_(before_div),
unique_pins_(unique_pins),
before_div_rf_index_(before_div_.rfIndex(sta_)),
before_div_tag_(before_div_.tag(sta_)),
before_div_ap_index_(before_div_.pathAnalysisPtIndex(sta_)),
before_div_arrival_(before_div_.arrival(sta_)),
before_div_rf_index_(before_div_.rfIndex(this)),
before_div_tag_(before_div_.tag(this)),
before_div_ap_index_(before_div_.pathAnalysisPtIndex(this)),
before_div_arrival_(before_div_.arrival(this)),
path_enum_(path_enum),
crpr_active_(sta_->sdc()->crprActive())
crpr_active_(sdc_->crprActive())
{
}
@ -293,10 +293,10 @@ PathEnumFaninVisitor::visitFaninPathsThru(Vertex *vertex,
Vertex *prev_vertex,
TimingArc *prev_arc)
{
before_div_rf_index_ = before_div_.rfIndex(sta_);
before_div_tag_ = before_div_.tag(sta_);
before_div_ap_index_ = before_div_.pathAnalysisPtIndex(sta_);
before_div_arrival_ = before_div_.arrival(sta_);
before_div_rf_index_ = before_div_.rfIndex(this);
before_div_tag_ = before_div_.tag(this);
before_div_ap_index_ = before_div_.pathAnalysisPtIndex(this);
before_div_arrival_ = before_div_.arrival(this);
prev_arc_ = prev_arc;
prev_vertex_ = prev_vertex;
visitFaninPaths(vertex);
@ -325,13 +325,12 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
const MinMax *min_max,
const PathAnalysisPt *path_ap)
{
const Debug *debug = sta_->debug();
debugPrint(debug, "path_enum", 3, "visit fanin %s -> %s %s %s",
from_path->name(sta_),
to_vertex->name(sta_->network()),
debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s",
from_path->name(this),
to_vertex->name(network_),
to_rf->asString(),
delayAsString(sta_->search()->deratedDelay(from_vertex, arc, edge,
false,path_ap),sta_));
delayAsString(search_->deratedDelay(from_vertex, arc, edge,
false,path_ap), this));
// These paths fanin to before_div_ so we know to_vertex matches.
if (to_rf->index() == before_div_rf_index_
&& path_ap->index() == before_div_ap_index_
@ -344,7 +343,7 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
// Make the diverted path end to check slack with from_path crpr.
makeDivertedPathEnd(from_path, arc, div_end, after_div_copy);
// Only enumerate paths with greater slack.
if (delayGreaterEqual(div_end->slack(sta_), path_end_slack_, sta_)) {
if (delayGreaterEqual(div_end->slack(this), path_end_slack_, this)) {
reportDiversion(arc, from_path);
path_enum_->makeDiversion(div_end, after_div_copy);
}
@ -352,7 +351,7 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
delete div_end;
}
// Only enumerate slower/faster paths.
else if (delayLessEqual(to_arrival, before_div_arrival_, min_max, sta_)) {
else if (delayLessEqual(to_arrival, before_div_arrival_, min_max, this)) {
PathEnd *div_end;
PathEnumed *after_div_copy;
makeDivertedPathEnd(from_path, arc, div_end, after_div_copy);
@ -374,36 +373,34 @@ PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div,
path_enum_->makeDivertedPath(path_end_->path(), &before_div_, after_div,
div_arc, div_path, after_div_copy);
div_end = path_end_->copy();
div_end->setPath(div_path, sta_);
div_end->setPath(div_path, this);
}
void
PathEnumFaninVisitor::reportDiversion(TimingArc *div_arc,
Path *after_div)
{
Debug *debug = sta_->debug();
if (debug->check("path_enum", 3)) {
Report *report = sta_->report();
if (debug_->check("path_enum", 3)) {
Path *path = path_end_->path();
const PathAnalysisPt *path_ap = path->pathAnalysisPt(sta_);
const PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
Arrival path_delay = path_enum_->cmp_slack_
? path_end_->slack(sta_)
: path_end_->dataArrivalTime(sta_);
? path_end_->slack(this)
: path_end_->dataArrivalTime(this);
Arrival div_delay = path_delay - path_enum_->divSlack(&before_div_,
after_div,
div_arc, path_ap);
PathRef div_prev;
before_div_.prevPath(sta_, div_prev);
report->reportLine("path_enum: diversion %s %s %s -> %s",
path->name(sta_),
path_enum_->cmp_slack_ ? "slack" : "delay",
delayAsString(path_delay, sta_),
delayAsString(div_delay, sta_));
report->reportLine("path_enum: from %s -> %s",
div_prev.name(sta_),
before_div_.name(sta_));
report->reportLine("path_enum: to %s ->e",
after_div->name(sta_));
before_div_.prevPath(this, div_prev);
report_->reportLine("path_enum: diversion %s %s %s -> %s",
path->name(this),
path_enum_->cmp_slack_ ? "slack" : "delay",
delayAsString(path_delay, this),
delayAsString(div_delay, this));
report_->reportLine("path_enum: from %s -> %s",
div_prev.name(this),
before_div_.name(this));
report_->reportLine("path_enum: to %s ->e",
after_div->name(this));
}
}

View File

@ -371,7 +371,7 @@ PrevPathVisitor::PrevPathVisitor(const Path *path,
VertexVisitor *
PrevPathVisitor::copy() const
{
return new PrevPathVisitor(path_, pred_, sta_);
return new PrevPathVisitor(path_, pred_, this);
}
bool
@ -396,14 +396,14 @@ PrevPathVisitor::visitFromToPath(const Pin *,
&& (dcalc_tol_ > 0.0
? std::abs(delayAsFloat(to_arrival - path_arrival_)) < dcalc_tol_
: delayEqual(to_arrival, path_arrival_))
&& (tagMatch(to_tag, path_tag_, sta_)
&& (tagMatch(to_tag, path_tag_, this)
// If the filter exception became active searching from
// from_path to to_path the tag includes the filter, but
// to_vertex still has paths from previous searches that do
// not have the filter.
|| (!from_tag->isFilter()
&& to_tag->isFilter()
&& tagMatch(unfilteredTag(to_tag), path_tag_, sta_)))) {
&& tagMatch(unfilteredTag(to_tag), path_tag_, this)))) {
int arrival_index;
bool arrival_exists;
from_path->arrivalIndex(arrival_index, arrival_exists);
@ -420,8 +420,6 @@ PrevPathVisitor::visitFromToPath(const Pin *,
Tag *
PrevPathVisitor::unfilteredTag(const Tag *tag) const
{
Search *search = sta_->search();
const Corners *corners = sta_->corners();
ExceptionStateSet *unfiltered_states = nullptr;
const ExceptionStateSet *states = tag->states();
ExceptionStateSet::ConstIterator state_iter(states);
@ -434,8 +432,8 @@ PrevPathVisitor::unfilteredTag(const Tag *tag) const
unfiltered_states->insert(state);
}
}
return search->findTag(tag->transition(),
corners->findPathAnalysisPt(tag->pathAPIndex()),
return search_->findTag(tag->transition(),
corners_->findPathAnalysisPt(tag->pathAPIndex()),
tag->clkInfo(),
tag->isClock(),
tag->inputDelay(),

View File

@ -384,6 +384,7 @@ Search::copyState(const StaState *sta)
// Notify sub-components.
arrival_iter_->copyState(sta);
required_iter_->copyState(sta);
arrival_visitor_->copyState(sta);
visit_path_ends_->copyState(sta);
gated_clk_->copyState(sta);
check_crpr_->copyState(sta);
@ -1030,16 +1031,15 @@ ArrivalVisitor::ArrivalVisitor(bool always_to_endpoints,
void
ArrivalVisitor::init0()
{
tag_bldr_ = new TagGroupBldr(true, sta_);
tag_bldr_no_crpr_ = new TagGroupBldr(false, sta_);
adj_pred_ = new SearchThru(tag_bldr_, sta_);
tag_bldr_ = new TagGroupBldr(true, this);
tag_bldr_no_crpr_ = new TagGroupBldr(false, this);
adj_pred_ = new SearchThru(tag_bldr_, this);
}
void
ArrivalVisitor::init(bool always_to_endpoints)
{
Search *search = sta_->search();
init(always_to_endpoints, search ? search->evalPred() : nullptr);
init(always_to_endpoints, search_ ? search_->evalPred() : nullptr);
}
void
@ -1048,14 +1048,14 @@ ArrivalVisitor::init(bool always_to_endpoints,
{
always_to_endpoints_ = always_to_endpoints;
pred_ = pred;
crpr_active_ = sta_->sdc()->crprActive();
crpr_active_ = sdc_->crprActive();
}
VertexVisitor *
ArrivalVisitor::copy() const
{
return new ArrivalVisitor(always_to_endpoints_, pred_, sta_);
return new ArrivalVisitor(always_to_endpoints_, pred_, this);
}
ArrivalVisitor::~ArrivalVisitor()
@ -1074,40 +1074,34 @@ ArrivalVisitor::setAlwaysToEndpoints(bool to_endpoints)
void
ArrivalVisitor::visit(Vertex *vertex)
{
const Debug *debug = sta_->debug();
const Network *network = sta_->network();
const Network *sdc_network = sta_->sdcNetwork();
const Graph *graph = sta_->graph();
const Sdc *sdc = sta_->sdc();
Search *search = sta_->search();
debugPrint(debug, "search", 2, "find arrivals %s",
vertex->name(sdc_network));
debugPrint(debug_, "search", 2, "find arrivals %s",
vertex->name(sdc_network_));
Pin *pin = vertex->pin();
tag_bldr_->init(vertex);
has_fanin_one_ = graph->hasFaninOne(vertex);
has_fanin_one_ = graph_->hasFaninOne(vertex);
if (crpr_active_
&& !has_fanin_one_)
tag_bldr_no_crpr_->init(vertex);
visitFaninPaths(vertex);
if (crpr_active_
&& search->crprPathPruningEnabled()
&& search_->crprPathPruningEnabled()
&& !vertex->crprPathPruningDisabled()
&& !has_fanin_one_)
pruneCrprArrivals();
// Insert paths that originate here.
if (!network->isTopLevelPort(pin)
&& sdc->hasInputDelay(pin))
if (!network_->isTopLevelPort(pin)
&& sdc_->hasInputDelay(pin))
// set_input_delay on internal pin.
search->seedInputSegmentArrival(pin, vertex, tag_bldr_);
if (sdc->isPathDelayInternalStartpoint(pin))
search_->seedInputSegmentArrival(pin, vertex, tag_bldr_);
if (sdc_->isPathDelayInternalStartpoint(pin))
// set_min/max_delay -from internal pin.
search->makeUnclkedPaths(vertex, false, true, tag_bldr_);
if (sdc->isLeafPinClock(pin))
search_->makeUnclkedPaths(vertex, false, true, tag_bldr_);
if (sdc_->isLeafPinClock(pin))
// set_min/max_delay -to internal pin also a clock src. Bizzaroland.
// Re-seed the clock arrivals on top of the propagated paths.
search->seedClkArrivals(pin, vertex, tag_bldr_);
search_->seedClkArrivals(pin, vertex, tag_bldr_);
// Register/latch clock pin that is not connected to a declared clock.
// Seed with unclocked tag, zero arrival and allow search thru reg
// clk->q edges.
@ -1115,30 +1109,30 @@ ArrivalVisitor::visit(Vertex *vertex)
// For example, "set_max_delay -to" from an unclocked source register.
bool is_clk = tag_bldr_->hasClkTag();
if (vertex->isRegClk() && !is_clk) {
debugPrint(debug, "search", 2, "arrival seed unclked reg clk %s",
network->pathName(pin));
search->makeUnclkedPaths(vertex, true, false, tag_bldr_);
debugPrint(debug_, "search", 2, "arrival seed unclked reg clk %s",
network_->pathName(pin));
search_->makeUnclkedPaths(vertex, true, false, tag_bldr_);
}
bool arrivals_changed = search->arrivalsChanged(vertex, tag_bldr_);
bool arrivals_changed = search_->arrivalsChanged(vertex, tag_bldr_);
// If vertex is a latch data input arrival that changed from the
// previous eval pass enqueue the latch outputs to be re-evaled on the
// next pass.
if (network->isLatchData(pin)) {
if (network_->isLatchData(pin)) {
if (arrivals_changed
&& network->isLatchData(pin))
search->enqueueLatchDataOutputs(vertex);
&& network_->isLatchData(pin))
search_->enqueueLatchDataOutputs(vertex);
}
if (!search->arrivalsAtEndpointsExist()
if (!search_->arrivalsAtEndpointsExist()
|| always_to_endpoints_
|| arrivals_changed)
search->arrivalIterator()->enqueueAdjacentVertices(vertex, adj_pred_);
search_->arrivalIterator()->enqueueAdjacentVertices(vertex, adj_pred_);
if (arrivals_changed) {
debugPrint(debug, "search", 4, "arrival changed");
debugPrint(debug_, "search", 4, "arrival changed");
// Only update arrivals when delays change by more than
// fuzzyEqual can distinguish.
search->setVertexArrivals(vertex, tag_bldr_);
search->tnsInvalid(vertex);
search_->setVertexArrivals(vertex, tag_bldr_);
search_->tnsInvalid(vertex);
constrainedRequiredsInvalid(vertex, is_clk);
}
enqueueRefPinInputDelays(pin);
@ -1151,37 +1145,33 @@ void
ArrivalVisitor::constrainedRequiredsInvalid(Vertex *vertex,
bool is_clk)
{
Search *search = sta_->search();
Pin *pin = vertex->pin();
const Network *network = sta_->network();
if (network->isLoad(pin)
&& search->requiredsExist()) {
const Graph *graph = sta_->graph();
const Sdc *sdc = sta_->sdc();
if (is_clk && network->isCheckClk(pin)) {
VertexOutEdgeIterator edge_iter(vertex, graph);
if (network_->isLoad(pin)
&& search_->requiredsExist()) {
if (is_clk && network_->isCheckClk(pin)) {
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
if (edge->role()->isTimingCheck()) {
Vertex *to_vertex = edge->to(graph);
search->requiredInvalid(to_vertex);
Vertex *to_vertex = edge->to(graph_);
search_->requiredInvalid(to_vertex);
}
}
}
// Data checks (vertex does not need to be a clk).
DataCheckSet *data_checks = sdc->dataChecksFrom(pin);
DataCheckSet *data_checks = sdc_->dataChecksFrom(pin);
if (data_checks) {
for (DataCheck *data_check : *data_checks) {
Pin *to = data_check->to();
search->requiredInvalid(to);
search_->requiredInvalid(to);
}
}
// Gated clocks.
if (is_clk && sdc->gatedClkChecksEnabled()) {
if (is_clk && sdc_->gatedClkChecksEnabled()) {
PinSet enable_pins;
search->gatedClk()->gatedClkEnables(vertex, enable_pins);
search_->gatedClk()->gatedClkEnables(vertex, enable_pins);
for (Pin *enable : enable_pins)
search->requiredInvalid(enable);
search_->requiredInvalid(enable);
}
}
}
@ -1232,18 +1222,16 @@ ArrivalVisitor::visitFromToPath(const Pin *,
const MinMax *min_max,
const PathAnalysisPt *)
{
const Debug *debug = sta_->debug();
const Network *sdc_network = sta_->sdcNetwork();
debugPrint(debug, "search", 3, " %s",
from_vertex->name(sdc_network));
debugPrint(debug, "search", 3, " %s -> %s %s",
debugPrint(debug_, "search", 3, " %s",
from_vertex->name(sdc_network_));
debugPrint(debug_, "search", 3, " %s -> %s %s",
from_rf->asString(),
to_rf->asString(),
min_max->asString());
debugPrint(debug, "search", 3, " from tag: %s",
from_tag->asString(sta_));
debugPrint(debug, "search", 3, " to tag : %s",
to_tag->asString(sta_));
debugPrint(debug_, "search", 3, " from tag: %s",
from_tag->asString(this));
debugPrint(debug_, "search", 3, " to tag : %s",
to_tag->asString(this));
ClkInfo *to_clk_info = to_tag->clkInfo();
bool to_is_clk = to_tag->isClock();
Arrival arrival;
@ -1251,16 +1239,16 @@ ArrivalVisitor::visitFromToPath(const Pin *,
Tag *tag_match;
tag_bldr_->tagMatchArrival(to_tag, tag_match, arrival, arrival_index);
if (tag_match == nullptr
|| delayGreater(to_arrival, arrival, min_max, sta_)) {
debugPrint(debug, "search", 3, " %s + %s = %s %s %s",
delayAsString(from_path->arrival(sta_), sta_),
delayAsString(arc_delay, sta_),
delayAsString(to_arrival, sta_),
|| delayGreater(to_arrival, arrival, min_max, this)) {
debugPrint(debug_, "search", 3, " %s + %s = %s %s %s",
delayAsString(from_path->arrival(this), this),
delayAsString(arc_delay, this),
delayAsString(to_arrival, this),
min_max == MinMax::max() ? ">" : "<",
tag_match ? delayAsString(arrival, sta_) : "MIA");
tag_match ? delayAsString(arrival, this) : "MIA");
PathVertexRep prev_path;
if (to_tag->isClock() || to_tag->isGenClkSrcPath())
prev_path.init(from_path, sta_);
prev_path.init(from_path, this);
tag_bldr_->setMatchArrival(to_tag, tag_match,
to_arrival, arrival_index,
&prev_path);
@ -1271,7 +1259,7 @@ ArrivalVisitor::visitFromToPath(const Pin *,
tag_bldr_no_crpr_->tagMatchArrival(to_tag, tag_match,
arrival, arrival_index);
if (tag_match == nullptr
|| delayGreater(to_arrival, arrival, min_max, sta_)) {
|| delayGreater(to_arrival, arrival, min_max, this)) {
tag_bldr_no_crpr_->setMatchArrival(to_tag, tag_match,
to_arrival, arrival_index,
&prev_path);
@ -1284,9 +1272,8 @@ ArrivalVisitor::visitFromToPath(const Pin *,
void
ArrivalVisitor::pruneCrprArrivals()
{
const Debug *debug = sta_->debug();
ArrivalMap::Iterator arrival_iter(tag_bldr_->arrivalMap());
CheckCrpr *crpr = sta_->search()->checkCrpr();
CheckCrpr *crpr = search_->checkCrpr();
while (arrival_iter.hasNext()) {
Tag *tag;
int arrival_index;
@ -1294,7 +1281,7 @@ ArrivalVisitor::pruneCrprArrivals()
ClkInfo *clk_info = tag->clkInfo();
if (!tag->isClock()
&& clk_info->hasCrprClkPin()) {
PathAnalysisPt *path_ap = tag->pathAnalysisPt(sta_);
PathAnalysisPt *path_ap = tag->pathAnalysisPt(this);
const MinMax *min_max = path_ap->pathMinMax();
Tag *tag_no_crpr;
Arrival max_arrival;
@ -1307,15 +1294,15 @@ ArrivalVisitor::pruneCrprArrivals()
Arrival max_arrival_max_crpr = (min_max == MinMax::max())
? max_arrival - max_crpr
: max_arrival + max_crpr;
debugPrint(debug, "search", 4, " cmp %s %s - %s = %s",
tag->asString(sta_),
delayAsString(max_arrival, sta_),
delayAsString(max_crpr, sta_),
delayAsString(max_arrival_max_crpr, sta_));
debugPrint(debug_, "search", 4, " cmp %s %s - %s = %s",
tag->asString(this),
delayAsString(max_arrival, this),
delayAsString(max_crpr, this),
delayAsString(max_arrival_max_crpr, this));
Arrival arrival = tag_bldr_->arrival(arrival_index);
if (delayGreater(max_arrival_max_crpr, arrival, min_max, sta_)) {
debugPrint(debug, "search", 3, " pruned %s",
tag->asString(sta_));
if (delayGreater(max_arrival_max_crpr, arrival, min_max, this)) {
debugPrint(debug_, "search", 3, " pruned %s",
tag->asString(this));
tag_bldr_->deleteArrival(tag);
}
}
@ -1329,14 +1316,12 @@ ArrivalVisitor::pruneCrprArrivals()
void
ArrivalVisitor::enqueueRefPinInputDelays(const Pin *ref_pin)
{
const Sdc *sdc = sta_->sdc();
InputDelaySet *input_delays = sdc->refPinInputDelays(ref_pin);
InputDelaySet *input_delays = sdc_->refPinInputDelays(ref_pin);
if (input_delays) {
const Graph *graph = sta_->graph();
for (InputDelay *input_delay : *input_delays) {
const Pin *pin = input_delay->pin();
Vertex *vertex, *bidirect_drvr_vertex;
graph->pinVertices(pin, vertex, bidirect_drvr_vertex);
graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
seedInputDelayArrival(pin, vertex, input_delay);
if (bidirect_drvr_vertex)
seedInputDelayArrival(pin, bidirect_drvr_vertex, input_delay);
@ -1349,15 +1334,13 @@ ArrivalVisitor::seedInputDelayArrival(const Pin *pin,
Vertex *vertex,
InputDelay *input_delay)
{
TagGroupBldr tag_bldr(true, sta_);
Search *search = sta_->search();
Network *network = sta_->network();
TagGroupBldr tag_bldr(true, this);
tag_bldr.init(vertex);
search->seedInputDelayArrival(pin, vertex, input_delay,
!network->isTopLevelPort(pin), &tag_bldr);
search->setVertexArrivals(vertex, &tag_bldr);
search->arrivalIterator()->enqueueAdjacentVertices(vertex,
search->searchAdj());
search_->seedInputDelayArrival(pin, vertex, input_delay,
!network_->isTopLevelPort(pin), &tag_bldr);
search_->setVertexArrivals(vertex, &tag_bldr);
search_->arrivalIterator()->enqueueAdjacentVertices(vertex,
search_->searchAdj());
}
void
@ -1958,15 +1941,15 @@ Search::inputDelayTag(const Pin *pin,
////////////////////////////////////////////////////////////////
PathVisitor::PathVisitor(const StaState *sta) :
pred_(sta->search()->evalPred()),
sta_(sta)
StaState(sta),
pred_(sta->search()->evalPred())
{
}
PathVisitor::PathVisitor(SearchPred *pred,
const StaState *sta) :
pred_(pred),
sta_(sta)
StaState(sta),
pred_(pred)
{
}
@ -1974,11 +1957,10 @@ void
PathVisitor::visitFaninPaths(Vertex *to_vertex)
{
if (pred_->searchTo(to_vertex)) {
const Graph *graph = sta_->graph();
VertexInEdgeIterator edge_iter(to_vertex, graph);
VertexInEdgeIterator edge_iter(to_vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *from_vertex = edge->from(graph);
Vertex *from_vertex = edge->from(graph_);
const Pin *from_pin = from_vertex->pin();
if (pred_->searchFrom(from_vertex)
&& pred_->searchThru(edge)) {
@ -1995,16 +1977,15 @@ PathVisitor::visitFanoutPaths(Vertex *from_vertex)
{
const Pin *from_pin = from_vertex->pin();
if (pred_->searchFrom(from_vertex)) {
const Graph *graph = sta_->graph();
VertexOutEdgeIterator edge_iter(from_vertex, graph);
VertexOutEdgeIterator edge_iter(from_vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *to_vertex = edge->to(graph);
Vertex *to_vertex = edge->to(graph_);
const Pin *to_pin = to_vertex->pin();
if (pred_->searchTo(to_vertex)
&& pred_->searchThru(edge)) {
debugPrint(sta_->debug(), "search", 3,
" %s", to_vertex->name(sta_->network()));
debugPrint(debug_, "search", 3, " %s",
to_vertex->name(network_));
if (!visitEdge(from_pin, from_vertex, edge, to_pin, to_vertex))
break;
}
@ -2019,16 +2000,15 @@ PathVisitor::visitEdge(const Pin *from_pin,
const Pin *to_pin,
Vertex *to_vertex)
{
Search *search = sta_->search();
TagGroup *from_tag_group = search->tagGroup(from_vertex);
TagGroup *from_tag_group = search_->tagGroup(from_vertex);
if (from_tag_group) {
TimingArcSet *arc_set = edge->timingArcSet();
VertexPathIterator from_iter(from_vertex, search);
VertexPathIterator from_iter(from_vertex, search_);
while (from_iter.hasNext()) {
PathVertex *from_path = from_iter.next();
PathAnalysisPt *path_ap = from_path->pathAnalysisPt(sta_);
PathAnalysisPt *path_ap = from_path->pathAnalysisPt(this);
const MinMax *min_max = path_ap->pathMinMax();
const RiseFall *from_rf = from_path->transition(sta_);
const RiseFall *from_rf = from_path->transition(this);
TimingArc *arc1, *arc2;
arc_set->arcsFrom(from_rf, arc1, arc2);
if (!visitArc(from_pin, from_vertex, from_rf, from_path,
@ -2079,27 +2059,23 @@ PathVisitor::visitFromPath(const Pin *from_pin,
const MinMax *min_max,
const PathAnalysisPt *path_ap)
{
Network *network = sta_->network();
Sdc *sdc = sta_->sdc();
Search *search = sta_->search();
Latches *latches = sta_->latches();
const TimingRole *role = edge->role();
Tag *from_tag = from_path->tag(sta_);
Tag *from_tag = from_path->tag(this);
ClkInfo *from_clk_info = from_tag->clkInfo();
Tag *to_tag = nullptr;
ClockEdge *clk_edge = from_clk_info->clkEdge();
Clock *clk = from_clk_info->clock();
Arrival from_arrival = from_path->arrival(sta_);
Arrival from_arrival = from_path->arrival(this);
ArcDelay arc_delay = 0.0;
Arrival to_arrival;
if (from_clk_info->isGenClkSrcPath()) {
if (!sdc->clkStopPropagation(clk,from_pin,from_rf,to_pin,to_rf)
&& (sdc->clkThruTristateEnabled()
if (!sdc_->clkStopPropagation(clk,from_pin,from_rf,to_pin,to_rf)
&& (sdc_->clkThruTristateEnabled()
|| !(role == TimingRole::tristateEnable()
|| role == TimingRole::tristateDisable()))) {
Clock *gclk = from_tag->genClkSrcPathClk(sta_);
Clock *gclk = from_tag->genClkSrcPathClk(this);
if (gclk) {
Genclks *genclks = search->genclks();
Genclks *genclks = search_->genclks();
VertexSet *fanins = genclks->fanins(gclk);
// Note: encountering a latch d->q edge means find the
// latch feedback edges, but they are referenced for
@ -2112,20 +2088,20 @@ PathVisitor::visitFromPath(const Pin *from_pin,
|| !gclk->combinational())
&& fanins->hasKey(to_vertex)
&& !(fdbk_edges && fdbk_edges->hasKey(edge))) {
to_tag = search->thruClkTag(from_path, from_tag, true, edge, to_rf,
min_max, path_ap);
to_tag = search_->thruClkTag(from_path, from_tag, true, edge, to_rf,
min_max, path_ap);
if (to_tag) {
arc_delay = search->deratedDelay(from_vertex, arc, edge, true,
path_ap);
arc_delay = search_->deratedDelay(from_vertex, arc, edge, true,
path_ap);
to_arrival = from_arrival + arc_delay;
}
}
}
else {
// PLL out to feedback path.
to_tag = search->thruTag(from_tag, edge, to_rf, min_max, path_ap);
to_tag = search_->thruTag(from_tag, edge, to_rf, min_max, path_ap);
if (to_tag) {
arc_delay = search->deratedDelay(from_vertex, arc, edge, true,
arc_delay = search_->deratedDelay(from_vertex, arc, edge, true,
path_ap);
to_arrival = from_arrival + arc_delay;
}
@ -2134,30 +2110,30 @@ PathVisitor::visitFromPath(const Pin *from_pin,
}
else if (role->genericRole() == TimingRole::regClkToQ()) {
if (clk == nullptr
|| !sdc->clkStopPropagation(from_pin, clk)) {
arc_delay = search->deratedDelay(from_vertex, arc, edge, false, path_ap);
|| !sdc_->clkStopPropagation(from_pin, clk)) {
arc_delay = search_->deratedDelay(from_vertex, arc, edge, false, path_ap);
// Propagate from unclocked reg/latch clk pins, which have no
// clk but are distinguished with a segment_start flag.
if ((clk_edge == nullptr
&& from_tag->isSegmentStart())
// Do not propagate paths from input ports with default
// input arrival clk thru CLK->Q edges.
|| (clk != sdc->defaultArrivalClock()
|| (clk != sdc_->defaultArrivalClock()
// Only propagate paths from clocks that have not
// passed thru reg/latch D->Q edges.
&& from_tag->isClock())) {
const RiseFall *clk_rf = clk_edge ? clk_edge->transition() : nullptr;
ClkInfo *to_clk_info = from_clk_info;
if (network->direction(to_pin)->isInternal())
to_clk_info = search->clkInfoWithCrprClkPath(from_clk_info,
from_path, path_ap);
to_tag = search->fromRegClkTag(from_pin, from_rf, clk, clk_rf,
to_clk_info, to_pin, to_rf, min_max,
path_ap);
if (network_->direction(to_pin)->isInternal())
to_clk_info = search_->clkInfoWithCrprClkPath(from_clk_info,
from_path, path_ap);
to_tag = search_->fromRegClkTag(from_pin, from_rf, clk, clk_rf,
to_clk_info, to_pin, to_rf, min_max,
path_ap);
if (to_tag)
to_tag = search->thruTag(to_tag, edge, to_rf, min_max, path_ap);
from_arrival = search->clkPathArrival(from_path, from_clk_info,
clk_edge, min_max, path_ap);
to_tag = search_->thruTag(to_tag, edge, to_rf, min_max, path_ap);
from_arrival = search_->clkPathArrival(from_path, from_clk_info,
clk_edge, min_max, path_ap);
to_arrival = from_arrival + arc_delay;
}
else
@ -2166,43 +2142,43 @@ PathVisitor::visitFromPath(const Pin *from_pin,
}
else if (edge->role() == TimingRole::latchDtoQ()) {
if (min_max == MinMax::max()) {
arc_delay = search->deratedDelay(from_vertex, arc, edge, false, path_ap);
latches->latchOutArrival(from_path, arc, edge, path_ap,
to_tag, arc_delay, to_arrival);
arc_delay = search_->deratedDelay(from_vertex, arc, edge, false, path_ap);
latches_->latchOutArrival(from_path, arc, edge, path_ap,
to_tag, arc_delay, to_arrival);
if (to_tag)
to_tag = search->thruTag(to_tag, edge, to_rf, min_max, path_ap);
to_tag = search_->thruTag(to_tag, edge, to_rf, min_max, path_ap);
}
}
else if (from_tag->isClock()) {
ClockSet *clks = sdc->findLeafPinClocks(from_pin);
ClockSet *clks = sdc_->findLeafPinClocks(from_pin);
// Disable edges from hierarchical clock source pins that do
// not go thru the hierarchical pin and edges from clock source pins
// that traverse a hierarchical source pin of a different clock.
// Clock arrivals used as data also need to be disabled.
if (!(role == TimingRole::wire()
&& sdc->clkDisabledByHpinThru(clk, from_pin, to_pin))
&& sdc_->clkDisabledByHpinThru(clk, from_pin, to_pin))
// Generated clock source pins have arrivals for the source clock.
// Do not propagate them past the generated clock source pin.
&& !(clks
&& !clks->hasKey(from_tag->clock()))) {
// Propagate arrival as non-clock at the end of the clock tree.
bool to_propagates_clk =
!sdc->clkStopPropagation(clk,from_pin,from_rf,to_pin,to_rf)
&& (sdc->clkThruTristateEnabled()
!sdc_->clkStopPropagation(clk,from_pin,from_rf,to_pin,to_rf)
&& (sdc_->clkThruTristateEnabled()
|| !(role == TimingRole::tristateEnable()
|| role == TimingRole::tristateDisable()));
arc_delay = search->deratedDelay(from_vertex, arc, edge,
to_propagates_clk, path_ap);
to_tag = search->thruClkTag(from_path, from_tag, to_propagates_clk,
edge, to_rf, min_max, path_ap);
arc_delay = search_->deratedDelay(from_vertex, arc, edge,
to_propagates_clk, path_ap);
to_tag = search_->thruClkTag(from_path, from_tag, to_propagates_clk,
edge, to_rf, min_max, path_ap);
to_arrival = from_arrival + arc_delay;
}
}
else {
arc_delay = search->deratedDelay(from_vertex, arc, edge, false, path_ap);
arc_delay = search_->deratedDelay(from_vertex, arc, edge, false, path_ap);
if (!delayEqual(arc_delay, min_max->initValue())) {
to_arrival = from_arrival + arc_delay;
to_tag = search->thruTag(from_tag, edge, to_rf, min_max, path_ap);
to_tag = search_->thruTag(from_tag, edge, to_rf, min_max, path_ap);
}
}
if (to_tag)
@ -3402,30 +3378,28 @@ RequiredVisitor::~RequiredVisitor()
VertexVisitor *
RequiredVisitor::copy() const
{
return new RequiredVisitor(sta_);
return new RequiredVisitor(this);
}
void
RequiredVisitor::visit(Vertex *vertex)
{
Search *search = sta_->search();
const Debug *debug = sta_->debug();
debugPrint(debug, "search", 2, "find required %s",
vertex->name(sta_->network()));
required_cmp_->requiredsInit(vertex, sta_);
debugPrint(debug_, "search", 2, "find required %s",
vertex->name(network_));
required_cmp_->requiredsInit(vertex, this);
vertex->setRequiredsPruned(false);
// Back propagate requireds from fanout.
visitFanoutPaths(vertex);
// Check for constraints at endpoints that set required times.
if (search->isEndpoint(vertex)) {
FindEndRequiredVisitor seeder(required_cmp_, sta_);
if (search_->isEndpoint(vertex)) {
FindEndRequiredVisitor seeder(required_cmp_, this);
visit_path_ends_->visitPathEnds(vertex, &seeder);
}
bool changed = required_cmp_->requiredsSave(vertex, sta_);
search->tnsInvalid(vertex);
bool changed = required_cmp_->requiredsSave(vertex, this);
search_->tnsInvalid(vertex);
if (changed)
search->requiredIterator()->enqueueAdjacentVertices(vertex);
search_->requiredIterator()->enqueueAdjacentVertices(vertex);
}
bool
@ -3446,58 +3420,57 @@ RequiredVisitor::visitFromToPath(const Pin *,
{
// Don't propagate required times through latch D->Q edges.
if (edge->role() != TimingRole::latchDtoQ()) {
const Debug *debug = sta_->debug();
debugPrint(debug, "search", 3, " %s -> %s %s",
debugPrint(debug_, "search", 3, " %s -> %s %s",
from_rf->asString(),
to_rf->asString(),
min_max->asString());
debugPrint(debug, "search", 3, " from tag %2u: %s",
debugPrint(debug_, "search", 3, " from tag %2u: %s",
from_tag->index(),
from_tag->asString(sta_));
from_tag->asString(this));
int arrival_index;
bool arrival_exists;
from_path->arrivalIndex(arrival_index, arrival_exists);
const MinMax *req_min = min_max->opposite();
TagGroup *to_tag_group = sta_->search()->tagGroup(to_vertex);
TagGroup *to_tag_group = search_->tagGroup(to_vertex);
// Check to see if to_tag was pruned.
if (to_tag_group && to_tag_group->hasTag(to_tag)) {
PathVertex to_path(to_vertex, to_tag, sta_);
Required to_required = to_path.required(sta_);
PathVertex to_path(to_vertex, to_tag, this);
Required to_required = to_path.required(this);
Required from_required = to_required - arc_delay;
debugPrint(debug, "search", 3, " to tag %2u: %s",
debugPrint(debug_, "search", 3, " to tag %2u: %s",
to_tag->index(),
to_tag->asString(sta_));
debugPrint(debug, "search", 3, " %s - %s = %s %s %s",
delayAsString(to_required, sta_),
delayAsString(arc_delay, sta_),
delayAsString(from_required, sta_),
to_tag->asString(this));
debugPrint(debug_, "search", 3, " %s - %s = %s %s %s",
delayAsString(to_required, this),
delayAsString(arc_delay, this),
delayAsString(from_required, this),
min_max == MinMax::max() ? "<" : ">",
delayAsString(required_cmp_->required(arrival_index), sta_));
required_cmp_->requiredSet(arrival_index, from_required, req_min, sta_);
delayAsString(required_cmp_->required(arrival_index), this));
required_cmp_->requiredSet(arrival_index, from_required, req_min, this);
}
else {
if (sta_->search()->crprApproxMissingRequireds()) {
if (search_->crprApproxMissingRequireds()) {
// Arrival on to_vertex that differs by crpr_pin was pruned.
// Find an arrival that matches everything but the crpr_pin
// as an appromate required.
VertexPathIterator to_iter(to_vertex, to_rf, path_ap, sta_);
VertexPathIterator to_iter(to_vertex, to_rf, path_ap, this);
while (to_iter.hasNext()) {
PathVertex *to_path = to_iter.next();
Tag *to_path_tag = to_path->tag(sta_);
Tag *to_path_tag = to_path->tag(this);
if (tagMatchNoCrpr(to_path_tag, to_tag)) {
Required to_required = to_path->required(sta_);
Required to_required = to_path->required(this);
Required from_required = to_required - arc_delay;
debugPrint(debug, "search", 3, " to tag %2u: %s",
debugPrint(debug_, "search", 3, " to tag %2u: %s",
to_path_tag->index(),
to_path_tag->asString(sta_));
debugPrint(debug, "search", 3, " %s - %s = %s %s %s",
delayAsString(to_required, sta_),
delayAsString(arc_delay, sta_),
delayAsString(from_required, sta_),
to_path_tag->asString(this));
debugPrint(debug_, "search", 3, " %s - %s = %s %s %s",
delayAsString(to_required, this),
delayAsString(arc_delay, this),
delayAsString(from_required, this),
min_max == MinMax::max() ? "<" : ">",
delayAsString(required_cmp_->required(arrival_index),
sta_));
required_cmp_->requiredSet(arrival_index, from_required, req_min, sta_);
this));
required_cmp_->requiredSet(arrival_index, from_required, req_min, this);
break;
}
}

View File

@ -231,8 +231,8 @@ PathGroupPathVisitor::~PathGroupPathVisitor()
VertexVisitor *
PathGroupPathVisitor::copy() const
{
return new PathGroupPathVisitor(visitor_, bkwd_iter_, matching_path_map_,
sta_);
return new PathGroupPathVisitor(visitor_, bkwd_iter_,
matching_path_map_, this);
}
void
@ -241,9 +241,8 @@ PathGroupPathVisitor::visit(Vertex *vertex)
vertex_matches_ = false;
visitFanoutPaths(vertex);
if (vertex_matches_) {
const Debug *debug = sta_->debug();
debugPrint(debug, "visit_path_group", 1, "visit %s",
vertex->name(sta_->network()));
debugPrint(debug_, "visit_path_group", 1, "visit %s",
vertex->name(network_));
visitor_->visit(vertex);
bkwd_iter_->enqueueAdjacentVertices(vertex);
}
@ -270,31 +269,29 @@ PathGroupPathVisitor::visitFromToPath(const Pin *,
int arrival_index;
bool arrival_exists;
from_path->arrivalIndex(arrival_index, arrival_exists);
PathVertex to_path(to_vertex, to_tag, sta_);
PathVertex to_path(to_vertex, to_tag, this);
if (!to_path.isNull()) {
if (matching_paths->hasKey(&to_path)) {
const Debug *debug = sta_->debug();
debugPrint(debug, "visit_path_group", 2, "match %s %s -> %s %s",
from_vertex->name(sta_->network()),
from_tag->asString(sta_),
to_vertex->name(sta_->network()),
to_tag->asString(sta_));
debugPrint(debug_, "visit_path_group", 2, "match %s %s -> %s %s",
from_vertex->name(network_),
from_tag->asString(this),
to_vertex->name(network_),
to_tag->asString(this));
fromMatches(from_vertex, from_tag, arrival_index);
}
}
else {
VertexPathIterator to_iter(to_vertex, to_rf, path_ap, sta_);
VertexPathIterator to_iter(to_vertex, to_rf, path_ap, this);
while (to_iter.hasNext()) {
PathVertex *to_path = to_iter.next();
if (tagMatchNoCrpr(to_path->tag(sta_), to_tag)
if (tagMatchNoCrpr(to_path->tag(this), to_tag)
&& matching_paths->hasKey(to_path)) {
const Debug *debug = sta_->debug();
debugPrint(debug, "visit_path_group", 2,
debugPrint(debug_, "visit_path_group", 2,
"match crpr %s %s -> %s %s",
from_vertex->name(sta_->network()),
from_tag->asString(sta_),
to_vertex->name(sta_->network()),
to_tag->asString(sta_));
from_vertex->name(network_),
from_tag->asString(this),
to_vertex->name(network_),
to_tag->asString(this));
fromMatches(from_vertex, from_tag, arrival_index);
}
}
@ -310,7 +307,7 @@ PathGroupPathVisitor::fromMatches(Vertex *from_vertex,
{
vertex_matches_ = true;
vertexPathSetMapInsertPath(matching_path_map_, from_vertex,
from_tag, from_arrival_index, sta_);
from_tag, from_arrival_index, this);
}
} // namespace