This commit is contained in:
James Cherry 2018-12-26 11:03:31 -08:00
parent 4f381f6669
commit a6e21377e6
14 changed files with 916 additions and 549 deletions

View File

@ -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)

View File

@ -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

View File

@ -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_; }

View File

@ -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;

View File

@ -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);

View File

@ -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();
}

View File

@ -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 \

View File

@ -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)

View File

@ -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);

572
search/Property.cc Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
#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

136
search/Property.hh Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
#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

View File

@ -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" } {

View File

@ -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)

View File

@ -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<char*>(""), TCL_STATIC);
break;
case PropertyValue::Type::type_string:
Tcl_SetResult(interp, const_cast<char*>(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<char*>(""), 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<TransRiseFall*>(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()
{