2018/12/24 all_fanout from input port

This commit is contained in:
James Cherry 2018-12-24 13:07:10 -08:00
parent 0a693f3236
commit 4f381f6669
14 changed files with 193 additions and 35 deletions

View File

@ -34,7 +34,7 @@ tcl 8.2 8.6 8.6.6
These packages are optional: These packages are optional:
libz 1.1.4 1.2.5 1.2.8 libz 1.1.4 1.2.5 1.2.8
cudd 2.4.1 2.5.0 cudd 2.4.1 3.0.0
Use the following commands to unpack the dist file and compile it. Use the following commands to unpack the dist file and compile it.
@ -60,9 +60,10 @@ configure options:
--with-visualstudio use Microcruft Visual Studio C++ compiler --with-visualstudio use Microcruft Visual Studio C++ compiler
CUDD is a BDD package that is used to improve conditional timing arc CUDD is a BDD package that is used to improve conditional timing arc
handling. It is available from the following url: handling. It is available here:
ftp://vlsi.colorado.edu/pub/cudd-2.5.0.tar.gz https://www.davidkebo.com/source/cudd_versions/cudd-3.0.0.tar.gz
https://sourceforge.net/projects/cudd-mirror/
The Zlib library is an optional. If the configure script finds libz, The Zlib library is an optional. If the configure script finds libz,
OpenSTA can read Verilog, SDF, SPF, and SPEF files compressed with OpenSTA can read Verilog, SDF, SPF, and SPEF files compressed with

View File

@ -16,7 +16,7 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
AC_INIT(sta, 2.0) AC_INIT(sta, 2.0.1)
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS(config.h) AC_CONFIG_HEADERS(config.h)
@ -173,7 +173,7 @@ AC_ARG_WITH(tcl,
[]) [])
AC_ARG_WITH(cudd, AC_ARG_WITH(cudd,
[AS_HELP_STRING([--with-cudd=path],[use Cudd BDD package, defaults to $CUDD])], [AS_HELP_STRING([--with-cudd=path],[use CUDD BDD package, defaults to $CUDD])],
[CUDD_ARG="${withval}"], [CUDD_ARG="${withval}"],
[CUDD_ARG=$CUDD]) [CUDD_ARG=$CUDD])
@ -352,23 +352,24 @@ AC_SUBST(ZLIB_LIB)
CUDD_INCLUDE="" CUDD_INCLUDE=""
CUDD_LIBS="" CUDD_LIBS=""
if test "$CUDD_ARG"; then if test "$CUDD_ARG"; then
AC_MSG_CHECKING(for Cudd header file) AC_MSG_RESULT($CUDD_ARG)
AC_MSG_CHECKING(for CUDD header file)
CUDD_INCLUDE_DIR="$CUDD_ARG/include" CUDD_INCLUDE_DIR="$CUDD_ARG/include"
CUDD_HEADER="$CUDD_INCLUDE_DIR/cudd.h" CUDD_HEADER="$CUDD_INCLUDE_DIR/cudd.h"
if test -r "$CUDD_HEADER"; then if test -r "$CUDD_HEADER"; then
AC_MSG_RESULT($CUDD_HEADER) AC_MSG_RESULT($CUDD_HEADER)
CUDD_INCLUDE=$CUDD_INCLUDE_DIR CUDD_INCLUDE=$CUDD_INCLUDE_DIR
AC_DEFINE(CUDD, 1, "Cudd bdd package") AC_DEFINE(CUDD, 1, "CUDD bdd package")
else else
AC_MSG_RESULT(not found) AC_MSG_RESULT(not found)
fi fi
AC_MSG_CHECKING(for Cudd library) AC_MSG_CHECKING(for CUDD library)
CUDD_LIB_EXT="a" CUDD_LIB_EXT="a"
CUDD_LIB="$CUDD_ARG/cudd/libcudd.$CUDD_LIB_EXT" CUDD_LIB="$CUDD_ARG/lib/libcudd.$CUDD_LIB_EXT"
if test -r $CUDD_LIB; then if test -r $CUDD_LIB; then
AC_MSG_RESULT($CUDD_LIB) AC_MSG_RESULT($CUDD_LIB)
CUDD_LIBS="$CUDD_ARG/cudd/libcudd.$CUDD_LIB_EXT $CUDD_ARG/mtr/libmtr.$CUDD_LIB_EXT $CUDD_ARG/st/libst.$CUDD_LIB_EXT $CUDD_ARG/util/libutil.$CUDD_LIB_EXT $CUDD_ARG/epd/libepd.$CUDD_LIB_EXT" CUDD_LIBS="$CUDD_ARG/lib/libcudd.$CUDD_LIB_EXT"
else else
AC_MSG_RESULT(not found) AC_MSG_RESULT(not found)
fi fi

View File

@ -405,7 +405,7 @@ close $in_stream
# Disable emacs syntax highlighting. # Disable emacs syntax highlighting.
puts $out_stream "// Local Variables:" puts $out_stream "// Local Variables:"
puts $out_stream "// font-lock-auto-fontify: nil" puts $out_stream "// mode:c++"
puts $out_stream "// End:" puts $out_stream "// End:"
close $out_stream close $out_stream

View File

@ -895,6 +895,8 @@ LibertyCell::~LibertyCell()
delete test_cell_; delete test_cell_;
ocv_derate_map_.deleteContents(); ocv_derate_map_.deleteContents();
pg_port_map_.deleteContents();
} }
// Multiple timing arc sets (buses bits or a related_ports list) // Multiple timing arc sets (buses bits or a related_ports list)
@ -944,6 +946,18 @@ LibertyCell::setHasInternalPorts(bool has_internal)
has_internal_ports_ = has_internal; has_internal_ports_ = has_internal;
} }
void
LibertyCell::addPgPort(LibertyPgPort *pg_port)
{
pg_port_map_[pg_port->name()] = pg_port;
}
LibertyPgPort *
LibertyCell::findPgPort(const char *name)
{
return pg_port_map_.findKey(name);
}
ModeDef * ModeDef *
LibertyCell::makeModeDef(const char *name) LibertyCell::makeModeDef(const char *name)
{ {
@ -1752,6 +1766,7 @@ LibertyPort::LibertyPort(LibertyCell *cell,
min_period_(0.0), min_period_(0.0),
pulse_clk_trigger_(NULL), pulse_clk_trigger_(NULL),
pulse_clk_sense_(NULL), pulse_clk_sense_(NULL),
related_ground_pin_(NULL),
related_power_pin_(NULL), related_power_pin_(NULL),
min_pulse_width_exists_(false), min_pulse_width_exists_(false),
min_period_exists_(false), min_period_exists_(false),
@ -1775,6 +1790,7 @@ LibertyPort::~LibertyPort()
if (tristate_enable_) if (tristate_enable_)
tristate_enable_->deleteSubexprs(); tristate_enable_->deleteSubexprs();
delete scaled_ports_; delete scaled_ports_;
stringDelete(related_ground_pin_);
stringDelete(related_power_pin_); stringDelete(related_power_pin_);
} }
@ -2134,6 +2150,12 @@ LibertyPort::setCornerPort(LibertyPort *corner_port,
corner_ports_[ap_index] = corner_port; corner_ports_[ap_index] = corner_port;
} }
void
LibertyPort::setRelatedGroundPin(const char *related_ground_pin)
{
related_ground_pin_ = stringCopy(related_ground_pin);
}
void void
LibertyPort::setRelatedPowerPin(const char *related_power_pin) LibertyPort::setRelatedPowerPin(const char *related_power_pin)
{ {
@ -2690,4 +2712,31 @@ OcvDerate::setDerateTable(const TransRiseFall *tr,
derate_[tr->index()][early_late->index()][path_type] = derate; derate_[tr->index()][early_late->index()][path_type] = derate;
} }
////////////////////////////////////////////////////////////////
LibertyPgPort::LibertyPgPort(const char *name) :
name_(stringCopy(name)),
pg_type_(unknown),
voltage_name_(NULL)
{
}
LibertyPgPort::~LibertyPgPort()
{
stringDelete(name_);
stringDelete(voltage_name_);
}
void
LibertyPgPort::setPgType(PgType type)
{
pg_type_ = type;
}
void
LibertyPgPort::setVoltageName(const char *voltage_name)
{
voltage_name_ = stringCopy(voltage_name);
}
} // namespace } // namespace

View File

@ -43,6 +43,7 @@ class LibertyReader;
class OcvDerate; class OcvDerate;
class TimingArcAttrs; class TimingArcAttrs;
class InternalPowerAttrs; class InternalPowerAttrs;
class LibertyPgPort;
typedef Set<Library*> LibrarySet; typedef Set<Library*> LibrarySet;
typedef Map<const char*, TableTemplate*, CharPtrLess> TableTemplateMap; typedef Map<const char*, TableTemplate*, CharPtrLess> TableTemplateMap;
@ -69,6 +70,7 @@ typedef Map<const char *, OcvDerate*, CharPtrLess> OcvDerateMap;
typedef Vector<TimingArcAttrs*> TimingArcAttrsSeq; typedef Vector<TimingArcAttrs*> TimingArcAttrsSeq;
typedef Vector<InternalPowerAttrs*> InternalPowerAttrsSeq; typedef Vector<InternalPowerAttrs*> InternalPowerAttrsSeq;
typedef Map<const char *, float, CharPtrLess> SupplyVoltageMap; typedef Map<const char *, float, CharPtrLess> SupplyVoltageMap;
typedef Map<const char *, LibertyPgPort*, CharPtrLess> LibertyPgPortMap;
typedef enum { typedef enum {
clock_gate_none, clock_gate_none,
@ -388,6 +390,7 @@ public:
void findLibertyPortsMatching(PatternMatch *pattern, void findLibertyPortsMatching(PatternMatch *pattern,
LibertyPortSeq *ports) const; LibertyPortSeq *ports) const;
bool hasInternalPorts() const { return has_internal_ports_; } bool hasInternalPorts() const { return has_internal_ports_; }
LibertyPgPort *findPgPort(const char *name);
ScaleFactors *scaleFactors() const { return scale_factors_; } ScaleFactors *scaleFactors() const { return scale_factors_; }
void setScaleFactors(ScaleFactors *scale_factors); void setScaleFactors(ScaleFactors *scale_factors);
ModeDef *makeModeDef(const char *name); ModeDef *makeModeDef(const char *name);
@ -475,6 +478,8 @@ public:
OcvDerate *findOcvDerate(const char *derate_name); OcvDerate *findOcvDerate(const char *derate_name);
void addOcvDerate(OcvDerate *derate); void addOcvDerate(OcvDerate *derate);
void addPgPort(LibertyPgPort *pg_port);
protected: protected:
virtual void addPort(ConcretePort *port); virtual void addPort(ConcretePort *port);
void setHasInternalPorts(bool has_internal); void setHasInternalPorts(bool has_internal);
@ -534,6 +539,7 @@ protected:
bool is_disabled_constraint_; bool is_disabled_constraint_;
Vector<LibertyCell*> corner_cells_; Vector<LibertyCell*> corner_cells_;
float leakage_power_; float leakage_power_;
LibertyPgPortMap pg_port_map_;
private: private:
DISALLOW_COPY_AND_ASSIGN(LibertyCell); DISALLOW_COPY_AND_ASSIGN(LibertyCell);
@ -699,6 +705,8 @@ public:
LibertyPort *cornerPort(int ap_index); LibertyPort *cornerPort(int ap_index);
void setCornerPort(LibertyPort *corner_port, void setCornerPort(LibertyPort *corner_port,
int ap_index); int ap_index);
const char *relatedGroundPin() const { return related_ground_pin_; }
void setRelatedGroundPin(const char *related_ground_pin);
const char *relatedPowerPin() const { return related_power_pin_; } const char *relatedPowerPin() const { return related_power_pin_; }
void setRelatedPowerPin(const char *related_power_pin); void setRelatedPowerPin(const char *related_power_pin);
@ -734,6 +742,7 @@ protected:
float min_pulse_width_[TransRiseFall::index_count]; float min_pulse_width_[TransRiseFall::index_count];
TransRiseFall *pulse_clk_trigger_; TransRiseFall *pulse_clk_trigger_;
TransRiseFall *pulse_clk_sense_; TransRiseFall *pulse_clk_sense_;
const char *related_ground_pin_;
const char *related_power_pin_; const char *related_power_pin_;
Vector<LibertyPort*> corner_ports_; Vector<LibertyPort*> corner_ports_;
@ -1002,5 +1011,24 @@ private:
Table *derate_[TransRiseFall::index_count][EarlyLate::index_count][path_type_count]; Table *derate_[TransRiseFall::index_count][EarlyLate::index_count][path_type_count];
}; };
// Power/ground port.
class LibertyPgPort
{
public:
enum PgType { unknown, power, ground };
LibertyPgPort(const char *name);
~LibertyPgPort();
const char *name() { return name_; }
PgType pgType() const { return pg_type_; }
void setPgType(PgType type);
const char *voltageName() const { return voltage_name_; }
void setVoltageName(const char *voltage_name);
private:
const char *name_;
PgType pg_type_;
const char *voltage_name_;
};
} // namespace } // namespace
#endif #endif

View File

@ -131,6 +131,7 @@ LibertyReader::readLibertyFile(const char *filename,
mode_def_ = NULL; mode_def_ = NULL;
mode_value_ = NULL; mode_value_ = NULL;
ocv_derate_ = NULL; ocv_derate_ = NULL;
pg_port_ = NULL;
have_resistance_unit_ = false; have_resistance_unit_ = false;
TransRiseFallIterator tr_iter; TransRiseFallIterator tr_iter;
@ -404,6 +405,7 @@ LibertyReader::defineVisitors()
&LibertyReader::endRiseFallPower); &LibertyReader::endRiseFallPower);
defineGroupVisitor("rise_power", &LibertyReader::beginRisePower, defineGroupVisitor("rise_power", &LibertyReader::beginRisePower,
&LibertyReader::endRiseFallPower); &LibertyReader::endRiseFallPower);
defineAttrVisitor("related_ground_pin",&LibertyReader::visitRelatedGroundPin);
defineAttrVisitor("related_power_pin", &LibertyReader::visitRelatedPowerPin); defineAttrVisitor("related_power_pin", &LibertyReader::visitRelatedPowerPin);
defineAttrVisitor("related_pg_pin", &LibertyReader::visitRelatedPgPin); defineAttrVisitor("related_pg_pin", &LibertyReader::visitRelatedPgPin);
@ -438,6 +440,11 @@ LibertyReader::defineVisitors()
&LibertyReader::endOcvSigmaTransition); &LibertyReader::endOcvSigmaTransition);
defineAttrVisitor("sigma_type", &LibertyReader::visitSigmaType); defineAttrVisitor("sigma_type", &LibertyReader::visitSigmaType);
defineAttrVisitor("cell_leakage_power", &LibertyReader::visitCellLeakagePower); defineAttrVisitor("cell_leakage_power", &LibertyReader::visitCellLeakagePower);
defineGroupVisitor("pg_pin", &LibertyReader::beginPgPin,
&LibertyReader::endPgPin);
defineAttrVisitor("pg_type", &LibertyReader::visitPgType);
defineAttrVisitor("voltage_name", &LibertyReader::visitVoltageName);
} }
void void
@ -4476,6 +4483,19 @@ LibertyReader::endRiseFallPower(LibertyGroup *)
endTableModel(); endTableModel();
} }
void
LibertyReader::visitRelatedGroundPin(LibertyAttr *attr)
{
if (ports_) {
const char *related_ground_pin = getAttrString(attr);
LibertyPortSeq::Iterator port_iter(ports_);
while (port_iter.hasNext()) {
LibertyPort *port = port_iter.next();
port->setRelatedGroundPin(related_ground_pin);
}
}
}
void void
LibertyReader::visitRelatedPowerPin(LibertyAttr *attr) LibertyReader::visitRelatedPowerPin(LibertyAttr *attr)
{ {
@ -4704,6 +4724,47 @@ LibertyReader::visitCellLeakagePower(LibertyAttr *attr)
} }
} }
void
LibertyReader::beginPgPin(LibertyGroup *group)
{
if (cell_) {
const char *name = group->firstName();
pg_port_ = new LibertyPgPort(name);
cell_->addPgPort(pg_port_);
}
}
void
LibertyReader::endPgPin(LibertyGroup *)
{
pg_port_ = NULL;
}
void
LibertyReader::visitPgType(LibertyAttr *attr)
{
if (pg_port_) {
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;
else
libError(attr, "unknown pg_type.\n");
pg_port_->setPgType(type);
}
}
void
LibertyReader::visitVoltageName(LibertyAttr *attr)
{
if (pg_port_) {
const char *voltage_name = getAttrString(attr);
pg_port_->setVoltageName(voltage_name);
}
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
LibertyFunc::LibertyFunc(const char *expr, LibertyFunc::LibertyFunc(const char *expr,

View File

@ -359,6 +359,7 @@ public:
virtual void beginFallPower(LibertyGroup *group); virtual void beginFallPower(LibertyGroup *group);
virtual void beginRisePower(LibertyGroup *group); virtual void beginRisePower(LibertyGroup *group);
virtual void endRiseFallPower(LibertyGroup *group); virtual void endRiseFallPower(LibertyGroup *group);
virtual void visitRelatedGroundPin(LibertyAttr *attr);
virtual void visitRelatedPowerPin(LibertyAttr *attr); virtual void visitRelatedPowerPin(LibertyAttr *attr);
virtual void visitRelatedPgPin(LibertyAttr *attr); virtual void visitRelatedPgPin(LibertyAttr *attr);
virtual void makeInternalPowers(LibertyPort *port, virtual void makeInternalPowers(LibertyPort *port,
@ -389,6 +390,12 @@ public:
virtual void endOcvSigmaTransition(LibertyGroup *group); virtual void endOcvSigmaTransition(LibertyGroup *group);
virtual void visitSigmaType(LibertyAttr *attr); virtual void visitSigmaType(LibertyAttr *attr);
// PgPin group.
virtual void beginPgPin(LibertyGroup *group);
virtual void endPgPin(LibertyGroup *group);
virtual void visitPgType(LibertyAttr *attr);
virtual void visitVoltageName(LibertyAttr *attr);
// Visitors for derived classes to overload. // Visitors for derived classes to overload.
virtual void beginGroup1(LibertyGroup *) {} virtual void beginGroup1(LibertyGroup *) {}
virtual void beginGroup2(LibertyGroup *) {} virtual void beginGroup2(LibertyGroup *) {}
@ -533,6 +540,7 @@ protected:
EarlyLateAll *derate_type_; EarlyLateAll *derate_type_;
EarlyLateAll *sigma_type_; EarlyLateAll *sigma_type_;
PathType path_type_; PathType path_type_;
LibertyPgPort *pg_port_;
ScaleFactorType scale_factor_type_; ScaleFactorType scale_factor_type_;
TableAxis *axis_[3]; TableAxis *axis_[3];
bool own_axis_[3]; bool own_axis_[3];

View File

@ -888,6 +888,7 @@ ConcreteParasitics::clear()
} }
} }
delete lumped_elmore_maps_; delete lumped_elmore_maps_;
lumped_elmore_maps_ = NULL;
} }
if (pi_elmore_maps_) { if (pi_elmore_maps_) {
@ -902,6 +903,7 @@ ConcreteParasitics::clear()
} }
} }
delete pi_elmore_maps_; delete pi_elmore_maps_;
pi_elmore_maps_ = NULL;
} }
if (pi_pole_residue_maps_) { if (pi_pole_residue_maps_) {
@ -916,6 +918,7 @@ ConcreteParasitics::clear()
} }
} }
delete pi_pole_residue_maps_; delete pi_pole_residue_maps_;
pi_pole_residue_maps_ = NULL;
} }
if (parasitic_network_maps_) { if (parasitic_network_maps_) {
@ -930,6 +933,7 @@ ConcreteParasitics::clear()
} }
} }
delete parasitic_network_maps_; delete parasitic_network_maps_;
parasitic_network_maps_ = NULL;
} }
} }

