Merge remote-tracking branch 'upstream/master'

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
Matt Liberty 2025-09-03 23:00:11 +00:00
commit e475ee2c98
24 changed files with 981 additions and 880 deletions

View File

@ -263,12 +263,16 @@ protected:
// Driver parameter Newton-Raphson state. // Driver parameter Newton-Raphson state.
int nr_order_; int nr_order_;
double *x_;
double *fvec_; static constexpr int max_nr_order_ = 3;
double **fjac_;
double *scale_; double x_[max_nr_order_];
double *p_; double fvec_[max_nr_order_];
int *index_; double fjac_storage_[max_nr_order_ * max_nr_order_];
double *fjac_[max_nr_order_];
double scale_[max_nr_order_];
double p_[max_nr_order_ ];
int index_[max_nr_order_];
// Driver slew used to check load delay. // Driver slew used to check load delay.
double drvr_slew_; double drvr_slew_;
@ -288,27 +292,12 @@ DmpAlg::DmpAlg(int nr_order,
c1_(0.0), c1_(0.0),
nr_order_(nr_order) nr_order_(nr_order)
{ {
x_ = new double[nr_order_];
fvec_ = new double[nr_order_];
scale_ = new double[nr_order_];
p_ = new double[nr_order_];
fjac_ = new double*[nr_order_];
for (int i = 0; i < nr_order_; i++) for (int i = 0; i < nr_order_; i++)
fjac_[i] = new double[nr_order_]; // Only use the upper left block of the matrix
index_ = new int[nr_order_]; fjac_[i] = fjac_storage_ + i * max_nr_order_;
} }
DmpAlg::~DmpAlg() DmpAlg::~DmpAlg() = default;
{
delete [] x_;
delete [] fvec_;
delete [] scale_;
delete [] p_;
for (int i = 0; i < nr_order_; i++)
delete [] fjac_[i];
delete [] fjac_;
delete [] index_;
}
void void
DmpAlg::init(const LibertyLibrary *drvr_library, DmpAlg::init(const LibertyLibrary *drvr_library,

View File

@ -260,8 +260,10 @@ GraphDelayCalc::findDelays(Level level)
if (incremental_) if (incremental_)
seedInvalidDelays(); seedInvalidDelays();
FindVertexDelays visitor(this); if (!iter_->empty()) {
dcalc_count += iter_->visitParallel(level, &visitor); FindVertexDelays visitor(this);
dcalc_count += iter_->visitParallel(level, &visitor);
}
// Timing checks require slews at both ends of the arc, // Timing checks require slews at both ends of the arc,
// so find their delays after all slews are known. // so find their delays after all slews are known.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -375,6 +375,8 @@ public:
virtual const TimingRole *checkRole(const StaState *sta) const; virtual const TimingRole *checkRole(const StaState *sta) const;
virtual Required requiredTime(const StaState *sta) const; virtual Required requiredTime(const StaState *sta) const;
virtual Arrival borrow(const StaState *sta) const; virtual Arrival borrow(const StaState *sta) const;
virtual float targetClkTime(const StaState *sta) const;
virtual float targetClkOffset(const StaState *sta) const;
Arrival targetClkWidth(const StaState *sta) const; Arrival targetClkWidth(const StaState *sta) const;
virtual int exceptPathCmp(const PathEnd *path_end, virtual int exceptPathCmp(const PathEnd *path_end,
const StaState *sta) const; const StaState *sta) const;

View File

@ -356,7 +356,8 @@ public:
TagGroup *tagGroup(const Vertex *vertex) const; TagGroup *tagGroup(const Vertex *vertex) const;
TagGroup *tagGroup(TagGroupIndex index) const; TagGroup *tagGroup(TagGroupIndex index) const;
void reportArrivals(Vertex *vertex) const; void reportArrivals(Vertex *vertex,
bool report_tag_index) const;
Slack wnsSlack(Vertex *vertex, Slack wnsSlack(Vertex *vertex,
PathAPIndex path_ap_index); PathAPIndex path_ap_index);
void levelsChangedBefore(); void levelsChangedBefore();
@ -410,6 +411,7 @@ public:
TagGroupIndex tag_index); TagGroupIndex tag_index);
void checkPrevPaths() const; void checkPrevPaths() const;
void deletePaths(Vertex *vertex); void deletePaths(Vertex *vertex);
void deleteTagGroup(TagGroup *group);
protected: protected:
void init(StaState *sta); void init(StaState *sta);
@ -645,6 +647,7 @@ protected:
// Capacity of tag_groups_. // Capacity of tag_groups_.
TagGroupIndex tag_group_capacity_; TagGroupIndex tag_group_capacity_;
std::mutex tag_group_lock_; std::mutex tag_group_lock_;
std::mutex tag_group_ref_count_lock_;
// Latches data outputs to queue on the next search pass. // Latches data outputs to queue on the next search pass.
VertexSet *pending_latch_outputs_; VertexSet *pending_latch_outputs_;
std::mutex pending_latch_outputs_lock_; std::mutex pending_latch_outputs_lock_;

View File

@ -559,6 +559,8 @@ LibertyReader::defineVisitors()
defineGroupVisitor("ecsm_waveform", &LibertyReader::beginEcsmWaveform, defineGroupVisitor("ecsm_waveform", &LibertyReader::beginEcsmWaveform,
&LibertyReader::endEcsmWaveform); &LibertyReader::endEcsmWaveform);
defineGroupVisitor("ecsm_waveform_set", &LibertyReader::beginEcsmWaveform,
&LibertyReader::endEcsmWaveform);
} }
void void

