graph dcalc use ClkNetwork
This commit is contained in:
parent
0db8d142d8
commit
b36d2753d1
|
|
@ -116,12 +116,6 @@ GraphDelayCalc::ceff(Edge *,
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
GraphDelayCalc::isIdealClk(const Vertex *vertex)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
GraphDelayCalc::minPulseWidth(const Pin *pin,
|
GraphDelayCalc::minPulseWidth(const Pin *pin,
|
||||||
const RiseFall *hi_low,
|
const RiseFall *hi_low,
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,6 @@ GraphDelayCalc1::~GraphDelayCalc1()
|
||||||
delete clk_pred_;
|
delete clk_pred_;
|
||||||
delete iter_;
|
delete iter_;
|
||||||
deleteMultiDrvrNets();
|
deleteMultiDrvrNets();
|
||||||
clearIdealClkMap();
|
|
||||||
delete observer_;
|
delete observer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -293,7 +292,6 @@ GraphDelayCalc1::delaysInvalid()
|
||||||
delays_seeded_ = false;
|
delays_seeded_ = false;
|
||||||
incremental_ = false;
|
incremental_ = false;
|
||||||
iter_->clear();
|
iter_->clear();
|
||||||
clearIdealClkMap();
|
|
||||||
// No need to keep track of incremental updates any more.
|
// No need to keep track of incremental updates any more.
|
||||||
invalid_delays_.clear();
|
invalid_delays_.clear();
|
||||||
invalid_checks_.clear();
|
invalid_checks_.clear();
|
||||||
|
|
@ -360,7 +358,6 @@ public:
|
||||||
virtual ~FindVertexDelays();
|
virtual ~FindVertexDelays();
|
||||||
virtual void visit(Vertex *vertex);
|
virtual void visit(Vertex *vertex);
|
||||||
virtual VertexVisitor *copy();
|
virtual VertexVisitor *copy();
|
||||||
virtual void levelFinished();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GraphDelayCalc1 *graph_delay_calc1_;
|
GraphDelayCalc1 *graph_delay_calc1_;
|
||||||
|
|
@ -398,24 +395,6 @@ FindVertexDelays::visit(Vertex *vertex)
|
||||||
graph_delay_calc1_->findVertexDelay(vertex, arc_delay_calc_, true);
|
graph_delay_calc1_->findVertexDelay(vertex, arc_delay_calc_, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
FindVertexDelays::levelFinished()
|
|
||||||
{
|
|
||||||
graph_delay_calc1_->mergeIdealClks();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GraphDelayCalc1::mergeIdealClks()
|
|
||||||
{
|
|
||||||
for (auto vertex_clks : ideal_clks_map_next_) {
|
|
||||||
const Vertex *vertex = vertex_clks.first;
|
|
||||||
ClockSet *prev_clks = ideal_clks_map_.findKey(vertex);
|
|
||||||
delete prev_clks;
|
|
||||||
ideal_clks_map_[vertex] = vertex_clks.second;
|
|
||||||
}
|
|
||||||
ideal_clks_map_next_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// The logical structure of incremental delay calculation closely
|
// The logical structure of incremental delay calculation closely
|
||||||
// resembles the incremental search arrival time algorithm
|
// resembles the incremental search arrival time algorithm
|
||||||
// (Search::findArrivals).
|
// (Search::findArrivals).
|
||||||
|
|
@ -437,7 +416,6 @@ GraphDelayCalc1::findDelays(Level level)
|
||||||
if (incremental_)
|
if (incremental_)
|
||||||
seedInvalidDelays();
|
seedInvalidDelays();
|
||||||
|
|
||||||
mergeIdealClks();
|
|
||||||
FindVertexDelays visitor(this, arc_delay_calc_, false);
|
FindVertexDelays visitor(this, arc_delay_calc_, false);
|
||||||
dcalc_count += iter_->visitParallel(level, &visitor);
|
dcalc_count += iter_->visitParallel(level, &visitor);
|
||||||
|
|
||||||
|
|
@ -578,7 +556,6 @@ GraphDelayCalc1::seedRootSlews()
|
||||||
while (root_iter.hasNext()) {
|
while (root_iter.hasNext()) {
|
||||||
Vertex *vertex = root_iter.next();
|
Vertex *vertex = root_iter.next();
|
||||||
seedRootSlew(vertex, arc_delay_calc_);
|
seedRootSlew(vertex, arc_delay_calc_);
|
||||||
findIdealClks(vertex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -857,7 +834,6 @@ GraphDelayCalc1::findVertexDelay(Vertex *vertex,
|
||||||
bool propagate)
|
bool propagate)
|
||||||
{
|
{
|
||||||
const Pin *pin = vertex->pin();
|
const Pin *pin = vertex->pin();
|
||||||
bool ideal_clks_changed = findIdealClks(vertex);
|
|
||||||
// Don't clobber root slews.
|
// Don't clobber root slews.
|
||||||
if (!vertex->isRoot()) {
|
if (!vertex->isRoot()) {
|
||||||
debugPrint2(debug_, "delay_calc", 2, "find delays %s (%s)\n",
|
debugPrint2(debug_, "delay_calc", 2, "find delays %s (%s)\n",
|
||||||
|
|
@ -871,7 +847,7 @@ GraphDelayCalc1::findVertexDelay(Vertex *vertex,
|
||||||
enqueueTimingChecksEdges(vertex);
|
enqueueTimingChecksEdges(vertex);
|
||||||
// Enqueue adjacent vertices even if the delays did not
|
// Enqueue adjacent vertices even if the delays did not
|
||||||
// change when non-incremental to stride past annotations.
|
// change when non-incremental to stride past annotations.
|
||||||
if (delay_changed || ideal_clks_changed || !incremental_)
|
if (delay_changed || !incremental_)
|
||||||
iter_->enqueueAdjacentVertices(vertex);
|
iter_->enqueueAdjacentVertices(vertex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1595,132 +1571,6 @@ GraphDelayCalc1::checkEdgeClkSlew(const Vertex *from_vertex,
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool
|
|
||||||
GraphDelayCalc1::findIdealClks(Vertex *vertex)
|
|
||||||
{
|
|
||||||
const Pin *pin = vertex->pin();
|
|
||||||
ClockSet *ideal_clks = nullptr;
|
|
||||||
if (sdc_->isLeafPinClock(pin)) {
|
|
||||||
// Seed ideal clocks pins.
|
|
||||||
if (!sdc_->isPropagatedClock(pin)) {
|
|
||||||
ClockSet *clks = sdc_->findLeafPinClocks(pin);
|
|
||||||
ClockSet::ConstIterator clk_iter(clks);
|
|
||||||
while (clk_iter.hasNext()) {
|
|
||||||
Clock *clk = clk_iter.next();
|
|
||||||
if (!clk->isPropagated()) {
|
|
||||||
if (ideal_clks == nullptr) {
|
|
||||||
ideal_clks = new ClockSet;
|
|
||||||
debugPrint1(debug_, "ideal_clks", 1, " %s\n",
|
|
||||||
vertex->name(sdc_network_));
|
|
||||||
}
|
|
||||||
ideal_clks->insert(clk);
|
|
||||||
debugPrint1(debug_, "ideal_clks", 1, " %s\n", clk->name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!sdc_->isPropagatedClock(pin)) {
|
|
||||||
VertexInEdgeIterator edge_iter(vertex, graph_);
|
|
||||||
while (edge_iter.hasNext()) {
|
|
||||||
Edge *edge = edge_iter.next();
|
|
||||||
if (clk_pred_->searchThru(edge)) {
|
|
||||||
Vertex *from_vertex = edge->from(graph_);
|
|
||||||
ClockSet *from_clks = idealClks(from_vertex);
|
|
||||||
if (from_clks) {
|
|
||||||
ClockSet::ConstIterator from_clk_iter(from_clks);
|
|
||||||
while (from_clk_iter.hasNext()) {
|
|
||||||
Clock *from_clk = from_clk_iter.next();
|
|
||||||
if (ideal_clks == nullptr) {
|
|
||||||
ideal_clks = new ClockSet;
|
|
||||||
debugPrint1(debug_, "ideal_clks", 1, " %s\n",
|
|
||||||
vertex->name(sdc_network_));
|
|
||||||
}
|
|
||||||
ideal_clks->insert(from_clk);
|
|
||||||
debugPrint1(debug_, "ideal_clks", 1, " %s\n", from_clk->name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return setIdealClks(vertex, ideal_clks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GraphDelayCalc1::clearIdealClkMap()
|
|
||||||
{
|
|
||||||
ideal_clks_map_.deleteContentsClear();
|
|
||||||
ideal_clks_map_next_.deleteContentsClear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
GraphDelayCalc1::setIdealClks(const Vertex *vertex,
|
|
||||||
ClockSet *clks)
|
|
||||||
{
|
|
||||||
bool changed = false;
|
|
||||||
ClockSet *clks1 = ideal_clks_map_.findKey(vertex);
|
|
||||||
if (!ClockSet::equal(clks, clks1)) {
|
|
||||||
// Only lock for updates to vertex ideal clks.
|
|
||||||
// Finding ideal clks by level means only changes at the current
|
|
||||||
// delay calc level are changed.
|
|
||||||
UniqueLock lock(ideal_clks_map_next_lock_);
|
|
||||||
ideal_clks_map_next_[vertex] = clks;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
delete clks;
|
|
||||||
return changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClockSet *
|
|
||||||
GraphDelayCalc1::idealClks(const Vertex *vertex)
|
|
||||||
{
|
|
||||||
ClockSet *ideal_clks = ideal_clks_map_.findKey(vertex);
|
|
||||||
const ClockSet *ideal_clks2 = clk_network_->idealClocks(vertex->pin());
|
|
||||||
if (ideal_clks) {
|
|
||||||
for (Clock *clk : *ideal_clks) {
|
|
||||||
if (ideal_clks2) {
|
|
||||||
if (!ideal_clks2->findKey(clk))
|
|
||||||
printf("pin %s clk_net missing1 %s\n",
|
|
||||||
vertex->name(network_),
|
|
||||||
clk->name());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
printf("pin %s clk_net missing2 %s\n",
|
|
||||||
vertex->name(network_),
|
|
||||||
clk->name());
|
|
||||||
}
|
|
||||||
if (ideal_clks2) {
|
|
||||||
for (Clock *clk : *ideal_clks2) {
|
|
||||||
if (ideal_clks) {
|
|
||||||
if (!ideal_clks->findKey(clk)) {
|
|
||||||
printf("pin %s dcalc missing3 %s\n",
|
|
||||||
vertex->name(network_),
|
|
||||||
clk->name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
printf("pin %s dcalc missing4 %s\n",
|
|
||||||
vertex->name(network_),
|
|
||||||
clk->name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ideal_clks;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
GraphDelayCalc1::isIdealClk(const Vertex *vertex)
|
|
||||||
{
|
|
||||||
const ClockSet *clks = idealClks(vertex);
|
|
||||||
bool ideal = clks != 0
|
|
||||||
&& clks->size() > 0;
|
|
||||||
if (ideal != clk_network_->isIdealClock(vertex->pin()))
|
|
||||||
printf("ideal missmatch\n");
|
|
||||||
return ideal;
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
float
|
||||||
GraphDelayCalc1::ceff(Edge *edge,
|
GraphDelayCalc1::ceff(Edge *edge,
|
||||||
TimingArc *arc,
|
TimingArc *arc,
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,6 @@ protected:
|
||||||
ArcDelayCalc *arc_delay_calc,
|
ArcDelayCalc *arc_delay_calc,
|
||||||
bool propagate);
|
bool propagate);
|
||||||
void enqueueTimingChecksEdges(Vertex *vertex);
|
void enqueueTimingChecksEdges(Vertex *vertex);
|
||||||
bool findIdealClks(Vertex *vertex);
|
|
||||||
bool findArcDelay(LibertyCell *drvr_cell,
|
bool findArcDelay(LibertyCell *drvr_cell,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
Vertex *drvr_vertex,
|
Vertex *drvr_vertex,
|
||||||
|
|
@ -195,11 +194,6 @@ protected:
|
||||||
const RiseFall *from_rf,
|
const RiseFall *from_rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const DcalcAnalysisPt *dcalc_ap);
|
||||||
bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const;
|
bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const;
|
||||||
void clearIdealClkMap();
|
|
||||||
bool setIdealClks(const Vertex *vertex,
|
|
||||||
ClockSet *clks);
|
|
||||||
ClockSet *idealClks(const Vertex *vertex);
|
|
||||||
virtual bool isIdealClk(const Vertex *vertex);
|
|
||||||
Slew idealClkSlew(const Vertex *vertex,
|
Slew idealClkSlew(const Vertex *vertex,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
|
|
@ -214,7 +208,6 @@ protected:
|
||||||
Parasitic *drvr_parasitic,
|
Parasitic *drvr_parasitic,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) const;
|
const DcalcAnalysisPt *dcalc_ap) const;
|
||||||
void mergeIdealClks();
|
|
||||||
|
|
||||||
// Observer for edge delay changes.
|
// Observer for edge delay changes.
|
||||||
DelayCalcObserver *observer_;
|
DelayCalcObserver *observer_;
|
||||||
|
|
@ -235,9 +228,6 @@ protected:
|
||||||
// Percentage (0.0:1.0) change in delay that causes downstream
|
// Percentage (0.0:1.0) change in delay that causes downstream
|
||||||
// delays to be recomputed during incremental delay calculation.
|
// delays to be recomputed during incremental delay calculation.
|
||||||
float incremental_delay_tolerance_;
|
float incremental_delay_tolerance_;
|
||||||
VertexIdealClksMap ideal_clks_map_;
|
|
||||||
VertexIdealClksMap ideal_clks_map_next_;
|
|
||||||
std::mutex ideal_clks_map_next_lock_;
|
|
||||||
|
|
||||||
friend class FindVertexDelays;
|
friend class FindVertexDelays;
|
||||||
friend class MultiDrvrNet;
|
friend class MultiDrvrNet;
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,6 @@ public:
|
||||||
virtual float ceff(Edge *edge,
|
virtual float ceff(Edge *edge,
|
||||||
TimingArc *arc,
|
TimingArc *arc,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const DcalcAnalysisPt *dcalc_ap);
|
||||||
virtual bool isIdealClk(const Vertex *vertex);
|
|
||||||
// Precedence:
|
// Precedence:
|
||||||
// SDF annotation
|
// SDF annotation
|
||||||
// Liberty library
|
// Liberty library
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,8 @@ public:
|
||||||
Search *search() const { return search_; }
|
Search *search() const { return search_; }
|
||||||
Latches *latches() { return latches_; }
|
Latches *latches() { return latches_; }
|
||||||
Latches *latches() const { return latches_; }
|
Latches *latches() const { return latches_; }
|
||||||
|
ClkNetwork *clkNetwork() { return clk_network_; }
|
||||||
|
ClkNetwork *clkNetwork() const { return clk_network_; }
|
||||||
unsigned threadCount() const { return thread_count_; }
|
unsigned threadCount() const { return thread_count_; }
|
||||||
bool pocvEnabled() const { return pocv_enabled_; }
|
bool pocvEnabled() const { return pocv_enabled_; }
|
||||||
float sigmaFactor() const { return sigma_factor_; }
|
float sigmaFactor() const { return sigma_factor_; }
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include "PathVertex.hh"
|
#include "PathVertex.hh"
|
||||||
#include "PortDirection.hh"
|
#include "PortDirection.hh"
|
||||||
#include "Search.hh"
|
#include "Search.hh"
|
||||||
|
#include "ClkNetwork.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
|
|
@ -147,13 +148,14 @@ CheckSlewLimits::checkSlews1(Vertex *vertex,
|
||||||
float &limit,
|
float &limit,
|
||||||
float &slack) const
|
float &slack) const
|
||||||
{
|
{
|
||||||
|
const Pin *pin = vertex->pin();
|
||||||
if (!vertex->isDisabledConstraint()
|
if (!vertex->isDisabledConstraint()
|
||||||
&& !vertex->isConstant()
|
&& !vertex->isConstant()
|
||||||
&& !sta_->graphDelayCalc()->isIdealClk(vertex)) {
|
&& !sta_->clkNetwork()->isIdealClock(pin)) {
|
||||||
for (auto rf1 : RiseFall::range()) {
|
for (auto rf1 : RiseFall::range()) {
|
||||||
float limit1;
|
float limit1;
|
||||||
bool limit1_exists;
|
bool limit1_exists;
|
||||||
findLimit(vertex->pin(), vertex, rf1, min_max, check_clks,
|
findLimit(pin, vertex, rf1, min_max, check_clks,
|
||||||
limit1, limit1_exists);
|
limit1, limit1_exists);
|
||||||
if (limit1_exists) {
|
if (limit1_exists) {
|
||||||
checkSlew(vertex, corner1, rf1, min_max, limit1,
|
checkSlew(vertex, corner1, rf1, min_max, limit1,
|
||||||
|
|
@ -186,7 +188,7 @@ CheckSlewLimits::findLimit(const Pin *pin,
|
||||||
bool exists1;
|
bool exists1;
|
||||||
if (check_clks) {
|
if (check_clks) {
|
||||||
// Look for clock slew limits.
|
// Look for clock slew limits.
|
||||||
bool is_clk = sta_->search()->isClock(vertex);
|
bool is_clk = sta_->clkNetwork()->isIdealClock(pin);
|
||||||
ClockSet clks;
|
ClockSet clks;
|
||||||
clockDomains(vertex, clks);
|
clockDomains(vertex, clks);
|
||||||
ClockSet::Iterator clk_iter(clks);
|
ClockSet::Iterator clk_iter(clks);
|
||||||
|
|
|
||||||
|
|
@ -143,23 +143,13 @@ ClkNetwork::findClkPins(bool ideal_only,
|
||||||
bool
|
bool
|
||||||
ClkNetwork::isClock(const Pin *pin) const
|
ClkNetwork::isClock(const Pin *pin) const
|
||||||
{
|
{
|
||||||
ClockSet clks;
|
return pin_clks_map_.hasKey(pin);
|
||||||
bool exists;
|
|
||||||
pin_clks_map_.findKey(pin, clks, exists);
|
|
||||||
if (exists && clks.empty())
|
|
||||||
printf("luse empty clks\n");
|
|
||||||
return exists;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ClkNetwork::isIdealClock(const Pin *pin) const
|
ClkNetwork::isIdealClock(const Pin *pin) const
|
||||||
{
|
{
|
||||||
ClockSet clks;
|
return pin_ideal_clks_map_.hasKey(pin);
|
||||||
bool exists;
|
|
||||||
pin_ideal_clks_map_.findKey(pin, clks, exists);
|
|
||||||
if (exists && clks.empty())
|
|
||||||
printf("luse empty clks\n");
|
|
||||||
return exists;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ClockSet *
|
const ClockSet *
|
||||||
|
|
|
||||||
|
|
@ -4865,6 +4865,7 @@ Sta::checkSlewLimitPreamble()
|
||||||
findDelays();
|
findDelays();
|
||||||
if (check_slew_limits_ == nullptr)
|
if (check_slew_limits_ == nullptr)
|
||||||
makeCheckSlewLimits();
|
makeCheckSlewLimits();
|
||||||
|
ensureClkNetwork();
|
||||||
}
|
}
|
||||||
|
|
||||||
Pin *
|
Pin *
|
||||||
|
|
|
||||||
18
tcl/StaTcl.i
18
tcl/StaTcl.i
|
|
@ -3768,7 +3768,21 @@ update_generated_clks()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pin_is_clock(const Pin *pin)
|
is_clock(Pin *pin)
|
||||||
|
{
|
||||||
|
Sta *sta = Sta::sta();
|
||||||
|
return sta->isClock(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
is_ideal_clock(Pin *pin)
|
||||||
|
{
|
||||||
|
Sta *sta = Sta::sta();
|
||||||
|
return sta->isIdealClock(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
is_clock_search(const Pin *pin)
|
||||||
{
|
{
|
||||||
Sta *sta = Sta::sta();
|
Sta *sta = Sta::sta();
|
||||||
Graph *graph = sta->graph();
|
Graph *graph = sta->graph();
|
||||||
|
|
@ -3779,7 +3793,7 @@ pin_is_clock(const Pin *pin)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pin_is_genclk_src(const Pin *pin)
|
is_genclk_src(const Pin *pin)
|
||||||
{
|
{
|
||||||
Sta *sta = Sta::sta();
|
Sta *sta = Sta::sta();
|
||||||
Graph *graph = sta->graph();
|
Graph *graph = sta->graph();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue