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 <dsengupta@precisioninno.com> * defineProperty overload Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> * define and set user property Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> * address review comments to generalize- current support for mode and scene Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> * address second round comments- removed user from cmd names Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> * remove defaults, check property vals against type defined Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> * address reviews, indent Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> * indent fix Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com> --------- Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
This commit is contained in:
parent
ceb7e6389d
commit
a0de2706d3
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "GraphClass.hh"
|
#include "GraphClass.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
|
#include "Scene.hh"
|
||||||
#include "SdcClass.hh"
|
#include "SdcClass.hh"
|
||||||
#include "SearchClass.hh"
|
#include "SearchClass.hh"
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
|
|
@ -64,6 +65,16 @@ filterClocks(std::string_view filter_expression,
|
||||||
ClockSeq *clks,
|
ClockSeq *clks,
|
||||||
Sta *sta);
|
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
|
LibertyCellSeq
|
||||||
filterLibCells(std::string_view filter_expression,
|
filterLibCells(std::string_view filter_expression,
|
||||||
LibertyCellSeq *cells,
|
LibertyCellSeq *cells,
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "LibertyClass.hh"
|
#include "LibertyClass.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
|
|
@ -61,109 +62,6 @@ private:
|
||||||
std::map<std::string, PropertyHandler, std::less<>> registry_;
|
std::map<std::string, PropertyHandler, std::less<>> 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<const Library *>::PropertyHandler &handler);
|
|
||||||
void defineProperty(std::string_view property,
|
|
||||||
const PropertyRegistry<const LibertyLibrary *>::PropertyHandler &handler);
|
|
||||||
void defineProperty(std::string_view property,
|
|
||||||
const PropertyRegistry<const Cell *>::PropertyHandler &handler);
|
|
||||||
void defineProperty(std::string_view property,
|
|
||||||
const PropertyRegistry<const LibertyCell *>::PropertyHandler &handler);
|
|
||||||
void defineProperty(std::string_view property,
|
|
||||||
const PropertyRegistry<const Port *>::PropertyHandler &handler);
|
|
||||||
void defineProperty(std::string_view property,
|
|
||||||
const PropertyRegistry<const LibertyPort *>::PropertyHandler &handler);
|
|
||||||
void defineProperty(std::string_view property,
|
|
||||||
const PropertyRegistry<const Instance *>::PropertyHandler &handler);
|
|
||||||
void defineProperty(std::string_view property,
|
|
||||||
const PropertyRegistry<const Pin *>::PropertyHandler &handler);
|
|
||||||
void defineProperty(std::string_view property,
|
|
||||||
const PropertyRegistry<const Net *>::PropertyHandler &handler);
|
|
||||||
void defineProperty(std::string_view property,
|
|
||||||
const PropertyRegistry<const Clock *>::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<const Library*> registry_library_;
|
|
||||||
PropertyRegistry<const LibertyLibrary*> registry_liberty_library_;
|
|
||||||
PropertyRegistry<const Cell*> registry_cell_;
|
|
||||||
PropertyRegistry<const LibertyCell*> registry_liberty_cell_;
|
|
||||||
PropertyRegistry<const Port*> registry_port_;
|
|
||||||
PropertyRegistry<const LibertyPort*> registry_liberty_port_;
|
|
||||||
PropertyRegistry<const Instance*> registry_instance_;
|
|
||||||
PropertyRegistry<const Pin*> registry_pin_;
|
|
||||||
PropertyRegistry<const Net*> registry_net_;
|
|
||||||
PropertyRegistry<const Clock*> registry_clock_;
|
|
||||||
|
|
||||||
Sta *sta_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Adding a new property type
|
// Adding a new property type
|
||||||
// value union (string values use std::string* so the union stays trivial)
|
// value union (string values use std::string* so the union stays trivial)
|
||||||
// enum Type
|
// enum Type
|
||||||
|
|
@ -262,4 +160,151 @@ private:
|
||||||
const Unit *unit_;
|
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<const Library *>::PropertyHandler &handler);
|
||||||
|
void defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const LibertyLibrary *>::PropertyHandler &handler);
|
||||||
|
void defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const Cell *>::PropertyHandler &handler);
|
||||||
|
void defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const LibertyCell *>::PropertyHandler &handler);
|
||||||
|
void defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const Port *>::PropertyHandler &handler);
|
||||||
|
void defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const LibertyPort *>::PropertyHandler &handler);
|
||||||
|
void defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const Instance *>::PropertyHandler &handler);
|
||||||
|
void defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const Pin *>::PropertyHandler &handler);
|
||||||
|
void defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const Net *>::PropertyHandler &handler);
|
||||||
|
void defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const Clock *>::PropertyHandler &handler);
|
||||||
|
void defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const Scene *>::PropertyHandler &handler);
|
||||||
|
void defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const Mode *>::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<class TYPE>
|
||||||
|
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<const Library*> registry_library_;
|
||||||
|
PropertyRegistry<const LibertyLibrary*> registry_liberty_library_;
|
||||||
|
PropertyRegistry<const Cell*> registry_cell_;
|
||||||
|
PropertyRegistry<const LibertyCell*> registry_liberty_cell_;
|
||||||
|
PropertyRegistry<const Port*> registry_port_;
|
||||||
|
PropertyRegistry<const LibertyPort*> registry_liberty_port_;
|
||||||
|
PropertyRegistry<const Instance*> registry_instance_;
|
||||||
|
PropertyRegistry<const Pin*> registry_pin_;
|
||||||
|
PropertyRegistry<const Net*> registry_net_;
|
||||||
|
PropertyRegistry<const Clock*> registry_clock_;
|
||||||
|
PropertyRegistry<const Scene*> registry_scene_;
|
||||||
|
PropertyRegistry<const Mode*> registry_mode_;
|
||||||
|
|
||||||
|
// Value types of user-defined properties keyed by object type name and
|
||||||
|
// property name.
|
||||||
|
std::map<std::pair<std::string, std::string>, PropertyValue::Type> prop_types_;
|
||||||
|
// User-defined property values.
|
||||||
|
std::map<PropertyKey, PropertyValue> prop_values_;
|
||||||
|
|
||||||
|
Sta *sta_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace sta
|
} // namespace sta
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
#include "GraphCmp.hh"
|
#include "GraphCmp.hh"
|
||||||
#include "Liberty.hh"
|
#include "Liberty.hh"
|
||||||
#include "LibertyClass.hh"
|
#include "LibertyClass.hh"
|
||||||
|
#include "Mode.hh"
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
#include "PathEnd.hh"
|
#include "PathEnd.hh"
|
||||||
|
|
@ -497,6 +498,30 @@ filterClocks(std::string_view filter_expression,
|
||||||
}, sta);
|
}, sta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SceneSeq
|
||||||
|
filterScenes(std::string_view filter_expression,
|
||||||
|
SceneSeq *scenes,
|
||||||
|
Sta *sta)
|
||||||
|
{
|
||||||
|
return filterObjects<Scene>(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<Mode>(filter_expression, modes,
|
||||||
|
[] (const Mode *mode1,
|
||||||
|
const Mode *mode2) {
|
||||||
|
return mode1->name() < mode2->name();
|
||||||
|
}, sta);
|
||||||
|
}
|
||||||
|
|
||||||
LibertyCellSeq
|
LibertyCellSeq
|
||||||
filterLibCells(std::string_view filter_expression,
|
filterLibCells(std::string_view filter_expression,
|
||||||
LibertyCellSeq *cells,
|
LibertyCellSeq *cells,
|
||||||
|
|
|
||||||
16
sdc/Sdc.i
16
sdc/Sdc.i
|
|
@ -1531,6 +1531,22 @@ filter_clocks(const char *filter_expression,
|
||||||
return filterClocks(filter_expression, clocks, sta);
|
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
|
LibertyCellSeq
|
||||||
filter_lib_cells(const char *filter_expression,
|
filter_lib_cells(const char *filter_expression,
|
||||||
LibertyCellSeq *cells)
|
LibertyCellSeq *cells)
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "Clock.hh"
|
#include "Clock.hh"
|
||||||
|
|
@ -1205,7 +1206,9 @@ Properties::getProperty(const Scene *scene,
|
||||||
|| property == "full_name")
|
|| property == "full_name")
|
||||||
return PropertyValue(scene->name());
|
return PropertyValue(scene->name());
|
||||||
else
|
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")
|
|| property == "full_name")
|
||||||
return PropertyValue(mode->name());
|
return PropertyValue(mode->name());
|
||||||
else
|
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);
|
registry_clock_.defineProperty(property, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Properties::defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const Scene *>::PropertyHandler &handler)
|
||||||
|
{
|
||||||
|
registry_scene_.defineProperty(property, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Properties::defineProperty(std::string_view property,
|
||||||
|
const PropertyRegistry<const Mode *>::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<class TYPE>
|
||||||
|
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<const TYPE *>::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<Scene>(std::string_view,
|
||||||
|
std::string_view,
|
||||||
|
std::string_view);
|
||||||
|
template void Properties::defineProperty<Mode>(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<class TYPE>
|
template<class TYPE>
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
%{
|
%{
|
||||||
|
|
||||||
#include "Property.hh"
|
#include "Property.hh"
|
||||||
|
#include "Report.hh"
|
||||||
#include "Sta.hh"
|
#include "Sta.hh"
|
||||||
|
|
||||||
using namespace sta;
|
using namespace sta;
|
||||||
|
|
@ -137,6 +138,39 @@ mode_property(Mode *mode,
|
||||||
return properties.getProperty(mode, property);
|
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<Scene>(object_type, property, type);
|
||||||
|
else if (object_type_view == "mode")
|
||||||
|
properties.defineProperty<Mode>(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
|
PropertyValue
|
||||||
path_end_property(PathEnd *end,
|
path_end_property(PathEnd *end,
|
||||||
const char *property)
|
const char *property)
|
||||||
|
|
|
||||||
|
|
@ -120,5 +120,33 @@ proc get_property_object_type { object_type object_name quiet } {
|
||||||
return [lindex $object 0]
|
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.
|
# sta namespace end.
|
||||||
}
|
}
|
||||||
|
|
|
||||||
28
tcl/Sta.tcl
28
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 } {
|
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
|
check_argc_eq0or1 "get_scenes" $args
|
||||||
|
|
||||||
if { [llength $args] == 0 } {
|
if { [llength $args] == 0 } {
|
||||||
|
|
@ -132,18 +132,34 @@ proc get_scenes { args } {
|
||||||
}
|
}
|
||||||
lappend modes $mode
|
lappend modes $mode
|
||||||
}
|
}
|
||||||
return [find_mode_scenes_matching $scene_name $modes]
|
set scenes [find_mode_scenes_matching $scene_name $modes]
|
||||||
} else {
|
} 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 } {
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
|
|
|
||||||
|
|
@ -1218,6 +1218,10 @@ using namespace sta;
|
||||||
$1 = tclListSeq<Mode*>($input, SWIGTYPE_p_Mode, interp);
|
$1 = tclListSeq<Mode*>($input, SWIGTYPE_p_Mode, interp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%typemap(in) ModeSeq* {
|
||||||
|
$1 = tclListSeqPtr<Mode*>($input, SWIGTYPE_p_Mode, interp);
|
||||||
|
}
|
||||||
|
|
||||||
%typemap(out) ModeSeq {
|
%typemap(out) ModeSeq {
|
||||||
seqTclList<ModeSeq, Mode>($1, SWIGTYPE_p_Mode, interp);
|
seqTclList<ModeSeq, Mode>($1, SWIGTYPE_p_Mode, interp);
|
||||||
}
|
}
|
||||||
|
|
@ -1251,6 +1255,10 @@ using namespace sta;
|
||||||
$1 = tclListSeq<Scene*>($input, SWIGTYPE_p_Scene, interp);
|
$1 = tclListSeq<Scene*>($input, SWIGTYPE_p_Scene, interp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%typemap(in) SceneSeq* {
|
||||||
|
$1 = tclListSeqPtr<Scene*>($input, SWIGTYPE_p_Scene, interp);
|
||||||
|
}
|
||||||
|
|
||||||
%typemap(out) SceneSeq {
|
%typemap(out) SceneSeq {
|
||||||
seqTclList<SceneSeq, Scene>($1, SWIGTYPE_p_Scene, interp);
|
seqTclList<SceneSeq, Scene>($1, SWIGTYPE_p_Scene, interp);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,30 @@ scene2
|
||||||
[get_modes *]
|
[get_modes *]
|
||||||
mode1
|
mode1
|
||||||
mode2
|
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
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,47 @@ report_object_names [get_scenes *]
|
||||||
|
|
||||||
puts {[get_modes *]}
|
puts {[get_modes *]}
|
||||||
report_object_names [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}]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue