eval latches out of bfs

Signed-off-by: James Cherry <cherry@CerezoBook.local>
This commit is contained in:
James Cherry 2026-06-17 19:54:36 -07:00
parent 9e39e42703
commit 1c6ab172e2
3 changed files with 49 additions and 59 deletions

View File

@ -75,6 +75,8 @@ using ExceptionPathSeq = std::vector<ExceptionPath*>;
class Search : public StaState
{
public:
bool postpone_latch_outputs_{false};
Search(StaState *sta);
~Search() override;
void copyState(const StaState *sta) override;
@ -530,9 +532,6 @@ protected:
const MinMax *min_max) const;
void seedRequireds();
void seedInvalidRequireds();
[[nodiscard]] bool havePendingLatchOutputs();
void clearPendingLatchOutputs();
void enqueuePendingLatchOutputs();
void findFilteredArrivals(bool thru_latches);
void findArrivalsSeed();
void seedFilterStarts();
@ -669,7 +668,6 @@ protected:
std::mutex filtered_arrivals_lock_;
bool found_downstream_clk_pins_{false};
bool postpone_latch_outputs_{false};
std::vector<Path*> enum_paths_;
VisitPathEnds *visit_path_ends_;

View File

@ -356,7 +356,9 @@ PathEnumFaninVisitor::visitFaninPathsThru(Path *before_div,
prev_vertex_ = prev_vertex;
visited_fanins_.clear();
unique_edge_divs_.clear();
search_->postpone_latch_outputs_ = false;
visitFaninPaths(before_div_->vertex(this));
search_->postpone_latch_outputs_ = true;
if (unique_edges_) {
for (auto [vertex_edge, div] : unique_edge_divs_)
@ -422,6 +424,14 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
Arrival & /* to_arrival */,
const MinMax *)
{
debugPrint(debug_, "path_enum", 3, "visit fanin {} -> {} {} {}",
from_path->to_string(this),
to_vertex->to_string(this), to_rf->shortName(),
delayAsString(
search_->deratedDelay(
from_vertex, arc, edge, false, from_path->minMax(this),
from_path->dcalcAnalysisPtIndex(this), from_path->sdc(this)),
this));
// These paths fanin to before_div_ so we know to_vertex matches.
if ((!unique_pins_ || from_vertex != prev_vertex_)
&& (!unique_edges_ || from_vertex != prev_vertex_

View File

@ -326,7 +326,7 @@ Search::clear()
deletePathGroups();
deletePaths();
deleteTags();
clearPendingLatchOutputs();
pending_latch_outputs_.clear();
pending_clk_endpoints_.clear();
deleteFilter();
found_downstream_clk_pins_ = false;
@ -644,18 +644,26 @@ Search::findFilteredArrivals(bool thru_latches)
// Search always_to_endpoint to search from exisiting arrivals at
// fanin startpoints to reach -thru/-to endpoints.
arrival_visitor_->init(true, false, eval_pred_);
// Iterate until data arrivals at all latches stop changing.
postpone_latch_outputs_ = true;
enqueuePendingClkFanouts();
for (int pass = 1; pass == 1 || (thru_latches && havePendingLatchOutputs());
postpone_latch_outputs_ = true;
bool have_pending_latch_outputs = false;
// Iterate until data arrivals at all latches stop changing.
for (int pass = 1;
pass == 1 || (thru_latches && have_pending_latch_outputs);
pass++) {
if (thru_latches)
enqueuePendingLatchOutputs();
debugPrint(debug_, "search", 1, "find arrivals pass {}", pass);
int arrival_count = arrival_iter_->visitParallel(max_level, arrival_visitor_);
deleteTagsPrev();
debugPrint(debug_, "search", 1, "found {} arrivals", arrival_count);
have_pending_latch_outputs = !pending_latch_outputs_.empty();
postpone_latch_outputs_ = false;
for (Vertex *latch_vertex : pending_latch_outputs_)
arrival_visitor_->visit(latch_vertex);
pending_latch_outputs_.clear();
postpone_latch_outputs_ = true;
deleteTagsPrev();
}
arrivals_exist_ = true;
}
@ -983,41 +991,23 @@ Search::findAllArrivals(bool thru_latches,
if (!clks_only)
enqueuePendingClkFanouts();
arrival_visitor_->init(false, clks_only, eval_pred_);
// Iterate until data arrivals at all latches stop changing.
postpone_latch_outputs_ = true;
for (int pass = 1; pass == 1 || (thru_latches && havePendingLatchOutputs());
bool have_pending_latch_outputs = false;
// Iterate until data arrivals at all latches stop changing.
for (int pass = 1; pass == 1 || (thru_latches && have_pending_latch_outputs);
pass++) {
enqueuePendingLatchOutputs();
debugPrint(debug_, "search", 1, "find arrivals pass {}", pass);
findArrivals1(levelize_->maxLevel());
if (pass > 2)
postpone_latch_outputs_ = false;
have_pending_latch_outputs = !pending_latch_outputs_.empty();
postpone_latch_outputs_ = false;
for (Vertex *latch_vertex : pending_latch_outputs_)
arrival_visitor_->visit(latch_vertex);
pending_latch_outputs_.clear();
postpone_latch_outputs_ = true;
}
}
bool
Search::havePendingLatchOutputs()
{
return !pending_latch_outputs_.empty();
}
void
Search::clearPendingLatchOutputs()
{
pending_latch_outputs_.clear();
}
void
Search::enqueuePendingLatchOutputs()
{
for (Vertex *latch_vertex : pending_latch_outputs_) {
debugPrint(debug_, "search", 2, "enqueue latch output {}",
latch_vertex->to_string(this));
arrival_iter_->enqueue(latch_vertex);
}
clearPendingLatchOutputs();
}
void
Search::enqueuePendingClkFanouts()
{
@ -1148,6 +1138,17 @@ ArrivalVisitor::visit(Vertex *vertex)
{
debugPrint(debug_, "search", 2, "find arrivals {}",
vertex->to_string(this));
if (search_->postponeLatchOutputs()) {
VertexInEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
if (edge->role()->isLatchDtoQ()) {
search_->enqueueLatchOutput(edge->to(graph_));
return;
}
}
}
Pin *pin = vertex->pin();
tag_bldr_->init(vertex);
has_fanin_one_ = graph_->hasFaninOne(vertex);
@ -2139,26 +2140,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
}
else if (edge->role() == TimingRole::latchDtoQ()) {
if (min_max == MinMax::max() && clk) {
bool postponed = false;
if (search_->postponeLatchOutputs()) {
const Path *from_clk_path = from_clk_info->crprClkPath(this);
if (from_clk_path) {
Vertex *d_clk_vertex = from_clk_path->vertex(this);
Level d_clk_level = d_clk_vertex->level();
Level q_level = to_vertex->level();
if (d_clk_level >= q_level) {
// Crpr clk path on latch data input is required to find Q
// arrival. If the data clk path level is >= Q level the
// crpr clk path prev_path pointers are not complete.
debugPrint(debug_, "search", 3, "postponed latch eval {} {} -> {} {}",
d_clk_level, d_clk_vertex->to_string(this),
edge->to_string(this), q_level);
postponed = true;
search_->enqueueLatchOutput(to_vertex);
}
}
}
if (!postponed) {
if (!search_->postponeLatchOutputs()) {
arc_delay = search_->deratedDelay(from_vertex, arc, edge, false, min_max,
dcalc_ap, sdc);
latches_->latchOutArrival(from_path, arc, edge, to_tag, arc_delay,