Skip to content

Commit f2db044

Browse files
authored
Merge branch 'parallaxsw:master' into main
2 parents 72bcca9 + 2f26c1e commit f2db044

20 files changed

Lines changed: 465 additions & 258 deletions

.cursor/rules/cpp-coding-standards.mdc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ alwaysApply: true
3434
- Prefer `std::string` over `char*` for string members.
3535
- Prefer pass-by-value and move for sink parameters (parameters that get stored).
3636

37+
## Control flow
38+
39+
- Prefer positive `if` conditions that wrap the main logic instead of early
40+
`continue` or `return` to skip work.
41+
- Example: use `if (!visited.contains(vertex)) { ... }` rather than
42+
`if (visited.contains(vertex)) continue;`.
43+
3744
## File Extensions
3845

3946
- C++ source: `.cc`

dcalc/GraphDelayCalc.cc

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ GraphDelayCalc::delayInvalid(Vertex *vertex)
248248
{
249249
debugPrint(debug_, "delay_calc", 2, "delay invalid {}",
250250
vertex->to_string(this));
251-
if (graph_ && incremental_) {
251+
if (incremental_) {
252252
invalid_delays_.insert(vertex);
253253
// Invalidate driver that triggers dcalc for multi-driver nets.
254254
MultiDrvrNet *multi_drvr = multiDrvrNet(vertex);
@@ -338,40 +338,38 @@ FindVertexDelays::visit(Vertex *vertex)
338338
void
339339
GraphDelayCalc::findDelays(Level level)
340340
{
341-
if (arc_delay_calc_) {
342-
Stats stats(debug_, report_);
343-
int dcalc_count = 0;
344-
debugPrint(debug_, "delay_calc", 1, "find delays to level {}", level);
345-
if (!delays_seeded_) {
346-
iter_->clear();
347-
seedRootSlews();
348-
delays_seeded_ = true;
349-
}
350-
else
351-
iter_->ensureSize();
352-
if (incremental_)
353-
seedInvalidDelays();
341+
Stats stats(debug_, report_);
342+
int dcalc_count = 0;
343+
debugPrint(debug_, "delay_calc", 1, "find delays to level {}", level);
344+
if (!delays_seeded_) {
345+
iter_->clear();
346+
seedRootSlews();
347+
delays_seeded_ = true;
348+
}
349+
else
350+
iter_->ensureSize();
351+
if (incremental_)
352+
seedInvalidDelays();
354353

355-
if (!iter_->empty()) {
356-
FindVertexDelays visitor(this);
357-
dcalc_count += iter_->visitParallel(level, &visitor);
358-
}
354+
if (!iter_->empty()) {
355+
FindVertexDelays visitor(this);
356+
dcalc_count += iter_->visitParallel(level, &visitor);
357+
}
359358

360-
// Timing checks require slews at both ends of the arc,
361-
// so find their delays after all slews are known.
362-
for (Edge *check_edge : invalid_check_edges_)
363-
findCheckEdgeDelays(check_edge, arc_delay_calc_);
364-
invalid_check_edges_.clear();
359+
// Timing checks require slews at both ends of the arc,
360+
// so find their delays after all slews are known.
361+
for (Edge *check_edge : invalid_check_edges_)
362+
findCheckEdgeDelays(check_edge, arc_delay_calc_);
363+
invalid_check_edges_.clear();
365364

366-
for (Edge *latch_edge : invalid_latch_edges_)
367-
findLatchEdgeDelays(latch_edge);
368-
invalid_latch_edges_.clear();
365+
for (Edge *latch_edge : invalid_latch_edges_)
366+
findLatchEdgeDelays(latch_edge);
367+
invalid_latch_edges_.clear();
369368

370-
delays_exist_ = true;
371-
incremental_ = true;
372-
debugPrint(debug_, "delay_calc", 1, "found {} delays", dcalc_count);
373-
stats.report("Delay calc");
374-
}
369+
delays_exist_ = true;
370+
incremental_ = true;
371+
debugPrint(debug_, "delay_calc", 1, "found {} delays", dcalc_count);
372+
stats.report("Delay calc");
375373
}
376374

377375
void

doc/ApiChanges.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424

2525
This file summarizes STA API changes for each release.
2626

27+
2026/06/22
28+
----------
29+
30+
Liberty::hasSequentials has been renamed isSequential.
31+
2732
Release 3.1.0 2026/03/25
2833
------------------------
2934

graph/Graph.cc

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "Mutex.hh"
3333
#include "Network.hh"
3434
#include "PortDirection.hh"
35+
#include "SearchPred.hh"
3536
#include "Stats.hh"
3637
#include "TimingArc.hh"
3738
#include "TimingRole.hh"
@@ -487,7 +488,7 @@ Graph::deleteVertex(Vertex *vertex)
487488
EdgeId edge_id, next_id;
488489
for (edge_id = vertex->in_edges_; edge_id; edge_id = next_id) {
489490
Edge *edge = Graph::edge(edge_id);
490-
next_id = edge->vertex_in_link_;
491+
next_id = edge->vertex_in_next_;
491492
deleteOutEdge(edge->from(this), edge);
492493
edge->clear();
493494
edges_->destroy(edge);
@@ -508,7 +509,7 @@ bool
508509
Graph::hasFaninOne(Vertex *vertex) const
509510
{
510511
return vertex->in_edges_
511-
&& edge(vertex->in_edges_)->vertex_in_link_ == 0;
512+
&& edge(vertex->in_edges_)->vertex_in_next_ == 0;
512513
}
513514

514515
void
@@ -519,12 +520,12 @@ Graph::deleteInEdge(Vertex *vertex,
519520
EdgeId prev = 0;
520521
for (EdgeId i = vertex->in_edges_;
521522
i && i != edge_id;
522-
i = Graph::edge(i)->vertex_in_link_)
523+
i = Graph::edge(i)->vertex_in_next_)
523524
prev = i;
524525
if (prev)
525-
Graph::edge(prev)->vertex_in_link_ = edge->vertex_in_link_;
526+
Graph::edge(prev)->vertex_in_next_ = edge->vertex_in_next_;
526527
else
527-
vertex->in_edges_ = edge->vertex_in_link_;
528+
vertex->in_edges_ = edge->vertex_in_next_;
528529
}
529530

530531
void
@@ -574,6 +575,76 @@ Graph::gateEdgeArc(const Pin *in_pin,
574575

575576
////////////////////////////////////////////////////////////////
576577

578+
void
579+
Graph::visitFanouts(Vertex *vertex,
580+
SearchPred *pred,
581+
const VertexFn &fn)
582+
{
583+
if (pred->searchFrom(vertex)) {
584+
for (Edge *edge = this->edge(vertex->out_edges_);
585+
edge;
586+
edge = this->edge(edge->vertex_out_next_)) {
587+
Vertex *to_vertex = this->vertex(edge->to_);
588+
if (pred->searchThru(edge)
589+
&& pred->searchTo(to_vertex))
590+
fn(to_vertex);
591+
}
592+
}
593+
}
594+
595+
void
596+
Graph::visitFanoutEdges(Vertex *vertex,
597+
SearchPred *pred,
598+
const EdgeFn &fn)
599+
{
600+
if (pred->searchFrom(vertex)) {
601+
for (Edge *edge = this->edge(vertex->out_edges_);
602+
edge;
603+
edge = this->edge(edge->vertex_out_next_)) {
604+
Vertex *to_vertex = this->vertex(edge->to_);
605+
if (pred->searchThru(edge)
606+
&& pred->searchTo(to_vertex))
607+
fn(edge, to_vertex);
608+
}
609+
}
610+
}
611+
612+
void
613+
Graph::visitFanins(Vertex *vertex,
614+
SearchPred *pred,
615+
const VertexFn &fn)
616+
{
617+
if (pred->searchFrom(vertex)) {
618+
for (Edge *edge = this->edge(vertex->in_edges_);
619+
edge;
620+
edge = this->edge(edge->vertex_in_next_)) {
621+
Vertex *from_vertex = this->vertex(edge->from_);
622+
if (pred->searchThru(edge)
623+
&& pred->searchFrom(from_vertex))
624+
fn(from_vertex);
625+
}
626+
}
627+
}
628+
629+
void
630+
Graph::visitFaninEdges(Vertex *vertex,
631+
SearchPred *pred,
632+
const EdgeFn &fn)
633+
{
634+
if (pred->searchFrom(vertex)) {
635+
for (Edge *edge = this->edge(vertex->in_edges_);
636+
edge;
637+
edge = this->edge(edge->vertex_in_next_)) {
638+
Vertex *from_vertex = this->vertex(edge->from_);
639+
if (pred->searchThru(edge)
640+
&& pred->searchFrom(from_vertex))
641+
fn(edge, from_vertex);
642+
}
643+
}
644+
}
645+
646+
////////////////////////////////////////////////////////////////
647+
577648
Slew
578649
Graph::slew(const Vertex *vertex,
579650
const RiseFall *rf,
@@ -650,7 +721,7 @@ Graph::makeEdge(Vertex *from,
650721
from->out_edges_ = edge_id;
651722

652723
// Add in edge to to vertex.
653-
edge->vertex_in_link_ = to->in_edges_;
724+
edge->vertex_in_next_ = to->in_edges_;
654725
to->in_edges_ = edge_id;
655726

656727
initArcDelays(edge);
@@ -1213,7 +1284,7 @@ Edge::init(VertexId from,
12131284
from_ = from;
12141285
to_ = to;
12151286
arc_set_ = arc_set;
1216-
vertex_in_link_ = edge_id_null;
1287+
vertex_in_next_ = edge_id_null;
12171288
vertex_out_next_ = edge_id_null;
12181289
vertex_out_prev_ = edge_id_null;
12191290
is_bidirect_inst_path_ = false;
@@ -1464,6 +1535,8 @@ VertexIterator::findNext()
14641535
findNextPin();
14651536
}
14661537

1538+
////////////////////////////////////////////////////////////////
1539+
14671540
VertexInEdgeIterator::VertexInEdgeIterator(Vertex *vertex,
14681541
const Graph *graph) :
14691542
next_(graph->edge(vertex->in_edges_)),
@@ -1483,7 +1556,7 @@ VertexInEdgeIterator::next()
14831556
{
14841557
Edge *next = next_;
14851558
if (next_)
1486-
next_ = graph_->edge(next_->vertex_in_link_);
1559+
next_ = graph_->edge(next_->vertex_in_next_);
14871560
return next;
14881561
}
14891562

include/sta/Graph.hh

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,19 @@ public:
8787
bool hasFaninOne(Vertex *vertex) const;
8888
VertexId vertexCount() { return vertices_->size(); }
8989

90+
void visitFanouts(Vertex *vertex,
91+
SearchPred *pred,
92+
const VertexFn &fn);
93+
void visitFanins(Vertex *vertex,
94+
SearchPred *pred,
95+
const VertexFn &fn);
96+
void visitFanoutEdges(Vertex *vertex,
97+
SearchPred *pred,
98+
const EdgeFn &fn);
99+
void visitFaninEdges(Vertex *vertex,
100+
SearchPred *pred,
101+
const EdgeFn &fn);
102+
90103
// Reported slew are the same as those in the liberty tables.
91104
// reported_slews = measured_slews / slew_derate_from_library
92105
// Measured slews are between slew_lower_threshold and slew_upper_threshold.
@@ -394,7 +407,7 @@ protected:
394407
TimingArcSet *arc_set_;
395408
VertexId from_;
396409
VertexId to_;
397-
EdgeId vertex_in_link_; // Vertex in edges list.
410+
EdgeId vertex_in_next_; // Vertex in edges list.
398411
EdgeId vertex_out_next_; // Vertex out edges doubly linked list.
399412
EdgeId vertex_out_prev_;
400413
float *arc_delays_;

include/sta/GraphClass.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ using Level = int;
6565
using DcalcAPIndex = int;
6666
using TagGroupIndex = int;
6767
using SlewSeq = std::vector<Slew>;
68+
using VertexFn = std::function<void(Vertex*)>;
69+
using EdgeFn = std::function<void(Edge *, Vertex*)>;
6870

6971
static constexpr int level_max = std::numeric_limits<Level>::max();
7072

include/sta/Liberty.hh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,9 @@ public:
543543
bool leakagePowerExists() const { return leakage_power_exists_; }
544544

545545
// Register, Latch or Statetable.
546-
bool hasSequentials() const;
546+
bool isSequential() const;
547+
// deprecated 2026-06-22 (use isSequential)
548+
bool hasSequentials() const __attribute__ ((deprecated));
547549
const SequentialSeq &sequentials() const { return sequentials_; }
548550
// Find the sequential with the output connected to an (internal) port.
549551
Sequential *outputPortSequential(LibertyPort *port);

include/sta/Search.hh

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,8 @@ public:
290290
Vertex *vertex,
291291
const Mode *mode,
292292
TagGroupBldr *tag_bldr);
293-
void enqueueLatchDataOutputs(Vertex *vertex);
294-
void enqueueLatchOutput(Vertex *vertex);
293+
void postponeLatchDataOutputs(Vertex *vertex);
294+
void postponeArrivals(Vertex *vertex);
295295
void enqueuePendingClkFanouts();
296296
void postponeClkFanouts(Vertex *vertex);
297297
void seedRequired(Vertex *vertex);
@@ -596,7 +596,7 @@ protected:
596596

597597
// Search predicates.
598598
SearchPred *search_thru_;
599-
SearchAdj *search_adj_;
599+
SearchPred *search_adj_;
600600
EvalPred *eval_pred_;
601601

602602
// Clock arrivals are known.
@@ -657,11 +657,11 @@ protected:
657657
std::mutex tag_group_lock_;
658658

659659
// Latches data outputs to queue on the next search pass.
660-
VertexSet pending_latch_outputs_;
661-
std::mutex pending_latch_outputs_lock_;
660+
VertexSet postponed_arrivals_;
661+
std::mutex postponed_arrivals_lock_;
662662
// Clock network endpoints where arrival search was suppended by findClkArrivals().
663-
VertexSet pending_clk_endpoints_;
664-
std::mutex pending_clk_endpoints_lock_;
663+
VertexSet postponed_clk_endpoints_;
664+
std::mutex postponed_clk_endpoints_lock_;
665665

666666
VertexSet endpoints_;
667667
bool endpoints_initialized_{false};
@@ -812,6 +812,8 @@ protected:
812812
void pruneCrprArrivals();
813813
void constrainedRequiredsInvalid(Vertex *vertex,
814814
bool is_clk);
815+
bool hasPendingLoopPaths(Edge *edge) const;
816+
815817
bool always_to_endpoints_;
816818
bool always_save_prev_paths_;
817819
bool clks_only_;

include/sta/SearchPred.hh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,19 @@ public:
5151
// Search is allowed from from_vertex.
5252
virtual bool searchFrom(const Vertex *from_vertex,
5353
const Mode *mode) const = 0;
54-
bool searchFrom(const Vertex *from_vertex) const;
54+
virtual bool searchFrom(const Vertex *from_vertex) const;
5555
// Search is allowed through edge.
5656
// from/to pins are NOT checked.
5757
// inst can be either the from_pin or to_pin instance because it
5858
// is only referenced when they are the same (non-wire edge).
5959
virtual bool searchThru(Edge *edge,
6060
const Mode *mode) const = 0;
61-
bool searchThru(Edge *edge) const;
61+
virtual bool searchThru(Edge *edge) const;
6262
// Search is allowed to to_pin.
6363
virtual bool searchTo(const Vertex *to_vertex,
6464
const Mode *mode) const = 0;
65-
bool searchTo(const Vertex *to_vertex) const;
66-
void copyState(const StaState *sta);
65+
virtual bool searchTo(const Vertex *to_vertex) const;
66+
virtual void copyState(const StaState *sta);
6767

6868
protected:
6969
const StaState *sta_;

include/sta/Sta.hh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1575,7 +1575,6 @@ protected:
15751575
bool infer_latches);
15761576
void delayCalcPreamble();
15771577
void delaysInvalidFrom(const Port *port);
1578-
void delaysInvalidFromFanin(const Port *port);
15791578
void deleteEdge(Edge *edge);
15801579
void netParasiticCaps(Net *net,
15811580
const RiseFall *rf,

0 commit comments

Comments
 (0)