diff --git a/dcalc/GraphDelayCalc1.cc b/dcalc/GraphDelayCalc1.cc index 5ff10c9a..0164b126 100644 --- a/dcalc/GraphDelayCalc1.cc +++ b/dcalc/GraphDelayCalc1.cc @@ -657,7 +657,8 @@ GraphDelayCalc1::seedNoDrvrCellSlew(Vertex *drvr_vertex, drive_delay = cap * drive_res; slew = cap * drive_res; } - if (!drvr_vertex->slewAnnotated(tr, ap_index)) + const MinMax *slew_min_max = dcalc_ap->slewMinMax(); + if (!drvr_vertex->slewAnnotated(tr, slew_min_max)) graph_->setSlew(drvr_vertex, tr, ap_index, slew); arc_delay_calc->inputPortDelay(drvr_pin, delayAsFloat(slew), tr, parasitic, dcalc_ap); @@ -674,6 +675,7 @@ GraphDelayCalc1::seedNoDrvrSlew(Vertex *drvr_vertex, DcalcAnalysisPt *dcalc_ap, ArcDelayCalc *arc_delay_calc) { + const MinMax *slew_min_max = dcalc_ap->slewMinMax(); DcalcAPIndex ap_index = dcalc_ap->index(); Slew slew(default_slew); // Top level bidirect driver uses load slew unless @@ -682,7 +684,7 @@ GraphDelayCalc1::seedNoDrvrSlew(Vertex *drvr_vertex, Vertex *load_vertex = graph_->pinLoadVertex(drvr_pin); slew = graph_->slew(load_vertex, tr, ap_index); } - if (!drvr_vertex->slewAnnotated(tr, ap_index)) + if (!drvr_vertex->slewAnnotated(tr, slew_min_max)) graph_->setSlew(drvr_vertex, tr, ap_index, slew); Parasitic *parasitic; bool delete_parasitic; @@ -711,8 +713,7 @@ GraphDelayCalc1::seedLoadSlew(Vertex *vertex) while (ap_iter.hasNext()) { DcalcAnalysisPt *dcalc_ap = ap_iter.next(); const MinMax *slew_min_max = dcalc_ap->slewMinMax(); - DcalcAPIndex ap_index = dcalc_ap->index(); - if (!vertex->slewAnnotated(tr, ap_index)) { + if (!vertex->slewAnnotated(tr, slew_min_max)) { float slew = 0.0; if (clks) { slew = slew_min_max->initValue(); @@ -724,6 +725,7 @@ GraphDelayCalc1::seedLoadSlew(Vertex *vertex) slew = clk_slew; } } + DcalcAPIndex ap_index = dcalc_ap->index(); graph_->setSlew(vertex, tr, ap_index, slew); } } @@ -988,11 +990,12 @@ GraphDelayCalc1::initRootSlews(Vertex *vertex) DcalcAnalysisPtIterator ap_iter(this); while (ap_iter.hasNext()) { DcalcAnalysisPt *dcalc_ap = ap_iter.next(); + const MinMax *slew_min_max = dcalc_ap->slewMinMax(); DcalcAPIndex ap_index = dcalc_ap->index(); TransRiseFallIterator tr_iter; while (tr_iter.hasNext()) { TransRiseFall *tr = tr_iter.next(); - if (!vertex->slewAnnotated(tr, ap_index)) + if (!vertex->slewAnnotated(tr, slew_min_max)) graph_->setSlew(vertex, tr, ap_index, default_slew); } } @@ -1181,9 +1184,10 @@ GraphDelayCalc1::initSlew(Vertex *vertex) while (ap_iter.hasNext()) { DcalcAnalysisPt *dcalc_ap = ap_iter.next(); const MinMax *slew_min_max = dcalc_ap->slewMinMax(); - DcalcAPIndex ap_index = dcalc_ap->index(); - if (!vertex->slewAnnotated(tr, ap_index)) + if (!vertex->slewAnnotated(tr, slew_min_max)) { + DcalcAPIndex ap_index = dcalc_ap->index(); graph_->setSlew(vertex, tr, ap_index, slew_min_max->initValue()); + } } } } @@ -1213,7 +1217,7 @@ GraphDelayCalc1::initWireDelays(Vertex *drvr_vertex, graph_->setWireArcDelay(wire_edge, tr, ap_index, delay_init_value); // Init load vertex slew. if (init_load_slews - && !load_vertex->slewAnnotated(tr, ap_index)) + && !load_vertex->slewAnnotated(tr, slew_min_max)) graph_->setSlew(load_vertex, tr, ap_index, slew_init_value); } } @@ -1278,8 +1282,9 @@ GraphDelayCalc1::findArcDelay(LibertyCell *drvr_cell, delayAsString(gate_slew, this)); // Merge slews. const Slew &drvr_slew = graph_->slew(drvr_vertex, drvr_tr, ap_index); + const MinMax *slew_min_max = dcalc_ap->slewMinMax(); if (delayFuzzyGreater(gate_slew, drvr_slew, dcalc_ap->slewMinMax()) - && !drvr_vertex->slewAnnotated(drvr_tr, ap_index)) + && !drvr_vertex->slewAnnotated(drvr_tr, slew_min_max)) graph_->setSlew(drvr_vertex, drvr_tr, ap_index, gate_slew); if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) { const ArcDelay &prev_gate_delay = graph_->arcDelay(edge,arc,ap_index); @@ -1479,8 +1484,8 @@ GraphDelayCalc1::annotateLoadDelays(Vertex *drvr_vertex, load_vertex->name(sdc_network_), delayAsString(wire_delay, this), delayAsString(load_slew, this)); - if (!load_vertex->slewAnnotated(drvr_tr, ap_index)) { - if (drvr_vertex->slewAnnotated(drvr_tr, ap_index)) { + if (!load_vertex->slewAnnotated(drvr_tr, slew_min_max)) { + if (drvr_vertex->slewAnnotated(drvr_tr, slew_min_max)) { // Copy the driver slew to the load if it is annotated. const Slew &drvr_slew = graph_->slew(drvr_vertex,drvr_tr,ap_index); graph_->setSlew(load_vertex, drvr_tr, ap_index, drvr_slew); diff --git a/graph/Graph.cc b/graph/Graph.cc index f83075d5..4066f0d3 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -830,10 +830,14 @@ Graph::arcDelayAnnotated(Edge *edge, TimingArc *arc, DcalcAPIndex ap_index) const { - unsigned index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index; - if (index >= arc_delay_annotated_.size()) - internalError("arc_delay_annotated array bounds exceeded"); - return arc_delay_annotated_[index]; + if (arc_delay_annotated_.size()) { + unsigned index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index; + if (index >= arc_delay_annotated_.size()) + internalError("arc_delay_annotated array bounds exceeded"); + return arc_delay_annotated_[index]; + } + else + return false; } void @@ -1162,6 +1166,8 @@ Vertex::init(Pin *pin, color_ = vertex_color_white; level_ = 0; bfs_in_queue_ = 0; + crpr_path_pruning_disabled_ = false; + requireds_pruned_ = false; } const char * @@ -1191,13 +1197,9 @@ Vertex::setColor(VertexColor color) bool Vertex::slewAnnotated(const TransRiseFall *tr, - DcalcAPIndex ap_index) const + const MinMax *min_max) const { - // Track rise/fall/min/max annotations separately, but after that - // only rise/fall. - if (ap_index > 1) - ap_index = 0; - int index = ap_index * transitionCount() + tr->index(); + int index = min_max->index() * transitionCount() + tr->index(); return ((1 << index) & slew_annotated_) != 0; } @@ -1229,6 +1231,18 @@ Vertex::removeSlewAnnotated() slew_annotated_ = 0; } +void +Vertex::setCrprPathPruningDisabled(bool disabled) +{ + crpr_path_pruning_disabled_ = disabled; +} + +void +Vertex::setRequiredsPruned(bool pruned) +{ + requireds_pruned_ = pruned; +} + TagGroupIndex Vertex::tagGroupIndex() const { diff --git a/graph/Graph.hh b/graph/Graph.hh index 101a1fe3..68176e62 100644 --- a/graph/Graph.hh +++ b/graph/Graph.hh @@ -284,7 +284,7 @@ public: void setTagGroupIndex(TagGroupIndex tag_index); // Slew is annotated by sdc set_annotated_transition cmd. bool slewAnnotated(const TransRiseFall *tr, - DcalcAPIndex ap_index) const; + const MinMax *min_max) const; // True if any rise/fall analysis pt slew is annotated. bool slewAnnotated() const; void setSlewAnnotated(bool annotated, @@ -316,6 +316,11 @@ public: bool bfsInQueue(BfsIndex index) const; void setBfsInQueue(BfsIndex index, bool value); bool isRegClk() const { return is_reg_clk_; } + bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;} + void setCrprPathPruningDisabled(bool disabled); + bool requiredsPruned() const { return requireds_pruned_; } + void setRequiredsPruned(bool pruned); + static int transitionCount() { return 2; } // rise/fall protected: @@ -328,14 +333,23 @@ protected: PathVertexRep *prev_paths_; EdgeIndex in_edges_; // Edges to this vertex. EdgeIndex out_edges_; // Edges from this vertex. - unsigned int tag_group_index_:tag_group_index_bits; + + // 4 bytes + unsigned int tag_group_index_:tag_group_index_bits; // 24 + // Each bit corresponds to a different BFS queue. + unsigned int bfs_in_queue_:bfs_index_bits; // 4 + unsigned int slew_annotated_:slew_annotated_bits; + + // 4 bytes (32 bits) + unsigned int level_:16; + // Levelization search state. + unsigned int color_:2; + unsigned int sim_value_:3; // LogicValue bool has_requireds_:1; - unsigned int slew_annotated_:4; // Bidirect pins have two vertices. // This flag distinguishes the driver and load vertices. bool is_bidirect_drvr_:1; bool is_reg_clk_:1; - unsigned int sim_value_:3; // LogicValue bool is_disabled_constraint_:1; bool is_gated_clk_enable_:1; // Constrained by timing check edge. @@ -344,11 +358,8 @@ protected: bool is_check_clk_:1; bool is_constrained_:1; bool has_downstream_clk_pin_:1; - // Levelization search state. - unsigned int color_:2; - unsigned int level_:16; - // Each bit corresponds to a different BFS queue. - unsigned int bfs_in_queue_:bfs_index_bits; + bool crpr_path_pruning_disabled_:1; + bool requireds_pruned_:1; private: DISALLOW_COPY_AND_ASSIGN(Vertex); diff --git a/graph/GraphClass.hh b/graph/GraphClass.hh index dc24bc75..d5f03d72 100644 --- a/graph/GraphClass.hh +++ b/graph/GraphClass.hh @@ -20,6 +20,8 @@ #include "ObjectIndex.hh" #include "Set.hh" #include "Vector.hh" +#include "MinMax.hh" +#include "Transition.hh" namespace sta { @@ -47,6 +49,7 @@ typedef Vector GraphLoopSeq; // 16,777,215 tags static const int tag_group_index_bits = 24; static const TagGroupIndex tag_group_index_max = (1<clear(); deleteFilter(); - arrivals_exist_ = false; arrivals_at_endpoints_exist_ = false; arrivals_seeded_ = false; requireds_exist_ = false; @@ -1096,8 +1094,11 @@ ArrivalVisitor::visit(Vertex *vertex) visitFaninPaths(vertex); if (crpr_active_ && search->crprPathPruningEnabled() + && !vertex->crprPathPruningDisabled() && !has_fanin_one_) pruneCrprArrivals(); + vertex->setCrprPathPruningDisabled(false); + // Insert paths that originate here but if (!network->isTopLevelPort(pin) && sdc->hasInputDelay(pin)) @@ -2769,7 +2770,6 @@ Search::setVertexArrivals(Vertex *vertex, vertex->setArrivals(arrivals); vertex->setPrevPaths(prev_paths); - have_paths_ = true; if (has_requireds) { requiredInvalid(vertex); vertex->setHasRequireds(false); @@ -3472,6 +3472,7 @@ RequiredVisitor::visit(Vertex *vertex) debugPrint1(debug, "search", 2, "find required %s\n", vertex->name(sta_->network())); required_cmp_->requiredsInit(vertex, sta_); + vertex->setRequiredsPruned(false); // Back propagate requireds from fanout. visitFanoutPaths(vertex); // Check for constraints at endpoints that set required times. @@ -3488,7 +3489,7 @@ RequiredVisitor::visit(Vertex *vertex) bool RequiredVisitor::visitFromToPath(const Pin *, - Vertex *, + Vertex *from_vertex, const TransRiseFall *from_tr, Tag *from_tag, PathVertex *from_path, @@ -3500,7 +3501,7 @@ RequiredVisitor::visitFromToPath(const Pin *, Tag *to_tag, Arrival &, const MinMax *min_max, - const PathAnalysisPt *path_ap) + const PathAnalysisPt *) { // Don't propagate required times through latch D->Q edges. if (edge->role() != TimingRole::latchDtoQ()) { @@ -3533,31 +3534,11 @@ RequiredVisitor::visitFromToPath(const Pin *, delayAsString(required_cmp_->required(arrival_index), sta_)); required_cmp_->requiredSet(arrival_index, from_required, req_min); } - else { - // Arrival that differ by crpr_pin may be pruned. Find an arrival - // that matches everything but the crpr_pin. - VertexPathIterator to_iter(to_vertex, to_tr, path_ap, sta_); - while (to_iter.hasNext()) { - PathVertex *to_path = to_iter.next(); - Tag *to_path_tag = to_path->tag(sta_); - if (tagMatchNoCrpr(to_path_tag, to_tag)) { - Required to_required = to_path->required(sta_); - Required from_required = to_required - arc_delay; - debugPrint2(debug, "search", 3, " to tag %2u: %s\n", - to_path_tag->index(), - to_path_tag->asString(sta_)); - debugPrint5(debug, "search", 3, " %s - %s = %s %s %s\n", - delayAsString(to_required, sta_), - delayAsString(arc_delay, sta_), - delayAsString(from_required, sta_), - min_max == MinMax::max() ? "<" : ">", - delayAsString(required_cmp_->required(arrival_index), - sta_)); - required_cmp_->requiredSet(arrival_index, from_required, req_min); - break; - } - } - } + else + from_vertex->setRequiredsPruned(true); + // Propagate requireds pruned flag backwards. + if (to_vertex->requiredsPruned()) + from_vertex->setRequiredsPruned(true); } return true; } diff --git a/search/Search.hh b/search/Search.hh index 2a0dd07b..6ba30180 100644 --- a/search/Search.hh +++ b/search/Search.hh @@ -525,7 +525,6 @@ protected: // findPathEnds arg. bool unconstrained_paths_; - bool have_paths_; // Search predicates. SearchPred *search_adj_; SearchPred *search_clk_; diff --git a/search/Sta.cc b/search/Sta.cc index 768b7f9f..53b03554 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2713,7 +2713,7 @@ Sta::vertexArrival(Vertex *vertex, search_->findArrivals(vertex->level()); const MinMax *min_max = path_ap->pathMinMax(); Arrival arrival = min_max->initValue(); - VertexPathIterator path_iter(vertex, tr, path_ap, search_); + VertexPathIterator path_iter(vertex, tr, path_ap, this); while (path_iter.hasNext()) { Path *path = path_iter.next(); const Arrival &path_arrival = path->arrival(this); @@ -2744,7 +2744,7 @@ Sta::vertexRequired(Vertex *vertex, findRequired(vertex); const MinMax *min_max = path_ap->pathMinMax()->opposite(); Required required = min_max->initValue(); - VertexPathIterator path_iter(vertex, tr, path_ap, search_); + VertexPathIterator path_iter(vertex, tr, path_ap, this); while (path_iter.hasNext()) { const Path *path = path_iter.next(); const Required path_required = path->required(this); @@ -2794,7 +2794,7 @@ Sta::vertexSlack(Vertex *vertex, findRequired(vertex); MinMax *min = MinMax::min(); Slack slack = min->initValue(); - VertexPathIterator path_iter(vertex, search_); + VertexPathIterator path_iter(vertex, this); while (path_iter.hasNext()) { Path *path = path_iter.next(); if (path->minMax(this) == min_max) { @@ -2813,7 +2813,7 @@ Sta::vertexSlack(Vertex *vertex, { findRequired(vertex); Slack slack = MinMax::min()->initValue(); - VertexPathIterator path_iter(vertex, tr, min_max, search_); + VertexPathIterator path_iter(vertex, tr, min_max, this); while (path_iter.hasNext()) { Path *path = path_iter.next(); Slack path_slack = path->slack(this); @@ -2850,7 +2850,7 @@ Sta::vertexSlack1(Vertex *vertex, { MinMax *min = MinMax::min(); Slack slack = min->initValue(); - VertexPathIterator path_iter(vertex, tr, path_ap, search_); + VertexPathIterator path_iter(vertex, tr, path_ap, this); while (path_iter.hasNext()) { Path *path = path_iter.next(); Slack path_slack = path->slack(this); @@ -2868,6 +2868,44 @@ Sta::findRequired(Vertex *vertex) searchPreamble(); search_->findAllArrivals(); search_->findRequireds(vertex->level()); + if (sdc_->crprEnabled() + && vertex->requiredsPruned()) { + debugPrint1(debug_, "search", 2, "resurrect pruned required %s\n", + vertex->name(sdc_network_)); + // printf("resurrect pruned required %s\n", vertex->name(sdc_network_)); + // Invalidate arrivals and requireds and disable + // path pruning on fanout vertices. + int fanout = 0; + disableFanoutCrprPruning(vertex, fanout); + // if (fanout > 100) + // printf("fanout %s %d\n", vertex->name(network_), fanout); + // Find fanout arrivals and requireds with pruning disabled. + search_->findArrivals(); + search_->findRequireds(vertex->level()); + } +} + +// DFS to invalidate arrivals and requireds to +// find arrivals with pruning disabled. +void +Sta::disableFanoutCrprPruning(Vertex *vertex, + int &fanout) +{ + if (!vertex->crprPathPruningDisabled()) { + search_->arrivalInvalid(vertex); + search_->requiredInvalid(vertex); + vertex->setCrprPathPruningDisabled(true); + fanout++; + SearchPred *pred = search_->searchAdj(); + VertexOutEdgeIterator edge_iter(vertex, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + Vertex *to_vertex = edge->to(graph_); + if (pred->searchThru(edge) + && pred->searchTo(to_vertex)) + disableFanoutCrprPruning(to_vertex, fanout); + } + } } Slack diff --git a/search/Sta.hh b/search/Sta.hh index e8ce25d4..e661f0a5 100644 --- a/search/Sta.hh +++ b/search/Sta.hh @@ -1297,6 +1297,8 @@ protected: const MinMax *min_max); void parasiticsChangedAfter(); void powerPreamble(); + void disableFanoutCrprPruning(Vertex *vertex, + int &fanou); CmdNamespace cmd_namespace_; Instance *current_instance_; diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index 7394d317..3177a7a5 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -1997,7 +1997,7 @@ private: %inline %{ float float_inf = INF; - int group_count_max = PathGroup::group_count_max; +int group_count_max = PathGroup::group_count_max; const char * version() diff --git a/util/Fuzzy.cc b/util/Fuzzy.cc index 79576401..f6a83eb7 100644 --- a/util/Fuzzy.cc +++ b/util/Fuzzy.cc @@ -17,6 +17,7 @@ #include // max #include // abs #include "Machine.hh" +#include "MinMax.hh" // INF namespace sta { @@ -66,4 +67,11 @@ fuzzyGreaterEqual(float v1, return v1 > v2 || fuzzyEqual(v1, v2); } +bool +fuzzyInf(float value) +{ + return fuzzyEqual(value, INF) + || fuzzyEqual(value, -INF); +} + } // namespace diff --git a/util/Fuzzy.hh b/util/Fuzzy.hh index 698a7caa..e81b5d29 100644 --- a/util/Fuzzy.hh +++ b/util/Fuzzy.hh @@ -35,5 +35,7 @@ fuzzyGreater(float v1, bool fuzzyGreaterEqual(float v1, float v2); +bool +fuzzyInf(float value); } // namespace