Merge pull request #403 from The-OpenROAD-Project-staging/secure-sta_update_0814
Merge upstream OpenSTA 08/14
This commit is contained in:
commit
d1b2b3962c
|
|
@ -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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
|
|
|
||||||
|
|
@ -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 };
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
43
sdc/Sdc.cc
43
sdc/Sdc.cc
|
|
@ -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);
|
||||||
|
|
|
||||||
50
sdc/Sdc.i
50
sdc/Sdc.i
|
|
@ -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,
|
||||||
|
|
|
||||||
63
sdc/Sdc.tcl
63
sdc/Sdc.tcl
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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."
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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]
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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]
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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]
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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]
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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]
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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]
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue