FEATURE: Implement `set_max_dynamic_power` and `set_max_leakage_power` (#471)

* Implement set_max_dynamic_power and set_max_leakage_power.

Store max dynamic/leakage power like max area, expose getters through Sta,
write them in write_sdc, and document that they are ignored during timing.

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

* Drop get_max_* Tcl wrappers; use SWIG accessors in tests.

James pointed out the get_max_* commands duplicate existing SWIG
accessors; remove them and call sta::max_* from the regression.

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

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Akash Levy 2026-07-31 12:57:23 -07:00 committed by GitHub
parent ecdef77537
commit d0526b524b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 174 additions and 4 deletions

View File

@ -11986,7 +11986,7 @@
</table:table-cell>
</table:table-row>
</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-column table:style-name="Table102.A"/>
<table:table-column table:style-name="Table102.B"/>
@ -12028,7 +12028,7 @@
</table:table-cell>
</table:table-row>
</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-column table:style-name="Table104.A"/>
<table:table-column table:style-name="Table104.B"/>

View File

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

View File

@ -346,6 +346,13 @@ public:
Sdc *sdc);
void setMaxArea(float area,
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,
const PinSet &pins,

View File

@ -244,6 +244,8 @@ Sdc::initVariables()
analysis_type_ = AnalysisType::ocv;
wireload_mode_ = WireloadMode::unknown;
max_area_ = 0.0;
max_dynamic_power_ = 0.0;
max_leakage_power_ = 0.0;
path_delays_without_to_ = false;
clk_hpin_disables_valid_ = false;
have_clk_slew_limits_ = false;
@ -951,6 +953,30 @@ Sdc::maxArea() const
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 *

View File

@ -1229,6 +1229,43 @@ set_max_area_cmd(float area)
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
set_port_fanout_limit(Port *port,
const MinMax *min_max,

View File

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

View File

@ -2031,6 +2031,8 @@ WriteSdc::writeDesignRules() const
writeCapLimits();
writeFanoutLimits();
writeMaxArea();
writeMaxDynamicPower();
writeMaxLeakagePower();
}
void
@ -2262,6 +2264,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
WriteSdc::writeFanoutLimits() const
{

View File

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

View File

@ -1148,6 +1148,38 @@ Sta::setMaxArea(float 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
Sta::makeClock(std::string_view name,
const PinSet &pins,

6
test/max_power_area.ok Normal file
View File

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

25
test/max_power_area.tcl Normal file
View File

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

View File

@ -157,6 +157,7 @@ record_public_tests {
liberty_float_as_str
liberty_latch3
make_concrete_parasitics_leak
max_power_area
package_require
path_group_names
power_json