update latest OpenSTA from upstream 7/25
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
This commit is contained in:
commit
836d704802
|
|
@ -5,7 +5,8 @@ on:
|
|||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# Primary native Linux build used for install artifacts.
|
||||
linux-ubuntu:
|
||||
if: github.repository_owner != 'The-OpenROAD-Project-private'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
|
@ -51,7 +52,7 @@ jobs:
|
|||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: artifact
|
||||
name: artifact-ubuntu
|
||||
path: |
|
||||
build/install/*
|
||||
retention-days: 1
|
||||
|
|
@ -60,6 +61,78 @@ jobs:
|
|||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: result
|
||||
name: result-ubuntu
|
||||
path: |
|
||||
test/results/*
|
||||
|
||||
# CentOS 7 Docker: old platform still common in EDA environments.
|
||||
linux-centos:
|
||||
if: github.repository_owner != 'The-OpenROAD-Project-private'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Build image
|
||||
run: docker build -f Dockerfile.centos7 --tag sta-centos7 .
|
||||
|
||||
- name: Test in container
|
||||
run: |
|
||||
mkdir -p test/results
|
||||
docker run --rm \
|
||||
-v "$PWD/test/results:/OpenSTA/test/results" \
|
||||
--entrypoint /bin/bash sta-centos7 \
|
||||
-c "cd /OpenSTA/test && ./regression || (cat results/diffs && exit 1)"
|
||||
|
||||
- name: Upload Test Result
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: result-centos7
|
||||
path: |
|
||||
test/results/*
|
||||
|
||||
# Native macOS coverage via Brewfile.
|
||||
macos:
|
||||
if: github.repository_owner != 'The-OpenROAD-Project-private'
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Install dependencies
|
||||
run: brew bundle
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
eval "$(/opt/homebrew/bin/brew shellenv)"
|
||||
export PATH="$(brew --prefix flex)/bin:$PATH"
|
||||
export PATH="$(brew --prefix bison)/bin:$PATH"
|
||||
export TCL_LIBRARY="$(brew --prefix tcl-tk@8)/lib/libtcl8.6.dylib"
|
||||
export TCL_INCLUDE_PATH="$(brew --prefix tcl-tk@8)/include/tcl-tk"
|
||||
export FLEX_INCLUDE_DIR="$(brew --prefix flex)/include"
|
||||
cmake -S . -B build \
|
||||
-D TCL_LIBRARY=$TCL_LIBRARY \
|
||||
-D TCL_INCLUDE_PATH=$TCL_INCLUDE_PATH \
|
||||
-D FLEX_INCLUDE_DIR=$FLEX_INCLUDE_DIR \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build -j "$(sysctl -n hw.ncpu)"
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
cd test
|
||||
./regression || (cat results/diffs && exit 1)
|
||||
|
||||
- name: Upload Test Result
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: result-macos
|
||||
path: |
|
||||
test/results/*
|
||||
|
|
|
|||
3
Brewfile
3
Brewfile
|
|
@ -2,8 +2,9 @@ brew "bison"
|
|||
brew "cmake"
|
||||
brew "eigen"
|
||||
brew "flex"
|
||||
brew "googletest"
|
||||
brew "swig"
|
||||
brew "tcl-tk@8"
|
||||
|
||||
tap "mht208/formal"
|
||||
brew "mht208/formal/cudd"
|
||||
brew "mht208/formal/cudd", trusted: true
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo \
|
|||
RUN ln -sf /usr/bin/cmake3 /usr/bin/cmake
|
||||
|
||||
# Download Bison
|
||||
RUN wget https://ftp.gnu.org/gnu/bison/bison-3.8.2.tar.gz && \
|
||||
RUN wget https://ftpmirror.gnu.org/gnu/bison/bison-3.8.2.tar.gz && \
|
||||
tar -xvf bison-3.8.2.tar.gz && \
|
||||
rm bison-3.8.2.tar.gz
|
||||
|
||||
|
|
@ -42,7 +42,8 @@ RUN source /opt/rh/devtoolset-11/enable && \
|
|||
make install
|
||||
|
||||
# Download TCL
|
||||
RUN wget http://prdownloads.sourceforge.net/tcl/tcl8.6.16-src.tar.gz && \
|
||||
RUN wget https://sourceforge.net/projects/tcl/files/Tcl/8.6.16/tcl8.6.16-src.tar.gz/download \
|
||||
-O tcl8.6.16-src.tar.gz && \
|
||||
tar -xvf tcl8.6.16-src.tar.gz && \
|
||||
rm tcl8.6.16-src.tar.gz
|
||||
|
||||
|
|
|
|||
|
|
@ -213,7 +213,6 @@ GraphDelayCalc::delaysInvalid()
|
|||
debugPrint(debug_, "delay_calc", 1, "delays invalid");
|
||||
delays_exist_ = false;
|
||||
delays_seeded_ = false;
|
||||
incremental_ = false;
|
||||
iter_->clear();
|
||||
// No need to keep track of incremental updates any more.
|
||||
invalid_delays_.clear();
|
||||
|
|
@ -224,7 +223,7 @@ GraphDelayCalc::delaysInvalid()
|
|||
void
|
||||
GraphDelayCalc::delayInvalid(const Pin *pin)
|
||||
{
|
||||
if (graph_ && incremental_) {
|
||||
if (graph_ && delays_exist_) {
|
||||
if (network_->isHierarchical(pin)) {
|
||||
EdgesThruHierPinIterator edge_iter(pin, network_, graph_);
|
||||
while (edge_iter.hasNext()) {
|
||||
|
|
@ -248,7 +247,7 @@ GraphDelayCalc::delayInvalid(Vertex *vertex)
|
|||
{
|
||||
debugPrint(debug_, "delay_calc", 2, "delay invalid {}",
|
||||
vertex->to_string(this));
|
||||
if (incremental_) {
|
||||
if (delays_exist_) {
|
||||
invalid_delays_.insert(vertex);
|
||||
// Invalidate driver that triggers dcalc for multi-driver nets.
|
||||
MultiDrvrNet *multi_drvr = multiDrvrNet(vertex);
|
||||
|
|
@ -274,7 +273,7 @@ void
|
|||
GraphDelayCalc::deleteVertexBefore(Vertex *vertex)
|
||||
{
|
||||
iter_->deleteVertexBefore(vertex);
|
||||
if (incremental_)
|
||||
if (delays_exist_)
|
||||
invalid_delays_.erase(vertex);
|
||||
MultiDrvrNet *multi_drvr = multiDrvrNet(vertex);
|
||||
if (multi_drvr) {
|
||||
|
|
@ -329,7 +328,7 @@ FindVertexDelays::copy() const
|
|||
void
|
||||
FindVertexDelays::visit(Vertex *vertex)
|
||||
{
|
||||
graph_delay_calc_->findVertexDelay(vertex, arc_delay_calc_, true);
|
||||
graph_delay_calc_->findVertexDelay(vertex, arc_delay_calc_);
|
||||
}
|
||||
|
||||
// The logical structure of incremental delay calculation closely
|
||||
|
|
@ -348,7 +347,7 @@ GraphDelayCalc::findDelays(Level level)
|
|||
}
|
||||
else
|
||||
iter_->ensureSize();
|
||||
if (incremental_)
|
||||
if (delays_exist_)
|
||||
seedInvalidDelays();
|
||||
|
||||
if (!iter_->empty()) {
|
||||
|
|
@ -367,7 +366,6 @@ GraphDelayCalc::findDelays(Level level)
|
|||
invalid_latch_edges_.clear();
|
||||
|
||||
delays_exist_ = true;
|
||||
incremental_ = true;
|
||||
debugPrint(debug_, "delay_calc", 1, "found {} delays", dcalc_count);
|
||||
stats.report("Delay calc");
|
||||
}
|
||||
|
|
@ -674,13 +672,12 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin,
|
|||
void
|
||||
GraphDelayCalc::findDelays(Vertex *drvr_vertex)
|
||||
{
|
||||
findVertexDelay(drvr_vertex, arc_delay_calc_, true);
|
||||
findVertexDelay(drvr_vertex, arc_delay_calc_);
|
||||
}
|
||||
|
||||
void
|
||||
GraphDelayCalc::findVertexDelay(Vertex *vertex,
|
||||
ArcDelayCalc *arc_delay_calc,
|
||||
bool propagate)
|
||||
ArcDelayCalc *arc_delay_calc)
|
||||
{
|
||||
const Pin *pin = vertex->pin();
|
||||
debugPrint(debug_, "delay_calc", 2, "find delays {} ({})",
|
||||
|
|
@ -692,32 +689,38 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex,
|
|||
|| (vertex->isBidirectDriver()
|
||||
&& network_->isTopLevelPort(pin)))
|
||||
seedRootSlew(vertex, arc_delay_calc);
|
||||
else {
|
||||
if (network_->isLeaf(pin)) {
|
||||
if (vertex->isDriver(network_)) {
|
||||
LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(vertex);
|
||||
DrvrLoadSlews load_slews_prev;
|
||||
if (incremental_)
|
||||
load_slews_prev = loadSlews(load_pin_index_map);
|
||||
findDriverDelays(vertex, arc_delay_calc, load_pin_index_map);
|
||||
if (propagate) {
|
||||
if (network_->direction(pin)->isInternal())
|
||||
enqueueTimingChecksEdges(vertex);
|
||||
// Enqueue adjacent vertices even if the load slews did not
|
||||
// change when non-incremental to stride past annotations.
|
||||
if (!incremental_
|
||||
|| loadSlewsChanged(load_slews_prev, load_pin_index_map))
|
||||
iter_->enqueueFanout(vertex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Load vertex.
|
||||
enqueueTimingChecksEdges(vertex);
|
||||
// Enqueue driver vertices from this input load.
|
||||
if (propagate)
|
||||
iter_->enqueueFanout(vertex);
|
||||
}
|
||||
}
|
||||
else if (network_->isLeaf(pin)
|
||||
&& vertex->isDriver(network_)) {
|
||||
LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(vertex);
|
||||
DrvrLoadSlews load_slews_prev;
|
||||
if (delays_exist_)
|
||||
load_slews_prev = loadSlews(load_pin_index_map);
|
||||
findDriverDelays(vertex, arc_delay_calc, load_pin_index_map);
|
||||
if (network_->direction(pin)->isInternal())
|
||||
enqueueCheckEdges(vertex);
|
||||
graph_->visitFanouts(vertex, search_non_latch_pred_,
|
||||
[this, &load_slews_prev, &load_pin_index_map]
|
||||
(Vertex *fanout) {
|
||||
// Enqueue adjacent vertices even if the load slew
|
||||
// did not change when non-incremental to stride
|
||||
// past annotations.
|
||||
if (!delays_exist_
|
||||
|| loadSlewChanged(fanout, load_slews_prev,
|
||||
load_pin_index_map)) {
|
||||
iter_->enqueue(fanout);
|
||||
fanout->setBfsPredecessorChanged(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (vertex->isLoad(network_)) {
|
||||
// Load vertex.
|
||||
// Includes top level bidirect load vertex with wire edge to bidirect driver.
|
||||
enqueueCheckEdges(vertex);
|
||||
graph_->visitFanouts(vertex, search_non_latch_pred_,
|
||||
[this] (Vertex *fanout) {
|
||||
iter_->enqueue(fanout);
|
||||
fanout->setBfsPredecessorChanged(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -737,24 +740,25 @@ GraphDelayCalc::loadSlews(LoadPinIndexMap &load_pin_index_map)
|
|||
}
|
||||
|
||||
bool
|
||||
GraphDelayCalc::loadSlewsChanged(DrvrLoadSlews &load_slews_prev,
|
||||
LoadPinIndexMap &load_pin_index_map)
|
||||
GraphDelayCalc::loadSlewChanged(Vertex *load_vertex,
|
||||
DrvrLoadSlews &load_slews_prev,
|
||||
LoadPinIndexMap &load_pin_index_map)
|
||||
{
|
||||
if (load_slews_prev.empty())
|
||||
return true;
|
||||
size_t index = load_pin_index_map[load_vertex->pin()];
|
||||
SlewSeq &slews_prev = load_slews_prev[index];;
|
||||
size_t slew_count = graph_->slewCount();
|
||||
for (auto const [pin, index] : load_pin_index_map) {
|
||||
Vertex *load_vertex = graph_->pinLoadVertex(pin);
|
||||
SlewSeq &slews_prev = load_slews_prev[index];;
|
||||
for (size_t i = 0; i < slew_count; i++) {
|
||||
const Slew slew = graph_->slew(load_vertex, i);
|
||||
if (!delayEqual(slew, slews_prev[i], this))
|
||||
return true;
|
||||
}
|
||||
for (size_t i = 0; i < slew_count; i++) {
|
||||
const Slew slew = graph_->slew(load_vertex, i);
|
||||
if (!delayEqual(slew, slews_prev[i], this))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
GraphDelayCalc::enqueueTimingChecksEdges(Vertex *vertex)
|
||||
GraphDelayCalc::enqueueCheckEdges(Vertex *vertex)
|
||||
{
|
||||
if (vertex->hasChecks()) {
|
||||
VertexInEdgeIterator edge_iter(vertex, graph_);
|
||||
|
|
@ -1180,10 +1184,10 @@ GraphDelayCalc::annotateDelaysSlews(Edge *edge,
|
|||
dcalc_result.drvrSlew(), scene, min_max);
|
||||
if (!edge->role()->isLatchDtoQ()) {
|
||||
Vertex *drvr_vertex = edge->to(graph_);
|
||||
delay_changed |= annotateLoadDelays(drvr_vertex, arc->toEdge()->asRiseFall(),
|
||||
dcalc_result,
|
||||
load_pin_index_map, delay_zero, true,
|
||||
scene, min_max);
|
||||
annotateLoadDelays(drvr_vertex, arc->toEdge()->asRiseFall(),
|
||||
dcalc_result,
|
||||
load_pin_index_map, delay_zero, true,
|
||||
scene, min_max);
|
||||
}
|
||||
return delay_changed;
|
||||
}
|
||||
|
|
@ -1238,7 +1242,7 @@ GraphDelayCalc::annotateDelaySlew(Edge *edge,
|
|||
// Annotate wire arc delays and load pin slews.
|
||||
// extra_delay is additional wire delay to add to delay returned
|
||||
// by the delay calculator.
|
||||
bool
|
||||
void
|
||||
GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex,
|
||||
const RiseFall *drvr_rf,
|
||||
ArcDcalcResult &dcalc_result,
|
||||
|
|
@ -1249,7 +1253,6 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex,
|
|||
const MinMax *min_max)
|
||||
{
|
||||
DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max);
|
||||
bool changed = false;
|
||||
VertexOutEdgeIterator edge_iter(drvr_vertex, graph_);
|
||||
while (edge_iter.hasNext()) {
|
||||
Edge *wire_edge = edge_iter.next();
|
||||
|
|
@ -1264,20 +1267,17 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex,
|
|||
load_vertex->to_string(this),
|
||||
delayAsString(wire_delay, this),
|
||||
delayAsString(load_slew, this));
|
||||
bool load_changed = false;
|
||||
if (!load_vertex->slewAnnotated(drvr_rf, min_max)) {
|
||||
if (drvr_vertex->slewAnnotated(drvr_rf, min_max)) {
|
||||
// Copy the driver slew to the load if it is annotated.
|
||||
const Slew drvr_slew = graph_->slew(drvr_vertex, drvr_rf, ap_index);
|
||||
graph_->setSlew(load_vertex, drvr_rf, ap_index, drvr_slew);
|
||||
load_changed = true;
|
||||
}
|
||||
else {
|
||||
const Slew slew = graph_->slew(load_vertex, drvr_rf, ap_index);
|
||||
if (!merge
|
||||
|| delayGreater(load_slew, slew, min_max, this)) {
|
||||
graph_->setSlew(load_vertex, drvr_rf, ap_index, load_slew);
|
||||
load_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1290,18 +1290,12 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex,
|
|||
if (!merge
|
||||
|| delayGreater(wire_delay_extra, delay, min_max, this)) {
|
||||
graph_->setWireArcDelay(wire_edge, drvr_rf, ap_index, wire_delay_extra);
|
||||
load_changed = true;
|
||||
if (observer_)
|
||||
observer_->delayChangedTo(load_vertex);
|
||||
}
|
||||
}
|
||||
if (load_changed && observer_)
|
||||
observer_->delayChangedTo(load_vertex);
|
||||
// Enqueue bidirect driver from load vertex.
|
||||
if (bidirectDrvrSlewFromLoad(load_pin))
|
||||
iter_->enqueue(graph_->pinDrvrVertex(load_pin));
|
||||
changed |= load_changed;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
LoadPinIndexMap
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ PrimaDelayCalc::PrimaDelayCalc(StaState *sta) :
|
|||
PrimaDelayCalc::PrimaDelayCalc(const PrimaDelayCalc &dcalc) :
|
||||
DelayCalcBase(dcalc),
|
||||
pin_node_map_(network_),
|
||||
node_index_map_(dcalc.node_index_map_),
|
||||
prima_order_(dcalc.prima_order_),
|
||||
watch_pin_values_(network_),
|
||||
table_dcalc_(makeDmpCeffElmoreDelayCalc(this))
|
||||
|
|
|
|||
370
doc/OpenSTA.fodt
370
doc/OpenSTA.fodt
File diff suppressed because it is too large
Load Diff
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -1053,6 +1053,7 @@ Vertex::init(Pin *pin,
|
|||
has_downstream_clk_pin_ = false;
|
||||
visited1_ = false;
|
||||
visited2_ = false;
|
||||
bfs_predecessor_changed_ = false;
|
||||
has_sim_value_ = false;
|
||||
level_ = 0;
|
||||
slew_annotated_ = false;
|
||||
|
|
@ -1115,6 +1116,23 @@ Vertex::isDriver(const Network *network) const
|
|||
|| dir->isInternal())));
|
||||
}
|
||||
|
||||
bool
|
||||
Vertex::isLoad(const Network *network) const
|
||||
{
|
||||
PortDirection *dir = network->direction(pin_);
|
||||
bool top_level_port = network->isTopLevelPort(pin_);
|
||||
return ((top_level_port
|
||||
&& (dir->isOutput()
|
||||
|| (dir->isBidirect()
|
||||
&& !is_bidirect_drvr_)))
|
||||
|| (!top_level_port
|
||||
&& (dir->isInput()
|
||||
|| dir->isTristate()
|
||||
|| (dir->isBidirect()
|
||||
&& !is_bidirect_drvr_)
|
||||
|| dir->isInternal())));
|
||||
}
|
||||
|
||||
void
|
||||
Vertex::setLevel(Level level)
|
||||
{
|
||||
|
|
@ -1264,6 +1282,12 @@ Vertex::setBfsInQueue(BfsIndex index,
|
|||
bfs_in_queue_ &= ~(1 << static_cast<unsigned>(index));
|
||||
}
|
||||
|
||||
void
|
||||
Vertex::setBfsPredecessorChanged(bool changed)
|
||||
{
|
||||
bfs_predecessor_changed_ = changed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Edge
|
||||
|
|
|
|||
|
|
@ -255,6 +255,7 @@ public:
|
|||
std::string name(const Network *network) const;
|
||||
[[nodiscard]] bool isBidirectDriver() const { return is_bidirect_drvr_; }
|
||||
[[nodiscard]] bool isDriver(const Network *network) const;
|
||||
[[nodiscard]] bool isLoad(const Network *network) const;
|
||||
Level level() const { return level_; }
|
||||
void setLevel(Level level);
|
||||
[[nodiscard]] bool visited() const { return visited1_; }
|
||||
|
|
@ -288,6 +289,8 @@ public:
|
|||
void setHasDownstreamClkPin(bool has_clk_pin);
|
||||
[[nodiscard]] bool bfsInQueue(BfsIndex index) const;
|
||||
void setBfsInQueue(BfsIndex index, bool value);
|
||||
bool bfsPredecessorChanged() const { return bfs_predecessor_changed_; }
|
||||
void setBfsPredecessorChanged(bool changed);
|
||||
[[nodiscard]] bool isRegClk() const { return is_reg_clk_; }
|
||||
// Has sim value in some mode.
|
||||
[[nodiscard]] bool hasSimValue() const { return has_sim_value_; }
|
||||
|
|
@ -335,6 +338,7 @@ protected:
|
|||
unsigned int has_downstream_clk_pin_:1;
|
||||
unsigned int visited1_:1;
|
||||
unsigned int visited2_:1;
|
||||
unsigned int bfs_predecessor_changed_:1;
|
||||
unsigned int has_sim_value_:1;
|
||||
int level_:Graph::vertex_level_bits; // 24
|
||||
unsigned int slew_annotated_:slew_annotated_bits; // 4
|
||||
|
|
|
|||
|
|
@ -232,12 +232,12 @@ protected:
|
|||
void zeroSlewAndWireDelays(Vertex *drvr_vertex,
|
||||
const RiseFall *rf);
|
||||
void findVertexDelay(Vertex *vertex,
|
||||
ArcDelayCalc *arc_delay_calc,
|
||||
bool propagate);
|
||||
ArcDelayCalc *arc_delay_calc);
|
||||
DrvrLoadSlews loadSlews(LoadPinIndexMap &load_pin_index_map);
|
||||
bool loadSlewsChanged(DrvrLoadSlews &load_slews_prev,
|
||||
LoadPinIndexMap &load_pin_index_map);
|
||||
void enqueueTimingChecksEdges(Vertex *vertex);
|
||||
void enqueueCheckEdges(Vertex *vertex);
|
||||
bool loadSlewChanged(Vertex *load_vertex,
|
||||
DrvrLoadSlews &load_slews_prev,
|
||||
LoadPinIndexMap &load_pin_index_map);
|
||||
bool annotateDelaysSlews(Edge *edge,
|
||||
const TimingArc *arc,
|
||||
ArcDcalcResult &dcalc_result,
|
||||
|
|
@ -251,7 +251,7 @@ protected:
|
|||
const Slew &gate_slew,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
bool annotateLoadDelays(Vertex *drvr_vertex,
|
||||
void annotateLoadDelays(Vertex *drvr_vertex,
|
||||
const RiseFall *drvr_rf,
|
||||
ArcDcalcResult &dcalc_result,
|
||||
LoadPinIndexMap &load_pin_index_map,
|
||||
|
|
@ -296,7 +296,6 @@ protected:
|
|||
// Observer for edge delay changes.
|
||||
DelayCalcObserver *observer_{nullptr};
|
||||
bool delays_seeded_{false};
|
||||
bool incremental_{false};
|
||||
bool delays_exist_{false};
|
||||
// Vertices with invalid -to delays.
|
||||
VertexSet invalid_delays_;
|
||||
|
|
|
|||
|
|
@ -1008,6 +1008,8 @@ public:
|
|||
void reportPathEnds(PathEndSeq *ends);
|
||||
ReportPath *reportPath() { return report_path_; }
|
||||
void reportPath(const Path *path);
|
||||
// For debugging.
|
||||
void reportPathVerbose(const Path *path);
|
||||
|
||||
// Report clk skews for clks.
|
||||
void reportClkSkew(ConstClockSeq &clks,
|
||||
|
|
|
|||
|
|
@ -118,6 +118,15 @@ ClkInfo::crprClkVertexId(const StaState *sta) const
|
|||
return crpr_clk_path_.vertexId(sta);
|
||||
}
|
||||
|
||||
const MinMax *
|
||||
ClkInfo::crprClkMinMax(const StaState *sta) const
|
||||
{
|
||||
if (crpr_clk_path_.isNull())
|
||||
return nullptr;
|
||||
else
|
||||
return crpr_clk_path_.tag(sta)->minMax();
|
||||
}
|
||||
|
||||
Path *
|
||||
ClkInfo::crprClkPath(const StaState *sta)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -78,13 +78,14 @@ public:
|
|||
// Null for clocks because the path cannot point to itself.
|
||||
Path *crprClkPath(const StaState *sta);
|
||||
const Path *crprClkPath(const StaState *sta) const;
|
||||
const Path *crprClkPathRaw() const;
|
||||
VertexId crprClkVertexId(const StaState *sta) const;
|
||||
const MinMax *crprClkMinMax(const StaState *sta) const;
|
||||
bool hasCrprClkPin() const { return !crpr_clk_path_.isNull(); }
|
||||
// This clk_info/tag is used for a generated clock source path.
|
||||
bool isGenClkSrcPath() const { return is_gen_clk_src_path_; }
|
||||
size_t hash() const { return hash_; }
|
||||
bool crprPathRefsFilter() const { return crpr_path_refs_filter_; }
|
||||
const Path *crprClkPathRaw() const;
|
||||
|
||||
static int cmp(const ClkInfo *clk_info1,
|
||||
const ClkInfo *clk_info2,
|
||||
|
|
|
|||
|
|
@ -1396,13 +1396,15 @@ ArrivalVisitor::pruneCrprArrivals()
|
|||
size_t path_index = path_itr->second;
|
||||
const ClkInfo *clk_info = tag->clkInfo();
|
||||
bool deleted_tag = false;
|
||||
if (!tag->isClock() && clk_info->hasCrprClkPin()) {
|
||||
const MinMax *min_max = tag->minMax();
|
||||
if (!tag->isClock()
|
||||
&& clk_info->hasCrprClkPin()) {
|
||||
Path *path_no_crpr = tag_bldr_no_crpr_->tagMatchPath(tag);
|
||||
if (path_no_crpr) {
|
||||
if (path_no_crpr
|
||||
&& path_no_crpr->tag(this) != tag) {
|
||||
Arrival max_arrival = path_no_crpr->arrival();
|
||||
const ClkInfo *clk_info_no_crpr = path_no_crpr->clkInfo(this);
|
||||
Arrival max_crpr = crpr->maxCrpr(clk_info_no_crpr);
|
||||
const MinMax *min_max = tag->minMax();
|
||||
Arrival max_arrival_max_crpr = (min_max == MinMax::max())
|
||||
? delayDiff(max_arrival, max_crpr, this)
|
||||
: delaySum(max_arrival, max_crpr, this);
|
||||
|
|
@ -1412,11 +1414,10 @@ ArrivalVisitor::pruneCrprArrivals()
|
|||
delayAsString(max_crpr, this),
|
||||
delayAsString(max_arrival_max_crpr, this));
|
||||
Arrival arrival = tag_bldr_->arrival(path_index);
|
||||
// Latch D->Q path uses enable min so crpr clk path min/max
|
||||
// does not match the path min/max.
|
||||
if (delayGreater(max_arrival_max_crpr, arrival, min_max, this)
|
||||
&& clk_info_no_crpr->crprClkPath(this)->minMax(this)
|
||||
== clk_info->crprClkPath(this)->minMax(this)) {
|
||||
// Latch D->Q path uses enable min so crpr clk path min/max
|
||||
// does not match the path min/max.
|
||||
&& clk_info_no_crpr->crprClkMinMax(this) == clk_info->crprClkMinMax(this)) {
|
||||
debugPrint(debug_, "search", 3, " pruned {}",
|
||||
tag->to_string(this));
|
||||
path_itr = path_index_map.erase(path_itr);
|
||||
|
|
|
|||
|
|
@ -2862,6 +2862,14 @@ Sta::reportPath(const Path *path)
|
|||
report_path_->reportPath(path);
|
||||
}
|
||||
|
||||
void
|
||||
Sta::reportPathVerbose(const Path *path)
|
||||
{
|
||||
const StringSeq field_names = {"input_pins", "slew", "capacitance"};
|
||||
setReportPathFields(field_names);
|
||||
report_path_->reportPath(path);
|
||||
}
|
||||
|
||||
void
|
||||
Sta::updateTiming(bool full)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue