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()
{