bfs update kahns prep

commit 4075953c9798444b9d5275f8fa0320f74b9bf1ef
Author: James Cherry <cherry@CerezoBook.local>
Date:   Sat Jul 4 09:00:48 2026 -0700

    bfs resort hasNext

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit 4fb0dd19e479f507935129fe940bcd1cf93b29d0
Author: James Cherry <cherry@CerezoBook.local>
Date:   Thu Jul 2 12:23:54 2026 -0700

    ApiChanges

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit 510afbc1403c9fd2b764b4f3a71dddabd696f052
Author: James Cherry <cherry@CerezoBook.local>
Date:   Thu Jul 2 11:07:44 2026 -0700

    bfs enqueueFanin/out

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit 9a5aa570e910c289b276a519bdf532dfa2e28c5f
Author: James Cherry <cherry@CerezoBook.local>
Date:   Thu Jul 2 10:41:27 2026 -0700

    Revert "bfs continueFrom/enqueueFanin/out"

    This reverts commit d18498c947a7df2b615fafda38fbdbe8033eca9d.

commit 02a253ab252f6637cfea29bdd788cb25da16813d
Author: James Cherry <cherry@CerezoBook.local>
Date:   Thu Jul 2 08:21:49 2026 -0700

    Revert "Bfs rm search_pred"

    This reverts commit d858b3380b5e1d81ff6162b6378672a6099a246f.

commit 0adf03613d91c5774545d12cba1dc52052ca732a
Author: James Cherry <cherry@CerezoBook.local>
Date:   Thu Jul 2 08:08:04 2026 -0700

    Genclks::ensureMaster

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit 089b373c548b77f9189a2617c3168867de620dfe
Author: James Cherry <cherry@CerezoBook.local>
Date:   Wed Jul 1 17:50:43 2026 -0700

    Search::ensureDownstreamClkPins() use dfs

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit 000ca16adb9bdcb92266e5f242629bc3e8612658
Author: James Cherry <cherry@CerezoBook.local>
Date:   Wed Jul 1 10:03:57 2026 -0700

    ApiChangeLog

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit d858b3380b5e1d81ff6162b6378672a6099a246f
Author: James Cherry <cherry@CerezoBook.local>
Date:   Wed Jul 1 09:56:53 2026 -0700

    Bfs rm search_pred

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit d18498c947a7df2b615fafda38fbdbe8033eca9d
Author: James Cherry <cherry@CerezoBook.local>
Date:   Wed Jul 1 08:07:15 2026 -0700

    bfs continueFrom/enqueueFanin/out

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit a8c55b12b3ad7a1041766775727ad758ae8c6d18
Author: James Cherry <cherry@CerezoBook.local>
Date:   Tue Jun 30 10:07:46 2026 -0700

    bfs continue

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit 8530dcd86b7ee736f1858143c3b2cee57cdbc991
Author: James Cherry <cherry@CerezoBook.local>
Date:   Tue Jun 30 07:15:28 2026 -0700

    Graph::visitFanin/out uninline edge iter

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit 1ba1f4576f4b72c64db742369a63dcf8726ba002
Author: James Cherry <cherry@CerezoBook.local>
Date:   Mon Jun 29 21:09:17 2026 -0700

    BfsIterator rm Iterator<Vector> subclass

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit b3ddd2580298958ad6da8225ecac0d255315504c
Author: James Cherry <cherry@CerezoBook.local>
Date:   Mon Jun 29 20:15:23 2026 -0700

    ClkNetwork::findClkPins use VertexQueue instead of bfs

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit 9e73154db48a7301be4039a25aec1fef589ef18a
Author: James Cherry <cherry@CerezoBook.local>
Date:   Mon Jun 29 18:39:39 2026 -0700

    Search::ensureDownstreamClkPins use VertexQueue

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit 9cd1b160e126ccacc47375ef508fdbb580bfa162
Author: James Cherry <cherry@CerezoBook.local>
Date:   Mon Jun 29 11:18:03 2026 -0700

    comment

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit 0baf3838e2b8faa5fea560b0c95431b277631fea
Author: James Cherry <cherry@CerezoBook.local>
Date:   Mon Jun 29 10:57:39 2026 -0700

    findClkArrivals use invalid for clk fringe

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit e82ccd10a5e4bd69e41ce889685d7a130ae79ed6
Author: James Cherry <cherry@CerezoBook.local>
Date:   Sun Jun 28 20:36:48 2026 -0700

    Search::findClkArrivals

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

commit cb66a72686c8728141c72ceb593b8a4b895ff696
Author: James Cherry <cherry@CerezoBook.local>
Date:   Sun Jun 28 10:11:55 2026 -0700

    rm Search::postponeClkFanouts

    Signed-off-by: James Cherry <cherry@CerezoBook.local>

