mirror of
https://github.com/The-OpenROAD-Project/OpenSTA.git
synced 2026-08-22 14:06:56 +02:00
Merge remote-tracking branch 'parallaxsw/master' into update_sta
Signed-off-by: Eder Monteiro <[email protected]>
This commit is contained in:
+58
-19
@@ -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();
|
||||||
|
|||||||
@@ -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 *
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
+19
-18
@@ -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);
|
||||||
|
|||||||
+2
-2
@@ -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;
|
||||||
|
|||||||
+40
-21
@@ -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",
|
||||||
|
|||||||
+2
-2
@@ -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,
|
||||||
|
|||||||
+6
-4
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user