BIGFEATURE: Add `set_path_margin` command (#469)

* Implement set_path_margin command

Adds a new set_path_margin SDC command that applies a signed slack
adjustment to the capture-clock side of timing paths. A positive
margin tightens the path (harder to meet) and a negative margin
loosens it. Supports -setup/-hold/-from/-through/-to scoping,
priority/override semantics matching other exceptions, text and
JSON report output, and write_sdc serialisation.

Adapted from Silimate PR #57; uses upstream/master Mode/Scene and
string_view APIs. Test uses unset_path_exceptions in place of the
Silimate-only reset_path alias.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix nested delaySum call indentation to match project style.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address review: store PathMargin on PathEnd, split tests

Keep the path margin exception on PathEndClkConstrained, add
PathEnd::hasPathMargin for report gating, and split the monolithic
regression into set_path_margin1–6. Rebased onto upstream/master and
document the command in ChangeLog.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Document set_path_margin in OpenSTA.fodt/pdf

Add the command reference, index entry, and note that
unset_path_exceptions also clears path margin exceptions.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Drop [[nodiscard]] from PathEnd::hasPathMargin.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Akash Levy 2026-08-09 09:29:03 -07:00 committed by GitHub
parent 3f4b337e30
commit e9c075ab94
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 1030 additions and 28 deletions

View File

@ -4,6 +4,20 @@ OpenSTA Timing Analyzer Release Notes
This file summarizes user visible changes for each release. This file summarizes user visible changes for each release.
See ApiChangeLog.txt for changes to the STA api. See ApiChangeLog.txt for changes to the STA api.
2026/08/02
----------
The set_path_margin command applies a signed slack adjustment to the
capture-clock side of matching timing paths. A positive margin
tightens the path and a negative margin loosens it.
set_path_margin [-setup] [-hold] [-rise] [-fall]
[-from from_list|-rise_from from_list|-fall_from from_list]
[-through through_list|-rise_through through_list|-fall_through through_list]
[-to to_list|-rise_to to_list|-fall_to to_list]
[-comment comment]
margin
2026/07/20 2026/07/20
---------- ----------

View File

@ -12579,6 +12579,91 @@
</table:table> </table:table>
<text:p text:style-name="Body_20_first">The <text:span text:style-name="Command">set_output_delay</text:span> command is used to specify <text:span text:style-name="T280">the external delay to </text:span><text:span text:style-name="T286">a setup/</text:span><text:span text:style-name="T287">hold</text:span><text:span text:style-name="T286"> check on an output port or internal pin </text:span><text:span text:style-name="T288">that is clocked by </text:span><text:span text:style-name="Command_20_Argument"><text:span text:style-name="T288">clock</text:span></text:span><text:span text:style-name="T286">.</text:span> Unless the <text:span text:style-name="Command">-add_delay</text:span> option is specified any existing <text:span text:style-name="T288">output delays are</text:span> replaced.</text:p> <text:p text:style-name="Body_20_first">The <text:span text:style-name="Command">set_output_delay</text:span> command is used to specify <text:span text:style-name="T280">the external delay to </text:span><text:span text:style-name="T286">a setup/</text:span><text:span text:style-name="T287">hold</text:span><text:span text:style-name="T286"> check on an output port or internal pin </text:span><text:span text:style-name="T288">that is clocked by </text:span><text:span text:style-name="Command_20_Argument"><text:span text:style-name="T288">clock</text:span></text:span><text:span text:style-name="T286">.</text:span> Unless the <text:span text:style-name="Command">-add_delay</text:span> option is specified any existing <text:span text:style-name="T288">output delays are</text:span> replaced.</text:p>
<text:p text:style-name="P276">The <text:span text:style-name="Command">reference_pin</text:span> option is used to specify a <text:span text:style-name="T287">timing check</text:span> with respect to the arrival on a pin in the clock network. For propagated clocks, the <text:span text:style-name="T287">timing check</text:span> is relative to the clock arrival time at the reference pin (the clock source latency and network latency from the clock source to the reference pin). For ideal clocks, <text:span text:style-name="T287">the timing check</text:span> is relative to the reference pin clock source latency. With the <text:span text:style-name="Command">-clock_fall</text:span> flag the <text:span text:style-name="T287">timing check</text:span> is relative to the falling <text:span text:style-name="T280">edge</text:span> <text:span text:style-name="T280">of</text:span> the reference pin. If no clocks arrive at the reference pin the <text:span text:style-name="Command">set_output_delay</text:span> command is ignored. If <text:span text:style-name="Default_20_Paragraph_20_Font">no </text:span><text:span text:style-name="Command">-clock</text:span> is specified the <text:span text:style-name="T287">timing check</text:span> is with respect to all clocks that arrive at the reference pin. The <text:span text:style-name="Command">-source_latency_included</text:span> and <text:span text:style-name="Command">-network_latency_included</text:span> options cannot be used with <text:span text:style-name="Command">-reference_pin</text:span>.</text:p> <text:p text:style-name="P276">The <text:span text:style-name="Command">reference_pin</text:span> option is used to specify a <text:span text:style-name="T287">timing check</text:span> with respect to the arrival on a pin in the clock network. For propagated clocks, the <text:span text:style-name="T287">timing check</text:span> is relative to the clock arrival time at the reference pin (the clock source latency and network latency from the clock source to the reference pin). For ideal clocks, <text:span text:style-name="T287">the timing check</text:span> is relative to the reference pin clock source latency. With the <text:span text:style-name="Command">-clock_fall</text:span> flag the <text:span text:style-name="T287">timing check</text:span> is relative to the falling <text:span text:style-name="T280">edge</text:span> <text:span text:style-name="T280">of</text:span> the reference pin. If no clocks arrive at the reference pin the <text:span text:style-name="Command">set_output_delay</text:span> command is ignored. If <text:span text:style-name="Default_20_Paragraph_20_Font">no </text:span><text:span text:style-name="Command">-clock</text:span> is specified the <text:span text:style-name="T287">timing check</text:span> is with respect to all clocks that arrive at the reference pin. The <text:span text:style-name="Command">-source_latency_included</text:span> and <text:span text:style-name="Command">-network_latency_included</text:span> options cannot be used with <text:span text:style-name="Command">-reference_pin</text:span>.</text:p>
<table:table table:name="TablePathMargin" table:style-name="Table114">
<table:table-column table:style-name="Table114.A"/>
<table:table-column table:style-name="Table114.B"/>
<table:table-row table:style-name="Table114.1">
<table:table-cell table:style-name="Table114.A1" office:value-type="string">
<text:p text:style-name="P42"><text:alphabetical-index-mark-start text:id="IMark31489446320"/><text:span text:style-name="Command_20_Heading">set_path_margin</text:span><text:alphabetical-index-mark-end text:id="IMark31489446320"/></text:p>
</table:table-cell>
<table:table-cell table:style-name="Table114.A1" office:value-type="string">
<text:p text:style-name="P42">[-setup]<text:line-break/>[-hold]<text:line-break/>[-rise]<text:line-break/>[-fall]<text:line-break/>[-from <text:span text:style-name="T32">from_list</text:span>]<text:line-break/>[-rise_from <text:span text:style-name="T32">from_list</text:span>]<text:line-break/>[-fall_from <text:span text:style-name="T32">from_list</text:span>]<text:line-break/>[-through <text:span text:style-name="T32">through_list</text:span>]<text:line-break/>[-rise_through <text:span text:style-name="T32">through_list</text:span>]<text:line-break/>[-fall_through <text:span text:style-name="T32">through_list</text:span>]<text:line-break/>[-to <text:span text:style-name="T32">to_list</text:span>]<text:line-break/>[-rise_to <text:span text:style-name="T32">to_list</text:span>]<text:line-break/>[-fall_to <text:span text:style-name="T32">to_list</text:span>]<text:line-break/>[-comment <text:span text:style-name="T32">comment</text:span>]<text:line-break/><text:span text:style-name="T32">margin</text:span></text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name="Table114.1">
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="P42">-setup</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="Example"><text:span text:style-name="Default_20_Paragraph_20_Font">Apply the margin to setup checks.</text:span></text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name="Table114.1">
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="P42">-hold</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="Example"><text:span text:style-name="Default_20_Paragraph_20_Font">Apply the margin to hold checks.</text:span></text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name="Table114.1">
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="P42">-rise</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="Example"><text:span text:style-name="Default_20_Paragraph_20_Font">Apply the margin to rising path edges.</text:span></text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name="Table114.1">
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="P42">-fall</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="Example"><text:span text:style-name="Default_20_Paragraph_20_Font">Apply the margin to falling path edges.</text:span></text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name="Table114.1">
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="P48"><text:span text:style-name="T30">-</text:span><text:span text:style-name="T272">from </text:span>from_list</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="Example"><text:span text:style-name="Default_20_Paragraph_20_Font">A list of clocks, instances, ports or pins.</text:span></text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name="Table114.1">
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="P48"><text:span text:style-name="T30">-</text:span><text:span text:style-name="T272">through </text:span>through_list</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="Example"><text:span text:style-name="Default_20_Paragraph_20_Font">A list of instances, pins or nets.</text:span></text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name="Table114.1">
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="P48"><text:span text:style-name="T30">-</text:span><text:span text:style-name="T272">to </text:span>to_list</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="Example"><text:span text:style-name="Default_20_Paragraph_20_Font">A list of clocks, instances, ports or pins.</text:span></text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name="Table114.1">
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="P48">-comment comment</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="Example"><text:span text:style-name="Default_20_Paragraph_20_Font">Optional comment written by </text:span><text:span text:style-name="Command">write_sdc</text:span><text:span text:style-name="Default_20_Paragraph_20_Font">.</text:span></text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name="Table114.1">
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="P48">margin</text:p>
</table:table-cell>
<table:table-cell table:style-name="Table114.A2" office:value-type="string">
<text:p text:style-name="Example"><text:span text:style-name="Default_20_Paragraph_20_Font">Signed slack adjustment applied on the capture clock. A positive margin tightens the path and a negative margin loosens it.</text:span></text:p>
</table:table-cell>
</table:table-row>
</table:table>
<text:p text:style-name="Body_20_first">The <text:span text:style-name="Command">set_path_margin</text:span> command applies a signed slack adjustment to matching timing paths on the capture-clock side. A positive margin makes the path harder to meet and a negative margin makes it easier. If neither <text:span text:style-name="Command">-setup</text:span> nor <text:span text:style-name="Command">-hold</text:span> is specified the margin applies to both. See <text:span text:style-name="Command">set_false_path</text:span> for a description of allowed <text:span text:style-name="Command_20_Argument">from_list</text:span>, <text:span text:style-name="Command_20_Argument">through_list</text:span> and <text:span text:style-name="Command_20_Argument">to_list</text:span> objects. At least one of <text:span text:style-name="Command">-from</text:span>, <text:span text:style-name="Command">-through</text:span>, or <text:span text:style-name="Command">-to</text:span> is required. Matching exceptions are removed with <text:span text:style-name="Command">unset_path_exceptions</text:span>.</text:p>
<table:table table:name="Table115" table:style-name="Table115"> <table:table table:name="Table115" table:style-name="Table115">
<table:table-column table:style-name="Table115.A"/> <table:table-column table:style-name="Table115.A"/>
<table:table-column table:style-name="Table115.B"/> <table:table-column table:style-name="Table115.B"/>
@ -13724,7 +13809,7 @@
</table:table-cell> </table:table-cell>
</table:table-row> </table:table-row>
</table:table> </table:table>
<text:p text:style-name="Body_20_first">The unset_path_exceptions command removes any matching set_false_path, set_multicycle_path, set_max_delay, and set_min_delay exceptions.</text:p> <text:p text:style-name="Body_20_first">The <text:span text:style-name="Command">unset_path_exceptions</text:span> command removes any matching <text:span text:style-name="Command">set_false_path</text:span>, <text:span text:style-name="Command">set_multicycle_path</text:span>, <text:span text:style-name="Command">set_max_delay</text:span>, <text:span text:style-name="Command">set_min_delay</text:span>, and <text:span text:style-name="Command">set_path_margin</text:span> exceptions.</text:p>
<text:p text:style-name="P304"/> <text:p text:style-name="P304"/>
<table:table table:name="Table164" table:style-name="Table164"> <table:table table:name="Table164" table:style-name="Table164">
<table:table-column table:style-name="Table164.A"/> <table:table-column table:style-name="Table164.A"/>
@ -14587,6 +14672,7 @@
<text:p text:style-name="P339">set_multicycle_path<text:tab/>67</text:p> <text:p text:style-name="P339">set_multicycle_path<text:tab/>67</text:p>
<text:p text:style-name="P339">set_operating_conditions<text:tab/>68</text:p> <text:p text:style-name="P339">set_operating_conditions<text:tab/>68</text:p>
<text:p text:style-name="P339">set_output_delay<text:tab/>69</text:p> <text:p text:style-name="P339">set_output_delay<text:tab/>69</text:p>
<text:p text:style-name="P339">set_path_margin<text:tab/>70</text:p>
<text:p text:style-name="P339">set_port_fanout_number<text:tab/>70</text:p> <text:p text:style-name="P339">set_port_fanout_number<text:tab/>70</text:p>
<text:p text:style-name="P339">set_power_activity<text:tab/>70</text:p> <text:p text:style-name="P339">set_power_activity<text:tab/>70</text:p>
<text:p text:style-name="P339">set_propagated_clock<text:tab/>71</text:p> <text:p text:style-name="P339">set_propagated_clock<text:tab/>71</text:p>

Binary file not shown.

View File

@ -66,6 +66,7 @@ public:
virtual bool isLoop() const { return false; } virtual bool isLoop() const { return false; }
virtual bool isMultiCycle() const { return false; } virtual bool isMultiCycle() const { return false; }
virtual bool isPathDelay() const { return false; } virtual bool isPathDelay() const { return false; }
virtual bool isPathMargin() const { return false; }
virtual bool isGroupPath() const { return false; } virtual bool isGroupPath() const { return false; }
virtual bool isFilter() const { return false; } virtual bool isFilter() const { return false; }
virtual ExceptionPathType type() const = 0; virtual ExceptionPathType type() const = 0;
@ -101,6 +102,7 @@ public:
static int pathDelayPriority() { return 3000; } static int pathDelayPriority() { return 3000; }
static int multiCyclePathPriority() { return 2000; } static int multiCyclePathPriority() { return 2000; }
static int filterPathPriority() { return 1000; } static int filterPathPriority() { return 1000; }
static int pathMarginPriority() { return 500; }
static int groupPathPriority() { return 0; } static int groupPathPriority() { return 0; }
// Compare the value (path delay or cycle count) to another exception // Compare the value (path delay or cycle count) to another exception
// of the same priority. Because the exception "values" are floats, // of the same priority. Because the exception "values" are floats,
@ -130,6 +132,7 @@ public:
virtual bool useEndClk() const { return false; } virtual bool useEndClk() const { return false; }
virtual int pathMultiplier() const { return 0; } virtual int pathMultiplier() const { return 0; }
virtual float delay() const { return 0.0; } virtual float delay() const { return 0.0; }
virtual float margin() const { return 0.0; }
virtual std::string_view name() const { return {}; } virtual std::string_view name() const { return {}; }
virtual bool isDefault() const { return false; } virtual bool isDefault() const { return false; }
virtual bool ignoreClkLatency() const { return false; } virtual bool ignoreClkLatency() const { return false; }
@ -227,6 +230,35 @@ protected:
float delay_; float delay_;
}; };
// set_path_margin
class PathMargin : public ExceptionPath
{
public:
PathMargin(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
const MinMaxAll *min_max,
float margin,
bool own_pts,
std::string_view comment);
ExceptionPath *clone(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
bool own_pts) override;
bool isPathMargin() const override { return true; }
ExceptionPathType type() const override
{ return ExceptionPathType::path_margin; }
std::string_view typeString() const override;
bool mergeable(ExceptionPath *exception) const override;
bool overrides(ExceptionPath *exception) const override;
float margin() const override { return margin_; }
int typePriority() const override;
bool tighterThan(ExceptionPath *exception) const override;
protected:
float margin_;
};
// set_multicycle_path // set_multicycle_path
class MultiCyclePath : public ExceptionPath class MultiCyclePath : public ExceptionPath
{ {

View File

@ -135,6 +135,10 @@ public:
// Target clock uncertainty + inter-clk uncertainty. // Target clock uncertainty + inter-clk uncertainty.
virtual float targetClkUncertainty(const StaState *sta) const; virtual float targetClkUncertainty(const StaState *sta) const;
virtual float targetClkMcpAdjustment(const StaState *sta) const; virtual float targetClkMcpAdjustment(const StaState *sta) const;
// Target clock path margin (set_path_margin).
virtual float targetClkPathMargin(const StaState *sta) const;
virtual bool hasPathMargin() const { return false; }
virtual PathMargin *pathMargin() const { return nullptr; }
virtual const TimingRole *checkRole(const StaState *sta) const; virtual const TimingRole *checkRole(const StaState *sta) const;
const TimingRole *checkGenericRole(const StaState *sta) const; const TimingRole *checkGenericRole(const StaState *sta) const;
virtual bool pathDelayMarginIsExternal() const; virtual bool pathDelayMarginIsExternal() const;
@ -260,6 +264,9 @@ public:
float targetNonInterClkUncertainty(const StaState *sta) const override; float targetNonInterClkUncertainty(const StaState *sta) const override;
float interClkUncertainty(const StaState *sta) const override; float interClkUncertainty(const StaState *sta) const override;
float targetClkUncertainty(const StaState *sta) const override; float targetClkUncertainty(const StaState *sta) const override;
float targetClkPathMargin(const StaState *sta) const override;
bool hasPathMargin() const override { return path_margin_ != nullptr; }
PathMargin *pathMargin() const override { return path_margin_; }
Crpr crpr(const StaState *sta) const override; Crpr crpr(const StaState *sta) const override;
Required requiredTime(const StaState *sta) const override; Required requiredTime(const StaState *sta) const override;
Slack slack(const StaState *sta) const override; Slack slack(const StaState *sta) const override;
@ -270,7 +277,8 @@ public:
protected: protected:
PathEndClkConstrained(Path *path, PathEndClkConstrained(Path *path,
Path *clk_path); Path *clk_path,
PathMargin *path_margin);
float sourceClkOffset(const ClockEdge *src_clk_edge, float sourceClkOffset(const ClockEdge *src_clk_edge,
const ClockEdge *tgt_clk_edge, const ClockEdge *tgt_clk_edge,
const TimingRole *check_role, const TimingRole *check_role,
@ -280,6 +288,7 @@ protected:
virtual Required requiredTimeNoCrpr(const StaState *sta) const; virtual Required requiredTimeNoCrpr(const StaState *sta) const;
Path *clk_path_; Path *clk_path_;
PathMargin *path_margin_;
mutable Crpr crpr_; mutable Crpr crpr_;
mutable bool crpr_valid_{false}; mutable bool crpr_valid_{false};
}; };
@ -295,7 +304,8 @@ public:
protected: protected:
PathEndClkConstrainedMcp(Path *path, PathEndClkConstrainedMcp(Path *path,
Path *clk_path, Path *clk_path,
MultiCyclePath *mcp); MultiCyclePath *mcp,
PathMargin *path_margin);
float checkMcpAdjustment(const Path *path, float checkMcpAdjustment(const Path *path,
const ClockEdge *tgt_clk_edge, const ClockEdge *tgt_clk_edge,
const StaState *sta) const; const StaState *sta) const;
@ -316,6 +326,7 @@ public:
Edge *check_edge, Edge *check_edge,
Path *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathMargin *path_margin,
const StaState *sta); const StaState *sta);
PathEnd *copy() const override; PathEnd *copy() const override;
Type type() const override; Type type() const override;
@ -348,6 +359,7 @@ public:
Edge *check_edge, Edge *check_edge,
Path *disable_path, Path *disable_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathMargin *path_margin,
PathDelay *path_delay, PathDelay *path_delay,
const StaState *sta); const StaState *sta);
Type type() const override; Type type() const override;
@ -404,6 +416,7 @@ public:
Path *path, Path *path,
Path *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathMargin *path_margin,
const StaState *sta); const StaState *sta);
PathEnd *copy() const override; PathEnd *copy() const override;
Type type() const override; Type type() const override;
@ -443,6 +456,7 @@ public:
Path *clk_path, Path *clk_path,
const TimingRole *check_role, const TimingRole *check_role,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathMargin *path_margin,
ArcDelay margin, ArcDelay margin,
const StaState *sta); const StaState *sta);
PathEnd *copy() const override; PathEnd *copy() const override;
@ -468,6 +482,7 @@ public:
Path *data_path, Path *data_path,
Path *data_clk_path, Path *data_clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathMargin *path_margin,
const StaState *sta); const StaState *sta);
PathEnd *copy() const override; PathEnd *copy() const override;
Type type() const override; Type type() const override;

