From 15c59e752701d75499a9b6da158a23f86f014ab4 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 25 Apr 2026 16:05:09 -0700 Subject: [PATCH 1/5] regression.tcl Signed-off-by: James Cherry --- test/regression.tcl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/regression.tcl b/test/regression.tcl index 3afe8287..bec27ac3 100755 --- a/test/regression.tcl +++ b/test/regression.tcl @@ -156,11 +156,8 @@ proc expand_tests { argv } { lappend tests $test } } - } elseif { [lsearch [group_tests "all"] $arg] != -1 } { - lappend tests $arg } else { - puts "Error: test $arg not found." - incr errors(no_cmd) + lappend tests $arg } } return $tests From 6fd319474fbe5e179464f3d675aae9c06a55e6d6 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 25 Apr 2026 18:59:53 -0700 Subject: [PATCH 2/5] regression Signed-off-by: James Cherry --- test/regression.tcl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/regression.tcl b/test/regression.tcl index bec27ac3..523589be 100755 --- a/test/regression.tcl +++ b/test/regression.tcl @@ -522,15 +522,11 @@ proc show_summary {} { if { $valgrind_shared_lib_failure } { puts "WARNING: valgrind failed because the executable is not statically linked." } - puts "See $result_dir for log files" set test_count [llength $tests] if { [found_errors] } { if { $errors(error) != 0 } { puts "Errored $errors(error)/$test_count" } - if { $errors(fail) != 0 } { - puts "Failed $errors(fail)/$test_count" - } if { $errors(leak) != 0 } { puts "Memory leaks in $errors(leak)/$test_count" } @@ -544,7 +540,7 @@ proc show_summary {} { puts "No cmd tcl file for $errors(no_cmd)/$test_count" } if { $errors(fail) != 0 } { - puts "See $diff_file for differences" + puts "Failed $errors(fail)/$test_count" } } else { puts "Passed $test_count" From f622da713443662802b36d1c06d5089561cdc248 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Fri, 1 May 2026 10:01:10 -0700 Subject: [PATCH 3/5] set_mode Signed-off-by: James Cherry --- include/sta/Sta.hh | 3 ++- sdc/Sdc.tcl | 20 ++++++++------- search/Search.i | 2 +- search/Sta.cc | 62 ++++++++++++++++++++++++++++++---------------- tcl/Sta.tcl | 4 +-- 5 files changed, 56 insertions(+), 35 deletions(-) diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 7817b1c2..5f9c1362 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -138,7 +138,7 @@ public: void setCmdScene(Scene *scene); SceneSeq makeSceneSeq(Scene *scene) const; - Mode *cmdMode() const { return cmd_scene_->mode(); } + Mode *cmdMode() const { return cmd_mode_; } const std::string &cmdModeName(); void setCmdMode(std::string_view mode_name); Mode *findMode(std::string_view mode_name) const; @@ -1604,6 +1604,7 @@ protected: void checkLibrarayPocv(); Scene *cmd_scene_{nullptr}; + Mode *cmd_mode_{nullptr}; CmdNamespace cmd_namespace_{CmdNamespace::sdc}; Instance *current_instance_{nullptr}; SceneNameMap scene_name_map_; diff --git a/sdc/Sdc.tcl b/sdc/Sdc.tcl index d8e5aef1..4c11522b 100644 --- a/sdc/Sdc.tcl +++ b/sdc/Sdc.tcl @@ -42,18 +42,20 @@ proc_redirect read_sdc { check_argc_eq1 "read_sdc" $args set echo [info exists flags(-echo)] set filename [file nativename [lindex $args 0]] - set mode_name {} + if { [info exists keys(-mode)] } { set mode_name $keys(-mode) - } - set prev_mode [cmd_mode_name] - try { - set_mode_cmd $mode_name - include_file $filename $echo 0 - } finally { - if { $prev_mode != "default" } { - set_mode_cmd $prev_mode + set prev_mode [cmd_mode_name] + try { + set_cmd_mode $mode_name + include_file $filename $echo 0 + } finally { + if { $prev_mode != "default" } { + set_cmd_mode $prev_mode + } } + } else { + include_file $filename $echo 0 } } diff --git a/search/Search.i b/search/Search.i index 0764ae68..85de21d5 100644 --- a/search/Search.i +++ b/search/Search.i @@ -817,7 +817,7 @@ cmd_mode_name() } void -set_mode_cmd(std::string mode_name) +set_cmd_mode(std::string mode_name) { Sta::sta()->setCmdMode(mode_name); } diff --git a/search/Sta.cc b/search/Sta.cc index 9ccdc841..6593b16d 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -570,30 +570,46 @@ Sta::clearNonSdc() Sdc * Sta::cmdSdc() const { - return cmdMode()->sdc(); + return cmd_mode_->sdc(); } void Sta::setCmdMode(std::string_view mode_name) { - if (!mode_name.empty()) { - if (!mode_name_map_.contains(mode_name)) { - if (modes_.size() == 1 && modes_[0]->name() == "default") { - // No need for default mode if one is defined. - delete modes_[0]; - mode_name_map_.clear(); - modes_.clear(); + Mode *mode = findKey(mode_name_map_, std::string(mode_name)); + if (mode) { + // Sync scene with mode. Note that multiple scenes can share a mode. + Scene *mode_scene = nullptr; + for (Scene *scene : scenes_) { + if (scene->mode() == mode) { + if (mode_scene) { + report_->warn(1556, "multiple scenes reference mode {}", mode_name); + break; + } + mode_scene = scene; } - Mode *mode = new Mode(mode_name, mode_name_map_.size(), this); - mode_name_map_[std::string(mode_name)] = mode; - modes_.push_back(mode); - mode->sim()->setMode(mode); - mode->sim()->setObserver(new StaSimObserver(this)); - - if (scenes_.size() == 1 && scenes_[0]->name() == "default") - scenes_[0]->setMode(mode); - updateComponentsState(); } + if (mode_scene) + cmd_scene_ = mode_scene; + cmd_mode_ = mode; + } + else { + if (modes_.size() == 1 && modes_[0]->name() == "default") { + // No need for default mode if one is defined. + delete modes_[0]; + mode_name_map_.clear(); + modes_.clear(); + } + Mode *mode = new Mode(mode_name, mode_name_map_.size(), this); + mode_name_map_[std::string(mode_name)] = mode; + modes_.push_back(mode); + mode->sim()->setMode(mode); + mode->sim()->setObserver(new StaSimObserver(this)); + cmd_mode_ = mode; + + if (scenes_.size() == 1 && scenes_[0]->name() == "default") + scenes_[0]->setMode(mode); + updateComponentsState(); } } @@ -2514,6 +2530,7 @@ Sta::makeDefaultScene() makeScene(name, mode, parasitics); cmd_scene_ = scenes_[0]; + cmd_mode_ = mode; } // define_corners (before read_liberty). @@ -2603,8 +2620,8 @@ Sta::makeScene(const std::string &name, if (scenes_.size() == 1 && findScene("default")) deleteScenes(); - Scene *scene = - new Scene(name, scenes_.size(), mode, parasitics_min, parasitics_max); + Scene *scene = new Scene(name, scenes_.size(), mode, + parasitics_min, parasitics_max); scene_name_map_[name] = scene; scenes_.push_back(scene); mode->addScene(scene); @@ -2696,6 +2713,7 @@ void Sta::setCmdScene(Scene *scene) { cmd_scene_ = scene; + cmd_mode_ = scene->mode(); } SceneSeq @@ -3496,7 +3514,7 @@ Sta::findRequired(Vertex *vertex) search_->findAllArrivals(); if (search_->isEndpoint(vertex) // Need to include downstream required times if there is fanout. - && !hasFanout(vertex, search_->searchAdj(), graph_, cmdMode())) + && !hasFanout(vertex, search_->searchAdj(), graph_, cmd_mode_)) search_->seedRequired(vertex); else search_->findRequireds(vertex->level()); @@ -3894,14 +3912,14 @@ Sta::findLogicConstants() { ensureGraph(); // Sdc independent constants so any mode should return the same values. - Sim *sim = cmdMode()->sim(); + Sim *sim = cmd_mode_->sim(); sim->findLogicConstants(); } void Sta::clearLogicConstants() { - Sim *sim = cmdMode()->sim(); + Sim *sim = cmd_mode_->sim(); sim->clear(); } diff --git a/tcl/Sta.tcl b/tcl/Sta.tcl index 2db64f5e..ee560962 100644 --- a/tcl/Sta.tcl +++ b/tcl/Sta.tcl @@ -102,7 +102,7 @@ define_cmd_args "set_scene" {scene_name} proc set_scene { args } { check_argc_eq1 "set_scene" $args - set_scene_cmd [lindex $args 0] + set_cmd_scene [lindex $args 0] } ################################################################ @@ -141,7 +141,7 @@ define_cmd_args "set_mode" {mode_name} proc set_mode { args } { check_argc_eq1 "set_mode" $args - set_mode_cmd [lindex $args 0] + set_cmd_mode [lindex $args 0] } ################################################################ From bd1cbefcd5a8aeed69c6332e02f6c47fecdfb469 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Fri, 1 May 2026 10:32:20 -0700 Subject: [PATCH 4/5] write_sdc -mode Signed-off-by: James Cherry --- doc/ChangeLog.txt | 7 +++++++ include/sta/Sta.hh | 7 +++++++ sdc/Sdc.i | 14 +++++++------- sdc/Sdc.tcl | 11 ++++++++--- sdf/Sdf.tcl | 2 +- search/Search.i | 12 ++++++++++++ search/Sta.cc | 16 ++++++++++++++++ 7 files changed, 58 insertions(+), 11 deletions(-) diff --git a/doc/ChangeLog.txt b/doc/ChangeLog.txt index b6238246..496aab91 100644 --- a/doc/ChangeLog.txt +++ b/doc/ChangeLog.txt @@ -4,6 +4,13 @@ OpenSTA Timing Analyzer Release Notes This file summarizes user visible changes for each release. See ApiChangeLog.txt for changes to the STA api. +2026/05/01 +---------- + +The write_sdc command supports a -mode argument. + + read_sdc [-mode mode] + 2026/03/23 ---------- diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 5f9c1362..5237ec9a 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -1041,6 +1041,13 @@ public: const Scene *scene, const MinMax *min_max, int digits); + void writeSdc(std::string_view filename, + std::string_view mode_name, + bool leaf, + bool native, + int digits, + bool gzip, + bool no_timestamp); void writeSdc(const Sdc *sdc, std::string_view filename, // Map hierarchical pins and instances to leaf pins and instances. diff --git a/sdc/Sdc.i b/sdc/Sdc.i index 0a02cb07..4b3050b0 100644 --- a/sdc/Sdc.i +++ b/sdc/Sdc.i @@ -94,15 +94,15 @@ private: void write_sdc_cmd(std::string filename, - bool leaf, - bool compatible, - int digits, - bool gzip, - bool no_timestamp) + std::string mode_name, + bool leaf, + bool compatible, + int digits, + bool gzip, + bool no_timestamp) { Sta *sta = Sta::sta(); - const Sdc *sdc = sta->cmdSdc(); - sta->writeSdc(sdc, filename, leaf, compatible, digits, gzip, no_timestamp); + sta->writeSdc(filename, mode_name, leaf, compatible, digits, gzip, no_timestamp); } void diff --git a/sdc/Sdc.tcl b/sdc/Sdc.tcl index 4c11522b..ead9a778 100644 --- a/sdc/Sdc.tcl +++ b/sdc/Sdc.tcl @@ -62,13 +62,18 @@ proc_redirect read_sdc { ################################################################ define_cmd_args "write_sdc" \ - {[-map_hpins] [-digits digits] [-gzip] [-no_timestamp] filename} + {[-mode mode] [-map_hpins] [-digits digits] [-gzip] [-no_timestamp] filename} proc write_sdc { args } { - parse_key_args "write_sdc" args keys {-digits -significant_digits} \ + parse_key_args "write_sdc" args keys {-mode -digits} \ flags {-map_hpins -compatible -gzip -no_timestamp} check_argc_eq1 "write_sdc" $args + set mode [cmd_mode] + if { [info exists keys(-mode)] } { + set mode $keys(-mode) + } + set digits 4 if { [info exists keys(-digits)] } { set digits $keys(-digits) @@ -80,7 +85,7 @@ proc write_sdc { args } { set no_timestamp [info exists flags(-no_timestamp)] set map_hpins [info exists flags(-map_hpins)] set native [expr ![info exists flags(-compatible)]] - write_sdc_cmd $filename $map_hpins $native $digits $gzip $no_timestamp + write_sdc_cmd $filename $mode $map_hpins $native $digits $gzip $no_timestamp } ################################################################ diff --git a/sdf/Sdf.tcl b/sdf/Sdf.tcl index df0a775c..bdbb1de8 100644 --- a/sdf/Sdf.tcl +++ b/sdf/Sdf.tcl @@ -180,7 +180,7 @@ define_cmd_args "write_sdf" \ proc_redirect write_sdf { parse_key_args "write_sdf" args \ - keys {-corner -scene -divider -digits -significant_digits} \ + keys {-corner -scene -divider -digits} \ flags {-include_typ -gzip -no_timestamp -no_version} check_argc_eq1 "write_sdf" $args set scene [parse_scene keys] diff --git a/search/Search.i b/search/Search.i index 85de21d5..d3eb7455 100644 --- a/search/Search.i +++ b/search/Search.i @@ -816,6 +816,12 @@ cmd_mode_name() return Sta::sta()->cmdMode()->name(); } +Mode * +cmd_mode() +{ + return Sta::sta()->cmdMode(); +} + void set_cmd_mode(std::string mode_name) { @@ -828,6 +834,12 @@ find_modes(std::string mode_name) return Sta::sta()->findModes(mode_name); } +Mode * +find_mode(std::string mode_name) +{ + return Sta::sta()->findMode(mode_name); +} + //////////////////////////////////////////////////////////////// CheckErrorSeq & diff --git a/search/Sta.cc b/search/Sta.cc index 6593b16d..357256d0 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2206,6 +2206,22 @@ Sta::checkExceptionToPins(ExceptionTo *to, } } +void +Sta::writeSdc(std::string_view filename, + std::string_view mode_name, + bool leaf, + bool native, + int digits, + bool gzip, + bool no_timestamp) +{ + Mode *mode = findMode(mode_name); + if (mode) + writeSdc(mode->sdc(), filename, leaf, native, digits, gzip, no_timestamp); + else + report_->warn(1561, "mode {} not found.", mode_name); +} + void Sta::writeSdc(const Sdc *sdc, std::string_view filename, From f813d949ae16507b221526c83b80b40fc255c91d Mon Sep 17 00:00:00 2001 From: James Cherry Date: Fri, 1 May 2026 11:34:15 -0700 Subject: [PATCH 5/5] write_verilog port missing net (issue 429) Signed-off-by: James Cherry --- verilog/VerilogWriter.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/verilog/VerilogWriter.cc b/verilog/VerilogWriter.cc index 4f5e5fc6..c5d3fe7a 100644 --- a/verilog/VerilogWriter.cc +++ b/verilog/VerilogWriter.cc @@ -447,12 +447,13 @@ VerilogWriter::writeAssigns(const Instance *inst) if (term) { Net *net = network_->net(term); Port *port = network_->port(pin); - if (port + if (net + && port && (include_pwr_gnd_ || !(network_->isPower(net) || network_->isGround(net))) && (network_->direction(port)->isAnyOutput() || (include_pwr_gnd_ && network_->direction(port)->isPowerGround())) - && !stringEqual(network_->name(port), network_->name(net))) { + && network_->name(port) != network_->name(net)) { // Port name is different from net name. std::string port_vname = netVerilogName(std::string(network_->name(port))); std::string net_vname = netVerilogName(std::string(network_->name(net)));