View File

@ -303,12 +303,14 @@ BfsIterator::checkInQueue(Vertex *vertex)
if (vertex->bfsInQueue(bfs_index_)) if (vertex->bfsInQueue(bfs_index_))
return; return;
else else
printf("extra %s\n", vertex->to_string(this).c_str()); debugPrint(debug_, "bfs", 1, "extra %s",
vertex->to_string(this).c_str());
} }
} }
} }
if (vertex->bfsInQueue(bfs_index_)) if (vertex->bfsInQueue(bfs_index_))
printf("missing %s\n", vertex->to_string(this).c_str()); debugPrint(debug_, "brs", 1, "missing %s",
vertex->to_string(this).c_str());
} }
void void

View File

@ -93,7 +93,7 @@ Latches::latchRequired(const Path *data_path,
CycleAccting *acct = sdc_->cycleAccting(data_clk_edge, CycleAccting *acct = sdc_->cycleAccting(data_clk_edge,
enable_clk_edge); enable_clk_edge);
// checkTgtClkTime // checkTgtClkTime
float tgt_clk_time = acct->requiredTime(check_role); float tgt_clk_time = path_delay ? 0.0 : acct->requiredTime(check_role);
// checkTgtClkArrival broken down into components. // checkTgtClkArrival broken down into components.
Arrival enable_arrival = max_delay Arrival enable_arrival = max_delay
+ tgt_clk_time + tgt_clk_time

View File

@ -52,7 +52,6 @@ Levelize::Levelize(StaState *sta) :
levels_valid_(false), levels_valid_(false),
max_level_(0), max_level_(0),
level_space_(10), level_space_(10),
max_incremental_level_(std::numeric_limits<size_t>::max()),
roots_(graph_), roots_(graph_),
relevelize_from_(graph_), relevelize_from_(graph_),
observer_(nullptr) observer_(nullptr)
@ -106,8 +105,7 @@ void
Levelize::ensureLevelized() Levelize::ensureLevelized()
{ {
if (!levels_valid_) { if (!levels_valid_) {
if (levelized_ if (levelized_)
&& relevelize_from_.size() < max_incremental_level_)
relevelize(); relevelize();
else else
levelize(); levelize();

View File

@ -108,7 +108,6 @@ protected:
bool levels_valid_; bool levels_valid_;
Level max_level_; Level max_level_;
Level level_space_; Level level_space_;
size_t max_incremental_level_;
VertexSet roots_; VertexSet roots_;
VertexSet relevelize_from_; VertexSet relevelize_from_;
GraphLoopSeq loops_; GraphLoopSeq loops_;

View File

@ -1193,6 +1193,24 @@ PathEndLatchCheck::checkRole(const StaState *sta) const
return TimingRole::latchSetup(); return TimingRole::latchSetup();
} }
float
PathEndLatchCheck::targetClkTime(const StaState *sta) const
{
if (path_delay_)
return 0.0;
else
return PathEndClkConstrained::targetClkTime(sta);
}
float
PathEndLatchCheck::targetClkOffset(const StaState *sta) const
{
if (path_delay_)
return -targetClkEdge(sta)->time();
else
return PathEndClkConstrained::targetClkOffset(sta);
}
Required Required
PathEndLatchCheck::requiredTime(const StaState *sta) const PathEndLatchCheck::requiredTime(const StaState *sta) const
{ {

View File

@ -35,6 +35,7 @@
#include "PathAnalysisPt.hh" #include "PathAnalysisPt.hh"
#include "Tag.hh" #include "Tag.hh"
#include "Search.hh" #include "Search.hh"
#include "Latches.hh"
#include "PathEnd.hh" #include "PathEnd.hh"
#include "Path.hh" #include "Path.hh"
@ -219,7 +220,8 @@ PathEnum::reportDiversionPath(Diversion *div)
p->to_string(this).c_str(), p->to_string(this).c_str(),
delayAsString(p->arrival(), this), delayAsString(p->arrival(), this),
Path::equal(p, after_div, this) ? " <-after diversion" : ""); Path::equal(p, after_div, this) ? " <-after diversion" : "");
if (p != path && network_->isLatchData(p->pin(this))) if (p != path
&& network_->isLatchData(p->pin(this)))
break; break;
p = p->prevPath(); p = p->prevPath();
} }
@ -529,13 +531,23 @@ PathEnum::divSlack(Path *before_div,
const TimingArc *div_arc, const TimingArc *div_arc,
const PathAnalysisPt *path_ap) const PathAnalysisPt *path_ap)
{ {
Arrival arc_arrival = before_div->arrival(); Arrival before_div_arrival = before_div->arrival();
if (div_edge) { if (div_edge) {
ArcDelay div_delay = search_->deratedDelay(div_edge->from(graph_), if (div_edge->role()->isLatchDtoQ()) {
div_arc, div_edge, Arrival div_arrival;
false, path_ap); ArcDelay div_delay;
Arrival div_arrival = search_->clkPathArrival(after_div) + div_delay; Tag *q_tag;
return div_arrival - arc_arrival; latches_->latchOutArrival(after_div, div_arc, div_edge, path_ap,
q_tag, div_delay, div_arrival);
return div_arrival - before_div_arrival;
}
else {
ArcDelay div_delay = search_->deratedDelay(div_edge->from(graph_),
div_arc, div_edge,
false, path_ap);
Arrival div_arrival = search_->clkPathArrival(after_div) + div_delay;
return div_arrival - before_div_arrival;
}
} }
else { else {
report()->error(1370, "path diversion missing edge."); report()->error(1370, "path diversion missing edge.");
@ -634,39 +646,56 @@ PathEnum::updatePathHeadDelays(PathSeq &paths,
Tag *prev_tag = after_div->tag(this); Tag *prev_tag = after_div->tag(this);
ClkInfo *prev_clk_info = prev_tag->clkInfo(); ClkInfo *prev_clk_info = prev_tag->clkInfo();
Arrival prev_arrival = search_->clkPathArrival(after_div); Arrival prev_arrival = search_->clkPathArrival(after_div);
for (int i = paths.size() - 1; i >= 0; i--) { int path_idx_max = paths.size() - 1;
// paths[0] is the path endpoint
for (int i = path_idx_max; i >= 0; i--) {
Path *path = paths[i]; Path *path = paths[i];
TimingArc *arc = path->prevArc(this); TimingArc *arc = path->prevArc(this);
Edge *edge = path->prevEdge(this); Edge *edge = path->prevEdge(this);
if (edge) { if (edge) {
Arrival arrival;
PathAnalysisPt *path_ap = path->pathAnalysisPt(this); PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
ArcDelay arc_delay = search_->deratedDelay(edge->from(graph_), const MinMax *min_max = path->minMax(this);
arc, edge, false, path_ap); if (i == path_idx_max
Arrival arrival = prev_arrival + arc_delay; && edge->role()->isLatchDtoQ()
debugPrint(debug_, "path_enum", 5, "update arrival %s %s %s -> %s", && min_max == MinMax::max()) {
path->vertex(this)->to_string(this).c_str(), ArcDelay arc_delay;
path->tag(this)->to_string(this).c_str(), Tag *q_tag;
delayAsString(path->arrival(), this), latches_->latchOutArrival(after_div, arc, edge, path_ap,
delayAsString(arrival, this)); q_tag, arc_delay, arrival);
path->setArrival(arrival); path->setArrival(arrival);
prev_arrival = arrival; path->setTag(q_tag);
const Tag *tag = path->tag(this); prev_clk_info = q_tag->clkInfo();
const ClkInfo *clk_info = tag->clkInfo();
if (crprActive()
&& clk_info != prev_clk_info
// D->Q paths use the EN->Q clk info so no need to update.
&& arc->role() != TimingRole::latchDtoQ()) {
// When crpr is enabled the diverion may be from another crpr clk pin,
// so update the tags to use the corresponding ClkInfo.
Tag *updated_tag = search_->findTag(path->transition(this),
path_ap,
prev_clk_info,
tag->isClock(),
tag->inputDelay(),
tag->isSegmentStart(),
tag->states(), false);
path->setTag(updated_tag);
} }
else {
ArcDelay arc_delay = search_->deratedDelay(edge->from(graph_),
arc, edge, false, path_ap);
arrival = prev_arrival + arc_delay;
path->setArrival(arrival);
const Tag *tag = path->tag(this);
const ClkInfo *clk_info = tag->clkInfo();
if (crprActive()
&& clk_info != prev_clk_info
// D->Q paths use the EN->Q clk info so no need to update.
&& arc->role() != TimingRole::latchDtoQ()) {
// When crpr is enabled the diverion may be from another crpr clk pin,
// so update the tags to use the corresponding ClkInfo.
Tag *updated_tag = search_->findTag(path->transition(this),
path_ap,
prev_clk_info,
tag->isClock(),
tag->inputDelay(),
tag->isSegmentStart(),
tag->states(), false);
path->setTag(updated_tag);
}
debugPrint(debug_, "path_enum", 5, "update arrival %s %s %s -> %s",
path->vertex(this)->to_string(this).c_str(),
path->tag(this)->to_string(this).c_str(),
delayAsString(path->arrival(), this),
delayAsString(arrival, this));
}
prev_arrival = arrival;
} }
} }
} }

View File

@ -549,8 +549,7 @@ ReportPath::reportFull(const PathEndLatchCheck *end) const
if (ignore_clk_latency) { if (ignore_clk_latency) {
// Based on reportSrcPath. // Based on reportSrcPath.
reportPathHeader(); reportPathHeader();
reportPath3(end->path(), expanded, false, false, 0.0, reportPath3(end->path(), expanded, false, end->sourceClkOffset(this));
end->sourceClkOffset(this));
} }
else else
reportSrcPath(end, expanded); reportSrcPath(end, expanded);
@ -716,8 +715,7 @@ ReportPath::reportFull(const PathEndPathDelay *end) const
if (end->ignoreClkLatency(this)) { if (end->ignoreClkLatency(this)) {
// Based on reportSrcPath. // Based on reportSrcPath.
reportPathHeader(); reportPathHeader();
reportPath3(end->path(), expanded, false, false, 0.0, reportPath3(end->path(), expanded, false, end->sourceClkOffset(this));
end->sourceClkOffset(this));
} }
else else
reportSrcPath(end, expanded); reportSrcPath(end, expanded);
@ -935,11 +933,9 @@ ReportPath::reportFull(const PathEndDataCheck *end) const
const ClockEdge *tgt_clk_edge = end->targetClkEdge(this); const ClockEdge *tgt_clk_edge = end->targetClkEdge(this);
float prev = delayAsFloat(clk_arrival) + src_offset; float prev = delayAsFloat(clk_arrival) + src_offset;
float offset = prev - delayAsFloat(clk_delay) - tgt_clk_edge->time(); float offset = prev - delayAsFloat(clk_delay) - tgt_clk_edge->time();
reportPath5(data_clk_path, clk_expanded, clk_expanded.startIndex(), // Delay to startpoint is already included.
clk_expanded.size() - 1, reportPath6(data_clk_path, clk_expanded, clk_expanded.startIndex(),
data_clk_path->clkInfo(search_)->isPropagated(), false, true, false, prev, offset);
// Delay to startpoint is already included.
prev, offset);
} }
reportRequired(end, checkRoleReason(end)); reportRequired(end, checkRoleReason(end));
reportSlack(end); reportSlack(end);
@ -1103,6 +1099,7 @@ ReportPath::reportJson(const PathEnd *end,
sdc_network_->pathName(endpoint)); sdc_network_->pathName(endpoint));
const ClockEdge *src_clk_edge = end->sourceClkEdge(this); const ClockEdge *src_clk_edge = end->sourceClkEdge(this);
const Path *src_clk_path = expanded.clkPath();
const Path *tgt_clk_path = end->targetClkPath(); const Path *tgt_clk_path = end->targetClkPath();
if (src_clk_edge) { if (src_clk_edge) {
stringAppend(result, " \"source_clock\": \"%s\",\n", stringAppend(result, " \"source_clock\": \"%s\",\n",
@ -1110,6 +1107,8 @@ ReportPath::reportJson(const PathEnd *end,
stringAppend(result, " \"source_clock_edge\": \"%s\",\n", stringAppend(result, " \"source_clock_edge\": \"%s\",\n",
src_clk_edge->transition()->name()); src_clk_edge->transition()->name());
} }
if (src_clk_path)
reportJson(src_clk_path, "source_clock_path", 2, true, result);
reportJson(expanded, "source_path", 2, !end->isUnconstrained(), result); reportJson(expanded, "source_path", 2, !end->isUnconstrained(), result);
const ClockEdge *tgt_clk_edge = end->targetClkEdge(this); const ClockEdge *tgt_clk_edge = end->targetClkEdge(this);
@ -1180,7 +1179,7 @@ ReportPath::reportJson(const PathExpanded &expanded,
string &result) const string &result) const
{ {
stringAppend(result, "%*s\"%s\": [\n", indent, "", path_name); stringAppend(result, "%*s\"%s\": [\n", indent, "", path_name);
for (size_t i = 0; i < expanded.size(); i++) { for (size_t i = expanded.startIndex(); i < expanded.size(); i++) {
const Path *path = expanded.path(i); const Path *path = expanded.path(i);
const Pin *pin = path->vertex(this)->pin(); const Pin *pin = path->vertex(this)->pin();
const Net *net = network_->net(pin); const Net *net = network_->net(pin);
@ -1657,7 +1656,7 @@ ReportPath::reportSkewClkPath(const char *arrival_msg,
insertion, latency); insertion, latency);
reportClkSrcLatency(insertion, clk_time, early_late); reportClkSrcLatency(insertion, clk_time, early_late);
PathExpanded clk_expanded(clk_path, this); PathExpanded clk_expanded(clk_path, this);
reportPath2(clk_path, clk_expanded, false, 0.0); reportPath1(clk_path, clk_expanded, false, 0.0);
} }
} }
else { else {
@ -2226,8 +2225,8 @@ ReportPath::reportTgtClk(const PathEnd *end,
PathExpanded clk_expanded(clk_path, this); PathExpanded clk_expanded(clk_path, this);
float insertion_offset = tgtClkInsertionOffet(clk_path, early_late, float insertion_offset = tgtClkInsertionOffet(clk_path, early_late,
path_ap); path_ap);
reportPath5(clk_path, clk_expanded, 0, clk_expanded.size() - 1, is_prop, reportPath6(clk_path, clk_expanded, 0, is_prop, reportClkPath(),
reportClkPath(), delay_zero, time_offset + insertion_offset); delay_zero, time_offset + insertion_offset);
} }
else { else {
// Output departure. // Output departure.
@ -2374,7 +2373,7 @@ ReportPath::reportGenClkSrcAndPath(const Path *path,
time_offset, clk_used_as_data); time_offset, clk_used_as_data);
if (path) { if (path) {
PathExpanded expanded(path, this); PathExpanded expanded(path, this);
reportPath4(path, expanded, skip_first_path, false, clk_used_as_data, reportPath2(path, expanded, skip_first_path, clk_used_as_data,
path_time_offset); path_time_offset);
} }
} }
@ -2416,7 +2415,7 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk,
reportClkSrcLatency(insertion, gclk_time, early_late); reportClkSrcLatency(insertion, gclk_time, early_late);
} }
PathExpanded src_expanded(src_path, this); PathExpanded src_expanded(src_path, this);
reportPath4(src_path, src_expanded, skip_first_path, false, reportPath2(src_path, src_expanded, skip_first_path,
clk_used_as_data, gclk_time); clk_used_as_data, gclk_time);
if (!clk->isPropagated()) if (!clk->isPropagated())
reportLine("clock network delay (ideal)", 0.0, reportLine("clock network delay (ideal)", 0.0,
@ -2600,11 +2599,51 @@ ReportPath::reportPathFull(const Path *path) const
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Main entry point for reporting a path.
void void
ReportPath::reportPath1(const Path *path, ReportPath::reportPath1(const Path *path,
const PathExpanded &expanded, const PathExpanded &expanded,
bool clk_used_as_data, bool clk_used_as_data,
float time_offset) const float time_offset) const
{
reportPath2(path, expanded, false, clk_used_as_data, time_offset);
}
// Alternate entry point with skip_first_path arg.
void
ReportPath::reportPath2(const Path *path,
const PathExpanded &expanded,
bool skip_first_path,
bool clk_used_as_data,
float time_offset) const
{
bool clk_is_propagated = path->clkInfo(search_)->isPropagated();
bool report_clk_path = (reportClkPath() && clk_is_propagated)
|| clk_used_as_data;
bool propagated_clk = clk_is_propagated || clk_used_as_data;
reportPath4(path, expanded, skip_first_path, propagated_clk,
report_clk_path, time_offset);
}
// Alternate entry point with report_clk_path arg.
void
ReportPath::reportPath3(const Path *path,
const PathExpanded &expanded,
bool report_clk_path,
float time_offset) const
{
bool propagated_clk = path->clkInfo(search_)->isPropagated();
reportPath4(path, expanded, false, propagated_clk,
report_clk_path, time_offset);
}
void
ReportPath::reportPath4(const Path *path,
const PathExpanded &expanded,
bool skip_first_path,
bool propagated_clk,
bool report_clk_path,
float time_offset) const
{ {
const Path *d_path, *q_path; const Path *d_path, *q_path;
Edge *d_q_edge; Edge *d_q_edge;
@ -2617,11 +2656,11 @@ ReportPath::reportPath1(const Path *path,
if (latch_enable_path) { if (latch_enable_path) {
const EarlyLate *early_late = latch_enable_path->minMax(this); const EarlyLate *early_late = latch_enable_path->minMax(this);
latch_enable_time = search_->clkPathArrival(latch_enable_path); latch_enable_time = search_->clkPathArrival(latch_enable_path);
if (reportClkPath()) { if (report_clk_path) {
PathExpanded enable_expanded(latch_enable_path, this); PathExpanded enable_expanded(latch_enable_path, this);
// Report the path to the latch enable. // Report the path to the latch enable.
reportPath2(latch_enable_path, enable_expanded, false, reportPath5(latch_enable_path, enable_expanded, skip_first_path,
time_offset); propagated_clk, report_clk_path, time_offset);
} }
Arrival time = latch_enable_time + latch_time_given; Arrival time = latch_enable_time + latch_time_given;
Arrival incr = latch_time_given; Arrival incr = latch_time_given;
@ -2631,86 +2670,45 @@ ReportPath::reportPath1(const Path *path,
reportLine("time borrowed from startpoint", incr, time, early_late); reportLine("time borrowed from startpoint", incr, time, early_late);
// Override latch D arrival with enable + given. // Override latch D arrival with enable + given.
reportPathLine(expanded.path(0), delay_zero, time, "latch_D"); reportPathLine(expanded.path(0), delay_zero, time, "latch_D");
bool propagated_clk = path->clkInfo(search_)->isPropagated(); reportPath6(path, expanded, 1, propagated_clk, report_clk_path,
bool report_clk_path = path->isClock(search_) || reportClkPath();
reportPath5(path, expanded, 1, expanded.size() - 1,
propagated_clk, report_clk_path,
latch_enable_time + latch_time_given, time_offset); latch_enable_time + latch_time_given, time_offset);
} }
} }
else else
reportPath2(path, expanded, clk_used_as_data, time_offset); reportPath5(path, expanded, skip_first_path, propagated_clk,
} report_clk_path, time_offset);
void
ReportPath::reportPath2(const Path *path,
const PathExpanded &expanded,
bool clk_used_as_data,
float time_offset) const
{
// Report the clock path if the end is a clock or we wouldn't have
// anything to report.
bool report_clk_path = clk_used_as_data
|| (reportClkPath()
&& path->clkInfo(search_)->isPropagated());
reportPath3(path, expanded, clk_used_as_data, report_clk_path,
delay_zero, time_offset);
}
void
ReportPath::reportPath3(const Path *path,
const PathExpanded &expanded,
bool clk_used_as_data,
bool report_clk_path,
Arrival prev_time,
float time_offset) const
{
bool propagated_clk = clk_used_as_data
|| path->clkInfo(search_)->isPropagated();
size_t path_last_index = expanded.size() - 1;
reportPath5(path, expanded, 0, path_last_index, propagated_clk,
report_clk_path, prev_time, time_offset);
}
void
ReportPath::reportPath4(const Path *path,
const PathExpanded &expanded,
bool skip_first_path,
bool skip_last_path,
bool clk_used_as_data,
float time_offset) const
{
size_t path_first_index = 0;
Arrival prev_time(0.0);
if (skip_first_path) {
path_first_index = 1;
const Path *start = expanded.path(0);
prev_time = start->arrival() + time_offset;
}
size_t path_last_index = expanded.size() - 1;
if (skip_last_path
&& path_last_index > 1)
path_last_index--;
bool propagated_clk = clk_used_as_data
|| path->clkInfo(search_)->isPropagated();
// Report the clock path if the end is a clock or we wouldn't have
// anything to report.
bool report_clk_path = path->isClock(search_)
|| (reportClkPath() && propagated_clk);
reportPath5(path, expanded, path_first_index, path_last_index,
propagated_clk, report_clk_path, prev_time, time_offset);
} }
void void
ReportPath::reportPath5(const Path *path, ReportPath::reportPath5(const Path *path,
const PathExpanded &expanded,
bool skip_first_path,
bool propagated_clk,
bool report_clk_path,
float time_offset) const
{
size_t path_first_index = 0;
Arrival prev_time = 0.0;
if (skip_first_path) {
path_first_index = 1;
const Path *start = expanded.path(0);
prev_time = start->arrival() + time_offset;
}
reportPath6(path, expanded, path_first_index, propagated_clk,
report_clk_path, prev_time, time_offset);
}
// This does the real workk of reporting an expanded path.
void
ReportPath::reportPath6(const Path *path,
const PathExpanded &expanded, const PathExpanded &expanded,
size_t path_first_index, size_t path_first_index,
size_t path_last_index,
bool propagated_clk, bool propagated_clk,
bool report_clk_path, bool report_clk_path,
Arrival prev_time, Arrival prev_time,
float time_offset) const float time_offset) const
{ {
size_t path_last_index = expanded.size() - 1;
const MinMax *min_max = path->minMax(this); const MinMax *min_max = path->minMax(this);
DcalcAnalysisPt *dcalc_ap = path->pathAnalysisPt(this)->dcalcAnalysisPt(); DcalcAnalysisPt *dcalc_ap = path->pathAnalysisPt(this)->dcalcAnalysisPt();
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
@ -2986,8 +2984,7 @@ ReportPath::reportInputExternalDelay(const Path *first_path,
pathInputDelayRefPath(first_path, input_delay, ref_path); pathInputDelayRefPath(first_path, input_delay, ref_path);
if (!ref_path.isNull() && reportClkPath()) { if (!ref_path.isNull() && reportClkPath()) {
PathExpanded ref_expanded(&ref_path, this); PathExpanded ref_expanded(&ref_path, this);
reportPath3(&ref_path, ref_expanded, false, true, reportPath3(&ref_path, ref_expanded, true, 0.0);
delay_zero, 0.0);
} }
} }
float input_arrival = float input_arrival =

View File

@ -302,24 +302,28 @@ protected:
float time_offset) const; float time_offset) const;
void reportPath2(const Path *path, void reportPath2(const Path *path,
const PathExpanded &expanded, const PathExpanded &expanded,
bool skip_first_path,
bool clk_used_as_data, bool clk_used_as_data,
float time_offset) const; float time_offset) const;
void reportPath3(const Path *path, void reportPath3(const Path *path,
const PathExpanded &expanded, const PathExpanded &expanded,
bool clk_used_as_data,
bool report_clk_path, bool report_clk_path,
Arrival prev_time,
float time_offset) const; float time_offset) const;
void reportPath4(const Path *path, void reportPath4(const Path *path,
const PathExpanded &expanded, const PathExpanded &expanded,
bool clk_used_as_data,
bool skip_first_path, bool skip_first_path,
bool skip_last_path, bool propagated_clk,
bool report_clk_path,
float time_offset) const; float time_offset) const;
void reportPath5(const Path *path, void reportPath5(const Path *path,
const PathExpanded &expanded,
bool skip_first_path,
bool propagated_clk,
bool report_clk_path,
float time_offset) const;
void reportPath6(const Path *path,
const PathExpanded &expanded, const PathExpanded &expanded,
size_t path_first_index, size_t path_first_index,
size_t path_last_index,
bool propagated_clk, bool propagated_clk,
bool report_clk_path, bool report_clk_path,
Arrival prev_time, Arrival prev_time,

View File

@ -554,15 +554,20 @@ Search::deleteFilterTagGroups()
for (TagGroupIndex i = 0; i < tag_group_next_; i++) { for (TagGroupIndex i = 0; i < tag_group_next_; i++) {
TagGroup *group = tag_groups_[i]; TagGroup *group = tag_groups_[i];
if (group if (group
&& group->hasFilterTag()) { && group->hasFilterTag())
tag_group_set_->erase(group); deleteTagGroup(group);
tag_groups_[group->index()] = nullptr;
tag_group_free_indices_.push_back(i);
delete group;
}
} }
} }
void
Search::deleteTagGroup(TagGroup *group)
{
tag_group_set_->erase(group);
tag_groups_[group->index()] = nullptr;
tag_group_free_indices_.push_back(group->index());
delete group;
}
void void
Search::deleteFilterTags() Search::deleteFilterTags()
{ {
@ -2777,6 +2782,15 @@ Search::setVertexArrivals(Vertex *vertex,
filtered_arrivals_->insert(vertex); filtered_arrivals_->insert(vertex);
} }
} }
if (tag_group != prev_tag_group) {
LockGuard lock(tag_group_ref_count_lock_);
tag_group->incrRefCount();
if (prev_tag_group) {
prev_tag_group->decrRefCount();
if (prev_tag_group->refCount() == 0)
deleteTagGroup(prev_tag_group);
}
}
} }
} }
@ -2819,12 +2833,14 @@ ReportPathLess::operator()(const Path *path1,
} }
void void
Search::reportArrivals(Vertex *vertex) const Search::reportArrivals(Vertex *vertex,
bool report_tag_index) const
{ {
report_->reportLine("Vertex %s", vertex->to_string(this).c_str()); report_->reportLine("Vertex %s", vertex->to_string(this).c_str());
TagGroup *tag_group = tagGroup(vertex); TagGroup *tag_group = tagGroup(vertex);
if (tag_group) { if (tag_group) {
report_->reportLine("Group %u", tag_group->index()); if (report_tag_index)
report_->reportLine("Group %u", tag_group->index());
std::vector<const Path*> paths; std::vector<const Path*> paths;
VertexPathIterator path_iter(vertex, this); VertexPathIterator path_iter(vertex, this);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
@ -2859,7 +2875,7 @@ Search::reportArrivals(Vertex *vertex) const
path_ap->pathMinMax()->to_string().c_str(), path_ap->pathMinMax()->to_string().c_str(),
delayAsString(path->arrival(), this), delayAsString(path->arrival(), this),
req, req,
tag->to_string(true, false, this).c_str(), tag->to_string(report_tag_index, false, this).c_str(),
prev_str.c_str()); prev_str.c_str());
} }
} }