Signed-off-by: James Cherry <cherry@CerezoBook.local>
This commit is contained in:
James Cherry 2026-07-04 09:04:31 -07:00
parent 900116cf72
commit 2c866d5f2d
8 changed files with 333 additions and 244 deletions

View File

@ -395,7 +395,7 @@ GraphDelayCalc::seedRootSlew(Vertex *vertex,
seedDrvrSlew(vertex, arc_delay_calc);
else
seedLoadSlew(vertex);
iter_->enqueueAdjacentVertices(vertex);
iter_->enqueueFanout(vertex);
}
void
@ -703,7 +703,7 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex,
// change when non-incremental to stride past annotations.
if (!incremental_
|| loadSlewsChanged(load_slews_prev, load_pin_index_map))
iter_->enqueueAdjacentVertices(vertex);
iter_->enqueueFanout(vertex);
}
}
else {
@ -711,7 +711,7 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex,
enqueueTimingChecksEdges(vertex);
// Enqueue driver vertices from this input load.
if (propagate)
iter_->enqueueAdjacentVertices(vertex);
iter_->enqueueFanout(vertex);
}
}
// Bidirect port drivers are enqueued by their load vertex in

View File

@ -581,9 +581,9 @@ Graph::visitFanouts(Vertex *vertex,
const VertexFn &fn)
{
if (pred->searchFrom(vertex)) {
for (Edge *edge = this->edge(vertex->out_edges_);
edge;
edge = this->edge(edge->vertex_out_next_)) {
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *to_vertex = this->vertex(edge->to_);
if (pred->searchThru(edge)
&& pred->searchTo(to_vertex))
@ -598,9 +598,9 @@ Graph::visitFanoutEdges(Vertex *vertex,
const EdgeFn &fn)
{
if (pred->searchFrom(vertex)) {
for (Edge *edge = this->edge(vertex->out_edges_);
edge;
edge = this->edge(edge->vertex_out_next_)) {
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *to_vertex = this->vertex(edge->to_);
if (pred->searchThru(edge)
&& pred->searchTo(to_vertex))
@ -615,9 +615,9 @@ Graph::visitFanins(Vertex *vertex,
const VertexFn &fn)
{
if (pred->searchFrom(vertex)) {
for (Edge *edge = this->edge(vertex->in_edges_);
edge;
edge = this->edge(edge->vertex_in_next_)) {
VertexInEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *from_vertex = this->vertex(edge->from_);
if (pred->searchThru(edge)
&& pred->searchFrom(from_vertex))
@ -632,9 +632,9 @@ Graph::visitFaninEdges(Vertex *vertex,
const EdgeFn &fn)
{
if (pred->searchFrom(vertex)) {
for (Edge *edge = this->edge(vertex->in_edges_);
edge;
edge = this->edge(edge->vertex_in_next_)) {
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *from_vertex = this->vertex(edge->from_);
if (pred->searchThru(edge)
&& pred->searchFrom(from_vertex))

View File

@ -24,6 +24,7 @@
#pragma once
#include <functional>
#include <mutex>
#include <vector>
@ -38,6 +39,8 @@ class SearchPred;
class BfsFwdIterator;
class BfsBkwdIterator;
using VertexFn = std::function<void(Vertex*)>;
// LevelQueue is a vector of vertex vectors indexed by logic level.
using LevelQueue = std::vector<VertexSeq>;
@ -50,26 +53,23 @@ using LevelQueue = std::vector<VertexSeq>;
// Vertices are marked as being in the queue by using a flag on
// the vertex indexed by bfs_index. A unique flag is only needed
// if the BFS in in use when other BFS's are simultaneously in use.
class BfsIterator : public StaState,
public Iterator<Vertex*>
class BfsIterator : public StaState
{
public:
// Make sure that the BFS queue is deep enough for the max logic level.
void ensureSize();
// Reset to virgin state.
void clear();
// Apply fn to each vertex and clear.
void clear(const VertexFn &fn);
[[nodiscard]] bool empty() const;
// Enqueue a vertex to search from.
void enqueue(Vertex *vertex);
// Enqueue vertices adjacent to a vertex.
void enqueueAdjacentVertices(Vertex *vertex);
virtual void enqueueAdjacentVertices(Vertex *vertex) = 0;
virtual void enqueueAdjacentVertices(Vertex *vertex,
const Mode *mode);
virtual void enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred,
const Mode *mode) = 0;
virtual void enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred) = 0;
[[nodiscard]] bool inQueue(Vertex *vertex);
void checkInQueue(Vertex *vertex);
// Notify iterator that vertex will be deleted.
@ -77,10 +77,6 @@ public:
void remove(Vertex *vertex);
void reportEntries() const;
bool hasNext() override;
bool hasNext(Level to_level);
Vertex *next() override;
// Apply visitor to all vertices in the queue in level order.
// Returns the number of vertices that are visited.
virtual int visit(Level to_level,
@ -91,6 +87,10 @@ public:
int visitParallel(Level to_level,
VertexVisitor *visitor);
bool hasNext();
bool hasNext(Level to_level);
Vertex *next();
protected:
BfsIterator(BfsIndex bfs_index,
Level level_min,
@ -104,10 +104,10 @@ protected:
virtual bool levelLessOrEqual(Level level1,
Level level2) const = 0;
virtual void incrLevel(Level &level) const = 0;
void findNext(Level to_level);
void deleteEntries();
void checkLevel(Vertex *vertex,
Level level);
void findNext(Level to_level);
BfsIndex bfs_index_;
Level level_min_;
@ -131,12 +131,13 @@ public:
SearchPred *search_pred,
StaState *sta);
~BfsFwdIterator() override;
void enqueueAdjacentVertices(Vertex *vertex) override;
void enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred) override;
void enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred,
const Mode *mode) override;
using BfsIterator::enqueueAdjacentVertices;
void enqueueFanout(Vertex *vertex);
void enqueueFanout(Vertex *vertex,
const Mode *mode);
protected:
bool levelLessOrEqual(Level level1,
@ -153,14 +154,17 @@ public:
SearchPred *search_pred,
StaState *sta);
~BfsBkwdIterator() override;
void enqueueAdjacentVertices(Vertex *vertex) override;
void enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred) override;
void enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred,
const Mode *mode) override;
using BfsIterator::enqueueAdjacentVertices;
void enqueueFanin(Vertex *vertex);
void enqueueFanin(Vertex *vertex,
const Mode *mode);
protected:
void enqueueFanin(Vertex *vertex,
SearchPred *search_pred);
bool levelLessOrEqual(Level level1,
Level level2) const override;
bool levelLess(Level level1,

View File

@ -286,8 +286,6 @@ public:
TagGroupBldr *tag_bldr);
void postponeLatchDataOutputs(Vertex *vertex);
void postponeArrivals(Vertex *vertex);
void enqueuePendingClkFanouts();
void postponeClkFanouts(Vertex *vertex);
void seedRequired(Vertex *vertex);
void seedRequiredEnqueueFanin(Vertex *vertex);
void seedInputDelayArrival(const Pin *pin,
@ -503,12 +501,12 @@ protected:
bool is_segment_start,
const MinMax *min_max,
Scene *scene);
void seedClkVertexArrivals();
void findClkArrivals1();
void enqueueClkRoots();
void enqueueInvalidClks();
void findAllArrivals(bool thru_latches,
bool clks_only);
void findAllArrivals(bool thru_latches);
void findArrivals1(Level level);
void findArrivals2(Level level);
Tag *mutateTag(Tag *from_tag,
const Pin *from_pin,
const RiseFall *from_rf,
@ -646,12 +644,9 @@ protected:
std::vector<TagIndex> tag_group_free_indices_;
std::mutex tag_group_lock_;
// Latches data outputs to queue on the next search pass.
VertexSet postponed_arrivals_;
std::mutex postponed_arrivals_lock_;
// Clock network endpoints where arrival search was suppended by findClkArrivals().
VertexSet postponed_clk_endpoints_;
std::mutex postponed_clk_endpoints_lock_;
// Arrivals to queue on the next search pass.
VertexSet pending_arrivals_;
std::mutex pending_arrivals_lock_;
VertexSet endpoints_;
bool endpoints_initialized_{false};

View File

@ -70,13 +70,21 @@ BfsIterator::ensureSize()
void
BfsIterator::clear()
{
clear([] (Vertex *) {});
}
void
BfsIterator::clear(const VertexFn &fn)
{
Level level = first_level_;
while (levelLessOrEqual(level, last_level_)) {
VertexSeq &level_vertices = queue_[level];
for (Vertex *vertex : level_vertices) {
if (vertex)
if (vertex) {
vertex->setBfsInQueue(bfs_index_, false);
fn(vertex);
}
}
level_vertices.clear();
incrLevel(level);
@ -115,19 +123,6 @@ BfsIterator::empty() const
return levelLess(last_level_, first_level_);
}
void
BfsIterator::enqueueAdjacentVertices(Vertex *vertex)
{
enqueueAdjacentVertices(vertex, search_pred_);
}
void
BfsIterator::enqueueAdjacentVertices(Vertex *vertex,
const Mode *mode)
{
enqueueAdjacentVertices(vertex, search_pred_, mode);
}
int
BfsIterator::visit(Level to_level,
VertexVisitor *visitor)
@ -217,50 +212,6 @@ BfsIterator::visitParallel(Level to_level,
return visit_count;
}
bool
BfsIterator::hasNext()
{
return hasNext(last_level_);
}
bool
BfsIterator::hasNext(Level to_level)
{
findNext(to_level);
return levelLessOrEqual(first_level_, last_level_)
&& !queue_[first_level_].empty();
}
Vertex *
BfsIterator::next()
{
VertexSeq &level_vertices = queue_[first_level_];
Vertex *vertex = level_vertices.back();
level_vertices.pop_back();
vertex->setBfsInQueue(bfs_index_, false);
return vertex;
}
void
BfsIterator::findNext(Level to_level)
{
while (levelLessOrEqual(first_level_, last_level_)
&& levelLessOrEqual(first_level_, to_level)) {
VertexSeq &level_vertices = queue_[first_level_];
// Skip null entries from deleted vertices.
while (!level_vertices.empty()) {
Vertex *vertex = level_vertices.back();
if (vertex == nullptr)
level_vertices.pop_back();
else {
checkLevel(vertex, first_level_);
return;
}
}
incrLevel(first_level_);
}
}
void
BfsIterator::enqueue(Vertex *vertex)
{
@ -340,6 +291,52 @@ BfsIterator::remove(Vertex *vertex)
////////////////////////////////////////////////////////////////
bool
BfsIterator::hasNext()
{
return hasNext(last_level_);
}
bool
BfsIterator::hasNext(Level to_level)
{
findNext(to_level);
return levelLessOrEqual(first_level_, last_level_)
&& !queue_[first_level_].empty();
}
Vertex *
BfsIterator::next()
{
VertexSeq &level_vertices = queue_[first_level_];
Vertex *vertex = level_vertices.back();
level_vertices.pop_back();
vertex->setBfsInQueue(bfs_index_, false);
return vertex;
}
void
BfsIterator::findNext(Level to_level)
{
while (levelLessOrEqual(first_level_, last_level_)
&& levelLessOrEqual(first_level_, to_level)) {
VertexSeq &level_vertices = queue_[first_level_];
// Skip null entries from deleted vertices.
while (!level_vertices.empty()) {
Vertex *vertex = level_vertices.back();
if (vertex == nullptr)
level_vertices.pop_back();
else {
checkLevel(vertex, first_level_);
return;
}
}
incrLevel(first_level_);
}
}
////////////////////////////////////////////////////////////////
BfsFwdIterator::BfsFwdIterator(BfsIndex bfs_index,
SearchPred *search_pred,
StaState *sta) :
@ -375,15 +372,46 @@ BfsFwdIterator::levelLess(Level level1,
}
void
BfsFwdIterator::enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred)
BfsFwdIterator::enqueueFanout(Vertex *vertex)
{
if (search_pred->searchFrom(vertex)) {
if (search_pred_->searchFrom(vertex)) {
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *to_vertex = edge->to(graph_);
if (search_pred->searchThru(edge) && search_pred->searchTo(to_vertex))
if (search_pred_->searchThru(edge)
&& search_pred_->searchTo(to_vertex))
enqueue(to_vertex);
}
}
}
void
BfsFwdIterator::enqueueFanout(Vertex *vertex,
const Mode *mode)
{
if (search_pred_->searchFrom(vertex, mode)) {
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *to_vertex = edge->to(graph_);
if (search_pred_->searchThru(edge, mode)
&& search_pred_->searchTo(to_vertex, mode))
enqueue(to_vertex);
}
}
}
void
BfsFwdIterator::enqueueAdjacentVertices(Vertex *vertex)
{
if (search_pred_->searchFrom(vertex)) {
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *to_vertex = edge->to(graph_);
if (search_pred_->searchThru(edge)
&& search_pred_->searchTo(to_vertex))
enqueue(to_vertex);
}
}
@ -391,16 +419,15 @@ BfsFwdIterator::enqueueAdjacentVertices(Vertex *vertex,
void
BfsFwdIterator::enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred,
const Mode *mode)
{
if (search_pred->searchFrom(vertex, mode)) {
if (search_pred_->searchFrom(vertex, mode)) {
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *to_vertex = edge->to(graph_);
if (search_pred->searchThru(edge, mode)
&& search_pred->searchTo(to_vertex, mode))
if (search_pred_->searchThru(edge, mode)
&& search_pred_->searchTo(to_vertex, mode))
enqueue(to_vertex);
}
}
@ -443,15 +470,15 @@ BfsBkwdIterator::levelLess(Level level1,
}
void
BfsBkwdIterator::enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred)
BfsBkwdIterator::enqueueAdjacentVertices(Vertex *vertex)
{
if (search_pred->searchTo(vertex)) {
if (search_pred_->searchTo(vertex)) {
VertexInEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *from_vertex = edge->from(graph_);
if (search_pred->searchFrom(from_vertex) && search_pred->searchThru(edge))
if (search_pred_->searchFrom(from_vertex)
&& search_pred_->searchThru(edge))
enqueue(from_vertex);
}
}
@ -459,16 +486,46 @@ BfsBkwdIterator::enqueueAdjacentVertices(Vertex *vertex,
void
BfsBkwdIterator::enqueueAdjacentVertices(Vertex *vertex,
SearchPred *search_pred,
const Mode *mode)
{
if (search_pred->searchTo(vertex, mode)) {
if (search_pred_->searchTo(vertex, mode)) {
VertexInEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *from_vertex = edge->from(graph_);
if (search_pred->searchFrom(from_vertex, mode)
&& search_pred->searchThru(edge, mode))
if (search_pred_->searchFrom(from_vertex, mode)
&& search_pred_->searchThru(edge, mode))
enqueue(from_vertex);
}
}
}
void
BfsBkwdIterator::enqueueFanin(Vertex *vertex)
{
if (search_pred_->searchTo(vertex)) {
VertexInEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *from_vertex = edge->from(graph_);
if (search_pred_->searchFrom(from_vertex)
&& search_pred_->searchThru(edge))
enqueue(from_vertex);
}
}
}
void
BfsBkwdIterator::enqueueFanin(Vertex *vertex,
const Mode *mode)
{
if (search_pred_->searchTo(vertex, mode)) {
VertexInEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *from_vertex = edge->from(graph_);
if (search_pred_->searchFrom(from_vertex, mode)
&& search_pred_->searchThru(edge, mode))
enqueue(from_vertex);
}
}

View File

@ -24,7 +24,8 @@
#include "ClkNetwork.hh"
#include "Bfs.hh"
#include <queue>
#include "Debug.hh"
#include "Graph.hh"
#include "Mode.hh"
@ -127,7 +128,6 @@ ClkNetwork::findClkPins(bool ideal_only,
{
const Sdc *sdc = mode_->sdc();
ClkSearchPred srch_pred(this);
BfsFwdIterator bfs(BfsIndex::other, &srch_pred, this);
for (Clock *clk : sdc->clocks()) {
if (!ideal_only
|| !clk->isPropagated()) {
@ -136,25 +136,39 @@ ClkNetwork::findClkPins(bool ideal_only,
clk_pins = new PinSet(network_);
clk_pins_map_[clk] = clk_pins;
}
std::queue<Vertex *> queue;
VertexSet visited = makeVertexSet(this);
auto enqueue = [&queue, &visited] (Vertex *vertex) {
if (vertex && !visited.contains(vertex)) {
visited.insert(vertex);
queue.push(vertex);
}
};
for (const Pin *pin : clk->leafPins()) {
if (!ideal_only
|| !sdc->isPropagatedClock(pin)) {
Vertex *vertex, *bidirect_drvr_vertex;
graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
bfs.enqueue(vertex);
if (bidirect_drvr_vertex)
bfs.enqueue(bidirect_drvr_vertex);
enqueue(vertex);
enqueue(bidirect_drvr_vertex);
}
}
while (bfs.hasNext()) {
Vertex *vertex = bfs.next();
while (!queue.empty()) {
Vertex *vertex = queue.front();
queue.pop();
const Pin *pin = vertex->pin();
if (!ideal_only
|| !sdc->isPropagatedClock(pin)) {
clk_pins->insert(pin);
ClockSet &pin_clks = pin_clks_map[pin];
pin_clks.insert(clk);
bfs.enqueueAdjacentVertices(vertex);
graph_->visitFanouts(vertex, &srch_pred,
[&queue, &visited] (Vertex *fanout) {
if (!visited.contains(fanout)) {
visited.insert(fanout);
queue.push(fanout);
}
});
}
}
}

View File

@ -271,7 +271,6 @@ Genclks::ensureMaster(Clock *gclk,
// Search backward from generated clock source pin to a clock pin.
GenClkMasterSearchPred srch_pred(this);
VertexQueue master_queue;
VertexSet visited = makeVertexSet(this);
VertexSet src_vertices = makeVertexSet(this);
gclk->srcPinVertices(src_vertices, network_, graph_);
for (Vertex *vertex : src_vertices)
@ -279,28 +278,25 @@ Genclks::ensureMaster(Clock *gclk,
while (!master_queue.empty()) {
Vertex *vertex = master_queue.front();
master_queue.pop();
if (!visited.contains(vertex)) {
visited.insert(vertex);
Pin *pin = vertex->pin();
if (sdc->isLeafPinClock(pin)) {
ClockSet *master_clks = sdc->findLeafPinClocks(pin);
if (master_clks) {
ClockSet::iterator master_iter = master_clks->begin();
if (master_iter != master_clks->end()) {
master_clk = *master_iter++;
// Master source pin can actually be a clock source pin.
if (master_clk != gclk) {
gclk->setInferedMasterClk(master_clk);
debugPrint(debug_, "genclk", 2, " {} master clk {}", gclk->name(),
master_clk->name());
master_clk_count++;
break;
}
Pin *pin = vertex->pin();
if (sdc->isLeafPinClock(pin)) {
ClockSet *master_clks = sdc->findLeafPinClocks(pin);
if (master_clks) {
ClockSet::iterator master_iter = master_clks->begin();
if (master_iter != master_clks->end()) {
master_clk = *master_iter++;
// Master source pin can actually be a clock source pin.
if (master_clk != gclk) {
gclk->setInferedMasterClk(master_clk);
debugPrint(debug_, "genclk", 2, " {} master clk {}", gclk->name(),
master_clk->name());
master_clk_count++;
break;
}
}
}
enqueueFanin(vertex, master_queue, srch_pred);
}
enqueueFanin(vertex, master_queue, srch_pred);
}
}
if (master_clk_count > 1)

View File

@ -30,6 +30,7 @@
#include "Bfs.hh"
#include "ClkInfo.hh"
#include "ClkNetwork.hh"
#include "Clock.hh"
#include "ContainerHelpers.hh"
#include "Crpr.hh"
@ -263,8 +264,7 @@ Search::Search(StaState *sta) :
tag_group_capacity_(tag_capacity_),
tag_groups_(new TagGroup *[tag_group_capacity_]),
tag_group_set_(new TagGroupSet(tag_group_capacity_)),
postponed_arrivals_(makeVertexSet(this)),
postponed_clk_endpoints_(makeVertexSet(this)),
pending_arrivals_(makeVertexSet(this)),
endpoints_(makeVertexSet(this)),
invalid_endpoints_(makeVertexSet(this)),
@ -328,8 +328,7 @@ Search::clear()
deletePathGroups();
deletePaths();
deleteTags();
postponed_arrivals_.clear();
postponed_clk_endpoints_.clear();
pending_arrivals_.clear();
deleteFilter();
found_downstream_clk_pins_ = false;
}
@ -546,7 +545,7 @@ Search::findFilteredArrivals(ExceptionFrom *from,
// These cases do not require filtered arrivals.
// -from clocks
// -to
findAllArrivals(thru_latches, false);
findAllArrivals(thru_latches);
}
// From/thrus/to are used to make a filter exception. If the last
@ -639,32 +638,36 @@ Search::deleteFilterClkInfos()
void
Search::findFilteredArrivals(bool thru_latches)
{
filtered_arrivals_.clear();
findArrivalsSeed();
seedFilterStarts();
Level max_level = levelize_->maxLevel();
// Search always_to_endpoint to search from exisiting arrivals at
// fanin startpoints to reach -thru/-to endpoints.
arrival_visitor_->init(true, false, eval_pred_);
enqueuePendingClkFanouts();
bool have_pending_latch_outputs = false;
// Iterate until data arrivals at all latches stop changing.
arrival_iter_->ensureSize();
filtered_arrivals_.clear();
findArrivalsSeed();
seedFilterStarts();
Level max_level = levelize_->maxLevel();
bool have_pending_arrivals = false;
for (int pass = 1;
pass == 1 || (thru_latches && have_pending_latch_outputs);
pass == 1 || (thru_latches && have_pending_arrivals);
pass++) {
debugPrint(debug_, "search", 1, "find arrivals pass {}", pass);
int arrival_count = arrival_iter_->visitParallel(max_level, arrival_visitor_);
debugPrint(debug_, "search", 1, "found {} arrivals", arrival_count);
have_pending_latch_outputs = !postponed_arrivals_.empty();
for (Vertex *latch_output : postponed_arrivals_)
arrival_visitor_->visit(latch_output, true);
postponed_arrivals_.clear();
// Latch D->Q and disabled loop edges have level discontinuities so their
// eval. For latches the data path crpr clk path may be evaled in another
// thread at the same time the latch D->Q edge.
// Disabled loop edges propagate pending loop paths here.
have_pending_arrivals = !pending_arrivals_.empty();
for (Vertex *vertex : pending_arrivals_)
arrival_visitor_->visit(vertex, true);
pending_arrivals_.clear();
deleteTagsPrev();
}
arrivals_exist_ = true;
}
// Delete stale tag arrarys.
@ -860,14 +863,13 @@ void
Search::levelsChangedBefore()
{
if (arrivals_exist_) {
while (arrival_iter_->hasNext()) {
Vertex *vertex = arrival_iter_->next();
arrival_iter_->clear([this] (Vertex *vertex) {
arrivalInvalid(vertex);
}
while (required_iter_->hasNext()) {
Vertex *vertex = required_iter_->next();
});
required_iter_->clear([this] (Vertex *vertex) {
requiredInvalid(vertex);
}
});
}
}
@ -939,11 +941,16 @@ Search::requiredInvalid(Vertex *vertex)
void
Search::findClkArrivals()
{
findAllArrivals(false, true);
debugPrint(debug_, "search", 1, "find clk arrivals");
arrival_visitor_->init(false, true, eval_pred_);
arrival_iter_->ensureSize();
enqueueClkRoots();
enqueueInvalidClks();
findArrivals2(levelize_->maxLevel());
}
void
Search::seedClkVertexArrivals()
Search::enqueueClkRoots()
{
PinSet clk_pins(network_);
findClkVertexPins(clk_pins);
@ -954,6 +961,32 @@ Search::seedClkVertexArrivals()
if (bidirect_drvr_vertex)
arrival_iter_->enqueue(bidirect_drvr_vertex);
}
arrivals_exist_ = true;
}
void
Search::enqueueInvalidClks()
{
if (!invalid_arrivals_.empty()) {
for (Mode *mode : modes_)
mode->clkNetwork()->ensureClkNetwork();
for (auto itr = invalid_arrivals_.begin(); itr != invalid_arrivals_.end();) {
Vertex *vertex = *itr;
bool is_clk = false;
for (Mode *mode : modes_) {
if (mode->clkNetwork()->isClock(vertex)) {
is_clk = true;
break;
}
}
if (is_clk) {
arrival_iter_->enqueue(vertex);
itr = invalid_arrivals_.erase(itr);
}
else
itr++;
}
}
}
Arrival
@ -980,51 +1013,31 @@ Search::clockInsertion(const Clock *clk,
void
Search::findAllArrivals()
{
findAllArrivals(true, false);
findAllArrivals(true);
}
void
Search::findAllArrivals(bool thru_latches,
bool clks_only)
Search::findAllArrivals(bool thru_latches)
{
if (!clks_only)
enqueuePendingClkFanouts();
arrival_visitor_->init(false, clks_only, eval_pred_);
bool have_pending_latch_outputs = false;
arrival_visitor_->init(false, false, eval_pred_);
arrival_iter_->ensureSize();
bool have_pending_arrivals = false;
// Iterate until data arrivals at all latches stop changing.
for (int pass = 1;
pass == 1 || (thru_latches && have_pending_latch_outputs);
pass == 1 || (thru_latches && have_pending_arrivals);
pass++) {
debugPrint(debug_, "search", 1, "find arrivals pass {}", pass);
findArrivals1(levelize_->maxLevel());
have_pending_latch_outputs = !postponed_arrivals_.empty();
for (Vertex *latch_output : postponed_arrivals_)
arrival_visitor_->visit(latch_output, true);
postponed_arrivals_.clear();
have_pending_arrivals = !pending_arrivals_.empty();
for (Vertex *vertex : pending_arrivals_)
arrival_visitor_->visit(vertex, true);
pending_arrivals_.clear();
}
}
// Pick up where the search stopped at the clock network boundary.
void
Search::enqueuePendingClkFanouts()
{
for (Vertex *vertex : postponed_clk_endpoints_) {
debugPrint(debug_, "search", 2, "enqueue clk fanout {}",
vertex->to_string(this));
arrival_iter_->enqueueAdjacentVertices(vertex, search_adj_);
}
postponed_clk_endpoints_.clear();
}
void
Search::postponeClkFanouts(Vertex *vertex)
{
LockGuard lock(postponed_clk_endpoints_lock_);
postponed_clk_endpoints_.insert(vertex);
}
void
Search::findArrivals()
{
@ -1035,6 +1048,7 @@ void
Search::findArrivals(Level level)
{
arrival_visitor_->init(false, false, eval_pred_);
arrival_iter_->ensureSize();
findArrivals1(level);
}
@ -1043,13 +1057,19 @@ Search::findArrivals1(Level level)
{
debugPrint(debug_, "search", 1, "find arrivals to level {}", level);
findArrivalsSeed();
findArrivals2(level);
}
// Caller seeds arrival_iter_.
void
Search::findArrivals2(Level level)
{
Stats stats(debug_, report_);
int arrival_count = arrival_iter_->visitParallel(level, arrival_visitor_);
deleteTagsPrev();
if (arrival_count > 0)
deleteUnusedTagGroups();
stats.report("Find arrivals");
arrivals_exist_ = true;
debugPrint(debug_, "search", 1, "found {} arrivals", arrival_count);
}
@ -1059,15 +1079,9 @@ Search::findArrivalsSeed()
if (!arrivals_seeded_) {
for (const Mode *mode : modes_)
mode->genclks()->ensureInsertionDelays();
arrival_iter_->clear();
required_iter_->clear();
seedArrivals();
arrivals_seeded_ = true;
}
else {
arrival_iter_->ensureSize();
required_iter_->ensureSize();
}
seedInvalidArrivals();
}
@ -1173,22 +1187,18 @@ ArrivalVisitor::visit(Vertex *vertex,
search_->postponeLatchDataOutputs(vertex);
if ((always_to_endpoints_ || arrivals_changed)) {
if (clks_only_ && vertex->isRegClk()) {
debugPrint(debug_, "search", 3, "postponing clk fanout");
search_->postponeClkFanouts(vertex);
}
else {
graph_->visitFanoutEdges(vertex, search_adj_,
[this] (Edge *edge,
Vertex *fanout) {
if (edge->isDisabledLoop()) {
if (hasPendingLoopPaths(edge))
search_->postponeArrivals(fanout);
}
else
search_->arrivalIterator()->enqueue(fanout);
});
}
graph_->visitFanoutEdges(vertex, search_adj_,
[this, vertex] (Edge *edge,
Vertex *fanout) {
if (edge->isDisabledLoop()) {
if (hasPendingLoopPaths(edge))
search_->postponeArrivals(fanout);
}
else if (clks_only_ && vertex->isRegClk())
search_->arrivalInvalid(fanout);
else
search_->arrivalIterator()->enqueue(fanout);
});
}
if (arrivals_changed) {
debugPrint(debug_, "search", 4, "arrivals changed");
@ -1425,8 +1435,8 @@ Search::postponeLatchDataOutputs(Vertex *latch_data)
Edge *edge = edge_iter.next();
if (edge->role() == TimingRole::latchDtoQ()) {
Vertex *out_vertex = edge->to(graph_);
LockGuard lock(postponed_arrivals_lock_);
postponed_arrivals_.insert(out_vertex);
LockGuard lock(pending_arrivals_lock_);
pending_arrivals_.insert(out_vertex);
}
}
}
@ -1434,8 +1444,8 @@ Search::postponeLatchDataOutputs(Vertex *latch_data)
void
Search::postponeArrivals(Vertex *vertex)
{
LockGuard lock(postponed_arrivals_lock_);
postponed_arrivals_.insert(vertex);
LockGuard lock(pending_arrivals_lock_);
pending_arrivals_.insert(vertex);
}
void
@ -1448,6 +1458,7 @@ Search::seedArrivals()
for (Vertex *vertex : vertices)
arrival_iter_->enqueue(vertex);
arrivals_exist_ = true;
}
void
@ -3160,6 +3171,7 @@ void
Search::seedRequireds()
{
ensureDownstreamClkPins();
required_iter_->ensureSize();
for (Vertex *vertex : endpoints())
seedRequired(vertex);
requireds_seeded_ = true;
@ -3334,8 +3346,9 @@ Search::seedRequired(Vertex *vertex)
required_cmp.requiredsInit(vertex, this);
visit_path_ends_->visitPathEnds(vertex, &seeder);
// Enqueue fanin vertices for back-propagating required times.
required_iter_->ensureSize();
if (required_cmp.requiredsSave(vertex, this))
required_iter_->enqueueAdjacentVertices(vertex);
required_iter_->enqueueFanin(vertex);
}
void
@ -3347,7 +3360,7 @@ Search::seedRequiredEnqueueFanin(Vertex *vertex)
visit_path_ends_->visitPathEnds(vertex, &seeder);
// Enqueue fanin vertices for back-propagating required times.
required_cmp.requiredsSave(vertex, this);
required_iter_->enqueueAdjacentVertices(vertex);
required_iter_->enqueueFanin(vertex);
}
////////////////////////////////////////////////////////////////
@ -3455,7 +3468,7 @@ RequiredVisitor::visit(Vertex *vertex)
search_->tnsInvalid(vertex);
if (changed)
search_->requiredIterator()->enqueueAdjacentVertices(vertex);
search_->requiredIterator()->enqueueFanin(vertex);
}
bool
@ -3538,17 +3551,27 @@ void
Search::ensureDownstreamClkPins()
{
if (!found_downstream_clk_pins_) {
// Use backward BFS from register clk pins to mark upsteam pins
// as having downstream clk pins.
// Use backward DFS from register clk pins to mark upstream pins
// as having downstream clk pins. hasDownstreamClkPin doubles as the
// visited flag since its meaning is exactly "reached here".
ClkTreeSearchPred pred(this);
BfsBkwdIterator iter(BfsIndex::other, &pred, this);
for (Vertex *vertex : graph_->regClkVertices())
iter.enqueue(vertex);
while (iter.hasNext()) {
Vertex *vertex = iter.next();
vertex->setHasDownstreamClkPin(true);
iter.enqueueAdjacentVertices(vertex);
std::vector<Vertex*> stack;
for (Vertex *vertex : graph_->regClkVertices()) {
if (!vertex->hasDownstreamClkPin()) {
vertex->setHasDownstreamClkPin(true);
stack.push_back(vertex);
}
}
while (!stack.empty()) {
Vertex *vertex = stack.back();
stack.pop_back();
graph_->visitFanins(vertex, &pred,
[&stack] (Vertex *fanin) {
if (!fanin->hasDownstreamClkPin()) {
fanin->setHasDownstreamClkPin(true);
stack.push_back(fanin);
}
});
}
}
found_downstream_clk_pins_ = true;