Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
15c59e7
regression.tcl
jjcherry56 Apr 25, 2026
6fd3194
regression
jjcherry56 Apr 26, 2026
f622da7
set_mode
jjcherry56 May 1, 2026
bd1cbef
write_sdc -mode
jjcherry56 May 1, 2026
f813d94
write_verilog port missing net (issue 429)
jjcherry56 May 1, 2026
c1ebbb9
Vertex::has_sim_value_
jjcherry56 May 2, 2026
ccce34f
Merge remote-tracking branch 'parallax_sta/master' into sta_update_la…
dsengupta0628 May 5, 2026
bfbbe0d
rm blank
jjcherry56 May 5, 2026
5b9d0f3
is_object cleanup
jjcherry56 May 5, 2026
20af8fd
rm get_object_type
jjcherry56 May 5, 2026
c74dac5
clear_network clear sta
jjcherry56 May 5, 2026
e0ddce7
mv Variables.tcl to sdc
jjcherry56 May 5, 2026
afa2286
copy() use copy constructors
jjcherry56 May 5, 2026
0968c3f
comments
jjcherry56 May 5, 2026
7fca318
copy() use copy constructors
jjcherry56 May 5, 2026
801d621
Dmp delay calc inline algs
jjcherry56 May 6, 2026
9065d91
copy() use copy constructors
jjcherry56 May 6, 2026
9ccaa8c
rm report_arrival_entries
jjcherry56 May 6, 2026
b31ae3c
Search::reportArrivals
jjcherry56 May 6, 2026
4ec11fe
Sta::clockDomains
jjcherry56 May 6, 2026
2290ed9
rm cast
jjcherry56 May 6, 2026
fa3c89f
RequiredVistor integrate RequiredCmp
jjcherry56 May 6, 2026
2a2450f
read_sdc use cmd_mode
jjcherry56 May 6, 2026
ac7dfe5
Merge remote-tracking branch 'parallax_sta/master' into sta_update_la…
dsengupta0628 May 6, 2026
00f4f5e
bring back helper functions needed for our tests
dsengupta0628 May 6, 2026
8f7e85a
fix mac build
dsengupta0628 May 6, 2026
aa0b352
fix ODR violations in OpenROAD
dsengupta0628 May 6, 2026
76c4d6d
Merge branch 'master' into sta_update_latest_0505
dsengupta0628 May 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/ChangeLog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There appears to be a typo in the example provided. The note is about the write_sdc command, but the example shows read_sdc. To avoid confusion, the example should probably be for write_sdc.

  write_sdc [-mode mode]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


2026/03/23
----------

Expand Down
10 changes: 9 additions & 1 deletion include/sta/Sta.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1042,6 +1042,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.
Expand Down Expand Up @@ -1611,6 +1618,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_;
Expand Down
14 changes: 7 additions & 7 deletions sdc/Sdc.i
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 19 additions & 12 deletions sdc/Sdc.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -42,31 +42,38 @@ 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
}
}

################################################################

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)
}
Comment on lines +72 to +75

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There is a potential bug in how the mode variable is being set. The [cmd_mode] command returns a Mode* object, not the mode's name as a string. When this object is passed to write_sdc_cmd, it will likely be converted to a string representation of the pointer, causing findMode in the C++ code to fail when no -mode is specified. You should use [cmd_mode_name] to retrieve the name of the current mode.

  set mode [cmd_mode_name]
  if { [info exists keys(-mode)] } {
    set mode $keys(-mode)
  }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Search.i:822 cmd_mode() returns Mode* (SWIG pointer string _xxx_p_Mode).
Sdc.i:96 write_sdc_cmd expects std::string mode_name.
Line 72 set mode [cmd_mode] passes pointer string to wrapper expecting mode name --> findMode fails.

Line 48 already uses [cmd_mode_name] for prev_mode. Same pattern needed in line 72

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore


set digits 4
if { [info exists keys(-digits)] } {
set digits $keys(-digits)
Expand All @@ -78,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
}

################################################################
Expand Down
2 changes: 1 addition & 1 deletion sdf/Sdf.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
14 changes: 13 additions & 1 deletion search/Search.i
Original file line number Diff line number Diff line change
Expand Up @@ -818,8 +818,14 @@ cmd_mode_name()
return Sta::sta()->cmdMode()->name();
}

Mode *
cmd_mode()
{
return Sta::sta()->cmdMode();
}

void
set_mode_cmd(std::string mode_name)
set_cmd_mode(std::string mode_name)
{
Sta::sta()->setCmdMode(mode_name);
}
Expand All @@ -830,6 +836,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 &
Expand Down
78 changes: 56 additions & 22 deletions search/Sta.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The check for an empty mode_name has been removed from this function. The previous implementation had a check if (!mode_name.empty()). Without it, calling setCmdMode with an empty string could lead to a Mode with an empty name being created, which might result in an invalid state or unexpected behavior. It would be safer to restore a check for an empty mode_name at the beginning of the function.

@dsengupta0628 dsengupta0628 May 5, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit f622da7 removed if (!mode_name.empty()) guard. Now empty mode_name:

  • findKey miss (no "" entry)
  • Falls to else branch → new Mode("", ...) registered in map
  • Invalid Mode with empty name lingers

Fix: guard early in function:

void
 Sta::setCmdMode(std::string_view mode_name)
 {
   if (mode_name.empty())
     return;
   Mode *mode = findKey(mode_name_map_, std::string(mode_name));
   ...

Or report_->error(...) instead of silent return.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore

{
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();
}
}

Expand Down Expand Up @@ -2190,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,
Expand Down Expand Up @@ -2514,6 +2546,7 @@ Sta::makeDefaultScene()
makeScene(name, mode, parasitics);

cmd_scene_ = scenes_[0];
cmd_mode_ = mode;
}

// define_corners (before read_liberty).
Expand Down Expand Up @@ -2603,8 +2636,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);
Expand Down Expand Up @@ -2696,6 +2729,7 @@ void
Sta::setCmdScene(Scene *scene)
{
cmd_scene_ = scene;
cmd_mode_ = scene->mode();
}

SceneSeq
Expand Down Expand Up @@ -3529,7 +3563,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());
Expand Down Expand Up @@ -3927,14 +3961,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();
}

Expand Down
4 changes: 2 additions & 2 deletions tcl/Sta.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -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]
}

################################################################
Expand Down Expand Up @@ -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]
}

################################################################
Expand Down
11 changes: 2 additions & 9 deletions test/regression.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -525,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"
}
Expand All @@ -547,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"
Expand Down
5 changes: 3 additions & 2 deletions verilog/VerilogWriter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This condition compares two const char* pointers using !=, which compares their memory addresses instead of their string content. This is a bug. The previous implementation used !stringEqual(...), which was likely correct. You should use a proper string comparison method, such as strcmp or by converting the C-style strings to std::string before comparison.

          && std::string(network_->name(port)) != std::string(network_->name(net))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hallucination: Both Network::name(Port*) and Network::name(Net*) return std::string, not const char*. operator!= on std::string does content comparison. No bug

// 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)));
Expand Down