Merge remote-tracking branch 'upstream/master'
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
commit
e475ee2c98
|
|
@ -263,12 +263,16 @@ protected:
|
|||
|
||||
// Driver parameter Newton-Raphson state.
|
||||
int nr_order_;
|
||||
double *x_;
|
||||
double *fvec_;
|
||||
double **fjac_;
|
||||
double *scale_;
|
||||
double *p_;
|
||||
int *index_;
|
||||
|
||||
static constexpr int max_nr_order_ = 3;
|
||||
|
||||
double x_[max_nr_order_];
|
||||
double fvec_[max_nr_order_];
|
||||
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.
|
||||
double drvr_slew_;
|
||||
|
|
@ -288,27 +292,12 @@ DmpAlg::DmpAlg(int nr_order,
|
|||
c1_(0.0),
|
||||
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++)
|
||||
fjac_[i] = new double[nr_order_];
|
||||
index_ = new int[nr_order_];
|
||||
// Only use the upper left block of the matrix
|
||||
fjac_[i] = fjac_storage_ + i * max_nr_order_;
|
||||
}
|
||||
|
||||
DmpAlg::~DmpAlg()
|
||||
{
|
||||
delete [] x_;
|
||||
delete [] fvec_;
|
||||
delete [] scale_;
|
||||
delete [] p_;
|
||||
for (int i = 0; i < nr_order_; i++)
|
||||
delete [] fjac_[i];
|
||||
delete [] fjac_;
|
||||
delete [] index_;
|
||||
}
|
||||
DmpAlg::~DmpAlg() = default;
|
||||
|
||||
void
|
||||
DmpAlg::init(const LibertyLibrary *drvr_library,
|
||||
|
|
|
|||
|
|
@ -260,8 +260,10 @@ GraphDelayCalc::findDelays(Level level)
|
|||
if (incremental_)
|
||||
seedInvalidDelays();
|
||||
|
||||
FindVertexDelays visitor(this);
|
||||
dcalc_count += iter_->visitParallel(level, &visitor);
|
||||
if (!iter_->empty()) {
|
||||
FindVertexDelays visitor(this);
|
||||
dcalc_count += iter_->visitParallel(level, &visitor);
|
||||
}
|
||||
|
||||
// Timing checks require slews at both ends of the arc,
|
||||
// so find their delays after all slews are known.
|
||||
|
|
|
|||
1428
doc/OpenSTA.fodt
1428
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.
|
|
@ -375,6 +375,8 @@ public:
|
|||
virtual const TimingRole *checkRole(const StaState *sta) const;
|
||||
virtual Required requiredTime(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;
|
||||
virtual int exceptPathCmp(const PathEnd *path_end,
|
||||
const StaState *sta) const;
|
||||
|
|
|
|||
|
|
@ -356,7 +356,8 @@ public:
|
|||
|
||||
TagGroup *tagGroup(const Vertex *vertex) const;
|
||||
TagGroup *tagGroup(TagGroupIndex index) const;
|
||||
void reportArrivals(Vertex *vertex) const;
|
||||
void reportArrivals(Vertex *vertex,
|
||||
bool report_tag_index) const;
|
||||
Slack wnsSlack(Vertex *vertex,
|
||||
PathAPIndex path_ap_index);
|
||||
void levelsChangedBefore();
|
||||
|
|
@ -410,6 +411,7 @@ public:
|
|||
TagGroupIndex tag_index);
|
||||
void checkPrevPaths() const;
|
||||
void deletePaths(Vertex *vertex);
|
||||
void deleteTagGroup(TagGroup *group);
|
||||
|
||||
protected:
|
||||
void init(StaState *sta);
|
||||
|
|
@ -645,6 +647,7 @@ protected:
|
|||
// Capacity of tag_groups_.
|
||||
TagGroupIndex tag_group_capacity_;
|
||||
std::mutex tag_group_lock_;
|
||||
std::mutex tag_group_ref_count_lock_;
|
||||
// Latches data outputs to queue on the next search pass.
|
||||
VertexSet *pending_latch_outputs_;
|
||||
std::mutex pending_latch_outputs_lock_;
|
||||
|
|
|
|||
|
|
@ -559,6 +559,8 @@ LibertyReader::defineVisitors()
|
|||
|
||||
defineGroupVisitor("ecsm_waveform", &LibertyReader::beginEcsmWaveform,
|
||||
&LibertyReader::endEcsmWaveform);
|
||||
defineGroupVisitor("ecsm_waveform_set", &LibertyReader::beginEcsmWaveform,
|
||||
&LibertyReader::endEcsmWaveform);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -303,12 +303,14 @@ BfsIterator::checkInQueue(Vertex *vertex)
|
|||
if (vertex->bfsInQueue(bfs_index_))
|
||||
return;
|
||||
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_))
|
||||
printf("missing %s\n", vertex->to_string(this).c_str());
|
||||
debugPrint(debug_, "brs", 1, "missing %s",
|
||||
vertex->to_string(this).c_str());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ Latches::latchRequired(const Path *data_path,
|
|||
CycleAccting *acct = sdc_->cycleAccting(data_clk_edge,
|
||||
enable_clk_edge);
|
||||
// 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.
|
||||
Arrival enable_arrival = max_delay
|
||||
+ tgt_clk_time
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ Levelize::Levelize(StaState *sta) :
|
|||
levels_valid_(false),
|
||||
max_level_(0),
|
||||
level_space_(10),
|
||||
max_incremental_level_(std::numeric_limits<size_t>::max()),
|
||||
roots_(graph_),
|
||||
relevelize_from_(graph_),
|
||||
observer_(nullptr)
|
||||
|
|
@ -106,8 +105,7 @@ void
|
|||
Levelize::ensureLevelized()
|
||||
{
|
||||
if (!levels_valid_) {
|
||||
if (levelized_
|
||||
&& relevelize_from_.size() < max_incremental_level_)
|
||||
if (levelized_)
|
||||
relevelize();
|
||||
else
|
||||
levelize();
|
||||
|
|
|
|||
|
|
@ -108,7 +108,6 @@ protected:
|
|||
bool levels_valid_;
|
||||
Level max_level_;
|
||||
Level level_space_;
|
||||
size_t max_incremental_level_;
|
||||
VertexSet roots_;
|
||||
VertexSet relevelize_from_;
|
||||
GraphLoopSeq loops_;
|
||||
|
|
|
|||
|
|
@ -1193,6 +1193,24 @@ PathEndLatchCheck::checkRole(const StaState *sta) const
|
|||
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
|
||||
PathEndLatchCheck::requiredTime(const StaState *sta) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "PathAnalysisPt.hh"
|
||||
#include "Tag.hh"
|
||||
#include "Search.hh"
|
||||
#include "Latches.hh"
|
||||
#include "PathEnd.hh"
|
||||
#include "Path.hh"
|
||||
|
||||
|
|
@ -219,7 +220,8 @@ PathEnum::reportDiversionPath(Diversion *div)
|
|||
p->to_string(this).c_str(),
|
||||
delayAsString(p->arrival(), this),
|
||||
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;
|
||||
p = p->prevPath();
|
||||
}
|
||||
|
|
@ -529,13 +531,23 @@ PathEnum::divSlack(Path *before_div,
|
|||
const TimingArc *div_arc,
|
||||
const PathAnalysisPt *path_ap)
|
||||
{
|
||||
Arrival arc_arrival = before_div->arrival();
|
||||
Arrival before_div_arrival = before_div->arrival();
|
||||
if (div_edge) {
|
||||
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 - arc_arrival;
|
||||
if (div_edge->role()->isLatchDtoQ()) {
|
||||
Arrival div_arrival;
|
||||
ArcDelay div_delay;
|
||||
Tag *q_tag;
|
||||
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 {
|
||||
report()->error(1370, "path diversion missing edge.");
|
||||
|
|
@ -634,39 +646,56 @@ PathEnum::updatePathHeadDelays(PathSeq &paths,
|
|||
Tag *prev_tag = after_div->tag(this);
|
||||
ClkInfo *prev_clk_info = prev_tag->clkInfo();
|
||||
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];
|
||||
TimingArc *arc = path->prevArc(this);
|
||||
Edge *edge = path->prevEdge(this);
|
||||
if (edge) {
|
||||
Arrival arrival;
|
||||
PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
|
||||
ArcDelay arc_delay = search_->deratedDelay(edge->from(graph_),
|
||||
arc, edge, false, path_ap);
|
||||
Arrival arrival = prev_arrival + arc_delay;
|
||||
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));
|
||||
path->setArrival(arrival);
|
||||
prev_arrival = 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);
|
||||
const MinMax *min_max = path->minMax(this);
|
||||
if (i == path_idx_max
|
||||
&& edge->role()->isLatchDtoQ()
|
||||
&& min_max == MinMax::max()) {
|
||||
ArcDelay arc_delay;
|
||||
Tag *q_tag;
|
||||
latches_->latchOutArrival(after_div, arc, edge, path_ap,
|
||||
q_tag, arc_delay, arrival);
|
||||
path->setArrival(arrival);
|
||||
path->setTag(q_tag);
|
||||
prev_clk_info = q_tag->clkInfo();
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -549,8 +549,7 @@ ReportPath::reportFull(const PathEndLatchCheck *end) const
|
|||
if (ignore_clk_latency) {
|
||||
// Based on reportSrcPath.
|
||||
reportPathHeader();
|
||||
reportPath3(end->path(), expanded, false, false, 0.0,
|
||||
end->sourceClkOffset(this));
|
||||
reportPath3(end->path(), expanded, false, end->sourceClkOffset(this));
|
||||
}
|
||||
else
|
||||
reportSrcPath(end, expanded);
|
||||
|
|
@ -716,8 +715,7 @@ ReportPath::reportFull(const PathEndPathDelay *end) const
|
|||
if (end->ignoreClkLatency(this)) {
|
||||
// Based on reportSrcPath.
|
||||
reportPathHeader();
|
||||
reportPath3(end->path(), expanded, false, false, 0.0,
|
||||
end->sourceClkOffset(this));
|
||||
reportPath3(end->path(), expanded, false, end->sourceClkOffset(this));
|
||||
}
|
||||
else
|
||||
reportSrcPath(end, expanded);
|
||||
|
|
@ -935,11 +933,9 @@ ReportPath::reportFull(const PathEndDataCheck *end) const
|
|||
const ClockEdge *tgt_clk_edge = end->targetClkEdge(this);
|
||||
float prev = delayAsFloat(clk_arrival) + src_offset;
|
||||
float offset = prev - delayAsFloat(clk_delay) - tgt_clk_edge->time();
|
||||
reportPath5(data_clk_path, clk_expanded, clk_expanded.startIndex(),
|
||||
clk_expanded.size() - 1,
|
||||
data_clk_path->clkInfo(search_)->isPropagated(), false,
|
||||
// Delay to startpoint is already included.
|
||||
prev, offset);
|
||||
// Delay to startpoint is already included.
|
||||
reportPath6(data_clk_path, clk_expanded, clk_expanded.startIndex(),
|
||||
true, false, prev, offset);
|
||||
}
|
||||
reportRequired(end, checkRoleReason(end));
|
||||
reportSlack(end);
|
||||
|
|
@ -1103,6 +1099,7 @@ ReportPath::reportJson(const PathEnd *end,
|
|||
sdc_network_->pathName(endpoint));
|
||||
|
||||
const ClockEdge *src_clk_edge = end->sourceClkEdge(this);
|
||||
const Path *src_clk_path = expanded.clkPath();
|
||||
const Path *tgt_clk_path = end->targetClkPath();
|
||||
if (src_clk_edge) {
|
||||
stringAppend(result, " \"source_clock\": \"%s\",\n",
|
||||
|
|
@ -1110,6 +1107,8 @@ ReportPath::reportJson(const PathEnd *end,
|
|||
stringAppend(result, " \"source_clock_edge\": \"%s\",\n",
|
||||
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);
|
||||
|
||||
const ClockEdge *tgt_clk_edge = end->targetClkEdge(this);
|
||||
|
|
@ -1180,7 +1179,7 @@ ReportPath::reportJson(const PathExpanded &expanded,
|
|||
string &result) const
|
||||
{
|
||||
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 Pin *pin = path->vertex(this)->pin();
|
||||
const Net *net = network_->net(pin);
|
||||
|
|
@ -1657,7 +1656,7 @@ ReportPath::reportSkewClkPath(const char *arrival_msg,
|
|||
insertion, latency);
|
||||
reportClkSrcLatency(insertion, clk_time, early_late);
|
||||
PathExpanded clk_expanded(clk_path, this);
|
||||
reportPath2(clk_path, clk_expanded, false, 0.0);
|
||||
reportPath1(clk_path, clk_expanded, false, 0.0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -2226,8 +2225,8 @@ ReportPath::reportTgtClk(const PathEnd *end,
|
|||
PathExpanded clk_expanded(clk_path, this);
|
||||
float insertion_offset = tgtClkInsertionOffet(clk_path, early_late,
|
||||
path_ap);
|
||||
reportPath5(clk_path, clk_expanded, 0, clk_expanded.size() - 1, is_prop,
|
||||
reportClkPath(), delay_zero, time_offset + insertion_offset);
|
||||
reportPath6(clk_path, clk_expanded, 0, is_prop, reportClkPath(),
|
||||
delay_zero, time_offset + insertion_offset);
|
||||
}
|
||||
else {
|
||||
// Output departure.
|
||||
|
|
@ -2374,7 +2373,7 @@ ReportPath::reportGenClkSrcAndPath(const Path *path,
|
|||
time_offset, clk_used_as_data);
|
||||
if (path) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -2416,7 +2415,7 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk,
|
|||
reportClkSrcLatency(insertion, gclk_time, early_late);
|
||||
}
|
||||
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);
|
||||
if (!clk->isPropagated())
|
||||
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
|
||||
ReportPath::reportPath1(const Path *path,
|
||||
const PathExpanded &expanded,
|
||||
bool clk_used_as_data,
|
||||
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;
|
||||
Edge *d_q_edge;
|
||||
|
|
@ -2617,11 +2656,11 @@ ReportPath::reportPath1(const Path *path,
|
|||
if (latch_enable_path) {
|
||||
const EarlyLate *early_late = latch_enable_path->minMax(this);
|
||||
latch_enable_time = search_->clkPathArrival(latch_enable_path);
|
||||
if (reportClkPath()) {
|
||||
if (report_clk_path) {
|
||||
PathExpanded enable_expanded(latch_enable_path, this);
|
||||
// Report the path to the latch enable.
|
||||
reportPath2(latch_enable_path, enable_expanded, false,
|
||||
time_offset);
|
||||
reportPath5(latch_enable_path, enable_expanded, skip_first_path,
|
||||
propagated_clk, report_clk_path, time_offset);
|
||||
}
|
||||
Arrival time = latch_enable_time + 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);
|
||||
// Override latch D arrival with enable + given.
|
||||
reportPathLine(expanded.path(0), delay_zero, time, "latch_D");
|
||||
bool propagated_clk = path->clkInfo(search_)->isPropagated();
|
||||
bool report_clk_path = path->isClock(search_) || reportClkPath();
|
||||
reportPath5(path, expanded, 1, expanded.size() - 1,
|
||||
propagated_clk, report_clk_path,
|
||||
reportPath6(path, expanded, 1, propagated_clk, report_clk_path,
|
||||
latch_enable_time + latch_time_given, time_offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
reportPath2(path, expanded, clk_used_as_data, 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);
|
||||
reportPath5(path, expanded, skip_first_path, propagated_clk,
|
||||
report_clk_path, time_offset);
|
||||
}
|
||||
|
||||
void
|
||||
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,
|
||||
size_t path_first_index,
|
||||
size_t path_last_index,
|
||||
bool propagated_clk,
|
||||
bool report_clk_path,
|
||||
Arrival prev_time,
|
||||
float time_offset) const
|
||||
{
|
||||
size_t path_last_index = expanded.size() - 1;
|
||||
const MinMax *min_max = path->minMax(this);
|
||||
DcalcAnalysisPt *dcalc_ap = path->pathAnalysisPt(this)->dcalcAnalysisPt();
|
||||
DcalcAPIndex ap_index = dcalc_ap->index();
|
||||
|
|
@ -2986,8 +2984,7 @@ ReportPath::reportInputExternalDelay(const Path *first_path,
|
|||
pathInputDelayRefPath(first_path, input_delay, ref_path);
|
||||
if (!ref_path.isNull() && reportClkPath()) {
|
||||
PathExpanded ref_expanded(&ref_path, this);
|
||||
reportPath3(&ref_path, ref_expanded, false, true,
|
||||
delay_zero, 0.0);
|
||||
reportPath3(&ref_path, ref_expanded, true, 0.0);
|
||||
}
|
||||
}
|
||||
float input_arrival =
|
||||
|
|
|
|||
|
|
@ -302,24 +302,28 @@ protected:
|
|||
float time_offset) const;
|
||||
void reportPath2(const Path *path,
|
||||
const PathExpanded &expanded,
|
||||
bool skip_first_path,
|
||||
bool clk_used_as_data,
|
||||
float time_offset) const;
|
||||
void reportPath3(const Path *path,
|
||||
const PathExpanded &expanded,
|
||||
bool clk_used_as_data,
|
||||
bool report_clk_path,
|
||||
Arrival prev_time,
|
||||
float time_offset) const;
|
||||
void reportPath4(const Path *path,
|
||||
const PathExpanded &expanded,
|
||||
bool clk_used_as_data,
|
||||
bool skip_first_path,
|
||||
bool skip_last_path,
|
||||
bool propagated_clk,
|
||||
bool report_clk_path,
|
||||
float time_offset) const;
|
||||
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,
|
||||
size_t path_first_index,
|
||||
size_t path_last_index,
|
||||
bool propagated_clk,
|
||||
bool report_clk_path,
|
||||
Arrival prev_time,
|
||||
|
|
|
|||
|
|
@ -554,15 +554,20 @@ Search::deleteFilterTagGroups()
|
|||
for (TagGroupIndex i = 0; i < tag_group_next_; i++) {
|
||||
TagGroup *group = tag_groups_[i];
|
||||
if (group
|
||||
&& group->hasFilterTag()) {
|
||||
tag_group_set_->erase(group);
|
||||
tag_groups_[group->index()] = nullptr;
|
||||
tag_group_free_indices_.push_back(i);
|
||||
delete group;
|
||||
}
|
||||
&& group->hasFilterTag())
|
||||
deleteTagGroup(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
|
||||
Search::deleteFilterTags()
|
||||
{
|
||||
|
|
@ -2777,6 +2782,15 @@ Search::setVertexArrivals(Vertex *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
|
||||
Search::reportArrivals(Vertex *vertex) const
|
||||
Search::reportArrivals(Vertex *vertex,
|
||||
bool report_tag_index) const
|
||||
{
|
||||
report_->reportLine("Vertex %s", vertex->to_string(this).c_str());
|
||||
TagGroup *tag_group = tagGroup(vertex);
|
||||
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;
|
||||
VertexPathIterator path_iter(vertex, this);
|
||||
while (path_iter.hasNext()) {
|
||||
|
|
@ -2859,7 +2875,7 @@ Search::reportArrivals(Vertex *vertex) const
|
|||
path_ap->pathMinMax()->to_string().c_str(),
|
||||
delayAsString(path->arrival(), this),
|
||||
req,
|
||||
tag->to_string(true, false, this).c_str(),
|
||||
tag->to_string(report_tag_index, false, this).c_str(),
|
||||
prev_str.c_str());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -264,9 +264,10 @@ report_tag_groups()
|
|||
}
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ tagCmp(const Tag *tag1,
|
|||
return tagStateCmp(tag1, tag2);
|
||||
}
|
||||
|
||||
int
|
||||
bool
|
||||
tagEqual(const Tag *tag1,
|
||||
const Tag *tag2)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -140,6 +140,9 @@ public:
|
|||
const Tag *tag2) const;
|
||||
};
|
||||
|
||||
bool
|
||||
tagEqual(const Tag *tag1,
|
||||
const Tag *tag2);
|
||||
int
|
||||
tagCmp(const Tag *tag1,
|
||||
const Tag *tag2,
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ TagGroup::TagGroup(TagGroupIndex index,
|
|||
bool has_loop_tag) :
|
||||
path_index_map_(path_index_map),
|
||||
hash_(pathIndexMapHash(path_index_map)),
|
||||
ref_count_(0),
|
||||
index_(index),
|
||||
has_clk_tag_(has_clk_tag),
|
||||
has_genclk_src_tag_(has_genclk_src_tag),
|
||||
|
|
@ -56,6 +57,7 @@ TagGroup::TagGroup(TagGroupIndex index,
|
|||
TagGroup::TagGroup(TagGroupBldr *tag_bldr) :
|
||||
path_index_map_(&tag_bldr->pathIndexMap()),
|
||||
hash_(pathIndexMapHash(path_index_map_)),
|
||||
ref_count_(0),
|
||||
own_path_map_(false)
|
||||
{
|
||||
}
|
||||
|
|
@ -66,6 +68,18 @@ TagGroup::~TagGroup()
|
|||
delete path_index_map_;
|
||||
}
|
||||
|
||||
void
|
||||
TagGroup::incrRefCount()
|
||||
{
|
||||
ref_count_++;
|
||||
}
|
||||
|
||||
void
|
||||
TagGroup::decrRefCount()
|
||||
{
|
||||
ref_count_--;
|
||||
}
|
||||
|
||||
size_t
|
||||
TagGroup::pathIndexMapHash(PathIndexMap *path_index_map)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ public:
|
|||
size_t pathIndex(Tag *tag) const;
|
||||
PathIndexMap *pathIndexMap() const { return path_index_map_; }
|
||||
bool hasTag(Tag *tag) const;
|
||||
void incrRefCount();
|
||||
void decrRefCount();
|
||||
int refCount() const { return ref_count_; }
|
||||
|
||||
protected:
|
||||
static size_t pathIndexMapHash(PathIndexMap *path_index_map);
|
||||
|
|
@ -72,6 +75,7 @@ protected:
|
|||
// tag -> path index
|
||||
PathIndexMap *path_index_map_;
|
||||
size_t hash_;
|
||||
int ref_count_;
|
||||
unsigned int index_:tag_group_index_bits;
|
||||
bool has_clk_tag_:1;
|
||||
bool has_genclk_src_tag_:1;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
"endpoint": "_1416_[0]/D",
|
||||
"source_clock": "clk",
|
||||
"source_clock_edge": "rise",
|
||||
"source_path": [
|
||||
"source_clock_path": [
|
||||
{
|
||||
"instance": "",
|
||||
"cell": "counter",
|
||||
|
|
@ -25,7 +25,9 @@
|
|||
"net": "clk",
|
||||
"arrival": 0.000e+00,
|
||||
"slew": 0.000e+00
|
||||
},
|
||||
}
|
||||
],
|
||||
"source_path": [
|
||||
{
|
||||
"instance": "_1415_",
|
||||
"cell": "sky130_fd_sc_hd__dfrtp_1",
|
||||
|
|
|
|||
|
|
@ -89,7 +89,9 @@ PatternMatch::compileRegexp()
|
|||
anchored_pattern += '$';
|
||||
Tcl_Obj *pattern_obj = Tcl_NewStringObj(anchored_pattern.c_str(),
|
||||
anchored_pattern.size());
|
||||
Tcl_IncrRefCount(pattern_obj);
|
||||
regexp_ = Tcl_GetRegExpFromObj(interp_, pattern_obj, flags);
|
||||
Tcl_DecrRefCount(pattern_obj);
|
||||
if (regexp_ == nullptr && interp_)
|
||||
throw RegexpCompileError(pattern_);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ public:
|
|||
int n_putback = gptr() - eback();
|
||||
if ( 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);
|
||||
if (num <= 0) // ERROR or EOF
|
||||
|
|
|
|||
Loading…
Reference in New Issue