diff --git a/configure.ac b/configure.ac index 209edad2..d42cb79f 100644 --- a/configure.ac +++ b/configure.ac @@ -16,7 +16,7 @@ # Process this file with autoconf to produce a configure script. -AC_INIT(sta, 2.0.1) +AC_INIT(sta, 2.0.2) AM_INIT_AUTOMAKE AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS(config.h) diff --git a/doc/BugLog b/doc/BugLog index fcf7f594..37d62f82 100644 --- a/doc/BugLog +++ b/doc/BugLog @@ -4,3 +4,5 @@ Release 2.0 Patches 2018/10/23 read_verilog mod inst with no ports seg fault 2018/11/08 corners > 2 causes internal error 2018/11/09 Verilog ignore attributes (* blah *) +2018/12/24 all_fanout from input port +2018/12/25 liberty pg_types \ No newline at end of file diff --git a/liberty/Liberty.hh b/liberty/Liberty.hh index d64d871e..d705aa62 100644 --- a/liberty/Liberty.hh +++ b/liberty/Liberty.hh @@ -1015,7 +1015,12 @@ private: class LibertyPgPort { public: - enum PgType { unknown, power, ground }; + enum PgType { unknown, + primary_power, primary_ground, + backup_power, backup_ground, + internal_power, internal_ground, + nwell, pwell, + deepnwell, deeppwell}; LibertyPgPort(const char *name); ~LibertyPgPort(); const char *name() { return name_; } diff --git a/liberty/LibertyClass.hh b/liberty/LibertyClass.hh index babfebe1..9f56f621 100644 --- a/liberty/LibertyClass.hh +++ b/liberty/LibertyClass.hh @@ -133,6 +133,7 @@ typedef enum { table_axis_output_voltage, table_axis_path_depth, table_axis_path_distance, + table_axis_normalized_voltage, table_axis_unknown } TableAxisVariable; diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 9f98e8d4..ab92fb6c 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -289,6 +289,7 @@ LibertyReader::defineVisitors() &LibertyReader::endScaledCell); defineAttrVisitor("clock_gating_integrated_cell", &LibertyReader::visitClockGatingIntegratedCell); + defineAttrVisitor("area", &LibertyReader::visitArea); defineAttrVisitor("dont_use", &LibertyReader::visitDontUse); defineAttrVisitor("is_macro", &LibertyReader::visitIsMacro); @@ -4747,9 +4748,30 @@ LibertyReader::visitPgType(LibertyAttr *attr) const char *type_name = getAttrString(attr); LibertyPgPort::PgType type = LibertyPgPort::PgType::unknown; if (stringEqual(type_name, "primary_ground")) - type = LibertyPgPort::PgType::ground; - else if (stringEqual(type_name, "primary_power")) - type = LibertyPgPort::PgType::power; + type = LibertyPgPort::PgType::primary_ground; + else if (stringEqual(type_name, "primary_power")) + type = LibertyPgPort::PgType::primary_power; + + else if (stringEqual(type_name, "backup_ground")) + type = LibertyPgPort::PgType::backup_ground; + else if (stringEqual(type_name, "backup_power")) + type = LibertyPgPort::PgType::backup_power; + + else if (stringEqual(type_name, "internal_ground")) + type = LibertyPgPort::PgType::internal_ground; + else if (stringEqual(type_name, "internal_power")) + type = LibertyPgPort::PgType::internal_power; + + else if (stringEqual(type_name, "nwell")) + type = LibertyPgPort::PgType::nwell; + else if (stringEqual(type_name, "pwell")) + type = LibertyPgPort::PgType::pwell; + + else if (stringEqual(type_name, "deepnwell")) + type = LibertyPgPort::PgType::deepnwell; + else if (stringEqual(type_name, "deeppwell")) + type = LibertyPgPort::PgType::deeppwell; + else libError(attr, "unknown pg_type.\n"); pg_port_->setPgType(type); diff --git a/liberty/TableModel.cc b/liberty/TableModel.cc index 1b68b038..49371c01 100644 --- a/liberty/TableModel.cc +++ b/liberty/TableModel.cc @@ -1311,6 +1311,8 @@ stringTableAxisVariable(const char *variable) return table_axis_path_depth; else if (stringEq(variable, "path_distance")) return table_axis_path_distance; + else if (stringEq(variable, "normalzied_voltage")) + return table_axis_normalized_voltage; else return table_axis_unknown; } @@ -1376,6 +1378,7 @@ tableVariableUnit(TableAxisVariable variable, case table_axis_path_distance: return units->distanceUnit(); case table_axis_path_depth: + case table_axis_normalized_voltage: case table_axis_unknown: return units->scalarUnit(); } diff --git a/search/Makefile.am b/search/Makefile.am index 3d3c9309..2ccddb94 100644 --- a/search/Makefile.am +++ b/search/Makefile.am @@ -43,6 +43,7 @@ include_HEADERS = \ PathVertex.hh \ PathVertexRep.hh \ Power.hh \ + Property.hh \ ReportPath.hh \ Search.hh \ SearchClass.hh \ @@ -84,14 +85,15 @@ libsearch_la_SOURCES = \ PathVertex.cc \ PathVertexRep.cc \ Power.cc \ + Property.cc \ ReportPath.cc \ Search.cc \ SearchPred.cc \ Sim.cc \ - Tag.cc \ - TagGroup.cc \ Sta.cc \ StaState.cc \ + Tag.cc \ + TagGroup.cc \ VertexVisitor.cc \ VisitPathEnds.cc \ VisitPathGroupVertices.cc \ diff --git a/search/PathRef.cc b/search/PathRef.cc index 4ba316df..3e6503d5 100644 --- a/search/PathRef.cc +++ b/search/PathRef.cc @@ -42,6 +42,12 @@ PathRef::PathRef(const PathRef &path) : { } +PathRef::PathRef(const PathRef *path) : + path_vertex_(path->path_vertex_), + path_enumed_(path->path_enumed_) +{ +} + PathRef::PathRef(const PathVertex &path) : path_vertex_(&path), path_enumed_(NULL) diff --git a/search/PathRef.hh b/search/PathRef.hh index 2eef4933..db4b4e58 100644 --- a/search/PathRef.hh +++ b/search/PathRef.hh @@ -36,6 +36,7 @@ public: PathRef(); PathRef(const Path *path); PathRef(const PathRef &path); + PathRef(const PathRef *path); PathRef(const PathVertex &path); void init(); void init(const PathRef &path); diff --git a/search/Property.cc b/search/Property.cc new file mode 100644 index 00000000..406e745d --- /dev/null +++ b/search/Property.cc @@ -0,0 +1,572 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2018, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "Machine.hh" +#include "StringUtil.hh" +#include "MinMax.hh" +#include "Transition.hh" +#include "PortDirection.hh" +#include "Units.hh" +#include "TimingArc.hh" +#include "Liberty.hh" +#include "Network.hh" +#include "Graph.hh" +#include "Clock.hh" +#include "Corner.hh" +#include "PathEnd.hh" +#include "PathExpanded.hh" +#include "PathRef.hh" +#include "Property.hh" +#include "Sta.hh" + +namespace sta { + +static PropertyValue +pinSlewProperty(const Pin *pin, + const TransRiseFall *tr, + const MinMax *min_max, + Sta *sta); +static PropertyValue +pinSlackProperty(const Pin *pin, + const TransRiseFall *tr, + const MinMax *min_max, + Sta *sta); +static PropertyValue +portSlewProperty(const Port *port, + const TransRiseFall *tr, + const MinMax *min_max, + Sta *sta); +static PropertyValue +portSlackProperty(const Port *port, + const TransRiseFall *tr, + const MinMax *min_max, + Sta *sta); +static PropertyValue +edgeDelayProperty(Edge *edge, + const TransRiseFall *tr, + const MinMax *min_max, + Sta *sta); +static float +delayPropertyValue(Delay delay, + Sta *sta); + +//////////////////////////////////////////////////////////////// + +PropertyValue::PropertyValue() : + type_(type_none) +{ + init(); +} + +PropertyValue::PropertyValue(const char *value) : + type_(type_string) +{ + init(); + string_ = stringCopy(value); +} + +PropertyValue::PropertyValue(float value) : + type_(type_float) +{ + init(); + float_ = value; +} + +PropertyValue::PropertyValue(Instance *value) : + type_(type_instance) +{ + init(); + inst_ = value; +} + +PropertyValue::PropertyValue(Pin *value) : + type_(type_pin) +{ + init(); + pin_ = value; +} + +PropertyValue::PropertyValue(PinSeq *value) : + type_(type_pins) +{ + init(); + pins_ = value; +} + +PropertyValue::PropertyValue(PinSet *value) : + type_(type_pins) +{ + init(); + pins_ = new PinSeq; + PinSet::Iterator pin_iter(value); + while (pin_iter.hasNext()) { + Pin *pin = pin_iter.next(); + pins_->push_back( pin); + } +} + +PropertyValue::PropertyValue(Net *value) : + type_(type_net) +{ + init(); + net_ = value; +} + +PropertyValue::PropertyValue(Clock *value) : + type_(type_clock) +{ + init(); + clk_ = value; +} + +PropertyValue::PropertyValue(ClockSeq *value) : + type_(type_clocks) +{ + init(); + clks_ = new ClockSeq(*value); +} + +PropertyValue::PropertyValue(ClockSet *value) : + type_(type_clocks) +{ + init(); + clks_ = new ClockSeq; + ClockSet::Iterator clk_iter(value); + while (clk_iter.hasNext()) { + Clock *clk = clk_iter.next(); + clks_->push_back(clk); + } +} + +PropertyValue::PropertyValue(PathRefSeq *value) : + type_(type_path_refs) +{ + init(); + path_refs_ = new PathRefSeq(*value); +} + +PropertyValue::PropertyValue(const PropertyValue &value) : + type_(value.type_), + string_(stringCopy(value.string_)), + float_(value.float_), + inst_(value.inst_), + pin_(value.pin_), + pins_(value.pins_ ? new PinSeq(*value.pins_) : NULL), + net_(value.net_), + clk_(value.clk_), + clks_(value.clks_ ? new ClockSeq(*value.clks_) : NULL), + path_refs_(value.path_refs_ ? new PathRefSeq(*value.path_refs_) : NULL) +{ +} + +void +PropertyValue::init() +{ + string_ = NULL; + float_ = 0.0; + inst_ = NULL; + pin_ = NULL; + pins_ = NULL; + net_ = NULL; + clk_ = NULL; + clks_ = NULL; + path_refs_ = NULL; +} + +PropertyValue::~PropertyValue() +{ + stringDelete(string_); + delete clks_; + delete pins_; + delete path_refs_; +} + +void +PropertyValue::operator=(const PropertyValue &value) +{ + type_ = value.type_; + string_ = stringCopy(value.string_); + float_ = value.float_; + inst_ = value.inst_; + pin_ = value.pin_; + pins_ = value.pins_ ? new PinSeq(*value.pins_) : NULL; + net_ = value.net_; + clk_ = value.clk_; + clks_ = value.clks_ ? new ClockSeq(*value.clks_) : NULL; + path_refs_ = value.path_refs_ ? new PathRefSeq(*value.path_refs_) : NULL; +} + +PropertyValue +getProperty(const Instance *inst, + const char *property, + Sta *sta) +{ + Network *network = sta->network(); + if (stringEqual(property, "ref_name")) + return PropertyValue(network->name(network->cell(inst))); + else if (stringEqual(property, "full_name")) + return PropertyValue(network->pathName(inst)); + else + return PropertyValue(); +} + +//////////////////////////////////////////////////////////////// + +PropertyValue +getProperty(const Pin *pin, + const char *property, + Sta *sta) +{ + Network *network = sta->network(); + if (stringEqual(property, "direction")) + return PropertyValue(network->direction(pin)->name()); + else if (stringEqual(property, "full_name")) + return PropertyValue(network->pathName(pin)); + else if (stringEqual(property, "lib_pin_name")) + return PropertyValue(network->portName(pin)); + else if (stringEqual(property, "clocks")) { + ClockSet clks; + sta->clocks(pin, clks); + return PropertyValue(&clks); + } + + else if (stringEqual(property, "max_fall_slack")) + return pinSlackProperty(pin, TransRiseFall::fall(), MinMax::max(), sta); + else if (stringEqual(property, "max_rise_slack")) + return pinSlackProperty(pin, TransRiseFall::rise(), MinMax::max(), sta); + else if (stringEqual(property, "min_fall_slack")) + return pinSlackProperty(pin, TransRiseFall::fall(), MinMax::min(), sta); + else if (stringEqual(property, "min_rise_slack")) + return pinSlackProperty(pin, TransRiseFall::rise(), MinMax::min(), sta); + + else if (stringEqual(property, "actual_fall_transition_max")) + return pinSlewProperty(pin, TransRiseFall::fall(), MinMax::max(), sta); + else if (stringEqual(property, "actual_rise_transition_max")) + return pinSlewProperty(pin, TransRiseFall::rise(), MinMax::max(), sta); + else if (stringEqual(property, "actual_rise_transition_min")) + return pinSlewProperty(pin, TransRiseFall::rise(), MinMax::min(), sta); + else if (stringEqual(property, "actual_fall_transition_min")) + return pinSlewProperty(pin, TransRiseFall::fall(), MinMax::min(), sta); + + else + return PropertyValue(); +} + +static PropertyValue +pinSlackProperty(const Pin *pin, + const TransRiseFall *tr, + const MinMax *min_max, + Sta *sta) +{ + Slack slack = sta->pinSlack(pin, tr, min_max); + return PropertyValue(delayPropertyValue(slack, sta)); +} + +static PropertyValue +pinSlewProperty(const Pin *pin, + const TransRiseFall *tr, + const MinMax *min_max, + Sta *sta) +{ + auto graph = sta->graph(); + Vertex *vertex, *bidirect_drvr_vertex; + graph->pinVertices(pin, vertex, bidirect_drvr_vertex); + Slew slew = min_max->initValue(); + if (vertex) { + Slew vertex_slew = sta->vertexSlew(vertex, tr, min_max); + if (delayFuzzyGreater(vertex_slew, slew, min_max)) + slew = vertex_slew; + } + if (bidirect_drvr_vertex) { + Slew vertex_slew = sta->vertexSlew(bidirect_drvr_vertex, tr, min_max); + if (delayFuzzyGreater(vertex_slew, slew, min_max)) + slew = vertex_slew; + } + return PropertyValue(delayPropertyValue(slew, sta)); +} + +//////////////////////////////////////////////////////////////// + +PropertyValue +getProperty(const Net *net, + const char *property, + Sta *sta) +{ + Network *network = sta->network(); + if (stringEqual(property, "full_name")) + return PropertyValue(network->pathName(net)); + else + return PropertyValue(); +} + +//////////////////////////////////////////////////////////////// + +PropertyValue +getProperty(const Port *port, + const char *property, + Sta *sta) +{ + Network *network = sta->network(); + if (stringEqual(property, "direction")) + return PropertyValue(network->direction(port)->name()); + else if (stringEqual(property, "full_name")) + return PropertyValue(network->name(port)); + + else if (stringEqual(property, "actual_fall_transition_min")) + return portSlewProperty(port, TransRiseFall::fall(), MinMax::min(), sta); + else if (stringEqual(property, "actual_fall_transition_max")) + return portSlewProperty(port, TransRiseFall::fall(), MinMax::max(), sta); + else if (stringEqual(property, "actual_rise_transition_min")) + return portSlewProperty(port, TransRiseFall::rise(), MinMax::min(), sta); + else if (stringEqual(property, "actual_rise_transition_max")) + return portSlewProperty(port, TransRiseFall::rise(), MinMax::max(), sta); + + else if (stringEqual(property, "min_fall_slack")) + return portSlackProperty(port, TransRiseFall::fall(), MinMax::min(), sta); + else if (stringEqual(property, "max_fall_slack")) + return portSlackProperty(port, TransRiseFall::fall(), MinMax::max(), sta); + else if (stringEqual(property, "min_rise_slack")) + return portSlackProperty(port, TransRiseFall::rise(), MinMax::min(), sta); + else if (stringEqual(property, "max_rise_slack")) + return portSlackProperty(port, TransRiseFall::rise(), MinMax::max(), sta); + + else + return PropertyValue(); +} + +static PropertyValue +portSlewProperty(const Port *port, + const TransRiseFall *tr, + const MinMax *min_max, + Sta *sta) +{ + Network *network = sta->network(); + Instance *top_inst = network->topInstance(); + Pin *pin = network->findPin(top_inst, port); + return pinSlewProperty(pin, tr, min_max, sta); +} + +static PropertyValue +portSlackProperty(const Port *port, + const TransRiseFall *tr, + const MinMax *min_max, + Sta *sta) +{ + Network *network = sta->network(); + Instance *top_inst = network->topInstance(); + Pin *pin = network->findPin(top_inst, port); + return pinSlackProperty(pin, tr, min_max, sta); +} + +//////////////////////////////////////////////////////////////// + +PropertyValue +getProperty(const LibertyCell *cell, + const char *property, + Sta *sta) +{ + if (stringEqual(property, "base_name")) + return PropertyValue(cell->name()); + else if (stringEqual(property, "full_name")) { + Network *network = sta->network(); + const LibertyLibrary *lib = cell->libertyLibrary(); + const char *lib_name = lib->name(); + const char *cell_name = cell->name(); + char *full_name = stringPrintTmp(strlen(lib_name) + strlen(cell_name) + 2, + "%s%c%s", + lib_name, + network->pathDivider(), + cell_name); + return PropertyValue(full_name); + } + else + return PropertyValue(); +} + +//////////////////////////////////////////////////////////////// + +PropertyValue +getProperty(const LibertyPort *port, + const char *property, + Sta *) +{ + if (stringEqual(property, "direction")) + return PropertyValue(port->direction()->name()); + else if (stringEqual(property, "full_name")) + return PropertyValue(port->name()); + else + return PropertyValue(); +} + +PropertyValue +getProperty(const Library *lib, + const char *property, + Sta *sta) +{ + Network *network = sta->network(); + if (stringEqual(property, "name")) + return PropertyValue(network->name(lib)); + else + return PropertyValue(); +} + +PropertyValue +getProperty(const LibertyLibrary *lib, + const char *property, + Sta *) +{ + if (stringEqual(property, "name")) + return PropertyValue(lib->name()); + else if (stringEqual(property, "filename")) + return PropertyValue(lib->filename()); + else + return PropertyValue(); +} + +//////////////////////////////////////////////////////////////// + +PropertyValue +getProperty(Edge *edge, + const char *property, + Sta *sta) +{ + if (stringEqual(property, "delay_min_fall")) + return edgeDelayProperty(edge, TransRiseFall::fall(), MinMax::min(), sta); + else if (stringEqual(property, "delay_max_fall")) + return edgeDelayProperty(edge, TransRiseFall::fall(), MinMax::max(), sta); + else if (stringEqual(property, "delay_min_rise")) + return edgeDelayProperty(edge, TransRiseFall::rise(), MinMax::min(), sta); + else if (stringEqual(property, "delay_max_rise")) + return edgeDelayProperty(edge, TransRiseFall::rise(), MinMax::max(), sta); + else if (stringEqual(property, "sense")) + return PropertyValue(timingSenseString(edge->sense())); + else if (stringEqual(property, "from_pin")) + return PropertyValue(edge->from(sta->graph())->pin()); + else if (stringEqual(property, "to_pin")) + return PropertyValue(edge->to(sta->graph())->pin()); + else + return PropertyValue(); +} + +static PropertyValue +edgeDelayProperty(Edge *edge, + const TransRiseFall *tr, + const MinMax *min_max, + Sta *sta) +{ + ArcDelay delay = 0.0; + bool delay_exists = false; + TimingArcSet *arc_set = edge->timingArcSet(); + TimingArcSetArcIterator arc_iter(arc_set); + while (arc_iter.hasNext()) { + TimingArc *arc = arc_iter.next(); + TransRiseFall *to_tr = arc->toTrans()->asRiseFall(); + if (to_tr == tr) { + CornerIterator corner_iter(sta); + while (corner_iter.hasNext()) { + Corner *corner = corner_iter.next(); + DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max); + ArcDelay arc_delay = sta->arcDelay(edge, arc, dcalc_ap); + if (!delay_exists + || ((min_max == MinMax::max() + && arc_delay > delay) + || (min_max == MinMax::min() + && arc_delay < delay))) + delay = arc_delay; + } + } + } + return PropertyValue(delayPropertyValue(delay, sta)); +} + +//////////////////////////////////////////////////////////////// + +PropertyValue +getProperty(Clock *clk, + const char *property, + Sta *sta) +{ + if (stringEqual(property, "name")) + return PropertyValue(clk->name()); + else if (stringEqual(property, "period")) + return PropertyValue(sta->units()->timeUnit()->asString(clk->period(), 8)); + else if (stringEqual(property, "sources")) + return PropertyValue(clk->pins()); + else if (stringEqual(property, "propagated")) + return PropertyValue(clk->isPropagated() ? "1" : "0"); + else + return PropertyValue(); +} + +//////////////////////////////////////////////////////////////// + +PropertyValue +getProperty(PathEnd *end, + const char *property, + Sta *sta) +{ + if (stringEqual(property, "startpoint")) { + PathExpanded expanded(end->path(), sta); + return PropertyValue(expanded.startPath()->pin(sta)); + } + else if (stringEqual(property, "startpoint_clock")) + return PropertyValue(end->path()->clock(sta)); + else if (stringEqual(property, "endpoint")) + return PropertyValue(end->path()->pin(sta)); + else if (stringEqual(property, "endpoint_clock")) + return PropertyValue(end->targetClk(sta)); + else if (stringEqual(property, "endpoint_clock_pin")) + return PropertyValue(end->targetClkPath()->pin(sta)); + else if (stringEqual(property, "slack")) + return PropertyValue(delayPropertyValue(end->slack(sta), sta)); + else if (stringEqual(property, "points")) { + PathExpanded expanded(end->path(), sta); + PathRefSeq paths; + for (auto i = expanded.startIndex(); i < expanded.size(); i++) { + PathRef *path = expanded.path(i); + paths.push_back(*path); + } + return PropertyValue(&paths); + } + else + return PropertyValue(); +} + +PropertyValue +getProperty(PathRef *path, + const char *property, + Sta *sta) +{ + if (stringEqual(property, "pin")) + return PropertyValue(path->pin(sta)); + else if (stringEqual(property, "arrival")) + return PropertyValue(delayPropertyValue(path->arrival(sta), sta)); + else if (stringEqual(property, "required")) + return PropertyValue(delayPropertyValue(path->required(sta), sta)); + else if (stringEqual(property, "slack")) + return PropertyValue(delayPropertyValue(path->slack(sta), sta)); + else + return PropertyValue(); +} + +static float +delayPropertyValue(Delay delay, + Sta *sta) +{ + return delayAsFloat(delay) / sta->units()->timeUnit()->scale(); +} + +} // namespace diff --git a/search/Property.hh b/search/Property.hh new file mode 100644 index 00000000..b9b4fb45 --- /dev/null +++ b/search/Property.hh @@ -0,0 +1,136 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2018, Parallax Software, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#ifndef STA_PROPERTY_H +#define STA_PROPERTY_H + +#include "NetworkClass.hh" +#include "SearchClass.hh" + +namespace sta { + +class Sta; + +class PropertyValue +{ +public: + enum Type { type_none, type_string, type_float, + type_instance, type_pin, type_pins, type_net, + type_clock, type_clocks, type_path_refs }; + PropertyValue(); + PropertyValue(const char *value); + PropertyValue(float value); + PropertyValue(Instance *value); + PropertyValue(Pin *value); + PropertyValue(PinSeq *value); + PropertyValue(PinSet *value); + PropertyValue(Net *value); + PropertyValue(Clock *value); + PropertyValue(ClockSeq *value); + PropertyValue(ClockSet *value); + PropertyValue(PathRefSeq *value); + // Copy constructor. + PropertyValue(const PropertyValue &props); + ~PropertyValue(); + Type type() const { return type_; } + const char *string() const { return string_; } + float floatValue() const { return float_; } + Instance *instance() const { return inst_; } + Pin *pin() const { return pin_; } + PinSeq *pins() const { return pins_; } + Net *net() const { return net_; } + Clock *clock() const { return clk_; } + ClockSeq *clocks() const { return clks_; } + PathRefSeq *pathRefs() const { return path_refs_; } + void operator=(const PropertyValue &); + +private: + void init(); + + Type type_; + const char *string_; + float float_; + Instance *inst_; + Pin *pin_; + PinSeq *pins_; + Net *net_; + Clock *clk_; + ClockSeq *clks_; + PathRefSeq *path_refs_; +}; + +PropertyValue +getProperty(const Instance *inst, + const char *property, + Sta *sta); + +PropertyValue +getProperty(const Pin *pin, + const char *property, + Sta *sta); + +PropertyValue +getProperty(const Net *net, + const char *property, + Sta *sta); + +PropertyValue +getProperty(const Port *port, + const char *property, + Sta *sta); + +PropertyValue +getProperty(const LibertyCell *cell, + const char *property, + Sta *sta); + +PropertyValue +getProperty(const LibertyPort *port, + const char *property, + Sta *); + +PropertyValue +getProperty(const LibertyLibrary *lib, + const char *property, + Sta *sta); + +PropertyValue +getProperty(const Library *lib, + const char *property, + Sta *sta); + +PropertyValue +getProperty(Edge *edge, + const char *property, + Sta *sta); + +PropertyValue +getProperty(Clock *clk, + const char *property, + Sta *sta); + +PropertyValue +getProperty(PathEnd *end, + const char *property, + Sta *sta); + +PropertyValue +getProperty(PathRef *end, + const char *property, + Sta *sta); + +} // namespace +#endif diff --git a/tcl/Cmds.tcl b/tcl/Cmds.tcl index 6e162be8..e04a3b1d 100644 --- a/tcl/Cmds.tcl +++ b/tcl/Cmds.tcl @@ -1772,31 +1772,31 @@ proc get_property_cmd { cmd type_key cmd_args } { set object [get_property_object $object_type $object $quiet] } set object_type [object_type $object] - set attr [lindex $cmd_args 1] + set prop [lindex $cmd_args 1] if { $object_type == "Instance" } { - return [instance_property $object $attr] + return [instance_property $object $prop] } elseif { $object_type == "Pin" } { - return [pin_property $object $attr] + return [pin_property $object $prop] } elseif { $object_type == "Net" } { - return [net_property $object $attr] + return [net_property $object $prop] } elseif { $object_type == "Clock" } { - return [clock_property $object $attr] + return [clock_property $object $prop] } elseif { $object_type == "Port" } { - return [port_property $object $attr] + return [port_property $object $prop] } elseif { $object_type == "LibertyPort" } { - return [liberty_port_property $object $attr] + return [liberty_port_property $object $prop] } elseif { $object_type == "LibertyCell" } { - return [liberty_cell_property $object $attr] + return [liberty_cell_property $object $prop] } elseif { $object_type == "Library" } { - return [library_property $object $attr] + return [library_property $object $prop] } elseif { $object_type == "LibertyLibrary" } { - return [liberty_library_property $object $attr] + return [liberty_library_property $object $prop] } elseif { $object_type == "Edge" } { - return [edge_property $object $attr] + return [edge_property $object $prop] } elseif { $object_type == "PathEnd" } { - return [path_end_property $object $attr] + return [path_end_property $object $prop] } elseif { $object_type == "PathRef" } { - return [path_ref_property $object $attr] + return [path_ref_property $object $prop] } else { sta_error "$cmd unsupported object type $object_type." } @@ -1829,50 +1829,6 @@ proc get_property_object { object_type object_name quiet } { return [lindex $object 0] } -proc edge_property { edge property } { - if { $property == "from_pin" } { - return [$edge from_pin] - } elseif { $property == "to_pin" } { - return [$edge to_pin] - } else { - return [edge_string_property $edge $property] - } -} - -proc path_end_property { path_end property } { - if { $property == "points" } { - return [$path_end points] - } elseif { $property == "startpoint" } { - return [$path_end startpoint] - } elseif { $property == "startpoint_clock" } { - return [$path_end startpoint_clock] - } elseif { $property == "endpoint" } { - return [$path_end endpoint] - } elseif { $property == "endpoint_clock" } { - return [$path_end endpoint_clock] - } elseif { $property == "endpoint_clock_pin" } { - return [$path_end endpoint_clock_pin] - } elseif { $property == "slack" } { - return [time_sta_ui [$path_end slack]] - } else { - return "" - } -} - -proc path_ref_property { path property } { - if { $property == "pin" } { - return [$path pin] - } elseif { $property == "arrival" } { - return [time_sta_ui [$path arrival]] - } elseif { $property == "required" } { - return [time_sta_ui [$path required]] - } elseif { $property == "slack" } { - return [time_sta_ui [$path slack]] - } else { - return "" - } -} - proc get_object_type { obj } { set object_type [object_type $obj] if { $object_type == "Clock" } { diff --git a/tcl/Makefile.am b/tcl/Makefile.am index ee272549..070d5dc9 100644 --- a/tcl/Makefile.am +++ b/tcl/Makefile.am @@ -25,4 +25,5 @@ EXTRA_DIST = \ libs: xtags: - etags -a -o ../TAGS $(TCL_INIT_FILES) $(TCL_SRCS) + etags -a -o ../TAGS --lang=none --regex='/proc[ \t]+\([^ \t]+\)/\1/' \ + $(TCL_INIT_FILES) $(TCL_SRCS) diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index f7c69c5f..caf13fa2 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -77,6 +77,7 @@ #include "PathAnalysisPt.hh" #include "ReportPath.hh" #include "Power.hh" +#include "Property.hh" #include "Sta.hh" namespace sta { @@ -105,43 +106,6 @@ typedef MinMaxAll MinMaxAllNull; typedef ClockSet TmpClockSet; typedef StringSeq TmpStringSeq; -static const char * -pinSlewProperty(const Pin *pin, - const TransRiseFall *tr, - const MinMax *min_max, - Sta *sta); -static const char * -pinSlackProperty(const Pin *pin, - const TransRiseFall *tr, - const MinMax *min_max, - Sta *sta); -static const char * -portSlewProperty(const Port *port, - const TransRiseFall *tr, - const MinMax *min_max, - Sta *sta); -static const char * -portSlackProperty(const Port *port, - const TransRiseFall *tr, - const MinMax *min_max, - Sta *sta); -static const char * -pinClocksProperty(const Pin *pin, - Sta *sta); -const char * -clockProperty(Clock *clk, - const char *property, - Network *network, - Sta *sta); -static const char * -clockSourcesProperty(Clock *clk, - Network *network); -static const char * -pathNamesString(PinSet *pins, - Network *network); -static const char * -clkNamesString(ClockSet *clks); - class CmdErrorNetworkNotLinked : public StaException { public: @@ -456,353 +420,6 @@ TclListSeqEdge(Tcl_Obj * const source, Tcl_Interp *interp) return NULL; } -const char * -portProperty(const Port *port, - const char *property, - Sta *sta) -{ - Network *network = sta->network(); - if (stringEqual(property, "direction")) - return network->direction(port)->name(); - else if (stringEqual(property, "full_name")) - return network->name(port); - - else if (stringEqual(property, "actual_fall_transition_min")) - return portSlewProperty(port, TransRiseFall::fall(), MinMax::min(), sta); - else if (stringEqual(property, "actual_fall_transition_max")) - return portSlewProperty(port, TransRiseFall::fall(), MinMax::max(), sta); - else if (stringEqual(property, "actual_rise_transition_min")) - return portSlewProperty(port, TransRiseFall::rise(), MinMax::min(), sta); - else if (stringEqual(property, "actual_rise_transition_max")) - return portSlewProperty(port, TransRiseFall::rise(), MinMax::max(), sta); - - else if (stringEqual(property, "min_fall_slack")) - return portSlackProperty(port, TransRiseFall::fall(), MinMax::min(), sta); - else if (stringEqual(property, "max_fall_slack")) - return portSlackProperty(port, TransRiseFall::fall(), MinMax::max(), sta); - else if (stringEqual(property, "min_rise_slack")) - return portSlackProperty(port, TransRiseFall::rise(), MinMax::min(), sta); - else if (stringEqual(property, "max_rise_slack")) - return portSlackProperty(port, TransRiseFall::rise(), MinMax::max(), sta); - - else - return NULL; -} - -static const char * -portSlewProperty(const Port *port, - const TransRiseFall *tr, - const MinMax *min_max, - Sta *sta) -{ - Network *network = sta->network(); - Instance *top_inst = network->topInstance(); - Pin *pin = network->findPin(top_inst, port); - return pinSlewProperty(pin, tr, min_max, sta); -} - -static const char * -portSlackProperty(const Port *port, - const TransRiseFall *tr, - const MinMax *min_max, - Sta *sta) -{ - Network *network = sta->network(); - Instance *top_inst = network->topInstance(); - Pin *pin = network->findPin(top_inst, port); - return pinSlackProperty(pin, tr, min_max, sta); -} - -const char * -libertyCellProperty(const LibertyCell *cell, - const char *property, - Network *network) -{ - if (stringEqual(property, "base_name")) - return cell->name(); - else if (stringEqual(property, "full_name")) { - const LibertyLibrary *lib = cell->libertyLibrary(); - const char *lib_name = lib->name(); - const char *cell_name = cell->name(); - return stringPrintTmp(strlen(lib_name) + strlen(cell_name) + 2, - "%s%c%s", - lib_name, - network->pathDivider(), - cell_name); - } - else - return NULL; -} - -const char * -libertyPortProperty(const LibertyPort *port, - const char *property) -{ - if (stringEqual(property, "direction")) - return port->direction()->name(); - else if (stringEqual(property, "full_name")) - return port->name(); - else - return NULL; -} - -const char * -instanceProperty(const Instance *inst, - const char *property, - Network *network) -{ - if (stringEqual(property, "ref_name")) - return network->name(network->cell(inst)); - else if (stringEqual(property, "full_name")) - return network->pathName(inst); - else - return NULL; -} - -const char * -pinProperty(const Pin *pin, - const char *property, - Network *network, - Sta *sta) -{ - if (stringEqual(property, "direction")) - return network->direction(pin)->name(); - else if (stringEqual(property, "full_name")) - return network->pathName(pin); - else if (stringEqual(property, "lib_pin_name")) - return network->portName(pin); - else if (stringEqual(property, "clocks")) - return pinClocksProperty(pin, sta); - - else if (stringEqual(property, "max_fall_slack")) - return pinSlackProperty(pin, TransRiseFall::fall(), MinMax::max(), sta); - else if (stringEqual(property, "max_rise_slack")) - return pinSlackProperty(pin, TransRiseFall::rise(), MinMax::max(), sta); - else if (stringEqual(property, "min_fall_slack")) - return pinSlackProperty(pin, TransRiseFall::fall(), MinMax::min(), sta); - else if (stringEqual(property, "min_rise_slack")) - return pinSlackProperty(pin, TransRiseFall::rise(), MinMax::min(), sta); - - else if (stringEqual(property, "actual_fall_transition_max")) - return pinSlewProperty(pin, TransRiseFall::fall(), MinMax::max(), sta); - else if (stringEqual(property, "actual_rise_transition_max")) - return pinSlewProperty(pin, TransRiseFall::rise(), MinMax::max(), sta); - else if (stringEqual(property, "actual_rise_transition_min")) - return pinSlewProperty(pin, TransRiseFall::rise(), MinMax::min(), sta); - else if (stringEqual(property, "actual_fall_transition_min")) - return pinSlewProperty(pin, TransRiseFall::fall(), MinMax::min(), sta); - - else - return NULL; -} - -static const char * -pinClocksProperty(const Pin *pin, - Sta *sta) -{ - ClockSet clks; - sta->clocks(pin, clks); - return clkNamesString(&clks); -} - -static const char * -pinSlewProperty(const Pin *pin, - const TransRiseFall *tr, - const MinMax *min_max, - Sta *sta) -{ - Graph *graph = sta->ensureGraph(); - Vertex *vertex, *bidirect_drvr_vertex; - graph->pinVertices(pin, vertex, bidirect_drvr_vertex); - Slew slew = min_max->initValue(); - if (vertex) { - Slew vertex_slew = sta->vertexSlew(vertex, tr, min_max); - if (delayFuzzyGreater(vertex_slew, slew, min_max)) - slew = vertex_slew; - } - if (bidirect_drvr_vertex) { - Slew vertex_slew = sta->vertexSlew(bidirect_drvr_vertex, tr, min_max); - if (delayFuzzyGreater(vertex_slew, slew, min_max)) - slew = vertex_slew; - } - return sta->units()->timeUnit()->asString(delayAsFloat(slew), 8); -} - -static const char * -pinSlackProperty(const Pin *pin, - const TransRiseFall *tr, - const MinMax *min_max, - Sta *sta) -{ - Slack slack = sta->pinSlack(pin, tr, min_max); - return sta->units()->timeUnit()->asString(delayAsFloat(slack), 8); -} - -const char * -netProperty(const Net *net, - const char *property, - Network *network) -{ - if (stringEqual(property, "full_name")) - return network->pathName(net); - else - return NULL; -} - -const char * -libraryProperty(const Library *lib, - const char *property, - Network *network) -{ - if (stringEqual(property, "name")) - return network->name(lib); - else - return NULL; -} - -const char * -libertyLibraryProperty(const LibertyLibrary *lib, - const char *property) -{ - if (stringEqual(property, "name")) - return lib->name(); - else if (stringEqual(property, "filename")) - return lib->filename(); - else - return NULL; -} - -const char * -edgeDelayProperty(Edge *edge, - const TransRiseFall *tr, - const MinMax *min_max, - Sta *sta) -{ - ArcDelay delay = 0.0; - bool delay_exists = false; - TimingArcSet *arc_set = edge->timingArcSet(); - TimingArcSetArcIterator arc_iter(arc_set); - while (arc_iter.hasNext()) { - TimingArc *arc = arc_iter.next(); - TransRiseFall *to_tr = arc->toTrans()->asRiseFall(); - if (to_tr == tr) { - CornerIterator corner_iter(sta); - while (corner_iter.hasNext()) { - Corner *corner = corner_iter.next(); - DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max); - ArcDelay arc_delay = sta->arcDelay(edge, arc, dcalc_ap); - if (!delay_exists - || ((min_max == MinMax::max() - && arc_delay > delay) - || (min_max == MinMax::min() - && arc_delay < delay))) - delay = arc_delay; - } - } - } - return sta->units()->timeUnit()->asString(delayAsFloat(delay), 8); -} - -const char * -edgeStringProperty(Edge *edge, - const char *property, - Sta *sta) -{ - if (stringEqual(property, "delay_min_fall")) - return edgeDelayProperty(edge, TransRiseFall::fall(), MinMax::min(), sta); - else if (stringEqual(property, "delay_max_fall")) - return edgeDelayProperty(edge, TransRiseFall::fall(), MinMax::max(), sta); - else if (stringEqual(property, "delay_min_rise")) - return edgeDelayProperty(edge, TransRiseFall::rise(), MinMax::min(), sta); - else if (stringEqual(property, "delay_max_rise")) - return edgeDelayProperty(edge, TransRiseFall::rise(), MinMax::max(), sta); - else if (stringEqual(property, "sense")) - return timingSenseString(edge->sense()); - else - return NULL; -} - -const char * -clockProperty(Clock *clk, - const char *property, - Network *network, - Sta *sta) -{ - if (stringEqual(property, "name")) - return clk->name(); - else if (stringEqual(property, "period")) - return sta->units()->timeUnit()->asString(clk->period(), 8); - else if (stringEqual(property, "sources")) - return clockSourcesProperty(clk, network); - else if (stringEqual(property, "propagated")) - return clk->isPropagated() ? "1" : "0"; - else - return NULL; -} - -static const char * -clockSourcesProperty(Clock *clk, - Network *network) -{ - return pathNamesString(clk->pins(), network); -} - -// Concatenate the pin names separated with a space. -static const char * -pathNamesString(PinSet *pins, - Network *network) -{ - int length = 1; - PinSet::Iterator pin_iter1(pins); - while (pin_iter1.hasNext()) { - Pin *pin = pin_iter1.next(); - const char *name = network->pathName(pin); - length += strlen(name) + 1; - } - char *result = makeTmpString(length); - char *s = result; - bool first = true; - PinSet::Iterator pin_iter2(pins); - while (pin_iter2.hasNext()) { - Pin *pin = pin_iter2.next(); - const char *name = network->pathName(pin); - if (!first) - *s++ = ' '; - strcpy(s, name); - s += strlen(name); - first = false; - } - *s = '\0'; - return result; -} - -// Concatenate the clock names separated with a space. -static const char * -clkNamesString(ClockSet *clks) -{ - int length = 1; - ClockSet::Iterator clk_iter1(clks); - while (clk_iter1.hasNext()) { - Clock *clk = clk_iter1.next(); - length += strlen(clk->name()) + 1; - } - char *result = makeTmpString(length); - char *s = result; - bool first = true; - ClockSet::Iterator clk_iter2(clks); - while (clk_iter2.hasNext()) { - Clock *clk = clk_iter2.next(); - const char *name = clk->name(); - if (!first) - *s++ = ' '; - strcpy(s, name); - s += strlen(name); - first = false; - } - *s = '\0'; - return result; -} - //////////////////////////////////////////////////////////////// TmpPinSet * @@ -1777,9 +1394,6 @@ using namespace sta; } %typemap(out) PathEndSeq* { - Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false); - Tcl_SetObjResult(interp, obj); - Tcl_Obj *list = Tcl_NewListObj(0, NULL); const PathEndSeq *path_ends = $1; PathEndSeq::ConstIterator end_iter(path_ends); @@ -1788,6 +1402,7 @@ using namespace sta; Tcl_Obj *obj = SWIG_NewInstanceObj(path_end, SWIGTYPE_p_PathEnd, false); Tcl_ListObjAppendElement(interp, list, obj); } + // Delete the PathEndSeq, not the ends. delete path_ends; Tcl_SetObjResult(interp, list); } @@ -1810,7 +1425,6 @@ using namespace sta; Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_PathRef, false); Tcl_ListObjAppendElement(interp, list, obj); } - delete paths; Tcl_SetObjResult(interp, list); } @@ -1907,6 +1521,87 @@ using namespace sta; Tcl_SetObjResult(interp, obj); } +%typemap(out) PropertyValue { + PropertyValue value = $1; + switch (value.type()) { + case PropertyValue::Type::type_none: + Tcl_SetResult(interp, const_cast(""), TCL_STATIC); + break; + case PropertyValue::Type::type_string: + Tcl_SetResult(interp, const_cast(value.string()), TCL_VOLATILE); + break; + case PropertyValue::Type::type_float: { + char *float_string = stringPrint(10, "%.5f", value.floatValue()); + Tcl_SetResult(interp, float_string, TCL_VOLATILE); + stringDelete(float_string); + } + break; + case PropertyValue::Type::type_instance: { + Tcl_Obj *obj = SWIG_NewInstanceObj(value.instance(), + SWIGTYPE_p_Instance, false); + Tcl_SetObjResult(interp, obj); + } + break; + case PropertyValue::Type::type_pin: { + Tcl_Obj *obj = SWIG_NewInstanceObj(value.pin(), SWIGTYPE_p_Pin, false); + Tcl_SetObjResult(interp, obj); + } + break; + case PropertyValue::Type::type_pins: { + Tcl_Obj *list = Tcl_NewListObj(0, NULL); + PinSeq *pins = value.pins(); + PinSeq::Iterator pin_iter(pins); + while (pin_iter.hasNext()) { + Pin *pin = pin_iter.next(); + Tcl_Obj *obj = SWIG_NewInstanceObj(pin, SWIGTYPE_p_Pin, false); + Tcl_ListObjAppendElement(interp, list, obj); + } + Tcl_SetObjResult(interp, list); + } + break; + case PropertyValue::Type::type_net: { + Tcl_Obj *obj = SWIG_NewInstanceObj(value.net(), + SWIGTYPE_p_Net, false); + Tcl_SetObjResult(interp, obj); + } + break; + case PropertyValue::Type::type_clock: { + Tcl_Obj *obj = SWIG_NewInstanceObj(value.clock(), + SWIGTYPE_p_Clock, false); + Tcl_SetObjResult(interp, obj); + } + break; + case PropertyValue::Type::type_clocks: { + Tcl_Obj *list = Tcl_NewListObj(0, NULL); + ClockSeq *clks = value.clocks(); + ClockSeq::Iterator clk_iter(clks); + while (clk_iter.hasNext()) { + Clock *clk = clk_iter.next(); + Tcl_Obj *obj = SWIG_NewInstanceObj(clk, SWIGTYPE_p_Clock, false); + Tcl_ListObjAppendElement(interp, list, obj); + } + Tcl_SetObjResult(interp, list); + } + break; + case PropertyValue::Type::type_path_refs: { + Tcl_Obj *list = Tcl_NewListObj(0, NULL); + PathRefSeq *paths = value.pathRefs(); + PathRefSeq::Iterator path_iter(paths); + while (path_iter.hasNext()) { + PathRef &path = path_iter.next(); + PathRef *copy = new PathRef(path); + Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_PathRef, false); + Tcl_ListObjAppendElement(interp, list, obj); + } + Tcl_SetObjResult(interp, list); + } + break; + default: + Tcl_SetResult(interp, const_cast(""), TCL_STATIC); + break; + } +} + //////////////////////////////////////////////////////////////// // // Empty class definitions to make swig happy. @@ -2838,7 +2533,8 @@ filter_ports(const char *property, bool exact_match = stringEq(op, "=="); while (port_iter.hasNext()) { Port *port = port_iter.next(); - const char *prop = portProperty(port, property, sta); + PropertyValue value(getProperty(port, property, sta)); + const char *prop = value.string(); if (prop && ((exact_match && stringEq(prop, pattern)) || (!exact_match && patternMatch(pattern, prop)))) @@ -2854,13 +2550,15 @@ filter_insts(const char *property, const char *pattern, InstanceSeq *insts) { - Network *network = cmdLinkedNetwork(); + Sta *sta = Sta::sta(); + cmdLinkedNetwork(); TmpInstanceSeq *filtered_insts = new TmpInstanceSeq; TmpInstanceSeq::Iterator inst_iter(insts); bool exact_match = stringEq(op, "=="); while (inst_iter.hasNext()) { Instance *inst = inst_iter.next(); - const char *prop = instanceProperty(inst, property, network); + PropertyValue value(getProperty(inst, property, sta)); + const char *prop = value.string(); if (prop && ((exact_match && stringEq(prop, pattern)) || (!exact_match && patternMatch(pattern, prop)))) @@ -2876,14 +2574,14 @@ filter_pins(const char *property, const char *pattern, PinSeq *pins) { - Network *network = cmdLinkedNetwork(); Sta *sta = Sta::sta(); PinSeq *filtered_pins = new PinSeq; PinSeq::Iterator pin_iter(pins); bool exact_match = stringEq(op, "=="); while (pin_iter.hasNext()) { Pin *pin = pin_iter.next(); - const char *prop = pinProperty(pin, property, network, sta); + PropertyValue value(getProperty(pin, property, sta)); + const char *prop = value.string(); if (prop && ((exact_match && stringEq(prop, pattern)) || (!exact_match && patternMatch(pattern, prop)))) @@ -2893,75 +2591,100 @@ filter_pins(const char *property, return filtered_pins; } -const char * +PropertyValue pin_property(const Pin *pin, const char *property) { - return pinProperty(pin, property, cmdLinkedNetwork(), Sta::sta()); + cmdGraph(); + return getProperty(pin, property, Sta::sta()); } -const char * +PropertyValue instance_property(const Instance *inst, const char *property) { - return instanceProperty(inst, property, cmdLinkedNetwork()); + cmdGraph(); + return getProperty(inst, property, Sta::sta()); } -const char * +PropertyValue net_property(const Net *net, const char *property) { - return netProperty(net, property, cmdLinkedNetwork()); + cmdGraph(); + return getProperty(net, property, Sta::sta()); } -const char * +PropertyValue port_property(const Port *port, const char *property) { - Sta *sta = Sta::sta(); - return portProperty(port, property, sta); + cmdGraph(); + return getProperty(port, property, Sta::sta()); } -const char * + +PropertyValue liberty_cell_property(const LibertyCell *cell, const char *property) { - return libertyCellProperty(cell, property, cmdLinkedNetwork()); + cmdLinkedNetwork(); + return getProperty(cell, property, Sta::sta()); } -const char * +PropertyValue liberty_port_property(const LibertyPort *port, const char *property) { - return libertyPortProperty(port, property); + cmdLinkedNetwork(); + return getProperty(port, property, Sta::sta()); } -const char * +PropertyValue library_property(const Library *lib, const char *property) { - return libraryProperty(lib, property, cmdLinkedNetwork()); + cmdLinkedNetwork(); + return getProperty(lib, property, Sta::sta()); } -const char * +PropertyValue liberty_library_property(const LibertyLibrary *lib, const char *property) { - return libertyLibraryProperty(lib, property); + return getProperty(lib, property, Sta::sta()); } -const char * -edge_string_property(Edge *edge, - const char *property) +PropertyValue +edge_property(Edge *edge, + const char *property) { - return edgeStringProperty(edge, property, Sta::sta()); + cmdGraph(); + return getProperty(edge, property, Sta::sta()); } -const char * +PropertyValue clock_property(Clock *clk, const char *property) { - return clockProperty(clk, property, cmdLinkedNetwork(), Sta::sta()); + cmdLinkedNetwork(); + return getProperty(clk, property, Sta::sta()); +} + +PropertyValue +path_end_property(PathEnd *end, + const char *property) +{ + cmdLinkedNetwork(); + return getProperty(end, property, Sta::sta()); +} + +PropertyValue +path_ref_property(PathRef *path, + const char *property) +{ + cmdLinkedNetwork(); + return getProperty(path, property, Sta::sta()); } LeafInstanceIterator * @@ -3034,10 +2757,11 @@ filter_timing_arcs(const char *property, bool exact_match = stringEq(op, "=="); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - const char *value = edgeStringProperty(edge, property, sta); - if (value && - ((exact_match && stringEq(value, pattern)) - || (!exact_match && patternMatch(pattern, value)))) + PropertyValue value(getProperty(edge, property, sta)); + const char *prop = value.string(); + if (prop && + ((exact_match && stringEq(prop, pattern)) + || (!exact_match && patternMatch(pattern, prop)))) filtered_edges->push_back(edge); } delete edges; @@ -6259,55 +5983,6 @@ Crpr common_clk_pessimism() { return self->commonClkPessimism(Sta::sta()); } TransRiseFall *target_clk_end_trans() { return const_cast(self->targetClkEndTrans(Sta::sta())); } -Pin * -startpoint() -{ - Sta *sta = Sta::sta(); - PathExpanded expanded(self->path(), sta); - return expanded.startPath()->pin(sta); -} - -Clock * -startpoint_clock() -{ - Sta *sta = Sta::sta(); - return self->path()->clock(sta); -} - -Pin * -endpoint() -{ - Sta *sta = Sta::sta(); - return self->path()->pin(sta); -} - -Clock * -endpoint_clock() -{ - Sta *sta = Sta::sta(); - return self->targetClk(sta); -} - -Pin * -endpoint_clock_pin() -{ - Sta *sta = Sta::sta(); - return self->targetClkPath()->pin(sta); -} - -PathRefSeq * -points() -{ - Sta *sta = Sta::sta(); - PathExpanded expanded(self->path(), sta); - PathRefSeq *paths = new PathRefSeq; - for (auto i = expanded.startIndex(); i < expanded.size(); i++) { - PathRef *path = expanded.path(i); - paths->push_back(*path); - } - return paths; -} - } %extend MinPulseWidthCheckSeqIterator { @@ -6345,21 +6020,6 @@ pin() return self->pin(sta); } -TmpPinSeq * -pins() -{ - Sta *sta = Sta::sta(); - PinSeq *pins = new PinSeq; - PathRef path1(self); - while (!path1.isNull()) { - pins->push_back(path1.vertex(sta)->pin()); - PathRef prev_path; - path1.prevPath(sta, prev_path); - path1.init(prev_path); - } - return pins; -} - const char * tag() {