View File

@ -25,8 +25,6 @@
namespace sta { namespace sta {
typedef Vector<PathRef> PathRefSeq;
class PathExpanded class PathExpanded
{ {
public: public:

View File

@ -112,6 +112,7 @@ typedef UnorderedMap<Tag*, int, TagMatchHash, TagMatchEqual> ArrivalMap;
typedef Vector<PathVertex> PathVertexSeq; typedef Vector<PathVertex> PathVertexSeq;
typedef Vector<Slack> SlackSeq; typedef Vector<Slack> SlackSeq;
typedef Delay Crpr; typedef Delay Crpr;
typedef Vector<PathRef> PathRefSeq;
typedef enum { typedef enum {
report_path_full, report_path_full,

View File

@ -119,9 +119,9 @@ DdNode *
Sim::funcBdd(const FuncExpr *expr, Sim::funcBdd(const FuncExpr *expr,
const Instance *inst) const const Instance *inst) const
{ {
DdNode *left = 0; DdNode *left = NULL;
DdNode *right = 0; DdNode *right = NULL;
DdNode *result = 0; DdNode *result = NULL;
switch (expr->op()) { switch (expr->op()) {
case FuncExpr::op_port: { case FuncExpr::op_port: {
LibertyPort *port = expr->port(); LibertyPort *port = expr->port();

View File

@ -4622,9 +4622,20 @@ Sta::crossesHierarchy(Edge *edge) const
{ {
Vertex *from = edge->from(graph_); Vertex *from = edge->from(graph_);
Vertex *to = edge->to(graph_); Vertex *to = edge->to(graph_);
Instance *from_inst = network_->instance(from->pin()); const Pin *from_pin = from->pin();
Instance *from_inst = network_->instance(from_pin);
Instance *to_inst = network_->instance(to->pin()); Instance *to_inst = network_->instance(to->pin());
return network_->parent(from_inst) != network_->parent(to_inst); Instance *from_parent, *to_parent;
// Treat input/output port pins as "inside".
if (network_->isTopInstance(from_inst))
from_parent = from_inst;
else
from_parent = network_->parent(from_inst);
if (network_->isTopInstance(to_inst))
to_parent = to_inst;
else
to_parent = network_->parent(to_inst);
return from_parent != to_parent;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -1797,17 +1797,6 @@ using namespace sta;
Tcl_SetObjResult(interp, obj); Tcl_SetObjResult(interp, obj);
} }
%typemap(in) Path* {
void *obj;
SWIG_ConvertPtr($input, &obj, $1_descriptor, false);
$1 = reinterpret_cast<Path*>(obj);
}
%typemap(out) Path* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) PathRefSeq* { %typemap(out) PathRefSeq* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false); Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj); Tcl_SetObjResult(interp, obj);
@ -1817,7 +1806,8 @@ using namespace sta;
PathRefSeq::Iterator path_iter(paths); PathRefSeq::Iterator path_iter(paths);
while (path_iter.hasNext()) { while (path_iter.hasNext()) {
PathRef *path = &path_iter.next(); PathRef *path = &path_iter.next();
Tcl_Obj *obj = SWIG_NewInstanceObj(path, SWIGTYPE_p_PathRef, false); PathRef *copy = new PathRef(path);
Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_PathRef, false);
Tcl_ListObjAppendElement(interp, list, obj); Tcl_ListObjAppendElement(interp, list, obj);
} }
delete paths; delete paths;
@ -4509,7 +4499,7 @@ remove_constraints()
} }
void void
report_path_cmd(Path *path) report_path_cmd(PathRef *path)
{ {
Sta::sta()->reportPath(path); Sta::sta()->reportPath(path);
} }
@ -6311,10 +6301,9 @@ points()
Sta *sta = Sta::sta(); Sta *sta = Sta::sta();
PathExpanded expanded(self->path(), sta); PathExpanded expanded(self->path(), sta);
PathRefSeq *paths = new PathRefSeq; PathRefSeq *paths = new PathRefSeq;
for (int i = expanded.startIndex(); i < expanded.size(); i++) { for (auto i = expanded.startIndex(); i < expanded.size(); i++) {
PathRef *path = expanded.path(i); PathRef *path = expanded.path(i);
PathRef *copy = new PathRef(path); paths->push_back(*path);
paths->push_back(copy);
} }
return paths; return paths;
} }
@ -6371,6 +6360,13 @@ pins()
return pins; return pins;
} }
const char *
tag()
{
Sta *sta = Sta::sta();
return self->tag(sta)->asString(sta);
}
} }
%extend VertexPathIterator { %extend VertexPathIterator {

View File

@ -120,7 +120,7 @@ proc proc_redirect { proc_name body } {
"set redirect \[parse_redirect_args args\];" \ "set redirect \[parse_redirect_args args\];" \
"set code \[catch {" $body "} ret \];" \ "set code \[catch {" $body "} ret \];" \
"if {\$redirect} { redirect_file_end };" \ "if {\$redirect} { redirect_file_end };" \
"if {\$code != 0} {return -code error -errorcode \$errorCode -errorinfo \$errorInfo} else {return \$ret} }" ] "if {\$code == 1} {return -code \$code -errorcode \$errorCode -errorinfo \$errorInfo \$ret} else {return \$ret} }" ]
eval $proc_body eval $proc_body
} }