From a0de2706d3886c98b16a6df5277b621d577328f4 Mon Sep 17 00:00:00 2001 From: Deepashree Sengupta Date: Fri, 10 Jul 2026 12:37:48 -0400 Subject: [PATCH] Add property-based -filter to get_scenes / get_modes, and make Scene/Mode properties extensible (#456) * support for filter in get_scene/mode Signed-off-by: dsengupta0628 * defineProperty overload Signed-off-by: dsengupta0628 * define and set user property Signed-off-by: dsengupta0628 * address review comments to generalize- current support for mode and scene Signed-off-by: dsengupta0628 * address second round comments- removed user from cmd names Signed-off-by: dsengupta0628 * remove defaults, check property vals against type defined Signed-off-by: dsengupta0628 * address reviews, indent Signed-off-by: dsengupta0628 * indent fix Signed-off-by: dsengupta0628 --------- Signed-off-by: dsengupta0628 --- include/sta/FilterObjects.hh | 11 ++ include/sta/Property.hh | 251 +++++++++++++++++++++-------------- sdc/FilterObjects.cc | 25 ++++ sdc/Sdc.i | 16 +++ search/Property.cc | 122 ++++++++++++++++- search/Property.i | 34 +++++ tcl/Property.tcl | 28 ++++ tcl/Sta.tcl | 28 +++- tcl/StaTclTypes.i | 8 ++ test/get_scenes.ok | 27 ++++ test/get_scenes.tcl | 44 ++++++ 11 files changed, 483 insertions(+), 111 deletions(-) diff --git a/include/sta/FilterObjects.hh b/include/sta/FilterObjects.hh index 71bea6c0..791c6b10 100644 --- a/include/sta/FilterObjects.hh +++ b/include/sta/FilterObjects.hh @@ -30,6 +30,7 @@ #include "GraphClass.hh" #include "NetworkClass.hh" +#include "Scene.hh" #include "SdcClass.hh" #include "SearchClass.hh" #include "StringUtil.hh" @@ -64,6 +65,16 @@ filterClocks(std::string_view filter_expression, ClockSeq *clks, Sta *sta); +SceneSeq +filterScenes(std::string_view filter_expression, + SceneSeq *scenes, + Sta *sta); + +ModeSeq +filterModes(std::string_view filter_expression, + ModeSeq *modes, + Sta *sta); + LibertyCellSeq filterLibCells(std::string_view filter_expression, LibertyCellSeq *cells, diff --git a/include/sta/Property.hh b/include/sta/Property.hh index 57260cde..84ad5cfc 100644 --- a/include/sta/Property.hh +++ b/include/sta/Property.hh @@ -28,6 +28,7 @@ #include #include #include +#include #include "LibertyClass.hh" #include "NetworkClass.hh" @@ -61,109 +62,6 @@ private: std::map> registry_; }; -class Properties -{ -public: - Properties(Sta *sta); - - PropertyValue getProperty(const Library *lib, - std::string_view property); - PropertyValue getProperty(const LibertyLibrary *lib, - std::string_view property); - PropertyValue getProperty(const Cell *cell, - std::string_view property); - PropertyValue getProperty(const LibertyCell *cell, - std::string_view property); - PropertyValue getProperty(const Port *port, - std::string_view property); - PropertyValue getProperty(const LibertyPort *port, - std::string_view property); - PropertyValue getProperty(const Instance *inst, - std::string_view property); - PropertyValue getProperty(const Pin *pin, - std::string_view property); - PropertyValue getProperty(const Net *net, - std::string_view property); - PropertyValue getProperty(Edge *edge, - 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, - std::string_view property); - PropertyValue getProperty(TimingArcSet *arc_set, - std::string_view property); - - // Define handler for external property. - // properties->defineProperty("foo", - // [] (const Instance *, Sta *) -> PropertyValue { - // return PropertyValue("bar"); - // }); - void defineProperty(std::string_view property, - const PropertyRegistry::PropertyHandler &handler); - void defineProperty(std::string_view property, - const PropertyRegistry::PropertyHandler &handler); - void defineProperty(std::string_view property, - const PropertyRegistry::PropertyHandler &handler); - void defineProperty(std::string_view property, - const PropertyRegistry::PropertyHandler &handler); - void defineProperty(std::string_view property, - const PropertyRegistry::PropertyHandler &handler); - void defineProperty(std::string_view property, - const PropertyRegistry::PropertyHandler &handler); - void defineProperty(std::string_view property, - const PropertyRegistry::PropertyHandler &handler); - void defineProperty(std::string_view property, - const PropertyRegistry::PropertyHandler &handler); - void defineProperty(std::string_view property, - const PropertyRegistry::PropertyHandler &handler); - void defineProperty(std::string_view property, - const PropertyRegistry::PropertyHandler &handler); - -protected: - PropertyValue portSlew(const Port *port, - const RiseFallBoth *rf, - const MinMax *min_max); - PropertyValue portSlack(const Port *port, - const RiseFallBoth *rf, - const MinMax *min_max); - PropertyValue pinArrival(const Pin *pin, - const RiseFallBoth *rf, - const MinMax *min_max); - - PropertyValue pinSlack(const Pin *pin, - const RiseFallBoth *rf, - const MinMax *min_max); - PropertyValue pinSlew(const Pin *pin, - const RiseFallBoth *rf, - const MinMax *min_max); - - PropertyValue delayPropertyValue(Delay delay); - PropertyValue resistancePropertyValue(float res); - PropertyValue capacitancePropertyValue(float cap); - PropertyValue edgeDelay(Edge *edge, - const RiseFall *rf, - const MinMax *min_max); - - PropertyRegistry registry_library_; - PropertyRegistry registry_liberty_library_; - PropertyRegistry registry_cell_; - PropertyRegistry registry_liberty_cell_; - PropertyRegistry registry_port_; - PropertyRegistry registry_liberty_port_; - PropertyRegistry registry_instance_; - PropertyRegistry registry_pin_; - PropertyRegistry registry_net_; - PropertyRegistry registry_clock_; - - Sta *sta_; -}; - // Adding a new property type // value union (string values use std::string* so the union stays trivial) // enum Type @@ -262,4 +160,151 @@ private: const Unit *unit_; }; +// Key for user-defined property values: the object instance and the +// property name. +class PropertyKey +{ +public: + PropertyKey(const void *object, + std::string_view property); + bool operator<(const PropertyKey &key) const; + +private: + const void *object_; + std::string property_; +}; + +class Properties +{ +public: + Properties(Sta *sta); + + PropertyValue getProperty(const Library *lib, + std::string_view property); + PropertyValue getProperty(const LibertyLibrary *lib, + std::string_view property); + PropertyValue getProperty(const Cell *cell, + std::string_view property); + PropertyValue getProperty(const LibertyCell *cell, + std::string_view property); + PropertyValue getProperty(const Port *port, + std::string_view property); + PropertyValue getProperty(const LibertyPort *port, + std::string_view property); + PropertyValue getProperty(const Instance *inst, + std::string_view property); + PropertyValue getProperty(const Pin *pin, + std::string_view property); + PropertyValue getProperty(const Net *net, + std::string_view property); + PropertyValue getProperty(Edge *edge, + 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, + std::string_view property); + PropertyValue getProperty(TimingArcSet *arc_set, + std::string_view property); + + // Define handler for external property. + // properties->defineProperty("foo", + // [] (const Instance *, Sta *) -> PropertyValue { + // return PropertyValue("bar"); + // }); + void defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler); + void defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler); + void defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler); + void defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler); + void defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler); + void defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler); + void defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler); + void defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler); + void defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler); + void defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler); + void defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler); + void defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler); + + // User-defined, per-object mutable properties. defineProperty registers + // a property of the given value type ("bool", "float" or "string"); + // setProperty sets the value on one object. Objects the property was never + // set on read back as an empty (none) value. The property is read through + // the same registry path as every other property so get_property / + // get_* -filter work unchanged. + template + void defineProperty(std::string_view object_type, + std::string_view property, + std::string_view value_type); + void setProperty(const void *object, + std::string_view object_type, + std::string_view property, + std::string_view value); + +protected: + PropertyValue portSlew(const Port *port, + const RiseFallBoth *rf, + const MinMax *min_max); + PropertyValue portSlack(const Port *port, + const RiseFallBoth *rf, + const MinMax *min_max); + PropertyValue pinArrival(const Pin *pin, + const RiseFallBoth *rf, + const MinMax *min_max); + + PropertyValue pinSlack(const Pin *pin, + const RiseFallBoth *rf, + const MinMax *min_max); + PropertyValue pinSlew(const Pin *pin, + const RiseFallBoth *rf, + const MinMax *min_max); + + PropertyValue delayPropertyValue(Delay delay); + PropertyValue resistancePropertyValue(float res); + PropertyValue capacitancePropertyValue(float cap); + PropertyValue edgeDelay(Edge *edge, + const RiseFall *rf, + const MinMax *min_max); + PropertyValue::Type propertyType(std::string_view type); + PropertyValue coercePropertyValue(PropertyValue::Type type, + std::string_view value); + + PropertyRegistry registry_library_; + PropertyRegistry registry_liberty_library_; + PropertyRegistry registry_cell_; + PropertyRegistry registry_liberty_cell_; + PropertyRegistry registry_port_; + PropertyRegistry registry_liberty_port_; + PropertyRegistry registry_instance_; + PropertyRegistry registry_pin_; + PropertyRegistry registry_net_; + PropertyRegistry registry_clock_; + PropertyRegistry registry_scene_; + PropertyRegistry registry_mode_; + + // Value types of user-defined properties keyed by object type name and + // property name. + std::map, PropertyValue::Type> prop_types_; + // User-defined property values. + std::map prop_values_; + + Sta *sta_; +}; + } // namespace sta diff --git a/sdc/FilterObjects.cc b/sdc/FilterObjects.cc index 509e48df..eeea29f4 100644 --- a/sdc/FilterObjects.cc +++ b/sdc/FilterObjects.cc @@ -42,6 +42,7 @@ #include "GraphCmp.hh" #include "Liberty.hh" #include "LibertyClass.hh" +#include "Mode.hh" #include "Network.hh" #include "NetworkClass.hh" #include "PathEnd.hh" @@ -497,6 +498,30 @@ filterClocks(std::string_view filter_expression, }, sta); } +SceneSeq +filterScenes(std::string_view filter_expression, + SceneSeq *scenes, + Sta *sta) +{ + return filterObjects(filter_expression, scenes, + [] (const Scene *scene1, + const Scene *scene2) { + return scene1->name() < scene2->name(); + }, sta); +} + +ModeSeq +filterModes(std::string_view filter_expression, + ModeSeq *modes, + Sta *sta) +{ + return filterObjects(filter_expression, modes, + [] (const Mode *mode1, + const Mode *mode2) { + return mode1->name() < mode2->name(); + }, sta); +} + LibertyCellSeq filterLibCells(std::string_view filter_expression, LibertyCellSeq *cells, diff --git a/sdc/Sdc.i b/sdc/Sdc.i index 4b3050b0..3ac13d81 100644 --- a/sdc/Sdc.i +++ b/sdc/Sdc.i @@ -1531,6 +1531,22 @@ filter_clocks(const char *filter_expression, return filterClocks(filter_expression, clocks, sta); } +SceneSeq +filter_scenes(const char *filter_expression, + SceneSeq *scenes) +{ + sta::Sta *sta = Sta::sta(); + return filterScenes(filter_expression, scenes, sta); +} + +ModeSeq +filter_modes(const char *filter_expression, + ModeSeq *modes) +{ + sta::Sta *sta = Sta::sta(); + return filterModes(filter_expression, modes, sta); +} + LibertyCellSeq filter_lib_cells(const char *filter_expression, LibertyCellSeq *cells) diff --git a/search/Property.cc b/search/Property.cc index 6ecd9ab7..ee3ddc11 100644 --- a/search/Property.cc +++ b/search/Property.cc @@ -26,6 +26,7 @@ #include #include +#include #include #include "Clock.hh" @@ -1205,7 +1206,9 @@ Properties::getProperty(const Scene *scene, || property == "full_name") return PropertyValue(scene->name()); else - throw PropertyUnknown("scene", property); + // Unknown properties throw PropertyUnknown; a user-defined property + // never set on this scene returns a none value. + return registry_scene_.getProperty(scene, property, "scene", sta_); } //////////////////////////////////////////////////////////////// @@ -1218,7 +1221,9 @@ Properties::getProperty(const Mode *mode, || property == "full_name") return PropertyValue(mode->name()); else - throw PropertyUnknown("mode", property); + // Unknown properties throw PropertyUnknown; a user-defined property + // never set on this mode returns a none value. + return registry_mode_.getProperty(mode, property, "mode", sta_); } //////////////////////////////////////////////////////////////// @@ -1360,6 +1365,119 @@ Properties::defineProperty(std::string_view property, registry_clock_.defineProperty(property, handler); } +void +Properties::defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler) +{ + registry_scene_.defineProperty(property, handler); +} + +void +Properties::defineProperty(std::string_view property, + const PropertyRegistry::PropertyHandler &handler) +{ + registry_mode_.defineProperty(property, handler); +} + +//////////////////////////////////////////////////////////////// + +// Value type from the define_property -type argument. +PropertyValue::Type +Properties::propertyType(std::string_view type) +{ + if (type == "bool" || type == "boolean") + return PropertyValue::Type::bool_; + else if (type == "float" || type == "double" || type == "number") + return PropertyValue::Type::float_; + else if (type == "string") + return PropertyValue::Type::string; + else + sta_->report()->error(2210, "unknown property type '{}' (use bool, float or string).", + type); + return PropertyValue::Type::none; +} + +PropertyValue +Properties::coercePropertyValue(PropertyValue::Type type, + std::string_view value) +{ + switch (type) { + case PropertyValue::Type::bool_: + if (stringEqual(value, "true") || value == "1") + return PropertyValue(true); + if (stringEqual(value, "false") || value == "0") + return PropertyValue(false); + sta_->report()->error(2212, "'{}' is not a bool property value.", value); + return PropertyValue(); + case PropertyValue::Type::float_: { + auto [number, valid] = stringFloat(std::string(value)); + if (!valid) + sta_->report()->error(2215, "'{}' is not a float property value.", value); + return PropertyValue(number, sta_->units()->scalarUnit()); + } + default: + return PropertyValue(std::string(value)); + } +} + +PropertyKey::PropertyKey(const void *object, + std::string_view property) : + object_(object), + property_(property) +{ +} + +bool +PropertyKey::operator<(const PropertyKey &key) const +{ + return std::tie(object_, property_) + < std::tie(key.object_, key.property_); +} + +template +void +Properties::defineProperty(std::string_view object_type, + std::string_view property, + std::string_view value_type) +{ + prop_types_[{std::string(object_type), std::string(property)}] = + propertyType(value_type); + std::string name(property); + typename PropertyRegistry::PropertyHandler handler = + [this, name] (const TYPE *object, + Sta *) -> PropertyValue { + auto value_iter = prop_values_.find(PropertyKey(object, name)); + if (value_iter != prop_values_.end()) + return value_iter->second; + // Never set on this object. + return PropertyValue(); + }; + defineProperty(property, handler); +} + +// Object types the tcl interface exposes user properties on. +template void Properties::defineProperty(std::string_view, + std::string_view, + std::string_view); +template void Properties::defineProperty(std::string_view, + std::string_view, + std::string_view); + +void +Properties::setProperty(const void *object, + std::string_view object_type, + std::string_view property, + std::string_view value) +{ + auto type_iter = prop_types_.find({std::string(object_type), + std::string(property)}); + if (type_iter == prop_types_.end()) + sta_->report()->error(2211, "{} property '{}' is not defined.", + object_type, property); + prop_values_[PropertyKey(object, property)] = + coercePropertyValue(type_iter->second, value); +} + //////////////////////////////////////////////////////////////// template diff --git a/search/Property.i b/search/Property.i index 2002f901..c282f5fb 100644 --- a/search/Property.i +++ b/search/Property.i @@ -25,6 +25,7 @@ %{ #include "Property.hh" +#include "Report.hh" #include "Sta.hh" using namespace sta; @@ -137,6 +138,39 @@ mode_property(Mode *mode, return properties.getProperty(mode, property); } +void +define_property_cmd(const char *object_type, + const char *property, + const char *type) +{ + Properties &properties = Sta::sta()->properties(); + std::string_view object_type_view(object_type); + if (object_type_view == "scene") + properties.defineProperty(object_type, property, type); + else if (object_type_view == "mode") + properties.defineProperty(object_type, property, type); + else + Sta::sta()->report()->error(2209, "define_property -object_type {} not supported.", + object_type); +} + +void +set_property_cmd(void *object, + const char *object_type, + const char *property, + const char *value) +{ + Properties &properties = Sta::sta()->properties(); + std::string_view object_type_view(object_type); + if (object_type_view == "Scene") + properties.setProperty(object, "scene", property, value); + else if (object_type_view == "Mode") + properties.setProperty(object, "mode", property, value); + else + Sta::sta()->report()->error(2214, "set_property unsupported object type {}.", + object_type); +} + PropertyValue path_end_property(PathEnd *end, const char *property) diff --git a/tcl/Property.tcl b/tcl/Property.tcl index 3f70adc6..4df5b196 100644 --- a/tcl/Property.tcl +++ b/tcl/Property.tcl @@ -120,5 +120,33 @@ proc get_property_object_type { object_type object_name quiet } { return [lindex $object 0] } +define_cmd_args "define_property" \ + {-object_type scene|mode -type bool|float|string property} + +proc define_property { args } { + parse_key_args "define_property" args keys {-object_type -type} flags {} + check_argc_eq1 "define_property" $args + if { ![info exists keys(-object_type)] } { + sta_error 2207 "define_property -object_type must be specified." + } + if { ![info exists keys(-type)] } { + sta_error 2208 "define_property -type must be specified." + } + define_property_cmd $keys(-object_type) [lindex $args 0] $keys(-type) +} + +define_cmd_args "set_property" {object property value} + +proc set_property { args } { + check_argc_eq3 "set_property" $args + set object [lindex $args 0] + set prop [lindex $args 1] + set value [lindex $args 2] + if { ![is_object $object] } { + sta_error 2213 "set_property $object is not an object." + } + set_property_cmd $object [object_type $object] $prop $value +} + # sta namespace end. } diff --git a/tcl/Sta.tcl b/tcl/Sta.tcl index 0ec12a27..cffd6673 100644 --- a/tcl/Sta.tcl +++ b/tcl/Sta.tcl @@ -112,10 +112,10 @@ proc set_scene { args } { ################################################################ -define_cmd_args "get_scenes" {[-modes mode_names] scene_names} +define_cmd_args "get_scenes" {[-modes mode_names] [-filter expr] scene_names} proc get_scenes { args } { - parse_key_args "get_scenes" args keys {-modes} flags {} + parse_key_args "get_scenes" args keys {-modes -filter} flags {} check_argc_eq0or1 "get_scenes" $args if { [llength $args] == 0 } { @@ -132,18 +132,34 @@ proc get_scenes { args } { } lappend modes $mode } - return [find_mode_scenes_matching $scene_name $modes] + set scenes [find_mode_scenes_matching $scene_name $modes] } else { - return [find_scenes_matching $scene_name] + set scenes [find_scenes_matching $scene_name] } + if { [info exists keys(-filter)] } { + set scenes [filter_scenes $keys(-filter) $scenes] + } + return $scenes } ################################################################ -define_cmd_args "get_modes" {mode_name} +define_cmd_args "get_modes" {[-filter expr] [mode_name]} proc get_modes { args } { - return [find_modes [lindex $args 0]] + parse_key_args "get_modes" args keys {-filter} flags {} + check_argc_eq0or1 "get_modes" $args + + if { [llength $args] == 0 } { + set mode_name "*" + } else { + set mode_name [lindex $args 0] + } + set modes [find_modes $mode_name] + if { [info exists keys(-filter)] } { + set modes [filter_modes $keys(-filter) $modes] + } + return $modes } ################################################################ diff --git a/tcl/StaTclTypes.i b/tcl/StaTclTypes.i index c8c62584..a89054fa 100644 --- a/tcl/StaTclTypes.i +++ b/tcl/StaTclTypes.i @@ -1218,6 +1218,10 @@ using namespace sta; $1 = tclListSeq($input, SWIGTYPE_p_Mode, interp); } +%typemap(in) ModeSeq* { + $1 = tclListSeqPtr($input, SWIGTYPE_p_Mode, interp); +} + %typemap(out) ModeSeq { seqTclList($1, SWIGTYPE_p_Mode, interp); } @@ -1251,6 +1255,10 @@ using namespace sta; $1 = tclListSeq($input, SWIGTYPE_p_Scene, interp); } +%typemap(in) SceneSeq* { + $1 = tclListSeqPtr($input, SWIGTYPE_p_Scene, interp); +} + %typemap(out) SceneSeq { seqTclList($1, SWIGTYPE_p_Scene, interp); } diff --git a/test/get_scenes.ok b/test/get_scenes.ok index ab504b68..94478689 100644 --- a/test/get_scenes.ok +++ b/test/get_scenes.ok @@ -4,3 +4,30 @@ scene2 [get_modes *] mode1 mode2 +[get_scenes -filter {name == scene1}] +scene1 +[get_scenes -filter {name =~ scene*}] +scene1 +scene2 +[get_scenes -filter {name != scene1}] +scene2 +[get_modes -filter {name == mode2}] +mode2 +[get_modes -filter {name =~ mode*}] +mode1 +mode2 +[get_property scene1 active] +1 +[get_property scene2 active] (unset) +<> +[get_scenes -filter {active == true}] +scene1 +[get_scenes -filter {active == false}] (scene2 unset) +[get_scenes -filter {active}] +scene1 +[get_scenes -filter {!active}] +scene2 +[get_property scene2 active] (set false) +0 +[get_scenes -filter {active == false}] (scene2 set false) +scene2 diff --git a/test/get_scenes.tcl b/test/get_scenes.tcl index 396c32ce..0ccb98a4 100644 --- a/test/get_scenes.tcl +++ b/test/get_scenes.tcl @@ -18,3 +18,47 @@ report_object_names [get_scenes *] puts {[get_modes *]} report_object_names [get_modes *] + +puts {[get_scenes -filter {name == scene1}]} +report_object_names [get_scenes -filter {name == scene1}] + +puts {[get_scenes -filter {name =~ scene*}]} +report_object_names [get_scenes -filter {name =~ scene*}] + +puts {[get_scenes -filter {name != scene1}]} +report_object_names [get_scenes -filter {name != scene1}] + +puts {[get_modes -filter {name == mode2}]} +report_object_names [get_modes -filter {name == mode2}] + +puts {[get_modes -filter {name =~ mode*}]} +report_object_names [get_modes -filter {name =~ mode*}] + +# User-defined bool property. scene1 set active, scene2 left unset. +define_property -object_type scene -type bool active +set_property [get_scenes scene1] active true + +puts {[get_property scene1 active]} +puts [get_property [get_scenes scene1] active] +puts {[get_property scene2 active] (unset)} +puts "<[get_property [get_scenes scene2] active]>" + +puts {[get_scenes -filter {active == true}]} +report_object_names [get_scenes -filter {active == true}] + +# Unset does not match false; only an explicitly set value does. +puts {[get_scenes -filter {active == false}] (scene2 unset)} +report_object_names [get_scenes -filter {active == false}] + +puts {[get_scenes -filter {active}]} +report_object_names [get_scenes -filter {active}] + +puts {[get_scenes -filter {!active}]} +report_object_names [get_scenes -filter {!active}] + +set_property [get_scenes scene2] active false +puts {[get_property scene2 active] (set false)} +puts [get_property [get_scenes scene2] active] + +puts {[get_scenes -filter {active == false}] (scene2 set false)} +report_object_names [get_scenes -filter {active == false}]