Merge pull request #403 from The-OpenROAD-Project-staging/secure-sta_update_0814

Merge upstream OpenSTA 08/14
This commit is contained in:
Matt Liberty 2026-08-19 04:17:13 +00:00 committed by GitHub
commit d1b2b3962c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 1365 additions and 50 deletions

View File

@ -446,6 +446,14 @@ PrimaDelayCalc::driverResistance()
const Pin *drvr_pin = (*dcalc_args_)[0].drvrPin(); const Pin *drvr_pin = (*dcalc_args_)[0].drvrPin();
LibertyPort *drvr_port = network_->libertyPort(drvr_pin); LibertyPort *drvr_port = network_->libertyPort(drvr_pin);
LibertyPort *scene_port = drvr_port->scenePort(scene_, min_max_); LibertyPort *scene_port = drvr_port->scenePort(scene_, min_max_);
if (scene_port == nullptr) {
report_->warn(1754, "Port {}/{}/{} has no equivalent in scene {}.",
drvr_port->libertyLibrary()->name(),
drvr_port->libertyCell()->name(),
drvr_port->name(),
scene_->name());
scene_port = drvr_port;
}
return scene_port->driveResistance(drvr_rf_, min_max_); return scene_port->driveResistance(drvr_rf_, min_max_);
} }

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

@ -11986,7 +11986,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 <text:span text:style-name="Command">set_max_dynamic_power</text:span> command is ignored.</text:p> <text:p text:style-name="Body_20_first">The <text:span text:style-name="Command">set_max_dynamic_power</text:span> command is ignored during timing but is included in SDC files that are written.</text:p>
<table:table table:name="Table102" table:style-name="Table102"> <table:table table:name="Table102" table:style-name="Table102">
<table:table-column table:style-name="Table102.A"/> <table:table-column table:style-name="Table102.A"/>
<table:table-column table:style-name="Table102.B"/> <table:table-column table:style-name="Table102.B"/>
@ -12028,7 +12028,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 <text:span text:style-name="Command">set_max_leakage_power</text:span> command is ignored.</text:p> <text:p text:style-name="Body_20_first">The <text:span text:style-name="Command">set_max_leakage_power</text:span> command is ignored during timing but is included in SDC files that are written.</text:p>
<table:table table:name="Table104" table:style-name="Table104"> <table:table table:name="Table104" table:style-name="Table104">
<table:table-column table:style-name="Table104.A"/> <table:table-column table:style-name="Table104.A"/>
<table:table-column table:style-name="Table104.B"/> <table:table-column table:style-name="Table104.B"/>
@ -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

