diff --git a/include/sta/Property.hh b/include/sta/Property.hh index 1bb1e149..57260cde 100644 --- a/include/sta/Property.hh +++ b/include/sta/Property.hh @@ -42,6 +42,8 @@ class PropertyValue; class Sta; class PropertyValue; +class Scene; +class Mode; template class PropertyRegistry @@ -86,6 +88,10 @@ public: std::string_view property); PropertyValue getProperty(const Clock *clk, 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, std::string_view property); PropertyValue getProperty(Path *path, diff --git a/sdc/Sdc.tcl b/sdc/Sdc.tcl index 5588c8f1..e444eea8 100644 --- a/sdc/Sdc.tcl +++ b/sdc/Sdc.tcl @@ -45,7 +45,7 @@ proc_redirect read_sdc { if { [info exists keys(-mode)] } { set mode_name $keys(-mode) - set prev_mode [cmd_mode] + set prev_mode [cmd_mode_name] try { set_cmd_mode $mode_name include_file $filename $echo 0 @@ -69,7 +69,7 @@ proc write_sdc { args } { flags {-map_hpins -compatible -gzip -no_timestamp} check_argc_eq1 "write_sdc" $args - set mode [cmd_mode] + set mode [cmd_mode_name] if { [info exists keys(-mode)] } { set mode $keys(-mode) } diff --git a/search/Property.cc b/search/Property.cc index fe848d5e..6ecd9ab7 100644 --- a/search/Property.cc +++ b/search/Property.cc @@ -33,6 +33,7 @@ #include "Graph.hh" #include "Liberty.hh" #include "MinMax.hh" +#include "Mode.hh" #include "Network.hh" #include "Path.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 Properties::getProperty(PathEnd *end, std::string_view property) diff --git a/search/Property.i b/search/Property.i index 01c8b4c1..2002f901 100644 --- a/search/Property.i +++ b/search/Property.i @@ -121,6 +121,22 @@ clock_property(Clock *clk, 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 path_end_property(PathEnd *end, const char *property) diff --git a/search/Search.i b/search/Search.i index 6f0376de..7adf097f 100644 --- a/search/Search.i +++ b/search/Search.i @@ -72,6 +72,20 @@ private: ~PathEnd(); }; +class Scene +{ +private: + Scene(); + ~Scene(); +}; + +class Mode +{ +private: + Mode(); + ~Mode(); +}; + %inline %{ using std::string; diff --git a/tcl/CmdArgs.tcl b/tcl/CmdArgs.tcl index fb962df6..71232ef1 100644 --- a/tcl/CmdArgs.tcl +++ b/tcl/CmdArgs.tcl @@ -536,14 +536,23 @@ proc parse_scenes_or_all { keys_var } { } } -proc find_scenes { scene_names } { +proc find_scenes { scenes_arg } { set scenes {} - foreach scene_name $scene_names { - set scene [find_scene $scene_name] - if { $scene == "NULL" } { - sta_error 134 "$scene_name is not the name of a scene." + foreach scene_arg $scenes_arg { + if { [is_object $scene_arg] } { + set object_type [object_type $scene_arg] + if { $object_type == "Scene" } { + lappend scenes $scene_arg + } else { + sta_error 135 "scene object type '$object_type' is not a scene." + } } 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 diff --git a/tcl/Property.tcl b/tcl/Property.tcl index 87e0d3c3..3f70adc6 100644 --- a/tcl/Property.tcl +++ b/tcl/Property.tcl @@ -57,6 +57,10 @@ proc get_object_property { object prop } { return [net_property $object $prop] } elseif { $object_type == "Clock" } { 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" } { return [port_property $object $prop] } elseif { $object_type == "LibertyPort" } { diff --git a/tcl/Sta.tcl b/tcl/Sta.tcl index ee560962..0ec12a27 100644 --- a/tcl/Sta.tcl +++ b/tcl/Sta.tcl @@ -102,7 +102,12 @@ define_cmd_args "set_scene" {scene_name} proc 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 { set scene_name [lindex $args 0] } - set mode_names {} if { [info exists keys(-modes)] } { - set mode_names $keys(-modes) - return [find_mode_scenes_matching $scene_name $mode_names] + set modes {} + 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 { return [find_scenes_matching $scene_name] } diff --git a/tcl/StaTclTypes.i b/tcl/StaTclTypes.i index c5eb3420..c8c62584 100644 --- a/tcl/StaTclTypes.i +++ b/tcl/StaTclTypes.i @@ -1189,106 +1189,70 @@ using namespace sta; $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(obj); + } +} + %typemap(out) Mode* { - const Mode *mode = $1; - if (mode) - Tcl_SetResult(interp, const_cast($1->name().c_str()), TCL_VOLATILE); + Mode *mode = $1; + if (mode) { + Tcl_Obj *obj = SWIG_NewInstanceObj(mode, SWIGTYPE_p_Mode, false); + Tcl_SetObjResult(interp, obj); + } else Tcl_SetResult(interp, const_cast("NULL"), TCL_STATIC); } %typemap(in) ModeSeq { - Tcl_Size argc; - Tcl_Obj **argv; - - Sta *sta = Sta::sta(); - std::vector 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; + $1 = tclListSeq($input, SWIGTYPE_p_Mode, interp); } %typemap(out) ModeSeq { - Tcl_Obj *list = Tcl_NewListObj(0, nullptr); - 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); + seqTclList($1, SWIGTYPE_p_Mode, interp); } %typemap(in) Scene* { - sta::Sta *sta = Sta::sta(); Tcl_Size length; - std::string scene_name = Tcl_GetStringFromObj($input, &length); - // parse_scene_or_all support depreated 11/21/2025 - if (scene_name == "NULL") + const char *arg = Tcl_GetStringFromObj($input, &length); + if (stringEqual(arg, "NULL")) $1 = nullptr; else { - Scene *scene = sta->findScene(scene_name); - if (scene) - $1 = scene; - else { - tclArgError(interp, 2173, "scene {} not found.", scene_name.c_str()); + void *obj; + if (SWIG_ConvertPtr($input, &obj, SWIGTYPE_p_Scene, false) != TCL_OK) { + tclArgError(interp, 2173, "{} is not a scene object.", arg); return TCL_ERROR; } + $1 = reinterpret_cast(obj); } } %typemap(out) Scene* { - const Scene *scene = $1; - if (scene) - Tcl_SetResult(interp, const_cast($1->name().c_str()), TCL_VOLATILE); + Scene *scene = $1; + if (scene) { + Tcl_Obj *obj = SWIG_NewInstanceObj(scene, SWIGTYPE_p_Scene, false); + Tcl_SetObjResult(interp, obj); + } else Tcl_SetResult(interp, const_cast("NULL"), TCL_STATIC); } %typemap(in) SceneSeq { - Tcl_Size argc; - Tcl_Obj **argv; - - Sta *sta = Sta::sta(); - std::vector 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; + $1 = tclListSeq($input, SWIGTYPE_p_Scene, interp); } %typemap(out) SceneSeq { - Tcl_Obj *list = Tcl_NewListObj(0, nullptr); - 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); + seqTclList($1, SWIGTYPE_p_Scene, interp); } %typemap(in) PropertyValue { diff --git a/test/get_scenes.ok b/test/get_scenes.ok new file mode 100644 index 00000000..ab504b68 --- /dev/null +++ b/test/get_scenes.ok @@ -0,0 +1,6 @@ +[get_scenes *] +scene1 +scene2 +[get_modes *] +mode1 +mode2 diff --git a/test/get_scenes.tcl b/test/get_scenes.tcl new file mode 100644 index 00000000..396c32ce --- /dev/null +++ b/test/get_scenes.tcl @@ -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 *] diff --git a/test/regression_vars.tcl b/test/regression_vars.tcl index d1e30064..fcb2c291 100644 --- a/test/regression_vars.tcl +++ b/test/regression_vars.tcl @@ -147,6 +147,7 @@ record_public_tests { get_is_memory get_lib_pins_of_objects get_noargs + get_scenes get_objrefs input_delay_ref_pin_rebuild liberty_arcs_one2one_1