View File

@ -757,6 +757,12 @@ public:
bool break_path, bool break_path,
float delay, float delay,
std::string_view comment); std::string_view comment);
void makePathMargin(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
const MinMaxAll *min_max,
float margin,
std::string_view comment);
bool pathDelaysWithoutTo() const { return path_delays_without_to_; } bool pathDelaysWithoutTo() const { return path_delays_without_to_; }
// Delete matching false/multicycle/path_delay exceptions. // Delete matching false/multicycle/path_delay exceptions.
// Caller owns from, thrus, to exception points (and must delete them). // Caller owns from, thrus, to exception points (and must delete them).

View File

@ -44,6 +44,7 @@ class InputDelay;
class OutputDelay; class OutputDelay;
class FalsePath; class FalsePath;
class PathDelay; class PathDelay;
class PathMargin;
class MultiCyclePath; class MultiCyclePath;
class FilterPath; class FilterPath;
class GroupPath; class GroupPath;
@ -69,6 +70,7 @@ class PortDelay;
enum class AnalysisType { single, bc_wc, ocv }; enum class AnalysisType { single, bc_wc, ocv };
enum class ExceptionPathType { false_path, loop, multi_cycle, path_delay, enum class ExceptionPathType { false_path, loop, multi_cycle, path_delay,
path_margin,
group_path, filter, any}; group_path, filter, any};
enum class ClockSense { positive, negative, stop }; enum class ClockSense { positive, negative, stop };

