set_data_check support mcp, 1/2 cycle path reporting

This commit is contained in:
James Cherry 2020-07-13 07:38:39 -07:00
parent f60b82fee5
commit f3a50663d8
5 changed files with 19 additions and 10 deletions

View File

@ -142,6 +142,7 @@ public:
virtual TimingArc *checkArc() const { return nullptr; }
// PathEndDataCheck data clock path.
virtual const PathVertex *dataClkPath() const { return nullptr; }
virtual int setupDefaultCycles() const { return 1; }
static bool less(const PathEnd *path_end1,
const PathEnd *path_end2,
@ -181,6 +182,7 @@ public:
static float checkSetupMcpAdjustment(const ClockEdge *src_clk_edge,
const ClockEdge *tgt_clk_edge,
const MultiCyclePath *mcp,
int default_cycles,
Sdc *sdc);
protected:
@ -545,6 +547,8 @@ protected:
Crpr crpr,
bool crpr_valid);
Arrival requiredTimeNoCrpr(const StaState *sta) const;
// setup uses zero cycle default
virtual int setupDefaultCycles() const { return 0; }
private:
PathVertex data_clk_path_;

View File

@ -92,7 +92,7 @@ Latches::latchRequired(const Path *data_path,
+ open_latency
+ open_uncertainty
+ PathEnd::checkSetupMcpAdjustment(data_clk_edge, enable_clk_edge, mcp,
sdc_)
1, sdc_)
+ open_crpr;
debugPrint3(debug_, "latch", 1, "latch data %s %s enable %s\n",
network_->pathName(data_path->pin(this)),

View File

@ -358,7 +358,9 @@ PathEnd::checkTgtClkDelay(const PathVertex *tgt_clk_path,
const RiseFall *tgt_clk_rf = tgt_clk_edge->transition();
insertion = search->clockInsertion(tgt_clk, tgt_src_pin, tgt_clk_rf,
min_max, early_late, tgt_path_ap);
if (clk_info->isPropagated()) {
if (clk_info->isPropagated()
// Data check target clock is always propagated.
|| check_role->isDataCheck()) {
// Propagated clock. Propagated arrival is seeded with
// early_late==path_min_max insertion delay.
Arrival clk_arrival = tgt_clk_path->arrival(sta);
@ -824,7 +826,7 @@ PathEndClkConstrainedMcp::checkMcpAdjustment(const Path *path,
Sdc *sdc = sta->sdc();
if (min_max == MinMax::max())
return PathEnd::checkSetupMcpAdjustment(src_clk_edge, tgt_clk_edge,
mcp_, sdc);
mcp_, setupDefaultCycles(), sdc);
else {
// Hold check.
// Default arrival clock is a proxy for the target clock.
@ -874,6 +876,7 @@ float
PathEnd::checkSetupMcpAdjustment(const ClockEdge *src_clk_edge,
const ClockEdge *tgt_clk_edge,
const MultiCyclePath *mcp,
int default_cycles,
Sdc *sdc)
{
if (mcp) {
@ -887,7 +890,7 @@ PathEnd::checkSetupMcpAdjustment(const ClockEdge *src_clk_edge,
const ClockEdge *clk_edge =
mcp->useEndClk() ? tgt_clk_edge : src_clk_edge;
float period = clk_edge->clock()->period();
return (mult - 1) * period;
return (mult - default_cycles) * period;
}
else
return 0.0;

View File

@ -947,8 +947,8 @@ ReportPath::reportFull(const PathEndDataCheck *end,
reportShort(end, expanded, result);
reportSrcPathArrival(end, expanded, result);
// Capture/target clock path reporting resembles both source (reportSrcPath)
// and target (reportTgtClk) clocks.
// Data check target clock path reporting resembles
// both source (reportSrcPath) and target (reportTgtClk) clocks.
// It is like a source because it can be a non-clock path.
// It is like a target because crpr and uncertainty are reported.
// It is always propagated, even if the clock is ideal.
@ -960,12 +960,14 @@ ReportPath::reportFull(const PathEndDataCheck *end,
float src_offset = end->sourceClkOffset(this);
Delay clk_delay = end->targetClkDelay(this);
Arrival clk_arrival = end->targetClkArrival(this);
float offset = delayAsFloat(clk_arrival - clk_delay + src_offset);
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.
clk_arrival + src_offset, offset, result);
prev, offset, result);
}
reportRequired(end, checkRoleReason(end), result);
reportSlack(end, result);

View File

@ -556,8 +556,8 @@ VisitPathEnds::visitDataCheckEnd1(DataCheck *check,
|| exception->isMultiCycle())
&& (!filtered
|| search_->matchesFilter(path, tgt_clk_edge))) {
// No mcp for data checks.
PathEndDataCheck path_end(check, path, tgt_clk_path, nullptr, this);
MultiCyclePath *mcp=dynamic_cast<MultiCyclePath*>(exception);
PathEndDataCheck path_end(check, path, tgt_clk_path, mcp, this);
visitor->visit(&path_end);
is_constrained = true;
}