latch nworst thru D->Q (eagle 20250815)
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
872f611fea
commit
70f4bc0459
|
|
@ -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);
|
||||
|
|
@ -1660,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 {
|
||||
|
|
@ -2229,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.
|
||||
|
|
@ -2377,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -2419,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,
|
||||
|
|
@ -2603,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;
|
||||
|
|
@ -2620,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;
|
||||
|
|
@ -2634,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();
|
||||
|
|
@ -2989,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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue