Merge pull request #253 from eder-matheus/update_sta

update sta
This commit is contained in:
Matt Liberty 2024-12-16 14:04:59 -08:00 committed by GitHub
commit 7c31912ac9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 165 additions and 75 deletions

View File

@ -579,13 +579,17 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex,
else { else {
if (network_->isLeaf(pin)) { if (network_->isLeaf(pin)) {
if (vertex->isDriver(network_)) { if (vertex->isDriver(network_)) {
bool delay_changed = findDriverDelays(vertex, arc_delay_calc); LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(vertex);
DrvrLoadSlews prev_load_slews = loadSlews(load_pin_index_map);
findDriverDelays(vertex, arc_delay_calc, load_pin_index_map);
if (propagate) { if (propagate) {
if (network_->direction(pin)->isInternal()) if (network_->direction(pin)->isInternal())
enqueueTimingChecksEdges(vertex); enqueueTimingChecksEdges(vertex);
// Enqueue adjacent vertices even if the delays did not bool load_slews_changed = loadSlewsChanged(prev_load_slews,
load_pin_index_map);
// Enqueue adjacent vertices even if the load slews did not
// change when non-incremental to stride past annotations. // change when non-incremental to stride past annotations.
if (delay_changed || !incremental_) if (load_slews_changed || !incremental_)
iter_->enqueueAdjacentVertices(vertex); iter_->enqueueAdjacentVertices(vertex);
} }
} }
@ -605,6 +609,37 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex,
} }
} }
DrvrLoadSlews
GraphDelayCalc::loadSlews(LoadPinIndexMap &load_pin_index_map)
{
DrvrLoadSlews load_slews(load_pin_index_map.size());
for (auto const [pin, index] : load_pin_index_map) {
Vertex *load_vertex = graph_->pinLoadVertex(pin);
load_slews[index] = graph_->slews(load_vertex);
}
return load_slews;
}
bool
GraphDelayCalc::loadSlewsChanged(DrvrLoadSlews &prev_load_slews,
LoadPinIndexMap &load_pin_index_map)
{
for (auto const [pin, index] : load_pin_index_map) {
Vertex *load_vertex = graph_->pinLoadVertex(pin);
const SlewSeq load_slews = graph_->slews(load_vertex);
const SlewSeq &prev_slews = prev_load_slews[index];
for (size_t i = 0; i < load_slews.size(); i++) {
const Slew &slew = delayAsFloat(load_slews[i]);
const Slew &prev_slew = delayAsFloat(prev_slews[i]);
if ((prev_slew == 0.0 && slew != 0.0)
|| (prev_slew != 0.0
&& abs((slew - prev_slew) / prev_slew) > incremental_delay_tolerance_))
return true;
}
}
return false;
}
void void
GraphDelayCalc::enqueueTimingChecksEdges(Vertex *vertex) GraphDelayCalc::enqueueTimingChecksEdges(Vertex *vertex)
{ {
@ -639,21 +674,20 @@ GraphDelayCalc::enqueueTimingChecksEdges(Vertex *vertex)
} }
} }
bool void
GraphDelayCalc::findDriverDelays(Vertex *drvr_vertex, GraphDelayCalc::findDriverDelays(Vertex *drvr_vertex,
ArcDelayCalc *arc_delay_calc) ArcDelayCalc *arc_delay_calc,
LoadPinIndexMap &load_pin_index_map)
{ {
bool delay_changed = false;
MultiDrvrNet *multi_drvr = findMultiDrvrNet(drvr_vertex); MultiDrvrNet *multi_drvr = findMultiDrvrNet(drvr_vertex);
if (multi_drvr == nullptr if (multi_drvr == nullptr
|| (multi_drvr || (multi_drvr
&& (!multi_drvr->parallelGates(network_) && (!multi_drvr->parallelGates(network_)
|| drvr_vertex == multi_drvr->dcalcDrvr()))) { || drvr_vertex == multi_drvr->dcalcDrvr()))) {
initLoadSlews(drvr_vertex); initLoadSlews(drvr_vertex);
delay_changed |= findDriverDelays1(drvr_vertex, multi_drvr, arc_delay_calc); findDriverDelays1(drvr_vertex, multi_drvr, arc_delay_calc, load_pin_index_map);
} }
arc_delay_calc_->finishDrvrPin(); arc_delay_calc_->finishDrvrPin();
return delay_changed;
} }
MultiDrvrNet * MultiDrvrNet *
@ -782,7 +816,8 @@ GraphDelayCalc::initLoadSlews(Vertex *drvr_vertex)
bool bool
GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex, GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex,
MultiDrvrNet *multi_drvr, MultiDrvrNet *multi_drvr,
ArcDelayCalc *arc_delay_calc) ArcDelayCalc *arc_delay_calc,
LoadPinIndexMap &load_pin_index_map)
{ {
initSlew(drvr_vertex); initSlew(drvr_vertex);
if (multi_drvr if (multi_drvr
@ -806,7 +841,8 @@ GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex,
&& search_pred_->searchThru(edge) && search_pred_->searchThru(edge)
&& !edge->role()->isLatchDtoQ()) && !edge->role()->isLatchDtoQ())
delay_changed |= findDriverEdgeDelays(drvr_vertex, multi_drvr, edge, delay_changed |= findDriverEdgeDelays(drvr_vertex, multi_drvr, edge,
arc_delay_calc, delay_exists); arc_delay_calc, load_pin_index_map,
delay_exists);
} }
for (auto rf : RiseFall::range()) { for (auto rf : RiseFall::range()) {
if (!delay_exists[rf->index()]) if (!delay_exists[rf->index()])
@ -841,8 +877,10 @@ GraphDelayCalc::findLatchEdgeDelays(Edge *edge)
debugPrint(debug_, "delay_calc", 2, "find latch D->Q %s", debugPrint(debug_, "delay_calc", 2, "find latch D->Q %s",
sdc_network_->pathName(drvr_inst)); sdc_network_->pathName(drvr_inst));
array<bool, RiseFall::index_count> delay_exists = {false, false}; array<bool, RiseFall::index_count> delay_exists = {false, false};
LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
bool delay_changed = findDriverEdgeDelays(drvr_vertex, nullptr, edge, bool delay_changed = findDriverEdgeDelays(drvr_vertex, nullptr, edge,
arc_delay_calc_, delay_exists); arc_delay_calc_, load_pin_index_map,
delay_exists);
if (delay_changed && observer_) if (delay_changed && observer_)
observer_->delayChangedTo(drvr_vertex); observer_->delayChangedTo(drvr_vertex);
} }
@ -852,17 +890,18 @@ GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex,
const MultiDrvrNet *multi_drvr, const MultiDrvrNet *multi_drvr,
Edge *edge, Edge *edge,
ArcDelayCalc *arc_delay_calc, ArcDelayCalc *arc_delay_calc,
LoadPinIndexMap &load_pin_index_map,
// Return value.
array<bool, RiseFall::index_count> &delay_exists) array<bool, RiseFall::index_count> &delay_exists)
{ {
Vertex *from_vertex = edge->from(graph_); Vertex *from_vertex = edge->from(graph_);
const TimingArcSet *arc_set = edge->timingArcSet(); const TimingArcSet *arc_set = edge->timingArcSet();
bool delay_changed = false; bool delay_changed = false;
LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
for (const TimingArc *arc : arc_set->arcs()) { for (const TimingArc *arc : arc_set->arcs()) {
delay_changed |= findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc, delay_changed |= findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc,
load_pin_index_map, dcalc_ap, dcalc_ap, arc_delay_calc,
arc_delay_calc); load_pin_index_map);
delay_exists[arc->toEdge()->asRiseFall()->index()] = true; delay_exists[arc->toEdge()->asRiseFall()->index()] = true;
} }
} }
@ -873,6 +912,7 @@ GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex,
return delay_changed; return delay_changed;
} }
// External API.
void void
GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex, GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex,
Edge *edge, Edge *edge,
@ -882,9 +922,8 @@ GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex,
{ {
MultiDrvrNet *multi_drvr = multiDrvrNet(drvr_vertex); MultiDrvrNet *multi_drvr = multiDrvrNet(drvr_vertex);
LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex); LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc, findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc, dcalc_ap,
load_pin_index_map, dcalc_ap, arc_delay_calc, load_pin_index_map);
arc_delay_calc);
} }
bool bool
@ -892,9 +931,9 @@ GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex,
const MultiDrvrNet *multi_drvr, const MultiDrvrNet *multi_drvr,
Edge *edge, Edge *edge,
const TimingArc *arc, const TimingArc *arc,
LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
ArcDelayCalc *arc_delay_calc) ArcDelayCalc *arc_delay_calc,
LoadPinIndexMap &load_pin_index_map)
{ {
bool delay_changed = false; bool delay_changed = false;
const RiseFall *from_rf = arc->fromEdge()->asRiseFall(); const RiseFall *from_rf = arc->fromEdge()->asRiseFall();

View File

@ -741,6 +741,20 @@ Graph::setSlew(Vertex *vertex,
} }
} }
SlewSeq
Graph::slews(Vertex *vertex)
{
SlewSeq slews;
VertexId vertex_id = id(vertex);
DcalcAPIndex rf_ap_count = slew_rf_count_ * ap_count_;
for (DcalcAPIndex i = 0; i < rf_ap_count; i++) {
DelayTable *table = slew_tables_[i];
Slew &slew = table->ref(vertex_id);
slews.push_back(slew);
}
return slews;
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Edge * Edge *

View File

@ -130,6 +130,7 @@ public:
const RiseFall *rf, const RiseFall *rf,
DcalcAPIndex ap_index, DcalcAPIndex ap_index,
const Slew &slew); const Slew &slew);
SlewSeq slews(Vertex *vertex);
// Edge functions. // Edge functions.
virtual Edge *edge(EdgeId edge_index) const; virtual Edge *edge(EdgeId edge_index) const;

