diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index d770c367..88ea2b3e 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -604,14 +604,13 @@ public: ClockSet &clks); void checkSlewLimitPreamble(); - // Return the pin with the min/max slew limit slack. + // Return pins with the min/max slew limit slack. + // net=null check all nets // corner=nullptr checks all corners. - Pin *pinMinSlewLimitSlack(const Corner *corner, - const MinMax *min_max); - // Return all pins with min/max slew violations. - // corner=nullptr checks all corners. - PinSeq *pinSlewLimitViolations(const Corner *corner, - const MinMax *min_max); + PinSeq *checkSlewLimits(Net *net, + bool violators, + const Corner *corner, + const MinMax *min_max); void reportSlewLimitShortHeader(); void reportSlewLimitShort(Pin *pin, const Corner *corner, diff --git a/search/CheckSlewLimits.cc b/search/CheckSlewLimits.cc index 36ebe488..f8fab364 100644 --- a/search/CheckSlewLimits.cc +++ b/search/CheckSlewLimits.cc @@ -279,88 +279,83 @@ CheckSlewLimits::checkSlew(Vertex *vertex, } PinSeq * -CheckSlewLimits::pinSlewLimitViolations(const Corner *corner, - const MinMax *min_max) +CheckSlewLimits::checkSlewLimits(Net *net, + bool violators, + const Corner *corner, + const MinMax *min_max) { const Network *network = sta_->network(); - PinSeq *violators = new PinSeq; - LeafInstanceIterator *inst_iter = network->leafInstanceIterator(); - while (inst_iter->hasNext()) { - Instance *inst = inst_iter->next(); - pinSlewLimitViolations(inst, corner, min_max, violators); + PinSeq *slew_pins = new PinSeq; + Slack min_slack = MinMax::min()->initValue(); + if (net) { + NetPinIterator *pin_iter = network->pinIterator(net); + while (pin_iter->hasNext()) { + Pin *pin = pin_iter->next(); + checkSlewLimits(pin, violators, corner, min_max, slew_pins, min_slack); + } + delete pin_iter; } - delete inst_iter; - // Check top level ports. - pinSlewLimitViolations(network->topInstance(), corner, min_max, violators); - sort(violators, PinSlewLimitSlackLess(corner, min_max, this, sta_)); - return violators; + else { + LeafInstanceIterator *inst_iter = network->leafInstanceIterator(); + while (inst_iter->hasNext()) { + Instance *inst = inst_iter->next(); + checkSlewLimits(inst, violators,corner, min_max, slew_pins, min_slack); + } + delete inst_iter; + // Check top level ports. + checkSlewLimits(network->topInstance(), violators, corner, min_max, + slew_pins, min_slack); + } + sort(slew_pins, PinSlewLimitSlackLess(corner, min_max, this, sta_)); + // Keep the min slack pin unless all violators or net pins. + if (!slew_pins->empty() && !violators && net == nullptr) + slew_pins->resize(1); + return slew_pins; } void -CheckSlewLimits::pinSlewLimitViolations(Instance *inst, - const Corner *corner, - const MinMax *min_max, - PinSeq *violators) +CheckSlewLimits::checkSlewLimits(Instance *inst, + bool violators, + const Corner *corner, + const MinMax *min_max, + PinSeq *slew_pins, + float &min_slack) { const Network *network = sta_->network(); InstancePinIterator *pin_iter = network->pinIterator(inst); while (pin_iter->hasNext()) { Pin *pin = pin_iter->next(); - const Corner *corner1; - const RiseFall *rf; - Slew slew; - float limit, slack; - checkSlew(pin, corner, min_max, true, corner1, rf, slew, limit, slack); - if (rf && slack < 0.0 && !fuzzyInf(slack)) - violators->push_back(pin); + checkSlewLimits(pin, violators, corner, min_max, slew_pins, min_slack); } delete pin_iter; } -Pin * -CheckSlewLimits::pinMinSlewLimitSlack(const Corner *corner, - const MinMax *min_max) -{ - const Network *network = sta_->network(); - Pin *min_slack_pin = nullptr; - float min_slack = MinMax::min()->initValue(); - LeafInstanceIterator *inst_iter = network->leafInstanceIterator(); - while (inst_iter->hasNext()) { - Instance *inst = inst_iter->next(); - pinMinSlewLimitSlack(inst, corner, min_max, min_slack_pin, min_slack); - } - delete inst_iter; - // Check top level ports. - 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, - float &min_slack) +CheckSlewLimits::checkSlewLimits(Pin *pin, + bool violators, + const Corner *corner, + const MinMax *min_max, + PinSeq *slew_pins, + float &min_slack) { - const Network *network = sta_->network(); - InstancePinIterator *pin_iter = network->pinIterator(inst); - while (pin_iter->hasNext()) { - Pin *pin = pin_iter->next(); - const Corner *corner1; - const RiseFall *rf; - Slew slew; - float limit, slack; - checkSlew(pin, corner, min_max, true, corner1, rf, slew, limit, slack); - if (rf - && (min_slack_pin == nullptr - || slack < min_slack)) { - min_slack_pin = pin; - min_slack = slack; + const Corner *corner1; + const RiseFall *rf; + Slew slew; + float limit, slack; + checkSlew(pin, corner, min_max, true, corner1, rf, slew, limit, slack); + if (!fuzzyInf(slack)) { + if (violators) { + if (slack < 0.0) + slew_pins->push_back(pin); + } + else { + if (slew_pins->empty() + || slack < min_slack) { + slew_pins->push_back(pin); + min_slack = slack; + } } } - delete pin_iter; } } // namespace diff --git a/search/CheckSlewLimits.hh b/search/CheckSlewLimits.hh index 8c65a049..d254d87e 100644 --- a/search/CheckSlewLimits.hh +++ b/search/CheckSlewLimits.hh @@ -45,12 +45,13 @@ public: Slew &slew, float &limit, float &slack) const; + // Return pins with the min/max slew limit slack. + // net=null check all nets // corner=nullptr checks all corners. - PinSeq *pinSlewLimitViolations(const Corner *corner, - const MinMax *min_max); - // corner=nullptr checks all corners. - Pin *pinMinSlewLimitSlack(const Corner *corner, - const MinMax *min_max); + PinSeq *checkSlewLimits(Net *net, + bool violators, + const Corner *corner, + const MinMax *min_max); protected: void checkSlews1(const Pin *pin, @@ -92,16 +93,18 @@ protected: // Return values. 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, - float &min_slack); + void checkSlewLimits(Instance *inst, + bool violators, + const Corner *corner, + const MinMax *min_max, + PinSeq *slew_pins, + float &min_slack); + void checkSlewLimits(Pin *pin, + bool violators, + const Corner *corner, + const MinMax *min_max, + PinSeq *slew_pins, + float &min_slack); void clockDomains(const Vertex *vertex, // Return value. ClockSet &clks) const; diff --git a/search/Sta.cc b/search/Sta.cc index e88a93ff..22a3696f 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -4883,20 +4883,14 @@ Sta::checkSlewLimitPreamble() ensureClkNetwork(); } -Pin * -Sta::pinMinSlewLimitSlack(const Corner *corner, - const MinMax *min_max) -{ - checkSlewLimitPreamble(); - return check_slew_limits_->pinMinSlewLimitSlack(corner, min_max); -} - PinSeq * -Sta::pinSlewLimitViolations(const Corner *corner, - const MinMax *min_max) +Sta::checkSlewLimits(Net *net, + bool violators, + const Corner *corner, + const MinMax *min_max) { checkSlewLimitPreamble(); - return check_slew_limits_->pinSlewLimitViolations(corner, min_max); + return check_slew_limits_->checkSlewLimits(net, violators, corner, min_max); } void diff --git a/tcl/Search.tcl b/tcl/Search.tcl index ea205b7e..b28e0a99 100644 --- a/tcl/Search.tcl +++ b/tcl/Search.tcl @@ -382,38 +382,22 @@ proc parse_path_group_arg { group_names } { return $names } -proc report_slew_limits { corner min_max all_violators verbose nosplit } { - if { $all_violators } { - set violators [pin_slew_limit_violations $corner $min_max] - if { $violators != {} } { - report_line "${min_max} slew" - report_line "" - if { $verbose } { - foreach pin $violators { - report_slew_limit_verbose $pin $corner $min_max - report_line "" - } - } else { - report_slew_limit_short_header - foreach pin $violators { - report_slew_limit_short $pin $corner $min_max - } - report_line "" +proc report_slew_limits { net corner min_max violators verbose nosplit } { + set pins [check_slew_limits $net $violators $corner $min_max] + if { $pins != {} } { + report_line "${min_max} slew" + report_line "" + if { $verbose } { + foreach pin $pins { + report_slew_limit_verbose $pin $corner $min_max + report_line "" } - } - } else { - set pin [pin_min_slew_limit_slack $corner $min_max] - if { $pin != "NULL" } { - report_line "${min_max} slew" - report_line "" - if { $verbose } { - report_slew_limit_verbose $pin $corner $min_max - report_line "" - } else { - report_slew_limit_short_header - report_slew_limit_short $pin $corner $min_max - report_line "" + } else { + report_slew_limit_short_header + foreach pin $pins { + report_slew_limit_short $pin $corner $min_max } + report_line "" } } } diff --git a/tcl/Sta.tcl b/tcl/Sta.tcl index 02680dc6..16a5a96a 100644 --- a/tcl/Sta.tcl +++ b/tcl/Sta.tcl @@ -322,13 +322,14 @@ define_sta_cmd_args "report_check_types" \ [-max_fanout] [-min_fanout]\ [-max_capacitance] [-min_capacitance]\ [-min_pulse_width] [-min_period] [-max_skew]\ + [-net net]\ [-digits digits] [-no_line_splits]\ [> filename] [>> filename]} proc_redirect report_check_types { variable path_options - parse_key_args "report_check_types" args keys {-corner}\ + parse_key_args "report_check_types" args keys {-net -corner}\ flags {-violators -all_violators -verbose -no_line_splits} 0 set violators [info exists flags(-violators)] @@ -354,6 +355,11 @@ proc_redirect report_check_types { set corner [parse_corner_or_all keys] + set net "NULL" + if { [info exists keys(-net)] } { + set net [get_net_warn "-net" $keys(-net)] + } + if { $args == {} } { if { $min_max == "max" || $min_max == "min_max" } { set setup 1 @@ -468,10 +474,10 @@ proc_redirect report_check_types { } if { $max_slew } { - report_slew_limits $corner "max" $violators $verbose $nosplit + report_slew_limits $net $corner "max" $violators $verbose $nosplit } if { $min_slew } { - report_slew_limits $corner "min" $violators $verbose $nosplit + report_slew_limits $net $corner "min" $violators $verbose $nosplit } if { $max_fanout } { report_fanout_limits "max" $violators $verbose $nosplit