input ref pin graph edges

Signed-off-by: James Cherry <cherry@CerezoBook.local>
This commit is contained in:
James Cherry 2026-06-13 16:31:24 -07:00
parent 4249ab7b98
commit 740fa7d16c
11 changed files with 56 additions and 45 deletions

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

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

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

View File

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

View File

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