View File

@ -23,9 +23,12 @@
#include "Vector.hh" #include "Vector.hh"
#include "MinMax.hh" #include "MinMax.hh"
#include "Transition.hh" #include "Transition.hh"
#include "Delay.hh"
namespace sta { namespace sta {
using std::vector;
// Class declarations for pointer references. // Class declarations for pointer references.
class Graph; class Graph;
class Vertex; class Vertex;
@ -46,6 +49,7 @@ typedef int Level;
typedef int DcalcAPIndex; typedef int DcalcAPIndex;
typedef int TagGroupIndex; typedef int TagGroupIndex;
typedef Vector<GraphLoop*> GraphLoopSeq; typedef Vector<GraphLoop*> GraphLoopSeq;
typedef vector<Slew> SlewSeq;
static constexpr int level_max = std::numeric_limits<Level>::max(); static constexpr int level_max = std::numeric_limits<Level>::max();

View File

@ -26,7 +26,6 @@
#include "SearchClass.hh" #include "SearchClass.hh"
#include "DcalcAnalysisPt.hh" #include "DcalcAnalysisPt.hh"
#include "StaState.hh" #include "StaState.hh"
#include "Delay.hh"
#include "ArcDelayCalc.hh" #include "ArcDelayCalc.hh"
namespace sta { namespace sta {
@ -41,6 +40,7 @@ class FindVertexDelays;
class NetCaps; class NetCaps;
typedef Map<const Vertex*, MultiDrvrNet*> MultiDrvrNetMap; typedef Map<const Vertex*, MultiDrvrNet*> MultiDrvrNetMap;
typedef vector<SlewSeq> DrvrLoadSlews;
// This class traverses the graph calling the arc delay calculator and // This class traverses the graph calling the arc delay calculator and
// annotating delays on graph edges. // annotating delays on graph edges.
@ -163,8 +163,9 @@ protected:
const TimingArc *arc, const TimingArc *arc,
float from_slew, float from_slew,
const DcalcAnalysisPt *dcalc_ap); const DcalcAnalysisPt *dcalc_ap);
bool findDriverDelays(Vertex *drvr_vertex, void findDriverDelays(Vertex *drvr_vertex,
ArcDelayCalc *arc_delay_calc); ArcDelayCalc *arc_delay_calc,
LoadPinIndexMap &load_pin_index_map);
MultiDrvrNet *multiDrvrNet(const Vertex *drvr_vertex) const; MultiDrvrNet *multiDrvrNet(const Vertex *drvr_vertex) const;
MultiDrvrNet *findMultiDrvrNet(Vertex *drvr_pin); MultiDrvrNet *findMultiDrvrNet(Vertex *drvr_pin);
MultiDrvrNet *makeMultiDrvrNet(Vertex *drvr_vertex); MultiDrvrNet *makeMultiDrvrNet(Vertex *drvr_vertex);
@ -172,20 +173,23 @@ protected:
Vertex *firstLoad(Vertex *drvr_vertex); Vertex *firstLoad(Vertex *drvr_vertex);
bool findDriverDelays1(Vertex *drvr_vertex, bool findDriverDelays1(Vertex *drvr_vertex,
MultiDrvrNet *multi_drvr, MultiDrvrNet *multi_drvr,
ArcDelayCalc *arc_delay_calc); ArcDelayCalc *arc_delay_calc,
LoadPinIndexMap &load_pin_index_map);
void initLoadSlews(Vertex *drvr_vertex); void initLoadSlews(Vertex *drvr_vertex);
bool findDriverEdgeDelays(Vertex *drvr_vertex, bool findDriverEdgeDelays(Vertex *drvr_vertex,
const MultiDrvrNet *multi_drvr, const MultiDrvrNet *multi_drvr,
Edge *edge, Edge *edge,
ArcDelayCalc *arc_delay_calc, ArcDelayCalc *arc_delay_calc,
LoadPinIndexMap &load_pin_index_map,
// Return value.
array<bool, RiseFall::index_count> &delay_exists); array<bool, RiseFall::index_count> &delay_exists);
bool findDriverArcDelays(Vertex *drvr_vertex, bool findDriverArcDelays(Vertex *drvr_vertex,
const MultiDrvrNet *multi_drvr, const MultiDrvrNet *multi_drvr,
Edge *edge, Edge *edge,
const TimingArc *arc, const TimingArc *arc,
LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
ArcDelayCalc *arc_delay_calc); ArcDelayCalc *arc_delay_calc,
LoadPinIndexMap &load_pin_index_map);
ArcDcalcArgSeq makeArcDcalcArgs(Vertex *drvr_vertex, ArcDcalcArgSeq makeArcDcalcArgs(Vertex *drvr_vertex,
const MultiDrvrNet *multi_drvr, const MultiDrvrNet *multi_drvr,
Edge *edge, Edge *edge,
@ -205,6 +209,9 @@ protected:
void findVertexDelay(Vertex *vertex, void findVertexDelay(Vertex *vertex,
ArcDelayCalc *arc_delay_calc, ArcDelayCalc *arc_delay_calc,
bool propagate); bool propagate);
DrvrLoadSlews loadSlews(LoadPinIndexMap &load_pin_index_map);
bool loadSlewsChanged(DrvrLoadSlews &prev_load_slews,
LoadPinIndexMap &load_pin_index_map);
void enqueueTimingChecksEdges(Vertex *vertex); void enqueueTimingChecksEdges(Vertex *vertex);
bool annotateDelaysSlews(Edge *edge, bool annotateDelaysSlews(Edge *edge,
const TimingArc *arc, const TimingArc *arc,

View File

@ -238,25 +238,26 @@ public:
const RiseFall *to_rf, const RiseFall *to_rf,
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
virtual Tag *thruTag(Tag *from_tag, Tag *thruTag(Tag *from_tag,
Edge *edge, Edge *edge,
const RiseFall *to_rf, const RiseFall *to_rf,
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
virtual Tag *thruClkTag(PathVertex *from_path, Tag *thruClkTag(PathVertex *from_path,
Tag *from_tag, Tag *from_tag,
bool to_propagates_clk, bool to_propagates_clk,
Edge *edge, Edge *edge,
const RiseFall *to_rf, const RiseFall *to_rf,
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
ClkInfo *thruClkInfo(PathVertex *from_path, ClkInfo *thruClkInfo(PathVertex *from_path,
ClkInfo *from_tag_clk, ClkInfo *from_clk_info,
Edge *edge, bool from_is_clk,
Vertex *to_vertex, Edge *edge,
const Pin *to_pin, const Pin *to_pin,
const MinMax *min_max, bool to_is_clk,
const PathAnalysisPt *path_ap); const MinMax *min_max,
const PathAnalysisPt *path_ap);
ClkInfo *clkInfoWithCrprClkPath(ClkInfo *from_clk_info, ClkInfo *clkInfoWithCrprClkPath(ClkInfo *from_clk_info,
PathVertex *from_path, PathVertex *from_path,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);

View File

@ -54,8 +54,8 @@ public:
const Arrival &insertion() const { return insertion_; } const Arrival &insertion() const { return insertion_; }
ClockUncertainties *uncertainties() const { return uncertainties_; } ClockUncertainties *uncertainties() const { return uncertainties_; }
PathAPIndex pathAPIndex() const { return path_ap_index_; } PathAPIndex pathAPIndex() const { return path_ap_index_; }
// Clock path for the last driver in the clock network used for // Clock path used for crpr resolution.
// crpr resolution. // Null for clocks because the path cannot point to itself.
PathVertexRep &crprClkPath() { return crpr_clk_path_; } PathVertexRep &crprClkPath() { return crpr_clk_path_; }
const PathVertexRep &crprClkPath() const { return crpr_clk_path_; } const PathVertexRep &crprClkPath() const { return crpr_clk_path_; }
VertexId crprClkVertexId() const; VertexId crprClkVertexId() const;

View File

@ -46,20 +46,20 @@ CheckCrpr::CheckCrpr(StaState *sta) :
{ {
} }
PathVertex * void
CheckCrpr::clkPathPrev(const PathVertex *path, CheckCrpr::clkPathPrev(const PathVertex *path,
PathVertex &tmp) PathVertex &prev)
{ {
Vertex *vertex = path->vertex(this); Vertex *vertex = path->vertex(this);
int arrival_index; int arrival_index;
bool exists; bool exists;
path->arrivalIndex(arrival_index, exists); path->arrivalIndex(arrival_index, exists);
tmp = clkPathPrev(vertex, arrival_index); PathVertexRep *prevs = graph_->prevPaths(vertex);
if (tmp.isNull()) if (prevs)
return nullptr; prev.init(prevs[arrival_index], this);
else else
return &tmp; criticalError(2200, "missing prev paths");
} }
PathVertex PathVertex
@ -70,7 +70,7 @@ CheckCrpr::clkPathPrev(Vertex *vertex,
if (prevs) if (prevs)
return PathVertex(prevs[arrival_index], this); return PathVertex(prevs[arrival_index], this);
else { else {
criticalError(248, "missing prev paths"); criticalError(2201, "missing prev paths");
return PathVertex(); return PathVertex();
} }
} }
@ -152,13 +152,22 @@ CheckCrpr::checkCrpr1(const Path *src_path,
{ {
crpr = 0.0; crpr = 0.0;
crpr_pin = nullptr; crpr_pin = nullptr;
ClkInfo *src_clk_info = src_path->tag(this)->clkInfo(); const Tag *src_tag = src_path->tag(this);
ClkInfo *src_clk_info = src_tag->clkInfo();
ClkInfo *tgt_clk_info = tgt_clk_path->tag(this)->clkInfo(); ClkInfo *tgt_clk_info = tgt_clk_path->tag(this)->clkInfo();
const Clock *src_clk = src_clk_info->clock(); const Clock *src_clk = src_clk_info->clock();
const Clock *tgt_clk = tgt_clk_info->clock(); const Clock *tgt_clk = tgt_clk_info->clock();
const PathVertex src_clk_path1(src_clk_info->crprClkPath(), this); PathVertex src_clk_path1;
const PathVertex *src_clk_path = PathVertexRep &src_crpr_clk_path = src_clk_info->crprClkPath();
src_clk_path1.isNull() ? nullptr : &src_clk_path1; const PathVertex *src_clk_path = nullptr;
if (src_tag->isClock()) {
src_clk_path1.init(src_path->vertex(this), src_path->tag(this), this);
src_clk_path = &src_clk_path1;
}
else if (!src_crpr_clk_path.isNull()) {
src_clk_path1.init(src_crpr_clk_path, this);
src_clk_path = &src_clk_path1;
}
const MinMax *src_clk_min_max = const MinMax *src_clk_min_max =
src_clk_path ? src_clk_path->minMax(this) : src_path->minMax(this); src_clk_path ? src_clk_path->minMax(this) : src_path->minMax(this);
if (src_clk && tgt_clk if (src_clk && tgt_clk
@ -242,20 +251,30 @@ CheckCrpr::findCrpr(const PathVertex *src_clk_path,
} }
const PathVertex *src_clk_path2 = src_clk_path1; const PathVertex *src_clk_path2 = src_clk_path1;
const PathVertex *tgt_clk_path2 = tgt_clk_path1; const PathVertex *tgt_clk_path2 = tgt_clk_path1;
PathVertex tmp1, tmp2; PathVertex src_prev, tgt_prev;
// src_clk_path and tgt_clk_path are now in the same (gen)clk src path. // src_clk_path and tgt_clk_path are now in the same (gen)clk src path.
// Use the vertex levels to back up the deeper path to see if they // Use the vertex levels to back up the deeper path to see if they
// overlap. // overlap.
while (src_clk_path2 && tgt_clk_path2 int src_level = src_clk_path2->vertex(this)->level();
&& src_clk_path2->pin(this) != tgt_clk_path2->pin(this)) { int tgt_level = tgt_clk_path2->vertex(this)->level();
Level src_level = src_clk_path2->vertex(this)->level(); while (src_clk_path2->pin(this) != tgt_clk_path2->pin(this)) {
Level tgt_level = tgt_clk_path2->vertex(this)->level(); int level_diff = src_level - tgt_level;
if (src_level >= tgt_level) if (level_diff >= 0) {
src_clk_path2 = clkPathPrev(src_clk_path2, tmp1); clkPathPrev(src_clk_path2, src_prev);
if (tgt_level >= src_level) if (src_prev.isNull())
tgt_clk_path2 = clkPathPrev(tgt_clk_path2, tmp2); break;
src_clk_path2 = &src_prev;
src_level = src_clk_path2->vertex(this)->level();
}
if (level_diff <= 0) {
clkPathPrev(tgt_clk_path2, tgt_prev);
if (tgt_prev.isNull())
break;
tgt_clk_path2 = &tgt_prev;
tgt_level = tgt_clk_path2->vertex(this)->level();
}
} }
if (src_clk_path2 && tgt_clk_path2 if (!src_clk_path2->isNull() && !tgt_clk_path2->isNull()
&& (src_clk_path2->transition(this) == tgt_clk_path2->transition(this) && (src_clk_path2->transition(this) == tgt_clk_path2->transition(this)
|| same_pin)) { || same_pin)) {
debugPrint(debug_, "crpr", 2, "crpr pin %s", debugPrint(debug_, "crpr", 2, "crpr pin %s",

View File

@ -56,8 +56,8 @@ public:
int arrival_index); int arrival_index);
private: private:
PathVertex *clkPathPrev(const PathVertex *path, void clkPathPrev(const PathVertex *path,
PathVertex &tmp); PathVertex &prev);
Arrival otherMinMaxArrival(const PathVertex *path); Arrival otherMinMaxArrival(const PathVertex *path);
void checkCrpr1(const Path *src_path, void checkCrpr1(const Path *src_path,
const PathVertex *tgt_clk_path, const PathVertex *tgt_clk_path,

View File

@ -2417,8 +2417,9 @@ Search::thruClkTag(PathVertex *from_path,
&& to_propagates_clk && to_propagates_clk
&& (role->isWire() && (role->isWire()
|| role == TimingRole::combinational())); || role == TimingRole::combinational()));
ClkInfo *to_clk_info = thruClkInfo(from_path, from_clk_info, ClkInfo *to_clk_info = thruClkInfo(from_path, from_clk_info, from_is_clk,
edge, to_vertex, to_pin, min_max, path_ap); edge, to_pin, to_is_clk,
min_max, path_ap);
Tag *to_tag = mutateTag(from_tag,from_pin,from_rf,from_is_clk,from_clk_info, Tag *to_tag = mutateTag(from_tag,from_pin,from_rf,from_is_clk,from_clk_info,
to_pin, to_rf, to_is_clk, to_is_reg_clk, false, to_pin, to_rf, to_is_clk, to_is_reg_clk, false,
to_clk_info, nullptr, min_max, path_ap); to_clk_info, nullptr, min_max, path_ap);
@ -2429,9 +2430,10 @@ Search::thruClkTag(PathVertex *from_path,
ClkInfo * ClkInfo *
Search::thruClkInfo(PathVertex *from_path, Search::thruClkInfo(PathVertex *from_path,
ClkInfo *from_clk_info, ClkInfo *from_clk_info,
bool from_is_clk,
Edge *edge, Edge *edge,
Vertex *to_vertex,
const Pin *to_pin, const Pin *to_pin,
bool to_is_clk,
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap) const PathAnalysisPt *path_ap)
{ {
@ -2462,7 +2464,7 @@ Search::thruClkInfo(PathVertex *from_path,
PathVertex *to_crpr_clk_path = nullptr; PathVertex *to_crpr_clk_path = nullptr;
if (sdc_->crprActive() if (sdc_->crprActive()
&& to_vertex->isRegClk()) { && from_is_clk && !to_is_clk) {
to_crpr_clk_path = from_path; to_crpr_clk_path = from_path;
changed = true; changed = true;
} }

View File

@ -5600,6 +5600,9 @@ Sta::writeTimingModel(const char *lib_name,
const char *filename, const char *filename,
const Corner *corner) const Corner *corner)
{ {
if (network()->defaultLibertyLibrary() == nullptr) {
report_->error(2141, "No liberty libraries found.");
}
LibertyLibrary *library = makeTimingModel(lib_name, cell_name, filename, LibertyLibrary *library = makeTimingModel(lib_name, cell_name, filename,
corner, this); corner, this);
writeLiberty(library, filename, this); writeLiberty(library, filename, this);