2323#include " rsz/Resizer.hh"
2424#include " sta/Delay.hh"
2525#include " sta/ExceptionPath.hh"
26- #include " sta/FuncExpr.hh"
2726#include " sta/Fuzzy.hh"
2827#include " sta/Graph.hh"
2928#include " sta/GraphClass.hh"
3938#include " sta/Sdc.hh"
4039#include " sta/Search.hh"
4140#include " sta/SearchClass.hh"
42- #include " sta/Sequential.hh"
4341#include " sta/Sta.hh"
4442#include " sta/StringUtil.hh"
4543#include " sta/TimingArc.hh"
4644#include " sta/Transition.hh"
47- #include " sta/VisitPathEnds.hh"
4845#include " utl/Logger.h"
4946
5047namespace rsz {
@@ -815,9 +812,9 @@ void RepairTargetCollector::collectViolatingEndpoints()
815812
816813 const sta::VertexSet& endpoints = sta_->endpoints ();
817814 for (sta::Vertex* endpoint : endpoints) {
818- const sta::Slack effective_slack = getEndpointEffectiveSlack (endpoint);
819- if (sta::fuzzyLess (effective_slack , slack_margin_)) {
820- violating_endpoints_.emplace_back (endpoint->pin (), effective_slack );
815+ const sta::Slack slack = sta_-> slack (endpoint, max_ );
816+ if (sta::fuzzyLess (slack , slack_margin_)) {
817+ violating_endpoints_.emplace_back (endpoint->pin (), slack );
821818 }
822819 }
823820
@@ -835,144 +832,6 @@ void RepairTargetCollector::collectViolatingEndpoints()
835832 * 100 ));
836833}
837834
838- namespace {
839-
840- // Track the worst-slack constrained max path end at a vertex and record its
841- // latch time borrow. Non-latch path ends report zero borrow.
842- class WorstPathEndBorrowVisitor : public sta ::PathEndVisitor
843- {
844- public:
845- WorstPathEndBorrowVisitor (const sta::MinMax* min_max,
846- const sta::StaState* sta)
847- : min_max_(min_max), sta_(sta)
848- {
849- }
850- sta::PathEndVisitor* copy () const override
851- {
852- return new WorstPathEndBorrowVisitor (*this );
853- }
854- void visit (sta::PathEnd* path_end) override
855- {
856- if (path_end->isUnconstrained () || path_end->minMax (sta_) != min_max_) {
857- return ;
858- }
859- const sta::Slack end_slack = path_end->slack (sta_);
860- if (sta::delayLess (end_slack, worst_slack_, sta_)) {
861- worst_slack_ = end_slack;
862- borrow_ = path_end->borrow (sta_);
863- }
864- }
865- sta::Arrival borrow () const { return borrow_; }
866-
867- private:
868- const sta::MinMax* min_max_;
869- const sta::StaState* sta_;
870- sta::Slack worst_slack_ = sta::INF ;
871- sta::Arrival borrow_ = 0.0 ;
872- };
873-
874- } // namespace
875-
876- sta::Slack RepairTargetCollector::getEndpointEffectiveSlack (
877- sta::Vertex* endpoint) const
878- {
879- const sta::Slack reported_slack = sta_->slack (endpoint, max_);
880- if (sta::fuzzyGreater (reported_slack, slack_margin_)) {
881- return reported_slack;
882- }
883-
884- // Visit the path ends stored at this endpoint and read the time borrow of
885- // the worst-slack one. This avoids the heavyweight findPathEnds() machinery
886- // (exception filter, path group construction, sorting) per endpoint.
887- sta::VisitPathEnds visit_ends (sta_);
888- WorstPathEndBorrowVisitor borrow_visitor (max_, sta_);
889- visit_ends.visitPathEnds (endpoint, &borrow_visitor);
890-
891- const sta::Arrival borrow = borrow_visitor.borrow ();
892- if (sta::fuzzyLessEqual (borrow, 0 .0f )) {
893- return reported_slack;
894- }
895-
896- const std::vector<const sta::Pin*> output_pins = latchOutputPins (endpoint);
897- const sta::Slack output_slack = latchOutputWorstSlack (output_pins);
898- const sta::Slack uncovered_borrow
899- = std::max<float >(borrow - std::max<float >(output_slack, 0 .0f ), 0 .0f );
900- return reported_slack - uncovered_borrow;
901- }
902-
903- std::vector<const sta::Pin*> RepairTargetCollector::latchOutputPins (
904- sta::Vertex* endpoint) const
905- {
906- std::vector<const sta::Pin*> output_pins;
907- const std::function<void (
908- sta::Instance*, sta::LibertyCell*, sta::LibertyPort*)>
909- add_output_pin = [this , &output_pins](sta::Instance* inst,
910- sta::LibertyCell* cell,
911- sta::LibertyPort* state_port) {
912- const sta::Pin* output_pin = network_->findPin (inst, state_port);
913- if (output_pin != nullptr ) {
914- output_pins.push_back (output_pin);
915- return ;
916- }
917-
918- // Some libraries declare latch state as an internal port and expose it
919- // through an output pin function, for example Q = IQ.
920- sta::LibertyCellPortIterator port_iter (cell);
921- while (port_iter.hasNext ()) {
922- sta::LibertyPort* port = port_iter.next ();
923- sta::FuncExpr* func = port->function ();
924- if (!port->direction ()->isAnyOutput () || func == nullptr
925- || !func->hasPort (state_port)) {
926- continue ;
927- }
928-
929- output_pin = network_->findPin (inst, port);
930- if (output_pin != nullptr
931- && std::ranges::find (output_pins, output_pin)
932- == output_pins.end ()) {
933- output_pins.push_back (output_pin);
934- }
935- }
936- };
937-
938- const sta::Pin* endpoint_pin = endpoint->pin ();
939- sta::LibertyPort* data_port = network_->libertyPort (endpoint_pin);
940- sta::LibertyCell* cell = data_port->libertyCell ();
941- sta::Instance* inst = network_->instance (endpoint_pin);
942-
943- for (const sta::Sequential& seq : cell->sequentials ()) {
944- if (!seq.isLatch () || seq.data () == nullptr
945- || !seq.data ()->hasPort (data_port)) {
946- continue ;
947- }
948-
949- if (seq.output () != nullptr ) {
950- add_output_pin (inst, cell, seq.output ());
951- }
952- if (seq.outputInv () != nullptr ) {
953- add_output_pin (inst, cell, seq.outputInv ());
954- }
955- }
956-
957- return output_pins;
958- }
959-
960- sta::Slack RepairTargetCollector::latchOutputWorstSlack (
961- const std::vector<const sta::Pin*>& output_pins) const
962- {
963- sta::Slack worst_slack = sta::INF ;
964-
965- for (const sta::Pin* output_pin : output_pins) {
966- sta::Vertex* output_vertex = graph_->pinDrvrVertex (output_pin);
967- const sta::Slack output_slack = sta_->slack (output_vertex, max_);
968- if (sta::delayLess (output_slack, worst_slack, sta_)) {
969- worst_slack = output_slack;
970- }
971- }
972-
973- return worst_slack;
974- }
975-
976835void RepairTargetCollector::collectViolatingStartpoints ()
977836{
978837 violating_startpoints_.clear ();
0 commit comments