From f476e269b94c932eb5d4f82189d075fed15b9686 Mon Sep 17 00:00:00 2001 From: Deepashree Sengupta Date: Mon, 27 Jul 2026 15:50:40 +0000 Subject: [PATCH] Extend user-defined properties to all basic object types (#479) * support for filter in get_scene/mode Signed-off-by: dsengupta0628 * extend user defined property to all 10 objects Signed-off-by: dsengupta0628 * address reviews Signed-off-by: dsengupta0628 --------- Signed-off-by: dsengupta0628 --- include/sta/Property.hh | 4 +++ search/Property.cc | 57 ++++++++++++++++++++++++++++++++++++++++ search/Property.i | 40 ++++++++++++++++++++++++++++ tcl/Property.tcl | 2 +- test/regression_vars.tcl | 1 + test/user_properties.ok | 17 ++++++++++++ test/user_properties.tcl | 44 +++++++++++++++++++++++++++++++ 7 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 test/user_properties.ok create mode 100644 test/user_properties.tcl diff --git a/include/sta/Property.hh b/include/sta/Property.hh index 84ad5cfc..780740d7 100644 --- a/include/sta/Property.hh +++ b/include/sta/Property.hh @@ -284,6 +284,10 @@ protected: PropertyValue::Type propertyType(std::string_view type); PropertyValue coercePropertyValue(PropertyValue::Type type, std::string_view value); + // True if a user-defined property of this name was declared (via + // defineProperty) on this object type. + bool isUserProperty(std::string_view object_type, + std::string_view property); PropertyRegistry registry_library_; PropertyRegistry registry_liberty_library_; diff --git a/search/Property.cc b/search/Property.cc index ee3ddc11..25008bd5 100644 --- a/search/Property.cc +++ b/search/Property.cc @@ -643,6 +643,8 @@ Properties::getProperty(const Library *lib, "library", sta_); if (value.type() != PropertyValue::Type::none) return value; + else if (isUserProperty("library", property)) + return value; else throw PropertyUnknown("library", property); } @@ -665,6 +667,8 @@ Properties::getProperty(const LibertyLibrary *lib, sta_); if (value.type() != PropertyValue::Type::none) return value; + else if (isUserProperty("liberty_library", property)) + return value; else throw PropertyUnknown("liberty library", property); } @@ -696,6 +700,8 @@ Properties::getProperty(const Cell *cell, "cell", sta_); if (value.type() != PropertyValue::Type::none) return value; + else if (isUserProperty("cell", property)) + return value; else throw PropertyUnknown("cell", property); } @@ -737,6 +743,8 @@ Properties::getProperty(const LibertyCell *cell, "liberty_cell", sta_); if (value.type() != PropertyValue::Type::none) return value; + else if (isUserProperty("liberty_cell", property)) + return value; else throw PropertyUnknown("liberty cell", property); } @@ -797,6 +805,8 @@ Properties::getProperty(const Port *port, "port", sta_); if (value.type() != PropertyValue::Type::none) return value; + else if (isUserProperty("port", property)) + return value; else throw PropertyUnknown("port", property); } @@ -898,6 +908,8 @@ Properties::getProperty(const LibertyPort *port, "liberty_port", sta_); if (value.type() != PropertyValue::Type::none) return value; + else if (isUserProperty("liberty_port", property)) + return value; else throw PropertyUnknown("liberty port", property); } @@ -938,6 +950,8 @@ Properties::getProperty(const Instance *inst, "instance", sta_); if (value.type() != PropertyValue::Type::none) return value; + else if (isUserProperty("instance", property)) + return value; else throw PropertyUnknown("instance", property); } @@ -1025,6 +1039,8 @@ Properties::getProperty(const Pin *pin, PropertyValue value = registry_pin_.getProperty(pin, property, "pin", sta_); if (value.type() != PropertyValue::Type::none) return value; + else if (isUserProperty("pin", property)) + return value; else throw PropertyUnknown("pin", property); } @@ -1086,6 +1102,8 @@ Properties::getProperty(const Net *net, PropertyValue value = registry_net_.getProperty(net, property, "net", sta_); if (value.type() != PropertyValue::Type::none) return value; + else if (isUserProperty("net", property)) + return value; else throw PropertyUnknown("net", property); } @@ -1191,6 +1209,8 @@ Properties::getProperty(const Clock *clk, "clock", sta_); if (value.type() != PropertyValue::Type::none) return value; + else if (isUserProperty("clock", property)) + return value; else throw PropertyUnknown("clock", property); } @@ -1420,6 +1440,13 @@ Properties::coercePropertyValue(PropertyValue::Type type, } } +bool +Properties::isUserProperty(std::string_view object_type, + std::string_view property) +{ + return prop_types_.contains({std::string(object_type), std::string(property)}); +} + PropertyKey::PropertyKey(const void *object, std::string_view property) : object_(object), @@ -1462,6 +1489,36 @@ template void Properties::defineProperty(std::string_view, 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); +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); +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); +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); +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); +template void Properties::defineProperty(std::string_view, + std::string_view, + std::string_view); void Properties::setProperty(const void *object, diff --git a/search/Property.i b/search/Property.i index c282f5fb..6d12eef7 100644 --- a/search/Property.i +++ b/search/Property.i @@ -149,6 +149,26 @@ define_property_cmd(const char *object_type, properties.defineProperty(object_type, property, type); else if (object_type_view == "mode") properties.defineProperty(object_type, property, type); + else if (object_type_view == "library") + properties.defineProperty(object_type, property, type); + else if (object_type_view == "liberty_library") + properties.defineProperty(object_type, property, type); + else if (object_type_view == "cell") + properties.defineProperty(object_type, property, type); + else if (object_type_view == "liberty_cell") + properties.defineProperty(object_type, property, type); + else if (object_type_view == "port") + properties.defineProperty(object_type, property, type); + else if (object_type_view == "liberty_port") + properties.defineProperty(object_type, property, type); + else if (object_type_view == "instance") + properties.defineProperty(object_type, property, type); + else if (object_type_view == "pin") + properties.defineProperty(object_type, property, type); + else if (object_type_view == "net") + properties.defineProperty(object_type, property, type); + else if (object_type_view == "clock") + properties.defineProperty(object_type, property, type); else Sta::sta()->report()->error(2209, "define_property -object_type {} not supported.", object_type); @@ -166,6 +186,26 @@ set_property_cmd(void *object, properties.setProperty(object, "scene", property, value); else if (object_type_view == "Mode") properties.setProperty(object, "mode", property, value); + else if (object_type_view == "Library") + properties.setProperty(object, "library", property, value); + else if (object_type_view == "LibertyLibrary") + properties.setProperty(object, "liberty_library", property, value); + else if (object_type_view == "Cell") + properties.setProperty(object, "cell", property, value); + else if (object_type_view == "LibertyCell") + properties.setProperty(object, "liberty_cell", property, value); + else if (object_type_view == "Port") + properties.setProperty(object, "port", property, value); + else if (object_type_view == "LibertyPort") + properties.setProperty(object, "liberty_port", property, value); + else if (object_type_view == "Instance") + properties.setProperty(object, "instance", property, value); + else if (object_type_view == "Pin") + properties.setProperty(object, "pin", property, value); + else if (object_type_view == "Net") + properties.setProperty(object, "net", property, value); + else if (object_type_view == "Clock") + properties.setProperty(object, "clock", property, value); else Sta::sta()->report()->error(2214, "set_property unsupported object type {}.", object_type); diff --git a/tcl/Property.tcl b/tcl/Property.tcl index 4df5b196..b0d30bd1 100644 --- a/tcl/Property.tcl +++ b/tcl/Property.tcl @@ -121,7 +121,7 @@ proc get_property_object_type { object_type object_name quiet } { } define_cmd_args "define_property" \ - {-object_type scene|mode -type bool|float|string property} + {-object_type scene|mode|library|liberty_library|cell|liberty_cell|port|liberty_port|instance|pin|net|clock -type bool|float|string property} proc define_property { args } { parse_key_args "define_property" args keys {-object_type -type} flags {} diff --git a/test/regression_vars.tcl b/test/regression_vars.tcl index df3640ec..4598051d 100644 --- a/test/regression_vars.tcl +++ b/test/regression_vars.tcl @@ -168,6 +168,7 @@ record_public_tests { report_json1 report_json2 suppress_msg + user_properties verilog_attribute verilog_well_supplies verilog_specify diff --git a/test/user_properties.ok b/test/user_properties.ok new file mode 100644 index 00000000..b7645df2 --- /dev/null +++ b/test/user_properties.ok @@ -0,0 +1,17 @@ +[get_property u1/Z owner] +alice +[get_property u2/ZN owner] (unset) +<> +[get_property r1q weight] +3.500000 +[get_property u1z weight] (unset) +<> +[get_property u2 crit] +1 +[get_property u1 crit] (unset) +<> +[get_property clk1 grp] +main +[get_pins -filter {owner == alice} *] +Z +Error: pin objects do not have a no_such_prop property. diff --git a/test/user_properties.tcl b/test/user_properties.tcl new file mode 100644 index 00000000..fb917c09 --- /dev/null +++ b/test/user_properties.tcl @@ -0,0 +1,44 @@ +# User-defined properties on pin/net/instance/clock object types. +read_liberty ../examples/nangate45_typ.lib.gz +read_verilog ../examples/example1.v +link_design top +create_clock -name clk1 -period 10 {clk1} + +# pin: string property, set on one pin, left unset on another. +define_property -object_type pin -type string owner +set_property [get_pins u1/Z] owner alice +puts {[get_property u1/Z owner]} +puts [get_property [get_pins u1/Z] owner] +puts {[get_property u2/ZN owner] (unset)} +puts "<[get_property [get_pins u2/ZN] owner]>" + +# net: float property. +define_property -object_type net -type float weight +set_property [get_nets r1q] weight 3.5 +puts {[get_property r1q weight]} +puts [get_property [get_nets r1q] weight] +puts {[get_property u1z weight] (unset)} +puts "<[get_property [get_nets u1z] weight]>" + +# instance: bool property. +define_property -object_type instance -type bool crit +set_property [get_cells u2] crit true +puts {[get_property u2 crit]} +puts [get_property [get_cells u2] crit] +puts {[get_property u1 crit] (unset)} +puts "<[get_property [get_cells u1] crit]>" + +# clock: string property. +define_property -object_type clock -type string grp +set_property [get_clocks clk1] grp main +puts {[get_property clk1 grp]} +puts [get_property [get_clocks clk1] grp] + +# -filter skips objects the property was never set on (no error). +puts {[get_pins -filter {owner == alice} *]} +report_object_names [get_pins -filter {owner == alice} *] + +# An undefined property still errors. +if {[catch {get_property [get_pins u1/Z] no_such_prop} msg]} { + puts $msg +}