Merge remote-tracking branch 'upstream/master' into sta_latest_0618

This commit is contained in:
dsengupta0628 2026-06-18 17:45:09 +00:00
commit 5dae3933dc
20 changed files with 123 additions and 93 deletions

View File

@ -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_) {

View File

@ -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)
{

View File

@ -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

View File

@ -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;

View File

@ -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_;
};

View File

@ -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.
@ -1221,6 +1221,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,
@ -1229,6 +1230,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);
@ -1334,7 +1336,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_;
@ -1342,7 +1344,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_;

View File

@ -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,

View File

@ -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;
@ -1044,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,
@ -1532,7 +1531,6 @@ protected:
const Mode *mode,
// Return value.
PinSet &pins);
void findRequired(Vertex *vertex);
void reportDelaysWrtClks(const Pin *pin,
const Scene *scene,

View File

@ -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_; }

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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) :

View File

@ -115,12 +115,10 @@ 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_)),
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_),
@ -191,9 +189,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,12 +285,10 @@ 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_);
deleteContents(output_delay_pin_map_);
deleteContents(output_delay_ref_pin_map_);
deleteContents(output_delay_leaf_pin_map_);
deleteContents(clk_hpin_disables_);
@ -2671,16 +2667,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 +2755,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,17 +2811,35 @@ 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_);
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_);
}
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
@ -2867,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);
}

View File

@ -118,6 +118,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();
@ -194,11 +197,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

View File

@ -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
@ -1226,7 +1227,6 @@ ArrivalVisitor::seedArrivals(Vertex *vertex)
network_->pathName(pin));
search_->makeUnclkedPaths(vertex, true, false, tag_bldr_, mode);
}
enqueueRefPinInputDelays(pin, sdc);
}
}
@ -1387,27 +1387,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)
{
@ -3250,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())

View File

@ -184,6 +184,7 @@ ClkTreeSearchPred::searchThru(Edge *edge,
|| sdc->isDisabledConstraint(edge)
|| sdc->isDisabledCondDefault(edge)
|| edge->isBidirectInstPath()
|| edge->isBidirectPortPath()
|| edge->isDisabledLoop());
}

View File

@ -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
{
@ -5242,8 +5238,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);
}

View File

@ -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