View File

@ -264,9 +264,10 @@ report_tag_groups()
} }
void void
report_tag_arrivals_cmd(Vertex *vertex) report_tag_arrivals_cmd(Vertex *vertex,
bool report_tag_index)
{ {
Sta::sta()->search()->reportArrivals(vertex); Sta::sta()->search()->reportArrivals(vertex, report_tag_index);
} }
void void

View File

@ -355,7 +355,7 @@ tagCmp(const Tag *tag1,
return tagStateCmp(tag1, tag2); return tagStateCmp(tag1, tag2);
} }
int bool
tagEqual(const Tag *tag1, tagEqual(const Tag *tag1,
const Tag *tag2) const Tag *tag2)
{ {

View File

@ -140,6 +140,9 @@ public:
const Tag *tag2) const; const Tag *tag2) const;
}; };
bool
tagEqual(const Tag *tag1,
const Tag *tag2);
int int
tagCmp(const Tag *tag1, tagCmp(const Tag *tag1,
const Tag *tag2, const Tag *tag2,

View File

@ -44,6 +44,7 @@ TagGroup::TagGroup(TagGroupIndex index,
bool has_loop_tag) : bool has_loop_tag) :
path_index_map_(path_index_map), path_index_map_(path_index_map),
hash_(pathIndexMapHash(path_index_map)), hash_(pathIndexMapHash(path_index_map)),
ref_count_(0),
index_(index), index_(index),
has_clk_tag_(has_clk_tag), has_clk_tag_(has_clk_tag),
has_genclk_src_tag_(has_genclk_src_tag), has_genclk_src_tag_(has_genclk_src_tag),
@ -56,6 +57,7 @@ TagGroup::TagGroup(TagGroupIndex index,
TagGroup::TagGroup(TagGroupBldr *tag_bldr) : TagGroup::TagGroup(TagGroupBldr *tag_bldr) :
path_index_map_(&tag_bldr->pathIndexMap()), path_index_map_(&tag_bldr->pathIndexMap()),
hash_(pathIndexMapHash(path_index_map_)), hash_(pathIndexMapHash(path_index_map_)),
ref_count_(0),
own_path_map_(false) own_path_map_(false)
{ {
} }
@ -66,6 +68,18 @@ TagGroup::~TagGroup()
delete path_index_map_; delete path_index_map_;
} }
void
TagGroup::incrRefCount()
{
ref_count_++;
}
void
TagGroup::decrRefCount()
{
ref_count_--;
}
size_t size_t
TagGroup::pathIndexMapHash(PathIndexMap *path_index_map) TagGroup::pathIndexMapHash(PathIndexMap *path_index_map)
{ {

View File

@ -65,6 +65,9 @@ public:
size_t pathIndex(Tag *tag) const; size_t pathIndex(Tag *tag) const;
PathIndexMap *pathIndexMap() const { return path_index_map_; } PathIndexMap *pathIndexMap() const { return path_index_map_; }
bool hasTag(Tag *tag) const; bool hasTag(Tag *tag) const;
void incrRefCount();
void decrRefCount();
int refCount() const { return ref_count_; }
protected: protected:
static size_t pathIndexMapHash(PathIndexMap *path_index_map); static size_t pathIndexMapHash(PathIndexMap *path_index_map);
@ -72,6 +75,7 @@ protected:
// tag -> path index // tag -> path index
PathIndexMap *path_index_map_; PathIndexMap *path_index_map_;
size_t hash_; size_t hash_;
int ref_count_;
unsigned int index_:tag_group_index_bits; unsigned int index_:tag_group_index_bits;
bool has_clk_tag_:1; bool has_clk_tag_:1;
bool has_genclk_src_tag_:1; bool has_genclk_src_tag_:1;

View File

@ -7,7 +7,7 @@
"endpoint": "_1416_[0]/D", "endpoint": "_1416_[0]/D",
"source_clock": "clk", "source_clock": "clk",
"source_clock_edge": "rise", "source_clock_edge": "rise",
"source_path": [ "source_clock_path": [
{ {
"instance": "", "instance": "",
"cell": "counter", "cell": "counter",
@ -25,7 +25,9 @@
"net": "clk", "net": "clk",
"arrival": 0.000e+00, "arrival": 0.000e+00,
"slew": 0.000e+00 "slew": 0.000e+00
}, }
],
"source_path": [
{ {
"instance": "_1415_", "instance": "_1415_",
"cell": "sky130_fd_sc_hd__dfrtp_1", "cell": "sky130_fd_sc_hd__dfrtp_1",

View File

@ -89,7 +89,9 @@ PatternMatch::compileRegexp()
anchored_pattern += '$'; anchored_pattern += '$';
Tcl_Obj *pattern_obj = Tcl_NewStringObj(anchored_pattern.c_str(), Tcl_Obj *pattern_obj = Tcl_NewStringObj(anchored_pattern.c_str(),
anchored_pattern.size()); anchored_pattern.size());
Tcl_IncrRefCount(pattern_obj);
regexp_ = Tcl_GetRegExpFromObj(interp_, pattern_obj, flags); regexp_ = Tcl_GetRegExpFromObj(interp_, pattern_obj, flags);
Tcl_DecrRefCount(pattern_obj);
if (regexp_ == nullptr && interp_) if (regexp_ == nullptr && interp_)
throw RegexpCompileError(pattern_); throw RegexpCompileError(pattern_);
} }

View File

@ -117,7 +117,7 @@ public:
int n_putback = gptr() - eback(); int n_putback = gptr() - eback();
if ( n_putback > 4) if ( n_putback > 4)
n_putback = 4; n_putback = 4;
memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback); memmove( buffer + (4 - n_putback), gptr() - n_putback, n_putback);
int num = gzread( file, buffer+4, bufferSize-4); int num = gzread( file, buffer+4, bufferSize-4);
if (num <= 0) // ERROR or EOF if (num <= 0) // ERROR or EOF