From 740fa7d16ce72bb241a8583ff94b693aa96f17f0 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 13 Jun 2026 16:31:24 -0700 Subject: [PATCH 1/4] 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) { From 376d86bbce84fb395b11d46f6ccd0caab99fc678 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 13 Jun 2026 16:45:23 -0700 Subject: [PATCH 2/4] rm Sdc::output_delay_ref_pin_map_ Signed-off-by: James Cherry --- include/sta/Sdc.hh | 1 - sdc/Sdc.cc | 12 ------------ 2 files changed, 13 deletions(-) diff --git a/include/sta/Sdc.hh b/include/sta/Sdc.hh index 557beaa6..1ba41f91 100644 --- a/include/sta/Sdc.hh +++ b/include/sta/Sdc.hh @@ -1340,7 +1340,6 @@ protected: OutputDelaySet output_delays_; OutputDelaysPinMap output_delay_pin_map_; - OutputDelaysPinMap output_delay_ref_pin_map_; // Output delays on hierarchical pins are indexed by the load pins. OutputDelaysPinMap output_delay_leaf_pin_map_; diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index aa6bb723..088cc967 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -119,7 +119,6 @@ Sdc::Sdc(Mode *mode, input_delay_internal_pin_map_(PinIdLess(network_)), output_delay_pin_map_(PinIdLess(network_)), - output_delay_ref_pin_map_(PinIdLess(network_)), output_delay_leaf_pin_map_(PinIdLess(network_)), port_ext_cap_map_(network_), @@ -290,7 +289,6 @@ Sdc::deleteConstraints() deleteContents(output_delays_); deleteContents(output_delay_pin_map_); - deleteContents(output_delay_ref_pin_map_); deleteContents(output_delay_leaf_pin_map_); deleteContents(clk_hpin_disables_); @@ -2819,7 +2817,6 @@ Sdc::swapPortDelays(Sdc *sdc1, std::swap(sdc1->output_delays_, sdc2->output_delays_); std::swap(sdc1->output_delay_pin_map_, sdc2->output_delay_pin_map_); - std::swap(sdc1->output_delay_ref_pin_map_, sdc2->output_delay_ref_pin_map_); std::swap(sdc1->output_delay_leaf_pin_map_, sdc2->output_delay_leaf_pin_map_); } @@ -2871,16 +2868,7 @@ Sdc::setOutputDelay(const Pin *pin, delays->setValue(rf, min_max, delay); } - if (ref_pin) { - OutputDelaySet *ref_outputs = findKey(output_delay_ref_pin_map_, ref_pin); - if (ref_outputs == nullptr) { - ref_outputs = new OutputDelaySet; - output_delay_ref_pin_map_[ref_pin] = ref_outputs; - } - ref_outputs->insert(output_delay); - } output_delay->setRefPin(ref_pin); - output_delay->setSourceLatencyIncluded(source_latency_included); output_delay->setNetworkLatencyIncluded(network_latency_included); } From 0fe167a80dd32c3fce0bc7f4c4cb85dc2a1eced1 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Mon, 15 Jun 2026 17:02:58 -0700 Subject: [PATCH 3/4] sta_internal_bidirect_instance_paths_enabled use load->driver edges Signed-off-by: James Cherry --- dcalc/GraphDelayCalc.cc | 15 +++++++-------- graph/Graph.cc | 14 ++++++++++++++ graph/Graph.i | 1 + include/sta/Graph.hh | 5 +++++ include/sta/Sta.hh | 2 -- include/sta/StaState.hh | 2 ++ search/Levelize.cc | 12 +++++++----- search/Search.cc | 21 ++++++++++++--------- search/SearchPred.cc | 1 + search/Sta.cc | 18 ++++++++---------- search/StaState.cc | 9 +++++++++ 11 files changed, 66 insertions(+), 34 deletions(-) diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index 3bf51343..c61ebfed 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -107,8 +107,7 @@ DcalcPred::searchThru(Edge *edge, || edge->isDisabledLoop() || sdc->isDisabledConstraint(edge) || sdc->isDisabledCondDefault(edge) - || (edge->isBidirectInstPath() - && !variables->bidirectInstPathsEnabled())); + || sta_->isDisabledBidirectInstPath(edge)); } bool @@ -1011,13 +1010,13 @@ GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex, if (search_pred_->searchFrom(from_vertex, mode) && search_pred_->searchThru(edge, mode)) { for (const MinMax *min_max : MinMax::range()) { - for (const TimingArc *arc : arc_set->arcs()) { - delay_changed |= findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc, + for (const TimingArc *arc : arc_set->arcs()) { + delay_changed |= findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc, scene, min_max, arc_delay_calc, - load_pin_index_map); - delay_exists[arc->toEdge()->asRiseFall()->index()] = true; - } - } + load_pin_index_map); + delay_exists[arc->toEdge()->asRiseFall()->index()] = true; + } + } } } if (delay_changed && observer_) { diff --git a/graph/Graph.cc b/graph/Graph.cc index f19927ff..6c9d47e8 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -250,6 +250,13 @@ Graph::makeInstDrvrWireEdges(const Instance *inst, if (network_->isDriver(pin) && !visited_drvrs.contains(pin)) makeWireEdgesFromPin(pin, visited_drvrs); + if (network_->isTopInstance(inst) + && network_->direction(pin)->isBidirect()) { + Vertex *bidir_load, *bidir_drvr; + pinVertices(pin, bidir_load, bidir_drvr); + Edge *edge = makeEdge(bidir_load, bidir_drvr, TimingArcSet::wireTimingArcSet()); + edge->setIsBidirectPortPath(true); + } } delete pin_iter; } @@ -1211,6 +1218,7 @@ Edge::init(VertexId from, vertex_out_prev_ = edge_id_null; is_bidirect_inst_path_ = false; is_bidirect_net_path_ = false; + is_bidirect_port_path_ = false; arc_delays_ = nullptr; arc_delay_annotated_is_bits_ = true; @@ -1368,6 +1376,12 @@ Edge::setIsBidirectNetPath(bool is_bidir) is_bidirect_net_path_ = is_bidir; } +void +Edge::setIsBidirectPortPath(bool is_bidir) +{ + is_bidirect_port_path_ = is_bidir; +} + void Edge::setHasSimSense(bool has_sense) { diff --git a/graph/Graph.i b/graph/Graph.i index d6fb1769..9c41e431 100644 --- a/graph/Graph.i +++ b/graph/Graph.i @@ -128,6 +128,7 @@ remove_delay_slew_annotations() Pin *pin() { return self->pin(); } bool is_bidirect_driver() { return self->isBidirectDriver(); } int level() { return Sta::sta()->vertexLevel(self); } +bool is_root() { return self->isRoot(); } int tag_group_index() { return self->tagGroupIndex(); } float diff --git a/include/sta/Graph.hh b/include/sta/Graph.hh index 572d95a7..1f6e7ce2 100644 --- a/include/sta/Graph.hh +++ b/include/sta/Graph.hh @@ -364,6 +364,9 @@ public: void setIsBidirectInstPath(bool is_bidir); bool isBidirectNetPath() const { return is_bidirect_net_path_; } void setIsBidirectNetPath(bool is_bidir); + bool isBidirectPortPath() const { return is_bidirect_port_path_; } + void setIsBidirectPortPath(bool is_bidir); + void removeDelayAnnotated(); [[nodiscard]] bool hasSimSense() const { return has_sim_sense_; } void setHasSimSense(bool has_sense); @@ -403,6 +406,8 @@ protected: bool delay_annotation_is_incremental_:1; bool is_bidirect_inst_path_:1; bool is_bidirect_net_path_:1; + // Bidirect load -> driver edge. + bool is_bidirect_port_path_:1; bool is_disabled_loop_:1; bool has_sim_sense_:1; bool has_disabled_cond_:1; diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 913608aa..4f0701ff 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -567,8 +567,6 @@ public: const Sdc *sdc); // Edge is disabled to break combinational loops. [[nodiscard]] bool isDisabledLoop(Edge *edge) const; - // Edge is disabled internal bidirect output path. - [[nodiscard]] bool isDisabledBidirectInstPath(Edge *edge) const; // Edge is disabled bidirect net path. [[nodiscard]] bool isDisabledBidirectNetPath(Edge *edge) const; [[nodiscard]] bool isDisabledPresetClr(Edge *edge) const; diff --git a/include/sta/StaState.hh b/include/sta/StaState.hh index c0da5998..d0062d7c 100644 --- a/include/sta/StaState.hh +++ b/include/sta/StaState.hh @@ -106,6 +106,8 @@ public: const Variables *variables() const { return variables_; } // Edge is default cond disabled by timing_disable_cond_default_arcs var. [[nodiscard]] bool isDisabledCondDefault(const Edge *edge) const; + // Edge is disabled internal bidirect output path. + [[nodiscard]] bool isDisabledBidirectInstPath(Edge *edge) const; const SceneSeq &scenes() { return scenes_; } const SceneSeq &scenes() const { return scenes_; } diff --git a/search/Levelize.cc b/search/Levelize.cc index f6deee0a..baacfdb3 100644 --- a/search/Levelize.cc +++ b/search/Levelize.cc @@ -196,11 +196,13 @@ bool Levelize::searchThru(Edge *edge) { const TimingRole *role = edge->role(); - return !role->isTimingCheck() && role != TimingRole::latchDtoQ() - && !edge->isDisabledLoop() - // Register/latch preset/clr edges are disabled by default. - && !(role == TimingRole::regSetClr() && !variables_->presetClrArcsEnabled()) - && !(edge->isBidirectInstPath() && !variables_->bidirectInstPathsEnabled()); + return !(role->isTimingCheck() + || role == TimingRole::latchDtoQ() + || edge->isDisabledLoop() + // Register/latch preset/clr edges are disabled by default. + || (role == TimingRole::regSetClr() + && !variables_->presetClrArcsEnabled()) + || isDisabledBidirectInstPath(edge)); } bool diff --git a/search/Search.cc b/search/Search.cc index 7868108d..8e78f358 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -184,13 +184,14 @@ SearchAdj::searchThru(Edge *edge, { const TimingRole *role = edge->role(); const Variables *variables = sta_->variables(); - return !role->isTimingCheck() - && !role->isLatchDtoQ() - // Register/latch preset/clr edges are disabled by default. - && !(role == TimingRole::regSetClr() && !variables->presetClrArcsEnabled()) - && !(edge->isBidirectInstPath() && !variables->bidirectInstPathsEnabled()) - && (!edge->isDisabledLoop() - || (variables->dynamicLoopBreaking() && hasPendingLoopPaths(edge))); + return !(role->isTimingCheck() + || role->isLatchDtoQ() + // Register/latch preset/clr edges are disabled by default. + || (role == TimingRole::regSetClr() + && !variables->presetClrArcsEnabled()) + || sta_->isDisabledBidirectInstPath(edge) + || (edge->isDisabledLoop() + && !(variables->dynamicLoopBreaking() && hasPendingLoopPaths(edge)))); } bool @@ -3228,8 +3229,10 @@ Search::isEndpoint(Vertex *vertex, const Pin *pin = vertex->pin(); const Sdc *sdc = mode->sdc(); return hasFanin(vertex, pred, graph_, mode) - && ((vertex->hasChecks() && hasEnabledChecks(vertex, mode)) - || sdc->isConstrainedEnd(pin) || !hasFanout(vertex, pred, graph_, mode) + && ((vertex->hasChecks() + && hasEnabledChecks(vertex, mode)) + || sdc->isConstrainedEnd(pin) + || !hasFanout(vertex, pred, graph_, mode) || sdc->isPathDelayInternalTo(pin) // Unconstrained paths at register clk pins. || (unconstrained_paths_ && vertex->isRegClk()) diff --git a/search/SearchPred.cc b/search/SearchPred.cc index 77279374..4a0a8304 100644 --- a/search/SearchPred.cc +++ b/search/SearchPred.cc @@ -184,6 +184,7 @@ ClkTreeSearchPred::searchThru(Edge *edge, || sdc->isDisabledConstraint(edge) || sdc->isDisabledCondDefault(edge) || edge->isBidirectInstPath() + || edge->isBidirectPortPath() || edge->isDisabledLoop()); } diff --git a/search/Sta.cc b/search/Sta.cc index 75d3d730..87a3f7d1 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -1702,8 +1702,10 @@ Sta::disabledEdges(const Mode *mode) VertexOutEdgeIterator edge_iter(vertex, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - if (isDisabledConstant(edge, mode) || isDisabledCondDefault(edge) - || isDisabledConstraint(edge, sdc) || edge->isDisabledLoop() + if (isDisabledConstant(edge, mode) + || isDisabledCondDefault(edge) + || isDisabledConstraint(edge, sdc) + || edge->isDisabledLoop() || isDisabledPresetClr(edge)) disabled_edges.push_back(edge); } @@ -1841,12 +1843,6 @@ Sta::exprConstantPins(FuncExpr *expr, } } -bool -Sta::isDisabledBidirectInstPath(Edge *edge) const -{ - return !variables_->bidirectInstPathsEnabled() && edge->isBidirectInstPath(); -} - bool Sta::isDisabledPresetClr(Edge *edge) const { @@ -5217,8 +5213,10 @@ FanInOutSrchPred::searchThru(Edge *edge, const Sim *sim = mode->sim(); return searchThruRole(edge) && (thru_disabled_ - || !(sdc->isDisabledConstraint(edge) || sim->isDisabledCond(edge) - || sta_->isDisabledCondDefault(edge))) + || !(sdc->isDisabledConstraint(edge) + || sim->isDisabledCond(edge) + || sta_->isDisabledCondDefault(edge) + || sta_->isDisabledBidirectInstPath(edge))) && (thru_constants_ || sim->simTimingSense(edge) != TimingSense::none); } diff --git a/search/StaState.cc b/search/StaState.cc index ea673b38..95d33060 100644 --- a/search/StaState.cc +++ b/search/StaState.cc @@ -31,6 +31,7 @@ #include "Graph.hh" #include "Mode.hh" #include "Network.hh" +#include "PortDirection.hh" #include "Scene.hh" #include "Sdc.hh" #include "TimingArc.hh" @@ -124,6 +125,14 @@ StaState::isDisabledCondDefault(const Edge *edge) const && edge->timingArcSet()->isCondDefault(); } +bool +StaState::isDisabledBidirectInstPath(Edge *edge) const +{ + return (edge->isBidirectInstPath() + || edge->isBidirectPortPath()) + && !variables_->bidirectInstPathsEnabled(); +} + //////////////////////////////////////////////////////////////// size_t From 133580eeae424af876c3732a16a366c6957ddaa5 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 16 Jun 2026 12:00:17 -0700 Subject: [PATCH 4/4] Sta::findRequired(vertex) public Signed-off-by: James Cherry --- include/sta/Sta.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 4f0701ff..da5da08b 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -1042,6 +1042,7 @@ public: int endpointViolationCount(const MinMax *min_max); // Find all required times after updateTiming(). void findRequireds(); + void findRequired(Vertex *vertex); std::string reportDelayCalc(Edge *edge, TimingArc *arc, const Scene *scene, @@ -1525,7 +1526,6 @@ protected: const Mode *mode, // Return value. PinSet &pins); - void findRequired(Vertex *vertex); void reportDelaysWrtClks(const Pin *pin, const Scene *scene,