vertex_pin -> leaf_pin
This commit is contained in:
parent
13037e6093
commit
6ac93c8c7d
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ makeClonePins(Instance *proto,
|
|||
ConcreteBindingTbl *parent_bindings,
|
||||
NetworkReader *network);
|
||||
|
||||
Network *
|
||||
NetworkReader *
|
||||
makeConcreteNetwork()
|
||||
{
|
||||
return new ConcreteNetwork;
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
class Network;
|
||||
class NetworkReader;
|
||||
|
||||
Network *
|
||||
NetworkReader *
|
||||
makeConcreteNetwork();
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
52
sdc/Clock.cc
52
sdc/Clock.cc
|
|
@ -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
|
||||
|
|
|
|||
35
sdc/Clock.hh
35
sdc/Clock.hh
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
310
sdc/Sdc.cc
310
sdc/Sdc.cc
|
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
112
sdc/Sdc.hh
112
sdc/Sdc.hh
|
|
@ -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
|
||||
|
|
|
|||
251
sdc/WriteSdc.cc
251
sdc/WriteSdc.cc
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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_));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
################################################################
|
||||
|
|
|
|||
38
tcl/StaTcl.i
38
tcl/StaTcl.i
|
|
@ -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(); }
|
||||
|
|
|
|||
11
util/Set.hh
11
util/Set.hh
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue