diff --git a/configure.ac b/configure.ac index 714febc0..af6a0969 100644 --- a/configure.ac +++ b/configure.ac @@ -412,7 +412,7 @@ AC_FUNC_ERROR_AT_LINE if test $CXX = clang++; then # -Wno-deprecated-register to suppress warnings in flex files - CXXFLAGS="-std=c++11 -Wno-deprecated-register -Wcast-qual -pipe" + CXXFLAGS="-std=c++11 -Wall -Wno-deprecated-register -Wcast-qual" CXX_OPT="-O3" CXX_DEBUG="-g" CXX_ASAN="-fsanitize=address -O1 -fno-omit-frame-pointer" diff --git a/dcalc/GraphDelayCalc1.cc b/dcalc/GraphDelayCalc1.cc index 8425cc31..256ecd38 100644 --- a/dcalc/GraphDelayCalc1.cc +++ b/dcalc/GraphDelayCalc1.cc @@ -1202,7 +1202,7 @@ GraphDelayCalc1::initWireDelays(Vertex *drvr_vertex, TransRiseFallIterator tr_iter; while (tr_iter.hasNext()) { TransRiseFall *tr = tr_iter.next(); - if (!wire_edge->wireDelayAnnotated(tr, ap_index)) + if (!graph_->wireDelayAnnotated(wire_edge, tr, ap_index)) graph_->setWireArcDelay(wire_edge, tr, ap_index, delay_init_value); // Init load vertex slew. if (init_load_slews @@ -1274,7 +1274,7 @@ GraphDelayCalc1::findArcDelay(LibertyCell *drvr_cell, if (delayFuzzyGreater(gate_slew, drvr_slew, dcalc_ap->slewMinMax()) && !drvr_vertex->slewAnnotated(drvr_tr, ap_index)) graph_->setSlew(drvr_vertex, drvr_tr, ap_index, gate_slew); - if (!edge->arcDelayAnnotated(arc, ap_index)) { + if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) { const ArcDelay &prev_gate_delay = graph_->arcDelay(edge,arc,ap_index); float gate_delay1 = delayAsFloat(gate_delay); float prev_gate_delay1 = delayAsFloat(prev_gate_delay); @@ -1486,7 +1486,7 @@ GraphDelayCalc1::annotateLoadDelays(Vertex *drvr_vertex, graph_->setSlew(load_vertex, drvr_tr, ap_index, load_slew); } } - if (!wire_edge->wireDelayAnnotated(drvr_tr, ap_index)) { + if (!graph_->wireDelayAnnotated(wire_edge, drvr_tr, ap_index)) { // Multiple timing arcs with the same output transition // annotate the same wire edges so they must be combined // rather than set. @@ -1570,7 +1570,7 @@ GraphDelayCalc1::findCheckEdgeDelays(Edge *edge, while (ap_iter.hasNext()) { DcalcAnalysisPt *dcalc_ap = ap_iter.next(); DcalcAPIndex ap_index = dcalc_ap->index(); - if (!edge->arcDelayAnnotated(arc, ap_index)) { + if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) { const Pvt *pvt = sdc_->pvt(inst,dcalc_ap->constraintMinMax()); if (pvt == NULL) pvt = dcalc_ap->operatingConditions(); diff --git a/doc/BugLog b/doc/BugLog index ea7d8f08..fcf7f594 100644 --- a/doc/BugLog +++ b/doc/BugLog @@ -2,3 +2,5 @@ Release 2.0 Patches ------------------- 2018/10/23 spash msg embedded quotes seg fault 2018/10/23 read_verilog mod inst with no ports seg fault +2018/11/08 corners > 2 causes internal error +2018/11/09 Verilog ignore attributes (* blah *) diff --git a/graph/Graph.cc b/graph/Graph.cc index 81fd092d..2f82db92 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -714,6 +714,9 @@ Graph::makeArcDelayPools(ArcIndex arc_count, DelayPool *pool = new DelayPool(arc_count); arc_delays_[i] = pool; } + + unsigned annot_size = arc_count * 1.2; + arc_delay_annotated_.resize(annot_size * ap_count); } } @@ -743,6 +746,13 @@ Graph::makeEdgeArcDelays(Edge *edge) *arc_delays++ = 0.0; } edge->setArcDelays(arc_index); + // Make sure there is room for delay_annotated flags. + unsigned max_annot_index = arc_index + (arc_count * ap_count_); + if (max_annot_index >= arc_delay_annotated_.size()) { + unsigned size = max_annot_index * 1.2; + arc_delay_annotated_.resize(size); + } + removeDelayAnnotated(edge); } } @@ -817,6 +827,46 @@ Graph::setWireArcDelay(Edge *edge, } } +bool +Graph::arcDelayAnnotated(Edge *edge, + TimingArc *arc, + DcalcAPIndex ap_index) const +{ + int index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index; + return arc_delay_annotated_[index]; +} + +void +Graph::setArcDelayAnnotated(Edge *edge, + TimingArc *arc, + DcalcAPIndex ap_index, + bool annotated) +{ + int index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index; + arc_delay_annotated_[index] = annotated; +} + +bool +Graph::wireDelayAnnotated(Edge *edge, + const TransRiseFall *tr, + DcalcAPIndex ap_index) const +{ + int index = (edge->arcDelays() + TimingArcSet::wireArcIndex(tr)) * ap_count_ + + ap_index; + return arc_delay_annotated_[index]; +} + +void +Graph::setWireDelayAnnotated(Edge *edge, + const TransRiseFall *tr, + DcalcAPIndex ap_index, + bool annotated) +{ + int index = (edge->arcDelays() + TimingArcSet::wireArcIndex(tr)) * ap_count_ + + ap_index; + arc_delay_annotated_[index] = annotated; +} + // This only gets called if the analysis type changes from single // to bc_wc/ocv or visa versa. void @@ -846,11 +896,41 @@ Graph::removeDelays() while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); makeEdgeArcDelays(edge); - edge->removeDelayAnnotated(); + removeDelayAnnotated(edge); } } } +void +Graph::removeDelayAnnotated(Edge *edge) +{ + edge->setDelayAnnotationIsIncremental(false); + TimingArcSet *arc_set = edge->timingArcSet(); + TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator(); + while (arc_iter->hasNext()) { + TimingArc *arc = arc_iter->next(); + for (DcalcAPIndex ap_index = 0; ap_index < ap_count_; ap_index++) { + setArcDelayAnnotated(edge, arc, ap_index, false); + } + } + delete arc_iter; +} + +bool +Graph::delayAnnotated(Edge *edge) +{ + TimingArcSet *arc_set = edge->timingArcSet(); + TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator(); + while (arc_iter->hasNext()) { + TimingArc *arc = arc_iter->next(); + for (DcalcAPIndex ap_index = 0; ap_index < ap_count_; ap_index++) { + if (arcDelayAnnotated(edge, arc, ap_index)) + return true; + } + } + return false; +} + void Graph::makeSlewPools(VertexIndex vertex_count, DcalcAPIndex ap_count) @@ -1019,7 +1099,7 @@ Graph::removeDelaySlewAnnotations() VertexOutEdgeIterator edge_iter(vertex, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - edge->removeDelayAnnotated(); + removeDelayAnnotated(edge); } vertex->removeSlewAnnotated(); } @@ -1272,7 +1352,6 @@ Edge::init(VertexIndex from, vertex_out_prev_ = 0; is_bidirect_inst_path_ = false; is_bidirect_net_path_ = false; - delay_annotated_ = false; delay_annotation_is_incremental_ = false; sim_timing_sense_ = timing_sense_unknown; is_disabled_constraint_ = false; @@ -1292,62 +1371,6 @@ Edge::setArcDelays(ArcIndex arc_delays) arc_delays_ = arc_delays; } -bool -Edge::arcDelayAnnotated() const -{ - return delay_annotated_ != 0; -} - -bool -Edge::arcDelayAnnotated(TimingArc *arc, - DcalcAPIndex ap_index) const -{ - int bit_index = ap_index * arc_set_->arcCount() + arc->index(); - if (bit_index >= delay_annotation_bit_count) - internalError("arc annotation bit index out of range"); - return (delay_annotated_ & (1 << bit_index)) != 0; -} - -void -Edge::setArcDelayAnnotated(bool annotated, - TimingArc *arc, - DcalcAPIndex ap_index) -{ - int bit_index = ap_index * arc_set_->arcCount() + arc->index(); - if (bit_index >= delay_annotation_bit_count) - internalError("arc annotation bit index out of range"); - if (annotated) - delay_annotated_ |= (1 << bit_index); - else - delay_annotated_ &= ~(1 << bit_index); -} - -bool -Edge::wireDelayAnnotated(const TransRiseFall *tr, - DcalcAPIndex ap_index) const -{ - int bit_index = ap_index * TimingArcSet::wireArcCount() - + TimingArcSet::wireArcIndex(tr); - if (bit_index >= delay_annotation_bit_count) - internalError("arc annotation bit index out of range"); - return (delay_annotated_ & (1 << bit_index)) != 0; -} - -void -Edge::setWireDelayAnnotated(bool annotated, - const TransRiseFall *tr, - DcalcAPIndex ap_index) -{ - int bit_index = ap_index * TimingArcSet::wireArcCount() - + TimingArcSet::wireArcIndex(tr); - if (bit_index >= delay_annotation_bit_count) - internalError("arc annotation bit index out of range"); - if (annotated) - delay_annotated_ |= (1 << bit_index); - else - delay_annotated_ &= ~(1 << bit_index); -} - bool Edge::delayAnnotationIsIncremental() const { @@ -1357,19 +1380,9 @@ Edge::delayAnnotationIsIncremental() const void Edge::setDelayAnnotationIsIncremental(bool is_incr) { - if (delay_annotated_ != 0 - && is_incr != delay_annotation_is_incremental_) - delay_annotated_ = 0; delay_annotation_is_incremental_ = is_incr; } -void -Edge::removeDelayAnnotated() -{ - delay_annotated_ = 0; - delay_annotation_is_incremental_ = false; -} - TimingRole * Edge::role() const { diff --git a/graph/Graph.hh b/graph/Graph.hh index b41ac1cc..e2651f5f 100644 --- a/graph/Graph.hh +++ b/graph/Graph.hh @@ -128,6 +128,23 @@ public: const TransRiseFall *tr, DcalcAPIndex ap_index, const ArcDelay &delay); + // Is timing arc delay annotated. + bool arcDelayAnnotated(Edge *edge, + TimingArc *arc, + DcalcAPIndex ap_index) const; + void setArcDelayAnnotated(Edge *edge, + TimingArc *arc, + DcalcAPIndex ap_index, + bool annotated); + bool wireDelayAnnotated(Edge *edge, + const TransRiseFall *tr, + DcalcAPIndex ap_index) const; + void setWireDelayAnnotated(Edge *edge, + const TransRiseFall *tr, + DcalcAPIndex ap_index, + bool annotated); + // True if any edge arc is annotated. + bool delayAnnotated(Edge *edge); EdgeIndex edgeCount() { return edge_count_; } virtual ArcIndex arcCount() { return arc_count_; } @@ -205,6 +222,7 @@ protected: float *makeFloats(ObjectIndex count); void deleteFloats(float *floats, ObjectIndex count); + void removeDelayAnnotated(Edge *edge); VertexPool *vertices_; EdgePool *edges_; @@ -216,6 +234,7 @@ protected: VertexIndex vertex_count_; EdgeIndex edge_count_; ArcIndex arc_count_; + Vector arc_delay_annotated_; int slew_tr_count_; bool have_arc_delays_; DcalcAPIndex ap_count_; @@ -339,11 +358,6 @@ private: friend class VertexOutEdgeIterator; }; -#define max_dcalc_analysis_pt_count 4 -// One annotation bit per timing arc per delay calculation analysis point. -#define delay_annotation_bit_count \ - ((timing_arc_index_max + 1) * max_dcalc_analysis_pt_count) - // There is one Edge between each pair of pins that has a timing // path between them. class Edge @@ -359,20 +373,6 @@ public: void setTimingArcSet(TimingArcSet *set); ArcIndex arcDelays() const { return arc_delays_; } void setArcDelays(ArcIndex arc_delays); - // True if any timing arc delay is annotated. - bool arcDelayAnnotated() const; - // Is timing arc delay annotated. - bool arcDelayAnnotated(TimingArc *arc, - DcalcAPIndex ap_index) const; - void setArcDelayAnnotated(bool annotated, - TimingArc *arc, - DcalcAPIndex ap_index); - bool wireDelayAnnotated(const TransRiseFall *tr, - DcalcAPIndex ap_index) const; - void setWireDelayAnnotated(bool annotated, - const TransRiseFall *tr, - DcalcAPIndex ap_index); - void removeDelayAnnotated(); bool delayAnnotationIsIncremental() const; void setDelayAnnotationIsIncremental(bool is_incr); // Edge is disabled by set_disable_timing constraint. @@ -406,8 +406,6 @@ protected: VertexIndex vertex_out_next_; // Vertex out edges doubly linked list. VertexIndex vertex_out_prev_; ArcIndex arc_delays_; - // Timing arcs with sdf annotation. - unsigned int delay_annotated_:delay_annotation_bit_count; unsigned int delay_annotation_is_incremental_:1; unsigned int is_bidirect_inst_path_:1; unsigned int is_bidirect_net_path_:1; diff --git a/liberty/Transition.cc b/liberty/Transition.cc index ca7c9532..08e2cd90 100644 --- a/liberty/Transition.cc +++ b/liberty/Transition.cc @@ -40,11 +40,6 @@ TransRiseFall::destroy() fall_ = NULL; } -TransRiseFall::~TransRiseFall() -{ - stringDelete(short_name_); -} - TransRiseFall::TransRiseFall(const char *name, const char *short_name, int sdf_triple_index) : @@ -54,9 +49,15 @@ TransRiseFall::TransRiseFall(const char *name, { } +TransRiseFall::~TransRiseFall() +{ + stringDelete(short_name_); +} + void TransRiseFall::setShortName(const char *short_name) { + stringDelete(short_name_); short_name_ = stringCopy(short_name); } @@ -152,6 +153,11 @@ TransRiseFallBoth::TransRiseFallBoth(const char *name, { } +TransRiseFallBoth::~TransRiseFallBoth() +{ + stringDelete(short_name_); +} + TransRiseFallBoth * TransRiseFallBoth::find(const char *tr_str) { @@ -185,6 +191,7 @@ TransRiseFallBoth::matches(const Transition *tr) const void TransRiseFallBoth::setShortName(const char *short_name) { + stringDelete(short_name_); short_name_ = stringCopy(short_name); } @@ -289,6 +296,7 @@ Transition::asRiseFallBoth() const void Transition::setName(const char *name) { + stringDelete(name_); name_ = stringCopy(name); } diff --git a/liberty/Transition.hh b/liberty/Transition.hh index f8957d28..08055001 100644 --- a/liberty/Transition.hh +++ b/liberty/Transition.hh @@ -106,6 +106,7 @@ protected: const char *short_name, int sdf_triple_index, TransRiseFall *as_rise_fall); + ~TransRiseFallBoth(); const char *name_; const char *short_name_; diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index 00b074de..acfc5e65 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -98,6 +98,7 @@ Sdc::Sdc(StaState *sta) : clk_index_(0), clk_insertions_(NULL), clk_group_exclusions_(NULL), + clk_group_same_(NULL), clk_sense_map_(network_), clk_gating_check_(NULL), input_delay_index_(0), @@ -2082,6 +2083,7 @@ Sdc::ensureClkGroupExclusions() { if (clk_group_exclusions_ == NULL) { clk_group_exclusions_ = new ClockPairSet; + clk_group_same_ = new ClockPairSet; ClockGroupsNameMap::Iterator groups_iter(clk_groups_name_map_); while (groups_iter.hasNext()) { ClockGroups *clk_groups = groups_iter.next(); @@ -2096,54 +2098,85 @@ Sdc::makeClkGroupExclusions(ClockGroups *clk_groups) if (!(clk_groups->asynchronous() && clk_groups->allowPaths())) { ClockGroupSet *groups = clk_groups->groups(); - if (groups->size() == 1) { - // If there is only one group all clocks not in the group - // are excluded. - ClockGroupSet::Iterator group_iter1(groups); - ClockGroup *group1 = group_iter1.next(); - ClockSet *clks1 = group1->clks(); - ClockSet::Iterator clk_iter1(clks1); - while (clk_iter1.hasNext()) { - Clock *clk1 = clk_iter1.next(); - ClockIterator *clk_iter2 = clockIterator(); - while (clk_iter2->hasNext()) { - Clock *clk2 = clk_iter2->next(); - if (clk2 != clk1 - && !group1->isMember(clk2)) { - ClockPair *clk_pair = new ClockPair(clk1, clk2); - clk_group_exclusions_->insert(clk_pair); - } - } - delete clk_iter2; + if (groups->size() == 1) + makeClkGroupExclusions1(groups); + else + makeClkGroupExclusions(groups); + } +} + +// If there is only one group all clocks not in the group +// are excluded. +void +Sdc::makeClkGroupExclusions1(ClockGroupSet *groups) +{ + ClockGroupSet::Iterator group_iter1(groups); + ClockGroup *group1 = group_iter1.next(); + ClockSet *clks1 = group1->clks(); + ClockSet::Iterator clk_iter1(clks1); + while (clk_iter1.hasNext()) { + Clock *clk1 = clk_iter1.next(); + ClockIterator *clk_iter2 = clockIterator(); + while (clk_iter2->hasNext()) { + Clock *clk2 = clk_iter2->next(); + if (clk2 != clk1 + && !group1->isMember(clk2)) { + ClockPair *clk_pair = new ClockPair(clk1, clk2); + clk_group_exclusions_->insert(clk_pair); } } - else { - ClockGroupSet::Iterator group_iter1(groups); - while (group_iter1.hasNext()) { - ClockGroup *group1 = group_iter1.next(); - ClockGroupSet::Iterator group_iter2(groups); - while (group_iter2.hasNext()) { - ClockGroup *group2 = group_iter2.next(); - if (group1 != group2) { - ClockSet *clks1 = group1->clks(); - ClockSet *clks2 = group2->clks(); - ClockSet::Iterator clk_iter1(clks1); - while (clk_iter1.hasNext()) { - Clock *clk1 = clk_iter1.next(); - ClockSet::Iterator clk_iter2(clks2); - while (clk_iter2.hasNext()) { - Clock *clk2 = clk_iter2.next(); - // ClockPair is symmetric so only add one clk1/clk2 pair. - if (clk1->index() < clk2->index()) { - ClockPair *clk_pair = new ClockPair(clk1, clk2); - clk_group_exclusions_->insert(clk_pair); - } - } + delete clk_iter2; + } + makeClkGroupSame(group1); +} + +void +Sdc::makeClkGroupExclusions(ClockGroupSet *groups) +{ + ClockGroupSet::Iterator group_iter1(groups); + while (group_iter1.hasNext()) { + ClockGroup *group1 = group_iter1.next(); + ClockSet *clks1 = group1->clks(); + ClockGroupSet::Iterator group_iter2(groups); + while (group_iter2.hasNext()) { + ClockGroup *group2 = group_iter2.next(); + if (group1 != group2) { + ClockSet *clks2 = group2->clks(); + ClockSet::Iterator clk_iter1(clks1); + while (clk_iter1.hasNext()) { + Clock *clk1 = clk_iter1.next(); + ClockSet::Iterator clk_iter2(clks2); + while (clk_iter2.hasNext()) { + Clock *clk2 = clk_iter2.next(); + // ClockPair is symmetric so only add one clk1/clk2 pair. + if (clk1->index() < clk2->index()) { + ClockPair *clk_pair = new ClockPair(clk1, clk2); + clk_group_exclusions_->insert(clk_pair); } } } } } + makeClkGroupSame(group1); + } +} + +void +Sdc::makeClkGroupSame(ClockGroup *group) +{ + ClockSet *clks = group->clks(); + ClockSet::Iterator clk_iter1(clks); + while (clk_iter1.hasNext()) { + Clock *clk1 = clk_iter1.next(); + ClockSet::Iterator clk_iter2(clks); + while (clk_iter2.hasNext()) { + Clock *clk2 = clk_iter2.next(); + if (clk1->index() <= clk2->index()) { + ClockPair *clk_pair = new ClockPair(clk1, clk2); + if (!clk_group_same_->hasKey(clk_pair)) + clk_group_same_->insert(clk_pair); + } + } } } @@ -2152,14 +2185,17 @@ Sdc::clearClkGroupExclusions() { if (clk_group_exclusions_) { clk_group_exclusions_->deleteContents(); + clk_group_same_->deleteContents(); delete clk_group_exclusions_; + delete clk_group_same_; clk_group_exclusions_ = NULL; + clk_group_same_ = NULL; } } bool Sdc::sameClockGroup(const Clock *clk1, - const Clock *clk2) + const Clock *clk2) { if (clk1 && clk2) { ClockPair clk_pair(clk1, clk2); @@ -2170,6 +2206,14 @@ Sdc::sameClockGroup(const Clock *clk1, return true; } +bool +Sdc::sameClockGroupExplicit(const Clock *clk1, + const Clock *clk2) +{ + ClockPair clk_pair(clk1, clk2); + return clk_group_same_->hasKey(&clk_pair); +} + void Sdc::removeClockGroups(const char *name) { diff --git a/sdc/Sdc.hh b/sdc/Sdc.hh index 0ea2e331..f99b930e 100644 --- a/sdc/Sdc.hh +++ b/sdc/Sdc.hh @@ -488,6 +488,9 @@ public: void removeClockGroupsAsynchronous(const char *name); bool sameClockGroup(const Clock *clk1, const Clock *clk2); + // Clocks explicitly excluded by set_clock_group. + bool sameClockGroupExplicit(const Clock *clk1, + const Clock *clk2); void setClockSense(PinSet *pins, ClockSet *clks, ClockSense sense); @@ -1250,6 +1253,9 @@ protected: void removeClockGroups(ClockGroups *groups); void ensureClkGroupExclusions();; void makeClkGroupExclusions(ClockGroups *clk_groups); + void makeClkGroupExclusions1(ClockGroupSet *groups); + void makeClkGroupExclusions(ClockGroupSet *groups); + void makeClkGroupSame(ClockGroup *group); void clearClkGroupExclusions(); char *makeClockGroupsName(); void setClockSense(const Pin *pin, @@ -1298,6 +1304,8 @@ protected: ClockGroupsNameMap clk_groups_name_map_; // clk to clk paths excluded by clock groups. ClockPairSet *clk_group_exclusions_; + // clks in the same set_clock_group set. + ClockPairSet *clk_group_same_; ClockSenseMap clk_sense_map_; ClockGatingCheck *clk_gating_check_; ClockGatingCheckMap clk_gating_check_map_; diff --git a/sdf/ReportAnnotation.cc b/sdf/ReportAnnotation.cc index f1d6230b..969e3e7e 100644 --- a/sdf/ReportAnnotation.cc +++ b/sdf/ReportAnnotation.cc @@ -316,7 +316,7 @@ ReportAnnotated::findCounts() LogicValue from_logic_value; bool from_logic_value_exists; sdc_->logicValue(from_pin, from_logic_value, - from_logic_value_exists); + from_logic_value_exists); VertexOutEdgeIterator edge_iter(from_vertex, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); @@ -327,14 +327,14 @@ ReportAnnotated::findCounts() LogicValue to_logic_value; bool to_logic_value_exists; sdc_->logicValue(to_pin, to_logic_value, - to_logic_value_exists); + to_logic_value_exists); edge_count_[index]++; if (from_logic_value_exists || to_logic_value_exists) edge_constant_count_[index]++; if (report_role_[index]) { - if (edge->arcDelayAnnotated()) { + if (graph_->delayAnnotated(edge)) { edge_annotated_count_[index]++; if (from_logic_value_exists || to_logic_value_exists) edge_constant_annotated_count_[index]++; @@ -501,7 +501,7 @@ ReportAnnotated::reportArcs(Vertex *vertex, Edge *edge = edge_iter.next(); TimingRole *role = edge->role(); const Pin *to_pin = edge->to(graph_)->pin(); - if (edge->arcDelayAnnotated() == report_annotated + if (graph_->delayAnnotated(edge) == report_annotated && report_role_[roleIndex(role, from_pin, to_pin)]) { const char *role_name; if (role->isTimingCheck()) diff --git a/sdf/SdfReader.cc b/sdf/SdfReader.cc index 8dd31d89..161865ef 100644 --- a/sdf/SdfReader.cc +++ b/sdf/SdfReader.cc @@ -759,7 +759,7 @@ SdfReader::setEdgeArcDelays(Edge *edge, else delay = *value_ptr; graph_->setArcDelay(edge, arc, arc_delay_index, delay); - edge->setArcDelayAnnotated(true, arc, arc_delay_index); + graph_->setArcDelayAnnotated(edge, arc, arc_delay_index, true); edge->setDelayAnnotationIsIncremental(is_incremental_only_); } } @@ -809,13 +809,13 @@ SdfReader::setEdgeArcDelaysCondUse(Edge *edge, ArcDelay delay(*value); if (!is_incremental_only_ && in_incremental_) delay = graph_->arcDelay(edge, arc, arc_delay_index) + *value; - else if (edge->arcDelayAnnotated(arc, arc_delay_index)) { + else if (graph_->arcDelayAnnotated(edge, arc, arc_delay_index)) { ArcDelay prev_value = graph_->arcDelay(edge, arc, arc_delay_index); if (delayFuzzyGreater(prev_value, delay, min_max)) delay = prev_value; } graph_->setArcDelay(edge, arc, arc_delay_index, delay); - edge->setArcDelayAnnotated(true, arc, arc_delay_index); + graph_->setArcDelayAnnotated(edge, arc, arc_delay_index, true); edge->setDelayAnnotationIsIncremental(is_incremental_only_); } } diff --git a/search/CheckMinPeriods.cc b/search/CheckMinPeriods.cc index 862e7f93..1efcfd43 100644 --- a/search/CheckMinPeriods.cc +++ b/search/CheckMinPeriods.cc @@ -61,17 +61,21 @@ CheckMinPeriods::clear() class MinPeriodViolatorsVisitor : public MinPeriodCheckVisitor { public: - MinPeriodViolatorsVisitor(MinPeriodCheckSeq &checks); + MinPeriodViolatorsVisitor(const Corner *corner, + MinPeriodCheckSeq &checks); virtual void visit(MinPeriodCheck &check, StaState *sta); private: DISALLOW_COPY_AND_ASSIGN(MinPeriodViolatorsVisitor); + const Corner *corner_; MinPeriodCheckSeq &checks_; }; -MinPeriodViolatorsVisitor::MinPeriodViolatorsVisitor(MinPeriodCheckSeq &checks): +MinPeriodViolatorsVisitor::MinPeriodViolatorsVisitor(const Corner *corner, + MinPeriodCheckSeq &checks): + corner_(corner), checks_(checks) { } @@ -85,10 +89,10 @@ MinPeriodViolatorsVisitor::visit(MinPeriodCheck &check, } MinPeriodCheckSeq & -CheckMinPeriods::violations() +CheckMinPeriods::violations(const Corner *corner) { clear(); - MinPeriodViolatorsVisitor visitor(checks_); + MinPeriodViolatorsVisitor visitor(corner, checks_); visitMinPeriodChecks(&visitor); sort(checks_, MinPeriodSlackLess(sta_)); return checks_; @@ -128,10 +132,12 @@ CheckMinPeriods::visitMinPeriodChecks(Vertex *vertex, } } +//////////////////////////////////////////////////////////////// + class MinPeriodSlackVisitor : public MinPeriodCheckVisitor { public: - MinPeriodSlackVisitor(); + MinPeriodSlackVisitor(const Corner *corner); virtual void visit(MinPeriodCheck &check, StaState *sta); MinPeriodCheck *minSlackCheck(); @@ -139,10 +145,12 @@ public: private: DISALLOW_COPY_AND_ASSIGN(MinPeriodSlackVisitor); + const Corner *corner_; MinPeriodCheck *min_slack_check_; }; -MinPeriodSlackVisitor::MinPeriodSlackVisitor() : +MinPeriodSlackVisitor::MinPeriodSlackVisitor(const Corner *corner) : + corner_(corner), min_slack_check_(NULL) { } @@ -167,10 +175,10 @@ MinPeriodSlackVisitor::minSlackCheck() } MinPeriodCheck * -CheckMinPeriods::minSlackCheck() +CheckMinPeriods::minSlackCheck(const Corner *corner) { clear(); - MinPeriodSlackVisitor visitor; + MinPeriodSlackVisitor visitor(corner); visitMinPeriodChecks(&visitor); MinPeriodCheck *check = visitor.minSlackCheck(); // Save check for cleanup. diff --git a/search/CheckMinPeriods.hh b/search/CheckMinPeriods.hh index 94f25cd9..bda5cfcb 100644 --- a/search/CheckMinPeriods.hh +++ b/search/CheckMinPeriods.hh @@ -36,9 +36,11 @@ public: ~CheckMinPeriods(); void clear(); // All violating min period checks. - MinPeriodCheckSeq &violations(); + // corner=NULL checks all corners. + MinPeriodCheckSeq &violations(const Corner *corner); // Min period check with the least slack. - MinPeriodCheck *minSlackCheck(); + // corner=NULL checks all corners. + MinPeriodCheck *minSlackCheck(const Corner *corner); protected: void visitMinPeriodChecks(MinPeriodCheckVisitor *visitor); diff --git a/search/CheckMinPulseWidths.cc b/search/CheckMinPulseWidths.cc index 79bdeb76..37b20141 100644 --- a/search/CheckMinPulseWidths.cc +++ b/search/CheckMinPulseWidths.cc @@ -74,49 +74,59 @@ CheckMinPulseWidths::clear() checks_.deleteContentsClear(); } +//////////////////////////////////////////////////////////////// + class MinPulseWidthChecksVisitor : public MinPulseWidthCheckVisitor { public: - explicit MinPulseWidthChecksVisitor(MinPulseWidthCheckSeq &checks); + explicit MinPulseWidthChecksVisitor(const Corner *corner, + MinPulseWidthCheckSeq &checks); virtual void visit(MinPulseWidthCheck &check, const StaState *sta); private: DISALLOW_COPY_AND_ASSIGN(MinPulseWidthChecksVisitor); + const Corner *corner_; MinPulseWidthCheckSeq &checks_; }; MinPulseWidthChecksVisitor:: -MinPulseWidthChecksVisitor(MinPulseWidthCheckSeq &checks) : +MinPulseWidthChecksVisitor(const Corner *corner, + MinPulseWidthCheckSeq &checks) : + corner_(corner), checks_(checks) { } void MinPulseWidthChecksVisitor::visit(MinPulseWidthCheck &check, - const StaState *) + const StaState *sta) { - MinPulseWidthCheck *copy = new MinPulseWidthCheck(check.openPath()); - checks_.push_back(copy); + if (corner_ == NULL + || check.corner(sta) == corner_) { + MinPulseWidthCheck *copy = new MinPulseWidthCheck(check.openPath()); + checks_.push_back(copy); + } } MinPulseWidthCheckSeq & -CheckMinPulseWidths::check() +CheckMinPulseWidths::check(const Corner *corner) { clear(); - MinPulseWidthChecksVisitor visitor(checks_); + MinPulseWidthChecksVisitor visitor(corner, checks_); visitMinPulseWidthChecks(&visitor); sort(checks_, MinPulseWidthSlackLess(sta_)); return checks_; } MinPulseWidthCheckSeq & -CheckMinPulseWidths::check(PinSeq *pins) +CheckMinPulseWidths::check(PinSeq *pins, + const Corner *corner) { clear(); Graph *graph = sta_->graph(); - MinPulseWidthChecksVisitor visitor(checks_); + MinPulseWidthChecksVisitor visitor(corner, checks_); PinSeq::Iterator pin_iter(pins); while (pin_iter.hasNext()) { Pin *pin = pin_iter.next(); @@ -127,49 +137,59 @@ CheckMinPulseWidths::check(PinSeq *pins) return checks_; } -class MinPulseWidthViolatorsVisititor : public MinPulseWidthCheckVisitor +//////////////////////////////////////////////////////////////// + +class MinPulseWidthViolatorsVisitor : public MinPulseWidthCheckVisitor { public: - explicit MinPulseWidthViolatorsVisititor(MinPulseWidthCheckSeq &checks); + explicit MinPulseWidthViolatorsVisitor(const Corner *corner, + MinPulseWidthCheckSeq &checks); virtual void visit(MinPulseWidthCheck &check, const StaState *sta); private: - DISALLOW_COPY_AND_ASSIGN(MinPulseWidthViolatorsVisititor); + DISALLOW_COPY_AND_ASSIGN(MinPulseWidthViolatorsVisitor); + const Corner *corner_; MinPulseWidthCheckSeq &checks_; }; -MinPulseWidthViolatorsVisititor:: -MinPulseWidthViolatorsVisititor(MinPulseWidthCheckSeq &checks) : +MinPulseWidthViolatorsVisitor:: +MinPulseWidthViolatorsVisitor(const Corner *corner, + MinPulseWidthCheckSeq &checks) : + corner_(corner), checks_(checks) { } void -MinPulseWidthViolatorsVisititor::visit(MinPulseWidthCheck &check, - const StaState *sta) +MinPulseWidthViolatorsVisitor::visit(MinPulseWidthCheck &check, + const StaState *sta) { - if (delayFuzzyLess(check.slack(sta), 0.0)) { + if (delayFuzzyLess(check.slack(sta), 0.0) + && (corner_ == NULL + || check.corner(sta) == corner_)) { MinPulseWidthCheck *copy = new MinPulseWidthCheck(check.openPath()); checks_.push_back(copy); } } MinPulseWidthCheckSeq & -CheckMinPulseWidths::violations() +CheckMinPulseWidths::violations(const Corner *corner) { clear(); - MinPulseWidthViolatorsVisititor visitor(checks_); + MinPulseWidthViolatorsVisitor visitor(corner, checks_); visitMinPulseWidthChecks(&visitor); sort(checks_, MinPulseWidthSlackLess(sta_)); return checks_; } +//////////////////////////////////////////////////////////////// + class MinPulseWidthSlackVisitor : public MinPulseWidthCheckVisitor { public: - MinPulseWidthSlackVisitor(); + MinPulseWidthSlackVisitor(const Corner *corner); virtual void visit(MinPulseWidthCheck &check, const StaState *sta); MinPulseWidthCheck *minSlackCheck(); @@ -177,10 +197,12 @@ public: private: DISALLOW_COPY_AND_ASSIGN(MinPulseWidthSlackVisitor); + const Corner *corner_; MinPulseWidthCheck *min_slack_check_; }; -MinPulseWidthSlackVisitor::MinPulseWidthSlackVisitor() : +MinPulseWidthSlackVisitor::MinPulseWidthSlackVisitor(const Corner *corner) : + corner_(corner), min_slack_check_(NULL) { } @@ -190,11 +212,14 @@ MinPulseWidthSlackVisitor::visit(MinPulseWidthCheck &check, const StaState *sta) { MinPulseWidthSlackLess slack_less(sta); - if (min_slack_check_ == NULL) - min_slack_check_ = check.copy(); - else if (slack_less(&check, min_slack_check_)) { - delete min_slack_check_; - min_slack_check_ = check.copy(); + if (corner_ == NULL + || check.corner(sta) == corner_) { + if (min_slack_check_ == NULL) + min_slack_check_ = check.copy(); + else if (slack_less(&check, min_slack_check_)) { + delete min_slack_check_; + min_slack_check_ = check.copy(); + } } } @@ -205,10 +230,10 @@ MinPulseWidthSlackVisitor::minSlackCheck() } MinPulseWidthCheck * -CheckMinPulseWidths::minSlackCheck() +CheckMinPulseWidths::minSlackCheck(const Corner *corner) { clear(); - MinPulseWidthSlackVisitor visitor; + MinPulseWidthSlackVisitor visitor(corner); visitMinPulseWidthChecks(&visitor); MinPulseWidthCheck *check = visitor.minSlackCheck(); // Save check for cleanup. @@ -452,6 +477,12 @@ MinPulseWidthCheck::slack(const StaState *sta) const return width(sta) - minWidth(sta); } +Corner * +MinPulseWidthCheck::corner(const StaState *sta) const +{ + return open_path_.pathAnalysisPt(sta)->corner(); +} + //////////////////////////////////////////////////////////////// MinPulseWidthSlackLess::MinPulseWidthSlackLess(const StaState *sta) : diff --git a/search/CheckMinPulseWidths.hh b/search/CheckMinPulseWidths.hh index 2d8331b2..12a74856 100644 --- a/search/CheckMinPulseWidths.hh +++ b/search/CheckMinPulseWidths.hh @@ -36,13 +36,18 @@ public: ~CheckMinPulseWidths(); void clear(); // Min pulse width checks for pins. - MinPulseWidthCheckSeq &check(PinSeq *pins); + // corner=NULL checks all corners. + MinPulseWidthCheckSeq &check(PinSeq *pins, + const Corner *corner); // All min pulse width checks. - MinPulseWidthCheckSeq &check(); + // corner=NULL checks all corners. + MinPulseWidthCheckSeq &check(const Corner *corner); // All violating min pulse width checks. - MinPulseWidthCheckSeq &violations(); + // corner=NULL checks all corners. + MinPulseWidthCheckSeq &violations(const Corner *corner); // Min pulse width check with the least slack. - MinPulseWidthCheck *minSlackCheck(); + // corner=NULL checks all corners. + MinPulseWidthCheck *minSlackCheck(const Corner *corner); protected: void visitMinPulseWidthChecks(MinPulseWidthCheckVisitor *visitor); @@ -68,6 +73,7 @@ public: float minWidth(const StaState *sta) const; Slack slack(const StaState *sta) const; Path *openPath() { return &open_path_; } + Corner *corner(const StaState *sta) const; const Path *openPath() const { return &open_path_; } Arrival openArrival(const StaState *sta) const; void closePath(const StaState *sta, diff --git a/search/CheckSlewLimits.cc b/search/CheckSlewLimits.cc index 43ff3513..75fef7eb 100644 --- a/search/CheckSlewLimits.cc +++ b/search/CheckSlewLimits.cc @@ -32,22 +32,26 @@ namespace sta { class PinSlewLimitSlackLess { public: - PinSlewLimitSlackLess(const MinMax *min_max, + PinSlewLimitSlackLess(const Corner *corner, + const MinMax *min_max, CheckSlewLimits *check_slew_limit, const StaState *sta); bool operator()(Pin *pin1, Pin *pin2) const; private: + const Corner *corner_; const MinMax *min_max_; CheckSlewLimits *check_slew_limit_; const StaState *sta_; }; -PinSlewLimitSlackLess::PinSlewLimitSlackLess(const MinMax *min_max, +PinSlewLimitSlackLess::PinSlewLimitSlackLess(const Corner *corner, + const MinMax *min_max, CheckSlewLimits *check_slew_limit, const StaState *sta) : + corner_(corner), min_max_(min_max), check_slew_limit_(check_slew_limit), sta_(sta) @@ -62,9 +66,9 @@ PinSlewLimitSlackLess::operator()(Pin *pin1, const TransRiseFall *tr1, *tr2; Slew slew1, slew2; float limit1, limit2, slack1, slack2; - check_slew_limit_->checkSlews(pin1, min_max_, + check_slew_limit_->checkSlews(pin1, corner_, min_max_, corner1, tr1, slew1, limit1, slack1); - check_slew_limit_->checkSlews(pin2, min_max_, + check_slew_limit_->checkSlews(pin2, corner_, min_max_, corner2, tr2, slew2, limit2, slack2); return slack1 < slack2 || (fuzzyEqual(slack1, slack2) @@ -94,41 +98,71 @@ CheckSlewLimits::init(const MinMax *min_max) void CheckSlewLimits::checkSlews(const Pin *pin, + const Corner *corner, const MinMax *min_max, // Return values. - const Corner *&corner, - // Return the min slack transition. + const Corner *&corner1, const TransRiseFall *&tr, Slew &slew, float &limit, float &slack) const { - corner = NULL; + corner1 = NULL; tr = NULL; slack = MinMax::min()->initValue(); + if (corner) + checkSlews1(pin, corner, min_max, + corner1, tr, slew, limit, slack); + else { + CornerIterator corner_iter(sta_); + while (corner_iter.hasNext()) { + const Corner *corner2 = corner_iter.next(); + checkSlews1(pin, corner2, min_max, + corner1, tr, slew, limit, slack); + } + } +} + +void +CheckSlewLimits::checkSlews1(const Pin *pin, + const Corner *corner, + const MinMax *min_max, + // Return values. + const Corner *&corner1, + const TransRiseFall *&tr, + Slew &slew, + float &limit, + float &slack) const +{ Vertex *vertex, *bidirect_drvr_vertex; sta_->graph()->pinVertices(pin, vertex, bidirect_drvr_vertex); + checkSlews1(vertex, corner, min_max, + corner1, tr, slew, limit, slack); + if (bidirect_drvr_vertex) + checkSlews1(bidirect_drvr_vertex, corner, min_max, + corner1, tr, slew, limit, slack); +} + +void +CheckSlewLimits::checkSlews1(Vertex *vertex, + const Corner *corner1, + const MinMax *min_max, + // Return values. + const Corner *&corner, + const TransRiseFall *&tr, + Slew &slew, + float &limit, + float &slack) const +{ TransRiseFallIterator tr_iter; while (tr_iter.hasNext()) { TransRiseFall *tr1 = tr_iter.next(); float limit1; bool limit1_exists; - findLimit(pin, vertex, tr1, min_max, limit1, limit1_exists); + findLimit(vertex->pin(), vertex, tr1, min_max, limit1, limit1_exists); if (limit1_exists) { - CornerIterator corner_iter(sta_); - while (corner_iter.hasNext()) { - Corner *corner1 = corner_iter.next(); - checkSlew(vertex, limit1, tr1, corner1, min_max, - corner, tr, slew, slack, limit); - if (bidirect_drvr_vertex) { - findLimit(pin, bidirect_drvr_vertex, tr1, min_max, - limit1, limit1_exists); - if (limit1_exists) { - checkSlew(bidirect_drvr_vertex, limit1, tr1, corner1, min_max, - corner, tr, slew, slack, limit); - } - } - } + checkSlew(vertex, corner1, min_max, tr1, limit1, + corner, tr, slew, slack, limit); } } } @@ -229,10 +263,10 @@ CheckSlewLimits::clockDomains(const Vertex *vertex, void CheckSlewLimits::checkSlew(Vertex *vertex, - float limit1, - const TransRiseFall *tr1, const Corner *corner1, const MinMax *min_max, + const TransRiseFall *tr1, + float limit1, // Return values. const Corner *&corner, const TransRiseFall *&tr, @@ -259,7 +293,8 @@ CheckSlewLimits::checkSlew(Vertex *vertex, } PinSeq * -CheckSlewLimits::pinSlewLimitViolations(const MinMax *min_max) +CheckSlewLimits::pinSlewLimitViolations(const Corner *corner, + const MinMax *min_max) { init(min_max); const Network *network = sta_->network(); @@ -267,17 +302,18 @@ CheckSlewLimits::pinSlewLimitViolations(const MinMax *min_max) LeafInstanceIterator *inst_iter = network->leafInstanceIterator(); while (inst_iter->hasNext()) { Instance *inst = inst_iter->next(); - pinSlewLimitViolations(inst, min_max, violators); + pinSlewLimitViolations(inst, corner, min_max, violators); } delete inst_iter; // Check top level ports. - pinSlewLimitViolations(network->topInstance(), min_max, violators); - sort(violators, PinSlewLimitSlackLess(min_max, this, sta_)); + pinSlewLimitViolations(network->topInstance(), corner, min_max, violators); + sort(violators, PinSlewLimitSlackLess(corner, min_max, this, sta_)); return violators; } void CheckSlewLimits::pinSlewLimitViolations(Instance *inst, + const Corner *corner, const MinMax *min_max, PinSeq *violators) { @@ -285,11 +321,11 @@ CheckSlewLimits::pinSlewLimitViolations(Instance *inst, InstancePinIterator *pin_iter = network->pinIterator(inst); while (pin_iter->hasNext()) { Pin *pin = pin_iter->next(); - const Corner *corner; + const Corner *corner1; const TransRiseFall *tr; Slew slew; float limit, slack; - checkSlews(pin, min_max, corner, tr, slew, limit, slack); + checkSlews(pin, corner, min_max, corner1, tr, slew, limit, slack ); if (tr && slack < 0.0) violators->push_back(pin); } @@ -297,7 +333,8 @@ CheckSlewLimits::pinSlewLimitViolations(Instance *inst, } Pin * -CheckSlewLimits::pinMinSlewLimitSlack(const MinMax *min_max) +CheckSlewLimits::pinMinSlewLimitSlack(const Corner *corner, + const MinMax *min_max) { init(min_max); const Network *network = sta_->network(); @@ -306,17 +343,18 @@ CheckSlewLimits::pinMinSlewLimitSlack(const MinMax *min_max) LeafInstanceIterator *inst_iter = network->leafInstanceIterator(); while (inst_iter->hasNext()) { Instance *inst = inst_iter->next(); - pinMinSlewLimitSlack(inst, min_max, min_slack_pin, min_slack); + pinMinSlewLimitSlack(inst, corner, min_max, min_slack_pin, min_slack); } delete inst_iter; // Check top level ports. - pinMinSlewLimitSlack(network->topInstance(), min_max, + pinMinSlewLimitSlack(network->topInstance(), corner, min_max, min_slack_pin, min_slack); return min_slack_pin; } void CheckSlewLimits::pinMinSlewLimitSlack(Instance *inst, + const Corner *corner, const MinMax *min_max, // Return values. Pin *&min_slack_pin, @@ -326,11 +364,11 @@ CheckSlewLimits::pinMinSlewLimitSlack(Instance *inst, InstancePinIterator *pin_iter = network->pinIterator(inst); while (pin_iter->hasNext()) { Pin *pin = pin_iter->next(); - const Corner *corner; + const Corner *corner1; const TransRiseFall *tr; Slew slew; float limit, slack; - checkSlews(pin, min_max, corner, tr, slew, limit, slack); + checkSlews(pin, corner, min_max, corner1, tr, slew, limit, slack); if (tr && (min_slack_pin == 0 || slack < min_slack)) { diff --git a/search/CheckSlewLimits.hh b/search/CheckSlewLimits.hh index 01197b9f..836949f1 100644 --- a/search/CheckSlewLimits.hh +++ b/search/CheckSlewLimits.hh @@ -34,24 +34,48 @@ public: CheckSlewLimits(const StaState *sta); void init(const MinMax *min_max); // Requires init(). + // corner=NULL checks all corners. void checkSlews(const Pin *pin, + const Corner *corner, const MinMax *min_max, // Return values. // Corner is NULL for no slew limit. - const Corner *&corner, + const Corner *&corner1, const TransRiseFall *&tr, Slew &slew, float &limit, float &slack) const; - PinSeq *pinSlewLimitViolations(const MinMax *min_max); - Pin *pinMinSlewLimitSlack(const MinMax *min_max); + // corner=NULL checks all corners. + PinSeq *pinSlewLimitViolations(const Corner *corner, + const MinMax *min_max); + // corner=NULL checks all corners. + Pin *pinMinSlewLimitSlack(const Corner *corner, + const MinMax *min_max); protected: + void checkSlews1(const Pin *pin, + const Corner *corner, + const MinMax *min_max, + // Return values. + const Corner *&corner1, + const TransRiseFall *&tr, + Slew &slew, + float &limit, + float &slack) const; + void checkSlews1(Vertex *vertex, + const Corner *corner1, + const MinMax *min_max, + // Return values. + const Corner *&corner, + const TransRiseFall *&tr, + Slew &slew, + float &limit, + float &slack) const; void checkSlew(Vertex *vertex, - float limit1, - const TransRiseFall *tr1, const Corner *corner1, const MinMax *min_max, + const TransRiseFall *tr1, + float limit1, // Return values. const Corner *&corner, const TransRiseFall *&tr, @@ -66,9 +90,11 @@ protected: float &limit1, bool &limit1_exists) const; void pinSlewLimitViolations(Instance *inst, + const Corner *corner, const MinMax *min_max, PinSeq *violators); void pinMinSlewLimitSlack(Instance *inst, + const Corner *corner, const MinMax *min_max, // Return values. Pin *&min_slack_pin, diff --git a/search/ClkSkew.cc b/search/ClkSkew.cc index 10ecc173..8d6e9321 100644 --- a/search/ClkSkew.cc +++ b/search/ClkSkew.cc @@ -119,11 +119,12 @@ ClkSkews::ClkSkews(StaState *sta) : void ClkSkews::reportClkSkew(ClockSet *clks, + const Corner *corner, const SetupHold *setup_hold, int digits) { ClkSkewMap skews; - findClkSkew(clks, setup_hold, skews); + findClkSkew(clks, corner, setup_hold, skews); // Sort the clocks to report in a stable order. ClockSeq sorted_clks; @@ -167,6 +168,7 @@ ClkSkews::reportClkSkew(ClockSet *clks, void ClkSkews::findClkSkew(ClockSet *clks, + const Corner *corner, const SetupHold *setup_hold, ClkSkewMap &skews) { @@ -184,7 +186,7 @@ ClkSkews::findClkSkew(ClockSet *clks, ? tr->asRiseFallBoth() : TransRiseFallBoth::riseFall(); findClkSkewFrom(src_vertex, q_vertex, src_tr, clks, - setup_hold, skews); + corner, setup_hold, skews); } } } @@ -210,6 +212,7 @@ ClkSkews::findClkSkewFrom(Vertex *src_vertex, Vertex *q_vertex, TransRiseFallBoth *src_tr, ClockSet *clks, + const Corner *corner, const SetupHold *setup_hold, ClkSkewMap &skews) { @@ -233,7 +236,7 @@ ClkSkews::findClkSkewFrom(Vertex *src_vertex, ? tgt_tr1->asRiseFallBoth() : TransRiseFallBoth::riseFall(); findClkSkew(src_vertex, src_tr, tgt_vertex, tgt_tr, - clks, setup_hold, skews); + clks, corner, setup_hold, skews); } } } @@ -245,6 +248,7 @@ ClkSkews::findClkSkew(Vertex *src_vertex, Vertex *tgt_vertex, TransRiseFallBoth *tgt_tr, ClockSet *clks, + const Corner *corner, const SetupHold *setup_hold, ClkSkewMap &skews) { @@ -257,32 +261,35 @@ ClkSkews::findClkSkew(Vertex *src_vertex, if (src_tr->matches(src_path->transition(this)) && src_path->minMax(this) == setup_hold && clks->hasKey(src_clk)) { - Corner *corner = src_path->pathAnalysisPt(this)->corner(); - VertexPathIterator tgt_iter(tgt_vertex, this); - while (tgt_iter.hasNext()) { - PathVertex *tgt_path = tgt_iter.next(); - Clock *tgt_clk = tgt_path->clock(this); - if (tgt_clk == src_clk - && tgt_tr->matches(tgt_path->transition(this)) - && tgt_path->minMax(this) == tgt_min_max - && tgt_path->pathAnalysisPt(this)->corner() == corner) { - ClkSkew probe(src_path, tgt_path, this); - ClkSkew *clk_skew = skews.findKey(src_clk); - debugPrint8(debug_, "clk_skew", 2, "%s %s %s -> %s %s %s crpr = %s skew = %s\n", - network_->pathName(src_path->pin(this)), - src_path->transition(this)->asString(), - time_unit->asString(probe.srcLatency(this)), - network_->pathName(tgt_path->pin(this)), - tgt_path->transition(this)->asString(), - time_unit->asString(probe.tgtLatency(this)), - time_unit->asString(probe.crpr(this)), - time_unit->asString(probe.skew())); - if (clk_skew == NULL) { - clk_skew = new ClkSkew(probe); - skews[src_clk] = clk_skew; + Corner *src_corner = src_path->pathAnalysisPt(this)->corner(); + if (corner == NULL + || src_corner == corner) { + VertexPathIterator tgt_iter(tgt_vertex, this); + while (tgt_iter.hasNext()) { + PathVertex *tgt_path = tgt_iter.next(); + Clock *tgt_clk = tgt_path->clock(this); + if (tgt_clk == src_clk + && tgt_tr->matches(tgt_path->transition(this)) + && tgt_path->minMax(this) == tgt_min_max + && tgt_path->pathAnalysisPt(this)->corner() == src_corner) { + ClkSkew probe(src_path, tgt_path, this); + ClkSkew *clk_skew = skews.findKey(src_clk); + debugPrint8(debug_, "clk_skew", 2, "%s %s %s -> %s %s %s crpr = %s skew = %s\n", + network_->pathName(src_path->pin(this)), + src_path->transition(this)->asString(), + time_unit->asString(probe.srcLatency(this)), + network_->pathName(tgt_path->pin(this)), + tgt_path->transition(this)->asString(), + time_unit->asString(probe.tgtLatency(this)), + time_unit->asString(probe.crpr(this)), + time_unit->asString(probe.skew())); + if (clk_skew == NULL) { + clk_skew = new ClkSkew(probe); + skews[src_clk] = clk_skew; + } + else if (fuzzyGreater(probe.skew(), clk_skew->skew())) + clk_skew->copy(probe); } - else if (fuzzyGreater(probe.skew(), clk_skew->skew())) - clk_skew->copy(probe); } } } diff --git a/search/ClkSkew.hh b/search/ClkSkew.hh index 929869fa..06bfeda5 100644 --- a/search/ClkSkew.hh +++ b/search/ClkSkew.hh @@ -33,11 +33,13 @@ public: ClkSkews(StaState *sta); // Report clk skews for clks. void reportClkSkew(ClockSet *clks, + const Corner *corner, const SetupHold *setup_hold, int digits); protected: void findClkSkew(ClockSet *clks, + const Corner *corner, const SetupHold *setup_hold, ClkSkewMap &skews); bool hasClkPaths(Vertex *vertex, @@ -46,6 +48,7 @@ protected: Vertex *q_vertex, TransRiseFallBoth *src_tr, ClockSet *clks, + const Corner *corner, const SetupHold *setup_hold, ClkSkewMap &skews); void findClkSkew(Vertex *src_vertex, @@ -53,6 +56,7 @@ protected: Vertex *tgt_vertex, TransRiseFallBoth *tgt_tr, ClockSet *clks, + const Corner *corner, const SetupHold *setup_hold, ClkSkewMap &skews); void findFanout(Vertex *from, diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 747b254b..899963c1 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -63,8 +63,8 @@ ReportField::ReportField(const char *name, title_(stringCopy(title)), left_justify_(left_justify), unit_(unit), - blank_(NULL), - enabled_(enabled) + enabled_(enabled), + blank_(NULL) { setWidth(width); } @@ -1872,7 +1872,7 @@ ReportPath::reportStartEndPoint(const char *pt, result += pt; reportEndOfLine(result); - for (int i = 0; i < strlen(key); i++) + for (unsigned i = 0; i < strlen(key); i++) result += ' '; result += " ("; @@ -2785,7 +2785,7 @@ ReportPath::nextArcAnnotated(const PathRef *next_path, { TimingArc *arc = expanded.prevArc(next_index); Edge *edge = next_path->prevEdge(arc, this); - return edge->arcDelayAnnotated(arc, ap_index); + return graph_->arcDelayAnnotated(edge, arc, ap_index); } char * diff --git a/search/Sta.cc b/search/Sta.cc index f01d1315..72fc3de8 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2384,8 +2384,9 @@ Sta::findPathEnds(ExceptionFrom *from, { searchPreamble(); return search_->findPathEnds(from, thrus, to, - corner, min_max, group_count, endpoint_count, unique_pins, - slack_min, slack_max, sort_by_slack, group_names, + corner, min_max, group_count, endpoint_count, + unique_pins, slack_min, slack_max, + sort_by_slack, group_names, setup, hold, recovery, removal, clk_gating_setup, clk_gating_hold); @@ -2462,53 +2463,6 @@ Sta::reportPath(Path *path) report_path_->reportPath(path); } -PathEndSeq * -Sta::reportCheckTypes(bool all_violators, - bool setup, - bool hold, - bool recovery, - bool removal, - bool clock_gating_setup, - bool clock_gating_hold) -{ - MinMaxAll *path_min_max = MinMaxAll::max(); - if ((setup && hold) - || (recovery && removal) - || (clock_gating_setup && clock_gating_hold)) - path_min_max = MinMaxAll::all(); - else if (setup - || recovery - || clock_gating_setup) - path_min_max = MinMaxAll::max(); - else if (hold - || removal - || clock_gating_hold) - path_min_max = MinMaxAll::min(); - int group_count; - float slack_min, slack_max; - if (all_violators) { - group_count = std::numeric_limits::max(); - slack_min = -INF; - slack_max = 0.0; - } - else { - group_count = 1; - slack_min = -INF; - slack_max = INF; - } - return findPathEnds(NULL, NULL, NULL, // from, thru, to - NULL, // corner - path_min_max, group_count, - 1, // endpoint_count - false, // unique_pins - slack_min, slack_max, - false, // sort_by_slack - NULL, // group_names - setup, hold, - recovery, removal, - clock_gating_setup, clock_gating_hold); -} - void Sta::updateTiming(bool full) { @@ -2520,13 +2474,14 @@ Sta::updateTiming(bool full) void Sta::reportClkSkew(ClockSet *clks, + const Corner *corner, const SetupHold *setup_hold, int digits) { ensureClkArrivals(); if (clk_skews_ == NULL) clk_skews_ = new ClkSkews(this); - clk_skews_->reportClkSkew(clks, setup_hold, digits); + clk_skews_->reportClkSkew(clks, corner, setup_hold, digits); } //////////////////////////////////////////////////////////////// @@ -2966,16 +2921,16 @@ Sta::arcDelayAnnotated(Edge *edge, TimingArc *arc, DcalcAnalysisPt *dcalc_ap) { - return edge->arcDelayAnnotated(arc, dcalc_ap->index()); + return graph_->arcDelayAnnotated(edge, arc, dcalc_ap->index()); } void -Sta::setArcDelayAnnotated(bool annotated, - Edge *edge, +Sta::setArcDelayAnnotated(Edge *edge, TimingArc *arc, - DcalcAnalysisPt *dcalc_ap) + DcalcAnalysisPt *dcalc_ap, + bool annotated) { - edge->setArcDelayAnnotated(annotated, arc, dcalc_ap->index()); + graph_->setArcDelayAnnotated(edge, arc, dcalc_ap->index(), annotated); Vertex *to = edge->to(graph_); search_->arrivalInvalid(to); search_->requiredInvalid(edge->from(graph_)); @@ -3159,7 +3114,7 @@ Sta::setArcDelay(Edge *edge, DcalcAPIndex ap_index = dcalc_ap->index(); graph_->setArcDelay(edge, arc, ap_index, delay); // Don't let delay calculation clobber the value. - edge->setArcDelayAnnotated(true, arc, ap_index); + graph_->setArcDelayAnnotated(edge, arc, ap_index, true); } if (edge->role()->isTimingCheck()) search_->requiredInvalid(edge->to(graph_)); @@ -3326,10 +3281,10 @@ Sta::setPortExtFanout(Port *port, void Sta::setNetWireCap(Net *net, bool subtract_pin_cap, + const Corner *corner, const MinMaxAll *min_max, float cap) { - Corner *corner = corners_->defaultCorner(); MinMaxIterator mm_iter(min_max); while (mm_iter.hasNext()) { MinMax *mm = mm_iter.next(); @@ -3341,6 +3296,7 @@ Sta::setNetWireCap(Net *net, void Sta::connectedCap(Pin *drvr_pin, const TransRiseFall *tr, + const Corner *corner, const MinMax *min_max, float &pin_cap, float &wire_cap) const @@ -3348,7 +3304,6 @@ Sta::connectedCap(Pin *drvr_pin, pin_cap = 0.0; wire_cap = 0.0; bool cap_exists = false; - Corner *corner = corners_->defaultCorner(); const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max); Parasitic *parasitic; bool delete_parasitic; @@ -3371,13 +3326,14 @@ Sta::connectedCap(Pin *drvr_pin, void Sta::connectedCap(Net *net, const TransRiseFall *tr, + const Corner *corner, const MinMax *min_max, float &pin_cap, float &wire_cap) const { Pin *drvr_pin = findNetParasiticDrvrPin(net); if (drvr_pin) - connectedCap(drvr_pin, tr, min_max, pin_cap, wire_cap); + connectedCap(drvr_pin, tr, corner, min_max, pin_cap, wire_cap); else { pin_cap = 0.0; wire_cap = 0.0; @@ -4707,17 +4663,19 @@ Sta::checkSlewLimitPreamble() } Pin * -Sta::pinMinSlewLimitSlack(const MinMax *min_max) +Sta::pinMinSlewLimitSlack(const Corner *corner, + const MinMax *min_max) { checkSlewLimitPreamble(); - return check_slew_limits_->pinMinSlewLimitSlack(min_max); + return check_slew_limits_->pinMinSlewLimitSlack(corner, min_max); } PinSeq * -Sta::pinSlewLimitViolations(const MinMax *min_max) +Sta::pinSlewLimitViolations(const Corner *corner, + const MinMax *min_max) { checkSlewLimitPreamble(); - return check_slew_limits_->pinSlewLimitViolations(min_max); + return check_slew_limits_->pinSlewLimitViolations(corner, min_max); } void @@ -4728,34 +4686,39 @@ Sta::reportSlewLimitShortHeader() void Sta::reportSlewLimitShort(Pin *pin, + const Corner *corner, const MinMax *min_max) { - const Corner *corner; + const Corner *corner1; const TransRiseFall *tr; Slew slew; float limit, slack; - check_slew_limits_->checkSlews(pin, min_max, corner, tr, slew, limit, slack); + check_slew_limits_->checkSlews(pin, corner, min_max, + corner1, tr, slew, limit, slack); report_path_->reportSlewLimitShort(pin, tr, slew, limit, slack); } void Sta::reportSlewLimitVerbose(Pin *pin, + const Corner *corner, const MinMax *min_max) { - const Corner *corner; + const Corner *corner1; const TransRiseFall *tr; Slew slew; float limit, slack; - check_slew_limits_->checkSlews(pin, min_max, corner, tr, slew, limit, slack); - report_path_->reportSlewLimitVerbose(pin, corner, tr, slew, + check_slew_limits_->checkSlews(pin, corner, min_max, + corner, tr, slew, limit, slack); + report_path_->reportSlewLimitVerbose(pin, corner1, tr, slew, limit, slack, min_max); } void Sta::checkSlews(const Pin *pin, + const Corner *corner, const MinMax *min_max, // Return values. - const Corner *&corner, + const Corner *&corner1, const TransRiseFall *&tr, Slew &slew, float &limit, @@ -4763,8 +4726,8 @@ Sta::checkSlews(const Pin *pin, { checkSlewLimitPreamble(); check_slew_limits_->init(min_max); - check_slew_limits_->checkSlews(pin, min_max, - corner, tr, slew, limit, slack); + check_slew_limits_->checkSlews(pin, corner, min_max, + corner1, tr, slew, limit, slack); } ////////////////////////////////////////////////////////////////' @@ -4778,31 +4741,32 @@ Sta::minPulseWidthPreamble() } MinPulseWidthCheckSeq & -Sta::minPulseWidthChecks(PinSeq *pins) +Sta::minPulseWidthChecks(PinSeq *pins, + const Corner *corner) { minPulseWidthPreamble(); - return check_min_pulse_widths_->check(pins); + return check_min_pulse_widths_->check(pins, corner); } MinPulseWidthCheckSeq & -Sta::minPulseWidthChecks() +Sta::minPulseWidthChecks(const Corner *corner) { minPulseWidthPreamble(); - return check_min_pulse_widths_->check(); + return check_min_pulse_widths_->check(corner); } MinPulseWidthCheckSeq & -Sta::minPulseWidthViolations() +Sta::minPulseWidthViolations(const Corner *corner) { minPulseWidthPreamble(); - return check_min_pulse_widths_->violations(); + return check_min_pulse_widths_->violations(corner); } MinPulseWidthCheck * -Sta::minPulseWidthSlack() +Sta::minPulseWidthSlack(const Corner *corner) { minPulseWidthPreamble(); - return check_min_pulse_widths_->minSlackCheck(); + return check_min_pulse_widths_->minSlackCheck(corner); } void @@ -4822,17 +4786,17 @@ Sta::reportMpwCheck(MinPulseWidthCheck *check, //////////////////////////////////////////////////////////////// MinPeriodCheckSeq & -Sta::minPeriodViolations() +Sta::minPeriodViolations(const Corner *corner) { minPeriodPreamble(); - return check_min_periods_->violations(); + return check_min_periods_->violations(corner); } MinPeriodCheck * -Sta::minPeriodSlack() +Sta::minPeriodSlack(const Corner *corner) { minPeriodPreamble(); - return check_min_periods_->minSlackCheck(); + return check_min_periods_->minSlackCheck(corner); } void diff --git a/search/Sta.hh b/search/Sta.hh index 1a818614..c8eedaca 100644 --- a/search/Sta.hh +++ b/search/Sta.hh @@ -173,6 +173,7 @@ public: // Set net wire capacitance (set_load -wire net). void setNetWireCap(Net *net, bool subtract_pin_load, + const Corner *corner, const MinMaxAll *min_max, float cap); // Port external fanout (used by wireload models). @@ -188,11 +189,13 @@ public: // wire_cap = annotated net capacitance + port external wire capacitance. void connectedCap(Pin *drvr_pin, const TransRiseFall *tr, + const Corner *corner, const MinMax *min_max, float &pin_cap, float &wire_cap) const; void connectedCap(Net *net, const TransRiseFall *tr, + const Corner *corner, const MinMax *min_max, float &pin_cap, float &wire_cap) const; @@ -605,39 +608,53 @@ public: ClockSet &clks); // Return the pin with the min/max slew limit slack. - Pin *pinMinSlewLimitSlack(const MinMax *min_max); + // corner=NULL checks all corners. + Pin *pinMinSlewLimitSlack(const Corner *corner, + const MinMax *min_max); // Return all pins with min/max slew violations. - PinSeq *pinSlewLimitViolations(const MinMax *min_max); + // corner=NULL checks all corners. + PinSeq *pinSlewLimitViolations(const Corner *corner, + const MinMax *min_max); void reportSlewLimitShortHeader(); void reportSlewLimitShort(Pin *pin, + const Corner *corner, const MinMax *min_max); void reportSlewLimitVerbose(Pin *pin, + const Corner *corner, const MinMax *min_max); void checkSlews(const Pin *pin, + const Corner *corner, const MinMax *min_max, // Return values. - const Corner *&corner, + const Corner *&corner1, const TransRiseFall *&tr, Slew &slew, float &limit, float &slack); // Min pulse width check with the least slack. - MinPulseWidthCheck *minPulseWidthSlack(); + // corner=NULL checks all corners. + MinPulseWidthCheck *minPulseWidthSlack(const Corner *corner); // All violating min pulse width checks. - MinPulseWidthCheckSeq &minPulseWidthViolations(); + // corner=NULL checks all corners. + MinPulseWidthCheckSeq &minPulseWidthViolations(const Corner *corner); // Min pulse width checks for pins. - MinPulseWidthCheckSeq &minPulseWidthChecks(PinSeq *pins); + // corner=NULL checks all corners. + MinPulseWidthCheckSeq &minPulseWidthChecks(PinSeq *pins, + const Corner *corner); // All min pulse width checks. - MinPulseWidthCheckSeq &minPulseWidthChecks(); + // corner=NULL checks all corners. + MinPulseWidthCheckSeq &minPulseWidthChecks(const Corner *corner); void reportMpwChecks(MinPulseWidthCheckSeq *checks, bool verbose); void reportMpwCheck(MinPulseWidthCheck *check, bool verbose); // Min period check with the least slack. - MinPeriodCheck *minPeriodSlack(); + // corner=NULL checks all corners. + MinPeriodCheck *minPeriodSlack(const Corner *corner); // All violating min period checks. - MinPeriodCheckSeq &minPeriodViolations(); + // corner=NULL checks all corners. + MinPeriodCheckSeq &minPeriodViolations(const Corner *corner); void reportChecks(MinPeriodCheckSeq *checks, bool verbose); void reportCheck(MinPeriodCheck *check, @@ -836,13 +853,6 @@ public: bool removal, bool clk_gating_setup, bool clk_gating_hold) __attribute__ ((deprecated)); - PathEndSeq *reportCheckTypes(bool all_violators, - bool setup, - bool hold, - bool recovery, - bool removal, - bool clock_gating_setup, - bool clock_gating_hold); void setReportPathFormat(ReportPathFormat format); void setReportPathFieldOrder(StringSeq *field_names); void setReportPathFields(bool report_input_pin, @@ -854,6 +864,7 @@ public: void setReportPathNoSplit(bool no_split); // Report clk skews for clks. void reportClkSkew(ClockSet *clks, + const Corner *corner, const SetupHold *setup_hold, int digits); void reportPathEnds(PathEndSeq *ends); @@ -977,10 +988,10 @@ public: TimingArc *arc, DcalcAnalysisPt *dcalc_ap); // Set/unset the back-annotation flag for a timing arc. - void setArcDelayAnnotated(bool annotated, - Edge *edge, + void setArcDelayAnnotated(Edge *edge, TimingArc *arc, - DcalcAnalysisPt *dcalc_ap); + DcalcAnalysisPt *dcalc_ap, + bool annotated); // Make sure levels are up to date and return vertex level. Level vertexLevel(Vertex *vertex); GraphLoopSeq *graphLoops(); diff --git a/tcl/Network.tcl b/tcl/Network.tcl index 0a2123af..4a4acb33 100644 --- a/tcl/Network.tcl +++ b/tcl/Network.tcl @@ -324,9 +324,10 @@ proc net_connected_pins_sorted { net } { } proc report_net_caps { net pins digits } { - report_net_cap $net "Pin" "pin_capacitance" $digits - report_net_cap $net "Wire" "wire_capacitance" $digits - report_net_cap $net "Total" "capacitance" $digits + set corner [default_corner] + report_net_cap $net "Pin" "pin_capacitance" $corner $digits + report_net_cap $net "Wire" "wire_capacitance" $corner $digits + report_net_cap $net "Total" "capacitance" $corner $digits set pin_count 0 set driver_count 0 @@ -347,11 +348,11 @@ proc report_net_caps { net pins digits } { puts "" } -proc report_net_cap { net caption cap_msg digits } { - set cap_r_min [$net $cap_msg "rise" "min"] - set cap_r_max [$net $cap_msg "rise" "max"] - set cap_f_min [$net $cap_msg "fall" "min"] - set cap_f_max [$net $cap_msg "fall" "max"] +proc report_net_cap { net caption cap_msg corner digits } { + set cap_r_min [$net $cap_msg "rise" $corner "min"] + set cap_r_max [$net $cap_msg "rise" $corner "max"] + set cap_f_min [$net $cap_msg "fall" $corner "min"] + set cap_f_max [$net $cap_msg "fall" $corner "max"] puts " $caption capacitance: [capacitances_str $cap_r_min $cap_r_max $cap_f_min $cap_f_max $digits]" } diff --git a/tcl/Sdc.tcl b/tcl/Sdc.tcl index b7c75261..60f95e6a 100644 --- a/tcl/Sdc.tcl +++ b/tcl/Sdc.tcl @@ -2356,18 +2356,20 @@ proc set_input_transition { args } { ################################################################ define_cmd_args "set_load" \ - {[-rise] [-fall] [-max] [-min] [-subtract_pin_load] [-pin_load] [-wire_load]\ - capacitance objects} + {[-rise] [-fall] [-max] [-min] [-corner corner] [-subtract_pin_load]\ + [-pin_load] [-wire_load] capacitance objects} proc set_load { args } { parse_key_args "set_load" args keys {} \ - flags {-rise -fall -min -max -subtract_pin_load -pin_load -wire_load} + flags {-rise -fall -min -max -corner -subtract_pin_load \ + -pin_load -wire_load} check_argc_eq2 "set_load" $args set pin_load [info exists flags(-pin_load)] set wire_load [info exists flags(-wire_load)] set subtract_pin_load [info exists flags(-subtract_pin_load)] + set corner [parse_corner keys] set min_max [parse_min_max_all_check_flags flags] set tr [parse_rise_fall_flags flags] @@ -2399,7 +2401,7 @@ proc set_load { args } { sta_warn "-rise/-fall not allowed for net objects." } foreach net $nets { - set_net_wire_cap $net $subtract_pin_load $min_max $cap + set_net_wire_cap $net $subtract_pin_load $corner $min_max $cap } } } diff --git a/tcl/Search.tcl b/tcl/Search.tcl index 2260aa3a..69e9e0e9 100644 --- a/tcl/Search.tcl +++ b/tcl/Search.tcl @@ -288,36 +288,36 @@ proc parse_path_group_arg { group_names } { return $names } -proc report_slew_limits { min_max all_violators verbose nosplit } { +proc report_slew_limits { corner min_max all_violators verbose nosplit } { if { $all_violators } { - set violators [pin_slew_limit_violations $min_max] + set violators [pin_slew_limit_violations $corner $min_max] if { $violators != {} } { puts "${min_max}_transition" puts "" if { $verbose } { foreach pin $violators { - report_slew_limit_verbose $pin $min_max + report_slew_limit_verbose $pin $corner $min_max puts "" } } else { report_slew_limit_short_header foreach pin $violators { - report_slew_limit_short $pin $min_max + report_slew_limit_short $pin $corner $min_max } puts "" } } } else { - set pin [pin_min_slew_limit_slack $min_max] + set pin [pin_min_slew_limit_slack $corner $min_max] if { $pin != "NULL" } { puts "${min_max}_transition" puts "" if { $verbose } { - report_slew_limit_verbose $pin $min_max + report_slew_limit_verbose $pin $corner $min_max puts "" } else { report_slew_limit_short_header - report_slew_limit_short $pin $min_max + report_slew_limit_short $pin $corner $min_max puts "" } } diff --git a/tcl/Sta.tcl b/tcl/Sta.tcl index 73c4dff7..d3b90942 100644 --- a/tcl/Sta.tcl +++ b/tcl/Sta.tcl @@ -99,15 +99,16 @@ proc find_timing { args } { ################################################################ -define_sta_cmd_args "report_clock_skew" {[-setup|-hold] \ - [-clock clocks] \ +define_sta_cmd_args "report_clock_skew" {[-setup|-hold]\ + [-clock clocks]\ + [-corner corner_name]]\ [-digits digits]} proc_redirect report_clock_skew { global sta_report_default_digits parse_key_args "report_clock_skew" args \ - keys {-clock -digits} flags {-setup -hold} + keys {-clock -corner -digits} flags {-setup -hold} check_argc_eq0 "report_clock_skew" $args if { [info exists flags(-setup)] && [info exists flags(-hold)] } { @@ -125,13 +126,14 @@ proc_redirect report_clock_skew { } else { set clks [all_clocks] } + set corner [parse_corner_or_all keys] if [info exists keys(-digits)] { set digits $keys(-digits) check_positive_integer "-digits" $digits } else { set digits $sta_report_default_digits } - report_clk_skew $clks $setup_hold $digits + report_clk_skew $clks $corner $setup_hold $digits } ################################################################ @@ -141,10 +143,10 @@ define_sta_cmd_args "report_checks" \ [-through through_list|-rise_through through_list|-fall_through through_list]\ [-to to_list|-rise_to to_list|-fall_to to_list]\ [-path_delay min|min_rise|min_fall|max|max_rise|max_fall|min_max]\ + [-corner corner_name]\ [-group_count path_count] \ [-endpoint_count path_count]\ [-unique_paths_to_endpoint]\ - [-corner corner_name]\ [-slack_max slack_max]\ [-slack_min slack_min]\ [-sort_by_slack]\ @@ -161,7 +163,7 @@ proc_redirect report_checks { parse_key_args "report_checks" args \ keys {-from -rise_from -fall_from -to -rise_to -fall_to \ - -path_delay -group_count -endpoint_count -corner \ + -path_delay -corner -group_count -endpoint_count \ -slack_max -slack_min -path_group} \ flags {-sort_by_slack -unique_paths_to_endpoint} 0 @@ -203,6 +205,8 @@ proc_redirect report_checks { check_for_key_args $cmd args + set corner [parse_corner_or_all keys] + set endpoint_count 1 if [info exists keys(-endpoint_count)] { set endpoint_count $keys(-endpoint_count) @@ -221,8 +225,6 @@ proc_redirect report_checks { set unique_pins [info exists flags(-unique_paths_to_endpoint)] - set corner [parse_corner_or_all keys] - set slack_min "-1e+30" if [info exist keys(-slack_min)] { set slack_min $keys(-slack_min) @@ -254,10 +256,11 @@ proc_redirect report_checks { } } - set path_ends [find_path_ends $from $thrus $to $min_max \ - $group_count $endpoint_count $unique_pins $corner \ + set path_ends [find_path_ends $from $thrus $to $corner $min_max \ + $group_count $endpoint_count $unique_pins \ $slack_min $slack_max \ - $sort_by_slack $groups] + $sort_by_slack $groups \ + 1 1 1 1 1 1] if { [$path_ends empty] } { if { $sta_report_unconstrained_paths } { puts "No paths." @@ -274,6 +277,7 @@ proc_redirect report_checks { define_sta_cmd_args "report_check_types" \ {[-all_violators] [-verbose]\ + [-corner corner_name]\ [-format slack_only|end]\ [-max_delay] [-min_delay]\ [-recovery] [-removal]\ @@ -286,7 +290,7 @@ define_sta_cmd_args "report_check_types" \ proc_redirect report_check_types { variable path_options - parse_key_args "report_check_types" args keys {}\ + parse_key_args "report_check_types" args keys {-corner}\ flags {-all_violators -verbose -no_line_splits} 0 set all_violators [info exists flags(-all_violators)] @@ -305,6 +309,8 @@ proc_redirect report_check_types { set min_max "max" } + set corner [parse_corner_or_all keys] + if { $args == {} } { if { $min_max == "max" || $min_max == "min_max" } { set setup 1 @@ -362,9 +368,32 @@ proc_redirect report_check_types { sta_error "positional arguments not supported." } + set corner [parse_corner_or_all keys] + if { $setup || $hold || $recovery || $removal \ || $clk_gating_setup || $clk_gating_hold } { - set path_ends [report_check_types_cmd $all_violators \ + if { ($setup && $hold) \ + || ($recovery && $removal) \ + || ($clk_gating_setup && $clk_gating_hold) } { + set path_min_max "min_max" + } elseif { $setup || $recovery || $clk_gating_setup } { + set path_min_max "max" + } elseif { $hold || $removal || $clk_gating_hold } { + set path_min_max "min" + } + if { $all_violators } { + set group_count $sta::int_max + set slack_min [expr -$sta::float_inf] + set slack_max 0.0 + } else { + set group_count 1 + set slack_min [expr -$sta::float_inf] + set slack_max $sta::float_inf + } + set path_ends [find_path_ends "NULL" {} "NULL" \ + $corner $path_min_max $group_count 1 0 \ + $slack_min $slack_max \ + 0 {} \ $setup $hold \ $recovery $removal \ $clk_gating_setup $clk_gating_hold] @@ -373,17 +402,17 @@ proc_redirect report_check_types { } if { $max_transition } { - report_slew_limits "max" $all_violators $verbose $nosplit + report_slew_limits $corner "max" $all_violators $verbose $nosplit } if { $min_transition } { - report_slew_limits "min" $all_violators $verbose $nosplit + report_slew_limits $corner "min" $all_violators $verbose $nosplit } if { $min_pulse_width } { if { $all_violators } { - set checks [min_pulse_width_violations] + set checks [min_pulse_width_violations $corner] report_mpw_checks $checks $verbose } else { - set check [min_pulse_width_check_slack] + set check [min_pulse_width_check_slack $corner] if { $check != "NULL" } { report_mpw_check $check $verbose } @@ -391,10 +420,10 @@ proc_redirect report_check_types { } if { $min_period } { if { $all_violators } { - set checks [min_period_violations] + set checks [min_period_violations $corner] report_min_period_checks $checks $verbose } else { - set check [min_period_check_slack] + set check [min_period_check_slack $corner] if { $check != "NULL" } { report_min_period_check $check $verbose } @@ -429,22 +458,24 @@ define_sta_cmd_args "report_disabled_edges" {} ################################################################ define_sta_cmd_args "report_pulse_width_checks" \ - {[-verbose] [-digits digits] [-no_line_splits] [pins]\ + {[-verbose] [-corner corner_name] [-digits digits] [-no_line_splits] [pins]\ [> filename] [>> filename]} proc_redirect report_pulse_width_checks { variable path_options - parse_key_args "report_pulse_width_checks" args keys {} flags {-verbose} 0 + parse_key_args "report_pulse_width_checks" args keys {-corner} \ + flags {-verbose} 0 # Only -digits and -no_line_splits are respected. parse_report_path_options "report_pulse_width_checks" args "full" 0 check_argc_eq0or1 "report_pulse_width_checks" $args + set corner [parse_corner_or_all keys] set verbose [info exists flags(-verbose)] if { [llength $args] == 1 } { set pins [get_port_pins_error "pins" [lindex $args 0]] - set checks [min_pulse_width_check_pins $pins] + set checks [min_pulse_width_check_pins $pins $corner] } else { - set checks [min_pulse_width_checks] + set checks [min_pulse_width_checks $corner] } if { $checks != {} } { report_mpw_checks $checks $verbose diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index 5b63ead6..e1281337 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -2318,6 +2318,9 @@ private: %inline %{ +float float_inf = INF; +int int_max = std::numeric_limits::max(); + const char * version() { @@ -3163,10 +3166,11 @@ set_port_ext_fanout_cmd(Port *port, void set_net_wire_cap(Net *net, bool subtract_pin_cap, + Corner *corner, const MinMaxAll *min_max, float cap) { - Sta::sta()->setNetWireCap(net, subtract_pin_cap, min_max, cap); + Sta::sta()->setNetWireCap(net, subtract_pin_cap, corner, min_max, cap); } void @@ -4414,15 +4418,21 @@ PathEndSeq * find_path_ends(ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, + Corner *corner, const MinMaxAll *delay_min_max, int group_count, int endpoint_count, bool unique_pins, - Corner *corner, float slack_min, float slack_max, bool sort_by_slack, - PathGroupNameSet *groups) + PathGroupNameSet *groups, + bool setup, + bool hold, + bool recovery, + bool removal, + bool clk_gating_setup, + bool clk_gating_hold) { cmdLinkedNetwork(); Sta *sta = Sta::sta(); @@ -4430,30 +4440,15 @@ find_path_ends(ExceptionFrom *from, corner, delay_min_max, group_count, endpoint_count, unique_pins, slack_min, slack_max, - sort_by_slack, groups, - true, true, // setup, hold - true, true, // recovery, removal - true, true); // clk gating setup, hold + sort_by_slack, + groups->size() ? groups : NULL, + setup, hold, + recovery, removal, + clk_gating_setup, clk_gating_hold); delete groups; return ends; } -PathEndSeq * -report_check_types_cmd(bool all_violators, - bool setup, - bool hold, - bool recovery, - bool removal, - bool clock_gating_setup, - bool clock_gating_hold) -{ - cmdLinkedNetwork(); - return Sta::sta()->reportCheckTypes(all_violators, - setup, hold, - recovery, removal, - clock_gating_setup, clock_gating_hold); -} - void set_report_path_format(ReportPathFormat format) { @@ -4537,11 +4532,12 @@ report_path_cmd(Path *path) void report_clk_skew(ClockSet *clks, + const Corner *corner, const SetupHold *setup_hold, int digits) { cmdLinkedNetwork(); - Sta::sta()->reportClkSkew(clks, setup_hold, digits); + Sta::sta()->reportClkSkew(clks, corner, setup_hold, digits); delete clks; } @@ -4577,33 +4573,35 @@ group_path_pins(const char *group_path_name) //////////////////////////////////////////////////////////////// MinPulseWidthCheckSeq & -min_pulse_width_violations() +min_pulse_width_violations(const Corner *corner) { cmdLinkedNetwork(); - return Sta::sta()->minPulseWidthViolations(); + return Sta::sta()->minPulseWidthViolations(corner); } MinPulseWidthCheckSeq & -min_pulse_width_check_pins(PinSeq *pins) +min_pulse_width_check_pins(PinSeq *pins, + const Corner *corner) { cmdLinkedNetwork(); - MinPulseWidthCheckSeq &checks = Sta::sta()->minPulseWidthChecks(pins); + Sta *sta = Sta::sta(); + MinPulseWidthCheckSeq &checks = sta->minPulseWidthChecks(pins, corner); delete pins; return checks; } MinPulseWidthCheckSeq & -min_pulse_width_checks() +min_pulse_width_checks(const Corner *corner) { cmdLinkedNetwork(); - return Sta::sta()->minPulseWidthChecks(); + return Sta::sta()->minPulseWidthChecks(corner); } MinPulseWidthCheck * -min_pulse_width_check_slack() +min_pulse_width_check_slack(const Corner *corner) { cmdLinkedNetwork(); - return Sta::sta()->minPulseWidthSlack(); + return Sta::sta()->minPulseWidthSlack(corner); } void @@ -4623,17 +4621,17 @@ report_mpw_check(MinPulseWidthCheck *check, //////////////////////////////////////////////////////////////// MinPeriodCheckSeq & -min_period_violations() +min_period_violations(const Corner *corner) { cmdLinkedNetwork(); - return Sta::sta()->minPeriodViolations(); + return Sta::sta()->minPeriodViolations(corner); } MinPeriodCheck * -min_period_check_slack() +min_period_check_slack(const Corner *corner) { cmdLinkedNetwork(); - return Sta::sta()->minPeriodSlack(); + return Sta::sta()->minPeriodSlack(corner); } void @@ -4779,17 +4777,19 @@ report_delay_calc_cmd(Edge *edge, } Pin * -pin_min_slew_limit_slack(const MinMax *min_max) +pin_min_slew_limit_slack(const Corner *corner, + const MinMax *min_max) { cmdLinkedNetwork(); - return Sta::sta()->pinMinSlewLimitSlack(min_max); + return Sta::sta()->pinMinSlewLimitSlack(corner, min_max); } PinSeq * -pin_slew_limit_violations(const MinMax *min_max) +pin_slew_limit_violations(const Corner *corner, + const MinMax *min_max) { cmdLinkedNetwork(); - return Sta::sta()->pinSlewLimitViolations(min_max); + return Sta::sta()->pinSlewLimitViolations(corner, min_max); } void @@ -4800,16 +4800,18 @@ report_slew_limit_short_header() void report_slew_limit_short(Pin *pin, + const Corner *corner, const MinMax *min_max) { - Sta::sta()->reportSlewLimitShort(pin, min_max); + Sta::sta()->reportSlewLimitShort(pin, corner, min_max); } void report_slew_limit_verbose(Pin *pin, + const Corner *corner, const MinMax *min_max) { - Sta::sta()->reportSlewLimitVerbose(pin, min_max); + Sta::sta()->reportSlewLimitVerbose(pin, corner, min_max); } EdgeSeq * @@ -4937,13 +4939,14 @@ unset_clock_groups_asynchronous(const char *name) Sta::sta()->removeClockGroupsAsynchronous(name); } +// Debugging function. bool same_clk_group(Clock *clk1, Clock *clk2) { Sta *sta = Sta::sta(); Sdc *sdc = sta->sdc(); - return sdc->sameClockGroup(clk1, clk2); + return sdc->sameClockGroupExplicit(clk1, clk2); } void @@ -5725,31 +5728,34 @@ vertices() float capacitance(const TransRiseFall *tr, + const Corner *corner, const MinMax *min_max) { cmdLinkedNetwork(); float pin_cap, wire_cap; - Sta::sta()->connectedCap(self, tr, min_max, pin_cap, wire_cap); + Sta::sta()->connectedCap(self, tr, corner, min_max, pin_cap, wire_cap); return pin_cap + wire_cap; } float pin_capacitance(const TransRiseFall *tr, + const Corner *corner, const MinMax *min_max) { cmdLinkedNetwork(); float pin_cap, wire_cap; - Sta::sta()->connectedCap(self, tr, min_max, pin_cap, wire_cap); + Sta::sta()->connectedCap(self, tr, corner, min_max, pin_cap, wire_cap); return pin_cap; } float wire_capacitance(const TransRiseFall *tr, + const Corner *corner, const MinMax *min_max) { cmdLinkedNetwork(); float pin_cap, wire_cap; - Sta::sta()->connectedCap(self, tr, min_max, pin_cap, wire_cap); + Sta::sta()->connectedCap(self, tr, corner, min_max, pin_cap, wire_cap); return wire_cap; } @@ -5786,31 +5792,34 @@ bool is_ground() { return cmdLinkedNetwork()->isGround(self);} float capacitance(const TransRiseFall *tr, + const Corner *corner, const MinMax *min_max) { cmdLinkedNetwork(); float pin_cap, wire_cap; - Sta::sta()->connectedCap(self, tr, min_max, pin_cap, wire_cap); + Sta::sta()->connectedCap(self, tr, corner, min_max, pin_cap, wire_cap); return pin_cap + wire_cap; } float pin_capacitance(const TransRiseFall *tr, + const Corner *corner, const MinMax *min_max) { cmdLinkedNetwork(); float pin_cap, wire_cap; - Sta::sta()->connectedCap(self, tr, min_max, pin_cap, wire_cap); + Sta::sta()->connectedCap(self, tr, corner, min_max, pin_cap, wire_cap); return pin_cap; } float wire_capacitance(const TransRiseFall *tr, + const Corner *corner, const MinMax *min_max) { cmdLinkedNetwork(); float pin_cap, wire_cap; - Sta::sta()->connectedCap(self, tr, min_max, pin_cap, wire_cap); + Sta::sta()->connectedCap(self, tr, corner, min_max, pin_cap, wire_cap); return wire_cap; } diff --git a/verilog/VerilogLex.ll b/verilog/VerilogLex.ll index 47d658f6..550c091b 100644 --- a/verilog/VerilogLex.ll +++ b/verilog/VerilogLex.ll @@ -43,6 +43,7 @@ verilogFlushBuffer() %option never-interactive %x COMMENT +%x ATTRIBUTE %x QSTRING SIGN "+"|"-" @@ -78,6 +79,21 @@ ID_TOKEN {ID_ESCAPED_TOKEN}|{ID_ALPHA_TOKEN} } } +"(*" { BEGIN ATTRIBUTE; } +{ +. + +{EOL} { sta::verilog_reader->incrLine(); } + +"*)" { BEGIN INITIAL; } + +<> { + VerilogParse_error("unterminated attribute"); + BEGIN(INITIAL); + yyterminate(); + } +} + {SIGN}?{UNSIGNED_NUMBER}?"'"[bB][01_xz]+ { VerilogParse_lval.constant = sta::stringCopy(VerilogLex_text); return CONSTANT;