make mode/scene pass as tcl objects (#454)

* make mode/scene pass as tcl objects

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>

* address review comments

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>

* address review comments take 2

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>

* revert to using cmd mode name

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>

---------

Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
This commit is contained in:
Deepashree Sengupta 2026-06-30 12:18:56 -04:00 committed by GitHub
parent 310107acd8
commit 998806cb13
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 161 additions and 83 deletions

View File

@ -42,6 +42,8 @@ class PropertyValue;
class Sta; class Sta;
class PropertyValue; class PropertyValue;
class Scene;
class Mode;
template<class TYPE> template<class TYPE>
class PropertyRegistry class PropertyRegistry
@ -86,6 +88,10 @@ public:
std::string_view property); std::string_view property);
PropertyValue getProperty(const Clock *clk, PropertyValue getProperty(const Clock *clk,
std::string_view property); std::string_view property);
PropertyValue getProperty(const Scene *scene,
std::string_view property);
PropertyValue getProperty(const Mode *mode,
std::string_view property);
PropertyValue getProperty(PathEnd *end, PropertyValue getProperty(PathEnd *end,
std::string_view property); std::string_view property);
PropertyValue getProperty(Path *path, PropertyValue getProperty(Path *path,

View File

@ -45,7 +45,7 @@ proc_redirect read_sdc {
if { [info exists keys(-mode)] } { if { [info exists keys(-mode)] } {
set mode_name $keys(-mode) set mode_name $keys(-mode)
set prev_mode [cmd_mode] set prev_mode [cmd_mode_name]
try { try {
set_cmd_mode $mode_name set_cmd_mode $mode_name
include_file $filename $echo 0 include_file $filename $echo 0
@ -69,7 +69,7 @@ proc write_sdc { args } {
flags {-map_hpins -compatible -gzip -no_timestamp} flags {-map_hpins -compatible -gzip -no_timestamp}
check_argc_eq1 "write_sdc" $args check_argc_eq1 "write_sdc" $args
set mode [cmd_mode] set mode [cmd_mode_name]
if { [info exists keys(-mode)] } { if { [info exists keys(-mode)] } {
set mode $keys(-mode) set mode $keys(-mode)
} }

View File

@ -33,6 +33,7 @@
#include "Graph.hh" #include "Graph.hh"
#include "Liberty.hh" #include "Liberty.hh"
#include "MinMax.hh" #include "MinMax.hh"
#include "Mode.hh"
#include "Network.hh" #include "Network.hh"
#include "Path.hh" #include "Path.hh"
#include "PathEnd.hh" #include "PathEnd.hh"
@ -1196,6 +1197,32 @@ Properties::getProperty(const Clock *clk,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
PropertyValue
Properties::getProperty(const Scene *scene,
std::string_view property)
{
if (property == "name"
|| property == "full_name")
return PropertyValue(scene->name());
else
throw PropertyUnknown("scene", property);
}
////////////////////////////////////////////////////////////////
PropertyValue
Properties::getProperty(const Mode *mode,
std::string_view property)
{
if (property == "name"
|| property == "full_name")
return PropertyValue(mode->name());
else
throw PropertyUnknown("mode", property);
}
////////////////////////////////////////////////////////////////
PropertyValue PropertyValue
Properties::getProperty(PathEnd *end, Properties::getProperty(PathEnd *end,
std::string_view property) std::string_view property)

View File

@ -121,6 +121,22 @@ clock_property(Clock *clk,
return properties.getProperty(clk, property); return properties.getProperty(clk, property);
} }
PropertyValue
scene_property(Scene *scene,
const char *property)
{
Properties &properties = Sta::sta()->properties();
return properties.getProperty(scene, property);
}
PropertyValue
mode_property(Mode *mode,
const char *property)
{
Properties &properties = Sta::sta()->properties();
return properties.getProperty(mode, property);
}
PropertyValue PropertyValue
path_end_property(PathEnd *end, path_end_property(PathEnd *end,
const char *property) const char *property)

View File

@ -72,6 +72,20 @@ private:
~PathEnd(); ~PathEnd();
}; };
class Scene
{
private:
Scene();
~Scene();
};
class Mode
{
private:
Mode();
~Mode();
};
%inline %{ %inline %{
using std::string; using std::string;

View File

@ -536,14 +536,23 @@ proc parse_scenes_or_all { keys_var } {
} }
} }
proc find_scenes { scene_names } { proc find_scenes { scenes_arg } {
set scenes {} set scenes {}
foreach scene_name $scene_names { foreach scene_arg $scenes_arg {
set scene [find_scene $scene_name] if { [is_object $scene_arg] } {
if { $scene == "NULL" } { set object_type [object_type $scene_arg]
sta_error 134 "$scene_name is not the name of a scene." if { $object_type == "Scene" } {
lappend scenes $scene_arg
} else {
sta_error 135 "scene object type '$object_type' is not a scene."
}
} else { } else {
lappend scenes $scene set scene [find_scene $scene_arg]
if { $scene == "NULL" } {
sta_error 134 "$scene_arg is not the name of a scene."
} else {
lappend scenes $scene
}
} }
} }
return $scenes return $scenes

View File

@ -57,6 +57,10 @@ proc get_object_property { object prop } {
return [net_property $object $prop] return [net_property $object $prop]
} elseif { $object_type == "Clock" } { } elseif { $object_type == "Clock" } {
return [clock_property $object $prop] return [clock_property $object $prop]
} elseif { $object_type == "Scene" } {
return [scene_property $object $prop]
} elseif { $object_type == "Mode" } {
return [mode_property $object $prop]
} elseif { $object_type == "Port" } { } elseif { $object_type == "Port" } {
return [port_property $object $prop] return [port_property $object $prop]
} elseif { $object_type == "LibertyPort" } { } elseif { $object_type == "LibertyPort" } {

View File

@ -102,7 +102,12 @@ define_cmd_args "set_scene" {scene_name}
proc set_scene { args } { proc set_scene { args } {
check_argc_eq1 "set_scene" $args check_argc_eq1 "set_scene" $args
set_cmd_scene [lindex $args 0] set scene_name [lindex $args 0]
set scene [find_scene $scene_name]
if { $scene == "NULL" } {
sta_error 578 "$scene_name is not the name of a scene."
}
set_cmd_scene $scene
} }
################################################################ ################################################################
@ -118,10 +123,16 @@ proc get_scenes { args } {
} else { } else {
set scene_name [lindex $args 0] set scene_name [lindex $args 0]
} }
set mode_names {}
if { [info exists keys(-modes)] } { if { [info exists keys(-modes)] } {
set mode_names $keys(-modes) set modes {}
return [find_mode_scenes_matching $scene_name $mode_names] foreach mode_name $keys(-modes) {
set mode [find_mode $mode_name]
if { $mode == "NULL" } {
sta_error 579 "$mode_name is not the name of a mode."
}
lappend modes $mode
}
return [find_mode_scenes_matching $scene_name $modes]
} else { } else {
return [find_scenes_matching $scene_name] return [find_scenes_matching $scene_name]
} }

View File

@ -1189,106 +1189,70 @@ using namespace sta;
$1 = tclListSetConstChar($input, interp); $1 = tclListSetConstChar($input, interp);
} }
%typemap(in) Mode* {
Tcl_Size length;
const char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEqual(arg, "NULL"))
$1 = nullptr;
else {
void *obj;
if (SWIG_ConvertPtr($input, &obj, SWIGTYPE_p_Mode, false) != TCL_OK) {
tclArgError(interp, 2174, "{} is not a mode object.", arg);
return TCL_ERROR;
}
$1 = reinterpret_cast<Mode*>(obj);
}
}
%typemap(out) Mode* { %typemap(out) Mode* {
const Mode *mode = $1; Mode *mode = $1;
if (mode) if (mode) {
Tcl_SetResult(interp, const_cast<char*>($1->name().c_str()), TCL_VOLATILE); Tcl_Obj *obj = SWIG_NewInstanceObj(mode, SWIGTYPE_p_Mode, false);
Tcl_SetObjResult(interp, obj);
}
else else
Tcl_SetResult(interp, const_cast<char*>("NULL"), TCL_STATIC); Tcl_SetResult(interp, const_cast<char*>("NULL"), TCL_STATIC);
} }
%typemap(in) ModeSeq { %typemap(in) ModeSeq {
Tcl_Size argc; $1 = tclListSeq<Mode*>($input, SWIGTYPE_p_Mode, interp);
Tcl_Obj **argv;
Sta *sta = Sta::sta();
std::vector<Mode*> seq;
if (Tcl_ListObjGetElements(interp, $input, &argc, &argv) == TCL_OK
&& argc > 0) {
for (int i = 0; i < argc; i++) {
Tcl_Size length;
const char *mode_name = Tcl_GetStringFromObj(argv[i], &length);
Mode *mode = sta->findMode(mode_name);
if (mode)
seq.push_back(mode);
else {
tclArgError(interp, 2174, "mode {} not found.", mode_name);
return TCL_ERROR;
}
}
}
$1 = seq;
} }
%typemap(out) ModeSeq { %typemap(out) ModeSeq {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr); seqTclList<ModeSeq, Mode>($1, SWIGTYPE_p_Mode, interp);
ModeSeq &modes = $1;
for (Mode *mode : modes) {
const std::string &mode_name = mode->name();
Tcl_Obj *obj = Tcl_NewStringObj(mode_name.c_str(), mode_name.size());
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
} }
%typemap(in) Scene* { %typemap(in) Scene* {
sta::Sta *sta = Sta::sta();
Tcl_Size length; Tcl_Size length;
std::string scene_name = Tcl_GetStringFromObj($input, &length); const char *arg = Tcl_GetStringFromObj($input, &length);
// parse_scene_or_all support depreated 11/21/2025 if (stringEqual(arg, "NULL"))
if (scene_name == "NULL")
$1 = nullptr; $1 = nullptr;
else { else {
Scene *scene = sta->findScene(scene_name); void *obj;
if (scene) if (SWIG_ConvertPtr($input, &obj, SWIGTYPE_p_Scene, false) != TCL_OK) {
$1 = scene; tclArgError(interp, 2173, "{} is not a scene object.", arg);
else {
tclArgError(interp, 2173, "scene {} not found.", scene_name.c_str());
return TCL_ERROR; return TCL_ERROR;
} }
$1 = reinterpret_cast<Scene*>(obj);
} }
} }
%typemap(out) Scene* { %typemap(out) Scene* {
const Scene *scene = $1; Scene *scene = $1;
if (scene) if (scene) {
Tcl_SetResult(interp, const_cast<char*>($1->name().c_str()), TCL_VOLATILE); Tcl_Obj *obj = SWIG_NewInstanceObj(scene, SWIGTYPE_p_Scene, false);
Tcl_SetObjResult(interp, obj);
}
else else
Tcl_SetResult(interp, const_cast<char*>("NULL"), TCL_STATIC); Tcl_SetResult(interp, const_cast<char*>("NULL"), TCL_STATIC);
} }
%typemap(in) SceneSeq { %typemap(in) SceneSeq {
Tcl_Size argc; $1 = tclListSeq<Scene*>($input, SWIGTYPE_p_Scene, interp);
Tcl_Obj **argv;
Sta *sta = Sta::sta();
std::vector<Scene*> seq;
if (Tcl_ListObjGetElements(interp, $input, &argc, &argv) == TCL_OK
&& argc > 0) {
for (int i = 0; i < argc; i++) {
Tcl_Size length;
const char *scene_name = Tcl_GetStringFromObj(argv[i], &length);
Scene *scene = sta->findScene(scene_name);
if (scene)
seq.push_back(scene);
else {
tclArgError(interp, 2172, "scene {} not found.", scene_name);
return TCL_ERROR;
}
}
}
$1 = seq;
} }
%typemap(out) SceneSeq { %typemap(out) SceneSeq {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr); seqTclList<SceneSeq, Scene>($1, SWIGTYPE_p_Scene, interp);
SceneSeq &scenes = $1;
for (Scene *scene : scenes) {
const std::string &scene_name = scene->name();
Tcl_Obj *obj = Tcl_NewStringObj(scene_name.c_str(), scene_name.size());
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
} }
%typemap(in) PropertyValue { %typemap(in) PropertyValue {

6
test/get_scenes.ok Normal file
View File

@ -0,0 +1,6 @@
[get_scenes *]
scene1
scene2
[get_modes *]
mode1
mode2

20
test/get_scenes.tcl Normal file
View File

@ -0,0 +1,20 @@
# get_scenes / get_modes return objects
read_liberty ../examples/asap7_small_ff.lib.gz
read_liberty ../examples/asap7_small_ss.lib.gz
read_verilog ../examples/reg1_asap7.v
link_design top
read_sdc -mode mode1 ../examples/mcmm2_mode1.sdc
read_sdc -mode mode2 ../examples/mcmm2_mode2.sdc
read_spef -name reg1_ff ../examples/reg1_asap7.spef
read_spef -name reg1_ss ../examples/reg1_asap7_ss.spef
define_scene scene1 -mode mode1 -liberty asap7_small_ff -spef reg1_ff
define_scene scene2 -mode mode2 -liberty asap7_small_ss -spef reg1_ss
puts {[get_scenes *]}
report_object_names [get_scenes *]
puts {[get_modes *]}
report_object_names [get_modes *]

View File

@ -147,6 +147,7 @@ record_public_tests {
get_is_memory get_is_memory
get_lib_pins_of_objects get_lib_pins_of_objects
get_noargs get_noargs
get_scenes
get_objrefs get_objrefs
input_delay_ref_pin_rebuild input_delay_ref_pin_rebuild
liberty_arcs_one2one_1 liberty_arcs_one2one_1