diff --git a/include/sta/Sdc.hh b/include/sta/Sdc.hh index acf209861..d504264c2 100644 --- a/include/sta/Sdc.hh +++ b/include/sta/Sdc.hh @@ -389,6 +389,8 @@ public: float maxDynamicPower() const; void setMaxLeakagePower(float power); float maxLeakagePower() const; + void setMaxLOL(int lol); + int maxLOL() const; void createLibertyGeneratedClocks(Clock *clk); Clock *makeClock(std::string_view name, const PinSet &pins, @@ -1451,6 +1453,7 @@ protected: float max_area_; float max_dynamic_power_; float max_leakage_power_; + int max_lol_; // -1 if unset Wireload *wireload_[MinMax::index_count]; WireloadMode wireload_mode_; const WireloadSelection *wireload_selection_[MinMax::index_count]; diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index a1dfa852f..972ba8d8e 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -357,6 +357,9 @@ public: void setMaxLeakagePower(float power, Sdc *sdc); float maxLeakagePower(const Sdc *sdc) const; + void setMaxLOL(int lol, + Sdc *sdc); + int maxLOL(const Sdc *sdc) const; void makeClock(std::string_view name, const PinSet &pins, diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index 15ffd61b3..1df5ef984 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -249,6 +249,7 @@ Sdc::initVariables() max_area_ = 0.0; max_dynamic_power_ = 0.0; max_leakage_power_ = 0.0; + max_lol_ = -1; path_delays_without_to_ = false; clk_hpin_disables_valid_ = false; have_clk_slew_limits_ = false; @@ -1038,6 +1039,18 @@ Sdc::maxLeakagePower() const return max_leakage_power_; } +void +Sdc::setMaxLOL(int lol) +{ + max_lol_ = lol; +} + +int +Sdc::maxLOL() const +{ + return max_lol_; +} + //////////////////////////////////////////////////////////////// void Sdc::createLibertyGeneratedClocks(Clock *clk) { diff --git a/sdc/Sdc.i b/sdc/Sdc.i index 69d9dd220..630c59c3b 100644 --- a/sdc/Sdc.i +++ b/sdc/Sdc.i @@ -1296,6 +1296,21 @@ max_leakage_power() return sta->maxLeakagePower(sta->cmdSdc()); } +void +set_max_lol_cmd(int lol) +{ + Sta *sta = Sta::sta(); + Sdc *sdc = sta->cmdSdc(); + sta->setMaxLOL(lol, sdc); +} + +int +max_lol() +{ + Sta *sta = Sta::sta(); + return sta->maxLOL(sta->cmdSdc()); +} + void set_port_fanout_limit(Port *port, const MinMax *min_max, diff --git a/sdc/Sdc.tcl b/sdc/Sdc.tcl index 0ff82c9af..cd37fa05a 100644 --- a/sdc/Sdc.tcl +++ b/sdc/Sdc.tcl @@ -3818,6 +3818,16 @@ proc set_fanout_limit { fanout min_max objects } { ################################################################ +define_cmd_args "set_max_lol" {lol} \ + -help {The `set_max_lol` command is ignored during timing but is included in SDC files that are written.} + +proc set_max_lol { lol } { + check_positive_integer "lol" $lol + set_max_lol_cmd $lol +} + +################################################################ + define_cmd_args "set_max_transition" \ {[-clock_path] [-data_path] [-rise] [-fall] slew objects} \ -help {The `set_max_transition` command is specifies the maximum transition time (slew) design rule checked by the `report_check_types` `-max_transition` command. diff --git a/sdc/WriteSdc.cc b/sdc/WriteSdc.cc index 5ea4b0e10..6bc5858cf 100644 --- a/sdc/WriteSdc.cc +++ b/sdc/WriteSdc.cc @@ -2083,6 +2083,7 @@ WriteSdc::writeDesignRules() const writeMaxArea(); writeMaxDynamicPower(); writeMaxLeakagePower(); + writeMaxLOL(); } void @@ -2372,6 +2373,17 @@ WriteSdc::writeFanoutLimits(const MinMax *min_max, } } +void +WriteSdc::writeMaxLOL() const +{ + int max_lol = sdc_->maxLOL(); + if (max_lol >= 0) { + sta::print(stream_, "set_max_lol "); + writeInteger(max_lol); + sta::print(stream_, "\n"); + } +} + //////////////////////////////////////////////////////////////// void @@ -2817,6 +2829,12 @@ WriteSdc::writeFloat(float value) const sta::print(stream_, "{}", sta::formatRuntime("{:.{}f}", value, digits_)); } +void +WriteSdc::writeInteger(int value) const +{ + sta::print(stream_, "{}", value); +} + void WriteSdc::writeTime(float time) const { diff --git a/sdc/WriteSdcPvt.hh b/sdc/WriteSdcPvt.hh index 4d58d93d4..8d25c079f 100644 --- a/sdc/WriteSdcPvt.hh +++ b/sdc/WriteSdcPvt.hh @@ -172,6 +172,7 @@ public: void writeMaxArea() const; void writeMaxDynamicPower() const; void writeMaxLeakagePower() const; + void writeMaxLOL() const; void writeFanoutLimits() const; void writeFanoutLimits(const MinMax *min_max, std::string_view cmd) const; @@ -217,6 +218,7 @@ public: float scaleCapacitance(float cap) const; float scaleResistance(float res) const; void writeFloat(float value) const; + void writeInteger(int value) const; void writeTime(float time) const; void writeCapacitance(float cap) const; void writeResistance(float res) const; diff --git a/search/Sta.cc b/search/Sta.cc index 22c164f0f..5148e0833 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -1215,6 +1215,19 @@ Sta::maxLeakagePower(const Sdc *sdc) const return sdc->maxLeakagePower(); } +void +Sta::setMaxLOL(int lol, + Sdc *sdc) +{ + sdc->setMaxLOL(lol); +} + +int +Sta::maxLOL(const Sdc *sdc) const +{ + return sdc->maxLOL(); +} + void Sta::makeClock(std::string_view name, const PinSet &pins, diff --git a/stadb/DbFormat.hh b/stadb/DbFormat.hh index 539de9dbc..5c0d44080 100644 --- a/stadb/DbFormat.hh +++ b/stadb/DbFormat.hh @@ -38,7 +38,7 @@ constexpr uint32_t stadb_magic = 0x42445453; // Bump on any incompatible layout change that sizeof alone does not catch, // such as reordering fields within a record or changing an encoding. -constexpr uint32_t stadb_version = 1; +constexpr uint32_t stadb_version = 2; // v1 supports exactly one scene. Kept as a stored field so that adding corners // later is a version bump rather than a format redesign. diff --git a/stadb/DbSdc.cc b/stadb/DbSdc.cc index 4381b028a..0fa7a60b6 100644 --- a/stadb/DbSdc.cc +++ b/stadb/DbSdc.cc @@ -1028,6 +1028,8 @@ DbSdcWriter::writeDesignRules() writer_.putF32(sdc_->maxDynamicPower()); kind(DbSdcKind::max_leakage_power); writer_.putF32(sdc_->maxLeakagePower()); + kind(DbSdcKind::max_lol); + writer_.putI32(sdc_->maxLOL()); } void @@ -2358,6 +2360,7 @@ DbSdcReader::read() case DbSdcKind::max_leakage_power: sdc_->setMaxLeakagePower(reader_.getF32()); break; + case DbSdcKind::max_lol: sdc_->setMaxLOL(reader_.getI32()); break; default: throw DbCorrupt(sta::format("stadb sdc record kind {} unknown", tag)); } diff --git a/stadb/DbSdc.hh b/stadb/DbSdc.hh index 6c1946b6f..59841000a 100644 --- a/stadb/DbSdc.hh +++ b/stadb/DbSdc.hh @@ -100,6 +100,7 @@ enum class DbSdcKind : uint8_t { max_area, max_dynamic_power, max_leakage_power, + max_lol, }; void writeStaDbSdc(DbWriter &writer, Sta *sta); diff --git a/test/max_power_area.ok b/test/max_power_area.ok index 6848c1f8b..7cd859784 100644 --- a/test/max_power_area.ok +++ b/test/max_power_area.ok @@ -1,6 +1,8 @@ max_area 123.5 max_dynamic_power 1.25 max_leakage_power 0.75 +max_lol 42 set_max_area 123.5000 set_max_dynamic_power 1.2500 set_max_leakage_power 0.7500 +set_max_lol 42 diff --git a/test/max_power_area.tcl b/test/max_power_area.tcl index 017da8df1..e6bf49826 100644 --- a/test/max_power_area.tcl +++ b/test/max_power_area.tcl @@ -1,4 +1,4 @@ -# Store/retrieve/write max area and power SDC constraints. +# Store/retrieve/write max area, power, and lol SDC constraints. source helpers.tcl read_liberty asap7_small.lib.gz read_verilog reg1_asap7.v @@ -7,10 +7,12 @@ link_design top set_max_area 123.5 set_max_dynamic_power 1.25 set_max_leakage_power 0.75 +set_max_lol 42 puts "max_area [sta::max_area]" puts "max_dynamic_power [sta::max_dynamic_power]" puts "max_leakage_power [sta::max_leakage_power]" +puts "max_lol [sta::max_lol]" set sdc_file [make_result_file max_power_area.sdc] write_sdc -no_timestamp $sdc_file diff --git a/test/stadb_sdc.ok b/test/stadb_sdc.ok index ceda23671..896b4acff 100644 --- a/test/stadb_sdc.ok +++ b/test/stadb_sdc.ok @@ -24,6 +24,7 @@ sdc set_max_delay matches: 1 sdc set_max_dynamic_power matches: 1 sdc set_max_fanout matches: 1 sdc set_max_leakage_power matches: 1 +sdc set_max_lol matches: 1 sdc set_max_time_borrow matches: 1 sdc set_max_transition matches: 1 sdc set_min_capacitance matches: 1 diff --git a/test/stadb_sdc.tcl b/test/stadb_sdc.tcl index 14d4538c7..033f98d18 100644 --- a/test/stadb_sdc.tcl +++ b/test/stadb_sdc.tcl @@ -77,7 +77,8 @@ set_min_pulse_width 0.11 [get_clocks clk] set_min_pulse_width 0.09 [get_pins r1/CK] set_max_area 12345.678 set_max_leakage_power 0.00012345 -set_max_dynamic_power 0.0006789} +set_max_dynamic_power 0.0006789 +set_max_lol 42} set dump {foreach clk [get_clocks *] { stadb_dump_clock $clk }} diff --git a/test/stadb_sdc_inventory.ok b/test/stadb_sdc_inventory.ok index 8ad36667f..16d6d070b 100644 --- a/test/stadb_sdc_inventory.ok +++ b/test/stadb_sdc_inventory.ok @@ -37,6 +37,7 @@ set_max_delay stored DbSdcKind::exception stadb/DbSdc.cc set_max_dynamic_power stored DbSdcKind::max_dynamic_power stadb/DbSdc.cc set_max_fanout stored DbSdcKind::fanout_limit_* stadb/DbSdc.cc set_max_leakage_power stored DbSdcKind::max_leakage_power stadb/DbSdc.cc +set_max_lol stored DbSdcKind::max_lol stadb/DbSdc.cc set_max_time_borrow stored DbSdcKind::latch_borrow_limit stadb/DbSdc.cc set_max_transition stored DbSdcKind::slew_limit_*/clock_slew_limit stadb/DbSdc.cc set_min_capacitance stored DbSdcKind::cap_limit_* stadb/DbSdc.cc diff --git a/test/stadb_sdc_inventory.tcl b/test/stadb_sdc_inventory.tcl index 7dea221f2..c7ee6d624 100644 --- a/test/stadb_sdc_inventory.tcl +++ b/test/stadb_sdc_inventory.tcl @@ -44,6 +44,7 @@ array set stadb_sdc_map { set_max_dynamic_power {stored DbSdcKind::max_dynamic_power stadb/DbSdc.cc} set_max_fanout {stored DbSdcKind::fanout_limit_* stadb/DbSdc.cc} set_max_leakage_power {stored DbSdcKind::max_leakage_power stadb/DbSdc.cc} + set_max_lol {stored DbSdcKind::max_lol stadb/DbSdc.cc} set_max_time_borrow {stored DbSdcKind::latch_borrow_limit stadb/DbSdc.cc} set_max_transition {stored DbSdcKind::slew_limit_*/clock_slew_limit stadb/DbSdc.cc} set_min_capacitance {stored DbSdcKind::cap_limit_* stadb/DbSdc.cc}