From 740fa7d16ce72bb241a8583ff94b693aa96f17f0 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 13 Jun 2026 16:31:24 -0700 Subject: [PATCH] input ref pin graph edges Signed-off-by: James Cherry --- include/sta/PortDelay.hh | 3 +++ include/sta/Sdc.hh | 6 ++++-- include/sta/Search.hh | 2 -- include/sta/TimingArc.hh | 4 ++++ include/sta/TimingRole.hh | 3 +++ liberty/TimingArc.cc | 4 ++++ liberty/TimingRole.cc | 2 ++ sdc/PortDelay.cc | 10 ++++++++++ sdc/Sdc.cc | 42 +++++++++++++++++++++------------------ search/Levelize.cc | 3 +++ search/Search.cc | 22 -------------------- 11 files changed, 56 insertions(+), 45 deletions(-) diff --git a/include/sta/PortDelay.hh b/include/sta/PortDelay.hh index ab71151a..7d4a3897 100644 --- a/include/sta/PortDelay.hh +++ b/include/sta/PortDelay.hh @@ -51,6 +51,8 @@ public: const Pin *refPin() const { return ref_pin_; } void setRefPin(const Pin *ref_pin); const RiseFall *refTransition() const; + bool refPinEdgesExist() const { return ref_pin_edges_exist_; } + void setRefPinEdgesExist(bool exists); protected: PortDelay(const Pin *pin, @@ -62,6 +64,7 @@ protected: bool source_latency_included_{false}; bool network_latency_included_{false}; const Pin *ref_pin_{nullptr}; + bool ref_pin_edges_exist_{false}; RiseFallMinMax delays_; PinSet leaf_pins_; }; diff --git a/include/sta/Sdc.hh b/include/sta/Sdc.hh index 3f7cd8e4..557beaa6 100644 --- a/include/sta/Sdc.hh +++ b/include/sta/Sdc.hh @@ -576,6 +576,7 @@ public: const Clock *clk, const RiseFall *clk_rf, const MinMaxAll *min_max); + void ensureInputDelayRefPinEdges(); void setOutputDelay(const Pin *pin, const RiseFallBoth *rf, const Clock *clk, @@ -806,7 +807,6 @@ public: const MinMaxAll *min_max); // STA interface. - InputDelaySet *refPinInputDelays(const Pin *ref_pin) const; const LogicValueMap &logicValues() const { return logic_value_map_; } const LogicValueMap &caseLogicValues() const { return case_value_map_; } // Returns nullptr if set_operating_conditions has not been called. @@ -1217,6 +1217,7 @@ protected: InputDelay *except); void deleteInputDelaysReferencing(const Clock *clk); void deleteInputDelay(InputDelay *input_delay); + OutputDelay *findOutputDelay(const Pin *pin, const ClockEdge *clk_edge); OutputDelay *makeOutputDelay(const Pin *pin, @@ -1225,6 +1226,7 @@ protected: OutputDelay *except); void deleteOutputDelaysReferencing(const Clock *clk); void deleteOutputDelay(OutputDelay *output_delay); + void deleteClockInsertion(ClockInsertion *insertion); void deleteClockInsertionsReferencing(Clock *clk); void deleteInterClockUncertainty(InterClockUncertainty *uncertainties); @@ -1330,7 +1332,7 @@ protected: InputDelaySet input_delays_; InputDelaysPinMap input_delay_pin_map_; - InputDelaysPinMap input_delay_ref_pin_map_; + bool have_input_delay_ref_pins_{false}; // Input delays on hierarchical pins are indexed by the load pins. InputDelaysPinMap input_delay_leaf_pin_map_; InputDelaysPinMap input_delay_internal_pin_map_; diff --git a/include/sta/Search.hh b/include/sta/Search.hh index 4dc40efe..d6db126e 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -800,8 +800,6 @@ public: protected: void init0(); - void enqueueRefPinInputDelays(const Pin *ref_pin, - const Sdc *sdc); void seedArrivals(Vertex *vertex); void pruneCrprArrivals(); void constrainedRequiredsInvalid(Vertex *vertex, diff --git a/include/sta/TimingArc.hh b/include/sta/TimingArc.hh index b2f56230..158caec3 100644 --- a/include/sta/TimingArc.hh +++ b/include/sta/TimingArc.hh @@ -204,6 +204,9 @@ public: static int wireArcIndex(const RiseFall *rf); static int wireArcCount() { return 2; } + // Psuedo definition for port ref_pin arcs. + static TimingArcSet *portRefPinTimingArcSet() { return port_refpin_timing_arc_set_; } + protected: TimingArcSet(const TimingRole *role, TimingArcAttrsPtr attrs); @@ -230,6 +233,7 @@ protected: static TimingArcAttrsPtr wire_timing_arc_attrs_; static TimingArcSet *wire_timing_arc_set_; + static TimingArcSet *port_refpin_timing_arc_set_; }; // A timing arc is a single from/to transition between two ports. diff --git a/include/sta/TimingRole.hh b/include/sta/TimingRole.hh index f07d6ed6..99a39e45 100644 --- a/include/sta/TimingRole.hh +++ b/include/sta/TimingRole.hh @@ -68,6 +68,7 @@ public: static const TimingRole *nonSeqHold() { return &non_seq_hold_; } static const TimingRole *clockTreePathMin() { return &clock_tree_path_min_; } static const TimingRole *clockTreePathMax() { return &clock_tree_path_max_; } + static const TimingRole *portDelayRefPin() { return &port_delay_ref_pin_; } const std::string &to_string() const { return name_; } int index() const { return index_; } bool isWire() const; @@ -139,6 +140,8 @@ private: static const TimingRole non_seq_hold_; static const TimingRole clock_tree_path_min_; static const TimingRole clock_tree_path_max_; + // Artificial timing from input/output_delay ref_pin to the input/output. + static const TimingRole port_delay_ref_pin_; static TimingRoleMap timing_roles_; friend class TimingRoleLess; diff --git a/liberty/TimingArc.cc b/liberty/TimingArc.cc index dd1694bd..a8ec5516 100644 --- a/liberty/TimingArc.cc +++ b/liberty/TimingArc.cc @@ -175,6 +175,7 @@ TimingArc::intrinsicDelay() const TimingArcAttrsPtr TimingArcSet::wire_timing_arc_attrs_ = nullptr; TimingArcSet *TimingArcSet::wire_timing_arc_set_ = nullptr; +TimingArcSet *TimingArcSet::port_refpin_timing_arc_set_ = nullptr; TimingArcSet::TimingArcSet(LibertyCell *, LibertyPort *from, @@ -524,6 +525,9 @@ TimingArcSet::init() Transition::rise(), nullptr); new TimingArc(wire_timing_arc_set_, Transition::fall(), Transition::fall(), nullptr); + + port_refpin_timing_arc_set_ = new TimingArcSet(TimingRole::portDelayRefPin(), + wire_timing_arc_attrs_); } void diff --git a/liberty/TimingRole.cc b/liberty/TimingRole.cc index 672a6498..abc8c127 100644 --- a/liberty/TimingRole.cc +++ b/liberty/TimingRole.cc @@ -90,6 +90,8 @@ const TimingRole TimingRole::clock_tree_path_min_("min clock tree path", false, false, MinMax::min(), nullptr, 27); const TimingRole TimingRole::clock_tree_path_max_("max clock tree path", false, false, false, MinMax::max(), nullptr, 28); +const TimingRole TimingRole::port_delay_ref_pin_("port delay ref pin", false, false, + false, nullptr, nullptr, 29); TimingRole::TimingRole(const char *name, bool is_sdf_iopath, diff --git a/sdc/PortDelay.cc b/sdc/PortDelay.cc index 94d3bbb2..6fa0f1c9 100644 --- a/sdc/PortDelay.cc +++ b/sdc/PortDelay.cc @@ -87,6 +87,14 @@ PortDelay::refTransition() const return RiseFall::rise(); } +void +PortDelay::setRefPinEdgesExist(bool exists) +{ + ref_pin_edges_exist_ = exists; +} + +//////////////////////////////////////////////////////////////// + InputDelay::InputDelay(const Pin *pin, const ClockEdge *clk_edge, int index, @@ -97,6 +105,8 @@ InputDelay::InputDelay(const Pin *pin, findLeafLoadPins(pin, network, &leaf_pins_); } +//////////////////////////////////////////////////////////////// + OutputDelay::OutputDelay(const Pin *pin, const ClockEdge *clk_edge, const Network *network) : diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index fb9b9c75..aa6bb723 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -115,7 +115,6 @@ Sdc::Sdc(Mode *mode, cycle_acctings_(this), input_delay_pin_map_(PinIdLess(network_)), - input_delay_ref_pin_map_(PinIdLess(network_)), input_delay_leaf_pin_map_(PinIdLess(network_)), input_delay_internal_pin_map_(PinIdLess(network_)), @@ -191,9 +190,9 @@ Sdc::clear() input_delays_.clear(); input_delay_pin_map_.clear(); input_delay_index_ = 0; - input_delay_ref_pin_map_.clear(); input_delay_leaf_pin_map_.clear(); input_delay_internal_pin_map_.clear(); + have_input_delay_ref_pins_ = false; output_delays_.clear(); output_delay_pin_map_.clear(); @@ -287,7 +286,6 @@ Sdc::deleteConstraints() deleteContents(input_delays_); deleteContents(input_delay_pin_map_); deleteContents(input_delay_leaf_pin_map_); - deleteContents(input_delay_ref_pin_map_); deleteContents(input_delay_internal_pin_map_); deleteContents(output_delays_); @@ -2671,16 +2669,9 @@ Sdc::setInputDelay(const Pin *pin, delays->setValue(rf, min_max, delay); } - if (ref_pin) { - InputDelaySet *ref_inputs = findKey(input_delay_ref_pin_map_, ref_pin); - if (ref_inputs == nullptr) { - ref_inputs = new InputDelaySet; - input_delay_ref_pin_map_[ref_pin] = ref_inputs; - } - ref_inputs->insert(input_delay); - } input_delay->setRefPin(ref_pin); - + if (ref_pin) + have_input_delay_ref_pins_ = true; input_delay->setSourceLatencyIncluded(source_latency_included); input_delay->setNetworkLatencyIncluded(network_latency_included); } @@ -2766,12 +2757,6 @@ Sdc::deleteInputDelays(const Pin *pin, } } -InputDelaySet * -Sdc::refPinInputDelays(const Pin *ref_pin) const -{ - return findKey(input_delay_ref_pin_map_, ref_pin); -} - InputDelaySet * Sdc::inputDelaysLeafPin(const Pin *leaf_pin) const { @@ -2828,7 +2813,6 @@ Sdc::swapPortDelays(Sdc *sdc1, { std::swap(sdc1->input_delays_, sdc2->input_delays_); std::swap(sdc1->input_delay_pin_map_, sdc2->input_delay_pin_map_); - std::swap(sdc1->input_delay_ref_pin_map_, sdc2->input_delay_ref_pin_map_); std::swap(sdc1->input_delay_leaf_pin_map_, sdc2->input_delay_leaf_pin_map_); std::swap(sdc1->input_delay_internal_pin_map_, sdc2->input_delay_internal_pin_map_); std::swap(sdc1->input_delay_index_, sdc2->input_delay_index_); @@ -2839,6 +2823,26 @@ Sdc::swapPortDelays(Sdc *sdc1, std::swap(sdc1->output_delay_leaf_pin_map_, sdc2->output_delay_leaf_pin_map_); } +void +Sdc::ensureInputDelayRefPinEdges() +{ + if (have_input_delay_ref_pins_) { + for (InputDelay *input_delay : input_delays_) { + const Pin *ref_pin = input_delay->refPin(); + if (ref_pin + && !input_delay->refPinEdgesExist()) { + Vertex *ref_pin_vertex = graph_->pinLoadVertex(ref_pin); + for (const Pin *pin : input_delay->leafPins()) { + Vertex *input_vertex = graph_->pinDrvrVertex(pin); + graph_->makeEdge(ref_pin_vertex, input_vertex, + TimingArcSet::portRefPinTimingArcSet()); + } + input_delay->setRefPinEdgesExist(true); + } + } + } +} + //////////////////////////////////////////////////////////////// void diff --git a/search/Levelize.cc b/search/Levelize.cc index 2219a91d..f6deee0a 100644 --- a/search/Levelize.cc +++ b/search/Levelize.cc @@ -117,6 +117,9 @@ Levelize::findLevels() if (observer_) observer_->levelsChangedBefore(); + for (const Mode *mode : modes_) + mode->sdc()->ensureInputDelayRefPinEdges(); + VertexIterator vertex_iter(graph_); while (vertex_iter.hasNext()) { Vertex *vertex = vertex_iter.next(); diff --git a/search/Search.cc b/search/Search.cc index 1ab8c639..7868108d 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -1226,7 +1226,6 @@ ArrivalVisitor::seedArrivals(Vertex *vertex) network_->pathName(pin)); search_->makeUnclkedPaths(vertex, true, false, tag_bldr_, mode); } - enqueueRefPinInputDelays(pin, sdc); } } @@ -1387,27 +1386,6 @@ ArrivalVisitor::pruneCrprArrivals() } } -// Enqueue pins with input delays that use ref_pin as the clock -// reference pin as if there is a timing arc from the reference pin to -// the input delay pin. -void -ArrivalVisitor::enqueueRefPinInputDelays(const Pin *ref_pin, - const Sdc *sdc) -{ - InputDelaySet *input_delays = sdc->refPinInputDelays(ref_pin); - if (input_delays) { - BfsFwdIterator *arrival_iter = search_->arrivalIterator(); - for (InputDelay *input_delay : *input_delays) { - const Pin *pin = input_delay->pin(); - Vertex *vertex, *bidirect_drvr_vertex; - graph_->pinVertices(pin, vertex, bidirect_drvr_vertex); - arrival_iter->enqueue(vertex); - if (bidirect_drvr_vertex) - arrival_iter->enqueue(bidirect_drvr_vertex); - } - } -} - void Search::enqueueLatchDataOutputs(Vertex *vertex) {