@ -377,6 +377,10 @@ public:
float fanout); float fanout);
void setMaxArea(float area); void setMaxArea(float area);
float maxArea() const; float maxArea() const;
void setMaxDynamicPower(float power);
float maxDynamicPower() const;
void setMaxLeakagePower(float power);
float maxLeakagePower() const;
Clock *makeClock(std::string_view name, Clock *makeClock(std::string_view name,
const PinSet &pins, const PinSet &pins,
bool add_to_pins, bool add_to_pins,
@ -753,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).
@ -1424,6 +1434,8 @@ protected:
InstMinPulseWidthMap inst_min_pulse_width_map_; InstMinPulseWidthMap inst_min_pulse_width_map_;
ClockMinPulseWidthMap clk_min_pulse_width_map_; ClockMinPulseWidthMap clk_min_pulse_width_map_;
float max_area_; float max_area_;
float max_dynamic_power_;
float max_leakage_power_;
Wireload *wireload_[MinMax::index_count]; Wireload *wireload_[MinMax::index_count];
WireloadMode wireload_mode_; WireloadMode wireload_mode_;
const WireloadSelection *wireload_selection_[MinMax::index_count]; const WireloadSelection *wireload_selection_[MinMax::index_count];

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

@ -346,6 +346,13 @@ public:
Sdc *sdc); Sdc *sdc);
void setMaxArea(float area, void setMaxArea(float area,
Sdc *sdc); Sdc *sdc);
float maxArea(const Sdc *sdc) const;
void setMaxDynamicPower(float power,
Sdc *sdc);
float maxDynamicPower(const Sdc *sdc) const;
void setMaxLeakagePower(float power,
Sdc *sdc);
float maxLeakagePower(const Sdc *sdc) const;
void makeClock(std::string_view name, void makeClock(std::string_view name,
const PinSet &pins, const PinSet &pins,
@ -647,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

@ -108,7 +108,7 @@ proc parse_connect_pin { arg } {
set port [$pin port] set port [$pin port]
} elseif { $object_type == "Port" } { } elseif { $object_type == "Port" } {
# Explicit port arg - convert to pin. # Explicit port arg - convert to pin.
set pin [find_pin [get_name $arg]] set pin [get_port_pin $arg]
set inst [$pin instance] set inst [$pin instance]
set port [$pin port] set port [$pin port]
} else { } else {

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

@ -244,6 +244,8 @@ Sdc::initVariables()
analysis_type_ = AnalysisType::ocv; analysis_type_ = AnalysisType::ocv;
wireload_mode_ = WireloadMode::unknown; wireload_mode_ = WireloadMode::unknown;
max_area_ = 0.0; max_area_ = 0.0;
max_dynamic_power_ = 0.0;
max_leakage_power_ = 0.0;
path_delays_without_to_ = false; path_delays_without_to_ = false;
clk_hpin_disables_valid_ = false; clk_hpin_disables_valid_ = false;
have_clk_slew_limits_ = false; have_clk_slew_limits_ = false;
@ -951,6 +953,30 @@ Sdc::maxArea() const
return max_area_; return max_area_;
} }
void
Sdc::setMaxDynamicPower(float power)
{
max_dynamic_power_ = power;
}
float
Sdc::maxDynamicPower() const
{
return max_dynamic_power_;
}
void
Sdc::setMaxLeakagePower(float power)
{
max_leakage_power_ = power;
}
float
Sdc::maxLeakagePower() const
{
return max_leakage_power_;
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
Clock * Clock *
@ -3932,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)
{ {
@ -4339,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,
@ -1229,6 +1242,43 @@ set_max_area_cmd(float area)
sta->setMaxArea(area, sdc); sta->setMaxArea(area, sdc);
} }
float
max_area()
{
Sta *sta = Sta::sta();
return sta->maxArea(sta->cmdSdc());
}
void
set_max_dynamic_power_cmd(float power)
{
Sta *sta = Sta::sta();
Sdc *sdc = sta->cmdSdc();
sta->setMaxDynamicPower(power, sdc);
}
float
max_dynamic_power()
{
Sta *sta = Sta::sta();
return sta->maxDynamicPower(sta->cmdSdc());
}
void
set_max_leakage_power_cmd(float power)
{
Sta *sta = Sta::sta();
Sdc *sdc = sta->cmdSdc();
sta->setMaxLeakagePower(power, sdc);
}
float
max_leakage_power()
{
Sta *sta = Sta::sta();
return sta->maxLeakagePower(sta->cmdSdc());
}
void void
set_port_fanout_limit(Port *port, set_port_fanout_limit(Port *port,
const MinMax *min_max, const MinMax *min_max,

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 } {
@ -3599,7 +3654,9 @@ proc set_level_shifter_threshold { args } {
define_cmd_args "set_max_dynamic_power" {power [unit]} define_cmd_args "set_max_dynamic_power" {power [unit]}
proc set_max_dynamic_power { power {unit {}} } { proc set_max_dynamic_power { power {unit {}} } {
# ignored check_positive_float "power" $power
# Optional SDC unit argument is accepted but ignored; use set_units.
set_max_dynamic_power_cmd $power
} }
################################################################ ################################################################
@ -3607,7 +3664,9 @@ proc set_max_dynamic_power { power {unit {}} } {
define_cmd_args "set_max_leakage_power" {power [unit]} define_cmd_args "set_max_leakage_power" {power [unit]}
proc set_max_leakage_power { power {unit {}} } { proc set_max_leakage_power { power {unit {}} } {
# ignored check_positive_float "power" $power
# Optional SDC unit argument is accepted but ignored; use set_units.
set_max_leakage_power_cmd $power
} }
################################################################ ################################################################

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
@ -2031,6 +2039,8 @@ WriteSdc::writeDesignRules() const
writeCapLimits(); writeCapLimits();
writeFanoutLimits(); writeFanoutLimits();
writeMaxArea(); writeMaxArea();
writeMaxDynamicPower();
writeMaxLeakagePower();
} }
void void
@ -2262,6 +2272,28 @@ WriteSdc::writeMaxArea() const
} }
} }
void
WriteSdc::writeMaxDynamicPower() const
{
float max_power = sdc_->maxDynamicPower();
if (max_power > 0.0) {
sta::print(stream_, "set_max_dynamic_power ");
writeFloat(max_power);
sta::print(stream_, "\n");
}
}
void
WriteSdc::writeMaxLeakagePower() const
{
float max_power = sdc_->maxLeakagePower();
if (max_power > 0.0) {
sta::print(stream_, "set_max_leakage_power ");
writeFloat(max_power);
sta::print(stream_, "\n");
}
}
void void
WriteSdc::writeFanoutLimits() const WriteSdc::writeFanoutLimits() const
{ {

View File

@ -169,6 +169,8 @@ public:
void writeCapLimits(const MinMax *min_max, void writeCapLimits(const MinMax *min_max,
std::string_view cmd) const; std::string_view cmd) const;
void writeMaxArea() const; void writeMaxArea() const;
void writeMaxDynamicPower() const;
void writeMaxLeakagePower() const;
void writeFanoutLimits() const; void writeFanoutLimits() const;
void writeFanoutLimits(const MinMax *min_max, void writeFanoutLimits(const MinMax *min_max,
std::string_view cmd) const; std::string_view cmd) const;

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

@ -1149,6 +1149,38 @@ Sta::setMaxArea(float area,
sdc->setMaxArea(area); sdc->setMaxArea(area);
} }
float
Sta::maxArea(const Sdc *sdc) const
{
return sdc->maxArea();
}
void
Sta::setMaxDynamicPower(float power,
Sdc *sdc)
{
sdc->setMaxDynamicPower(power);
}
float
Sta::maxDynamicPower(const Sdc *sdc) const
{
return sdc->maxDynamicPower();
}
void
Sta::setMaxLeakagePower(float power,
Sdc *sdc)
{
sdc->setMaxLeakagePower(power);
}
float
Sta::maxLeakagePower(const Sdc *sdc) const
{
return sdc->maxLeakagePower();
}
void void
Sta::makeClock(std::string_view name, Sta::makeClock(std::string_view name,
const PinSet &pins, const PinSet &pins,
@ -1730,7 +1762,8 @@ Sta::isDisabledConstraint(Edge *edge,
{ {
Pin *from_pin = edge->from(graph_)->pin(); Pin *from_pin = edge->from(graph_)->pin();
Pin *to_pin = edge->to(graph_)->pin(); Pin *to_pin = edge->to(graph_)->pin();
return sdc->isDisabledConstraint(from_pin) || sdc->isDisabledConstraint(to_pin) return sdc->isDisabledConstraint(from_pin)
|| sdc->isDisabledConstraint(to_pin)
|| sdc->isDisabledConstraint(edge); || sdc->isDisabledConstraint(edge);
} }
@ -2038,6 +2071,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

@ -3229,7 +3229,7 @@ TEST_F(StaInitTest, PathEndCheckConstruct) {
Path *data_path = new Path(); Path *data_path = new Path();
Path *clk_path = new Path(); Path *clk_path = new Path();
PathEndCheck *pe = new PathEndCheck(data_path, nullptr, nullptr, PathEndCheck *pe = new PathEndCheck(data_path, nullptr, nullptr,
clk_path, nullptr, sta_); clk_path, nullptr, nullptr, sta_);
EXPECT_EQ(pe->type(), PathEnd::Type::check); EXPECT_EQ(pe->type(), PathEnd::Type::check);
EXPECT_STREQ(pe->typeName(), "check"); EXPECT_STREQ(pe->typeName(), "check");
EXPECT_TRUE(pe->isCheck()); EXPECT_TRUE(pe->isCheck());
@ -3250,7 +3250,7 @@ TEST_F(StaInitTest, PathEndOutputDelayConstruct) {
Path *data_path = new Path(); Path *data_path = new Path();
Path *clk_path = new Path(); Path *clk_path = new Path();
PathEndOutputDelay *pe = new PathEndOutputDelay(nullptr, data_path, PathEndOutputDelay *pe = new PathEndOutputDelay(nullptr, data_path,
clk_path, nullptr, sta_); clk_path, nullptr, nullptr, sta_);
EXPECT_EQ(pe->type(), PathEnd::Type::output_delay); EXPECT_EQ(pe->type(), PathEnd::Type::output_delay);
EXPECT_STREQ(pe->typeName(), "output_delay"); EXPECT_STREQ(pe->typeName(), "output_delay");
EXPECT_TRUE(pe->isOutputDelay()); EXPECT_TRUE(pe->isOutputDelay());
@ -3266,7 +3266,7 @@ TEST_F(StaInitTest, PathEndGatedClockConstruct) {
Path *clk_path = new Path(); Path *clk_path = new Path();
PathEndGatedClock *pe = new PathEndGatedClock(data_path, clk_path, PathEndGatedClock *pe = new PathEndGatedClock(data_path, clk_path,
TimingRole::setup(), TimingRole::setup(),
nullptr, 0.0f, sta_); nullptr, nullptr, 0.0f, sta_);
EXPECT_EQ(pe->type(), PathEnd::Type::gated_clk); EXPECT_EQ(pe->type(), PathEnd::Type::gated_clk);
EXPECT_STREQ(pe->typeName(), "gated_clk"); EXPECT_STREQ(pe->typeName(), "gated_clk");
EXPECT_TRUE(pe->isGatedClock()); EXPECT_TRUE(pe->isGatedClock());

View File

@ -655,7 +655,7 @@ TEST_F(StaInitTest, PathEndUnconstrainedExceptPathCmp) {
TEST_F(StaInitTest, PathEndCheckConstruct2) { TEST_F(StaInitTest, PathEndCheckConstruct2) {
Path *p = new Path(); Path *p = new Path();
Path *clk = new Path(); Path *clk = new Path();
PathEndCheck pe(p, nullptr, nullptr, clk, nullptr, sta_); PathEndCheck pe(p, nullptr, nullptr, clk, nullptr, nullptr, sta_);
EXPECT_EQ(pe.type(), PathEnd::Type::check); EXPECT_EQ(pe.type(), PathEnd::Type::check);
EXPECT_TRUE(pe.isCheck()); EXPECT_TRUE(pe.isCheck());
EXPECT_FALSE(pe.isLatchCheck()); EXPECT_FALSE(pe.isLatchCheck());
@ -665,7 +665,7 @@ TEST_F(StaInitTest, PathEndCheckConstruct2) {
TEST_F(StaInitTest, PathEndCheckGetters) { TEST_F(StaInitTest, PathEndCheckGetters) {
Path *p = new Path(); Path *p = new Path();
Path *clk = new Path(); Path *clk = new Path();
PathEndCheck pe(p, nullptr, nullptr, clk, nullptr, sta_); PathEndCheck pe(p, nullptr, nullptr, clk, nullptr, nullptr, sta_);
EXPECT_EQ(pe.checkArc(), nullptr); EXPECT_EQ(pe.checkArc(), nullptr);
EXPECT_EQ(pe.multiCyclePath(), nullptr); EXPECT_EQ(pe.multiCyclePath(), nullptr);
} }
@ -673,7 +673,7 @@ TEST_F(StaInitTest, PathEndCheckGetters) {
TEST_F(StaInitTest, PathEndCheckCopy) { TEST_F(StaInitTest, PathEndCheckCopy) {
Path *p = new Path(); Path *p = new Path();
Path *clk = new Path(); Path *clk = new Path();
PathEndCheck pe(p, nullptr, nullptr, clk, nullptr, sta_); PathEndCheck pe(p, nullptr, nullptr, clk, nullptr, nullptr, sta_);
PathEnd *copy = pe.copy(); PathEnd *copy = pe.copy();
EXPECT_NE(copy, nullptr); EXPECT_NE(copy, nullptr);
EXPECT_EQ(copy->type(), PathEnd::Type::check); EXPECT_EQ(copy->type(), PathEnd::Type::check);

View File

@ -226,7 +226,7 @@ proc parse_clk_inst_port_pin_arg { objects clks_var insts_var pins_var } {
set ports {} set ports {}
get_object_args $objects clks {} {} {} insts ports pins {} {} {} get_object_args $objects clks {} {} {} insts ports pins {} {} {}
foreach port $ports { foreach port $ports {
lappend pins [[top_instance] find_pin [get_name $port]] lappend pins [get_port_pin $port]
} }
} }
@ -238,7 +238,7 @@ proc parse_clk_port_pin_arg { objects clks_var pins_var } {
set ports {} set ports {}
get_object_args $objects clks {} {} {} {} ports pins {} {} {} get_object_args $objects clks {} {} {} {} ports pins {} {} {}
foreach port $ports { foreach port $ports {
lappend pins [[top_instance] find_pin [get_name $port]] lappend pins [get_port_pin $port]
} }
} }
@ -325,7 +325,7 @@ proc parse_inst_port_pin_arg { objects insts_var pins_var } {
set ports {} set ports {}
get_object_args $objects {} {} {} {} insts ports pins {} {} {} get_object_args $objects {} {} {} {} insts ports pins {} {} {}
foreach port $ports { foreach port $ports {
lappend pins [[top_instance] find_pin [get_name $port]] lappend pins [get_port_pin $port]
} }
} }
@ -347,7 +347,7 @@ proc parse_inst_port_pin_net_arg { objects insts_var pins_var nets_var } {
set nets {} set nets {}
get_object_args $objects {} {} {} {} insts ports pins nets {} {} get_object_args $objects {} {} {} {} insts ports pins nets {} {}
foreach port $ports { foreach port $ports {
lappend pins [[top_instance] find_pin [get_name $port]] lappend pins [get_port_pin $port]
} }
} }
@ -368,7 +368,7 @@ proc parse_port_pin_net_arg { objects pins_var nets_var } {
get_object_args $objects {} {} {} {} {} ports pins nets {} {} get_object_args $objects {} {} {} {} {} ports pins nets {} {}
foreach port $ports { foreach port $ports {
lappend pins [[top_instance] find_pin [get_name $port]] lappend pins [get_port_pin $port]
} }
} }
@ -857,7 +857,7 @@ proc get_port_pin_arg { arg_name arg warn_error } {
set pin $arg set pin $arg
} elseif { $object_type == "Port" } { } elseif { $object_type == "Port" } {
# Explicit port arg - convert to pin. # Explicit port arg - convert to pin.
set pin [find_pin [get_name $arg]] set pin [get_port_pin $arg]
} else { } else {
sta_warn_error 129 $warn_error "$arg_name type '$object_type' is not a pin or port." sta_warn_error 129 $warn_error "$arg_name type '$object_type' is not a pin or port."
} }
@ -868,7 +868,7 @@ proc get_port_pin_arg { arg_name arg warn_error } {
if { $port == "NULL" } { if { $port == "NULL" } {
set pin [find_pin $arg] set pin [find_pin $arg]
} else { } else {
set pin [$top_instance find_pin [get_name $port]] set pin [get_port_pin $port]
} }
if { $pin == "NULL" } { if { $pin == "NULL" } {
sta_warn_error 130 $warn_error "pin $arg not found." sta_warn_error 130 $warn_error "pin $arg not found."
@ -880,7 +880,7 @@ proc get_port_pin_arg { arg_name arg warn_error } {
proc get_port_pins_error { arg_name arglist } { proc get_port_pins_error { arg_name arglist } {
set pins {} set pins {}
# Copy backslashes that will be removed by foreach. # Copy backslashes that will be removed by foreach.
set arglilst [string map {\\ \\\\} $arglist] set arglist [string map {\\ \\\\} $arglist]
foreach arg $arglist { foreach arg $arglist {
if {[llength $arg] > 1} { if {[llength $arg] > 1} {
# Embedded list. # Embedded list.
@ -891,7 +891,7 @@ proc get_port_pins_error { arg_name arglist } {
lappend pins $arg lappend pins $arg
} elseif { $object_type == "Port" } { } elseif { $object_type == "Port" } {
# Convert port to pin. # Convert port to pin.
lappend pins [find_pin [get_name $arg]] lappend pins [get_port_pin $arg]
} else { } else {
sta_error 131 "$arg_name type '$object_type' is not a pin or port." sta_error 131 "$arg_name type '$object_type' is not a pin or port."
} }

6
test/max_power_area.ok Normal file
View File

@ -0,0 +1,6 @@
max_area 123.5
max_dynamic_power 1.25
max_leakage_power 0.75
set_max_area 123.5000
set_max_dynamic_power 1.2500
set_max_leakage_power 0.7500

25
test/max_power_area.tcl Normal file
View File

@ -0,0 +1,25 @@
# Store/retrieve/write max area and power SDC constraints.
source helpers.tcl
read_liberty asap7_small.lib.gz
read_verilog reg1_asap7.v
link_design top
set_max_area 123.5
set_max_dynamic_power 1.25
set_max_leakage_power 0.75
puts "max_area [sta::max_area]"
puts "max_dynamic_power [sta::max_dynamic_power]"
puts "max_leakage_power [sta::max_leakage_power]"
set sdc_file [make_result_file max_power_area.sdc]
write_sdc -no_timestamp $sdc_file
set stream [open $sdc_file r]
gets $stream line
while { ![eof $stream] } {
if {[string match "set_max_*" $line]} {
puts $line
}
gets $stream line
}
close $stream

View File

@ -157,6 +157,7 @@ record_public_tests {
liberty_float_as_str liberty_float_as_str
liberty_latch3 liberty_latch3
make_concrete_parasitics_leak make_concrete_parasitics_leak
max_power_area
package_require package_require
path_group_names path_group_names
power_json power_json
@ -167,6 +168,13 @@ 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
suppress_msg suppress_msg
user_properties user_properties
vcd_begin_end_time vcd_begin_end_time

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]

51
test/slash_port_test.ok Normal file
View File

@ -0,0 +1,51 @@
get_ports *
a/b
level1/Y
level1/level2/level3
out
all_inputs
a/b
level1/Y
level1/level2/level3
all_outputs
out
get_pins *
a/A
a/Y
level1/A
level1/Y
u3/A
u3/B
u3/Y
u4/A
u4/Y
get_cells *
a
level1
u3
u4
get_nets *
a/b
and_out
buf_out
buf_out2
level1/Y
level1/level2/level3
out
get_ports * -filter direction==input
a/b
level1/Y
level1/level2/level3
get_ports * -filter direction==output
out
set_input_delay -clock clk 0 [all_inputs]
set_input_delay -clock clk 0 <Port 'level1/level2/level3'>
set_input_delay -clock clk 0 <Port 'a/b'>
set_input_delay -clock clk 0 <Port 'level1/Y'>
set_false_path -from [all_inputs] -to [all_outputs]
set_data_check -from <Port 'level1/level2/level3'> -to <Port 'a/b'> 0
set_case_analysis 0 <Port 'level1/level2/level3'>
set_case_analysis 0 <Port 'a/b'>
set_case_analysis 0 <Port 'level1/Y'>
report_checks
No paths found.

62
test/slash_port_test.tcl Normal file
View File

@ -0,0 +1,62 @@
# Test: ports with escaped names containing slashes
# Exercises Port-to-Pin conversion paths with escaped Verilog identifiers
# like \level1/level2/level3 that contain hierarchy separators
read_liberty asap7_small.lib.gz
read_verilog slash_port_test.v
link_design slash_port_test
create_clock -name clk -period 500 [get_ports out]
puts {get_ports *}
report_object_full_names [get_ports *]
puts {all_inputs}
report_object_full_names [all_inputs]
puts {all_outputs}
report_object_full_names [all_outputs]
puts {get_pins *}
report_object_full_names [get_pins *]
puts {get_cells *}
report_object_full_names [get_cells *]
puts {get_nets *}
report_object_full_names [get_nets *]
puts {get_ports * -filter direction==input}
report_object_full_names [get_ports * -filter {direction == input}]
puts {get_ports * -filter direction==output}
report_object_full_names [get_ports * -filter {direction == output}]
# get_port_pins_error: Port objects via set_input_delay [all_inputs]
puts {set_input_delay -clock clk 0 [all_inputs]}
set_input_delay -clock clk 0 [all_inputs]
# get_port_pins_error: individual Port objects
foreach port [all_inputs] {
puts "set_input_delay -clock clk 0 <Port '[get_name $port]'>"
set_input_delay -clock clk 0 $port
}
# parse_clk_inst_port_pin_arg: Port objects via set_false_path
puts {set_false_path -from [all_inputs] -to [all_outputs]}
set_false_path -from [all_inputs] -to [all_outputs]
# get_port_pin_error (singular): set_data_check with Port objects
set input_ports [all_inputs]
set from_port [lindex $input_ports 0]
set to_port [lindex $input_ports 1]
puts "set_data_check -from <Port '[get_name $from_port]'> -to <Port '[get_name $to_port]'> 0"
set_data_check -from $from_port -to $to_port 0
# get_port_pin_error (singular): set_case_analysis with Port objects
foreach port [all_inputs] {
puts "set_case_analysis 0 <Port '[get_name $port]'>"
set_case_analysis 0 $port
}
puts {report_checks}
report_checks

20
test/slash_port_test.v Normal file
View File

@ -0,0 +1,20 @@
module slash_port_test (
\level1/level2/level3 ,
\a/b ,
\level1/Y ,
out
);
input \level1/level2/level3 ;
input \a/b ;
input \level1/Y ;
output out;
wire buf_out, buf_out2, and_out;
// Instance named "level1" collides with the prefix of port \level1/level2/level3
BUFx2_ASAP7_75t_R level1 (.A(\level1/level2/level3 ), .Y(buf_out));
// Instance named "a" collides with the prefix of port \a/b
BUFx2_ASAP7_75t_R a (.A(\a/b ), .Y(buf_out2));
AND2x2_ASAP7_75t_R u3 (.A(buf_out), .B(buf_out2), .Y(and_out));
BUFx2_ASAP7_75t_R u4 (.A(and_out), .Y(out));
endmodule