View File

@ -654,6 +654,13 @@ public:
float delay, float delay,
std::string_view comment, std::string_view comment,
Sdc *sdc); Sdc *sdc);
void makePathMargin(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
const MinMaxAll *min_max,
float margin,
std::string_view comment,
Sdc *sdc);
void makeGroupPath(std::string_view name, void makeGroupPath(std::string_view name,
bool is_default, bool is_default,
ExceptionFrom *from, ExceptionFrom *from,

View File

@ -131,6 +131,11 @@ protected:
const Pin *pin, const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
const MinMax *min_max); const MinMax *min_max);
PathMargin *pathMarginTo(const Path *path,
const Pin *pin,
const RiseFall *rf,
const ClockEdge *clk_edge,
const MinMax *min_max) const;
ExceptionPath *exceptionTo(const Path *path, ExceptionPath *exceptionTo(const Path *path,
const Pin *pin, const Pin *pin,
const RiseFall *rf, const RiseFall *rf,

View File

@ -559,6 +559,64 @@ PathDelay::overrides(ExceptionPath *exception) const
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
PathMargin::PathMargin(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
const MinMaxAll *min_max,
float margin,
bool own_pts,
std::string_view comment) :
ExceptionPath(from, thrus, to, min_max, own_pts,
pathMarginPriority() + fromThruToPriority(from, thrus, to),
comment),
margin_(margin)
{
}
ExceptionPath *
PathMargin::clone(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
bool own_pts)
{
return new PathMargin(from, thrus, to, min_max_, margin_, own_pts, comment_);
}
int
PathMargin::typePriority() const
{
return pathMarginPriority();
}
bool
PathMargin::tighterThan(ExceptionPath *) const
{
return false;
}
std::string_view
PathMargin::typeString() const
{
return "Margin";
}
bool
PathMargin::mergeable(ExceptionPath *) const
{
return false;
}
bool
PathMargin::overrides(ExceptionPath *exception) const
{
// A later set_path_margin with the same scope replaces the earlier one.
return exception->isPathMargin()
&& exception->priority() == priority_
&& exception->minMax() == min_max_;
}
////////////////////////////////////////////////////////////////
FalsePath::FalsePath(ExceptionFrom *from, FalsePath::FalsePath(ExceptionFrom *from,
ExceptionThruSeq *thrus, ExceptionThruSeq *thrus,
ExceptionTo *to, ExceptionTo *to,

View File

@ -3958,6 +3958,20 @@ Sdc::makePathDelay(ExceptionFrom *from,
addException(exception); addException(exception);
} }
void
Sdc::makePathMargin(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
const MinMaxAll *min_max,
float margin,
std::string_view comment)
{
checkFromThrusTo(from, thrus, to);
PathMargin *exception = new PathMargin(from, thrus, to, min_max,
margin, true, comment);
addException(exception);
}
void void
Sdc::recordPathDelayInternalFrom(ExceptionPath *exception) Sdc::recordPathDelayInternalFrom(ExceptionPath *exception)
{ {
@ -4365,7 +4379,8 @@ Sdc::addException1(ExceptionPath *exception)
void void
Sdc::addException2(ExceptionPath *exception) Sdc::addException2(ExceptionPath *exception)
{ {
if (exception->isMultiCycle() || exception->isPathDelay()) if (exception->isMultiCycle() || exception->isPathDelay()
|| exception->isPathMargin())
deleteMatchingExceptions(exception); deleteMatchingExceptions(exception);
recordException(exception); recordException(exception);
mergeException(exception); mergeException(exception);

View File

@ -838,6 +838,19 @@ make_path_delay(ExceptionFrom *from,
delay, std::move(comment), sdc); delay, std::move(comment), sdc);
} }
void
make_path_margin(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
const MinMaxAll *min_max,
float margin,
std::string_view comment)
{
Sta *sta = Sta::sta();
Sdc *sdc = sta->cmdSdc();
sta->makePathMargin(from, thrus, to, min_max, margin, comment, sdc);
}
void void
reset_path_cmd(ExceptionFrom * reset_path_cmd(ExceptionFrom *
from, ExceptionThruSeq *thrus, from, ExceptionThruSeq *thrus,

View File

@ -2430,6 +2430,61 @@ proc set_min_delay { args } {
################################################################ ################################################################
define_cmd_args "set_path_margin" \
{[-setup] [-hold] [-rise] [-fall] [-comment comment]\
[-from from_list] [-rise_from from_list] [-fall_from from_list]\
[-through|-thr|-th through_list] [-rise_through|-rise_thr|-rise_th through_list]\
[-fall_through|-fall_thr|-fall_th through_list]\
[-to to_list] [-rise_to to_list] [-fall_to to_list] margin}
proc set_path_margin { args } {
parse_key_args "set_path_margin" args \
keys {-from -rise_from -fall_from -to -rise_to -fall_to -comment} \
flags {-rise -fall -setup -hold} 0
# Applies to setup, hold, or both.
set min_max "min_max"
if { [info exists flags(-setup)] && ![info exists flags(-hold)] } {
set min_max "max"
} elseif { [info exists flags(-hold)] && ![info exists flags(-setup)] } {
set min_max "min"
}
# Validate arguments.
set cmd "set_path_margin"
set arg_error 0
set from [parse_from_arg keys arg_error]
set thrus [parse_thrus_arg args arg_error]
set to [parse_to_arg keys flags arg_error]
check_exception_pins $from $to
if { $arg_error } {
delete_from_thrus_to $from $thrus $to
return
}
# Validate margin value count and argument type.
check_for_key_args $cmd args
if { [llength $args] == 0 } {
delete_from_thrus_to $from $thrus $to
sta_error 1800 "missing margin argument."
} elseif { [llength $args] > 1 } {
sta_warn 1801 "'$args' ignored."
}
if { $from == "NULL" && $thrus == "" && $to == "NULL" } {
delete_from_thrus_to $from $thrus $to
sta_error 1802 "-from, -through or -to required."
}
# Parse margin value.
set margin [lindex $args 0]
check_float "set_path_margin margin" $margin
set margin [time_ui_sta $margin]
set comment [parse_comment_key keys]
make_path_margin $from $thrus $to $min_max $margin $comment
}
################################################################
define_cmd_args "set_min_pulse_width" {[-low] [-high] value [objects]} define_cmd_args "set_min_pulse_width" {[-low] [-high] value [objects]}
proc set_min_pulse_width { args } { proc set_min_pulse_width { args } {

View File

@ -1231,6 +1231,10 @@ WriteSdc::writeExceptionCmd(ExceptionPath *exception) const
if (exception->ignoreClkLatency()) if (exception->ignoreClkLatency())
sta::print(stream_, " -ignore_clock_latency"); sta::print(stream_, " -ignore_clock_latency");
} }
else if (exception->isPathMargin()) {
sta::print(stream_, "set_path_margin");
writeSetupHoldFlag(exception->minMax());
}
else if (exception->isGroupPath()) { else if (exception->isGroupPath()) {
if (exception->isDefault()) if (exception->isDefault())
sta::print(stream_, "group_path -default"); sta::print(stream_, "group_path -default");
@ -1251,6 +1255,10 @@ WriteSdc::writeExceptionValue(ExceptionPath *exception) const
sta::print(stream_, " "); sta::print(stream_, " ");
writeTime(exception->delay()); writeTime(exception->delay());
} }
else if (exception->isPathMargin()) {
sta::print(stream_, " ");
writeTime(exception->margin());
}
} }
void void

View File

@ -222,6 +222,12 @@ PathEnd::targetClkMcpAdjustment(const StaState *) const
return 0.0; return 0.0;
} }
float
PathEnd::targetClkPathMargin(const StaState *) const
{
return 0.0;
}
const TimingRole * const TimingRole *
PathEnd::checkRole(const StaState *) const PathEnd::checkRole(const StaState *) const
{ {
@ -511,9 +517,11 @@ PathEndUnconstrained::typeName() const
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
PathEndClkConstrained::PathEndClkConstrained(Path *path, PathEndClkConstrained::PathEndClkConstrained(Path *path,
Path *clk_path) : Path *clk_path,
PathMargin *path_margin) :
PathEnd(path), PathEnd(path),
clk_path_(clk_path), clk_path_(clk_path),
path_margin_(path_margin),
crpr_(0.0) crpr_(0.0)
{ {
} }
@ -630,8 +638,9 @@ PathEndClkConstrained::targetClkArrivalNoCrpr(const StaState *sta) const
targetClkPath(), targetClkPath(),
checkRole(sta), checkRole(sta),
sdc); sdc);
return delaySum(delaySum(clk_arrival, uncertainty, sta), return delaySum(delaySum(delaySum(clk_arrival, uncertainty, sta),
targetClkMcpAdjustment(sta), sta); targetClkMcpAdjustment(sta), sta),
targetClkPathMargin(sta), sta);
} }
Delay Delay
@ -692,6 +701,17 @@ PathEndClkConstrained::targetClkUncertainty(const StaState *sta) const
targetClkPath(), checkRole(sta), sdc); targetClkPath(), checkRole(sta), sdc);
} }
float
PathEndClkConstrained::targetClkPathMargin(const StaState *sta) const
{
if (!path_margin_)
return 0.0;
float margin = path_margin_->margin();
if (checkRole(sta)->genericRole() == TimingRole::setup())
margin = -margin;
return margin;
}
Crpr Crpr
PathEndClkConstrained::crpr(const StaState *sta) const PathEndClkConstrained::crpr(const StaState *sta) const
{ {
@ -752,8 +772,9 @@ PathEndClkConstrained::exceptPathCmp(const PathEnd *path_end,
PathEndClkConstrainedMcp::PathEndClkConstrainedMcp(Path *path, PathEndClkConstrainedMcp::PathEndClkConstrainedMcp(Path *path,
Path *clk_path, Path *clk_path,
MultiCyclePath *mcp) : MultiCyclePath *mcp,
PathEndClkConstrained(path, clk_path), PathMargin *path_margin) :
PathEndClkConstrained(path, clk_path, path_margin),
mcp_(mcp) mcp_(mcp)
{ {
} }
@ -921,8 +942,9 @@ PathEndCheck::PathEndCheck(Path *path,
Edge *check_edge, Edge *check_edge,
Path *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathMargin *path_margin,
const StaState *) : const StaState *) :
PathEndClkConstrainedMcp(path, clk_path, mcp), PathEndClkConstrainedMcp(path, clk_path, mcp, path_margin),
check_arc_(check_arc), check_arc_(check_arc),
check_edge_(check_edge) check_edge_(check_edge)
{ {
@ -1082,9 +1104,10 @@ PathEndLatchCheck::PathEndLatchCheck(Path *path,
Edge *check_edge, Edge *check_edge,
Path *disable_path, Path *disable_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathMargin *path_margin,
PathDelay *path_delay, PathDelay *path_delay,
const StaState *sta) : const StaState *sta) :
PathEndCheck(path, check_arc, check_edge, nullptr, mcp, sta), PathEndCheck(path, check_arc, check_edge, nullptr, mcp, path_margin, sta),
disable_path_(disable_path), disable_path_(disable_path),
path_delay_(path_delay), path_delay_(path_delay),
src_clk_arrival_(0.0) src_clk_arrival_(0.0)
@ -1300,9 +1323,10 @@ PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay,
Path *path, Path *path,
Path *clk_path, Path *clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathMargin *path_margin,
const StaState *) : const StaState *) :
// No target clk_path_ for output delays. // No target clk_path_ for output delays.
PathEndClkConstrainedMcp(path, clk_path, mcp), PathEndClkConstrainedMcp(path, clk_path, mcp, path_margin),
output_delay_(output_delay) output_delay_(output_delay)
{ {
} }
@ -1494,9 +1518,10 @@ PathEndGatedClock::PathEndGatedClock(Path *gating_ref,
Path *clk_path, Path *clk_path,
const TimingRole *check_role, const TimingRole *check_role,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathMargin *path_margin,
ArcDelay margin, ArcDelay margin,
const StaState *) : const StaState *) :
PathEndClkConstrainedMcp(gating_ref, clk_path, mcp), PathEndClkConstrainedMcp(gating_ref, clk_path, mcp, path_margin),
check_role_(check_role), check_role_(check_role),
margin_(margin) margin_(margin)
{ {
@ -1564,8 +1589,9 @@ PathEndDataCheck::PathEndDataCheck(DataCheck *check,
Path *data_path, Path *data_path,
Path *data_clk_path, Path *data_clk_path,
MultiCyclePath *mcp, MultiCyclePath *mcp,
PathMargin *path_margin,
const StaState *sta) : const StaState *sta) :
PathEndClkConstrainedMcp(data_path, nullptr, mcp), PathEndClkConstrainedMcp(data_path, nullptr, mcp, path_margin),
data_clk_path_(data_clk_path), data_clk_path_(data_clk_path),
check_(check) check_(check)
{ {
@ -1711,7 +1737,7 @@ PathEndDataCheck::exceptPathCmp(const PathEnd *path_end,
PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay, PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay,
Path *path, Path *path,
const StaState *sta): const StaState *sta):
PathEndClkConstrained(path, nullptr), PathEndClkConstrained(path, nullptr, nullptr),
path_delay_(path_delay), path_delay_(path_delay),
check_arc_(nullptr), check_arc_(nullptr),
check_edge_(nullptr), check_edge_(nullptr),
@ -1724,7 +1750,7 @@ PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay,
Path *path, Path *path,
OutputDelay *output_delay, OutputDelay *output_delay,
const StaState *sta): const StaState *sta):
PathEndClkConstrained(path, nullptr), PathEndClkConstrained(path, nullptr, nullptr),
path_delay_(path_delay), path_delay_(path_delay),
check_arc_(nullptr), check_arc_(nullptr),
check_edge_(nullptr), check_edge_(nullptr),
@ -1739,7 +1765,7 @@ PathEndPathDelay::PathEndPathDelay(PathDelay *path_delay,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge, Edge *check_edge,
const StaState *sta) : const StaState *sta) :
PathEndClkConstrained(path, clk_path), PathEndClkConstrained(path, clk_path, nullptr),
path_delay_(path_delay), path_delay_(path_delay),
check_arc_(check_arc), check_arc_(check_arc),
check_edge_(check_edge), check_edge_(check_edge),

View File

@ -1134,6 +1134,9 @@ ReportPath::reportJson(const PathEnd *end,
delayAsFloat(end->checkCrpr(this))); delayAsFloat(end->checkCrpr(this)));
result += sta::format(" \"margin\": {:.3e},\n", result += sta::format(" \"margin\": {:.3e},\n",
delayAsFloat(end->margin(this))); delayAsFloat(end->margin(this)));
if (end->hasPathMargin())
result += sta::format(" \"path_margin\": {:.3e},\n",
end->targetClkPathMargin(this));
result += sta::format(" \"required_time\": {:.3e},\n", result += sta::format(" \"required_time\": {:.3e},\n",
delayAsFloat(end->requiredTimeOffset(this))); delayAsFloat(end->requiredTimeOffset(this)));
result += sta::format(" \"slack\": {:.3e}\n", result += sta::format(" \"slack\": {:.3e}\n",
@ -2569,6 +2572,11 @@ ReportPath::reportClkUncertainty(const PathEnd *end,
if (inter_uncertainty != 0.0) if (inter_uncertainty != 0.0)
reportLine("inter-clock uncertainty", inter_uncertainty, reportLine("inter-clock uncertainty", inter_uncertainty,
clk_arrival, early_late); clk_arrival, early_late);
if (end->hasPathMargin()) {
float margin = end->targetClkPathMargin(this);
clk_arrival = delaySum(clk_arrival, margin, this);
reportLine("path margin", margin, clk_arrival, early_late);
}
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -2070,6 +2070,19 @@ Sta::makePathDelay(ExceptionFrom *from,
search_->arrivalsInvalid(); search_->arrivalsInvalid();
} }
void
Sta::makePathMargin(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
const MinMaxAll *min_max,
float margin,
std::string_view comment,
Sdc *sdc)
{
sdc->makePathMargin(from, thrus, to, min_max, margin, comment);
search_->arrivalsInvalid();
}
void void
Sta::resetPath(ExceptionFrom *from, Sta::resetPath(ExceptionFrom *from,
ExceptionThruSeq *thrus, ExceptionThruSeq *thrus,

View File

@ -185,19 +185,22 @@ VisitPathEnds::visitCheckEnd(const Pin *pin,
&& (exception == nullptr && (exception == nullptr
|| exception->isFilter() || exception->isFilter()
|| exception->isGroupPath() || exception->isGroupPath()
|| exception->isMultiCycle())) { || exception->isMultiCycle()
|| exception->isPathMargin())) {
MultiCyclePath *mcp=dynamic_cast<MultiCyclePath*>(exception); MultiCyclePath *mcp=dynamic_cast<MultiCyclePath*>(exception);
PathMargin *path_margin = pathMarginTo(path, pin, end_rf,
tgt_clk_edge, min_max);
if (network_->isLatchData(pin) if (network_->isLatchData(pin)
&& check_role == TimingRole::setup()) { && check_role == TimingRole::setup()) {
PathEndLatchCheck path_end(path, check_arc, edge, PathEndLatchCheck path_end(path, check_arc, edge,
tgt_clk_path, mcp, nullptr, tgt_clk_path, mcp, path_margin,
this); nullptr, this);
visitor->visit(&path_end); visitor->visit(&path_end);
is_constrained = true; is_constrained = true;
} }
else { else {
PathEndCheck path_end(path, check_arc, edge, PathEndCheck path_end(path, check_arc, edge,
tgt_clk_path, mcp, this); tgt_clk_path, mcp, path_margin, this);
visitor->visit(&path_end); visitor->visit(&path_end);
is_constrained = true; is_constrained = true;
} }
@ -210,7 +213,7 @@ VisitPathEnds::visitCheckEnd(const Pin *pin,
if (network_->isLatchData(pin) if (network_->isLatchData(pin)
&& check_role == TimingRole::setup()) { && check_role == TimingRole::setup()) {
PathEndLatchCheck path_end(path, check_arc, edge, PathEndLatchCheck path_end(path, check_arc, edge,
tgt_clk_path, nullptr, tgt_clk_path, nullptr, nullptr,
path_delay, this); path_delay, this);
visitor->visit(&path_end); visitor->visit(&path_end);
} }
@ -369,9 +372,13 @@ VisitPathEnds::visitOutputDelayEnd1(OutputDelay *output_delay,
&& (exception == nullptr && (exception == nullptr
|| exception->isFilter() || exception->isFilter()
|| exception->isGroupPath() || exception->isGroupPath()
|| exception->isMultiCycle())) { || exception->isMultiCycle()
|| exception->isPathMargin())) {
MultiCyclePath *mcp = dynamic_cast<MultiCyclePath*>(exception); MultiCyclePath *mcp = dynamic_cast<MultiCyclePath*>(exception);
PathEndOutputDelay path_end(output_delay, path, ref_path, mcp, this); PathMargin *path_margin = pathMarginTo(path, pin, end_rf,
tgt_clk_edge, min_max);
PathEndOutputDelay path_end(output_delay, path, ref_path, mcp,
path_margin, this);
visitor->visit(&path_end); visitor->visit(&path_end);
is_constrained = true; is_constrained = true;
} }
@ -442,13 +449,16 @@ VisitPathEnds::visitGatedClkEnd(const Pin *pin,
&& (exception == nullptr && (exception == nullptr
|| exception->isFilter() || exception->isFilter()
|| exception->isGroupPath() || exception->isGroupPath()
|| exception->isMultiCycle()) || exception->isMultiCycle()
|| exception->isPathMargin())
&& (!filtered && (!filtered
|| search_->matchesFilter(path, clk_edge))) { || search_->matchesFilter(path, clk_edge))) {
MultiCyclePath *mcp = MultiCyclePath *mcp =
dynamic_cast<MultiCyclePath *>(exception); dynamic_cast<MultiCyclePath *>(exception);
PathMargin *path_margin = pathMarginTo(path, pin, end_rf,
clk_edge, min_max);
PathEndGatedClock path_end(path, clk_path, check_role, PathEndGatedClock path_end(path, clk_path, check_role,
mcp, margin, this); mcp, path_margin, margin, this);
visitor->visit(&path_end); visitor->visit(&path_end);
is_constrained = true; is_constrained = true;
} }
@ -565,11 +575,15 @@ VisitPathEnds::visitDataCheckEnd1(DataCheck *check,
&& (exception == nullptr && (exception == nullptr
|| exception->isFilter() || exception->isFilter()
|| exception->isGroupPath() || exception->isGroupPath()
|| exception->isMultiCycle()) || exception->isMultiCycle()
|| exception->isPathMargin())
&& (!filtered && (!filtered
|| search_->matchesFilter(path, tgt_clk_edge))) { || search_->matchesFilter(path, tgt_clk_edge))) {
MultiCyclePath *mcp=dynamic_cast<MultiCyclePath*>(exception); MultiCyclePath *mcp=dynamic_cast<MultiCyclePath*>(exception);
PathEndDataCheck path_end(check, path, tgt_clk_path, mcp, this); PathMargin *path_margin = pathMarginTo(path, pin, end_rf,
tgt_clk_edge, min_max);
PathEndDataCheck path_end(check, path, tgt_clk_path, mcp,
path_margin, this);
visitor->visit(&path_end); visitor->visit(&path_end);
is_constrained = true; is_constrained = true;
} }
@ -639,6 +653,19 @@ VisitPathEnds::pathDelayTo(Path *path,
return dynamic_cast<PathDelay*>(exception); return dynamic_cast<PathDelay*>(exception);
} }
PathMargin *
VisitPathEnds::pathMarginTo(const Path *path,
const Pin *pin,
const RiseFall *rf,
const ClockEdge *clk_edge,
const MinMax *min_max) const
{
ExceptionPath *exception =
search_->exceptionTo(ExceptionPathType::path_margin, path, pin, rf,
clk_edge, min_max, false, false, path->sdc(this));
return dynamic_cast<PathMargin*>(exception);
}
ExceptionPath * ExceptionPath *
VisitPathEnds::exceptionTo(const Path *path, VisitPathEnds::exceptionTo(const Path *path,
const Pin *pin, const Pin *pin,

View File

@ -168,6 +168,12 @@ record_public_tests {
report_checks_src_attr report_checks_src_attr
report_json1 report_json1
report_json2 report_json2
set_path_margin1
set_path_margin2
set_path_margin3
set_path_margin4
set_path_margin5
set_path_margin6
slash_port_test slash_port_test
suppress_msg suppress_msg
user_properties user_properties

122
test/set_path_margin1.ok Normal file
View File

@ -0,0 +1,122 @@
Startpoint: r2 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r2/CK (DFF_X1)
0.0772 0.0772 v r2/Q (DFF_X1)
0.0233 0.1006 v u1/Z (BUF_X1)
0.0273 0.1278 v u2/ZN (AND2_X1)
0.0000 0.1278 v r3/D (DFF_X1)
0.1278 data arrival time
10.0000 10.0000 clock clk (rise edge)
0.0000 10.0000 clock network delay (ideal)
-0.5000 9.5000 path margin
0.0000 9.5000 clock reconvergence pessimism
9.5000 ^ r3/CK (DFF_X1)
-0.0390 9.4610 library setup time
9.4610 data required time
-------------------------------------------------------------
9.4610 data required time
-0.1278 data arrival time
-------------------------------------------------------------
9.3332 slack (MET)
setup_to_tighten -5.000e-10
Startpoint: r1 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: min
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r1/CK (DFF_X1)
0.0772 0.0772 v r1/Q (DFF_X1)
0.0254 0.1026 v u2/ZN (AND2_X1)
0.0000 0.1026 v r3/D (DFF_X1)
0.1026 data arrival time
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.5000 0.5000 path margin
0.0000 0.5000 clock reconvergence pessimism
0.5000 ^ r3/CK (DFF_X1)
0.0016 0.5016 library hold time
0.5016 data required time
-------------------------------------------------------------
0.5016 data required time
-0.1026 data arrival time
-------------------------------------------------------------
-0.3990 slack (VIOLATED)
hold_to_tighten 5.000e-10
Startpoint: r2 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r2/CK (DFF_X1)
0.0772 0.0772 v r2/Q (DFF_X1)
0.0233 0.1006 v u1/Z (BUF_X1)
0.0273 0.1278 v u2/ZN (AND2_X1)
0.0000 0.1278 v r3/D (DFF_X1)
0.1278 data arrival time
10.0000 10.0000 clock clk (rise edge)
0.0000 10.0000 clock network delay (ideal)
67.0000 77.0000 path margin
0.0000 77.0000 clock reconvergence pessimism
77.0000 ^ r3/CK (DFF_X1)
-0.0390 76.9610 library setup time
76.9610 data required time
-------------------------------------------------------------
76.9610 data required time
-0.1278 data arrival time
-------------------------------------------------------------
76.8332 slack (MET)
setup_to_loosen 6.700e-08
Startpoint: r1 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: min
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r1/CK (DFF_X1)
0.0772 0.0772 v r1/Q (DFF_X1)
0.0254 0.1026 v u2/ZN (AND2_X1)
0.0000 0.1026 v r3/D (DFF_X1)
0.1026 data arrival time
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
-0.5000 -0.5000 path margin
0.0000 -0.5000 clock reconvergence pessimism
-0.5000 ^ r3/CK (DFF_X1)
0.0016 -0.4984 library hold time
-0.4984 data required time
-------------------------------------------------------------
-0.4984 data required time
-0.1026 data arrival time
-------------------------------------------------------------
0.6010 slack (MET)
hold_to_loosen -5.000e-10

37
test/set_path_margin1.tcl Normal file
View File

@ -0,0 +1,37 @@
# set_path_margin -to with -setup/-hold
read_liberty ../examples/nangate45_typ.lib.gz
read_verilog ../examples/example1.v
link_design top
create_clock -name clk -period 10 {clk1 clk2 clk3}
set_input_delay -clock clk 0 {in1 in2}
proc setup_at { args } {
report_checks {*}$args -path_delay max -digits 4 -fields {} -group_path_count 1
}
proc hold_at { args } {
report_checks {*}$args -path_delay min -digits 4 -fields {} -group_path_count 1
}
proc report_json_path_margin { label path_delay args } {
set cmd [concat [list report_checks] $args \
[list -path_delay $path_delay -format json -group_path_count 1]]
with_output_to_variable json $cmd
if { [regexp {"path_margin": ([^,\n]+)} $json match margin] } {
puts "$label $margin"
} else {
puts "$label none"
}
}
set_path_margin -setup 0.50 -comment {tighten setup time} -to [get_pins r3/D]
setup_at -to [get_pins r3/D]
report_json_path_margin setup_to_tighten max -to [get_pins r3/D]
set_path_margin -hold 0.50 -comment {tighten hold time} -to [get_pins r3/D]
hold_at -to [get_pins r3/D]
report_json_path_margin hold_to_tighten min -to [get_pins r3/D]
set_path_margin -setup -67 -comment {loosen setup time} -to [get_pins r3/D]
setup_at -to [get_pins r3/D]
report_json_path_margin setup_to_loosen max -to [get_pins r3/D]
set_path_margin -hold -0.50 -comment {loosen hold time} -to [get_pins r3/D]
hold_at -to [get_pins r3/D]
report_json_path_margin hold_to_loosen min -to [get_pins r3/D]

60
test/set_path_margin2.ok Normal file
View File

@ -0,0 +1,60 @@
Startpoint: r1 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r1/CK (DFF_X1)
0.0836 0.0836 ^ r1/Q (DFF_X1)
0.0277 0.1113 ^ u2/ZN (AND2_X1)
0.0000 0.1113 ^ r3/D (DFF_X1)
0.1113 data arrival time
10.0000 10.0000 clock clk (rise edge)
0.0000 10.0000 clock network delay (ideal)
-2.0000 8.0000 path margin
0.0000 8.0000 clock reconvergence pessimism
8.0000 ^ r3/CK (DFF_X1)
-0.0311 7.9689 library setup time
7.9689 data required time
-------------------------------------------------------------
7.9689 data required time
-0.1113 data arrival time
-------------------------------------------------------------
7.8576 slack (MET)
setup_from_r1 -2.000e-09
Startpoint: r2 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r2/CK (DFF_X1)
0.0772 0.0772 v r2/Q (DFF_X1)
0.0233 0.1006 v u1/Z (BUF_X1)
0.0273 0.1278 v u2/ZN (AND2_X1)
0.0000 0.1278 v r3/D (DFF_X1)
0.1278 data arrival time
10.0000 10.0000 clock clk (rise edge)
0.0000 10.0000 clock network delay (ideal)
0.0000 10.0000 clock reconvergence pessimism
10.0000 ^ r3/CK (DFF_X1)
-0.0390 9.9610 library setup time
9.9610 data required time
-------------------------------------------------------------
9.9610 data required time
-0.1278 data arrival time
-------------------------------------------------------------
9.8332 slack (MET)
setup_from_r2 none

29
test/set_path_margin2.tcl Normal file
View File

@ -0,0 +1,29 @@
# set_path_margin -from
read_liberty ../examples/nangate45_typ.lib.gz
read_verilog ../examples/example1.v
link_design top
create_clock -name clk -period 10 {clk1 clk2 clk3}
set_input_delay -clock clk 0 {in1 in2}
proc setup_at { args } {
report_checks {*}$args -path_delay max -digits 4 -fields {} -group_path_count 1
}
proc report_json_path_margin { label path_delay args } {
set cmd [concat [list report_checks] $args \
[list -path_delay $path_delay -format json -group_path_count 1]]
with_output_to_variable json $cmd
if { [regexp {"path_margin": ([^,\n]+)} $json match margin] } {
puts "$label $margin"
} else {
puts "$label none"
}
}
set_path_margin -setup 2.0 -from [get_pins r1/CK]
# Should see path margin.
setup_at -from [get_pins r1/CK] -to [get_pins r3/D]
report_json_path_margin setup_from_r1 max -from [get_pins r1/CK] -to [get_pins r3/D]
# Should not see path margin.
setup_at -from [get_pins r2/CK] -to [get_pins r3/D]
report_json_path_margin setup_from_r2 max -from [get_pins r2/CK] -to [get_pins r3/D]

60
test/set_path_margin3.ok Normal file
View File

@ -0,0 +1,60 @@
Startpoint: r1 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r1/CK (DFF_X1)
0.0836 0.0836 ^ r1/Q (DFF_X1)
0.0277 0.1113 ^ u2/ZN (AND2_X1)
0.0000 0.1113 ^ r3/D (DFF_X1)
0.1113 data arrival time
10.0000 10.0000 clock clk (rise edge)
0.0000 10.0000 clock network delay (ideal)
-5.0000 5.0000 path margin
0.0000 5.0000 clock reconvergence pessimism
5.0000 ^ r3/CK (DFF_X1)
-0.0311 4.9689 library setup time
4.9689 data required time
-------------------------------------------------------------
4.9689 data required time
-0.1113 data arrival time
-------------------------------------------------------------
4.8576 slack (MET)
setup_from_to_r1 -5.000e-09
Startpoint: r2 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r2/CK (DFF_X1)
0.0772 0.0772 v r2/Q (DFF_X1)
0.0233 0.1006 v u1/Z (BUF_X1)
0.0273 0.1278 v u2/ZN (AND2_X1)
0.0000 0.1278 v r3/D (DFF_X1)
0.1278 data arrival time
10.0000 10.0000 clock clk (rise edge)
0.0000 10.0000 clock network delay (ideal)
0.0000 10.0000 clock reconvergence pessimism
10.0000 ^ r3/CK (DFF_X1)
-0.0390 9.9610 library setup time
9.9610 data required time
-------------------------------------------------------------
9.9610 data required time
-0.1278 data arrival time
-------------------------------------------------------------
9.8332 slack (MET)
setup_from_to_r2 none

29
test/set_path_margin3.tcl Normal file
View File

@ -0,0 +1,29 @@
# set_path_margin -from and -to
read_liberty ../examples/nangate45_typ.lib.gz
read_verilog ../examples/example1.v
link_design top
create_clock -name clk -period 10 {clk1 clk2 clk3}
set_input_delay -clock clk 0 {in1 in2}
proc setup_at { args } {
report_checks {*}$args -path_delay max -digits 4 -fields {} -group_path_count 1
}
proc report_json_path_margin { label path_delay args } {
set cmd [concat [list report_checks] $args \
[list -path_delay $path_delay -format json -group_path_count 1]]
with_output_to_variable json $cmd
if { [regexp {"path_margin": ([^,\n]+)} $json match margin] } {
puts "$label $margin"
} else {
puts "$label none"
}
}
set_path_margin -setup 5.0 -from [get_pins r1/CK] -to [get_pins r3/D]
# Should see path margin.
setup_at -from [get_pins r1/CK] -to [get_pins r3/D]
report_json_path_margin setup_from_to_r1 max -from [get_pins r1/CK] -to [get_pins r3/D]
# Should not see path margin.
setup_at -from [get_pins r2/CK] -to [get_pins r3/D]
report_json_path_margin setup_from_to_r2 max -from [get_pins r2/CK] -to [get_pins r3/D]

60
test/set_path_margin4.ok Normal file
View File

@ -0,0 +1,60 @@
Startpoint: r1 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r1/CK (DFF_X1)
0.0836 0.0836 ^ r1/Q (DFF_X1)
0.0277 0.1113 ^ u2/ZN (AND2_X1)
0.0000 0.1113 ^ r3/D (DFF_X1)
0.1113 data arrival time
10.0000 10.0000 clock clk (rise edge)
0.0000 10.0000 clock network delay (ideal)
0.0000 10.0000 clock reconvergence pessimism
10.0000 ^ r3/CK (DFF_X1)
-0.0311 9.9689 library setup time
9.9689 data required time
-------------------------------------------------------------
9.9689 data required time
-0.1113 data arrival time
-------------------------------------------------------------
9.8576 slack (MET)
setup_through_r1 none
Startpoint: r2 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r2/CK (DFF_X1)
0.0772 0.0772 v r2/Q (DFF_X1)
0.0233 0.1006 v u1/Z (BUF_X1)
0.0273 0.1278 v u2/ZN (AND2_X1)
0.0000 0.1278 v r3/D (DFF_X1)
0.1278 data arrival time
10.0000 10.0000 clock clk (rise edge)
0.0000 10.0000 clock network delay (ideal)
-3.0000 7.0000 path margin
0.0000 7.0000 clock reconvergence pessimism
7.0000 ^ r3/CK (DFF_X1)
-0.0390 6.9610 library setup time
6.9610 data required time
-------------------------------------------------------------
6.9610 data required time
-0.1278 data arrival time
-------------------------------------------------------------
6.8332 slack (MET)
setup_through_r2 -3.000e-09

29
test/set_path_margin4.tcl Normal file
View File

@ -0,0 +1,29 @@
# set_path_margin -through
read_liberty ../examples/nangate45_typ.lib.gz
read_verilog ../examples/example1.v
link_design top
create_clock -name clk -period 10 {clk1 clk2 clk3}
set_input_delay -clock clk 0 {in1 in2}
proc setup_at { args } {
report_checks {*}$args -path_delay max -digits 4 -fields {} -group_path_count 1
}
proc report_json_path_margin { label path_delay args } {
set cmd [concat [list report_checks] $args \
[list -path_delay $path_delay -format json -group_path_count 1]]
with_output_to_variable json $cmd
if { [regexp {"path_margin": ([^,\n]+)} $json match margin] } {
puts "$label $margin"
} else {
puts "$label none"
}
}
set_path_margin -setup 3.0 -through [get_pins u1/Z]
# Should not see path margin.
setup_at -from [get_pins r1/CK] -to [get_pins r3/D]
report_json_path_margin setup_through_r1 max -from [get_pins r1/CK] -to [get_pins r3/D]
# Should see path margin.
setup_at -from [get_pins r2/CK] -to [get_pins r3/D]
report_json_path_margin setup_through_r2 max -from [get_pins r2/CK] -to [get_pins r3/D]

61
test/set_path_margin5.ok Normal file
View File

@ -0,0 +1,61 @@
Startpoint: r1 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r1/CK (DFF_X1)
0.0836 0.0836 ^ r1/Q (DFF_X1)
0.0277 0.1113 ^ u2/ZN (AND2_X1)
0.0000 0.1113 ^ r3/D (DFF_X1)
0.1113 data arrival time
10.0000 10.0000 clock clk (rise edge)
0.0000 10.0000 clock network delay (ideal)
-4.0000 6.0000 path margin
0.0000 6.0000 clock reconvergence pessimism
6.0000 ^ r3/CK (DFF_X1)
-0.0311 5.9689 library setup time
5.9689 data required time
-------------------------------------------------------------
5.9689 data required time
-0.1113 data arrival time
-------------------------------------------------------------
5.8576 slack (MET)
setup_from_clk_r1 -4.000e-09
Startpoint: r2 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r2/CK (DFF_X1)
0.0772 0.0772 v r2/Q (DFF_X1)
0.0233 0.1006 v u1/Z (BUF_X1)
0.0273 0.1278 v u2/ZN (AND2_X1)
0.0000 0.1278 v r3/D (DFF_X1)
0.1278 data arrival time
10.0000 10.0000 clock clk (rise edge)
0.0000 10.0000 clock network delay (ideal)
-4.0000 6.0000 path margin
0.0000 6.0000 clock reconvergence pessimism
6.0000 ^ r3/CK (DFF_X1)
-0.0390 5.9610 library setup time
5.9610 data required time
-------------------------------------------------------------
5.9610 data required time
-0.1278 data arrival time
-------------------------------------------------------------
5.8332 slack (MET)
setup_from_clk_r2 -4.000e-09

28
test/set_path_margin5.tcl Normal file
View File

@ -0,0 +1,28 @@
# set_path_margin -from clock
read_liberty ../examples/nangate45_typ.lib.gz
read_verilog ../examples/example1.v
link_design top
create_clock -name clk -period 10 {clk1 clk2 clk3}
set_input_delay -clock clk 0 {in1 in2}
proc setup_at { args } {
report_checks {*}$args -path_delay max -digits 4 -fields {} -group_path_count 1
}
proc report_json_path_margin { label path_delay args } {
set cmd [concat [list report_checks] $args \
[list -path_delay $path_delay -format json -group_path_count 1]]
with_output_to_variable json $cmd
if { [regexp {"path_margin": ([^,\n]+)} $json match margin] } {
puts "$label $margin"
} else {
puts "$label none"
}
}
set_path_margin -setup 4.0 -from [get_clocks clk]
# Should see path margin on the clock.
setup_at -from [get_pins r1/CK] -to [get_pins r3/D]
report_json_path_margin setup_from_clk_r1 max -from [get_pins r1/CK] -to [get_pins r3/D]
setup_at -from [get_pins r2/CK] -to [get_pins r3/D]
report_json_path_margin setup_from_clk_r2 max -from [get_pins r2/CK] -to [get_pins r3/D]

60
test/set_path_margin6.ok Normal file
View File

@ -0,0 +1,60 @@
Startpoint: r1 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r1/CK (DFF_X1)
0.0836 0.0836 ^ r1/Q (DFF_X1)
0.0277 0.1113 ^ u2/ZN (AND2_X1)
0.0000 0.1113 ^ r3/D (DFF_X1)
0.1113 data arrival time
10.0000 10.0000 clock clk (rise edge)
0.0000 10.0000 clock network delay (ideal)
-6.0000 4.0000 path margin
0.0000 4.0000 clock reconvergence pessimism
4.0000 ^ r3/CK (DFF_X1)
-0.0311 3.9689 library setup time
3.9689 data required time
-------------------------------------------------------------
3.9689 data required time
-0.1113 data arrival time
-------------------------------------------------------------
3.8576 slack (MET)
setup_combo_r1 -6.000e-09
Startpoint: r2 (rising edge-triggered flip-flop clocked by clk)
Endpoint: r3 (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Delay Time Description
-------------------------------------------------------------
0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 ^ r2/CK (DFF_X1)
0.0772 0.0772 v r2/Q (DFF_X1)
0.0233 0.1006 v u1/Z (BUF_X1)
0.0273 0.1278 v u2/ZN (AND2_X1)
0.0000 0.1278 v r3/D (DFF_X1)
0.1278 data arrival time
10.0000 10.0000 clock clk (rise edge)
0.0000 10.0000 clock network delay (ideal)
0.0000 10.0000 clock reconvergence pessimism
10.0000 ^ r3/CK (DFF_X1)
-0.0390 9.9610 library setup time
9.9610 data required time
-------------------------------------------------------------
9.9610 data required time
-0.1278 data arrival time
-------------------------------------------------------------
9.8332 slack (MET)
setup_combo_r2 none

31
test/set_path_margin6.tcl Normal file
View File

@ -0,0 +1,31 @@
# set_path_margin -from/-through/-to
read_liberty ../examples/nangate45_typ.lib.gz
read_verilog ../examples/example1.v
link_design top
create_clock -name clk -period 10 {clk1 clk2 clk3}
set_input_delay -clock clk 0 {in1 in2}
proc setup_at { args } {
report_checks {*}$args -path_delay max -digits 4 -fields {} -group_path_count 1
}
proc report_json_path_margin { label path_delay args } {
set cmd [concat [list report_checks] $args \
[list -path_delay $path_delay -format json -group_path_count 1]]
with_output_to_variable json $cmd
if { [regexp {"path_margin": ([^,\n]+)} $json match margin] } {
puts "$label $margin"
} else {
puts "$label none"
}
}
set_path_margin -setup 6.0 -from [get_pins r1/CK] \
-through [get_pins u2/A1] \
-to [get_pins r3/D]
# Should see path margin.
setup_at -from [get_pins r1/CK] -to [get_pins r3/D]
report_json_path_margin setup_combo_r1 max -from [get_pins r1/CK] -to [get_pins r3/D]
# Should not see path margin.
setup_at -from [get_pins r2/CK] -to [get_pins r3/D]
report_json_path_margin setup_combo_r2 max -from [get_pins r2/CK] -to [get_pins r3/D]