set_input_delay/set_output_delay leaf pin iterators
This commit is contained in:
parent
5a9c99228c
commit
c89e9da712
|
|
@ -10,6 +10,7 @@
|
|||
TAGS
|
||||
*~
|
||||
\#*#
|
||||
.#*
|
||||
.~lock.*#
|
||||
.DS_Store
|
||||
Makefile
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ Clock::setPins(PinSet *pins,
|
|||
{
|
||||
if (pins)
|
||||
pins_ = *pins;
|
||||
delete pins;
|
||||
makeLeafPins(network);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,97 +82,21 @@ InputDelay::InputDelay(Pin *pin,
|
|||
int index,
|
||||
Network *network) :
|
||||
PortDelay(pin, clk_edge, ref_pin),
|
||||
next_(nullptr),
|
||||
index_(index)
|
||||
{
|
||||
findLeafLoadPins(pin, network, &leaf_pins_);
|
||||
}
|
||||
|
||||
void
|
||||
InputDelay::setNext(InputDelay *next)
|
||||
{
|
||||
next_ = next;
|
||||
}
|
||||
|
||||
OutputDelay::OutputDelay(Pin *pin,
|
||||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin,
|
||||
Network *network) :
|
||||
PortDelay(pin, clk_edge, ref_pin),
|
||||
next_(nullptr)
|
||||
PortDelay(pin, clk_edge, ref_pin)
|
||||
{
|
||||
if (network)
|
||||
findLeafDriverPins(pin, network, &leaf_pins_);
|
||||
}
|
||||
|
||||
void
|
||||
OutputDelay::setNext(OutputDelay *next)
|
||||
{
|
||||
next_ = next;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
PinInputDelayIterator::PinInputDelayIterator(const Pin *pin,
|
||||
const Sdc *sdc)
|
||||
{
|
||||
next_ = sdc->input_delay_map_.findKey(pin);
|
||||
}
|
||||
|
||||
bool
|
||||
PinInputDelayIterator::hasNext()
|
||||
{
|
||||
return next_ != nullptr;
|
||||
}
|
||||
|
||||
InputDelay *
|
||||
PinInputDelayIterator::next()
|
||||
{
|
||||
InputDelay *next = next_;
|
||||
if (next)
|
||||
next_ = next_->next();
|
||||
return next;
|
||||
}
|
||||
|
||||
LeafPinInputDelayIterator::LeafPinInputDelayIterator(const Pin *vertex_pin,
|
||||
const Sdc *sdc) :
|
||||
PinInputDelayIterator()
|
||||
{
|
||||
next_ = sdc->input_delay_leaf_pin_map_.findKey(vertex_pin);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
PinOutputDelayIterator::PinOutputDelayIterator(const Pin *pin,
|
||||
const Sdc *sdc)
|
||||
{
|
||||
next_ = sdc->output_delay_map_.findKey(pin);
|
||||
}
|
||||
|
||||
bool
|
||||
PinOutputDelayIterator::hasNext()
|
||||
{
|
||||
return next_ != nullptr;
|
||||
}
|
||||
|
||||
OutputDelay *
|
||||
PinOutputDelayIterator::next()
|
||||
{
|
||||
OutputDelay *next = next_;
|
||||
if (next)
|
||||
next_ = next_->next();
|
||||
return next;
|
||||
}
|
||||
|
||||
LeafPinOutputDelayIterator::LeafPinOutputDelayIterator(const Pin *vertex_pin,
|
||||
const Sdc *sdc) :
|
||||
PinOutputDelayIterator()
|
||||
{
|
||||
next_ = sdc->output_delay_leaf_pin_map_.findKey(vertex_pin);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
PortDelayLess::PortDelayLess(const Network *network) :
|
||||
|
|
|
|||
|
|
@ -71,11 +71,6 @@ protected:
|
|||
Pin *ref_pin,
|
||||
int index,
|
||||
Network *network);
|
||||
InputDelay *next() { return next_; }
|
||||
|
||||
// Linked list of port delays on the same pin wrt different clocks.
|
||||
InputDelay *next_;
|
||||
void setNext(InputDelay *next);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(InputDelay);
|
||||
|
|
@ -83,8 +78,6 @@ private:
|
|||
int index_;
|
||||
|
||||
friend class Sdc;
|
||||
friend class PinInputDelayIterator;
|
||||
friend class InputDelayIterator;
|
||||
};
|
||||
|
||||
class OutputDelay : public PortDelay
|
||||
|
|
@ -96,70 +89,11 @@ protected:
|
|||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin,
|
||||
Network *network);
|
||||
OutputDelay *next() { return next_; }
|
||||
void setNext(OutputDelay *next);
|
||||
|
||||
// Linked list of port delays on the same port wrt different clocks.
|
||||
OutputDelay *next_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(OutputDelay);
|
||||
|
||||
friend class Sdc;
|
||||
friend class PinOutputDelayIterator;
|
||||
friend class OutputDelayIterator;
|
||||
};
|
||||
|
||||
class PinInputDelayIterator : public Iterator<InputDelay*>
|
||||
{
|
||||
public:
|
||||
PinInputDelayIterator(const Pin *pin,
|
||||
const Sdc *sdc);
|
||||
virtual bool hasNext();
|
||||
virtual InputDelay *next();
|
||||
|
||||
protected:
|
||||
PinInputDelayIterator() {}
|
||||
|
||||
InputDelay *next_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PinInputDelayIterator);
|
||||
};
|
||||
|
||||
class LeafPinInputDelayIterator : public PinInputDelayIterator
|
||||
{
|
||||
public:
|
||||
LeafPinInputDelayIterator(const Pin *pin,
|
||||
const Sdc *sdc);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(LeafPinInputDelayIterator);
|
||||
};
|
||||
|
||||
class PinOutputDelayIterator : public Iterator<OutputDelay*>
|
||||
{
|
||||
public:
|
||||
PinOutputDelayIterator(const Pin *pin,
|
||||
const Sdc *sdc);
|
||||
virtual bool hasNext();
|
||||
virtual OutputDelay *next();
|
||||
|
||||
protected:
|
||||
PinOutputDelayIterator() {}
|
||||
|
||||
OutputDelay *next_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PinOutputDelayIterator);
|
||||
};
|
||||
|
||||
class LeafPinOutputDelayIterator : public PinOutputDelayIterator
|
||||
{
|
||||
public:
|
||||
LeafPinOutputDelayIterator(const Pin *pin,
|
||||
const Sdc *sdc);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(LeafPinOutputDelayIterator);
|
||||
};
|
||||
|
||||
// Prediate used to sort port delays.
|
||||
|
|
|
|||
373
sdc/Sdc.cc
373
sdc/Sdc.cc
|
|
@ -167,12 +167,14 @@ Sdc::clear()
|
|||
data_checks_to_map_.clear();
|
||||
|
||||
input_delays_.clear();
|
||||
input_delay_map_.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();
|
||||
output_delay_map_.clear();
|
||||
|
||||
output_delays_.clear();
|
||||
output_delay_pin_map_.clear();
|
||||
output_delay_leaf_pin_map_.clear();
|
||||
|
||||
port_slew_limit_map_.clear();
|
||||
|
|
@ -283,32 +285,18 @@ Sdc::deleteConstraints()
|
|||
delete checks;
|
||||
}
|
||||
|
||||
InputDelayMap::Iterator input_iter(input_delay_map_);
|
||||
while (input_iter.hasNext()) {
|
||||
InputDelay *input_delay = input_iter.next();
|
||||
while (input_delay) {
|
||||
InputDelay *next = input_delay->next();
|
||||
delete input_delay;
|
||||
input_delay = next;
|
||||
}
|
||||
}
|
||||
for (auto input_delay : input_delays_)
|
||||
delete input_delay;
|
||||
input_delay_pin_map_.deleteContents();
|
||||
input_delay_leaf_pin_map_.deleteContents();
|
||||
input_delay_internal_pin_map_.deleteContents();
|
||||
|
||||
InputDelayRefPinMap::Iterator input_set_iter(input_delay_ref_pin_map_);
|
||||
while (input_set_iter.hasNext()) {
|
||||
InputDelaySet *input_delays = input_set_iter.next();
|
||||
delete input_delays;
|
||||
}
|
||||
input_delay_internal_pin_map_.deleteContents();
|
||||
for (auto output_delay : output_delays_)
|
||||
delete output_delay;
|
||||
output_delay_pin_map_.deleteContents();
|
||||
output_delay_ref_pin_map_.deleteContents();
|
||||
output_delay_leaf_pin_map_.deleteContents();
|
||||
|
||||
OutputDelayMap::Iterator output_iter(output_delay_map_);
|
||||
while (output_iter.hasNext()) {
|
||||
OutputDelay *output_delay = output_iter.next();
|
||||
while (output_delay) {
|
||||
OutputDelay *next = output_delay->next();
|
||||
delete output_delay;
|
||||
output_delay = next;
|
||||
}
|
||||
}
|
||||
|
||||
clk_hpin_disables_.deleteContentsClear();
|
||||
clk_hpin_disables_valid_ = false;
|
||||
|
|
@ -442,8 +430,8 @@ Sdc::isConstrained(const Pin *pin) const
|
|||
|| pin_clk_gating_check_map_.hasKey(pin)
|
||||
|| data_checks_from_map_.hasKey(pin)
|
||||
|| data_checks_to_map_.hasKey(pin)
|
||||
|| input_delay_map_.hasKey(pin)
|
||||
|| output_delay_map_.hasKey(pin)
|
||||
|| input_delay_pin_map_.hasKey(pin)
|
||||
|| output_delay_pin_map_.hasKey(pin)
|
||||
|| port_slew_limit_map_.hasKey(port)
|
||||
|| pin_cap_limit_map_.hasKey(pin1)
|
||||
|| port_cap_limit_map_.hasKey(port)
|
||||
|
|
@ -2772,12 +2760,16 @@ Sdc::setInputDelay(Pin *pin,
|
|||
float delay)
|
||||
{
|
||||
ClockEdge *clk_edge = clk ? clk->edge(clk_tr) : nullptr;
|
||||
InputDelay *input_delay = ensureInputDelay(pin, clk_edge, ref_pin);
|
||||
RiseFallMinMax *delays = input_delay->delays();
|
||||
if (add)
|
||||
InputDelay *input_delay = findInputDelay(pin, clk_edge, ref_pin);
|
||||
if (input_delay == nullptr)
|
||||
input_delay = makeInputDelay(pin, clk_edge, ref_pin);
|
||||
if (add) {
|
||||
RiseFallMinMax *delays = input_delay->delays();
|
||||
delays->mergeValue(tr, min_max, delay);
|
||||
}
|
||||
else {
|
||||
deleteInputDelays(pin, input_delay);
|
||||
RiseFallMinMax *delays = input_delay->delays();
|
||||
delays->setValue(tr, min_max, delay);
|
||||
}
|
||||
input_delay->setSourceLatencyIncluded(source_latency_included);
|
||||
|
|
@ -2785,35 +2777,45 @@ Sdc::setInputDelay(Pin *pin,
|
|||
}
|
||||
|
||||
InputDelay *
|
||||
Sdc::ensureInputDelay(Pin *pin,
|
||||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin)
|
||||
Sdc::makeInputDelay(Pin *pin,
|
||||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin)
|
||||
{
|
||||
InputDelay *input_delay = findInputDelay(pin, clk_edge, ref_pin);
|
||||
if (input_delay == nullptr) {
|
||||
input_delay = new InputDelay(pin, clk_edge, ref_pin, input_delay_index_++,
|
||||
network_);
|
||||
input_delays_.insert(input_delay);
|
||||
input_delay->setNext(input_delay_map_[pin]);
|
||||
input_delay_map_[pin] = input_delay;
|
||||
if (ref_pin) {
|
||||
InputDelaySet *ref_inputs = input_delay_ref_pin_map_.findKey(ref_pin);
|
||||
if (ref_inputs == nullptr) {
|
||||
ref_inputs = new InputDelaySet;
|
||||
input_delay_ref_pin_map_[ref_pin] = ref_inputs;
|
||||
}
|
||||
ref_inputs->insert(input_delay);
|
||||
InputDelay *input_delay = new InputDelay(pin, clk_edge, ref_pin,
|
||||
input_delay_index_++,
|
||||
network_);
|
||||
input_delays_.insert(input_delay);
|
||||
InputDelaySet *inputs = input_delay_pin_map_.findKey(pin);
|
||||
if (inputs == nullptr) {
|
||||
inputs = new InputDelaySet;
|
||||
input_delay_pin_map_[pin] = inputs;
|
||||
}
|
||||
inputs->insert(input_delay);
|
||||
|
||||
if (ref_pin) {
|
||||
InputDelaySet *ref_inputs = input_delay_ref_pin_map_.findKey(ref_pin);
|
||||
if (ref_inputs == nullptr) {
|
||||
ref_inputs = new InputDelaySet;
|
||||
input_delay_ref_pin_map_[ref_pin] = ref_inputs;
|
||||
}
|
||||
for (Pin *vpin : input_delay->leafPins()) {
|
||||
input_delay_leaf_pin_map_[vpin] = input_delay;
|
||||
if (!network_->isTopLevelPort(vpin)) {
|
||||
InputDelaySet *input_set = input_delay_internal_pin_map_[vpin];
|
||||
if (input_set == nullptr) {
|
||||
input_set = new InputDelaySet;
|
||||
input_delay_internal_pin_map_[vpin] = input_set;
|
||||
}
|
||||
input_set->insert(input_delay);
|
||||
ref_inputs->insert(input_delay);
|
||||
}
|
||||
|
||||
for (Pin *lpin : input_delay->leafPins()) {
|
||||
InputDelaySet *leaf_inputs = input_delay_leaf_pin_map_[lpin];
|
||||
if (leaf_inputs == nullptr) {
|
||||
leaf_inputs = new InputDelaySet;
|
||||
input_delay_leaf_pin_map_[lpin] = leaf_inputs;
|
||||
}
|
||||
leaf_inputs->insert(input_delay);
|
||||
|
||||
if (!network_->isTopLevelPort(lpin)) {
|
||||
InputDelaySet *internal_inputs = input_delay_internal_pin_map_[lpin];
|
||||
if (internal_inputs == nullptr) {
|
||||
internal_inputs = new InputDelaySet;
|
||||
input_delay_internal_pin_map_[pin] = internal_inputs;
|
||||
}
|
||||
internal_inputs->insert(input_delay);
|
||||
}
|
||||
}
|
||||
return input_delay;
|
||||
|
|
@ -2824,12 +2826,13 @@ Sdc::findInputDelay(const Pin *pin,
|
|||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin)
|
||||
{
|
||||
for (InputDelay *input_delay = input_delay_map_.findKey(pin);
|
||||
input_delay;
|
||||
input_delay = input_delay->next()) {
|
||||
if (input_delay->clkEdge() == clk_edge
|
||||
&& input_delay->refPin() == ref_pin)
|
||||
return input_delay;
|
||||
InputDelaySet *inputs = input_delay_pin_map_.findKey(pin);
|
||||
if (inputs) {
|
||||
for (InputDelay *input_delay : *inputs) {
|
||||
if (input_delay->clkEdge() == clk_edge
|
||||
&& input_delay->refPin() == ref_pin)
|
||||
return input_delay;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -2855,27 +2858,12 @@ void
|
|||
Sdc::deleteInputDelays(Pin *pin,
|
||||
InputDelay *except)
|
||||
{
|
||||
InputDelay *input_delay = input_delay_map_.findKey(pin);
|
||||
while (input_delay) {
|
||||
InputDelay *next = input_delay->next();
|
||||
if (input_delay == except)
|
||||
input_delay->setNext(nullptr);
|
||||
else {
|
||||
delete input_delay;
|
||||
input_delays_.erase(input_delay);
|
||||
}
|
||||
input_delay = next;
|
||||
}
|
||||
input_delay_map_[pin] = except;
|
||||
|
||||
for (Pin *vpin : except->leafPins()) {
|
||||
input_delay_leaf_pin_map_[vpin] = except;
|
||||
InputDelaySet *input_delays =
|
||||
input_delay_internal_pin_map_.findKey(vpin);
|
||||
if (input_delays) {
|
||||
input_delays->clear();
|
||||
input_delays->insert(except);
|
||||
}
|
||||
InputDelaySet *input_delays = input_delay_pin_map_[pin];
|
||||
InputDelaySet::Iterator iter(input_delays);
|
||||
while (iter.hasNext()) {
|
||||
InputDelay *input_delay = iter.next();
|
||||
if (input_delay != except)
|
||||
deleteInputDelay(input_delay);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2885,70 +2873,48 @@ Sdc::refPinInputDelays(const Pin *ref_pin) const
|
|||
return input_delay_ref_pin_map_.findKey(ref_pin);
|
||||
}
|
||||
|
||||
PinInputDelayIterator *
|
||||
Sdc::inputDelayIterator(const Pin *pin) const
|
||||
InputDelaySet *
|
||||
Sdc::inputDelaysLeafPin(const Pin *leaf_pin)
|
||||
{
|
||||
return new PinInputDelayIterator(pin, this);
|
||||
return input_delay_leaf_pin_map_.findKey(leaf_pin);
|
||||
}
|
||||
|
||||
bool
|
||||
Sdc::hasInputDelay(const Pin *leaf_pin) const
|
||||
{
|
||||
return input_delay_leaf_pin_map_.findKey(leaf_pin) != nullptr;
|
||||
InputDelaySet *input_delays = input_delay_leaf_pin_map_.findKey(leaf_pin);
|
||||
return input_delays && !input_delays->empty();
|
||||
}
|
||||
|
||||
bool
|
||||
Sdc::isInputDelayInternal(const Pin *pin) const
|
||||
{
|
||||
InputDelaySet *input_delays =
|
||||
input_delay_internal_pin_map_.findKey(pin);
|
||||
return input_delays && !input_delays->empty();
|
||||
return input_delay_internal_pin_map_.hasKey(pin);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
Sdc::deleteInputDelaysReferencing(Clock *clk)
|
||||
{
|
||||
Vector<InputDelay*> refs;
|
||||
for (InputDelay *input_delay : input_delays_) {
|
||||
InputDelaySet::Iterator iter(input_delays_);
|
||||
while (iter.hasNext()) {
|
||||
InputDelay *input_delay = iter.next();
|
||||
if (input_delay->clock() == clk)
|
||||
refs.push_back(input_delay);
|
||||
}
|
||||
for (InputDelay *input_delay : refs)
|
||||
deleteInputDelay(input_delay);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Sdc::deleteInputDelay(InputDelay *input_delay)
|
||||
{
|
||||
input_delays_.erase(input_delay);
|
||||
Pin *pin = input_delay->pin();
|
||||
InputDelay *head = input_delay_map_.findKey(pin);
|
||||
if (head == input_delay) {
|
||||
InputDelay *next = input_delay->next();
|
||||
if (next)
|
||||
input_delay_map_[pin] = next;
|
||||
else
|
||||
input_delay_map_.erase(pin);
|
||||
head = next;
|
||||
}
|
||||
else {
|
||||
for (InputDelay *delay = head; delay; ) {
|
||||
InputDelay *next = delay->next();
|
||||
if (next == input_delay) {
|
||||
delay->setNext(input_delay->next());
|
||||
break;
|
||||
}
|
||||
delay = next;
|
||||
}
|
||||
}
|
||||
|
||||
for (Pin *vpin : input_delay->leafPins()) {
|
||||
if (head)
|
||||
input_delay_leaf_pin_map_[vpin] = head;
|
||||
else
|
||||
input_delay_leaf_pin_map_.erase(vpin);
|
||||
Pin *pin = input_delay->pin();
|
||||
InputDelaySet *inputs = input_delay_pin_map_[pin];
|
||||
inputs->erase(input_delay);
|
||||
|
||||
for (Pin *lpin : input_delay->leafPins()) {
|
||||
InputDelaySet *inputs = input_delay_leaf_pin_map_[lpin];
|
||||
inputs->erase(input_delay);
|
||||
}
|
||||
|
||||
delete input_delay;
|
||||
|
|
@ -2969,53 +2935,75 @@ Sdc::setOutputDelay(Pin *pin,
|
|||
float delay)
|
||||
{
|
||||
ClockEdge *clk_edge = clk ? clk->edge(clk_tr) : nullptr;
|
||||
OutputDelay *output_delay = ensureOutputDelay(pin, clk_edge, ref_pin);
|
||||
RiseFallMinMax *delays = output_delay->delays();
|
||||
if (add)
|
||||
OutputDelay *output_delay = findOutputDelay(pin, clk_edge, ref_pin);
|
||||
if (output_delay == nullptr)
|
||||
output_delay = makeOutputDelay(pin, clk_edge, ref_pin);
|
||||
if (add) {
|
||||
RiseFallMinMax *delays = output_delay->delays();
|
||||
delays->mergeValue(tr, min_max, delay);
|
||||
}
|
||||
else {
|
||||
deleteOutputDelays(pin, output_delay);
|
||||
RiseFallMinMax *delays = output_delay->delays();
|
||||
delays->setValue(tr, min_max, delay);
|
||||
}
|
||||
output_delay->setSourceLatencyIncluded(source_latency_included);
|
||||
output_delay->setNetworkLatencyIncluded(network_latency_included);
|
||||
}
|
||||
|
||||
OutputDelay *
|
||||
Sdc::ensureOutputDelay(Pin *pin,
|
||||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin)
|
||||
{
|
||||
OutputDelay *output_delay = findOutputDelay(pin, clk_edge, ref_pin);
|
||||
if (output_delay == nullptr) {
|
||||
output_delay = new OutputDelay(pin, clk_edge, ref_pin, network_);
|
||||
output_delays_.insert(output_delay);
|
||||
output_delay->setNext(output_delay_map_[pin]);
|
||||
output_delay_map_[pin] = output_delay;
|
||||
for (Pin *vpin : output_delay->leafPins()) {
|
||||
output_delay_leaf_pin_map_[vpin] = output_delay;
|
||||
if (graph_)
|
||||
annotateGraphConstrained(vpin, true);
|
||||
}
|
||||
}
|
||||
return output_delay;
|
||||
}
|
||||
|
||||
OutputDelay *
|
||||
Sdc::findOutputDelay(const Pin *pin,
|
||||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin)
|
||||
{
|
||||
for (OutputDelay *output_delay = output_delay_map_.findKey(pin);
|
||||
output_delay;
|
||||
output_delay = output_delay->next()) {
|
||||
if (output_delay->clkEdge() == clk_edge
|
||||
&& output_delay->refPin() == ref_pin)
|
||||
return output_delay;
|
||||
OutputDelaySet *outputs = output_delay_pin_map_.findKey(pin);
|
||||
if (outputs) {
|
||||
for (OutputDelay *output_delay : *outputs) {
|
||||
if (output_delay->clkEdge() == clk_edge
|
||||
&& output_delay->refPin() == ref_pin)
|
||||
return output_delay;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OutputDelay *
|
||||
Sdc::makeOutputDelay(Pin *pin,
|
||||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin)
|
||||
{
|
||||
OutputDelay *output_delay = new OutputDelay(pin, clk_edge, ref_pin,
|
||||
network_);
|
||||
output_delays_.insert(output_delay);
|
||||
OutputDelaySet *outputs = output_delay_pin_map_.findKey(pin);
|
||||
if (outputs == nullptr) {
|
||||
outputs = new OutputDelaySet;
|
||||
output_delay_pin_map_[pin] = outputs;
|
||||
}
|
||||
outputs->insert(output_delay);
|
||||
|
||||
if (ref_pin) {
|
||||
OutputDelaySet *ref_outputs = output_delay_ref_pin_map_.findKey(ref_pin);
|
||||
if (ref_outputs == nullptr) {
|
||||
ref_outputs = new OutputDelaySet;
|
||||
output_delay_ref_pin_map_[ref_pin] = ref_outputs;
|
||||
}
|
||||
ref_outputs->insert(output_delay);
|
||||
}
|
||||
|
||||
for (Pin *lpin : output_delay->leafPins()) {
|
||||
OutputDelaySet *leaf_outputs = output_delay_leaf_pin_map_[lpin];
|
||||
if (leaf_outputs == nullptr) {
|
||||
leaf_outputs = new OutputDelaySet;
|
||||
output_delay_leaf_pin_map_[lpin] = leaf_outputs;
|
||||
}
|
||||
leaf_outputs->insert(output_delay);
|
||||
if (graph_)
|
||||
annotateGraphConstrained(lpin, true);
|
||||
}
|
||||
return output_delay;
|
||||
}
|
||||
|
||||
void
|
||||
Sdc::removeOutputDelay(Pin *pin,
|
||||
TransRiseFallBoth *tr,
|
||||
|
|
@ -3024,9 +3012,9 @@ Sdc::removeOutputDelay(Pin *pin,
|
|||
MinMaxAll *min_max)
|
||||
{
|
||||
ClockEdge *clk_edge = clk ? clk->edge(clk_tr) : nullptr;
|
||||
InputDelay *input_delay = findInputDelay(pin, clk_edge, nullptr);
|
||||
if (input_delay) {
|
||||
RiseFallMinMax *delays = input_delay->delays();
|
||||
OutputDelay *output_delay = findOutputDelay(pin, clk_edge, nullptr);
|
||||
if (output_delay) {
|
||||
RiseFallMinMax *delays = output_delay->delays();
|
||||
delays->removeValue(tr, min_max);
|
||||
}
|
||||
}
|
||||
|
|
@ -3035,24 +3023,19 @@ void
|
|||
Sdc::deleteOutputDelays(Pin *pin,
|
||||
OutputDelay *except)
|
||||
{
|
||||
OutputDelay *output_delay = output_delay_map_.findKey(pin);
|
||||
while (output_delay) {
|
||||
OutputDelay *next = output_delay->next();
|
||||
if (output_delay == except)
|
||||
output_delay->setNext(nullptr);
|
||||
else
|
||||
delete output_delay;
|
||||
output_delay = next;
|
||||
OutputDelaySet *output_delays = output_delay_pin_map_[pin];
|
||||
OutputDelaySet::Iterator iter(output_delays);
|
||||
while (iter.hasNext()) {
|
||||
OutputDelay *output_delay = iter.next();
|
||||
if (output_delay != except)
|
||||
deleteOutputDelay(output_delay);
|
||||
}
|
||||
output_delay_map_[pin] = except;
|
||||
for (Pin *vpin : except->leafPins())
|
||||
output_delay_leaf_pin_map_[vpin] = except;
|
||||
}
|
||||
|
||||
PinOutputDelayIterator *
|
||||
Sdc::outputDelayIterator(const Pin *pin) const
|
||||
OutputDelaySet *
|
||||
Sdc::outputDelaysLeafPin(const Pin *leaf_pin)
|
||||
{
|
||||
return new PinOutputDelayIterator(pin, this);
|
||||
return output_delay_leaf_pin_map_.findKey(leaf_pin);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -3064,45 +3047,26 @@ Sdc::hasOutputDelay(const Pin *leaf_pin) const
|
|||
void
|
||||
Sdc::deleteOutputDelaysReferencing(Clock *clk)
|
||||
{
|
||||
Vector<OutputDelay*> refs;
|
||||
for (OutputDelay *output_delay : output_delays_) {
|
||||
OutputDelaySet::Iterator iter(output_delays_);
|
||||
while (iter.hasNext()) {
|
||||
OutputDelay *output_delay = iter.next();
|
||||
if (output_delay->clock() == clk)
|
||||
refs.push_back(output_delay);
|
||||
deleteOutputDelay(output_delay);
|
||||
}
|
||||
for (OutputDelay *output_delay : refs)
|
||||
deleteOutputDelay(output_delay);
|
||||
}
|
||||
|
||||
void
|
||||
Sdc::deleteOutputDelay(OutputDelay *output_delay)
|
||||
{
|
||||
Pin *pin = output_delay->pin();
|
||||
output_delays_.erase(output_delay);
|
||||
OutputDelay *head = output_delay_map_.findKey(pin);
|
||||
if (head == output_delay) {
|
||||
OutputDelay *next = output_delay->next();
|
||||
if (next)
|
||||
output_delay_map_[pin] = next;
|
||||
else
|
||||
output_delay_map_.erase(pin);
|
||||
head = next;
|
||||
}
|
||||
else {
|
||||
for (OutputDelay *delay = head; delay; ) {
|
||||
OutputDelay *next = delay->next();
|
||||
if (next == output_delay) {
|
||||
delay->setNext(output_delay->next());
|
||||
break;
|
||||
}
|
||||
delay = next;
|
||||
}
|
||||
}
|
||||
|
||||
for (Pin *vpin : output_delay->leafPins()) {
|
||||
if (head)
|
||||
output_delay_leaf_pin_map_[vpin] = head;
|
||||
else
|
||||
output_delay_leaf_pin_map_.erase(vpin);
|
||||
Pin *pin = output_delay->pin();
|
||||
OutputDelaySet *outputs = output_delay_pin_map_[pin];
|
||||
outputs->erase(output_delay);
|
||||
|
||||
for (Pin *lpin : output_delay->leafPins()) {
|
||||
OutputDelaySet *outputs = output_delay_leaf_pin_map_[lpin];
|
||||
outputs->erase(output_delay);
|
||||
}
|
||||
|
||||
delete output_delay;
|
||||
|
|
@ -6345,14 +6309,9 @@ Sdc::setEdgeDisabledInstFrom(Pin *from_pin,
|
|||
void
|
||||
Sdc::annotateGraphOutputDelays(bool annotate)
|
||||
{
|
||||
OutputDelayMap::Iterator output_iter(output_delay_map_);
|
||||
while (output_iter.hasNext()) {
|
||||
OutputDelay *output_delay = output_iter.next();
|
||||
while (output_delay) {
|
||||
for (Pin *vpin : output_delay->leafPins())
|
||||
annotateGraphConstrained(vpin, annotate);
|
||||
output_delay = output_delay->next();
|
||||
}
|
||||
for (OutputDelay *output_delay : output_delays_) {
|
||||
for (Pin *lpin : output_delay->leafPins())
|
||||
annotateGraphConstrained(lpin, annotate);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
56
sdc/Sdc.hh
56
sdc/Sdc.hh
|
|
@ -38,8 +38,6 @@
|
|||
namespace sta {
|
||||
|
||||
class OperatingConditions;
|
||||
class PinInputDelayIterator;
|
||||
class PinOutputDelayIterator;
|
||||
class PortExtCap;
|
||||
class ClockGatingCheck;
|
||||
class InputDriveCell;
|
||||
|
|
@ -106,12 +104,9 @@ public:
|
|||
typedef Map<const char*,Clock*, CharPtrLess> ClockNameMap;
|
||||
typedef UnorderedMap<const Pin*, ClockSet*> ClockPinMap;
|
||||
typedef Set<InputDelay*> InputDelaySet;
|
||||
typedef Map<const Pin*,InputDelay*> InputDelayMap;
|
||||
typedef Set<InputDelay*> InputDelaySet;
|
||||
typedef Map<const Pin*,InputDelaySet*> InputDelayRefPinMap;
|
||||
typedef Map<const Pin*,InputDelaySet*> InputDelayInternalPinMap;
|
||||
typedef Map<const Pin*,InputDelaySet*> InputDelaysPinMap;
|
||||
typedef Set<OutputDelay*> OutputDelaySet;
|
||||
typedef Map<const Pin*,OutputDelay*> OutputDelayMap;
|
||||
typedef Map<const Pin*,OutputDelaySet*> OutputDelaysPinMap;
|
||||
// Use HashSet so no read lock is required.
|
||||
typedef HashSet<CycleAccting*, CycleAcctingHash, CycleAcctingEqual> CycleAcctingSet;
|
||||
typedef Set<Instance*> InstanceSet;
|
||||
|
|
@ -817,13 +812,7 @@ public:
|
|||
void setUseDefaultArrivalClock(bool enable);
|
||||
|
||||
// STA interface.
|
||||
InputDelay *ensureInputDelay(Pin *pin,
|
||||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin);
|
||||
InputDelaySet *refPinInputDelays(const Pin *ref_pin) const;
|
||||
OutputDelay *ensureOutputDelay(Pin *pin,
|
||||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin);
|
||||
LogicValueMap *logicValues() { return &logic_value_map_; }
|
||||
LogicValueMap *caseLogicValues() { return &case_value_map_; }
|
||||
// Returns nullptr if set_operating_conditions has not been called.
|
||||
|
|
@ -892,18 +881,23 @@ public:
|
|||
const ClockEdge *tgt);
|
||||
// Report clock to clock relationships that exceed max_cycle_count.
|
||||
void reportClkToClkMaxCycleWarnings();
|
||||
|
||||
const InputDelaySet &inputDelays() const { return input_delays_; }
|
||||
// Pin -> input delays.
|
||||
const InputDelayMap &inputDelayMap() const { return input_delay_map_; }
|
||||
// Iterate over the input delays on pin (which may be hierarchical).
|
||||
PinInputDelayIterator *inputDelayIterator(const Pin *pin) const;
|
||||
const InputDelaysPinMap &inputDelayPinMap() const { return input_delay_pin_map_; }
|
||||
// Input delays on leaf_pin.
|
||||
InputDelaySet *inputDelaysLeafPin(const Pin *leaf_pin);
|
||||
bool hasInputDelay(const Pin *leaf_pin) const;
|
||||
// Pin is internal (not top level port) and has an input arrival.
|
||||
bool isInputDelayInternal(const Pin *pin) const;
|
||||
|
||||
const OutputDelaySet &outputDelays() const { return output_delays_; }
|
||||
// Iterate over the output delays on pin (which may be hierarchical).
|
||||
PinOutputDelayIterator *outputDelayIterator(const Pin *pin) const;
|
||||
// Pin -> output delays.
|
||||
const OutputDelaysPinMap &outputDelayPinMap() const { return output_delay_pin_map_; }
|
||||
// Output delays on leaf_pin.
|
||||
OutputDelaySet *outputDelaysLeafPin(const Pin *leaf_pin);
|
||||
bool hasOutputDelay(const Pin *leaf_pin) const;
|
||||
|
||||
PortExtCap *portExtCap(Port *port) const;
|
||||
bool hasPortExtCap(Port *port) const;
|
||||
void portExtCap(Port *port,
|
||||
|
|
@ -1168,6 +1162,9 @@ protected:
|
|||
InputDelay *findInputDelay(const Pin *pin,
|
||||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin);
|
||||
InputDelay *makeInputDelay(Pin *pin,
|
||||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin);
|
||||
void deleteInputDelays(Pin *pin,
|
||||
InputDelay *except);
|
||||
void deleteInputDelaysReferencing(Clock *clk);
|
||||
|
|
@ -1175,6 +1172,9 @@ protected:
|
|||
OutputDelay *findOutputDelay(const Pin *pin,
|
||||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin);
|
||||
OutputDelay *makeOutputDelay(Pin *pin,
|
||||
ClockEdge *clk_edge,
|
||||
Pin *ref_pin);
|
||||
void deleteOutputDelays(Pin *pin, OutputDelay *except);
|
||||
void deleteOutputDelaysReferencing(Clock *clk);
|
||||
void deleteOutputDelay(OutputDelay *output_delay);
|
||||
|
|
@ -1313,17 +1313,21 @@ protected:
|
|||
std::mutex cycle_acctings_lock_;
|
||||
DataChecksMap data_checks_from_map_;
|
||||
DataChecksMap data_checks_to_map_;
|
||||
|
||||
InputDelaySet input_delays_;
|
||||
InputDelayMap input_delay_map_;
|
||||
InputDelaysPinMap input_delay_pin_map_;
|
||||
int input_delay_index_;
|
||||
InputDelayRefPinMap input_delay_ref_pin_map_;
|
||||
InputDelaysPinMap input_delay_ref_pin_map_;
|
||||
// Input delays on hierarchical pins are indexed by the load pins.
|
||||
InputDelayMap input_delay_leaf_pin_map_;
|
||||
InputDelayInternalPinMap input_delay_internal_pin_map_;
|
||||
InputDelaysPinMap input_delay_leaf_pin_map_;
|
||||
InputDelaysPinMap input_delay_internal_pin_map_;
|
||||
|
||||
OutputDelaySet output_delays_;
|
||||
OutputDelayMap output_delay_map_;
|
||||
OutputDelaysPinMap output_delay_pin_map_;
|
||||
OutputDelaysPinMap output_delay_ref_pin_map_;
|
||||
// Output delays on hierarchical pins are indexed by the load pins.
|
||||
OutputDelayMap output_delay_leaf_pin_map_;
|
||||
OutputDelaysPinMap output_delay_leaf_pin_map_;
|
||||
|
||||
PortSlewLimitMap port_slew_limit_map_;
|
||||
PinSlewLimitMap pin_slew_limit_map_;
|
||||
CellSlewLimitMap cell_slew_limit_map_;
|
||||
|
|
@ -1420,10 +1424,6 @@ private:
|
|||
friend class FindNetCaps;
|
||||
friend class ClockGroupIterator;
|
||||
friend class GroupPathIterator;
|
||||
friend class PinInputDelayIterator;
|
||||
friend class LeafPinInputDelayIterator;
|
||||
friend class PinOutputDelayIterator;
|
||||
friend class LeafPinOutputDelayIterator;
|
||||
};
|
||||
|
||||
class ClockIterator : public ClockSeq::Iterator
|
||||
|
|
|
|||
|
|
@ -247,11 +247,12 @@ CheckTiming::checkUnconstraintedOutputs(PinSet &unconstrained_ends)
|
|||
bool
|
||||
CheckTiming::hasClkedDepature(Pin *pin)
|
||||
{
|
||||
PinOutputDelayIterator delay_iter(pin, sdc_);
|
||||
while (delay_iter.hasNext()) {
|
||||
OutputDelay *output_delay = delay_iter.next();
|
||||
if (output_delay->clkEdge() != nullptr)
|
||||
return true;
|
||||
OutputDelaySet *output_delays = sdc_->outputDelaysLeafPin(pin);
|
||||
if (output_delays) {
|
||||
for (OutputDelay *output_delay : *output_delays) {
|
||||
if (output_delay->clkEdge() != nullptr)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -868,7 +868,7 @@ Search::visitStartpoints(VertexVisitor *visitor)
|
|||
}
|
||||
delete pin_iter;
|
||||
|
||||
for (auto iter : sdc_->inputDelayMap()) {
|
||||
for (auto iter : sdc_->inputDelayPinMap()) {
|
||||
const Pin *pin = iter.first;
|
||||
// Already hit these.
|
||||
if (!network_->isTopLevelPort(pin)) {
|
||||
|
|
@ -1332,7 +1332,7 @@ ArrivalVisitor::enqueueRefPinInputDelays(const Pin *ref_pin)
|
|||
InputDelaySet *input_delays = sdc->refPinInputDelays(ref_pin);
|
||||
if (input_delays) {
|
||||
const Graph *graph = sta_->graph();
|
||||
for (auto input_delay : *input_delays) {
|
||||
for (InputDelay *input_delay : *input_delays) {
|
||||
const Pin *pin = input_delay->pin();
|
||||
Vertex *vertex, *bidirect_drvr_vertex;
|
||||
graph->pinVertices(pin, vertex, bidirect_drvr_vertex);
|
||||
|
|
@ -1661,7 +1661,7 @@ Search::seedInputArrivals(ClockSet *clks)
|
|||
{
|
||||
// Input arrivals can be on internal pins, so iterate over the pins
|
||||
// that have input arrivals rather than the top level input pins.
|
||||
for (auto iter : sdc_->inputDelayMap()) {
|
||||
for (auto iter : sdc_->inputDelayPinMap()) {
|
||||
const Pin *pin = iter.first;
|
||||
if (!sdc_->isLeafPinClock(pin)) {
|
||||
Vertex *vertex = graph_->pinDrvrVertex(pin);
|
||||
|
|
@ -1677,25 +1677,26 @@ Search::seedInputArrival(const Pin *pin,
|
|||
{
|
||||
bool has_arrival = false;
|
||||
// There can be multiple arrivals for a pin with wrt different clocks.
|
||||
LeafPinInputDelayIterator arrival_iter(pin, sdc_);
|
||||
TagGroupBldr tag_bldr(true, this);
|
||||
tag_bldr.init(vertex);
|
||||
while (arrival_iter.hasNext()) {
|
||||
InputDelay *input_delay = arrival_iter.next();
|
||||
Clock *input_clk = input_delay->clock();
|
||||
ClockSet *pin_clks = sdc_->findLeafPinClocks(pin);
|
||||
if (input_clk && wrt_clks->hasKey(input_clk)
|
||||
// Input arrivals wrt a clock source pin is the insertion
|
||||
// delay (source latency), but arrivals wrt other clocks
|
||||
// propagate.
|
||||
&& (pin_clks == nullptr
|
||||
|| !pin_clks->hasKey(input_clk))) {
|
||||
seedInputDelayArrival(pin, vertex, input_delay, false, &tag_bldr);
|
||||
has_arrival = true;
|
||||
InputDelaySet *input_delays = sdc_->inputDelaysLeafPin(pin);
|
||||
if (input_delays) {
|
||||
for (InputDelay *input_delay : *input_delays) {
|
||||
Clock *input_clk = input_delay->clock();
|
||||
ClockSet *pin_clks = sdc_->findLeafPinClocks(pin);
|
||||
if (input_clk && wrt_clks->hasKey(input_clk)
|
||||
// Input arrivals wrt a clock source pin is the insertion
|
||||
// delay (source latency), but arrivals wrt other clocks
|
||||
// propagate.
|
||||
&& (pin_clks == nullptr
|
||||
|| !pin_clks->hasKey(input_clk))) {
|
||||
seedInputDelayArrival(pin, vertex, input_delay, false, &tag_bldr);
|
||||
has_arrival = true;
|
||||
}
|
||||
}
|
||||
if (has_arrival)
|
||||
setVertexArrivals(vertex, &tag_bldr);
|
||||
}
|
||||
if (has_arrival)
|
||||
setVertexArrivals(vertex, &tag_bldr);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1725,18 +1726,19 @@ Search::seedInputArrival1(const Pin *pin,
|
|||
TagGroupBldr *tag_bldr)
|
||||
{
|
||||
// There can be multiple arrivals for a pin with wrt different clocks.
|
||||
LeafPinInputDelayIterator arrival_iter(pin, sdc_);
|
||||
while (arrival_iter.hasNext()) {
|
||||
InputDelay *input_delay = arrival_iter.next();
|
||||
Clock *input_clk = input_delay->clock();
|
||||
ClockSet *pin_clks = sdc_->findLeafPinClocks(pin);
|
||||
// Input arrival wrt a clock source pin is the clock insertion
|
||||
// delay (source latency), but arrivals wrt other clocks
|
||||
// propagate.
|
||||
if (pin_clks == nullptr
|
||||
|| !pin_clks->hasKey(input_clk))
|
||||
seedInputDelayArrival(pin, vertex, input_delay, is_segment_start,
|
||||
tag_bldr);
|
||||
InputDelaySet *input_delays = sdc_->inputDelaysLeafPin(pin);
|
||||
if (input_delays) {
|
||||
for (InputDelay *input_delay : *input_delays) {
|
||||
Clock *input_clk = input_delay->clock();
|
||||
ClockSet *pin_clks = sdc_->findLeafPinClocks(pin);
|
||||
// Input arrival wrt a clock source pin is the clock insertion
|
||||
// delay (source latency), but arrivals wrt other clocks
|
||||
// propagate.
|
||||
if (pin_clks == nullptr
|
||||
|| !pin_clks->hasKey(input_clk))
|
||||
seedInputDelayArrival(pin, vertex, input_delay, is_segment_start,
|
||||
tag_bldr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -299,36 +299,37 @@ VisitPathEnds::visitOutputDelayEnd(const Pin *pin,
|
|||
bool &is_constrained)
|
||||
{
|
||||
const MinMax *min_max = path_ap->pathMinMax();
|
||||
LeafPinOutputDelayIterator delay_iter(pin, sdc_);
|
||||
while (delay_iter.hasNext()) {
|
||||
OutputDelay *output_delay = delay_iter.next();
|
||||
float margin;
|
||||
bool exists;
|
||||
output_delay->delays()->value(end_tr, min_max, margin, exists);
|
||||
if (exists) {
|
||||
const Pin *ref_pin = output_delay->refPin();
|
||||
ClockEdge *tgt_clk_edge = output_delay->clkEdge();
|
||||
if (!filtered
|
||||
|| search_->matchesFilter(path, tgt_clk_edge)) {
|
||||
if (ref_pin) {
|
||||
Clock *tgt_clk = output_delay->clock();
|
||||
Vertex *ref_vertex = graph_->pinLoadVertex(ref_pin);
|
||||
TransRiseFall *ref_tr = output_delay->refTransition();
|
||||
VertexPathIterator ref_path_iter(ref_vertex,ref_tr,path_ap,this);
|
||||
while (ref_path_iter.hasNext()) {
|
||||
PathVertex *ref_path = ref_path_iter.next();
|
||||
if (ref_path->isClock(this)
|
||||
&& (tgt_clk == nullptr
|
||||
|| ref_path->clock(this) == tgt_clk))
|
||||
visitOutputDelayEnd1(output_delay, pin, path, end_tr,
|
||||
ref_path->clkEdge(this), ref_path, min_max,
|
||||
visitor, is_constrained);
|
||||
OutputDelaySet *output_delays = sdc_->outputDelaysLeafPin(pin);
|
||||
if (output_delays) {
|
||||
for (OutputDelay *output_delay : *output_delays) {
|
||||
float margin;
|
||||
bool exists;
|
||||
output_delay->delays()->value(end_tr, min_max, margin, exists);
|
||||
if (exists) {
|
||||
const Pin *ref_pin = output_delay->refPin();
|
||||
ClockEdge *tgt_clk_edge = output_delay->clkEdge();
|
||||
if (!filtered
|
||||
|| search_->matchesFilter(path, tgt_clk_edge)) {
|
||||
if (ref_pin) {
|
||||
Clock *tgt_clk = output_delay->clock();
|
||||
Vertex *ref_vertex = graph_->pinLoadVertex(ref_pin);
|
||||
TransRiseFall *ref_tr = output_delay->refTransition();
|
||||
VertexPathIterator ref_path_iter(ref_vertex,ref_tr,path_ap,this);
|
||||
while (ref_path_iter.hasNext()) {
|
||||
PathVertex *ref_path = ref_path_iter.next();
|
||||
if (ref_path->isClock(this)
|
||||
&& (tgt_clk == nullptr
|
||||
|| ref_path->clock(this) == tgt_clk))
|
||||
visitOutputDelayEnd1(output_delay, pin, path, end_tr,
|
||||
ref_path->clkEdge(this), ref_path, min_max,
|
||||
visitor, is_constrained);
|
||||
}
|
||||
}
|
||||
else
|
||||
visitOutputDelayEnd1(output_delay, pin, path, end_tr,
|
||||
tgt_clk_edge, nullptr, min_max,
|
||||
visitor, is_constrained);
|
||||
}
|
||||
else
|
||||
visitOutputDelayEnd1(output_delay, pin, path, end_tr,
|
||||
tgt_clk_edge, nullptr, min_max,
|
||||
visitor, is_constrained);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue