vertex_pin -> leaf_pin

This commit is contained in:
James Cherry 2019-10-25 08:51:59 -07:00
parent 13037e6093
commit 6ac93c8c7d
27 changed files with 445 additions and 601 deletions

View File

@ -48,7 +48,9 @@ netlist data structures without duplicating them.
* Query based incremental update of delays, arrival and required times
* Simulator to propagate constants from constraints and netlist tie high/low
See doc/OpenSTA.pdf for complete documentiaton.
See doc/OpenSTA.pdf for command documentiaton.
See doc/StaApi.txt for timing engine API documentiaton.
See doc/ChangeLog.txt for changes to commands.
## Getting Started

View File

@ -700,7 +700,7 @@ GraphDelayCalc1::seedLoadSlew(Vertex *vertex)
const Pin *pin = vertex->pin();
debugPrint1(debug_, "delay_calc", 2, "seed load slew %s\n",
vertex->name(sdc_network_));
ClockSet *clks = sdc_->findVertexPinClocks(pin);
ClockSet *clks = sdc_->findLeafPinClocks(pin);
initSlew(vertex);
for (auto tr : TransRiseFall::range()) {
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
@ -1594,10 +1594,10 @@ GraphDelayCalc1::findIdealClks(Vertex *vertex)
{
const Pin *pin = vertex->pin();
ClockSet *ideal_clks = nullptr;
if (sdc_->isVertexPinClock(pin)) {
if (sdc_->isLeafPinClock(pin)) {
// Seed ideal clocks pins.
if (!sdc_->isPropagatedClock(pin)) {
ClockSet *clks = sdc_->findVertexPinClocks(pin);
ClockSet *clks = sdc_->findLeafPinClocks(pin);
ClockSet::ConstIterator clk_iter(clks);
while (clk_iter.hasNext()) {
Clock *clk = clk_iter.next();

View File

@ -40,7 +40,7 @@ makeClonePins(Instance *proto,
ConcreteBindingTbl *parent_bindings,
NetworkReader *network);
Network *
NetworkReader *
makeConcreteNetwork()
{
return new ConcreteNetwork;

View File

@ -19,9 +19,9 @@
namespace sta {
class Network;
class NetworkReader;
Network *
NetworkReader *
makeConcreteNetwork();
} // namespace

View File

@ -34,9 +34,7 @@ isPowerOfTwo(int i);
Clock::Clock(const char *name,
int index) :
name_(stringCopy(name)),
pins_(nullptr),
add_to_pins_(false),
vertex_pins_(nullptr),
pll_out_(nullptr),
pll_fdbk_(nullptr),
period_(0.0),
@ -83,31 +81,26 @@ Clock::initClk(PinSet *pins,
bool
Clock::isVirtual() const
{
return pins_ == nullptr || pins_->empty();
return pins_.empty();
}
void
Clock::setPins(PinSet *pins,
const Network *network)
{
delete pins_;
pins_ = pins;
makeVertexPins(network);
if (pins)
pins_ = *pins;
makeLeafPins(network);
}
void
Clock::makeVertexPins(const Network *network)
Clock::makeLeafPins(const Network *network)
{
if (pins_) {
if (vertex_pins_)
vertex_pins_->clear();
else
vertex_pins_ = new PinSet;
PinSet::Iterator pin_iter(pins_);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
findVertexDriverPins(pin, network, vertex_pins_);
}
leaf_pins_.clear();
PinSet::Iterator pin_iter(pins_);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
findLeafDriverPins(pin, network, &leaf_pins_);
}
}
@ -130,8 +123,6 @@ Clock::makeClkEdges()
Clock::~Clock()
{
stringDelete(name_);
delete pins_;
delete vertex_pins_;
if (clk_edges_) {
delete clk_edges_[TransRiseFall::riseIndex()];
delete clk_edges_[TransRiseFall::fallIndex()];
@ -146,18 +137,14 @@ Clock::~Clock()
void
Clock::addPin(Pin *pin)
{
if (pins_ == nullptr)
pins_ = new PinSet;
pins_->insert(pin);
if (vertex_pins_ == nullptr)
vertex_pins_ = new PinSet;
vertex_pins_->insert(pin);
pins_.insert(pin);
leaf_pins_.insert(pin);
}
void
Clock::deletePin(Pin *pin)
{
pins_->erase(pin);
pins_.erase(pin);
}
void
@ -183,7 +170,7 @@ Clock::setClkEdgeTime(const TransRiseFall *tr)
Pin *
Clock::defaultPin() const
{
PinSet::Iterator pin_iter(vertex_pins_);
PinSet::ConstIterator pin_iter(leaf_pins_);
if (pin_iter.hasNext())
return pin_iter.next();
else
@ -510,9 +497,9 @@ Clock::srcPinVertices(VertexSet &src_vertices,
{
if (network->isHierarchical(src_pin_)) {
// Use the clocks on a non-hierarchical pin on the same net.
PinSet vertex_pins;
findVertexDriverPins(src_pin_, network, &vertex_pins);
PinSet::Iterator pin_iter(vertex_pins);
PinSet leaf_pins;
findLeafDriverPins(src_pin_, network, &leaf_pins);
PinSet::Iterator pin_iter(leaf_pins);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
Vertex *vertex, *bidirect_drvr_vertex;
@ -710,4 +697,9 @@ sortClockSet(ClockSet *set,
sort(clks, ClockNameLess());
}
ClockPinIterator::ClockPinIterator(Clock *clk) :
PinSet::Iterator(clk->pins())
{
}
} // namespace

View File

@ -36,8 +36,14 @@ public:
float period() const { return period_; }
// Virtual clocks have no pins.
bool isVirtual() const;
PinSet *pins() const { return pins_; }
PinSet *vertexPins() const { return vertex_pins_; }
PinSet &pins() { return pins_; }
const PinSet &pins() const { return pins_; }
// The clock source pin's leaf pins.
// If the source pin is hierarchical, the leaf pins are:
// hierarchical input - load pins inside the hierarchical instance
// hierarchical output - load pins outside the hierarchical instance
PinSet &leafPins() { return leaf_pins_; }
const PinSet &leafPins() const { return leaf_pins_; }
// Clock pin used by input/output delay for propagated generated
// clock insertion delay.
Pin *defaultPin() const;
@ -92,7 +98,7 @@ public:
void addPin(Pin *pin);
void deletePin(Pin *pin);
void makeVertexPins(const Network *network);
void makeLeafPins(const Network *network);
bool isGenerated() const;
bool isGeneratedWithPropagatedMaster() const;
@ -157,10 +163,10 @@ protected:
void generateEdgesClk(const Clock *src_clk);
const char *name_;
PinSet *pins_;
PinSet pins_;
bool add_to_pins_;
// Hierarchical pins in pins_ become driver pins through the pin.
PinSet *vertex_pins_;
PinSet leaf_pins_;
Pin *pll_out_;
Pin *pll_fdbk_;
float period_;
@ -293,23 +299,8 @@ sortClockSet(ClockSet * set,
class ClockPinIterator : public PinSet::Iterator
{
public:
ClockPinIterator(Clock *clk) :
PinSet::Iterator(clk->pins())
{
}
};
// The clock source pin's graph vertex pins.
// If the source pin is hierarchical, the vertex pins are:
// hierarchical input - load pins inside the hierarchical instance
// hierarchical output - load pins outside the hierarchical instance
class ClockVertexPinIterator : public PinSet::Iterator
{
public:
ClockVertexPinIterator(Clock *clk) :
PinSet::Iterator(clk->vertexPins())
{
}
// Use range iterator on Clock::pins().
ClockPinIterator(Clock *clk) __attribute__ ((deprecated));
};
} // namespace

View File

@ -85,7 +85,7 @@ InputDelay::InputDelay(Pin *pin,
next_(nullptr),
index_(index)
{
findVertexLoadPins(pin, network, &vertex_pins_);
findLeafLoadPins(pin, network, &leaf_pins_);
}
void
@ -102,7 +102,7 @@ OutputDelay::OutputDelay(Pin *pin,
next_(nullptr)
{
if (network)
findVertexDriverPins(pin, network, &vertex_pins_);
findLeafDriverPins(pin, network, &leaf_pins_);
}
void
@ -113,6 +113,8 @@ OutputDelay::setNext(OutputDelay *next)
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
PinInputDelayIterator::PinInputDelayIterator(const Pin *pin,
const Sdc *sdc)
{
@ -134,11 +136,11 @@ PinInputDelayIterator::next()
return next;
}
VertexPinInputDelayIterator::VertexPinInputDelayIterator(const Pin *vertex_pin,
const Sdc *sdc) :
LeafPinInputDelayIterator::LeafPinInputDelayIterator(const Pin *vertex_pin,
const Sdc *sdc) :
PinInputDelayIterator()
{
next_ = sdc->input_delay_vertex_map_.findKey(vertex_pin);
next_ = sdc->input_delay_leaf_pin_map_.findKey(vertex_pin);
}
////////////////////////////////////////////////////////////////
@ -164,11 +166,11 @@ PinOutputDelayIterator::next()
return next;
}
VertexPinOutputDelayIterator::VertexPinOutputDelayIterator(const Pin *vertex_pin,
const Sdc *sdc) :
LeafPinOutputDelayIterator::LeafPinOutputDelayIterator(const Pin *vertex_pin,
const Sdc *sdc) :
PinOutputDelayIterator()
{
next_ = sdc->output_delay_vertex_map_.findKey(vertex_pin);
next_ = sdc->output_delay_leaf_pin_map_.findKey(vertex_pin);
}
////////////////////////////////////////////////////////////////

View File

@ -33,7 +33,7 @@ class PortDelay
public:
RiseFallMinMax *delays() { return &delays_; }
Pin *pin() const { return pin_; }
PinSet &vertexPins() { return vertex_pins_; }
PinSet &leafPins() { return leaf_pins_; }
Clock *clock() const;
ClockEdge *clkEdge() const { return clk_edge_; }
bool sourceLatencyIncluded() const;
@ -44,7 +44,9 @@ public:
TransRiseFall *refTransition() const;
protected:
PortDelay(Pin *pin, ClockEdge *clk_edge, Pin *ref_pin);
PortDelay(Pin *pin,
ClockEdge *clk_edge,
Pin *ref_pin);
Pin *pin_;
ClockEdge *clk_edge_;
@ -52,7 +54,7 @@ protected:
bool network_latency_included_;
Pin *ref_pin_;
RiseFallMinMax delays_;
PinSet vertex_pins_;
PinSet leaf_pins_;
private:
DISALLOW_COPY_AND_ASSIGN(PortDelay);
@ -85,15 +87,6 @@ private:
friend class InputDelayIterator;
};
class InputDelayVertexPinIterator : public PinSet::Iterator
{
public:
InputDelayVertexPinIterator(InputDelay *input_delay) :
PinSet::Iterator(input_delay->vertexPins())
{
}
};
class OutputDelay : public PortDelay
{
public:
@ -117,15 +110,6 @@ private:
friend class OutputDelayIterator;
};
class OutputDelayVertexPinIterator : public PinSet::Iterator
{
public:
OutputDelayVertexPinIterator(OutputDelay *output_delay) :
PinSet::Iterator(output_delay->vertexPins())
{
}
};
class PinInputDelayIterator : public Iterator<InputDelay*>
{
public:
@ -142,14 +126,14 @@ protected:
DISALLOW_COPY_AND_ASSIGN(PinInputDelayIterator);
};
class VertexPinInputDelayIterator : public PinInputDelayIterator
class LeafPinInputDelayIterator : public PinInputDelayIterator
{
public:
VertexPinInputDelayIterator(const Pin *vertex_pin,
LeafPinInputDelayIterator(const Pin *pin,
const Sdc *sdc);
private:
DISALLOW_COPY_AND_ASSIGN(VertexPinInputDelayIterator);
DISALLOW_COPY_AND_ASSIGN(LeafPinInputDelayIterator);
};
class PinOutputDelayIterator : public Iterator<OutputDelay*>
@ -168,14 +152,14 @@ protected:
DISALLOW_COPY_AND_ASSIGN(PinOutputDelayIterator);
};
class VertexPinOutputDelayIterator : public PinOutputDelayIterator
class LeafPinOutputDelayIterator : public PinOutputDelayIterator
{
public:
VertexPinOutputDelayIterator(const Pin *vertex_pin,
const Sdc *sdc);
LeafPinOutputDelayIterator(const Pin *pin,
const Sdc *sdc);
private:
DISALLOW_COPY_AND_ASSIGN(VertexPinOutputDelayIterator);
DISALLOW_COPY_AND_ASSIGN(LeafPinOutputDelayIterator);
};
// Prediate used to sort port delays.

View File

@ -148,7 +148,7 @@ Sdc::clear()
clocks_.clear();
clock_name_map_.clear();
clock_pin_map_.clear();
clock_vertex_pin_map_.clear();
clock_leaf_pin_map_.clear();
clk_latencies_.clear();
edge_clk_latency_.clear();
if (clk_insertions_)
@ -166,13 +166,14 @@ Sdc::clear()
data_checks_from_map_.clear();
data_checks_to_map_.clear();
input_delays_.clear();
input_delay_map_.clear();
input_delay_index_ = 0;
input_delay_ref_pin_map_.clear();
input_delay_vertex_map_.clear();
input_delay_leaf_pin_map_.clear();
input_delay_internal_pin_map_.clear();
output_delay_map_.clear();
output_delay_vertex_map_.clear();
output_delay_leaf_pin_map_.clear();
port_slew_limit_map_.clear();
cell_slew_limit_map_.clear();
@ -244,7 +245,7 @@ Sdc::deleteConstraints()
clocks_.deleteContents();
delete default_arrival_clk_;
clock_pin_map_.deleteContents();
clock_vertex_pin_map_.deleteContents();
clock_leaf_pin_map_.deleteContents();
clk_latencies_.deleteContents();
if (clk_insertions_) {
clk_insertions_->deleteContents();
@ -1126,10 +1127,10 @@ Sdc::deletePinClocks(Clock *defining_clk,
clk->deletePin(pin);
}
if (clk != defining_clk) {
if (clk->pins()->empty())
if (clk->pins().empty())
removeClock(clk);
else {
clk->makeVertexPins(network_);
clk->makeLeafPins(network_);
// One of the remaining clock pins may use a vertex pin that
// was deleted above.
makeClkPinMappings(clk);
@ -1141,9 +1142,7 @@ Sdc::deletePinClocks(Clock *defining_clk,
void
Sdc::deleteClkPinMappings(Clock *clk)
{
ClockPinIterator pin_iter1(clk);
while (pin_iter1.hasNext()) {
Pin *pin = pin_iter1.next();
for (Pin *pin : clk->pins()) {
ClockSet *pin_clks = clock_pin_map_.findKey(pin);
if (pin_clks) {
pin_clks->erase(clk);
@ -1154,14 +1153,12 @@ Sdc::deleteClkPinMappings(Clock *clk)
}
}
ClockVertexPinIterator pin_iter2(clk);
while (pin_iter2.hasNext()) {
Pin *pin = pin_iter2.next();
ClockSet *pin_clks = clock_vertex_pin_map_.findKey(pin);
for (const Pin *pin : clk->leafPins()) {
ClockSet *pin_clks = clock_leaf_pin_map_.findKey(pin);
if (pin_clks) {
pin_clks->erase(clk);
if (pin_clks->empty()) {
clock_vertex_pin_map_.erase(pin);
clock_leaf_pin_map_.erase(pin);
delete pin_clks;
}
}
@ -1171,9 +1168,7 @@ Sdc::deleteClkPinMappings(Clock *clk)
void
Sdc::makeClkPinMappings(Clock *clk)
{
ClockPinIterator pin_iter1(clk);
while (pin_iter1.hasNext()) {
Pin *pin = pin_iter1.next();
for (Pin *pin : clk->pins()) {
ClockSet *pin_clks = clock_pin_map_.findKey(pin);
if (pin_clks == nullptr) {
pin_clks = new ClockSet;
@ -1182,13 +1177,11 @@ Sdc::makeClkPinMappings(Clock *clk)
pin_clks->insert(clk);
}
ClockVertexPinIterator pin_iter2(clk);
while (pin_iter2.hasNext()) {
Pin *pin = pin_iter2.next();
ClockSet *pin_clks = clock_vertex_pin_map_.findKey(pin);
for (const Pin *pin : clk->leafPins()) {
ClockSet *pin_clks = clock_leaf_pin_map_.findKey(pin);
if (pin_clks == nullptr) {
pin_clks = new ClockSet;
clock_vertex_pin_map_.insert(pin, pin_clks);
clock_leaf_pin_map_.insert(pin, pin_clks);
}
pin_clks->insert(clk);
}
@ -1236,7 +1229,7 @@ Sdc::clockDeletePin(Clock *clk,
if (pin_clks->empty())
clock_pin_map_.erase(pin);
clk->deletePin(pin);
clk->makeVertexPins(network_);
clk->makeLeafPins(network_);
makeClkPinMappings(clk);
}
@ -1254,16 +1247,16 @@ Sdc::isClock(const Pin *pin) const
}
bool
Sdc::isVertexPinClock(const Pin *pin) const
Sdc::isLeafPinClock(const Pin *pin) const
{
ClockSet *clks = findVertexPinClocks(pin);
ClockSet *clks = findLeafPinClocks(pin);
return clks && !clks->empty();
}
bool
Sdc::isVertexPinNonGeneratedClock(const Pin *pin) const
Sdc::isLeafPinNonGeneratedClock(const Pin *pin) const
{
ClockSet *clks = findVertexPinClocks(pin);
ClockSet *clks = findLeafPinClocks(pin);
if (clks) {
ClockSet::Iterator clk_iter(clks);
while (clk_iter.hasNext()) {
@ -1278,9 +1271,9 @@ Sdc::isVertexPinNonGeneratedClock(const Pin *pin) const
}
ClockSet *
Sdc::findVertexPinClocks(const Pin *pin) const
Sdc::findLeafPinClocks(const Pin *pin) const
{
return clock_vertex_pin_map_.findKey(pin);
return clock_leaf_pin_map_.findKey(pin);
}
ClockSet *
@ -1468,21 +1461,15 @@ Sdc::ensureClkHpinDisables()
if (!clk_hpin_disables_valid_) {
clk_hpin_disables_.deleteContentsClear();
for (auto clk : clocks_) {
PinSet *srcs = clk->pins();
PinSet::Iterator src_iter(srcs);
while (src_iter.hasNext()) {
Pin *src = src_iter.next();
for (Pin *src : clk->pins()) {
if (network_->isHierarchical(src)) {
FindClkHpinDisables visitor(clk, network_, this);
visitHpinDrvrLoads(src, network_, &visitor);
// Disable fanouts from the src driver pins that do
// not go thru the hierarchical src pin.
PinSet *vpins = clk->vertexPins();
PinSet::Iterator vpin_iter(vpins);
while (vpin_iter.hasNext()) {
Pin *vpin = vpin_iter.next();
for (Pin *lpin : clk->leafPins()) {
Vertex *vertex, *bidirect_drvr_vertex;
graph_->pinVertices(vpin, vertex, bidirect_drvr_vertex);
graph_->pinVertices(lpin, vertex, bidirect_drvr_vertex);
makeVertexClkHpinDisables(clk, vertex, visitor);
if (bidirect_drvr_vertex)
makeVertexClkHpinDisables(clk, bidirect_drvr_vertex, visitor);
@ -1516,7 +1503,7 @@ Sdc::clkHpinDisablesInvalid()
{
clk_hpin_disables_valid_ = false;
for (auto clk : clocks_)
clk->makeVertexPins(network_);
clk->makeLeafPins(network_);
}
// Check that driver/load edge goes thru clock hpin.
@ -1526,8 +1513,7 @@ Sdc::clkDisabledByHpinThru(const Clock *clk,
const Pin *from_pin,
const Pin *to_pin)
{
if (clk->vertexPins()
&& clk->vertexPins()->hasKey(const_cast<Pin*>(from_pin))) {
if (clk->leafPins().hasKey(const_cast<Pin*>(from_pin))) {
ClkHpinDisable probe(clk, from_pin, to_pin);
return clk_hpin_disables_.hasKey(&probe);
}
@ -2807,6 +2793,7 @@ Sdc::ensureInputDelay(Pin *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) {
@ -2817,10 +2804,8 @@ Sdc::ensureInputDelay(Pin *pin,
}
ref_inputs->insert(input_delay);
}
InputDelayVertexPinIterator vpin_iter(input_delay);
while (vpin_iter.hasNext()) {
Pin *vpin = vpin_iter.next();
input_delay_vertex_map_[vpin] = input_delay;
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) {
@ -2875,15 +2860,16 @@ Sdc::deleteInputDelays(Pin *pin,
InputDelay *next = input_delay->next();
if (input_delay == except)
input_delay->setNext(nullptr);
else
else {
delete input_delay;
input_delays_.erase(input_delay);
}
input_delay = next;
}
input_delay_map_[pin] = except;
InputDelayVertexPinIterator vpin_iter(except);
while (vpin_iter.hasNext()) {
Pin *vpin = vpin_iter.next();
input_delay_vertex_map_[vpin] = 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) {
@ -2899,35 +2885,16 @@ Sdc::refPinInputDelays(const Pin *ref_pin) const
return input_delay_ref_pin_map_.findKey(ref_pin);
}
InputDelayIterator *
Sdc::inputDelayIterator()
{
return new InputDelayIterator(input_delay_map_);
}
InputDelayVertexPinsIterator *
Sdc::inputDelayVertexPinsIterator()
{
return new InputDelayVertexPinsIterator(input_delay_vertex_map_);
}
PinInputDelayIterator *
Sdc::inputDelayIterator(const Pin *pin) const
{
return new PinInputDelayIterator(pin, this);
}
PinInputDelayIterator *
Sdc::inputDelayVertexIterator(const Pin *vertex_pin) const
{
return new VertexPinInputDelayIterator(vertex_pin, this);
}
bool
Sdc::hasInputDelay(const Pin *vertex_pin) const
Sdc::hasInputDelay(const Pin *leaf_pin) const
{
return input_delay_vertex_map_.findKey(vertex_pin) != nullptr;
return input_delay_leaf_pin_map_.findKey(leaf_pin) != nullptr;
}
bool
@ -2943,17 +2910,19 @@ Sdc::isInputDelayInternal(const Pin *pin) const
void
Sdc::deleteInputDelaysReferencing(Clock *clk)
{
InputDelayIterator input_iter(input_delay_map_);
while (input_iter.hasNext()) {
InputDelay *input_delay = input_iter.next();
Vector<InputDelay*> refs;
for (InputDelay *input_delay : input_delays_) {
if (input_delay->clock() == clk)
deleteInputDelay(input_delay);
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) {
@ -2975,13 +2944,11 @@ Sdc::deleteInputDelay(InputDelay *input_delay)
}
}
InputDelayVertexPinIterator vpin_iter(input_delay);
while (vpin_iter.hasNext()) {
Pin *vpin = vpin_iter.next();
for (Pin *vpin : input_delay->leafPins()) {
if (head)
input_delay_vertex_map_[vpin] = head;
input_delay_leaf_pin_map_[vpin] = head;
else
input_delay_vertex_map_.erase(vpin);
input_delay_leaf_pin_map_.erase(vpin);
}
delete input_delay;
@ -3022,12 +2989,11 @@ Sdc::ensureOutputDelay(Pin *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;
OutputDelayVertexPinIterator vpin_iter(output_delay);
while (vpin_iter.hasNext()) {
Pin *vpin = vpin_iter.next();
output_delay_vertex_map_[vpin] = output_delay;
for (Pin *vpin : output_delay->leafPins()) {
output_delay_leaf_pin_map_[vpin] = output_delay;
if (graph_)
annotateGraphConstrained(vpin, true);
}
@ -3079,17 +3045,8 @@ Sdc::deleteOutputDelays(Pin *pin,
output_delay = next;
}
output_delay_map_[pin] = except;
OutputDelayVertexPinIterator vpin_iter(except);
while (vpin_iter. hasNext()) {
Pin *vpin = vpin_iter.next();
output_delay_vertex_map_[vpin] = except;
}
}
OutputDelayIterator *
Sdc::outputDelayIterator()
{
return new OutputDelayIterator(output_delay_map_);
for (Pin *vpin : except->leafPins())
output_delay_leaf_pin_map_[vpin] = except;
}
PinOutputDelayIterator *
@ -3098,33 +3055,29 @@ Sdc::outputDelayIterator(const Pin *pin) const
return new PinOutputDelayIterator(pin, this);
}
PinOutputDelayIterator *
Sdc::outputDelayVertexIterator(const Pin *vertex_pin) const
{
return new VertexPinOutputDelayIterator(vertex_pin, this);
}
bool
Sdc::hasOutputDelay(const Pin *vertex_pin) const
Sdc::hasOutputDelay(const Pin *leaf_pin) const
{
return output_delay_vertex_map_.hasKey(vertex_pin);
return output_delay_leaf_pin_map_.hasKey(leaf_pin);
}
void
Sdc::deleteOutputDelaysReferencing(Clock *clk)
{
OutputDelayIterator output_iter(output_delay_map_);
while (output_iter.hasNext()) {
OutputDelay *output_delay = output_iter.next();
Vector<OutputDelay*> refs;
for (OutputDelay *output_delay : output_delays_) {
if (output_delay->clock() == clk)
deleteOutputDelay(output_delay);
refs.push_back(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();
@ -3145,13 +3098,11 @@ Sdc::deleteOutputDelay(OutputDelay *output_delay)
}
}
OutputDelayVertexPinIterator vpin_iter(output_delay);
while (vpin_iter.hasNext()) {
Pin *vpin = vpin_iter.next();
for (Pin *vpin : output_delay->leafPins()) {
if (head)
output_delay_vertex_map_[vpin] = head;
output_delay_leaf_pin_map_[vpin] = head;
else
output_delay_vertex_map_.erase(vpin);
output_delay_leaf_pin_map_.erase(vpin);
}
delete output_delay;
@ -6167,7 +6118,7 @@ Sdc::disconnectPinBefore(Pin *pin)
void
Sdc::clkHpinDisablesChanged(Pin *pin)
{
if (isVertexPinClock(pin))
if (isLeafPinClock(pin))
clkHpinDisablesInvalid();
}
@ -6398,11 +6349,8 @@ Sdc::annotateGraphOutputDelays(bool annotate)
while (output_iter.hasNext()) {
OutputDelay *output_delay = output_iter.next();
while (output_delay) {
OutputDelayVertexPinIterator vpin_iter(output_delay);
while (vpin_iter.hasNext()) {
Pin *vpin = vpin_iter.next();
for (Pin *vpin : output_delay->leafPins())
annotateGraphConstrained(vpin, annotate);
}
output_delay = output_delay->next();
}
}
@ -6534,40 +6482,14 @@ Sdc::clockLatency(Edge *edge,
////////////////////////////////////////////////////////////////
InputDelayVertexPinsIterator::InputDelayVertexPinsIterator(Sdc *sdc) :
InputDelayVertexPinsIterator(sdc->input_delay_map_)
{
}
InputDelayVertexPinsIterator::InputDelayVertexPinsIterator(InputDelayMap
&input_delay_map) :
input_iter_(input_delay_map)
{
}
bool
InputDelayVertexPinsIterator::hasNext()
{
return input_iter_.hasNext();
}
const Pin *
InputDelayVertexPinsIterator::next()
{
const Pin *pin;
InputDelay *input_delay;
input_iter_.next(pin, input_delay);
return pin;
}
////////////////////////////////////////////////////////////////
// Find the graph vertex pins corresponding to pin.
// If the pin is hierarchical, the vertex pins are:
// Find the leaf load pins corresponding to pin.
// If the pin is hierarchical, the leaf pins are:
// hierarchical input - load pins inside the hierarchical instance
// hierarchical output - load pins outside the hierarchical instance
void
findVertexLoadPins(Pin *pin, const Network *network, PinSet *vertex_pins)
findLeafLoadPins(Pin *pin,
const Network *network,
PinSet *leaf_pins)
{
if (network->isHierarchical(pin)) {
PortDirection *dir = network->direction(pin);
@ -6581,22 +6503,22 @@ findVertexLoadPins(Pin *pin, const Network *network, PinSet *vertex_pins)
if (((is_input && is_inside)
|| (is_output && !is_inside))
&& network->isLoad(pin1))
vertex_pins->insert(pin1);
leaf_pins->insert(pin1);
}
delete pin_iter;
}
else
vertex_pins->insert(pin);
leaf_pins->insert(pin);
}
// Find the graph vertex pins corresponding to pin.
// If the pin is hierarchical, the vertex pins are:
// Find the leaf driver pins corresponding to pin.
// If the pin is hierarchical, the leaf pins are:
// hierarchical input - driver pins outside the hierarchical instance
// hierarchical output - driver pins inside the hierarchical instance
void
findVertexDriverPins(Pin *pin,
const Network *network,
PinSet *vertex_pins)
findLeafDriverPins(Pin *pin,
const Network *network,
PinSet *leaf_pins)
{
if (network->isHierarchical(pin)) {
PortDirection *dir = network->direction(pin);
@ -6610,86 +6532,12 @@ findVertexDriverPins(Pin *pin,
if (((is_input && !is_inside)
|| (is_output && is_inside))
&& network->isDriver(pin1))
vertex_pins->insert(pin1);
leaf_pins->insert(pin1);
}
delete pin_iter;
}
else
vertex_pins->insert(pin);
}
////////////////////////////////////////////////////////////////
InputDelayIterator::InputDelayIterator(Sdc *sdc) :
InputDelayIterator(sdc->input_delay_map_)
{
}
InputDelayIterator::InputDelayIterator(InputDelayMap &input_delay_map) :
input_iter_(input_delay_map),
next_(NULL)
{
findNext();
}
bool
InputDelayIterator::hasNext()
{
return next_ != NULL;
}
InputDelay *
InputDelayIterator::next()
{
InputDelay *next = next_;
findNext();
return next;
}
void
InputDelayIterator::findNext()
{
if (next_)
next_ = next_->next();
if (next_ == NULL && input_iter_.hasNext())
next_ = input_iter_.next();
}
////////////////////////////////////////////////////////////////
OutputDelayIterator::OutputDelayIterator(Sdc *sdc) :
OutputDelayIterator(sdc->output_delay_map_)
{
}
OutputDelayIterator::OutputDelayIterator(OutputDelayMap &output_delay_map) :
output_iter_(output_delay_map),
next_(NULL)
{
findNext();
}
bool
OutputDelayIterator::hasNext()
{
return next_ != NULL;
}
OutputDelay *
OutputDelayIterator::next()
{
OutputDelay *next = next_;
findNext();
return next;
}
void
OutputDelayIterator::findNext()
{
if (next_)
next_ = next_->next();
if (next_ == NULL && output_iter_.hasNext())
next_ = output_iter_.next();
leaf_pins->insert(pin);
}
////////////////////////////////////////////////////////////////

View File

@ -39,14 +39,11 @@ namespace sta {
class OperatingConditions;
class PinInputDelayIterator;
class InputDelayVertexPinsIterator;
class PinOutputDelayIterator;
class PortExtCap;
class ClockGatingCheck;
class InputDriveCell;
class DisabledPorts;
class InputDelayIterator;
class OutputDelayIterator;
class GraphLoop;
class DeratingFactors;
class DeratingFactorsGlobal;
@ -59,7 +56,6 @@ class FindClkHpinDisables;
class Corner;
class ClockGroupIterator;
class GroupPathIterator;
class ClockVertexPinIterator;
class ClockPinIterator;
class ClockIterator;
@ -109,10 +105,12 @@ 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 Set<OutputDelay*> OutputDelaySet;
typedef Map<const Pin*,OutputDelay*> OutputDelayMap;
// Use HashSet so no read lock is required.
typedef HashSet<CycleAccting*, CycleAcctingHash, CycleAcctingEqual> CycleAcctingSet;
@ -169,13 +167,13 @@ typedef Map<const char*, GroupPathSet*, CharPtrLess> GroupPathMap;
typedef Set<ClockPair, ClockPairLess> ClockPairSet;
void
findVertexLoadPins(Pin *pin, const
Network *network,
PinSet *vertex_pins);
findLeafLoadPins(Pin *pin,
const Network *network,
PinSet *leaf_pins);
void
findVertexDriverPins(Pin *pin,
const Network *network,
PinSet *vertex_pins);
findLeafDriverPins(Pin *pin,
const Network *network,
PinSet *leaf_pins);
class Sdc : public StaState
{
@ -840,12 +838,12 @@ public:
// True if pin is defined as a clock source (pin may be hierarchical).
bool isClock(const Pin *pin) const;
// True if pin is a clock source vertex.
bool isVertexPinClock(const Pin *pin) const;
bool isLeafPinClock(const Pin *pin) const;
// True if pin is a non-generated clock source vertex.
bool isVertexPinNonGeneratedClock(const Pin *pin) const;
bool isLeafPinNonGeneratedClock(const Pin *pin) const;
// Find the clocks defined for pin.
ClockSet *findClocks(const Pin *pin) const;
ClockSet *findVertexPinClocks(const Pin *pin) const;
ClockSet *findLeafPinClocks(const Pin *pin) const;
ClockIterator *clockIterator();
void sortedClocks(ClockSeq &clks);
ClockSeq *clocks() { return &clocks_; }
@ -894,28 +892,18 @@ public:
const ClockEdge *tgt);
// Report clock to clock relationships that exceed max_cycle_count.
void reportClkToClkMaxCycleWarnings();
InputDelayIterator *inputDelayIterator();
// Iterate over the graph vertex pins that have input arrivals.
// If the pin is hierarchical, the vertex pins are:
// hierarchical input - load pins inside the hierarchical instance.
// hierarchical output - load pins outside the hierarchical instance.
InputDelayVertexPinsIterator *inputDelayVertexPinsIterator();
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;
// Iterate over the input delays on vertex_pin.
PinInputDelayIterator *inputDelayVertexIterator(const Pin *vertex_pin) const;
bool hasInputDelay(const Pin *vertex_pin) const;
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;
OutputDelayIterator *outputDelayIterator();
const OutputDelaySet &outputDelays() const { return output_delays_; }
// Iterate over the output delays on pin (which may be hierarchical).
PinOutputDelayIterator *outputDelayIterator(const Pin *pin) const;
// Iterate over the output delays on vertex_pin.
// If the pin is hierarchical, the vertex pins are:
// hierarchical input - driver pins outside the hierarchical instance.
// hierarchical output - driver pins inside the hierarchical instance.
PinOutputDelayIterator *outputDelayVertexIterator(const Pin *vertex_pin) const;
bool hasOutputDelay(const Pin *vertex_pin) const;
bool hasOutputDelay(const Pin *leaf_pin) const;
PortExtCap *portExtCap(Port *port) const;
bool hasPortExtCap(Port *port) const;
void portExtCap(Port *port,
@ -1302,7 +1290,7 @@ protected:
ClockNameMap clock_name_map_;
ClockPinMap clock_pin_map_;
// Clocks on hierarchical pins are indexed by the load pins.
ClockPinMap clock_vertex_pin_map_;
ClockPinMap clock_leaf_pin_map_;
ClkHpinDisables clk_hpin_disables_;
bool clk_hpin_disables_valid_;
PinSet propagated_clk_pins_;
@ -1325,15 +1313,17 @@ protected:
std::mutex cycle_acctings_lock_;
DataChecksMap data_checks_from_map_;
DataChecksMap data_checks_to_map_;
InputDelaySet input_delays_;
InputDelayMap input_delay_map_;
int input_delay_index_;
InputDelayRefPinMap input_delay_ref_pin_map_;
// Input delays on hierarchical pins are indexed by the load pins.
InputDelayMap input_delay_vertex_map_;
InputDelayMap input_delay_leaf_pin_map_;
InputDelayInternalPinMap input_delay_internal_pin_map_;
OutputDelaySet output_delays_;
OutputDelayMap output_delay_map_;
// Output delays on hierarchical pins are indexed by the load pins.
OutputDelayMap output_delay_vertex_map_;
OutputDelayMap output_delay_leaf_pin_map_;
PortSlewLimitMap port_slew_limit_map_;
PinSlewLimitMap pin_slew_limit_map_;
CellSlewLimitMap cell_slew_limit_map_;
@ -1427,67 +1417,13 @@ private:
DISALLOW_COPY_AND_ASSIGN(Sdc);
friend class WriteSdc;
friend class InputDelayIterator;
friend class OutputDelayIterator;
friend class FindNetCaps;
friend class ClockGroupIterator;
friend class GroupPathIterator;
friend class InputDelayVertexPinsIterator;
friend class PinInputDelayIterator;
friend class VertexPinInputDelayIterator;
friend class LeafPinInputDelayIterator;
friend class PinOutputDelayIterator;
friend class VertexPinOutputDelayIterator;
};
class InputDelayVertexPinsIterator : public Iterator<const Pin*>
{
public:
InputDelayVertexPinsIterator(Sdc *sdc);
virtual bool hasNext();
virtual const Pin *next();
private:
InputDelayVertexPinsIterator(InputDelayMap &input_delay_map);
InputDelayMap::ConstIterator input_iter_;
friend class Sdc;
DISALLOW_COPY_AND_ASSIGN(InputDelayVertexPinsIterator);
};
class InputDelayIterator : public Iterator<InputDelay*>
{
public:
InputDelayIterator(Sdc *sdc);
virtual bool hasNext();
virtual InputDelay *next();
private:
InputDelayIterator(InputDelayMap &input_delay_map);
void findNext();
InputDelayMap::Iterator input_iter_;
InputDelay *next_;
friend class Sdc;
DISALLOW_COPY_AND_ASSIGN(InputDelayIterator);
};
class OutputDelayIterator : public OutputDelayMap::Iterator
{
public:
OutputDelayIterator(Sdc *sdc);
virtual bool hasNext();
virtual OutputDelay *next();
private:
OutputDelayIterator(OutputDelayMap &output_delay_map);
void findNext();
OutputDelayMap::Iterator output_iter_;
OutputDelay *next_;
friend class Sdc;
DISALLOW_COPY_AND_ASSIGN(OutputDelayIterator);
friend class LeafPinOutputDelayIterator;
};
class ClockIterator : public ClockSeq::Iterator

View File

@ -110,6 +110,7 @@ class WriteGetPinAndClkKey : public WriteSdcObject
{
public:
WriteGetPinAndClkKey(const Pin *pin,
bool map_hpin_to_drvr,
const Clock *clk,
const WriteSdc *writer);
virtual void write() const;
@ -118,14 +119,17 @@ private:
DISALLOW_COPY_AND_ASSIGN(WriteGetPinAndClkKey);
const Pin *pin_;
bool map_hpin_to_drvr_;
const Clock *clk_;
const WriteSdc *writer_;
};
WriteGetPinAndClkKey::WriteGetPinAndClkKey(const Pin *pin,
bool map_hpin_to_drvr,
const Clock *clk,
const WriteSdc *writer) :
pin_(pin),
map_hpin_to_drvr_(map_hpin_to_drvr),
clk_(clk),
writer_(writer)
{
@ -136,13 +140,14 @@ WriteGetPinAndClkKey::write() const
{
writer_->writeClockKey(clk_);
fprintf(writer_->stream(), " ");
writer_->writeGetPin(pin_);
writer_->writeGetPin(pin_, map_hpin_to_drvr_);
}
class WriteGetPin : public WriteSdcObject
{
public:
WriteGetPin(const Pin *pin,
bool map_hpin_to_drvr,
const WriteSdc *writer);
virtual void write() const;
@ -150,12 +155,15 @@ private:
DISALLOW_COPY_AND_ASSIGN(WriteGetPin);
const Pin *pin_;
bool map_hpin_to_drvr_;
const WriteSdc *writer_;
};
WriteGetPin::WriteGetPin(const Pin *pin,
bool map_hpin_to_drvr,
const WriteSdc *writer) :
pin_(pin),
map_hpin_to_drvr_(map_hpin_to_drvr),
writer_(writer)
{
}
@ -163,7 +171,7 @@ WriteGetPin::WriteGetPin(const Pin *pin,
void
WriteGetPin::write() const
{
writer_->writeGetPin(pin_);
writer_->writeGetPin(pin_, map_hpin_to_drvr_);
}
class WriteGetNet : public WriteSdcObject
@ -280,20 +288,22 @@ void
writeSdc(Instance *instance,
const char *filename,
const char *creator,
bool compatible,
bool map_hpins,
bool native,
bool no_timestamp,
int digits,
Sdc *sdc)
{
WriteSdc writer(instance, filename, creator, compatible, digits,
no_timestamp, sdc);
WriteSdc writer(instance, filename, creator, map_hpins, native,
digits, no_timestamp, sdc);
writer.write();
}
WriteSdc::WriteSdc(Instance *instance,
const char *filename,
const char *creator,
bool compatible,
bool map_hpins,
bool native,
int digits,
bool no_timestamp,
Sdc *sdc) :
@ -301,7 +311,8 @@ WriteSdc::WriteSdc(Instance *instance,
instance_(instance),
filename_(filename),
creator_(creator),
compatible_(compatible),
map_hpins_(map_hpins),
native_(native),
digits_(digits),
no_timestamp_(no_timestamp),
top_instance_(instance == sdc_network_->topInstance()),
@ -430,7 +441,7 @@ WriteSdc::writeGeneratedClock(Clock *clk) const
if (clk->addToPins())
fprintf(stream_, " -add");
fprintf(stream_, " -source ");
writeGetPin(clk->srcPin());
writeGetPin(clk->srcPin(), true);
Clock *master = clk->masterClk();
if (master && !clk->masterClkInfered()) {
fprintf(stream_, " -master_clock ");
@ -439,12 +450,12 @@ WriteSdc::writeGeneratedClock(Clock *clk) const
Pin *pll_out = clk->pllOut();
if (pll_out) {
fprintf(stream_, " -pll_out ");
writeGetPin(pll_out);
writeGetPin(pll_out, true);
}
Pin *pll_fdbk = clk->pllFdbk();
if (pll_fdbk) {
fprintf(stream_, " -pll_feedback ");
writeGetPin(pll_fdbk);
writeGetPin(pll_fdbk, false);
}
if (clk->combinational())
fprintf(stream_, " -combinational");
@ -481,16 +492,11 @@ void
WriteSdc::writeClockPins(Clock *clk) const
{
// Sort pins.
PinSeq pins;
ClockPinIterator pin_iter(clk);
while (pin_iter.hasNext())
pins.push_back(pin_iter.next());
PinSet &pins = clk->pins();
if (!pins.empty()) {
sort(pins, PinPathNameLess(sdc_network_));
if (pins.size() > 1)
fprintf(stream_, "\\\n ");
writeGetPins(&pins);
writeGetPins(&pins, true);
}
}
@ -572,7 +578,7 @@ WriteSdc::writeClockUncertaintyPin(const Pin *pin,
fprintf(stream_, "set_clock_uncertainty %s", setup_hold);
writeTime(value);
fprintf(stream_, " ");
writeGetPin(pin);
writeGetPin(pin, true);
fprintf(stream_, "\n");
}
@ -585,12 +591,12 @@ WriteSdc::writeClockLatencies() const
const Pin *pin = latency->pin();
const Clock *clk = latency->clock();
if (pin && clk) {
WriteGetPinAndClkKey write_pin(pin, clk, this);
WriteGetPinAndClkKey write_pin(pin, true, clk, this);
writeRiseFallMinMaxTimeCmd("set_clock_latency", latency->delays(),
write_pin);
}
else if (pin) {
WriteGetPin write_pin(pin, this);
WriteGetPin write_pin(pin, true, this);
writeRiseFallMinMaxTimeCmd("set_clock_latency", latency->delays(),
write_pin);
}
@ -611,11 +617,11 @@ WriteSdc::writeClockInsertions() const
const Pin *pin = insert->pin();
const Clock *clk = insert->clock();
if (pin && clk) {
WriteGetPinAndClkKey write_pin_clk(pin, clk, this);
WriteGetPinAndClkKey write_pin_clk(pin, true, clk, this);
writeClockInsertion(insert, write_pin_clk);
}
else if (pin) {
WriteGetPin write_pin(pin, this);
WriteGetPin write_pin(pin, true, this);
writeClockInsertion(insert, write_pin);
}
else if (clk) {
@ -649,7 +655,7 @@ WriteSdc::writePropagatedClkPins() const
while (pin_iter.hasNext()) {
const Pin *pin = pin_iter.next();
fprintf(stream_, "set_propagated_clock ");
writeGetPin(pin);
writeGetPin(pin, true);
fprintf(stream_, "\n");
}
}
@ -717,11 +723,8 @@ WriteSdc::writeInputDelays() const
{
// Sort arrivals by pin and clock name.
PortDelaySeq delays;
InputDelayIterator input_iter(sdc_);
while (input_iter.hasNext()) {
InputDelay *input_delay = input_iter.next();
for (InputDelay *input_delay : sdc_->inputDelays())
delays.push_back(input_delay);
}
PortDelayLess port_delay_less(sdc_network_);
sort(delays, port_delay_less);
@ -729,7 +732,7 @@ WriteSdc::writeInputDelays() const
PortDelaySeq::Iterator delay_iter(delays);
while (delay_iter.hasNext()) {
PortDelay *input_delay = delay_iter.next();
writePortDelay(input_delay, "set_input_delay");
writePortDelay(input_delay, true, "set_input_delay");
}
}
@ -738,11 +741,8 @@ WriteSdc::writeOutputDelays() const
{
// Sort departures by pin and clock name.
PortDelaySeq delays;
OutputDelayIterator output_iter(sdc_);
while (output_iter.hasNext()) {
OutputDelay *output_delay = output_iter.next();
for (OutputDelay *output_delay : sdc_->outputDelays())
delays.push_back(output_delay);
}
PortDelayLess port_delay_less(sdc_network_);
sort(delays, port_delay_less);
@ -750,12 +750,13 @@ WriteSdc::writeOutputDelays() const
PortDelaySeq::Iterator delay_iter(delays);
while (delay_iter.hasNext()) {
PortDelay *output_delay = delay_iter.next();
writePortDelay(output_delay, "set_output_delay");
writePortDelay(output_delay, false, "set_output_delay");
}
}
void
WriteSdc::writePortDelay(PortDelay *port_delay,
bool is_input_delay,
const char *sdc_cmd) const
{
RiseFallMinMax *delays = port_delay->delays();
@ -777,7 +778,7 @@ WriteSdc::writePortDelay(PortDelay *port_delay,
&& rise_max == rise_min
&& fall_min == rise_min
&& fall_max == rise_min)
writePortDelay(port_delay, rise_min,
writePortDelay(port_delay, is_input_delay, rise_min,
TransRiseFallBoth::riseFall(), MinMaxAll::all(), sdc_cmd);
else if (rise_min_exists
&& rise_max_exists
@ -785,9 +786,9 @@ WriteSdc::writePortDelay(PortDelay *port_delay,
&& fall_min_exists
&& fall_max_exists
&& fall_min == fall_max) {
writePortDelay(port_delay, rise_min,
writePortDelay(port_delay, is_input_delay, rise_min,
TransRiseFallBoth::rise(), MinMaxAll::all(), sdc_cmd);
writePortDelay(port_delay, fall_min,
writePortDelay(port_delay, is_input_delay, fall_min,
TransRiseFallBoth::fall(), MinMaxAll::all(), sdc_cmd);
}
else if (rise_min_exists
@ -796,29 +797,30 @@ WriteSdc::writePortDelay(PortDelay *port_delay,
&& rise_max_exists
&& fall_max_exists
&& rise_max == fall_max) {
writePortDelay(port_delay, rise_min,
writePortDelay(port_delay, is_input_delay, rise_min,
TransRiseFallBoth::riseFall(), MinMaxAll::min(), sdc_cmd);
writePortDelay(port_delay, rise_max,
writePortDelay(port_delay, is_input_delay, rise_max,
TransRiseFallBoth::riseFall(), MinMaxAll::max(), sdc_cmd);
}
else {
if (rise_min_exists)
writePortDelay(port_delay, rise_min,
writePortDelay(port_delay, is_input_delay, rise_min,
TransRiseFallBoth::rise(), MinMaxAll::min(), sdc_cmd);
if (rise_max_exists)
writePortDelay(port_delay, rise_max,
writePortDelay(port_delay, is_input_delay, rise_max,
TransRiseFallBoth::rise(), MinMaxAll::max(), sdc_cmd);
if (fall_min_exists)
writePortDelay(port_delay, fall_min,
writePortDelay(port_delay, is_input_delay, fall_min,
TransRiseFallBoth::fall(), MinMaxAll::min(), sdc_cmd);
if (fall_max_exists)
writePortDelay(port_delay, fall_max,
writePortDelay(port_delay, is_input_delay, fall_max,
TransRiseFallBoth::fall(), MinMaxAll::max(), sdc_cmd);
}
}
void
WriteSdc::writePortDelay(PortDelay *port_delay,
bool is_input_delay,
float delay,
const TransRiseFallBoth *tr,
const MinMaxAll *min_max,
@ -838,16 +840,10 @@ WriteSdc::writePortDelay(PortDelay *port_delay,
Pin *ref_pin = port_delay->refPin();
if (ref_pin) {
fprintf(stream_, "-reference_pin ");
writeGetPin(ref_pin);
writeGetPin(ref_pin, true);
fprintf(stream_, " ");
}
Pin *pin = port_delay->pin();
if (sdc_network_->instance(pin) == instance_) {
Port *port = sdc_network_->port(pin);
writeGetPort(port);
}
else
writeGetPin(pin);
writeGetPin(port_delay->pin(), is_input_delay);
fprintf(stream_, "\n");
}
@ -919,7 +915,7 @@ WriteSdc::writeClockSense(PinClockPair &pin_clk,
writeGetClock(clk);
fprintf(stream_, " ");
}
writeGetPin(pin_clk.first);
writeGetPin(pin_clk.first, true);
fprintf(stream_, "\n");
}
@ -1184,7 +1180,7 @@ WriteSdc::writeDisabledPins() const
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
fprintf(stream_, "set_disable_timing ");
writeGetPin(pin);
writeGetPin(pin, false);
fprintf(stream_, "\n");
}
}
@ -1350,7 +1346,7 @@ WriteSdc::writeExceptionValue(ExceptionPath *exception) const
void
WriteSdc::writeExceptionFrom(ExceptionFrom *from) const
{
writeExceptionFromTo(from, "from");
writeExceptionFromTo(from, "from", true);
}
void
@ -1360,12 +1356,13 @@ WriteSdc::writeExceptionTo(ExceptionTo *to) const
if (end_tr != TransRiseFallBoth::riseFall())
fprintf(stream_, "%s ", transRiseFallFlag(end_tr));
if (to->hasObjects())
writeExceptionFromTo(to, "to");
writeExceptionFromTo(to, "to", false);
}
void
WriteSdc::writeExceptionFromTo(ExceptionFromTo *from_to,
const char *from_to_key) const
const char *from_to_key,
bool map_hpin_to_drvr) const
{
const TransRiseFallBoth *tr = from_to->transition();
const char *tr_prefix = "-";
@ -1389,7 +1386,7 @@ WriteSdc::writeExceptionFromTo(ExceptionFromTo *from_to,
Pin *pin = pin_iter.next();
if (multi_objs && !first)
fprintf(stream_, "\\\n ");
writeGetPin(pin);
writeGetPin(pin, map_hpin_to_drvr);
first = false;
}
}
@ -1421,25 +1418,25 @@ WriteSdc::writeExceptionThru(ExceptionThru *thru) const
else if (tr == TransRiseFallBoth::fall())
tr_prefix = "-fall_";
fprintf(stream_, "\\\n %sthrough ", tr_prefix);
PinSeq pins;
mapThruHpins(thru, pins);
bool multi_objs =
((thru->pins() ? thru->pins()->size() : 0)
(pins.size()
+ (thru->nets() ? thru->nets()->size() : 0)
+ (thru->instances() ? thru->instances()->size() : 0)) > 1;
+ (thru->instances() ? thru->instances()->size() : 0)) > 1;
if (multi_objs)
fprintf(stream_, "[list ");
bool first = true;
if (thru->pins()) {
PinSeq pins;
sortPinSet(thru->pins(), sdc_network_, pins);
PinSeq::Iterator pin_iter(pins);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
if (multi_objs && !first)
fprintf(stream_, "\\\n ");
writeGetPin(pin);
first = false;
}
sort(pins, PinPathNameLess(network_));
PinSeq::Iterator pin_iter(pins);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
if (multi_objs && !first)
fprintf(stream_, "\\\n ");
writeGetPin(pin);
first = false;
}
if (thru->nets()) {
NetSeq nets;
sortNetSet(thru->nets(), sdc_network_, nets);
@ -1468,6 +1465,33 @@ WriteSdc::writeExceptionThru(ExceptionThru *thru) const
fprintf(stream_, "]");
}
void
WriteSdc::mapThruHpins(ExceptionThru *thru,
PinSeq &pins) const
{
if (thru->pins()) {
for (Pin *pin : *thru->pins()) {
// Map hierarical pins to load pins outside of outputs or inside of inputs.
if (network_->isHierarchical(pin)) {
Instance *hinst = network_->instance(pin);
bool hpin_is_output = network_->direction(pin)->isAnyOutput();
PinConnectedPinIterator *cpin_iter = network_->connectedPinIterator(pin);
while (cpin_iter->hasNext()) {
Pin *cpin = cpin_iter->next();
if (network_->isLoad(cpin)
&& ((hpin_is_output
&& !network_->isInside(network_->instance(cpin), hinst))
|| (!hpin_is_output
&& network_->isInside(network_->instance(cpin), hinst))))
pins.push_back(cpin);
}
}
else
pins.push_back(pin);
}
}
}
////////////////////////////////////////////////////////////////
void
@ -1530,14 +1554,14 @@ WriteSdc::writeDataCheck(DataCheck *check,
else if (from_tr == TransRiseFallBoth::fall())
from_key = "-fall_from";
fprintf(stream_, "set_data_check %s ", from_key);
writeGetPin(check->from());
writeGetPin(check->from(), true);
const char *to_key = "-to";
if (to_tr == TransRiseFallBoth::rise())
to_key = "-rise_to";
else if (to_tr == TransRiseFallBoth::fall())
to_key = "-fall_to";
fprintf(stream_, " %s ", to_key);
writeGetPin(check->to());
writeGetPin(check->to(), false);
fprintf(stream_, "%s ",
setupHoldFlag(setup_hold));
writeTime(margin);
@ -1816,7 +1840,7 @@ WriteSdc::writeConstant(Pin *pin) const
{
const char *cmd = setConstantCmd(pin);
fprintf(stream_, "%s ", cmd);
writeGetPin(pin);
writeGetPin(pin, false);
fprintf(stream_, "\n");
}
@ -1858,7 +1882,7 @@ WriteSdc::writeCaseAnalysis(Pin *pin) const
{
const char *value_str = caseAnalysisValueStr(pin);
fprintf(stream_, "set_case_analysis %s ", value_str);
writeGetPin(pin);
writeGetPin(pin, false);
fprintf(stream_, "\n");
}
@ -2087,7 +2111,7 @@ WriteSdc::writeMinPulseWidths() const
const Pin *pin;
RiseFallValues *min_widths;
pin_iter.next(pin, min_widths);
WriteGetPin write_obj(pin, this);
WriteGetPin write_obj(pin, false, this);
writeMinPulseWidths(min_widths, write_obj);
}
InstMinPulseWidthMap::Iterator
@ -2155,7 +2179,7 @@ WriteSdc::writeLatchBorowLimits() const
fprintf(stream_, "set_max_time_borrow ");
writeTime(limit);
fprintf(stream_, " ");
writeGetPin(pin);
writeGetPin(pin, false);
fprintf(stream_, "\n");
}
InstLatchBorrowLimitMap::Iterator
@ -2226,7 +2250,7 @@ WriteSdc::writeSlewLimits() const
fprintf(stream_, "set_max_transition ");
writeTime(slew);
fprintf(stream_, " ");
writeGetPin(pin);
writeGetPin(pin, false);
fprintf(stream_, "\n");
}
}
@ -2345,7 +2369,7 @@ WriteSdc::writeCapLimits(const MinMax *min_max,
fprintf(stream_, "%s ", cmd);
writeCapacitance(cap);
fprintf(stream_, " ");
writeGetPin(pin);
writeGetPin(pin, false);
fprintf(stream_, "\n");
}
}
@ -2404,16 +2428,16 @@ void
WriteSdc::writeVariables() const
{
if (sdc_->propagateAllClocks()) {
if (compatible_)
fprintf(stream_, "set timing_all_clocks_propagated true\n");
else
if (native_)
fprintf(stream_, "set sta_propagate_all_clocks 1\n");
else
fprintf(stream_, "set timing_all_clocks_propagated true\n");
}
if (sdc_->presetClrArcsEnabled()) {
if (compatible_)
fprintf(stream_, "set timing_enable_preset_clear_arcs true\n");
else
if (native_)
fprintf(stream_, "set sta_preset_clear_arcs_enabled 1\n");
else
fprintf(stream_, "set timing_enable_preset_clear_arcs true\n");
}
}
@ -2439,10 +2463,10 @@ WriteSdc::writeGetTimingArcs(Edge *edge,
{
fprintf(stream_, "[%s -from ", getTimingArcsCmd());
Vertex *from_vertex = edge->from(graph_);
writeGetPin(from_vertex->pin());
writeGetPin(from_vertex->pin(), true);
fprintf(stream_, " -to ");
Vertex *to_vertex = edge->to(graph_);
writeGetPin(to_vertex->pin());
writeGetPin(to_vertex->pin(), false);
if (filter)
fprintf(stream_, " -filter {%s}", filter);
fprintf(stream_, "]");
@ -2451,7 +2475,7 @@ WriteSdc::writeGetTimingArcs(Edge *edge,
const char *
WriteSdc::getTimingArcsCmd() const
{
return compatible_ ? "get_timing_arcs" : "get_timing_edges";
return native_ ? "get_timing_edges" : "get_timing_arcs";
}
////////////////////////////////////////////////////////////////
@ -2518,15 +2542,17 @@ WriteSdc::writeGetPort(const Port *port) const
}
void
WriteSdc::writeGetPins(PinSet *pins) const
WriteSdc::writeGetPins(PinSet *pins,
bool map_hpin_to_drvr) const
{
PinSeq pins1;
sortPinSet(pins, sdc_network_, pins1);
writeGetPins(&pins1);
writeGetPins(&pins1, map_hpin_to_drvr);
}
void
WriteSdc::writeGetPins(PinSeq *pins) const
WriteSdc::writeGetPins(PinSeq *pins,
bool map_hpin_to_drvr) const
{
bool multiple = pins->size() > 1;
if (multiple)
@ -2537,7 +2563,7 @@ WriteSdc::writeGetPins(PinSeq *pins) const
Pin *pin = pin_iter.next();
if (multiple && !first)
fprintf(stream_, "\\\n ");
writeGetPin(pin);
writeGetPin(pin, map_hpin_to_drvr);
first = false;
}
if (multiple)
@ -2553,6 +2579,51 @@ WriteSdc::writeGetPin(const Pin *pin) const
fprintf(stream_, "[get_pins {%s}]", pathName(pin));
}
void
WriteSdc::writeGetPin(const Pin *pin,
bool map_hpin_to_drvr) const
{
if (map_hpins_ && map_hpin_to_drvr)
pin = leafDrvrPin(pin);
else if (map_hpins_ && !map_hpin_to_drvr)
pin = leafLoadPin(pin);
if (sdc_network_->instance(pin) == instance_)
fprintf(stream_, "[get_ports {%s}]", sdc_network_->portName(pin));
else
fprintf(stream_, "[get_pins {%s}]", pathName(pin));
}
const Pin *
WriteSdc::leafDrvrPin(const Pin *pin) const
{
PinSet leaf_pins;
findLeafDriverPins(const_cast<Pin*>(pin), network_, &leaf_pins);
PinSet::Iterator pin_iter(leaf_pins);
if (pin_iter.hasNext())
return pin_iter.next();
else {
report_->warn("No leaf driver pin found for hierarchical pin %s\n",
sdc_network_->pathName(pin));
return pin;
}
}
const Pin *
WriteSdc::leafLoadPin(const Pin *pin) const
{
PinSet leaf_pins;
findLeafLoadPins(const_cast<Pin*>(pin), network_, &leaf_pins);
PinSet::Iterator pin_iter(leaf_pins);
if (pin_iter.hasNext())
return pin_iter.next();
else {
report_->warn("No leaf load pin found for hierarchical pin %s\n",
sdc_network_->pathName(pin));
return pin;
}
}
void
WriteSdc::writeGetNet(const Net *net) const
{

View File

@ -28,7 +28,10 @@ void
writeSdc(Instance *instance,
const char *filename,
const char *creator,
bool compatible,
// Map hierarchical pins and instances to leaf pins and instances.
bool map_hpins,
// Replace non-sdc get functions with OpenSTA equivalents.
bool native,
bool no_timestamp,
int digits,
Sdc *sdc);

View File

@ -29,7 +29,8 @@ public:
WriteSdc(Instance *instance,
const char *filename,
const char *creator,
bool compatible,
bool map_hpins,
bool native,
int digits,
bool no_timestamp,
Sdc *sdc);
@ -82,8 +83,10 @@ public:
void writeInputDelays() const;
void writeOutputDelays() const;
void writePortDelay(PortDelay *port_delay,
bool is_input_delay,
const char *sdc_cmd) const;
void writePortDelay(PortDelay *port_delay,
bool is_input_delay,
float delay,
const TransRiseFallBoth *tr,
const MinMaxAll *min_max,
@ -100,8 +103,11 @@ public:
void writeExceptionFrom(ExceptionFrom *from) const;
void writeExceptionTo(ExceptionTo *to) const;
void writeExceptionFromTo(ExceptionFromTo *from_to,
const char *from_to_key) const;
const char *from_to_key,
bool map_hpin_to_drvr) const;
void writeExceptionThru(ExceptionThru *thru) const;
void mapThruHpins(ExceptionThru *thru,
PinSeq &pins) const;
void writeDataChecks() const;
void writeDataCheck(DataCheck *check) const;
void writeDataCheck(DataCheck *check,
@ -179,10 +185,14 @@ public:
bool &first) const;
virtual void writeGetPort(const Port *port) const;
virtual void writeGetPin(const Pin *pin) const;
void writeGetPin(const Pin *pin,
bool map_hpin_to_drvr) const;
virtual void writeGetNet(const Net *net) const;
virtual void writeGetInstance(const Instance *inst) const;
void writeGetPins(PinSet *pins) const;
void writeGetPins(PinSeq *pins) const;
void writeGetPins(PinSet *pins,
bool map_hpin_to_drvr) const;
void writeGetPins(PinSeq *pins,
bool map_hpin_to_drvr) const;
void writeClockKey(const Clock *clk) const;
float scaleTime(float time) const;
float scaleCapacitance(float cap) const;
@ -232,6 +242,8 @@ public:
void writeSetupHoldFlag(const MinMaxAll *min_max) const;
void writeVariables() const;
void writeCmdComment(SdcCmdComment *cmd) const;
const Pin *leafDrvrPin(const Pin *pin) const;
const Pin *leafLoadPin(const Pin *pin) const;
FILE *stream() const { return stream_; }
@ -239,7 +251,8 @@ protected:
Instance *instance_;
const char *filename_;
const char *creator_;
bool compatible_;
bool map_hpins_;
bool native_;
int digits_;
bool no_timestamp_;
bool top_instance_;

View File

@ -144,9 +144,7 @@ FindRegVisitor::visitRegs(ClockSet *clks,
Clock *clk = clk_iter.next();
FindRegClkPred clk_pred(clk, this);
VertexSet visited_vertices;
ClockVertexPinIterator pin_iter(clk);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
for (Pin *pin : clk->leafPins()) {
Vertex *vertex, *bidirect_drvr_vertex;
graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
visitFanoutRegs(vertex, TimingSense::positive_unate,

View File

@ -154,9 +154,7 @@ Level
Genclks::clkPinMaxLevel(Clock *clk) const
{
Level max_level = 0;
ClockVertexPinIterator pin_iter(clk);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
for (Pin *pin : clk->leafPins()) {
Vertex *vertex = srcPathVertex(pin);
max_level = max(max_level, vertex->level());
}
@ -305,8 +303,8 @@ Genclks::ensureMaster(Clock *gclk)
while (iter.hasNext()) {
Vertex *vertex = iter.next();
Pin *pin = vertex->pin();
if (sdc_->isVertexPinClock(pin)) {
ClockSet *master_clks = sdc_->findVertexPinClocks(pin);
if (sdc_->isLeafPinClock(pin)) {
ClockSet *master_clks = sdc_->findLeafPinClocks(pin);
if (master_clks) {
ClockSet::Iterator master_iter(master_clks);
while (master_iter.hasNext()) {
@ -357,8 +355,8 @@ Genclks::ensureMaster(Clock *gclk)
while (iter.hasNext()) {
Vertex *vertex = iter.next();
Pin *pin = vertex->pin();
if (sdc_->isVertexPinClock(pin)) {
ClockSet *master_clks = sdc_->findVertexPinClocks(pin);
if (sdc_->isLeafPinClock(pin)) {
ClockSet *master_clks = sdc_->findLeafPinClocks(pin);
if (master_clks) {
ClockSet::Iterator master_iter(master_clks);
if (master_iter.hasNext()) {
@ -474,9 +472,7 @@ Genclks::seedClkVertices(Clock *clk,
BfsBkwdIterator &iter,
VertexSet *fanins)
{
ClockVertexPinIterator pin_iter(clk);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
for (Pin *pin : clk->leafPins()) {
Vertex *vertex, *bidirect_drvr_vertex;
graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
fanins->insert(vertex);
@ -543,7 +539,7 @@ GenClkInsertionSearchPred::searchTo(const Vertex *to_vertex)
return SearchPred0::searchTo(to_vertex)
// Propagate through other generated clock roots but not regular
// clock roots.
&& !(!gclk_->vertexPins()->hasKey(to_pin)
&& !(!gclk_->leafPins().hasKey(to_pin)
&& isNonGeneratedClkPin(to_pin))
&& genclk_info_->fanins()->hasKey(const_cast<Vertex*>(to_vertex));
}
@ -552,7 +548,7 @@ bool
GenClkInsertionSearchPred::isNonGeneratedClkPin(const Pin *pin) const
{
const Sdc *sdc = sta_->sdc();
ClockSet *clks = sdc->findVertexPinClocks(pin);
ClockSet *clks = sdc->findLeafPinClocks(pin);
if (clks) {
ClockSet::Iterator clk_iter(clks);
while (clk_iter.hasNext()) {
@ -643,9 +639,7 @@ Genclks::findLatchFdbkEdges(const Clock *gclk,
{
Level gclk_level = genclk_info->gclkLevel();
EdgeSet *fdbk_edges = nullptr;
ClockVertexPinIterator pin_iter(gclk->masterClk());
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
for (Pin *pin : gclk->masterClk()->leafPins()) {
Vertex *vertex = graph_->pinDrvrVertex(pin);
VertexSet path_vertices;
VertexSet visited_vertices;
@ -717,9 +711,7 @@ Genclks::seedSrcPins(Clock *gclk,
BfsFwdIterator &insert_iter)
{
Clock *master_clk = gclk->masterClk();
ClockVertexPinIterator master_pin_iter(master_clk);
while (master_pin_iter.hasNext()) {
Pin *master_pin = master_pin_iter.next();
for (Pin *master_pin : master_clk->leafPins()) {
Vertex *vertex = graph_->pinDrvrVertex(master_pin);
debugPrint1(debug_, "genclk", 2, " seed src pin %s\n",
network_->pathName(master_pin));
@ -950,9 +942,7 @@ Genclks::recordSrcPaths(Clock *gclk)
bool invert = gclk->invert();
bool has_edges = gclk->edges() != nullptr;
ClockVertexPinIterator gclk_pin_iter(gclk);
while (gclk_pin_iter.hasNext()) {
Pin *gclk_pin = gclk_pin_iter.next();
for (Pin *gclk_pin : gclk->leafPins()) {
PathVertexRep *src_paths = new PathVertexRep[path_count];
genclk_src_paths_.insert(ClockPinPair(gclk, gclk_pin), src_paths);

View File

@ -422,7 +422,7 @@ Power::seedActivities(BfsFwdIterator &bfs)
for (auto vertex : levelize_->roots()) {
const Pin *pin = vertex->pin();
// Clock activities are baked in.
if (!sdc_->isVertexPinClock(pin)
if (!sdc_->isLeafPinClock(pin)
&& network_->direction(pin) != PortDirection::internal()) {
debugPrint1(debug_, "power_activity", 3, "seed %s\n",
vertex->name(network_));

View File

@ -911,7 +911,7 @@ getProperty(Clock *clk,
else if (stringEqual(property, "period"))
return PropertyValue(sta->units()->timeUnit()->asString(clk->period(), 6));
else if (stringEqual(property, "sources"))
return PropertyValue(clk->pins());
return PropertyValue(&clk->pins());
else if (stringEqual(property, "propagated"))
return PropertyValue(clk->isPropagated() ? "1" : "0");
else

View File

@ -1720,8 +1720,7 @@ ReportPath::pathFromClkPin(const Path *path,
{
Clock *clk = path->clock(search_);
return clk
&& clk->vertexPins()
&& clk->vertexPins()->hasKey(const_cast<Pin*>(start_pin));
&& clk->leafPins().hasKey(const_cast<Pin*>(start_pin));
}
void

View File

@ -104,7 +104,7 @@ EvalPred::searchTo(const Vertex *to_vertex)
const Sdc *sdc = sta_->sdc();
const Pin *pin = to_vertex->pin();
return SearchPred0::searchTo(to_vertex)
&& !(sdc->isVertexPinClock(pin)
&& !(sdc->isLeafPinClock(pin)
&& !sdc->isPathDelayInternalEndpoint(pin));
}
@ -868,9 +868,8 @@ Search::visitStartpoints(VertexVisitor *visitor)
}
delete pin_iter;
InputDelayVertexPinsIterator arrival_iter(sdc_);
while (arrival_iter.hasNext()) {
const Pin *pin = arrival_iter.next();
for (auto iter : sdc_->inputDelayMap()) {
const Pin *pin = iter.first;
// Already hit these.
if (!network_->isTopLevelPort(pin)) {
Vertex *vertex = graph_->pinDrvrVertex(pin);
@ -879,10 +878,8 @@ Search::visitStartpoints(VertexVisitor *visitor)
}
}
for (auto clk : sdc_->clks()) {
ClockVertexPinIterator pin_iter(clk);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
for (Clock *clk : sdc_->clks()) {
for (Pin *pin : clk->leafPins()) {
// Already hit these.
if (!network_->isTopLevelPort(pin)) {
Vertex *vertex = graph_->pinDrvrVertex(pin);
@ -1080,7 +1077,7 @@ ArrivalVisitor::visit(Vertex *vertex)
vertex->name(sdc_network));
Pin *pin = vertex->pin();
// Don't clobber clock sources.
if (!sdc->isVertexPinClock(pin)
if (!sdc->isLeafPinClock(pin)
// Unless it is an internal path delay endpoint.
|| sdc->isPathDelayInternalEndpoint(pin)) {
tag_bldr_->init(vertex);
@ -1105,7 +1102,7 @@ ArrivalVisitor::visit(Vertex *vertex)
// set_min/max_delay on internal pin.
search->makeUnclkedPaths(vertex, true, tag_bldr_);
if (sdc->isPathDelayInternalEndpoint(pin)
&& sdc->isVertexPinClock(pin))
&& sdc->isLeafPinClock(pin))
// set_min/max_delay on internal pin also a clock src. Bizzaroland.
// Re-seed the clock arrivals on top of the propagated paths.
search->seedClkArrivals(pin, vertex, tag_bldr_);
@ -1392,9 +1389,7 @@ void
Search::findClockVertices(VertexSet &vertices)
{
for (auto clk : sdc_->clks()) {
ClockVertexPinIterator pin_iter(clk);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
for (Pin *pin : clk->leafPins()) {
Vertex *vertex, *bidirect_drvr_vertex;
graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
vertices.insert(vertex);
@ -1416,7 +1411,7 @@ void
Search::seedArrival(Vertex *vertex)
{
const Pin *pin = vertex->pin();
if (sdc_->isVertexPinClock(pin)) {
if (sdc_->isLeafPinClock(pin)) {
TagGroupBldr tag_bldr(true, this);
tag_bldr.init(vertex);
genclks_->copyGenClkSrcPaths(vertex, &tag_bldr);
@ -1462,14 +1457,12 @@ Search::seedArrival(Vertex *vertex)
}
}
// Find all of the clock vertex pins.
// Find all of the clock leaf pins.
void
Search::findClkVertexPins(PinSet &clk_pins)
{
for (auto clk : sdc_->clks()) {
ClockVertexPinIterator pin_iter(clk);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
for (Pin *pin : clk->leafPins()) {
clk_pins.insert(pin);
}
}
@ -1480,7 +1473,7 @@ Search::seedClkArrivals(const Pin *pin,
Vertex *vertex,
TagGroupBldr *tag_bldr)
{
for (auto clk : *sdc_->findVertexPinClocks(pin)) {
for (auto clk : *sdc_->findLeafPinClocks(pin)) {
debugPrint2(debug_, "search", 2, "arrival seed clk %s pin %s\n",
clk->name(), network_->pathName(pin));
for (auto path_ap : corners_->pathAnalysisPts()) {
@ -1622,7 +1615,7 @@ Search::findRootVertices(VertexSet &vertices)
{
for (auto vertex : levelize_->roots()) {
const Pin *pin = vertex->pin();
if (!sdc_->isVertexPinClock(pin)
if (!sdc_->isLeafPinClock(pin)
&& !sdc_->hasInputDelay(pin)
&& !vertex->isConstant()) {
vertices.insert(vertex);
@ -1648,7 +1641,7 @@ Search::isSegmentStart(const Pin *pin)
{
return (sdc_->isPathDelayInternalStartpoint(pin)
|| sdc_->isInputDelayInternal(pin))
&& !sdc_->isVertexPinClock(pin);
&& !sdc_->isLeafPinClock(pin);
}
bool
@ -1668,10 +1661,9 @@ 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.
InputDelayVertexPinsIterator arrival_iter(sdc_);
while (arrival_iter.hasNext()) {
const Pin *pin = arrival_iter.next();
if (!sdc_->isVertexPinClock(pin)) {
for (auto iter : sdc_->inputDelayMap()) {
const Pin *pin = iter.first;
if (!sdc_->isLeafPinClock(pin)) {
Vertex *vertex = graph_->pinDrvrVertex(pin);
seedInputArrival(pin, vertex, clks);
}
@ -1685,13 +1677,13 @@ Search::seedInputArrival(const Pin *pin,
{
bool has_arrival = false;
// There can be multiple arrivals for a pin with wrt different clocks.
VertexPinInputDelayIterator arrival_iter(pin, sdc_);
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_->findVertexPinClocks(pin);
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
@ -1713,7 +1705,7 @@ Search::seedInputArrival(const Pin *pin,
{
if (sdc_->hasInputDelay(pin))
seedInputArrival1(pin, vertex, false, tag_bldr);
else if (!sdc_->isVertexPinClock(pin))
else if (!sdc_->isLeafPinClock(pin))
// Seed inputs without set_input_delays.
seedInputDelayArrival(pin, vertex, nullptr, false, tag_bldr);
}
@ -1733,11 +1725,11 @@ Search::seedInputArrival1(const Pin *pin,
TagGroupBldr *tag_bldr)
{
// There can be multiple arrivals for a pin with wrt different clocks.
VertexPinInputDelayIterator arrival_iter(pin, sdc_);
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_->findVertexPinClocks(pin);
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.
@ -2088,7 +2080,7 @@ Search::pathPropagatedToClkSrc(const Pin *pin,
// Clock source can have input arrivals from unrelated clock.
&& tag->inputDelay() == nullptr
&& sdc_->isPathDelayInternalEndpoint(pin)) {
ClockSet *clks = sdc_->findVertexPinClocks(pin);
ClockSet *clks = sdc_->findLeafPinClocks(pin);
return clks
&& !clks->hasKey(tag->clock());
}

View File

@ -1154,11 +1154,8 @@ Sta::removeClockSlew(Clock *clk)
void
Sta::clockSlewChanged(Clock *clk)
{
ClockPinIterator pin_iter(clk);
while (pin_iter.hasNext()) {
const Pin *pin = pin_iter.next();
for (Pin *pin : clk->pins())
graph_delay_calc_->delayInvalid(pin);
}
search_->arrivalsInvalid();
}
@ -2068,12 +2065,13 @@ Sta::constraintsChanged()
void
Sta::writeSdc(const char *filename,
bool compatible,
bool leaf,
bool native,
bool no_timestamp,
int digits)
{
sta::writeSdc(network_->topInstance(), filename, "write_sdc",
compatible, no_timestamp, digits, sdc_);
leaf, native, no_timestamp, digits, sdc_);
}
////////////////////////////////////////////////////////////////

View File

@ -911,6 +911,9 @@ public:
const MinMax *min_max,
int digits);
void writeSdc(const char *filename,
// Map hierarchical pins and instances to leaf pins and instances.
bool leaf,
// Replace non-sdc get functions with OpenSTA equivalents.
bool native,
bool no_timestamp,
int digits);

View File

@ -113,4 +113,16 @@ StaState::networkReader() const
return dynamic_cast<NetworkReader*>(network_);
}
void
StaState::setReport(Report *report)
{
report_ = report;
}
void
StaState::setDebug(Debug *debug)
{
debug_ = debug;
}
} // namespace

View File

@ -54,8 +54,10 @@ public:
virtual ~StaState() {}
Report *report() { return report_; }
Report *report() const { return report_; }
void setReport(Report *report);
Debug *debug() { return debug_; }
Debug *debug() const { return debug_; }
void setDebug(Debug *debug);
Units *units() { return units_; }
Units *units() const { return units_; }
Network *network() { return network_; }

View File

@ -299,7 +299,7 @@ VisitPathEnds::visitOutputDelayEnd(const Pin *pin,
bool &is_constrained)
{
const MinMax *min_max = path_ap->pathMinMax();
VertexPinOutputDelayIterator delay_iter(pin, sdc_);
LeafPinOutputDelayIterator delay_iter(pin, sdc_);
while (delay_iter.hasNext()) {
OutputDelay *output_delay = delay_iter.next();
float margin;

View File

@ -123,11 +123,11 @@ proc source_ { filename echo verbose } {
################################################################
define_cmd_args "write_sdc" \
{[-no_timestamp] [-digits digits] filename}
{[-map_hpins] [-no_timestamp] [-digits digits] filename}
proc write_sdc { args } {
parse_key_args "write_sdc" args keys {-digits -significant_digits} \
flags {-compatible -no_timestamp}
flags {-map_hpins -compatible -no_timestamp}
check_argc_eq1 "write_sdc" $args
set digits 4
@ -141,8 +141,9 @@ proc write_sdc { args } {
set filename [file nativename [lindex $args 0]]
set no_timestamp [info exists flags(-no_timestamp)]
set compatible [info exists flags(-native)]
write_sdc_cmd $filename $compatible $no_timestamp $digits
set map_hpins [info exists flags(-map_hpins)]
set native [expr ![info exists flags(-compatible)]]
write_sdc_cmd $filename $map_hpins $native $no_timestamp $digits
}
################################################################

View File

@ -820,11 +820,6 @@ using namespace sta;
Tcl_SetObjResult(interp, obj);
}
%typemap(out) ClockPinIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1,$1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) ClockEdge* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1,$1_descriptor, false);
Tcl_SetObjResult(interp, obj);
@ -1100,6 +1095,20 @@ using namespace sta;
Tcl_SetObjResult(interp, list);
}
%typemap(out) PinSet& {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
const PinSet *pins = $1;
if (pins) {
PinSet::ConstIterator pin_iter(pins);
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
Tcl_Obj *obj = SWIG_NewInstanceObj(pin, SWIGTYPE_p_Pin, false);
Tcl_ListObjAppendElement(interp, list, obj);
}
}
Tcl_SetObjResult(interp, list);
}
%typemap(in) ClockSet* {
$1 = tclListSet<Clock*>($input, SWIGTYPE_p_Clock, interp);
}
@ -1753,13 +1762,6 @@ private:
~ClockIterator();
};
class ClockPinIterator
{
private:
ClockPinIterator();
~ClockPinIterator();
};
class ClockEdge
{
private:
@ -4712,12 +4714,13 @@ disabled_edges_sorted()
void
write_sdc_cmd(const char *filename,
bool leaf,
bool compatible,
bool no_timestamp,
int digits)
{
cmdLinkedNetwork();
Sta::sta()->writeSdc(filename, compatible, no_timestamp, digits);
Sta::sta()->writeSdc(filename, leaf, compatible, no_timestamp, digits);
}
void
@ -5661,12 +5664,11 @@ void finish() { delete self; }
float period() { return self->period(); }
FloatSeq *waveform() { return self->waveform(); }
float time(TransRiseFall *tr) { return self->edge(tr)->time(); }
ClockPinIterator *pin_iterator() { return new ClockPinIterator(self); }
bool is_generated() { return self->isGenerated(); }
bool waveform_valid() { return self->waveformValid(); }
bool is_virtual() { return self->isVirtual(); }
bool is_propagated() { return self->isPropagated(); }
PinSet *sources() { return self->pins(); }
PinSet &sources() { return self->pins(); }
float
slew(const TransRiseFall *tr,
@ -5689,12 +5691,6 @@ Clock *next() { return self->next(); }
void finish() { delete self; }
}
%extend ClockPinIterator {
bool has_next() { return self->hasNext(); }
Pin *next() { return self->next(); }
void finish() { delete self; }
}
%extend Vertex {
Pin *pin() { return self->pin(); }
bool is_bidirect_driver() { return self->isBidirectDriver(); }

View File

@ -71,6 +71,9 @@ public:
this->clear();
}
static bool
intersects(std::set<KEY, CMP> &set1,
std::set<KEY, CMP> &set2);
static bool
intersects(std::set<KEY, CMP> *set1,
std::set<KEY, CMP> *set2);
@ -170,6 +173,14 @@ Set<KEY, CMP>::isSubset(const std::set<KEY, CMP> *set2)
}
}
template <class KEY, class CMP>
bool
Set<KEY, CMP>::intersects(std::set<KEY, CMP> &set1,
std::set<KEY, CMP> &set2)
{
return intersects(&set1, &set2);
}
template <class KEY, class CMP>
bool
Set<KEY, CMP>::intersects(std::set<KEY, CMP> *set1,