diff --git a/include/sta/Sdc.hh b/include/sta/Sdc.hh index a264d939..c6ddeaef 100644 --- a/include/sta/Sdc.hh +++ b/include/sta/Sdc.hh @@ -167,6 +167,7 @@ typedef Set ClkHpinDisables; typedef Set GroupPathSet; typedef Map GroupPathMap; typedef Set ClockPairSet; +typedef Map NetVoltageMap; void findLeafLoadPins(const Pin *pin, @@ -831,6 +832,20 @@ public: void setPvt(const Instance *inst, const MinMaxAll *min_max, const Pvt &pvt); + void voltage(const MinMax *min_max, + // Return values. + float &voltage, + bool &exists); + void voltage(const Net *net, + const MinMax *min_max, + // Return values. + float &voltage, + bool &exists); + void setVoltage(const MinMax *min_max, + float voltage); + void setVoltage(const Net *net, + const MinMax *min_max, + float voltage); InputDrive *findInputDrive(Port *port); Clock *findClock(const char *name) const; virtual ClockSeq findClocksMatching(PatternMatch *pattern) const; @@ -1267,6 +1282,8 @@ protected: AnalysisType analysis_type_; OperatingConditions *operating_conditions_[MinMax::index_count]; InstancePvtMap instance_pvt_maps_[MinMax::index_count]; + MinMaxFloatValues voltages_; + NetVoltageMap net_voltage_map_; DeratingFactorsGlobal *derating_factors_; NetDeratingFactorsMap net_derating_factors_; InstDeratingFactorsMap inst_derating_factors_; diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index ae3125c1..f14d0f60 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -747,6 +747,11 @@ public: void setPvt(const Instance *inst, const MinMaxAll *min_max, const Pvt &pvt); + void setVoltage(const MinMax *min_max, + float voltage); + void setVoltage(const Net *net, + const MinMax *min_max, + float voltage); // Clear all state except network. virtual void clear(); // Remove all constraints. diff --git a/messages.txt b/messages.txt index e842c26c..7fb38f8f 100644 --- a/messages.txt +++ b/messages.txt @@ -94,74 +94,74 @@ 0100 LibertyReader.cc:2918 pin name is not a string. 0101 LibertyReader.cc:2935 pin name is not a string. 0102 LibertyReader.cc:2949 pin name is not a string. -0103 LibertyReader.cc:3025 bus %s bus_type not found. -0104 LibertyReader.cc:3077 bus_type %s not found. -0105 LibertyReader.cc:3080 bus_type is not a string. -0106 LibertyReader.cc:3098 bundle %s member not found. -0107 LibertyReader.cc:3121 member is not a string. -0108 LibertyReader.cc:3128 members attribute is missing values. -0109 LibertyReader.cc:3179 unknown port direction. -0110 LibertyReader.cc:3519 pulse_latch unknown pulse type. -0111 LibertyReader.cc:3889 unknown timing_type %s. -0112 LibertyReader.cc:3909 unknown timing_sense %s. -0113 LibertyReader.cc:3949 mode value is not a string. -0114 LibertyReader.cc:3952 missing mode value. -0115 LibertyReader.cc:3955 mode name is not a string. -0116 LibertyReader.cc:3958 mode missing values. -0117 LibertyReader.cc:3961 mode missing mode name and value. +0103 LibertyReader.cc:3027 bus %s bus_type not found. +0104 LibertyReader.cc:3079 bus_type %s not found. +0105 LibertyReader.cc:3082 bus_type is not a string. +0106 LibertyReader.cc:3100 bundle %s member not found. +0107 LibertyReader.cc:3123 member is not a string. +0108 LibertyReader.cc:3130 members attribute is missing values. +0109 LibertyReader.cc:3181 unknown port direction. +0110 LibertyReader.cc:3521 pulse_latch unknown pulse type. +0111 LibertyReader.cc:3891 unknown timing_type %s. +0112 LibertyReader.cc:3911 unknown timing_sense %s. +0113 LibertyReader.cc:3951 mode value is not a string. +0114 LibertyReader.cc:3954 missing mode value. +0115 LibertyReader.cc:3957 mode name is not a string. +0116 LibertyReader.cc:3960 mode missing values. +0117 LibertyReader.cc:3963 mode missing mode name and value. 0118 LibertyReader.cc:2526 unsupported model axis. -0119 LibertyReader.cc:4064 unsupported model axis. -0120 LibertyReader.cc:4093 unsupported model axis. -0121 LibertyReader.cc:4128 unsupported model axis. -0122 LibertyReader.cc:4183 table template %s not found. -0123 LibertyReader.cc:4262 %s is missing values. -0124 LibertyReader.cc:4285 %s is not a list of floats. -0125 LibertyReader.cc:4287 table row has %u columns but axis has %d. -0126 LibertyReader.cc:4297 table has %u rows but axis has %d. -0127 LibertyReader.cc:4348 lut output is not a string. -0128 LibertyReader.cc:4390 mode definition missing name. -0129 LibertyReader.cc:4407 mode value missing name. -0130 LibertyReader.cc:4421 when attribute inside table model. -0131 LibertyReader.cc:4470 %s attribute is not a string. -0132 LibertyReader.cc:4473 %s is not a simple attribute. -0133 LibertyReader.cc:4496 %s is not a simple attribute. -0134 LibertyReader.cc:4509 %s is not a simple attribute. -0135 LibertyReader.cc:4535 %s value %s is not a float. -0136 LibertyReader.cc:4564 %s missing values. -0137 LibertyReader.cc:4568 %s missing values. -0138 LibertyReader.cc:4571 %s is not a complex attribute. -0139 LibertyReader.cc:4597 %s is not a float. -0140 LibertyReader.cc:4620 %s is missing values. -0141 LibertyReader.cc:4623 %s has more than one string. -0142 LibertyReader.cc:4632 %s is missing values. -0143 LibertyReader.cc:4657 %s attribute is not boolean. -0144 LibertyReader.cc:4660 %s attribute is not boolean. -0145 LibertyReader.cc:4663 %s is not a simple attribute. -0146 LibertyReader.cc:4679 attribute %s value %s not recognized. -0147 LibertyReader.cc:4710 unknown early/late value. -0148 LibertyReader.cc:4930 OCV derate group named %s not found. -0149 LibertyReader.cc:4946 ocv_derate missing name. -0150 LibertyReader.cc:4999 unknown rise/fall. -0151 LibertyReader.cc:5019 unknown derate type. -0152 LibertyReader.cc:5051 unsupported model axis. -0153 LibertyReader.cc:5083 unsupported model axis. -0154 LibertyReader.cc:5115 unsupported model axis. -0155 LibertyReader.cc:5186 unknown pg_type. -0156 LibertyReader.cc:5581 port %s subscript out of range. -0157 LibertyReader.cc:5585 port range %s of non-bus port %s. -0158 LibertyReader.cc:5599 port %s not found. -0159 LibertyReader.cc:5669 port %s not found. +0119 LibertyReader.cc:4066 unsupported model axis. +0120 LibertyReader.cc:4095 unsupported model axis. +0121 LibertyReader.cc:4130 unsupported model axis. +0122 LibertyReader.cc:4185 table template %s not found. +0123 LibertyReader.cc:4264 %s is missing values. +0124 LibertyReader.cc:4287 %s is not a list of floats. +0125 LibertyReader.cc:4289 table row has %u columns but axis has %d. +0126 LibertyReader.cc:4299 table has %u rows but axis has %d. +0127 LibertyReader.cc:4350 lut output is not a string. +0128 LibertyReader.cc:4392 mode definition missing name. +0129 LibertyReader.cc:4409 mode value missing name. +0130 LibertyReader.cc:4423 when attribute inside table model. +0131 LibertyReader.cc:4472 %s attribute is not a string. +0132 LibertyReader.cc:4475 %s is not a simple attribute. +0133 LibertyReader.cc:4498 %s is not a simple attribute. +0134 LibertyReader.cc:4511 %s is not a simple attribute. +0135 LibertyReader.cc:4537 %s value %s is not a float. +0136 LibertyReader.cc:4566 %s missing values. +0137 LibertyReader.cc:4570 %s missing values. +0138 LibertyReader.cc:4573 %s is not a complex attribute. +0139 LibertyReader.cc:4599 %s is not a float. +0140 LibertyReader.cc:4622 %s is missing values. +0141 LibertyReader.cc:4625 %s has more than one string. +0142 LibertyReader.cc:4634 %s is missing values. +0143 LibertyReader.cc:4659 %s attribute is not boolean. +0144 LibertyReader.cc:4662 %s attribute is not boolean. +0145 LibertyReader.cc:4665 %s is not a simple attribute. +0146 LibertyReader.cc:4681 attribute %s value %s not recognized. +0147 LibertyReader.cc:4712 unknown early/late value. +0148 LibertyReader.cc:4932 OCV derate group named %s not found. +0149 LibertyReader.cc:4948 ocv_derate missing name. +0150 LibertyReader.cc:5001 unknown rise/fall. +0151 LibertyReader.cc:5021 unknown derate type. +0152 LibertyReader.cc:5053 unsupported model axis. +0153 LibertyReader.cc:5085 unsupported model axis. +0154 LibertyReader.cc:5117 unsupported model axis. +0155 LibertyReader.cc:5188 unknown pg_type. +0156 LibertyReader.cc:5583 port %s subscript out of range. +0157 LibertyReader.cc:5587 port range %s of non-bus port %s. +0158 LibertyReader.cc:5601 port %s not found. +0159 LibertyReader.cc:5671 port %s not found. 0160 LibertyReader.cc:1026 default_max_transition is 0.0. -0161 LibertyReader.cc:3413 max_transition is 0.0. -0162 LibertyReader.cc:4493 %s attribute is not an integer. +0161 LibertyReader.cc:3415 max_transition is 0.0. +0162 LibertyReader.cc:4495 %s attribute is not an integer. 0163 LibertyReader.cc:1131 default_fanout_load is 0.0. 0164 LibertyReader.cc:2299 timing group from output port. 0165 LibertyReader.cc:2309 timing group from output port. 0166 LibertyReader.cc:2319 timing group from output port. 0167 LibertyReader.cc:2337 timing group from output port. 0168 LibertyReader.cc:2353 timing group from output port. -0169 LibertyReader.cc:4365 cell %s test_cell redefinition. -0170 LibertyReader.cc:3808 timing group missing related_pin/related_bus_pin. +0169 LibertyReader.cc:4367 cell %s test_cell redefinition. +0170 LibertyReader.cc:3810 timing group missing related_pin/related_bus_pin. 0171 LibertyReader.cc:815 unknown unit suffix %s. 0179 SpefReader.cc:734 %s. 0201 StaTcl.i:118 no network has been linked. @@ -264,7 +264,7 @@ 0370 Sdc.tcl:3336 no valid objects specified for $key 0371 Sdc.tcl:3497 set_wire_load_min_block_size not supported. 0372 NetworkEdit.tcl:137 connect_pins is deprecated. Use connect_pin. -0373 Sdc.tcl:3647 define_corners must be called before read_liberty. +0373 Sdc.tcl:3663 define_corners must be called before read_liberty. 0374 Sta.cc:2416 maximum corner count exceeded 0400 Util.tcl:44 $cmd $key missing value. 0401 Util.tcl:61 $cmd $key missing value. @@ -444,7 +444,7 @@ 0582 Sdc.tcl:3510 mode must be top, enclosed or segmented. 0583 Sdc.tcl:3525 no wire load model specified. 0584 Sdc.tcl:3586 wire load selection group '$selection_name' not found. -0585 Sdc.tcl:3717 no default operating conditions found. +0585 Sdc.tcl:3733 no default operating conditions found. 0586 NetworkEdit.tcl:107 unsupported object type $object_type. 0587 NetworkEdit.tcl:206 unsupported object type $object_type. 0588 NetworkEdit.tcl:224 unsupported object type $object_type. @@ -497,9 +497,9 @@ 0900 LibertyReader.cc:2817 level_shifter_type must be HL, LH, or HL_LH 0901 LibertyReader.cc:2853 switch_cell_type must be coarse_grain or fine_grain 0902 LibertyReader.cc:2437 unsupported model axis. -0903 LibertyReader.cc:4144 %s group not in timing group. +0903 LibertyReader.cc:4146 %s group not in timing group. 0904 LibertyReader.cc:2420 receiver_capacitance group not in timing or pin group. -0906 LibertyReader.cc:4037 unsupported model axis. +0906 LibertyReader.cc:4039 unsupported model axis. 0907 LibertyReader.cc:2465 output_current_%s group not in timing group. 0908 LibertyReader.cc:2570 vector reference_time not found. 0912 LibertyReader.cc:2568 vector index_1 and index_2 must have exactly one value. diff --git a/power/Vcd.hh b/power/Vcd.hh index dbe45056..76d904b5 100644 --- a/power/Vcd.hh +++ b/power/Vcd.hh @@ -47,6 +47,7 @@ enum class VcdVarType { real, supply0, supply1, + time, tri, triand, trior, diff --git a/power/VcdReader.cc b/power/VcdReader.cc index cd7e5e77..8c6ff5c8 100644 --- a/power/VcdReader.cc +++ b/power/VcdReader.cc @@ -169,6 +169,7 @@ static EnumNameMap vcd_var_type_map = {VcdVarType::real, "real"}, {VcdVarType::supply0, "supply0"}, {VcdVarType::supply1, "supply1"}, + {VcdVarType::time, "time"}, {VcdVarType::tri, "tri"}, {VcdVarType::triand, "triand"}, {VcdVarType::trior, "trior"}, diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index 949b5c2d..c16d4519 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -490,6 +490,42 @@ Sdc::setPvt(const Instance *inst, } } +void +Sdc::voltage(const MinMax *min_max, + // Return values. + float &voltage, + bool &exists) +{ + voltages_.value(min_max, voltage, exists); +} + +void +Sdc::voltage(const Net *net, + const MinMax *min_max, + // Return values. + float &voltage, + bool &exists) +{ + exists = false; + if (net_voltage_map_.hasKey(net)) + net_voltage_map_[net].value(min_max, voltage, exists); +} + +void +Sdc::setVoltage(const MinMax *min_max, + float voltage) +{ + voltages_.setValue(min_max, voltage); +} + +void +Sdc::setVoltage(const Net *net, + const MinMax *min_max, + float voltage) +{ + net_voltage_map_[net].setValue(min_max, voltage); +} + //////////////////////////////////////////////////////////////// void diff --git a/sdc/WriteSdc.cc b/sdc/WriteSdc.cc index eb172099..e937abac 100644 --- a/sdc/WriteSdc.cc +++ b/sdc/WriteSdc.cc @@ -1488,6 +1488,7 @@ WriteSdc::writeEnvironment() const writeConstants(); writeCaseAnalysis(); writeDeratings(); + writeVoltages(); } void @@ -2012,6 +2013,43 @@ timingDerateTypeKeyword(TimingDerateType type) //////////////////////////////////////////////////////////////// +void +WriteSdc::writeVoltages() const +{ + float voltage_max, voltage_min; + bool exists_max, exists_min; + sdc_->voltage(MinMax::max(), voltage_max, exists_max); + if (exists_max) { + sdc_->voltage(MinMax::min(), voltage_min, exists_min); + if (exists_min) + gzprintf(stream_, "set_voltage -min %.3f %.3f\n", + voltage_min, + voltage_max); + else + gzprintf(stream_, "set_voltage %.3f\n", voltage_max); + } + + for (auto net_volt : sdc_->net_voltage_map_) { + const Net *net = net_volt.first; + MinMaxFloatValues &values = net_volt.second; + values.value(MinMax::max(), voltage_max, exists_max); + if (exists_max) { + values.value(MinMax::min(), voltage_min, exists_min); + if (exists_min) + gzprintf(stream_, "set_voltage -object_list %s -min %.3f %.3f\n", + sdc_network_->pathName(net), + voltage_min, + voltage_max); + else + gzprintf(stream_, "set_voltage -object_list %s %.3f\n", + sdc_network_->pathName(net), + voltage_max); + } + } +} + +//////////////////////////////////////////////////////////////// + void WriteSdc::writeDesignRules() const { diff --git a/sdc/WriteSdcPvt.hh b/sdc/WriteSdcPvt.hh index d7470aee..5e07de2b 100644 --- a/sdc/WriteSdcPvt.hh +++ b/sdc/WriteSdcPvt.hh @@ -170,6 +170,7 @@ public: TimingDerateType type, const MinMax *early_late, WriteSdcObject *write_obj) const; + void writeVoltages() const; const char *pathName(const Pin *pin) const; const char *pathName(const Net *net) const; diff --git a/search/Sta.cc b/search/Sta.cc index e2ac0484..a67dfae7 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -826,6 +826,21 @@ Sta::setPvt(const Instance *inst, delaysInvalidFrom(inst); } +void +Sta::setVoltage(const MinMax *min_max, + float voltage) +{ + sdc_->setVoltage(min_max, voltage); +} + +void +Sta::setVoltage(const Net *net, + const MinMax *min_max, + float voltage) +{ + sdc_->setVoltage(net, min_max, voltage); +} + void Sta::setTimingDerate(TimingDerateType type, PathClkOrData clk_data, diff --git a/tcl/CmdArgs.tcl b/tcl/CmdArgs.tcl index 7610315a..c19df5a1 100644 --- a/tcl/CmdArgs.tcl +++ b/tcl/CmdArgs.tcl @@ -882,7 +882,7 @@ proc get_clocks_warn { arg_name arglist } { return $clks } -proc get_net_warn { arg_name arg } { +proc get_net_arg { arg_name arg } { set net "NULL" if {[llength $arg] > 1} { sta_warn 314 "$arg_name must be a single net." @@ -902,31 +902,23 @@ proc get_net_warn { arg_name arg } { return $net } -proc get_nets_error { arg_name arglist } { - return [get_nets_arg $arg_name $arglist "error"] -} - -proc get_nets_warn { arg_name arglist } { - return [get_nets_arg $arg_name $arglist "warn"] -} - -proc get_nets_arg { arg_name arglist warn_error } { +proc get_nets_arg { arg_name arglist } { set nets {} # Copy backslashes that will be removed by foreach. set arglist [string map {\\ \\\\} $arglist] foreach arg $arglist { if {[llength $arg] > 1} { # Embedded list. - set nets [concat $nets [get_nets_arg $arg_name $arg $warn_error]] + set nets [concat $nets [get_nets_arg $arg_name $arg]] } elseif { [is_object $arg] } { set object_type [object_type $arg] if { $object_type == "Net" } { lappend nets $arg } else { - sta_warn_error 317 $warn_error "unsupported object type $object_type." + sta_warn 317 "unsupported object type $object_type." } } elseif { $arg != {} } { - set arg_nets [get_nets -quiet $arg] + set arg_nets [get_nets $arg] if { $arg_nets != {} } { set nets [concat $nets $arg_nets] } diff --git a/tcl/NetworkEdit.tcl b/tcl/NetworkEdit.tcl index 639ea95f..d3e48208 100644 --- a/tcl/NetworkEdit.tcl +++ b/tcl/NetworkEdit.tcl @@ -80,7 +80,7 @@ proc connect_pin { net pin } { if { $insts_port == 0 } { return 0 } - set net [get_net_warn "net" $net] + set net [get_net_arg "net" $net] if { $net == "NULL" } { return 0 } @@ -140,7 +140,7 @@ proc connect_pins { net pins } { if { $insts_ports == 0 } { return 0 } - set net [get_net_warn "net" $net] + set net [get_net_arg "net" $net] if { $net == "NULL" } { return 0 } @@ -170,7 +170,7 @@ proc parse_connect_pins { arg } { define_cmd_args "disconnect_pin" {net -all|pin} proc disconnect_pin { net pin } { - set net [get_net_warn "net" $net] + set net [get_net_arg "net" $net] if { $net == "NULL" } { return 0 } diff --git a/tcl/Sdc.tcl b/tcl/Sdc.tcl index b5f30896..4f5b97d5 100644 --- a/tcl/Sdc.tcl +++ b/tcl/Sdc.tcl @@ -952,7 +952,7 @@ proc get_ports { args } { if { $args != {} } { sta_warn 336 "patterns argument not supported with -of_objects." } - set nets [get_nets_warn "objects" $keys(-of_objects)] + set nets [get_nets_arg "objects" $keys(-of_objects)] foreach net $nets { set ports [concat $ports [$net ports]] } @@ -3172,7 +3172,7 @@ proc set_resistance { args } { set res [lindex $args 0] check_positive_float "resistance" $res set res [resistance_ui_sta $res] - set nets [get_nets_error "nets" [lindex $args 1]] + set nets [get_nets_arg "nets" [lindex $args 1]] foreach net $nets { set_net_resistance $net $min_max $res } @@ -3594,6 +3594,33 @@ proc set_wire_load_selection_group { args } { # ################################################################ +define_cmd_args "set_voltage" \ + {[-min min_case_value] [-object_list list_of_power_nets] max_case_voltage} + +proc set_voltage { args } { + parse_key_args "set_voltage" args keys {-min -object_list} flags {} + check_argc_eq1 "set_voltage" $args + set max_case_voltage [lindex $args 0] + check_float "max_case_voltage" $max_case_voltage + + set nets {} + if { [info exists keys(-object_list)] } { + set nets [get_nets_arg "-object_list" $keys(-object_list)] + } + set_voltage_global "max" $max_case_voltage + foreach net $nets { + set_voltage_net $net "max" $max_case_voltage + } + if { [info exists keys(-min)] } { + set min_case_voltage $keys(-min) + check_float "-min" $min_case_voltage + set_voltage_global "min" $min_case_voltage + foreach net $nets { + set_voltage_net $net "min" $min_case_voltage + } + } +} + define_cmd_args "create_voltage_area" \ {[-name name] [-coordinate coordinates] [-guard_band_x guard_x]\ [-guard_band_y guard_y] cells } diff --git a/tcl/Search.tcl b/tcl/Search.tcl index c183bc49..192ac052 100644 --- a/tcl/Search.tcl +++ b/tcl/Search.tcl @@ -431,7 +431,7 @@ proc_redirect report_check_types { set net "NULL" if { [info exists keys(-net)] } { - set net [get_net_warn "-net" $keys(-net)] + set net [get_net_arg "-net" $keys(-net)] } if { $args == {} } { diff --git a/tcl/Splash.tcl b/tcl/Splash.tcl index a64345e7..398e25de 100644 --- a/tcl/Splash.tcl +++ b/tcl/Splash.tcl @@ -25,7 +25,7 @@ namespace eval sta { define_cmd_args show_splash {} proc show_splash {} { - report_line "OpenSTA [sta::version] [string range [sta::git_sha1] 0 9] Copyright (c) 2021, Parallax Software, Inc. + report_line "OpenSTA [sta::version] [string range [sta::git_sha1] 0 9] Copyright (c) 2023, Parallax Software, Inc. License GPLv3: GNU GPL version 3 This is free software, and you are free to change and redistribute it diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index e592b660..870267b4 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -5450,6 +5450,21 @@ endpoint_violation_count(const MinMax *min_max) return Sta::sta()->endpointViolationCount(min_max); } +void +set_voltage_global(const MinMax *min_max, + float voltage) +{ + Sta::sta()->setVoltage(min_max, voltage); +} + +void +set_voltage_net(const Net *net, + const MinMax *min_max, + float voltage) +{ + Sta::sta()->setVoltage(net, min_max, voltage); +} + %} // inline ////////////////////////////////////////////////////////////////