diff --git a/CMakeLists.txt b/CMakeLists.txt
index 269a14fa..202733b7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,22 +1,14 @@
-# OpenSTA, Static Timing Analyzer
+# Parallax Static Timing Analyzer
# Copyright (c) 2019, Parallax Software, Inc.
+# All rights reserved.
#
-# 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 .
+# No part of this document may be copied, transmitted or
+# disclosed in any form or fashion without the express
+# written consent of Parallax Software, Inc.
cmake_minimum_required (VERSION 3.9)
-project(STA VERSION 2.0.4)
+project(STA VERSION 2.0.5)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_STANDARD 11)
@@ -113,19 +105,12 @@ set(STA_SOURCE
parasitics/EstimateParasitics.cc
parasitics/NullParasitics.cc
parasitics/Parasitics.cc
- parasitics/ReadParasitics.cc
parasitics/ReduceParasitics.cc
parasitics/SpefLex.cc
parasitics/SpefNamespace.cc
parasitics/SpefParse.cc
parasitics/SpefReader.cc
parasitics/SpefReaderPvt.hh
- parasitics/SpfLex.cc
- parasitics/SpfParse.cc
- parasitics/SpfReader.cc
- parasitics/SpfReaderPvt.hh
- parasitics/SpfSpefReader.cc
- parasitics/SpfSpefReader.cc
sdc/Clock.cc
sdc/ClockGatingCheck.cc
@@ -288,11 +273,9 @@ set(STA_HEADERS
parasitics/NullParasitics.hh
parasitics/Parasitics.hh
parasitics/ParasiticsClass.hh
- parasitics/ReadParasitics.hh
parasitics/ReduceParasitics.hh
parasitics/SpefNamespace.hh
parasitics/SpefReader.hh
- parasitics/SpfReader.hh
sdc/Clock.hh
sdc/ClockGatingCheck.hh
@@ -597,19 +580,6 @@ flex_target(SpefLex parasitics/SpefLex.ll ${STA_HOME}/parasitics/SpefLex.cc
add_flex_bison_dependency(SpefLex SpefParser)
-# Spf scan/parse.
-bison_target(SpfParser parasitics/SpfParse.yy ${STA_HOME}/parasitics/SpfParse.cc
- DEFINES_FILE ${STA_HOME}/parasitics/SpfParse.hh
- COMPILE_FLAGS --name-prefix=SpfParse_
- )
-
-flex_target(SpfLex parasitics/SpfLex.ll ${STA_HOME}/parasitics/SpfLex.cc
- DEFINES_FILE ${STA_HOME}/parasitics/SpfLex.hh
- COMPILE_FLAGS --prefix=SpfLex_
- )
-
-add_flex_bison_dependency(SpfLex SpfParser)
-
# Verilog scan/parse.
bison_target(VerilogParser verilog/VerilogParse.yy ${STA_HOME}/verilog/VerilogParse.cc
DEFINES_FILE ${STA_HOME}/verilog/VerilogParse.hh
diff --git a/INSTALL b/INSTALL
index 24ee7769..c293f50e 100644
--- a/INSTALL
+++ b/INSTALL
@@ -49,6 +49,16 @@ Note that the file hierarchy of the CUDD installation changed with
version 3.0. This build only supports the 3.0 layout but only small
changes to configure.ac are required to support older versions.
+ cd $HOME/cudd-3.0.0
+ mkdir $HOME/cudd
+ ./configure --prefix $HOME/cudd
+ make
+ make install
+
+And then pass the install directory to cmake before building OpenSTA.
+
+ cmake .. -DCUDD=$HOME/cudd
+
The Zlib library is an optional. If the configure script finds libz,
OpenSTA can read Verilog, SDF, SPF, and SPEF files compressed with
gzip.
@@ -70,8 +80,10 @@ Optional cmake variables passed as -D= arguments to cmake
are show below.
CMAKE_BUILD_TYPE DEBUG|RELEASE
+ CMAKE_CXX_FLAGS - additional compiler flags
TCL_LIB - path to tcl library
TCL_HEADER - path to tcl.h
+ ZLIB_ROOT - path to zlib
CMAKE_INSTALL_PREFIX
If TCL_LIB is specified the cmake script will attempt to locate the
@@ -86,6 +98,10 @@ or use the DESTDIR variable with make.
make DESTDIR= install
+If you make changes to CMakeLists.txt you may need to clean out
+existing cmake cached variable values by deleting all of the
+files in the build directory.
+
Building from a tarfile
-----------------------
diff --git a/app/StaMain.cc b/app/StaMain.cc
index 17c738c7..8b38b4f3 100644
--- a/app/StaMain.cc
+++ b/app/StaMain.cc
@@ -188,11 +188,9 @@ static void
sourceTclFileEchoVerbose(const char *filename,
Tcl_Interp *interp)
{
- const char *source_cmd = "source -echo -verbose ";
- size_t cmd_length = strlen(source_cmd) + strlen(filename) + 1;
- char *cmd = stringPrint(cmd_length, "%s%s", source_cmd, filename);
- Tcl_Eval(interp, cmd);
- delete [] cmd;
+ string cmd;
+ stringPrint(cmd, "source -echo -verbose %s", filename);
+ Tcl_Eval(interp, cmd.c_str());
}
void
diff --git a/configure.ac b/configure.ac
index f11b57c3..c68f8ba4 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.4)
+AC_INIT(sta, 2.0.5)
AM_INIT_AUTOMAKE
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS(config.h)
diff --git a/dcalc/DelayCalc.tcl b/dcalc/DelayCalc.tcl
index ea8064ca..beaca5bc 100644
--- a/dcalc/DelayCalc.tcl
+++ b/dcalc/DelayCalc.tcl
@@ -82,17 +82,17 @@ proc report_edge_dcalc { edge corner min_max digits } {
# Filter timing checks based on min_max.
if {!(($min_max == "max" && $role == "hold") \
|| ($min_max=="min" && $role=="setup"))} {
- puts "Library: [$library name]"
- puts "Cell: [$cell name]"
+ puts "Library: [get_name $library]"
+ puts "Cell: [get_name $cell]"
puts "Arc sense: [$edge sense]"
puts "Arc type: $role"
set arc_iter [$edge timing_arc_iterator]
while {[$arc_iter has_next]} {
set arc [$arc_iter next]
- set from [[$from_pin port] name]
+ set from [get_name [$from_pin port]]
set from_tr [$arc from_trans]
- set to [[$to_pin port] name]
+ set to [get_name [$to_pin port]]
set to_tr [$arc to_trans]
puts "$from $from_tr -> $to $to_tr"
puts -nonewline [report_delay_calc_cmd $edge $arc $corner $min_max $digits]
diff --git a/doc/OpenSTA.odt b/doc/OpenSTA.odt
index 3ab8edb4..fa4e5b19 100644
Binary files a/doc/OpenSTA.odt and b/doc/OpenSTA.odt differ
diff --git a/doc/OpenSTA.pdf b/doc/OpenSTA.pdf
index d80c07d5..6b243d1a 100644
Binary files a/doc/OpenSTA.pdf and b/doc/OpenSTA.pdf differ
diff --git a/graph/DelayNormal2.cc b/graph/DelayNormal2.cc
index ac40a05c..4b2755c6 100644
--- a/graph/DelayNormal2.cc
+++ b/graph/DelayNormal2.cc
@@ -416,13 +416,11 @@ delayAsString(const Delay &delay,
float sigma_early = delay.sigma(EarlyLate::early());
float sigma_late = delay.sigma(EarlyLate::late());
if (fuzzyEqual(sigma_early, sigma_late))
- return stringPrintTmp((digits + 4) * 2 + 2,
- "%s|%s",
+ return stringPrintTmp("%s|%s",
unit->asString(delay.mean(), digits),
unit->asString(sigma_early, digits));
else
- return stringPrintTmp((digits + 4) * 3 + 3,
- "%s|%s:%s",
+ return stringPrintTmp("%s|%s:%s",
unit->asString(delay.mean(), digits),
unit->asString(sigma_early, digits),
unit->asString(sigma_late, digits));
diff --git a/graph/Graph.cc b/graph/Graph.cc
index b6222c9d..f83075d5 100644
--- a/graph/Graph.cc
+++ b/graph/Graph.cc
@@ -1169,8 +1169,7 @@ Vertex::name(const Network *network) const
{
if (network->direction(pin_)->isBidirect()) {
const char *pin_name = network->pathName(pin_);
- int result_len = strlen(pin_name) + strlen("driver") + 2;
- return stringPrintTmp(result_len, "%s %s",
+ return stringPrintTmp("%s %s",
pin_name,
is_bidirect_drvr_ ? "driver" : "load");
}
diff --git a/liberty/Liberty.hh b/liberty/Liberty.hh
index baaf07ae..16f24c19 100644
--- a/liberty/Liberty.hh
+++ b/liberty/Liberty.hh
@@ -385,7 +385,7 @@ public:
const char *name,
const char *filename);
virtual ~LibertyCell();
- const LibertyLibrary *libertyLibrary() const { return liberty_library_; }
+ LibertyLibrary *libertyLibrary() const { return liberty_library_; }
LibertyLibrary *libertyLibrary() { return liberty_library_; }
LibertyPort *findLibertyPort(const char *name) const;
void findLibertyPortsMatching(PatternMatch *pattern,
diff --git a/liberty/LibertyBuilder.cc b/liberty/LibertyBuilder.cc
index 31dd2e0e..b6f145e6 100644
--- a/liberty/LibertyBuilder.cc
+++ b/liberty/LibertyBuilder.cc
@@ -84,7 +84,7 @@ LibertyBuilder::makeBusPortBit(ConcreteLibrary *library,
const char *bus_name,
int bit_index)
{
- char *bit_name = stringPrintTmp(strlen(bus_name) + 6, "%s%c%d%c",
+ char *bit_name = stringPrintTmp("%s%c%d%c",
bus_name,
library->busBrktLeft(),
bit_index,
diff --git a/liberty/LibertyParse.yy b/liberty/LibertyParse.yy
index 109035cd..8047d84b 100644
--- a/liberty/LibertyParse.yy
+++ b/liberty/LibertyParse.yy
@@ -107,7 +107,7 @@ simple_attr_value:
/* Unquoted NOT function. */
/* clocked_on : !CP; */
| '!' string
- { $$ = sta::makeLibertyStringAttrValue(sta::stringPrint(strlen($2)+1, "!%s", $2)); sta::stringDelete($2); }
+ { $$ = sta::makeLibertyStringAttrValue(sta::stringPrint("!%s", $2)); sta::stringDelete($2); }
;
complex_attr:
diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc
index 13722a79..f4057f7b 100644
--- a/liberty/LibertyReader.cc
+++ b/liberty/LibertyReader.cc
@@ -461,11 +461,7 @@ LibertyReader::defineScalingFactorVisitors()
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
const char *tr_name = (tr == TransRiseFall::rise()) ? "rise":"fall";
- const char *attr_name = stringPrintTmp(strlen(pvt_name)
- + strlen(type_name)
- + strlen(tr_name)
- + 5, // k___\0
- "k_%s_%s_%s",
+ const char *attr_name = stringPrintTmp("k_%s_%s_%s",
pvt_name,
type_name,
tr_name);
@@ -477,11 +473,7 @@ LibertyReader::defineScalingFactorVisitors()
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
const char *tr_name = (tr == TransRiseFall::rise()) ? "rise":"fall";
- const char *attr_name = stringPrintTmp(strlen(pvt_name)
- + strlen(type_name)
- + strlen(tr_name)
- + 5, // k___\0
- "k_%s_%s_%s",
+ const char *attr_name = stringPrintTmp("k_%s_%s_%s",
pvt_name,
tr_name,
type_name);
@@ -493,11 +485,7 @@ LibertyReader::defineScalingFactorVisitors()
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
const char *tr_name = (tr == TransRiseFall::rise()) ? "high":"low";
- const char *attr_name = stringPrintTmp(strlen(pvt_name)
- + strlen(type_name)
- + strlen(tr_name)
- + 5, // k___\0
- "k_%s_%s_%s",
+ const char *attr_name = stringPrintTmp("k_%s_%s_%s",
pvt_name,
tr_name,
type_name);
@@ -505,10 +493,7 @@ LibertyReader::defineScalingFactorVisitors()
}
}
else {
- const char *attr_name = stringPrintTmp(strlen(pvt_name)
- + strlen(type_name)
- + 4, // k__\0
- "k_%s_%s",
+ const char *attr_name = stringPrintTmp("k_%s_%s",
pvt_name,
type_name);
defineAttrVisitor(attr_name,&LibertyReader::visitScaleFactor);
@@ -4327,12 +4312,7 @@ LibertyReader::parseFunc(const char *func,
const char *attr_name,
int line)
{
- const char *error_msg = stringPrintTmp(strlen(filename_)
- + strlen(", line ")
- + 8
- + strlen(attr_name)
- + 2,
- "%s, line %d %s",
+ const char *error_msg = stringPrintTmp("%s, line %d %s",
filename_,
line,
attr_name);
@@ -5221,8 +5201,7 @@ PortNameBitIterator::findRangeBusNameNext()
? range_bit_ >= range_to_
: range_bit_ <= range_to_) {
LibertyLibrary *library = visitor_->library();
- const char *bus_bit_name = stringPrintTmp(strlen(range_bus_name_) + 10,
- "%s%c%d%c",
+ const char *bus_bit_name = stringPrintTmp("%s%c%d%c",
range_bus_name_,
library->busBrktLeft(),
range_bit_,
diff --git a/liberty/TableModel.cc b/liberty/TableModel.cc
index 3292c1eb..64a8e572 100644
--- a/liberty/TableModel.cc
+++ b/liberty/TableModel.cc
@@ -592,14 +592,12 @@ reportPvt(const LibertyLibrary *library,
if (pvt == NULL)
pvt = library->defaultOperatingConditions();
if (pvt) {
- const char *pvt_str = stringPrint(strlen("P = %.*f V = %.*f T = %.*f\n")
- + (digits + 10) * 3 + 1,
- "P = %.*f V = %.*f T = %.*f\n",
- digits, pvt->process(),
- digits, pvt->voltage(),
- digits, pvt->temperature());
+ string pvt_str;
+ stringPrint(pvt_str, "P = %.*f V = %.*f T = %.*f\n",
+ digits, pvt->process(),
+ digits, pvt->voltage(),
+ digits, pvt->temperature());
*result += pvt_str;
- stringDelete(pvt_str);
}
}
@@ -613,13 +611,11 @@ TableModel::reportPvtScaleFactor(const LibertyLibrary *library,
if (pvt == NULL)
pvt = library->defaultOperatingConditions();
if (pvt) {
- const char *scale_str = stringPrint(strlen("PVT scale factor = %.*f\n")
- + digits + 10 + 1,
- "PVT scale factor = %.*f\n",
- digits,
- scaleFactor(library, cell, pvt));
+ string scale_str;
+ stringPrint(scale_str, "PVT scale factor = %.*f\n",
+ digits,
+ scaleFactor(library, cell, pvt));
*result += scale_str;
- stringDelete(scale_str);
}
}
diff --git a/liberty/Units.cc b/liberty/Units.cc
index 9eb7ede5..ae253926 100644
--- a/liberty/Units.cc
+++ b/liberty/Units.cc
@@ -106,9 +106,7 @@ Unit::asString(float value,
// prevent "-0.00" on slowaris
if (abs(scaled_value) < 1E-6)
scaled_value = 0.0;
- // Leave room for sign, E+-exponent.
- const int result_len = std::numeric_limits::digits10 + 10;
- return stringPrintTmp(result_len, "%.*f%s", digits, scaled_value, suffix_);
+ return stringPrintTmp("%.*f%s", digits, scaled_value, suffix_);
}
}
diff --git a/network/ConcreteLibrary.cc b/network/ConcreteLibrary.cc
index 0326090c..708904c7 100644
--- a/network/ConcreteLibrary.cc
+++ b/network/ConcreteLibrary.cc
@@ -41,7 +41,9 @@ ConcreteLibrary::~ConcreteLibrary()
}
ConcreteCell *
-ConcreteLibrary::makeCell(const char *name, bool is_leaf, const char *filename)
+ConcreteLibrary::makeCell(const char *name,
+ bool is_leaf,
+ const char *filename)
{
ConcreteCell *cell = new ConcreteCell(this, name, is_leaf, filename);
addCell(cell);
@@ -55,7 +57,8 @@ ConcreteLibrary::addCell(ConcreteCell *cell)
}
void
-ConcreteLibrary::renameCell(ConcreteCell *cell, const char *cell_name)
+ConcreteLibrary::renameCell(ConcreteCell *cell,
+ const char *cell_name)
{
cell_map_.eraseKey(cell->name());
cell_map_[cell_name] = cell;
@@ -93,7 +96,8 @@ ConcreteLibrary::findCellsMatching(const PatternMatch *pattern,
}
void
-ConcreteLibrary::setBusBrkts(char left, char right)
+ConcreteLibrary::setBusBrkts(char left,
+ char right)
{
bus_brkt_left_ = left;
bus_brkt_right_ = right;
@@ -101,8 +105,10 @@ ConcreteLibrary::setBusBrkts(char left, char right)
////////////////////////////////////////////////////////////////
-ConcreteCell::ConcreteCell(ConcreteLibrary *library, const char *name,
- bool is_leaf, const char *filename):
+ConcreteCell::ConcreteCell(ConcreteLibrary *library,
+ const char *name,
+ bool is_leaf,
+ const char *filename):
library_(library),
name_(stringCopy(name)),
filename_(stringCopy(filename)),
@@ -137,7 +143,8 @@ ConcreteCell::makePort(const char *name)
}
ConcretePort *
-ConcreteCell::makeBundlePort(const char *name, ConcretePortSeq *members)
+ConcreteCell::makeBundlePort(const char *name,
+ ConcretePortSeq *members)
{
ConcretePort *port = new ConcretePort(this, name, false, -1, -1,
true, members);
@@ -146,7 +153,9 @@ ConcreteCell::makeBundlePort(const char *name, ConcretePortSeq *members)
}
ConcretePort *
-ConcreteCell::makeBusPort(const char *name, int from_index, int to_index)
+ConcreteCell::makeBusPort(const char *name,
+ int from_index,
+ int to_index)
{
ConcretePort *port = new ConcretePort(this, name, true, from_index, to_index,
false, new ConcretePortSeq);
@@ -156,7 +165,9 @@ ConcreteCell::makeBusPort(const char *name, int from_index, int to_index)
}
ConcretePort *
-ConcreteCell::makeBusPort(const char *name, int from_index, int to_index,
+ConcreteCell::makeBusPort(const char *name,
+ int from_index,
+ int to_index,
ConcretePortSeq *members)
{
ConcretePort *port = new ConcretePort(this, name, true, from_index, to_index,
@@ -166,8 +177,10 @@ ConcreteCell::makeBusPort(const char *name, int from_index, int to_index,
}
void
-ConcreteCell::makeBusPortBits(ConcretePort *bus_port, const char *name,
- int from_index, int to_index)
+ConcreteCell::makeBusPortBits(ConcretePort *bus_port,
+ const char *name,
+ int from_index,
+ int to_index)
{
if (from_index < to_index) {
for (int index = from_index; index <= to_index; index++)
@@ -180,21 +193,24 @@ ConcreteCell::makeBusPortBits(ConcretePort *bus_port, const char *name,
}
void
-ConcreteCell::makeBusPortBit(ConcretePort *bus_port, const char *bus_name,
+ConcreteCell::makeBusPortBit(ConcretePort *bus_port,
+ const char *bus_name,
int bit_index)
{
- char *bit_name = stringPrintTmp(strlen(bus_name) + 8, "%s%c%d%c",
- bus_name,
- library_->busBrktLeft(),
- bit_index,
- library_->busBrktRight());
- ConcretePort *port = makePort(bit_name, bit_index);
+ string bit_name;
+ stringPrint(bit_name, "%s%c%d%c",
+ bus_name,
+ library_->busBrktLeft(),
+ bit_index,
+ library_->busBrktRight());
+ ConcretePort *port = makePort(bit_name.c_str(), bit_index);
bus_port->addPortBit(port);
addPortBit(port);
}
ConcretePort *
-ConcreteCell::makePort(const char *bit_name, int bit_index)
+ConcreteCell::makePort(const char *bit_name,
+ int bit_index)
{
ConcretePort *port = new ConcretePort(this, bit_name, false, bit_index,
bit_index, false, NULL);
@@ -278,7 +294,9 @@ ConcreteCell::portBitIterator() const
class BusPort
{
public:
- BusPort(const char *name, int from, PortDirection *direction);
+ BusPort(const char *name,
+ int from,
+ PortDirection *direction);
~BusPort();
const char *name() const { return name_; }
void pushMember(ConcretePort *port);
@@ -298,7 +316,9 @@ private:
ConcretePortSeq *members_;
};
-BusPort::BusPort(const char *name, int from, PortDirection *direction) :
+BusPort::BusPort(const char *name,
+ int from,
+ PortDirection *direction) :
name_(name),
from_(from),
to_(from),
@@ -392,9 +412,13 @@ ConcreteCell::groupBusPorts(const char *bus_brkts_left,
////////////////////////////////////////////////////////////////
-ConcretePort::ConcretePort(ConcreteCell *cell, const char *name,
- bool is_bus, int from_index, int to_index,
- bool is_bundle, ConcretePortSeq *member_ports) :
+ConcretePort::ConcretePort(ConcreteCell *cell,
+ const char *name,
+ bool is_bus,
+ int from_index,
+ int to_index,
+ bool is_bundle,
+ ConcretePortSeq *member_ports) :
name_(stringCopy(name)),
cell_(cell),
direction_(PortDirection::unknown()),
@@ -428,8 +452,7 @@ ConcretePort::busName() const
{
if (is_bus_) {
ConcreteLibrary *lib = cell_->library();
- return stringPrintTmp(strlen(name_) + 10,
- "%s%c%d:%d%c",
+ return stringPrintTmp("%s%c%d:%d%c",
name_,
lib->busBrktLeft(),
from_index_,
diff --git a/network/ConcreteLibrary.hh b/network/ConcreteLibrary.hh
index 06903f45..d929f702 100644
--- a/network/ConcreteLibrary.hh
+++ b/network/ConcreteLibrary.hh
@@ -52,7 +52,8 @@ public:
void setName(const char *name);
virtual const char *filename() const { return filename_; }
void addCell(ConcreteCell *cell);
- virtual ConcreteCell *makeCell(const char *name, bool is_leaf,
+ virtual ConcreteCell *makeCell(const char *name,
+ bool is_leaf,
const char *filename);
void deleteCell(ConcreteCell *cell);
ConcreteLibraryCellIterator *cellIterator() const;
@@ -61,10 +62,12 @@ public:
CellSeq *cells) const;
virtual char busBrktLeft() { return bus_brkt_left_; }
virtual char busBrktRight() { return bus_brkt_right_; }
- void setBusBrkts(char left, char right);
+ void setBusBrkts(char left,
+ char right);
protected:
- void renameCell(ConcreteCell *cell, const char *cell_name);
+ void renameCell(ConcreteCell *cell,
+ const char *cell_name);
const char *name_;
const char *filename_;
@@ -98,26 +101,39 @@ public:
// Cell acts as port factory.
ConcretePort *makePort(const char *name);
// Bus port.
- ConcretePort *makeBusPort(const char *name, int from_index, int to_index);
+ ConcretePort *makeBusPort(const char *name,
+ int from_index,
+ int to_index);
// Bundle port.
- ConcretePort *makeBundlePort(const char *name, ConcretePortSeq *members);
+ ConcretePort *makeBundlePort(const char *name,
+ ConcretePortSeq *members);
// Group previously defined bus bit ports together.
- void groupBusPorts(const char *bus_brkts_left, const char *bus_brkts_right);
+ void groupBusPorts(const char *bus_brkts_left,
+ const char *bus_brkts_right);
size_t portCount() const;
void setName(const char *name);
virtual void addPort(ConcretePort *port);
void addPortBit(ConcretePort *port);
protected:
- ConcreteCell(ConcreteLibrary *library, const char *name,
- bool is_leaf, const char *filename);
- ConcretePort *makeBusPort(const char *name, int from_index, int to_index,
+ ConcreteCell(ConcreteLibrary *library,
+ const char *name,
+ bool is_leaf,
+ const char *filename);
+ ConcretePort *makeBusPort(const char *name,
+ int from_index,
+ int to_index,
ConcretePortSeq *members);
- void makeBusPortBits(ConcretePort *bus_port, const char *name,
- int from_index, int to_index);
+ void makeBusPortBits(ConcretePort *bus_port,
+ const char *name,
+ int from_index,
+ int to_index);
// Bus port bit (internal to makeBusPortBits).
- virtual ConcretePort *makePort(const char *bit_name, int bit_index);
- void makeBusPortBit(ConcretePort *bus_port, const char *name, int index);
+ virtual ConcretePort *makePort(const char *bit_name,
+ int bit_index);
+ void makeBusPortBit(ConcretePort *bus_port,
+ const char *name,
+ int index);
ConcreteLibrary *library_;
const char *name_;
@@ -182,9 +198,13 @@ public:
protected:
// Constructors for factory in cell class.
- ConcretePort(ConcreteCell *cell, const char *name,
- bool is_bus, int from_index, int to_index,
- bool is_bundle, ConcretePortSeq *member_ports);
+ ConcretePort(ConcreteCell *cell,
+ const char *name,
+ bool is_bus,
+ int from_index,
+ int to_index,
+ bool is_bundle,
+ ConcretePortSeq *member_ports);
const char *name_;
ConcreteCell *cell_;
diff --git a/network/ConcreteNetwork.cc b/network/ConcreteNetwork.cc
index bdacfad8..e84d4736 100644
--- a/network/ConcreteNetwork.cc
+++ b/network/ConcreteNetwork.cc
@@ -1250,14 +1250,22 @@ ConcreteNetwork::connect(Instance *inst,
ConcreteNet *prev_net = cpin->net_;
if (prev_net)
disconnectNetPin(prev_net, cpin);
- cpin->net_ = cnet;
}
else {
cpin = new ConcretePin(cinst, cport, cnet);
cinst->addPin(cpin);
}
- if (cnet)
+ if (cinst == top_instance_) {
+ // makeTerm
+ ConcreteTerm *cterm = new ConcreteTerm(cpin, cnet);
+ cnet->addTerm(cterm);
+ cpin->term_ = cterm;
+ cpin->net_ = NULL;
+ }
+ else {
+ cpin->net_ = cnet;
connectNetPin(cnet, cpin);
+ }
return reinterpret_cast(cpin);
}
@@ -1288,13 +1296,15 @@ ConcreteNetwork::disconnectPin(Pin *pin)
ConcretePin *cpin = reinterpret_cast(pin);
if (cpin->instance() == top_instance_) {
ConcreteTerm *cterm = cpin->term_;
- ConcreteNet *cnet = cterm->net_;
- if (cnet) {
- cnet->deleteTerm(cterm);
- clearNetDrvPinrMap();
+ if (cterm) {
+ ConcreteNet *cnet = cterm->net_;
+ if (cnet) {
+ cnet->deleteTerm(cterm);
+ clearNetDrvPinrMap();
+ }
+ cpin->term_ = NULL;
+ delete cterm;
}
- cpin->term_ = NULL;
- delete cterm;
}
else {
ConcreteNet *cnet = cpin->net();
diff --git a/network/Network.cc b/network/Network.cc
index daa964e7..7961e279 100644
--- a/network/Network.cc
+++ b/network/Network.cc
@@ -901,17 +901,13 @@ Network::findInstPinsHierMatching(const Instance *instance,
PinSeq *pins) const
{
const char *inst_name = name(instance);
- size_t inst_length = strlen(inst_name);
InstancePinIterator *pin_iter = pinIterator(instance);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
const char *port_name = name(port(pin));
- const char *pin_name = stringPrintTmp(inst_length+strlen(port_name)+2,
- "%s%c%s",
- inst_name,
- divider_,
- port_name);
- if (pattern->match(pin_name))
+ string pin_name;
+ stringPrint(pin_name, "%s%c%s", inst_name,divider_, port_name);
+ if (pattern->match(pin_name.c_str()))
pins->push_back(pin);
}
delete pin_iter;
diff --git a/parasitics/ConcreteParasitics.cc b/parasitics/ConcreteParasitics.cc
index 6db058ba..8c800a43 100644
--- a/parasitics/ConcreteParasitics.cc
+++ b/parasitics/ConcreteParasitics.cc
@@ -528,8 +528,7 @@ const char *
ConcreteParasiticSubNode::name(const Network *network) const
{
const char *net_name = network->pathName(net_);
- return stringPrintTmp(strlen(net_name) + INT_DIGITS + 2,
- "%s:%d", net_name, id_);
+ return stringPrintTmp("%s:%d", net_name, id_);
}
////////////////////////////////////////////////////////////////
diff --git a/parasitics/Makefile.am b/parasitics/Makefile.am
index c6903c8b..9367e804 100644
--- a/parasitics/Makefile.am
+++ b/parasitics/Makefile.am
@@ -20,51 +20,31 @@ include_HEADERS = \
ConcreteParasitics.hh \
ConcreteParasiticsPvt.hh \
EstimateParasitics.hh \
- MakeConcreteParasitics.hh \
NullParasitics.hh \
Parasitics.hh \
ParasiticsClass.hh \
- ReadParasitics.hh \
ReduceParasitics.hh \
SpefNamespace.hh \
- SpefReader.hh \
- SpfReader.hh
+ SpefReader.hh
libparasitics_la_SOURCES = \
ConcreteParasitics.cc \
EstimateParasitics.cc \
NullParasitics.cc \
Parasitics.cc \
- ReadParasitics.cc \
ReduceParasitics.cc \
SpefLex.ll \
SpefNamespace.cc \
SpefParse.yy \
SpefReader.cc \
SpefReaderPvt.hh \
- SpfLex.ll \
- SpfParse.yy \
- SpfReader.cc \
- SpfReaderPvt.hh \
- SpfSpefReader.cc \
- SpfSpefReader.hh
-
-SpfLex.ll: SpfParse.hh
-
-SpfLex.cc: SpfLex.ll
- $(LEX) $(LFLAGS) -o SpfLex.cc --prefix=SpfLex_ --header-file=SpfLex.hh SpfLex.ll
+ SpfReaderPvt.hh
SpefLex.ll: SpefParse.hh
SpefLex.cc: SpefLex.ll
$(LEX) $(LFLAGS) -o SpefLex.cc --prefix=SpefLex_ --header-file=SpefLex.hh SpefLex.ll
-# Rules to support automake pre 1.12 that name header .h instead of .hh
-SpfParse.hh: SpfParse.cc
- if test -f SpfParse.h; then \
- cp SpfParse.h SpfParse.hh; \
- fi
-
SpefParse.hh: SpefParse.cc
if test -f SpefParse.h; then \
cp SpefParse.h SpefParse.hh; \
@@ -76,7 +56,6 @@ TCL_SRCS = \
EXTRA_DIST = \
$(TCL_SRCS) \
- SpfParse.hh \
SpefParse.hh
libs: $(lib_LTLIBRARIES)
diff --git a/parasitics/Parasitics.cc b/parasitics/Parasitics.cc
index a08d9f3c..54401d2c 100644
--- a/parasitics/Parasitics.cc
+++ b/parasitics/Parasitics.cc
@@ -51,8 +51,13 @@ Parasitics::findParasiticNet(const Pin *pin) const
Net *net = network_->net(pin);
// Pins on the top level instance may not have nets.
// Use the net connected to the pin's terminal.
- if (net == NULL && network_->isTopLevelPort(pin))
- net = network_->net(network_->term(pin));
+ if (net == NULL && network_->isTopLevelPort(pin)) {
+ Term *term = network_->term(pin);
+ if (term)
+ return network_->net(term);
+ else
+ return NULL;
+ }
if (net)
return network_->highestConnectedNet(net);
else
diff --git a/parasitics/Parasitics.i b/parasitics/Parasitics.i
index 3582afe4..9ecefbc9 100644
--- a/parasitics/Parasitics.i
+++ b/parasitics/Parasitics.i
@@ -34,24 +34,24 @@ using sta::TmpFloatSeq;
%inline %{
bool
-read_parasitics_cmd(const char *filename,
- Instance *instance,
- MinMaxAll *min_max,
- bool increment,
- bool pin_cap_included,
- bool keep_coupling_caps,
- float coupling_cap_factor,
- ReduceParasiticsTo reduce_to,
- bool delete_after_reduce,
- bool quiet,
- bool save)
+read_spef_cmd(const char *filename,
+ Instance *instance,
+ MinMaxAll *min_max,
+ bool increment,
+ bool pin_cap_included,
+ bool keep_coupling_caps,
+ float coupling_cap_factor,
+ ReduceParasiticsTo reduce_to,
+ bool delete_after_reduce,
+ bool quiet,
+ bool save)
{
cmdLinkedNetwork();
- return Sta::sta()->readParasitics(filename, instance, min_max,
- increment, pin_cap_included,
- keep_coupling_caps, coupling_cap_factor,
- reduce_to, delete_after_reduce,
- save, quiet);
+ return Sta::sta()->readSpef(filename, instance, min_max,
+ increment, pin_cap_included,
+ keep_coupling_caps, coupling_cap_factor,
+ reduce_to, delete_after_reduce,
+ save, quiet);
}
TmpFloatSeq *
diff --git a/parasitics/Parasitics.tcl b/parasitics/Parasitics.tcl
index f3c3d0fc..5f3e6309 100644
--- a/parasitics/Parasitics.tcl
+++ b/parasitics/Parasitics.tcl
@@ -16,7 +16,7 @@
namespace eval sta {
-define_cmd_args "read_parasitics" \
+define_cmd_args "read_spef" \
{[-min]\
[-max]\
[-elmore]\
@@ -31,14 +31,13 @@ define_cmd_args "read_parasitics" \
[-save]\
filename}
-proc_redirect read_parasitics {
- # The -elmore flag is required by dc.
- parse_key_args "read_parasitics" args \
+proc_redirect read_spef {
+ parse_key_args "read_spef" args \
keys {-path -coupling_reduction_factor -reduce_to} \
flags {-min -max -elmore -increment -pin_cap_included \
-keep_capacitive_coupling \
-delete_after_reduce -quiet -save}
- check_argc_eq1 "report_parasitics" $args
+ check_argc_eq1 "report_spef" $args
set instance [top_instance]
if [info exists keys(-path)] {
@@ -69,7 +68,7 @@ proc_redirect read_parasitics {
set quiet [info exists flags(-quiet)]
set save [info exists flags(-save)]
set filename $args
- return [read_parasitics_cmd $filename $instance $min_max $increment \
+ return [read_spef_cmd $filename $instance $min_max $increment \
$pin_cap_included $keep_coupling_caps $coupling_reduction_factor \
$reduce_to $delete_after_reduce \
$save $quiet]
diff --git a/parasitics/SpefLex.ll b/parasitics/SpefLex.ll
index bca213fb..8daebbed 100644
--- a/parasitics/SpefLex.ll
+++ b/parasitics/SpefLex.ll
@@ -91,6 +91,7 @@ INDEX "*"{POS_INTEGER}
"*CELL" { return CELL; }
"*CONN" { return CONN; }
"*C_UNIT" { return C_UNIT; }
+"*SPEF" { return SPEF; }
"*DATE" { return DATE; }
"*DEFINE" { return DEFINE; }
"*DELIMITER" { return DELIMITER; }
diff --git a/parasitics/SpefParse.yy b/parasitics/SpefParse.yy
index b05aa15a..100796a1 100755
--- a/parasitics/SpefParse.yy
+++ b/parasitics/SpefParse.yy
@@ -42,7 +42,7 @@ int SpefLex_lex();
sta::Net *net;
}
-%token DESIGN DATE VENDOR PROGRAM DESIGN_FLOW
+%token SPEF DESIGN DATE VENDOR PROGRAM DESIGN_FLOW
%token PVERSION DIVIDER DELIMITER
%token BUS_DELIMITER T_UNIT C_UNIT R_UNIT L_UNIT NAME_MAP
%token POWER_NETS GROUND_NETS KW_C KW_L KW_S KW_D KW_V
@@ -142,6 +142,7 @@ hchar:
/****************************************************************/
header_def:
+ spef_version
design_name
date
vendor
@@ -154,6 +155,11 @@ header_def:
unit_def
;
+spef_version:
+ SPEF QSTRING
+ { sta::stringDelete($2); }
+;
+
design_name:
DESIGN QSTRING
{ sta::stringDelete($2); }
diff --git a/parasitics/SpefReader.cc b/parasitics/SpefReader.cc
index 337b80d5..1c65a667 100644
--- a/parasitics/SpefReader.cc
+++ b/parasitics/SpefReader.cc
@@ -17,14 +17,18 @@
#include
#include "Machine.hh"
#include "Zlib.hh"
+#include "Report.hh"
#include "Debug.hh"
#include "StringUtil.hh"
#include "Map.hh"
#include "PortDirection.hh"
#include "Transition.hh"
#include "Network.hh"
+#include "Liberty.hh"
+#include "Sdc.hh"
#include "Parasitics.hh"
#include "SpefReaderPvt.hh"
+#include "SpefNamespace.hh"
#include "SpefReader.hh"
int
@@ -38,8 +42,6 @@ SpefReader *spef_reader;
bool
readSpefFile(const char *filename,
- gzFile stream,
- int line,
Instance *instance,
ParasiticAnalysisPt *ap,
bool increment,
@@ -57,14 +59,22 @@ readSpefFile(const char *filename,
Network *network,
Parasitics *parasitics)
{
- SpefReader reader(filename, stream, line, instance, ap, increment,
- pin_cap_included, keep_coupling_caps, coupling_cap_factor,
- reduce_to, delete_after_reduce, op_cond, corner,
- cnst_min_max, quiet, report, network, parasitics);
- spef_reader = &reader;
- ::spefResetScanner();
- // yyparse returns 0 on success.
- bool success = (::SpefParse_parse() == 0);
+ bool success = false;
+ // Use zlib to uncompress gzip'd files automagically.
+ gzFile stream = gzopen(filename, "rb");
+ if (stream) {
+ SpefReader reader(filename, stream, instance, ap, increment,
+ pin_cap_included, keep_coupling_caps, coupling_cap_factor,
+ reduce_to, delete_after_reduce, op_cond, corner,
+ cnst_min_max, quiet, report, network, parasitics);
+ spef_reader = &reader;
+ ::spefResetScanner();
+ // yyparse returns 0 on success.
+ success = (::SpefParse_parse() == 0);
+ gzclose(stream);
+ }
+ else
+ throw FileNotReadable(filename);
if (success && save)
parasitics->save();
return success;
@@ -72,7 +82,6 @@ readSpefFile(const char *filename,
SpefReader::SpefReader(const char *filename,
gzFile stream,
- int line,
Instance *instance,
ParasiticAnalysisPt *ap,
bool increment,
@@ -88,16 +97,35 @@ SpefReader::SpefReader(const char *filename,
Report *report,
Network *network,
Parasitics *parasitics) :
- SpfSpefReader(filename, stream, line, instance, ap,
- increment, pin_cap_included,
- keep_coupling_caps, coupling_cap_factor,
- reduce_to, delete_after_reduce,
- op_cond, corner, cnst_min_max, quiet,
- report, network, parasitics),
+ filename_(filename),
+ instance_(instance),
+ ap_(ap),
+ increment_(increment),
+ pin_cap_included_(pin_cap_included),
+ keep_coupling_caps_(keep_coupling_caps),
+ reduce_to_(reduce_to),
+ delete_after_reduce_(delete_after_reduce),
+ op_cond_(op_cond),
+ corner_(corner),
+ cnst_min_max_(cnst_min_max),
+ keep_device_names_(false),
+ quiet_(quiet),
+ stream_(stream),
+ line_(1),
+ // defaults
+ divider_('\0'),
+ delimiter_('\0'),
+ bus_brkt_left_('\0'),
+ bus_brkt_right_('\0'),
+ net_(NULL),
+ report_(report),
+ network_(network),
+ parasitics_(parasitics),
triple_index_(0),
design_flow_(NULL),
parasitic_(NULL)
{
+ ap->setCouplingCapFactor(coupling_cap_factor);
}
SpefReader::~SpefReader()
@@ -117,6 +145,18 @@ SpefReader::~SpefReader()
}
}
+void
+SpefReader::setDivider(char divider)
+{
+ divider_ = divider;
+}
+
+void
+SpefReader::setDelimiter(char delimiter)
+{
+ delimiter_ = delimiter;
+}
+
void
SpefReader::setBusBrackets(char left, char right)
{
@@ -127,7 +167,78 @@ SpefReader::setBusBrackets(char left, char right)
|| (left == ':' && right == '\0')
|| (left == '.' && right == '\0')))
warn("illegal bus delimiters.\n");
- SpfSpefReader::setBusBrackets(left, right);
+ bus_brkt_left_ = left;
+ bus_brkt_right_ = right;
+}
+
+Instance *
+SpefReader::findInstanceRelative(const char *name)
+{
+ return network_->findInstanceRelative(instance_, name);
+}
+
+Net *
+SpefReader::findNetRelative(const char *name)
+{
+ return network_->findNetRelative(instance_, name);
+}
+
+Pin *
+SpefReader::findPinRelative(const char *name)
+{
+ return network_->findPinRelative(instance_, name);
+}
+
+Pin *
+SpefReader::findPortPinRelative(const char *name)
+{
+ return network_->findPin(instance_, name);
+}
+
+void
+SpefReader::getChars(char *buf,
+ int &result,
+ size_t max_size)
+{
+ char *status = gzgets(stream_, buf, max_size);
+ if (status == Z_NULL)
+ result = 0; // YY_NULL
+ else
+ result = static_cast(strlen(buf));
+}
+
+void
+SpefReader::getChars(char *buf,
+ size_t &result,
+ size_t max_size)
+{
+ char *status = gzgets(stream_, buf, max_size);
+ if (status == Z_NULL)
+ result = 0; // YY_NULL
+ else
+ result = strlen(buf);
+}
+
+char *
+SpefReader::translated(const char *token)
+{
+ return spefToSta(token, divider_, network_->pathDivider(),
+ network_->pathEscape());
+}
+
+void
+SpefReader::incrLine()
+{
+ line_++;
+}
+
+void
+SpefReader::warn(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ report_->vfileWarn(filename_, line_, fmt, args);
+ va_end(args);
}
void
@@ -510,10 +621,11 @@ SpefReader::makeCouplingCap(int id,
char *node_name2,
float cap)
{
- const char *name = 0;
+ const char *name = NULL;
+ const char *name_tmp = NULL;
if (keep_device_names_)
// Prepend device type because OA uses one namespace for all devices.
- name = stringPrint(INT_DIGITS + 2, "C%d", id);
+ name = name_tmp = stringPrint("C%d", id);
ParasiticNode *node1, *node2;
Net *ext_net1, *ext_net2;
@@ -537,6 +649,7 @@ SpefReader::makeCouplingCap(int id,
else if (ext_pin1)
parasitics_->makeCouplingCap(name, node2, ext_pin1, cap, ap_);
}
+ stringDelete(name_tmp);
}
void
@@ -549,11 +662,13 @@ SpefReader::makeResistor(int id,
ParasiticNode *node2 = findParasiticNode(node_name2);
if (node1 && node2) {
float res1 = res->value(triple_index_) * res_scale_;
- const char *name = 0;
+ const char *name = NULL;
+ const char *name_tmp = NULL;
if (keep_device_names_)
// Prepend device type because OA uses one namespace for all devices.
- name = stringPrint(INT_DIGITS + 2, "R%d", id);
+ name = name_tmp = stringPrint("R%d", id);
parasitics_->makeResistor(name, node1, node2, res1, ap_);
+ stringDelete(name_tmp);
}
delete res;
stringDelete(node_name1);
diff --git a/parasitics/SpefReader.hh b/parasitics/SpefReader.hh
index 6639bdbf..d208cfdb 100644
--- a/parasitics/SpefReader.hh
+++ b/parasitics/SpefReader.hh
@@ -33,8 +33,6 @@ class Instance;
// Return true if successful.
bool
readSpefFile(const char *filename,
- gzFile stream,
- int line,
Instance *instance,
ParasiticAnalysisPt *ap,
bool increment,
diff --git a/parasitics/SpefReaderPvt.hh b/parasitics/SpefReaderPvt.hh
index a450b704..1ec304ed 100644
--- a/parasitics/SpefReaderPvt.hh
+++ b/parasitics/SpefReaderPvt.hh
@@ -21,7 +21,7 @@
#include "Map.hh"
#include "StringSeq.hh"
#include "NetworkClass.hh"
-#include "SpfSpefReader.hh"
+#include "ParasiticsClass.hh"
// Global namespace.
#define YY_INPUT(buf,result,max_size) \
@@ -34,21 +34,20 @@ SpefParse_error(const char *msg);
namespace sta {
-class Parasitic;
-class ParasiticNode;
-class ParasiticNetwork;
+class Report;
+class OperatingConditions;
+class MinMax;
class SpefRspfPi;
class SpefTriple;
class Corner;
typedef Map > SpefNameMap;
-class SpefReader : public SpfSpefReader
+class SpefReader
{
public:
SpefReader(const char *filename,
gzFile stream,
- int line,
Instance *instance,
ParasiticAnalysisPt *ap,
bool increment,
@@ -65,6 +64,25 @@ public:
Network *network,
Parasitics *parasitics);
virtual ~SpefReader();
+ char divider() const { return divider_; }
+ void setDivider(char divider);
+ char delimiter() const { return delimiter_; }
+ void setDelimiter(char delimiter);
+ void incrLine();
+ int line() const { return line_; }
+ const char *filename() const { return filename_; }
+ // flex YY_INPUT yy_n_chars arg changed definition from int to size_t,
+ // so provide both forms.
+ void getChars(char *buf,
+ int &result,
+ size_t max_size);
+ void getChars(char *buf,
+ size_t &result,
+ size_t max_size);
+ // Translate from spf/spef namespace to sta namespace.
+ char *translated(const char *token);
+ void warn(const char *fmt, ...)
+ __attribute__((format (printf, 2, 3)));
void setBusBrackets(char left,
char right);
void setTimeScale(float scale,
@@ -106,6 +124,10 @@ public:
PortDirection *portDirection(char *spef_dir);
private:
+ Pin *findPinRelative(const char *name);
+ Pin *findPortPinRelative(const char *name);
+ Net *findNetRelative(const char *name);
+ Instance *findInstanceRelative(const char *name);
void makeCouplingCap(int id,
char *node_name1,
char *node_name2,
@@ -117,6 +139,31 @@ private:
int &ext_node_id,
Pin *&ext_pin);
+ const char *filename_;
+ Instance *instance_;
+ const ParasiticAnalysisPt *ap_;
+ bool increment_;
+ bool pin_cap_included_;
+ bool keep_coupling_caps_;
+ ReduceParasiticsTo reduce_to_;
+ bool delete_after_reduce_;
+ const OperatingConditions *op_cond_;
+ const Corner *corner_;
+ const MinMax *cnst_min_max_;
+ // Normally no need to keep device names.
+ bool keep_device_names_;
+ bool quiet_;
+ gzFile stream_;
+ int line_;
+ char divider_;
+ char delimiter_;
+ char bus_brkt_left_;
+ char bus_brkt_right_;
+ Net *net_;
+ Report *report_;
+ Network *network_;
+ Parasitics *parasitics_;
+
int triple_index_;
float time_scale_;
float cap_scale_;
@@ -125,10 +172,6 @@ private:
SpefNameMap name_map_;
StringSeq *design_flow_;
Parasitic *parasitic_;
-
- using SpfSpefReader::findPortPinRelative;
- using SpfSpefReader::findNetRelative;
- using SpfSpefReader::findInstanceRelative;
};
class SpefTriple
diff --git a/sdc/Clock.cc b/sdc/Clock.cc
index b43d753c..72564079 100644
--- a/sdc/Clock.cc
+++ b/sdc/Clock.cc
@@ -548,8 +548,7 @@ ClockEdge::ClockEdge(Clock *clock,
TransRiseFall *tr) :
clock_(clock),
tr_(tr),
- name_(stringPrint(strlen(clock_->name())+strlen(tr_->asString()) + 2,
- "%s %s", clock_->name(), tr_->asString())),
+ name_(stringPrint("%s %s", clock_->name(), tr_->asString())),
time_(0.0),
index_(clock_->index() * TransRiseFall::index_count + tr_->index())
{
diff --git a/sdc/CycleAccting.cc b/sdc/CycleAccting.cc
index a48952fa..ae3d037f 100644
--- a/sdc/CycleAccting.cc
+++ b/sdc/CycleAccting.cc
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+#include // ceil
+#include // max
#include "Machine.hh"
#include "Debug.hh"
#include "Fuzzy.hh"
@@ -53,59 +55,60 @@ CycleAccting::findDelays(StaState *sta)
const int gclk_hold_index = TimingRole::gatedClockHold()->index();
Clock *src_clk = src_->clock();
Clock *tgt_clk = tgt_->clock();
- ClockEdge *tgt_opp = tgt_->opposite();
+ double tgt_opp_time1 = tgt_->opposite()->time();
double tgt_period = tgt_clk->period();
double src_period = src_clk->period();
if (tgt_period > 0.0 && src_period > 0.0) {
- int tgt_max_cycle_count, src_max_cycle_count;
- if (tgt_period > src_period) {
- tgt_max_cycle_count = small_period_clk_expansion_cycle_count;
- src_max_cycle_count = large_period_clk_expansion_cycle_count;
- }
+ // If the clocks are related (ie, generated clock and its source) allow
+ // allow enough cycles to match up the common period.
+ int tgt_max_cycle;
+ if (tgt_period > src_period)
+ tgt_max_cycle = 100;
else {
- tgt_max_cycle_count = large_period_clk_expansion_cycle_count;
- src_max_cycle_count = small_period_clk_expansion_cycle_count;
+ int ratio = std::ceil(src_period / tgt_period);
+ tgt_max_cycle = std::max(ratio, 100);
}
- int tgt_cycle;
bool tgt_past_src = false;
bool src_past_tgt = false;
+ int tgt_cycle, src_cycle;
for (tgt_cycle = (tgt_->time() < tgt_period) ? 0 : -1;
- tgt_cycle < tgt_max_cycle_count;
+ tgt_cycle <= tgt_max_cycle;
tgt_cycle++) {
double tgt_cycle_start = tgt_cycle * tgt_period;
double tgt_time = tgt_cycle_start + tgt_->time();
- double tgt_opp_time = tgt_cycle_start + tgt_opp->time();
- int src_cycle;
+ double tgt_opp_time = tgt_cycle_start + tgt_opp_time1;
for (src_cycle = (src_->time() < src_period) ? 0 : -1;
- src_cycle < src_max_cycle_count;
+ ;
src_cycle++) {
double src_cycle_start = src_cycle * src_period;
double src_time = src_cycle_start + src_->time();
- // Make sure both setup and hold required_ are determined.
+
+ // Make sure both setup and hold required are determined.
if (tgt_past_src && src_past_tgt
+ // Synchronicity achieved.
&& fuzzyEqual(src_cycle_start, tgt_cycle_start)) {
- debugPrint2(debug, "cycle_acct", 1,
- " setup = %s, required = %s\n",
+ debugPrint2(debug, "cycle_acct", 1, " setup = %s, required = %s\n",
time_unit->asString(delay_[setup_index]),
time_unit->asString(required_[setup_index]));
- debugPrint2(debug, "cycle_acct", 1,
- " hold = %s, required = %s\n",
+ debugPrint2(debug, "cycle_acct", 1, " hold = %s, required = %s\n",
time_unit->asString(delay_[hold_index]),
time_unit->asString(required_[hold_index]));
+ debugPrint2(debug, "cycle_acct", 1,
+ " converged at src cycles = %d tgt cycles = %d\n",
+ src_cycle, tgt_cycle);
return;
}
+
if (fuzzyGreater(src_cycle_start, tgt_cycle_start + tgt_period)
&& src_past_tgt)
break;
- debugPrint5(debug, "cycle_acct", 2,
- " %s src cycle %d %s + %s = %s\n",
+ debugPrint5(debug, "cycle_acct", 2, " %s src cycle %d %s + %s = %s\n",
src_->name(),
src_cycle,
time_unit->asString(src_cycle_start),
time_unit->asString(src_->time()),
time_unit->asString(src_time));
- debugPrint5(debug, "cycle_acct", 2,
- " %s tgt cycle %d %s + %s = %s\n",
+ debugPrint5(debug, "cycle_acct", 2, " %s tgt cycle %d %s + %s = %s\n",
tgt_->name(),
tgt_cycle,
time_unit->asString(tgt_cycle_start),
@@ -125,6 +128,7 @@ CycleAccting::findDelays(StaState *sta)
time_unit->asString(required_[setup_index]));
}
}
+
// Data check setup checks are zero cycle.
if (fuzzyLessEqual(tgt_time, src_time)) {
double setup_delay = src_time - tgt_time;
@@ -138,6 +142,7 @@ CycleAccting::findDelays(StaState *sta)
src_cycle + 1, tgt_cycle, hold_delay, hold_required);
}
}
+
// Latch setup cycle accting for the enable is the data clk edge
// closest to the disable (opposite) edge.
if (fuzzyGreater(tgt_opp_time, src_time)) {
@@ -159,6 +164,7 @@ CycleAccting::findDelays(StaState *sta)
time_unit->asString(required_[latch_setup_index]));
}
}
+
// For hold checks, target has to be BEFORE source.
if (fuzzyLessEqual(tgt_time, src_time)) {
double delay = src_time - tgt_time;
@@ -172,6 +178,7 @@ CycleAccting::findDelays(StaState *sta)
time_unit->asString(required_[hold_index]));
}
}
+
// Gated clock hold checks are in the same cycle as the
// setup check.
if (fuzzyLessEqual(tgt_opp_time, src_time)) {
@@ -187,11 +194,11 @@ CycleAccting::findDelays(StaState *sta)
}
}
}
- if (src_cycle == src_max_cycle_count)
- break;
}
max_cycles_exceeded_ = true;
- debugPrint0(debug, "cycle_acct", 1, " max cycles exceeded\n");
+ debugPrint2(debug, "cycle_acct", 1,
+ " max cycles exceeded after %d src cycles, %d tgt_cycles\n",
+ src_cycle, tgt_cycle);
}
else if (tgt_period > 0.0)
findDefaultArrivalSrcDelays();
diff --git a/sdc/CycleAccting.hh b/sdc/CycleAccting.hh
index 24995ee1..5a970929 100644
--- a/sdc/CycleAccting.hh
+++ b/sdc/CycleAccting.hh
@@ -25,15 +25,11 @@
namespace sta {
-// Maximum number of cycles we are willing to multiply the period by
-// looking for a minimum separation of edges to another clock.
-const int large_period_clk_expansion_cycle_count = 1000;
-const int small_period_clk_expansion_cycle_count = 101;
-
class CycleAccting
{
public:
- CycleAccting(const ClockEdge *src, const ClockEdge *tgt);
+ CycleAccting(const ClockEdge *src,
+ const ClockEdge *tgt);
// Fill in required times.
void findDelays(StaState *sta);
// Find delays when source clk edge is the default arrival clock edge
@@ -88,7 +84,8 @@ private:
class CycleAcctingLess
{
public:
- bool operator()(const CycleAccting *acct1, const CycleAccting *acct2) const;
+ bool operator()(const CycleAccting *acct1,
+ const CycleAccting *acct2) const;
};
} // namespace
diff --git a/sdc/ExceptionPath.cc b/sdc/ExceptionPath.cc
index 3087dddd..83456c55 100644
--- a/sdc/ExceptionPath.cc
+++ b/sdc/ExceptionPath.cc
@@ -583,9 +583,7 @@ const char *
PathDelay::asString(const Network *network) const
{
const char *from_thru_to = fromThruToString(network);
- const char *result = stringPrintTmp(strlen("PathDelay") + 10
- + strlen(from_thru_to) + 1,
- "PathDelay %.3fns%s",
+ const char *result = stringPrintTmp("PathDelay %.3fns%s",
delay_ * 1E+9F,
from_thru_to);
return result;
@@ -776,9 +774,7 @@ const char *
MultiCyclePath::asString(const Network *network) const
{
const char *from_thru_to = fromThruToString(network);
- const char *result = stringPrintTmp(strlen("Multicycle -max ") + 5
- + strlen(from_thru_to) + 1,
- "Multicycle %s %d%s",
+ const char *result = stringPrintTmp("Multicycle %s %d%s",
(use_end_clk_) ? "-end" : "-start",
path_multiplier_,
from_thru_to);
diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc
index 900c86d5..54fc0d7c 100644
--- a/sdc/Sdc.cc
+++ b/sdc/Sdc.cc
@@ -2033,15 +2033,20 @@ Sdc::makeClockGroups(const char *name,
bool allow_paths,
const char *comment)
{
+ char *gen_name = NULL;
if (name == NULL
|| name[0] == '\0')
- name = makeClockGroupsName();
- ClockGroups *groups = clk_groups_name_map_.findKey(name);
- if (groups)
- removeClockGroups(groups);
- groups = new ClockGroups(name, logically_exclusive, physically_exclusive,
- asynchronous, allow_paths, comment);
+ name = gen_name = makeClockGroupsName();
+ else {
+ ClockGroups *groups = clk_groups_name_map_.findKey(name);
+ if (groups)
+ removeClockGroups(groups);
+ }
+ ClockGroups *groups = new ClockGroups(name, logically_exclusive,
+ physically_exclusive,
+ asynchronous, allow_paths, comment);
clk_groups_name_map_[groups->name()] = groups;
+ stringDelete(gen_name);
return groups;
}
@@ -2049,11 +2054,12 @@ Sdc::makeClockGroups(const char *name,
char *
Sdc::makeClockGroupsName()
{
- char *name;
+ char *name = NULL;
int i = 0;
do {
i++;
- name = stringPrintTmp(10, "group%d", i);
+ stringDelete(name);
+ name = stringPrint("group%d", i);
} while (clk_groups_name_map_.hasKey(name));
return name;
}
@@ -2609,10 +2615,9 @@ Sdc::reportClkToClkMaxCycleWarnings()
ClockPairSeq::Iterator pair_iter2(clk_warnings2);
while (pair_iter2.hasNext()) {
ClockPair *pair = pair_iter2.next();
- report_->warn("No common period was found between clocks %s and %s in %d cycles.\n",
+ report_->warn("No common period was found between clocks %s and %s.\n",
pair->first->name(),
- pair->second->name(),
- large_period_clk_expansion_cycle_count);
+ pair->second->name());
delete pair;
}
}
diff --git a/sdc/WriteSdc.cc b/sdc/WriteSdc.cc
index dd2a0277..c42a6ecb 100644
--- a/sdc/WriteSdc.cc
+++ b/sdc/WriteSdc.cc
@@ -1265,9 +1265,9 @@ WriteSdc::writeDisabledEdgeSense(Edge *edge) const
{
fprintf(stream_, "set_disable_timing ");
const char *sense = timingSenseString(edge->sense());
- const char *filter = stringPrintTmp(strlen(sense) + strlen("sense == ") + 1,
- "sense == %s", sense);
- writeGetTimingArcs(edge, filter);
+ string filter;
+ stringPrint(filter, "sense == %s", sense);
+ writeGetTimingArcs(edge, filter.c_str());
fprintf(stream_, "\n");
}
diff --git a/sdf/ReportAnnotation.cc b/sdf/ReportAnnotation.cc
index d995950b..d80b8542 100644
--- a/sdf/ReportAnnotation.cc
+++ b/sdf/ReportAnnotation.cc
@@ -283,11 +283,9 @@ ReportAnnotated::reportCheckCount(TimingRole *role,
int index = role->index();
if (edge_count_[index] > 0) {
const char *role_name = role->asString();
- const char *title = stringPrintTmp(strlen("cell arcs")
- + strlen(role_name) + 1,
- "cell %s arcs",
- role_name);
- reportCount(title, index, total, annotated_total);
+ string title;
+ stringPrint(title, "cell %s arcs", role_name);
+ reportCount(title.c_str(), index, total, annotated_total);
}
}
diff --git a/sdf/SdfReader.cc b/sdf/SdfReader.cc
index 2487f8a0..7f30dc31 100644
--- a/sdf/SdfReader.cc
+++ b/sdf/SdfReader.cc
@@ -1043,23 +1043,25 @@ SdfReader::sdfError(const char *fmt, ...)
Pin *
SdfReader::findPin(const char *name)
{
- const char *path_name = (path_)
- ? stringPrintTmp(strlen(name) + strlen(name) + 2, "%s%c%s",
- path_, divider_, name)
- : name;
- return network_->findPin(path_name);
+ if (path_) {
+ string path_name;
+ stringPrint(path_name, path_, divider_, name);
+ Pin *pin = network_->findPin(path_name.c_str());
+ return pin;
+ }
+ else
+ return network_->findPin(name);
}
Instance *
SdfReader::findInstance(const char *name)
{
- const char *path_name = (path_)
- ? stringPrintTmp(strlen(name) + strlen(name) + 2, "%s%c%s",
- path_, divider_, name)
- : name;
- Instance *inst = network_->findInstance(path_name);
+ string inst_name = name;
+ if (path_)
+ stringPrint(inst_name, "%s%c%s", path_, divider_, name);
+ Instance *inst = network_->findInstance(inst_name.c_str());
if (inst == NULL)
- sdfError("instance %s not found.\n", path_name);
+ sdfError("instance %s not found.\n", inst_name.c_str());
return inst;
}
diff --git a/search/ClkInfo.cc b/search/ClkInfo.cc
index 9fbd5da5..a6b7ba81 100644
--- a/search/ClkInfo.cc
+++ b/search/ClkInfo.cc
@@ -116,7 +116,7 @@ ClkInfo::asString(const StaState *sta) const
string str;
PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index_);
- str += stringPrintTmp(15, "%s/%d ",
+ str += stringPrintTmp("%s/%d ",
path_ap->pathMinMax()->asString(),
path_ap_index_);
if (clk_edge_)
diff --git a/search/Crpr.cc b/search/Crpr.cc
index 03fbfd5f..9e694879 100644
--- a/search/Crpr.cc
+++ b/search/Crpr.cc
@@ -87,14 +87,15 @@ CheckCrpr::maxCrpr(ClkInfo *clk_info)
const PathVertexRep &crpr_clk_path = clk_info->crprClkPath();
if (!crpr_clk_path.isNull()) {
PathVertex crpr_clk_vpath(crpr_clk_path, this);
- Arrival other_arrival = otherMinMaxArrival(&crpr_clk_vpath);
- float crpr_diff = abs(delayAsFloat(crpr_clk_vpath.arrival(this),
- EarlyLate::late())
- - delayAsFloat(other_arrival, EarlyLate::early()));
- return crpr_diff;
+ if (!crpr_clk_vpath.isNull()) {
+ Arrival other_arrival = otherMinMaxArrival(&crpr_clk_vpath);
+ float crpr_diff = abs(delayAsFloat(crpr_clk_vpath.arrival(this),
+ EarlyLate::late())
+ - delayAsFloat(other_arrival, EarlyLate::early()));
+ return crpr_diff;
+ }
}
- else
- return 0.0F;
+ return 0.0F;
}
Arrival
diff --git a/search/Path.cc b/search/Path.cc
index 44911afc..0b569a10 100644
--- a/search/Path.cc
+++ b/search/Path.cc
@@ -40,9 +40,7 @@ Path::name(const StaState *sta) const
int ap_index = path_ap->index();
const char *min_max = path_ap->pathMinMax()->asString();
TagIndex tag_index = tagIndex(sta);
- size_t result_len = strlen(vertex_name) + strlen(tr_str)
- + 2 + strlen(min_max) + 16;
- return stringPrintTmp(result_len, "%s %s %s/%d %d",
+ return stringPrintTmp("%s %s %s/%d %d",
vertex_name, tr_str, min_max,
ap_index, tag_index);
}
diff --git a/search/PathVertex.cc b/search/PathVertex.cc
index e9c28440..dc76bbe4 100644
--- a/search/PathVertex.cc
+++ b/search/PathVertex.cc
@@ -104,16 +104,18 @@ PathVertex::init(Vertex *vertex,
Tag *tag,
const StaState *sta)
{
- vertex_ = vertex;
+ vertex_ = NULL;
tag_ = NULL;
arrival_index_ = 0;
const Search *search = sta->search();
- TagGroup *tag_group = search->tagGroup(vertex_);
+ TagGroup *tag_group = search->tagGroup(vertex);
if (tag_group) {
bool arrival_exists;
tag_group->arrivalIndex(tag, arrival_index_, arrival_exists);
- if (arrival_exists)
+ if (arrival_exists) {
+ vertex_ = vertex;
tag_ = tag;
+ }
}
}
diff --git a/search/Property.cc b/search/Property.cc
index 9b4c8207..f7d69fd9 100644
--- a/search/Property.cc
+++ b/search/Property.cc
@@ -31,9 +31,12 @@
#include "PathRef.hh"
#include "Property.hh"
#include "Sta.hh"
+#include "Property.hh"
namespace sta {
+using std::string;
+
static PropertyValue
pinSlewProperty(const Pin *pin,
const TransRiseFall *tr,
@@ -78,6 +81,13 @@ PropertyValue::PropertyValue(const char *value) :
string_ = stringCopy(value);
}
+PropertyValue::PropertyValue(std::string &value) :
+ type_(type_string)
+{
+ init();
+ string_ = stringCopy(value.c_str());
+}
+
PropertyValue::PropertyValue(float value) :
type_(type_float)
{
@@ -85,6 +95,27 @@ PropertyValue::PropertyValue(float value) :
float_ = value;
}
+PropertyValue::PropertyValue(LibertyLibrary *value) :
+ type_(type_liberty_library)
+{
+ init();
+ liberty_library_ = value;
+}
+
+PropertyValue::PropertyValue(LibertyCell *value) :
+ type_(type_liberty_cell)
+{
+ init();
+ liberty_cell_ = value;
+}
+
+PropertyValue::PropertyValue(Cell *value) :
+ type_(type_cell)
+{
+ init();
+ cell_ = value;
+}
+
PropertyValue::PropertyValue(Instance *value) :
type_(type_instance)
{
@@ -162,6 +193,9 @@ PropertyValue::PropertyValue(const PropertyValue &value) :
type_(value.type_),
string_(stringCopy(value.string_)),
float_(value.float_),
+ liberty_library_(value.liberty_library_),
+ liberty_cell_(value.liberty_cell_),
+ cell_(value.cell_),
inst_(value.inst_),
pin_(value.pin_),
pins_(value.pins_ ? new PinSeq(*value.pins_) : NULL),
@@ -177,6 +211,9 @@ PropertyValue::init()
{
string_ = NULL;
float_ = 0.0;
+ liberty_library_ = NULL;
+ liberty_cell_ = NULL;
+ cell_ = NULL;
inst_ = NULL;
pin_ = NULL;
pins_ = NULL;
@@ -200,6 +237,9 @@ PropertyValue::operator=(const PropertyValue &value)
type_ = value.type_;
string_ = stringCopy(value.string_);
float_ = value.float_;
+ liberty_library_ = value.liberty_library_;
+ liberty_cell_ = value.liberty_cell_;
+ cell_ = value.cell_;
inst_ = value.inst_;
pin_ = value.pin_;
pins_ = value.pins_ ? new PinSeq(*value.pins_) : NULL;
@@ -209,18 +249,217 @@ PropertyValue::operator=(const PropertyValue &value)
path_refs_ = value.path_refs_ ? new PathRefSeq(*value.path_refs_) : NULL;
}
+////////////////////////////////////////////////////////////////
+
+PropertyValue
+getProperty(const Library *lib,
+ const char *property,
+ Sta *sta)
+{
+ auto network = sta->cmdNetwork();
+ if (stringEqual(property, "name")
+ || stringEqual(property, "full_name"))
+ return PropertyValue(network->name(lib));
+#if 0
+ else if (stringEqual(property, "filename"))
+ return PropertyValue(network->filename(lib));
+#endif
+ else
+ return PropertyValue();
+}
+
+PropertyValue
+getProperty(const LibertyLibrary *lib,
+ const char *property,
+ Sta *)
+{
+ if (stringEqual(property, "name")
+ || stringEqual(property, "full_name"))
+ return PropertyValue(lib->name());
+ else if (stringEqual(property, "filename"))
+ return PropertyValue(lib->filename());
+ else
+ return PropertyValue();
+}
+
+PropertyValue
+getProperty(const LibertyCell *cell,
+ const char *property,
+ Sta *sta)
+{
+ if (stringEqual(property, "name")
+ || stringEqual(property, "base_name"))
+ return PropertyValue(cell->name());
+ else if (stringEqual(property, "full_name")) {
+ auto network = sta->cmdNetwork();
+ auto lib = cell->libertyLibrary();
+ const char *lib_name = lib->name();
+ const char *cell_name = cell->name();
+ string full_name;
+ stringPrint(full_name, "%s%c%s",
+ lib_name,
+ network->pathDivider(),
+ cell_name);
+ return PropertyValue(full_name);
+ }
+ else if (stringEqual(property, "filename"))
+ return PropertyValue(cell->filename());
+ else if (stringEqual(property, "library"))
+ return PropertyValue(cell->libertyLibrary());
+ else
+ return PropertyValue();
+}
+
+PropertyValue
+getProperty(const Cell *cell,
+ const char *property,
+ Sta *sta)
+{
+ auto network = sta->cmdNetwork();
+ if (stringEqual(property, "name")
+ || stringEqual(property, "base_name"))
+ return PropertyValue(network->name(cell));
+ else if (stringEqual(property, "full_name")) {
+ auto lib = network->library(cell);
+ const char *lib_name = network->name(lib);
+ const char *cell_name = network->name(cell);
+ string full_name;
+ stringPrint(full_name, "%s%c%s",
+ lib_name,
+ network->pathDivider(),
+ cell_name);
+ return PropertyValue(full_name);
+ }
+ else if (stringEqual(property, "filename"))
+ return PropertyValue(network->filename(cell));
+ else
+ return PropertyValue();
+}
+
+////////////////////////////////////////////////////////////////
+
+PropertyValue
+getProperty(const Port *port,
+ const char *property,
+ Sta *sta)
+{
+ auto network = sta->cmdNetwork();
+ if (stringEqual(property, "name")
+ || stringEqual(property, "full_name"))
+ return PropertyValue(network->name(port));
+ else if (stringEqual(property, "direction"))
+ return PropertyValue(network->direction(port)->name());
+
+ 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)
+{
+ auto network = sta->cmdNetwork();
+ 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)
+{
+ auto network = sta->cmdNetwork();
+ Instance *top_inst = network->topInstance();
+ Pin *pin = network->findPin(top_inst, port);
+ return pinSlackProperty(pin, tr, min_max, sta);
+}
+
+PropertyValue
+getProperty(const LibertyPort *port,
+ const char *property,
+ Sta *)
+{
+ if (stringEqual(property, "name"))
+ return PropertyValue(port->name());
+ else if (stringEqual(property, "full_name"))
+ return PropertyValue(port->name());
+ else if (stringEqual(property, "direction"))
+ return PropertyValue(port->direction()->name());
+ else
+ return PropertyValue();
+}
+
+////////////////////////////////////////////////////////////////
+
+class PropertyError : public StaException
+{
+public:
+ PropertyError(const char *type,
+ const char *property);
+ virtual const char *what() const throw();
+
+protected:
+ const char *type_;
+ const char *property_;
+};
+
+PropertyError::PropertyError(const char *type,
+ const char *property) :
+ type_(type),
+ property_(property)
+{
+}
+
+const char *
+PropertyError::what() const throw()
+{
+ // leak
+ return stringPrint("%s objects do not have a %s property.",
+ type_, property_);
+}
+
+////////////////////////////////////////////////////////////////
+
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)));
+ auto network = sta->cmdNetwork();
+ if (stringEqual(property, "name"))
+ return PropertyValue(network->name(inst));
else if (stringEqual(property, "full_name"))
return PropertyValue(network->pathName(inst));
+ else if (stringEqual(property, "ref_name"))
+ return PropertyValue(network->name(network->cell(inst)));
+ else if (stringEqual(property, "liberty_cell"))
+ return PropertyValue(network->libertyCell(inst));
+ else if (stringEqual(property, "cell"))
+ return PropertyValue(network->cell(inst));
else
- return PropertyValue();
+ throw PropertyError("instance", property);
}
////////////////////////////////////////////////////////////////
@@ -230,7 +469,7 @@ getProperty(const Pin *pin,
const char *property,
Sta *sta)
{
- Network *network = sta->network();
+ auto network = sta->cmdNetwork();
if (stringEqual(property, "direction"))
return PropertyValue(network->direction(pin)->name());
else if (stringEqual(property, "full_name"))
@@ -262,7 +501,7 @@ getProperty(const Pin *pin,
return pinSlewProperty(pin, TransRiseFall::fall(), MinMax::min(), sta);
else
- return PropertyValue();
+ throw PropertyError("pin", property);
}
static PropertyValue
@@ -305,135 +544,11 @@ getProperty(const Net *net,
const char *property,
Sta *sta)
{
- Network *network = sta->network();
+ auto network = sta->cmdNetwork();
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();
+ throw PropertyError("net", property);
}
////////////////////////////////////////////////////////////////
@@ -443,6 +558,13 @@ getProperty(Edge *edge,
const char *property,
Sta *sta)
{
+ if (stringEqual(property, "full_name")) {
+ auto network = sta->cmdNetwork();
+ auto graph = sta->graph();
+ const char *from = edge->from(graph)->name(network);
+ const char *to = edge->to(graph)->name(network);
+ return stringPrintTmp("%s -> %s", from, to);
+ }
if (stringEqual(property, "delay_min_fall"))
return edgeDelayProperty(edge, TransRiseFall::fall(), MinMax::min(), sta);
else if (stringEqual(property, "delay_max_fall"))
@@ -458,7 +580,7 @@ getProperty(Edge *edge,
else if (stringEqual(property, "to_pin"))
return PropertyValue(edge->to(sta->graph())->pin());
else
- return PropertyValue();
+ throw PropertyError("edge", property);
}
static PropertyValue
@@ -494,12 +616,33 @@ edgeDelayProperty(Edge *edge,
////////////////////////////////////////////////////////////////
+PropertyValue
+getProperty(TimingArcSet *arc_set,
+ const char *property,
+ Sta *)
+{
+ if (stringEqual(property, "name")
+ || stringEqual(property, "full_name")) {
+ auto from = arc_set->from()->name();
+ auto to = arc_set->to()->name();
+ auto cell_name = arc_set->libertyCell()->name();
+ string name;
+ stringPrint(name, "%s %s -> %s", cell_name, from, to);
+ return PropertyValue(name);
+ }
+ else
+ throw PropertyError("timing arc", property);
+}
+
+////////////////////////////////////////////////////////////////
+
PropertyValue
getProperty(Clock *clk,
const char *property,
Sta *sta)
{
- if (stringEqual(property, "name"))
+ if (stringEqual(property, "name")
+ || stringEqual(property, "full_name"))
return PropertyValue(clk->name());
else if (stringEqual(property, "period"))
return PropertyValue(sta->units()->timeUnit()->asString(clk->period(), 8));
@@ -508,7 +651,7 @@ getProperty(Clock *clk,
else if (stringEqual(property, "propagated"))
return PropertyValue(clk->isPropagated() ? "1" : "0");
else
- return PropertyValue();
+ throw PropertyError("clock", property);
}
////////////////////////////////////////////////////////////////
@@ -542,7 +685,7 @@ getProperty(PathEnd *end,
return PropertyValue(&paths);
}
else
- return PropertyValue();
+ throw PropertyError("path end", property);
}
PropertyValue
@@ -559,7 +702,7 @@ getProperty(PathRef *path,
else if (stringEqual(property, "slack"))
return PropertyValue(delayPropertyValue(path->slack(sta), sta));
else
- return PropertyValue();
+ throw PropertyError("path", property);
}
static float
diff --git a/search/Property.hh b/search/Property.hh
index 214f27d0..cde42d79 100644
--- a/search/Property.hh
+++ b/search/Property.hh
@@ -17,22 +17,32 @@
#ifndef STA_PROPERTY_H
#define STA_PROPERTY_H
+#include
+#include "LibertyClass.hh"
#include "NetworkClass.hh"
#include "SearchClass.hh"
+#include "SdcClass.hh"
namespace sta {
+using std::string;
+
class Sta;
class PropertyValue
{
public:
enum Type { type_none, type_string, type_float,
+ type_liberty_library, type_liberty_cell, type_cell,
type_instance, type_pin, type_pins, type_net,
type_clock, type_clocks, type_path_refs };
PropertyValue();
PropertyValue(const char *value);
+ PropertyValue(string &value);
PropertyValue(float value);
+ PropertyValue(LibertyLibrary *value);
+ PropertyValue(LibertyCell *value);
+ PropertyValue(Cell *value);
PropertyValue(Instance *value);
PropertyValue(Pin *value);
PropertyValue(PinSeq *value);
@@ -46,8 +56,11 @@ public:
PropertyValue(const PropertyValue &props);
~PropertyValue();
Type type() const { return type_; }
- const char *string() const { return string_; }
+ const char *stringValue() const { return string_; }
float floatValue() const { return float_; }
+ LibertyLibrary *libertyLibrary() const { return liberty_library_; }
+ LibertyCell *libertyCell() const { return liberty_cell_; }
+ Cell *cell() const { return cell_; }
Instance *instance() const { return inst_; }
Pin *pin() const { return pin_; }
PinSeq *pins() const { return pins_; }
@@ -63,6 +76,9 @@ private:
Type type_;
const char *string_;
float float_;
+ LibertyLibrary *liberty_library_;
+ LibertyCell *liberty_cell_;
+ Cell *cell_;
Instance *inst_;
Pin *pin_;
PinSeq *pins_;
@@ -92,6 +108,11 @@ getProperty(const Port *port,
const char *property,
Sta *sta);
+PropertyValue
+getProperty(const Cell *cell,
+ const char *property,
+ Sta *sta);
+
PropertyValue
getProperty(const LibertyCell *cell,
const char *property,
@@ -132,5 +153,10 @@ getProperty(PathRef *end,
const char *property,
Sta *sta);
+PropertyValue
+getProperty(TimingArcSet *arc_set,
+ const char *property,
+ Sta *sta);
+
} // namespace
#endif
diff --git a/search/ReportPath.cc b/search/ReportPath.cc
index a63b8f84..2b4f4c1c 100644
--- a/search/ReportPath.cc
+++ b/search/ReportPath.cc
@@ -137,10 +137,8 @@ ReportPath::~ReportPath()
delete field_edge_;
delete field_case_;
- if (plus_zero_) {
- stringDelete(plus_zero_);
- stringDelete(minus_zero_);
- }
+ stringDelete(plus_zero_);
+ stringDelete(minus_zero_);
}
void
@@ -250,8 +248,8 @@ ReportPath::setDigits(int digits)
stringDelete(plus_zero_);
stringDelete(minus_zero_);
}
- minus_zero_ = stringPrint(digits_ + 4, "-%.*f", digits_, 0.0);
- plus_zero_ = stringPrint(digits_ + 3, "%.*f", digits_, 0.0);
+ minus_zero_ = stringPrint("-%.*f", digits_, 0.0);
+ plus_zero_ = stringPrint("%.*f", digits_, 0.0);
}
////////////////////////////////////////////////////////////////
@@ -461,14 +459,11 @@ ReportPath::reportFull(const PathEndCheck *end,
reportSlack(end, result);
}
-char *
+string
ReportPath::checkRoleString(const PathEnd *end)
{
const char *check_role = end->checkRole(this)->asString();
- return stringPrintTmp(strlen("library time")
- + strlen(check_role) + 1,
- "library %s time",
- check_role);
+ return stdstrPrint("library %s time", check_role);
}
void
@@ -477,42 +472,30 @@ ReportPath::reportEndpoint(const PathEndCheck *end,
{
Instance *inst = network_->instance(end->vertex(this)->pin());
const char *inst_name = cmd_network_->pathName(inst);
- const char *clk_name = tgtClkName(end);
+ string clk_name = tgtClkName(end);
const char *rise_fall = asRisingFalling(end->targetClkEndTrans(this));
const TimingRole *check_role = end->checkRole(this);
const TimingRole *check_generic_role = check_role->genericRole();
if (check_role == TimingRole::recovery()
|| check_role == TimingRole::removal()) {
const char *check_role_name = check_role->asString();
- char *reason = stringPrintTmp(strlen(" check against -edge clock ")
- + strlen(check_role_name)
- + strlen(rise_fall)
- + strlen(clk_name) + 1,
- "%s check against %s-edge clock %s",
- check_role_name,
- rise_fall,
- clk_name);
+ auto reason = stdstrPrint("%s check against %s-edge clock %s",
+ check_role_name,
+ rise_fall,
+ clk_name.c_str());
reportEndpoint(inst_name, reason, result);
}
else if (check_generic_role == TimingRole::setup()
|| check_generic_role == TimingRole::hold()) {
LibertyCell *cell = network_->libertyCell(inst);
if (cell->isClockGate()) {
- const char *reason =
- stringPrintTmp(strlen( " clock gating-check end-point clocked by ")
- + strlen(rise_fall)
- + strlen(clk_name) + 1,
- "%s clock gating-check end-point clocked by %s",
- rise_fall, clk_name);
+ auto reason = stdstrPrint("%s clock gating-check end-point clocked by %s",
+ rise_fall, clk_name.c_str());
reportEndpoint(inst_name, reason, result);
}
else {
const char *reg_desc = clkRegLatchDesc(end);
- const char *reason = stringPrintTmp(strlen( " clocked by ")
- + strlen(reg_desc)
- + strlen(clk_name) + 1,
- "%s clocked by %s",
- reg_desc, clk_name);
+ auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str());
reportEndpoint(inst_name, reason, result);
}
}
@@ -604,13 +587,9 @@ ReportPath::reportEndpoint(const PathEndLatchCheck *end,
{
Instance *inst = network_->instance(end->vertex(this)->pin());
const char *inst_name = cmd_network_->pathName(inst);
- const char *clk_name = tgtClkName(end);
+ string clk_name = tgtClkName(end);
const char *reg_desc = latchDesc(end);
- const char *reason = stringPrintTmp(strlen( " clocked by ")
- + strlen(reg_desc)
- + strlen(clk_name) + 1,
- "%s clocked by %s",
- reg_desc, clk_name);
+ auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str());
reportEndpoint(inst_name, reason, result);
}
@@ -646,25 +625,19 @@ ReportPath::reportBorrowing(const PathEndLatchCheck *end,
if (borrow_limit_exists)
reportLineTotal("user max time borrow", max_borrow, early_late, result);
else {
- const char *tgt_clk_name = tgtClkName(end);
+ string tgt_clk_name = tgtClkName(end);
Arrival tgt_clk_width = end->targetClkWidth(this);
const Path *tgt_clk_path = end->targetClkPath();
if (tgt_clk_path->clkInfo(search_)->isPropagated()) {
- const char *width_msg = stringPrintTmp(strlen(" nominal pulse width")
- + strlen(tgt_clk_name) + 1,
- "%s nominal pulse width",
- tgt_clk_name);
- reportLineTotal(width_msg, nom_pulse_width, early_late, result);
+ auto width_msg = stdstrPrint("%s nominal pulse width", tgt_clk_name.c_str());
+ reportLineTotal(width_msg.c_str(), nom_pulse_width, early_late, result);
if (!delayFuzzyZero(latency_diff))
reportLineTotalMinus("clock latency difference", latency_diff,
early_late, result);
}
else {
- const char *width_msg = stringPrintTmp(strlen(" pulse width")
- + strlen(tgt_clk_name) + 1,
- "%s pulse width",
- tgt_clk_name);
- reportLineTotal(width_msg, tgt_clk_width, early_late, result);
+ auto width_msg = stdstrPrint("%s pulse width", tgt_clk_name.c_str());
+ reportLineTotal(width_msg.c_str(), tgt_clk_width, early_late, result);
}
ArcDelay margin = end->margin(this);
reportLineTotalMinus("library setup time", margin, early_late, result);
@@ -721,14 +694,9 @@ ReportPath::reportEndpoint(const PathEndPathDelay *end,
{
Instance *inst = network_->instance(end->vertex(this)->pin());
const char *inst_name = cmd_network_->pathName(inst);
- const char *clk_name = tgtClkName(end);
+ string clk_name = tgtClkName(end);
const char *reg_desc = clkRegLatchDesc(end);
- const char *reason = stringPrintTmp(strlen(" clocked by ")
- + strlen(reg_desc)
- + strlen(clk_name) + 1,
- "%s clocked by %s",
- reg_desc,
- clk_name);
+ auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str());
reportEndpoint(inst_name, reason, result);
}
@@ -760,18 +728,10 @@ ReportPath::reportFull(const PathEndPathDelay *end,
if (min_max == MinMax::max())
margin = -margin;
- const char *margin_what;
- if (end->pathDelayMarginIsExternal())
- margin_what = "output external delay";
- else
- margin_what = checkRoleString(end);
const char *min_max_str = min_max->asString();
- char *delay_msg = stringPrintTmp(strlen(" delay")
- + strlen(min_max_str) + 1,
- "%s_delay",
- min_max_str);
+ auto delay_msg = stdstrPrint("%s_delay", min_max_str);
float delay = path_delay->delay();
- reportLine(delay_msg, delay, delay, early_late, result);
+ reportLine(delay_msg.c_str(), delay, delay, early_late, result);
if (!path_delay->ignoreClkLatency()) {
const Path *tgt_clk_path = end->targetClkPath();
if (tgt_clk_path) {
@@ -792,7 +752,10 @@ ReportPath::reportFull(const PathEndPathDelay *end,
}
}
}
- reportRequired(end, margin_what, result);
+ if (end->pathDelayMarginIsExternal())
+ reportRequired(end, "output external delay", result);
+ else
+ reportRequired(end, checkRoleString(end), result);
reportSlack(end, result);
}
@@ -864,11 +827,8 @@ ReportPath::reportEndpoint(const PathEndOutputDelay *end,
if (network_->isTopLevelPort(pin)) {
// Pin direction is "output" even for bidirects.
if (tgt_clk) {
- const char *clk_name = tgtClkName(end);
- const char *reason = stringPrintTmp(strlen("output port clocked by ")
- + strlen(clk_name) + 1,
- "output port clocked by %s",
- clk_name);
+ string clk_name = tgtClkName(end);
+ auto reason = stdstrPrint("output port clocked by %s", clk_name.c_str());
reportEndpoint(pin_name, reason, result);
}
else
@@ -876,11 +836,8 @@ ReportPath::reportEndpoint(const PathEndOutputDelay *end,
}
else {
if (tgt_clk) {
- const char *clk_name = tgtClkName(end);
- const char *reason = stringPrintTmp(strlen("internal path endpoint clocked by ")
- + strlen(clk_name) + 1,
- "internal path endpoint clocked by %s",
- clk_name);
+ string clk_name = tgtClkName(end);
+ auto reason = stdstrPrint("internal path endpoint clocked by %s", clk_name.c_str());
reportEndpoint(pin_name, reason, result);
}
else
@@ -926,18 +883,15 @@ ReportPath::reportEndpoint(const PathEndGatedClock *end,
{
Instance *inst = network_->instance(end->vertex(this)->pin());
const char *inst_name = cmd_network_->pathName(inst);
- const char *clk_name = tgtClkName(end);
+ string clk_name = tgtClkName(end);
const TransRiseFall *clk_end_tr = end->targetClkEndTrans(this);
const TransRiseFall *clk_tr =
(end->minMax(this) == MinMax::max()) ? clk_end_tr : clk_end_tr->opposite();
const char *rise_fall = asRisingFalling(clk_tr);
// Note that target clock transition is ignored.
- const char *reason = stringPrintTmp(strlen(" clock gating-check end-point clocked by ")
- + strlen(rise_fall)
- + strlen(clk_name) + 1,
- "%s clock gating-check end-point clocked by %s",
- rise_fall,
- clk_name);
+ auto reason = stdstrPrint("%s clock gating-check end-point clocked by %s",
+ rise_fall,
+ clk_name.c_str());
reportEndpoint(inst_name, reason, result);
}
@@ -1002,12 +956,9 @@ ReportPath::reportEndpoint(const PathEndDataCheck *end,
const char *inst_name = cmd_network_->pathName(inst);
const char *tgt_clk_tr = asRisingFalling(end->dataClkPath()->transition(this));
const char *tgt_clk_name = end->targetClk(this)->name();
- char *reason = stringPrintTmp(strlen(" edge-triggered data to data check clocked by ")
- + strlen(tgt_clk_tr)
- + strlen(tgt_clk_name) + 1,
- "%s edge-triggered data to data check clocked by %s",
- tgt_clk_tr,
- tgt_clk_name);
+ auto reason = stdstrPrint("%s edge-triggered data to data check clocked by %s",
+ tgt_clk_tr,
+ tgt_clk_name);
reportEndpoint(inst_name, reason, result);
}
@@ -1044,7 +995,8 @@ ReportPath::reportEndLine(PathEnd *end,
string &result)
{
const EarlyLate *early_late = end->pathEarlyLate(this);
- reportDescription(pathEndpoint(end), result);
+ string endpoint = pathEndpoint(end);
+ reportDescription(endpoint.c_str(), result);
reportSpaceFieldDelay(end->requiredTimeOffset(this), early_late, result);
reportSpaceFieldDelay(end->dataArrivalTimeOffset(this), early_late, result);
Slack slack = end->slack(this);
@@ -1074,8 +1026,10 @@ ReportPath::reportSummaryLine(PathEnd *end,
{
PathExpanded expanded(end->path(), this);
const EarlyLate *early_late = end->pathEarlyLate(this);
- reportDescription(pathStartpoint(end, expanded), result);
- reportDescription(pathEndpoint(end), result);
+ auto startpoint = pathStartpoint(end, expanded);
+ reportDescription(startpoint.c_str(), result);
+ auto endpoint = pathEndpoint(end);
+ reportDescription(endpoint.c_str(), result);
if (end->isUnconstrained())
reportSpaceFieldDelay(end->dataArrivalTimeOffset(this), early_late, result);
else
@@ -1083,7 +1037,7 @@ ReportPath::reportSummaryLine(PathEnd *end,
reportEndOfLine(result);
}
-const char *
+string
ReportPath::pathStartpoint(PathEnd *end,
PathExpanded &expanded)
{
@@ -1092,40 +1046,28 @@ ReportPath::pathStartpoint(PathEnd *end,
const char *pin_name = cmd_network_->pathName(pin);
if (network_->isTopLevelPort(pin)) {
PortDirection *dir = network_->direction(pin);
- const char *dir_str = dir->name();
- return stringPrintTmp(strlen(pin_name) + strlen(dir_str) + 4,
- "%s (%s)",
- pin_name, dir_str);
+ return stdstrPrint("%s (%s)", pin_name, dir->name());
}
else {
Instance *inst = network_->instance(end->vertex(this)->pin());
const char *cell_name = cmd_network_->name(network_->cell(inst));
- return stringPrintTmp(strlen(pin_name) + strlen(cell_name) + 4,
- "%s (%s)",
- pin_name,
- cell_name);
+ return stdstrPrint("%s (%s)", pin_name, cell_name);
}
}
-const char *
+string
ReportPath::pathEndpoint(PathEnd *end)
{
Pin *pin = end->vertex(this)->pin();
const char *pin_name = cmd_network_->pathName(pin);
if (network_->isTopLevelPort(pin)) {
PortDirection *dir = network_->direction(pin);
- const char *dir_str = dir->name();
- return stringPrintTmp(strlen(pin_name) + strlen(dir_str) + 4,
- "%s (%s)",
- pin_name, dir_str);
+ return stdstrPrint("%s (%s)", pin_name, dir->name());
}
else {
Instance *inst = network_->instance(end->vertex(this)->pin());
const char *cell_name = cmd_network_->name(network_->cell(inst));
- return stringPrintTmp(strlen(pin_name) + strlen(cell_name) + 4,
- "%s (%s)",
- pin_name,
- cell_name);
+ return stdstrPrint("%s (%s)", pin_name, cell_name);
}
}
@@ -1237,13 +1179,8 @@ ReportPath::reportShort(MinPulseWidthCheck *check,
{
const char *pin_name = cmd_network_->pathName(check->pin(this));
const char *hi_low = mpwCheckHiLow(check);
- char *what = stringPrintTmp(strlen(" ()")
- + strlen(pin_name)
- + strlen(hi_low) + 1,
- "%s (%s)",
- pin_name,
- hi_low);
- reportDescription(what, result);
+ auto what = stdstrPrint("%s (%s)", pin_name, hi_low);
+ reportDescription(what.c_str(), result);
reportSpaceFieldTime(check->minWidth(this), result);
reportSpaceFieldDelay(check->width(this), EarlyLate::late(), result);
Slack slack = check->slack(this);
@@ -1271,13 +1208,8 @@ ReportPath::reportVerbose(MinPulseWidthCheck *check,
const char *open_clk_name = open_clk->name();
const char *open_rise_fall = asRiseFall(open_clk_edge->transition());
float open_clk_time = open_clk_edge->time();
- const char *open_clk_msg = stringPrintTmp(strlen("clock ( edge)")
- + strlen(open_clk_name)
- + strlen(open_rise_fall) + 1,
- "clock %s (%s edge)",
- open_clk_name,
- open_rise_fall);
- reportLine(open_clk_msg, open_clk_time, open_clk_time,
+ auto open_clk_msg = stdstrPrint("clock %s (%s edge)", open_clk_name, open_rise_fall);
+ reportLine(open_clk_msg.c_str(), open_clk_time, open_clk_time,
open_el, result);
Arrival open_arrival = check->openArrival(this);
bool is_prop = isPropagated(check->openPath());
@@ -1295,13 +1227,8 @@ ReportPath::reportVerbose(MinPulseWidthCheck *check,
const char *close_rise_fall = asRiseFall(close_clk_edge->transition());
float close_offset = check->closeOffset(this);
float close_clk_time = close_clk_edge->time() + close_offset;
- const char *close_clk_msg = stringPrintTmp(strlen("clock ( edge)")
- + strlen(close_clk_name)
- + strlen(close_rise_fall) + 1,
- "clock %s (%s edge)",
- close_clk_name,
- close_rise_fall);
- reportLine(close_clk_msg, close_clk_time, close_clk_time, close_el, result);
+ auto close_clk_msg = stdstrPrint("clock %s (%s edge)", close_clk_name, close_rise_fall);
+ reportLine(close_clk_msg.c_str(), close_clk_time, close_clk_time, close_el, result);
Arrival close_arrival = check->closeArrival(this) + close_offset;
reportLine(clk_ideal_prop, check->closeDelay(this), close_arrival,
close_el, result);
@@ -1318,13 +1245,9 @@ ReportPath::reportVerbose(MinPulseWidthCheck *check,
reportDashLine(result);
float min_width = check->minWidth(this);
const char *hi_low = mpwCheckHiLow(check);
- const char *rpw_msg = stringPrintTmp(strlen("required pulse width ()")
- + strlen(hi_low) + 1,
- "required pulse width (%s)",
- hi_low);
- reportLine(rpw_msg, min_width, EarlyLate::early(), result);
- reportLine("actual pulse width", check->width(this),
- EarlyLate::early(), result);
+ auto rpw_msg = stdstrPrint("required pulse width (%s)", hi_low);
+ reportLine(rpw_msg.c_str(), min_width, EarlyLate::early(), result);
+ reportLine("actual pulse width", check->width(this), EarlyLate::early(), result);
reportDashLine(result);
reportSlack(check->slack(this), result);
}
@@ -1530,13 +1453,11 @@ ReportPath::reportShort(MaxSkewCheck *check,
Pin *clk_pin = check->clkPin(this);
const char *clk_pin_name = network_->pathName(clk_pin);
TimingArc *check_arc = check->checkArc();
- const char *what = stringPrintTmp(strlen(clk_pin_name)
- + strlen(" (r->r)") + 1,
- "%s (%s->%s)",
- clk_pin_name,
- check_arc->fromTrans()->asString(),
- check_arc->toTrans()->asString());
- reportDescription(what, result);
+ auto what = stdstrPrint("%s (%s->%s)",
+ clk_pin_name,
+ check_arc->fromTrans()->asString(),
+ check_arc->toTrans()->asString());
+ reportDescription(what.c_str(), result);
reportSpaceFieldDelay(check->maxSkew(this), EarlyLate::early(), result);
reportSpaceFieldDelay(check->skew(this), EarlyLate::early(), result);
Slack slack = check->slack(this);
@@ -1586,16 +1507,15 @@ ReportPath::reportSkewClkPath(const char *arrival_msg,
const EarlyLate *early_late = clk_path->minMax(this);
const TransRiseFall *clk_tr = clk_edge->transition();
const TransRiseFall *clk_end_tr = clk_path->transition(this);
- const char *clk_name = (clk_end_tr == clk_tr)
- ? clk->name()
- : clkNameInverted(clk->name());
+ string clk_name = clkName(clk, clk_end_tr != clk_tr);
float clk_time = clk_edge->time();
const Arrival &clk_arrival = search_->clkPathArrival(clk_path);
Arrival clk_delay = clk_arrival - clk_time;
PathAnalysisPt *path_ap = clk_path->pathAnalysisPt(this);
const MinMax *min_max = path_ap->pathMinMax();
Vertex *clk_vertex = clk_path->vertex(this);
- reportClkLine(clk, clk_name, clk_end_tr, clk_time, min_max, result);
+ reportClkLine(clk, clk_name.c_str(), clk_end_tr, clk_time, min_max, result);
+
bool is_prop = isPropagated(clk_path);
if (is_prop && reportClkPath()) {
const EarlyLate *early_late = TimingRole::skew()->tgtClkEarlyLate();
@@ -1614,8 +1534,8 @@ ReportPath::reportSkewClkPath(const char *arrival_msg,
else {
reportLine(clkNetworkDelayIdealProp(is_prop), clk_delay, clk_arrival,
early_late, result);
- reportLine(descriptionField(clk_vertex), clk_arrival, early_late,
- clk_end_tr, result);
+ reportLine(descriptionField(clk_vertex).c_str(), clk_arrival,
+ early_late, clk_end_tr, result);
}
reportLine(arrival_msg, search_->clkPathArrival(clk_path),
early_late, result);
@@ -1741,9 +1661,7 @@ ReportPath::reportStartpoint(const PathEnd *end,
const char *pin_name = cmd_network_->pathName(pin);
if (pathFromClkPin(path, pin)) {
const char *clk_name = clk->name();
- const char *reason = stringPrintTmp(strlen("clock source ''")
- + strlen(clk_name) + 1,
- "clock source '%s'", clk_name);
+ auto reason = stdstrPrint("clock source '%s'", clk_name);
reportStartpoint(pin_name, reason, result);
}
else if (network_->isTopLevelPort(pin)) {
@@ -1751,10 +1669,7 @@ ReportPath::reportStartpoint(const PathEnd *end,
&& clk != sdc_->defaultArrivalClock()) {
const char *clk_name = clk->name();
// Pin direction is "input" even for bidirects.
- const char *reason=stringPrintTmp(strlen("input port clocked by ")
- + strlen(clk_name) + 1,
- "input port clocked by %s",
- clk_name);
+ auto reason = stdstrPrint("input port clocked by %s", clk_name);
reportStartpoint(pin_name, reason, result);
}
else
@@ -1764,22 +1679,14 @@ ReportPath::reportStartpoint(const PathEnd *end,
Instance *inst = network_->instance(pin);
const char *inst_name = cmd_network_->pathName(inst);
if (clk_edge) {
- const char *clk_name = clk->name();
const TransRiseFall *clk_tr = clk_edge->transition();
- const TransRiseFall *clk_end_tr = clk_tr;
PathRef clk_path;
expanded.clkPath(clk_path);
- if (!clk_path.isNull()) {
- clk_end_tr = clk_path.transition(this);
- if (clk_end_tr != clk_tr)
- clk_name = clkNameInverted(clk_name);
- }
+ bool clk_inverted = !clk_path.isNull()
+ && clk_tr != clk_path.transition(this);
+ string clk_name = clkName(clk, clk_inverted);
const char *reg_desc = edgeRegLatchDesc(prev_edge, prev_arc);
- const char *reason = stringPrintTmp(strlen(" clocked by ")
- + strlen(reg_desc)
- + strlen(clk_name) + 1,
- "%s clocked by %s",
- reg_desc, clk_name);
+ auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str());
reportStartpoint(inst_name, reason, result);
}
else {
@@ -1792,11 +1699,7 @@ ReportPath::reportStartpoint(const PathEnd *end,
Clock *clk = clk_edge->clock();
if (clk != sdc_->defaultArrivalClock()) {
const char *clk_name = clk->name();
- const char *reason =
- stringPrintTmp(strlen("internal path startpoint clocked by ")
- + strlen(clk_name) + 1,
- "internal path startpoint clocked by %s",
- clk_name);
+ auto reason = stdstrPrint("internal path startpoint clocked by %s", clk_name);
reportStartpoint(pin_name, reason, result);
}
else
@@ -1830,7 +1733,7 @@ ReportPath::pathFromClkPin(const Path *path,
void
ReportPath::reportStartpoint(const char *start,
- const char *reason,
+ string reason,
string &result)
{
reportStartEndPoint(start, reason, "Startpoint", result);
@@ -1880,19 +1783,21 @@ ReportPath::reportUnclockedEndpoint(const PathEnd *end,
}
void
-ReportPath::reportEndpoint(const char *end, const char *reason, string &result)
+ReportPath::reportEndpoint(const char *end,
+ string reason,
+ string &result)
{
reportStartEndPoint(end, reason, "Endpoint", result);
}
void
ReportPath::reportStartEndPoint(const char *pt,
- const char *reason,
+ string reason,
const char *key,
string &result)
{
// Account for punctuation in the line.
- int line_len = strlen(key) + 2 + strlen(pt) + 2 + strlen(reason) + 1;
+ int line_len = strlen(key) + 2 + strlen(pt) + 2 + reason.size() + 1;
if (!no_split_
&& line_len > start_end_pt_width_) {
result += key;
@@ -1936,34 +1841,31 @@ ReportPath::reportGroup(const PathEnd *end,
////////////////////////////////////////////////////////////////
-const char *
+string
ReportPath::checkRoleReason(const PathEnd *end)
{
const char *setup_hold = end->checkRole(this)->asString();
- return stringPrintTmp(strlen(" time")
- + strlen(setup_hold) + 1,
- "%s time",
- setup_hold);
+ return stdstrPrint("%s time", setup_hold);
}
-const char *
+string
ReportPath::tgtClkName(const PathEnd *end)
{
ClockEdge *tgt_clk_edge = end->targetClkEdge(this);
const Clock *tgt_clk = tgt_clk_edge->clock();
const TransRiseFall *clk_tr = tgt_clk_edge->transition();
const TransRiseFall *clk_end_tr = end->targetClkEndTrans(this);
- const char *clk_name = tgt_clk->name();
- if (clk_end_tr == clk_tr)
- return clk_name;
- else
- return clkNameInverted(clk_name);
+ return clkName(tgt_clk, clk_end_tr != clk_tr);
}
-const char *
-ReportPath::clkNameInverted(const char *clk_name)
+string
+ReportPath::clkName(const Clock *clk,
+ bool inverted)
{
- return stringPrintTmp(strlen(clk_name) + 2, "%s'", clk_name);
+ string name = clk->name();
+ if (inverted)
+ name += '\'';
+ return name;
}
const char *
@@ -2055,18 +1957,13 @@ ReportPath::reportSrcClkAndPath(const Path *path,
PathRef clk_path;
expanded.clkPath(clk_path);
const TransRiseFall *clk_end_tr;
- const char *clk_name;
if (!clk_path.isNull()) {
clk_end_time = search_->clkPathArrival(&clk_path) + time_offset;
clk_delay = clk_end_time - clk_time;
clk_end_tr = clk_path.transition(this);
- clk_name = (clk_end_tr == clk_tr)
- ? clk->name()
- : clkNameInverted(clk->name());
}
else {
// Path from input port or clk used as data.
- clk_name = clk->name();
clk_end_tr = clk_tr;
clk_delay = clk_insertion + clk_latency;
clk_end_time = clk_time + clk_delay;
@@ -2088,6 +1985,7 @@ ReportPath::reportSrcClkAndPath(const Path *path,
}
}
}
+ string clk_name = clkName(clk, clk_tr != clk_end_tr);
bool clk_used_as_data = pathFromClkPin(expanded);
bool is_prop = isPropagated(path);
@@ -2095,7 +1993,8 @@ ReportPath::reportSrcClkAndPath(const Path *path,
if (reportGenClkSrcPath(clk_path.isNull() ? NULL : &clk_path,
clk, clk_tr, min_max, early_late)
&& !(path_from_input && !input_has_ref_path)) {
- reportClkLine(clk, clk_name, clk_end_tr, clk_time, min_max, result);
+ reportClkLine(clk, clk_name.c_str(), clk_end_tr, clk_time,
+ min_max, result);
const PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
reportGenClkSrcAndPath(path, clk, clk_tr, early_late, path_ap,
time_offset, time_offset, clk_used_as_data,
@@ -2103,7 +2002,8 @@ ReportPath::reportSrcClkAndPath(const Path *path,
}
else if (clk_used_as_data
&& pathFromGenPropClk(path, path->minMax(this))) {
- reportClkLine(clk, clk_name, clk_end_tr, clk_time, min_max, result);
+ reportClkLine(clk, clk_name.c_str(), clk_end_tr, clk_time,
+ min_max, result);
ClkInfo *clk_info = path->tag(search_)->clkInfo();
if (clk_info->isPropagated())
reportClkSrcLatency(clk_insertion, clk_time, early_late, result);
@@ -2112,12 +2012,14 @@ ReportPath::reportSrcClkAndPath(const Path *path,
else if (is_prop
&& reportClkPath()
&& !(path_from_input && !input_has_ref_path)) {
- reportClkLine(clk, clk_name, clk_end_tr, clk_time, early_late, result);
+ reportClkLine(clk, clk_name.c_str(), clk_end_tr, clk_time,
+ early_late, result);
reportClkSrcLatency(clk_insertion, clk_time, early_late, result);
reportPath1(path, expanded, false, time_offset, result);
}
else if (clk_used_as_data) {
- reportClkLine(clk, clk_name, clk_end_tr, clk_time, early_late, result);
+ reportClkLine(clk, clk_name.c_str(), clk_end_tr, clk_time,
+ early_late, result);
if (clk_insertion > 0.0)
reportClkSrcLatency(clk_insertion, clk_time, early_late, result);
reportPath1(path, expanded, true, time_offset, result);
@@ -2129,7 +2031,8 @@ ReportPath::reportSrcClkAndPath(const Path *path,
clk_end_time, early_late, result);
}
else {
- reportClkLine(clk, clk_name, clk_end_tr, clk_time, min_max, result);
+ reportClkLine(clk, clk_name.c_str(), clk_end_tr, clk_time,
+ min_max, result);
Arrival clk_arrival = clk_end_time;
reportLine(clkNetworkDelayIdealProp(is_prop), clk_delay,
clk_arrival, early_late, result);
@@ -2170,9 +2073,7 @@ ReportPath::reportTgtClk(const PathEnd *end,
Clock *clk = clk_edge->clock();
const TransRiseFall *clk_tr = clk_edge->transition();
const TransRiseFall *clk_end_tr = end->targetClkEndTrans(this);
- const char *clk_name = (clk_end_tr == clk_tr)
- ? clk->name()
- : clkNameInverted(clk->name());
+ string clk_name = clkName(clk, clk_end_tr != clk_tr);
float clk_time = prev_time
+ end->targetClkTime(this)
+ end->targetClkMcpAdjustment(this)
@@ -2182,7 +2083,8 @@ ReportPath::reportTgtClk(const PathEnd *end,
PathAnalysisPt *path_ap = end->pathAnalysisPt(this)->tgtClkAnalysisPt();
const MinMax *min_max = path_ap->pathMinMax();
const Path *clk_path = end->targetClkPath();
- reportClkLine(clk, clk_name, clk_end_tr, prev_time, clk_time, min_max, result);
+ reportClkLine(clk, clk_name.c_str(), clk_end_tr, prev_time, clk_time,
+ min_max, result);
TimingRole *check_role = end->checkRole(this);
if (is_prop && reportClkPath()) {
float time_offset = prev_time
@@ -2224,7 +2126,7 @@ ReportPath::reportTgtClk(const PathEnd *end,
reportCommonClkPessimism(end, clk_arrival, result);
if (clk_path) {
Vertex *clk_vertex = clk_path->vertex(this);
- reportLine(descriptionField(clk_vertex),
+ reportLine(descriptionField(clk_vertex).c_str(),
prev_time
+ end->targetClkArrival(this)
+ end->sourceClkOffset(this),
@@ -2311,18 +2213,13 @@ ReportPath::reportClkLine(const Clock *clk,
string &result)
{
const char *rise_fall = asRiseFall(clk_tr);
- const char *clk_msg = stringPrintTmp(strlen("clock ( edge)")
- + strlen(clk_name)
- + strlen(rise_fall) + 1,
- "clock %s (%s edge)",
- clk_name,
- rise_fall);
+ auto clk_msg = stdstrPrint("clock %s (%s edge)", clk_name, rise_fall);
if (clk->isPropagated())
- reportLine(clk_msg, clk_time - prev_time, clk_time, min_max, result);
+ reportLine(clk_msg.c_str(), clk_time - prev_time, clk_time, min_max, result);
else {
// Report ideal clock slew.
float clk_slew = clk->slew(clk_tr, min_max);
- reportLine(clk_msg, clk_slew, clk_time - prev_time, clk_time,
+ reportLine(clk_msg.c_str(), clk_slew, clk_time - prev_time, clk_time,
min_max, result);
}
}
@@ -2453,7 +2350,7 @@ ReportPath::reportPathLine(const Path *path,
{
Vertex *vertex = path->vertex(this);
Pin *pin = vertex->pin();
- const char *what = descriptionField(vertex);
+ auto what = descriptionField(vertex);
const TransRiseFall *tr = path->transition(this);
bool is_driver = network_->isDriver(pin);
PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
@@ -2465,13 +2362,13 @@ ReportPath::reportPathLine(const Path *path,
// Don't show capacitance field for input pins.
if (is_driver && field_capacitance_->enabled())
cap = loadCap(pin, tr, dcalc_ap);
- reportLine(what, cap, slew, field_blank_,
+ reportLine(what.c_str(), cap, slew, field_blank_,
incr, time, false, early_late, tr, line_case, result);
}
void
ReportPath::reportRequired(const PathEnd *end,
- const char *margin_msg,
+ string margin_msg,
string &result)
{
Required req_time = end->requiredTimeOffset(this);
@@ -2479,7 +2376,7 @@ ReportPath::reportRequired(const PathEnd *end,
ArcDelay margin = end->margin(this);
if (end->minMax(this) == MinMax::max())
margin = -margin;
- reportLine(margin_msg, margin, req_time, early_late, result);
+ reportLine(margin_msg.c_str(), margin, req_time, early_late, result);
reportLine("data required time", req_time, early_late, result);
reportDashLine(result);
}
@@ -2784,36 +2681,33 @@ ReportPath::reportPath5(const Path *path,
// Don't show capacitance field for input pins.
if (is_driver && field_capacitance_->enabled())
cap = loadCap(pin, tr, dcalc_ap);
- const char *what = descriptionField(vertex);
+ auto what = descriptionField(vertex);
if (report_net_ && is_driver) {
// Capacitance field is reported on the net line.
- reportLine(what, field_blank_, slew, field_blank_,
+ reportLine(what.c_str(), field_blank_, slew, field_blank_,
incr, time, false, min_max, tr, line_case, result);
+ string what2;
if (network_->isTopLevelPort(pin)) {
const char *pin_name = cmd_network_->pathName(pin);
- what = stringPrintTmp(strlen(" (net)")
- + strlen(pin_name) + 1,
- "%s (net)", pin_name);
+ what2 = stdstrPrint("%s (net)", pin_name);
}
else {
Net *net = network_->net(pin);
if (net) {
Net *highest_net = network_->highestNetAbove(net);
const char *net_name = cmd_network_->pathName(highest_net);
- what = stringPrintTmp(strlen(" (net)")
- + strlen(net_name) + 1,
- "%s (net)", net_name);
+ what2 = stdstrPrint("%s (net)", net_name);
}
else
- what = "(unconnected)";
+ what2 = "(unconnected)";
}
float fanout = drvrFanout(vertex, min_max);
- reportLine(what, cap, field_blank_, fanout,
+ reportLine(what2.c_str(), cap, field_blank_, fanout,
field_blank_, field_blank_, false, min_max, NULL,
line_case, result);
}
else
- reportLine(what, cap, slew, field_blank_,
+ reportLine(what.c_str(), cap, slew, field_blank_,
incr, time, false, min_max, tr, line_case, result);
prev_time = time;
}
@@ -2834,7 +2728,7 @@ ReportPath::nextArcAnnotated(const PathRef *next_path,
return graph_->arcDelayAnnotated(edge, arc, ap_index);
}
-char *
+string
ReportPath::descriptionField(Vertex *vertex)
{
Pin *pin = vertex->pin();
@@ -2858,21 +2752,7 @@ ReportPath::descriptionField(Vertex *vertex)
Instance *inst = network_->instance(pin);
name2 = network_->cellName(inst);
}
- // stringPrintTmp("%s (%s)", pin_name, name2)
- size_t pin_name_length = strlen(pin_name);
- size_t name2_length = strlen(name2);
- char *result = makeTmpString(pin_name_length + name2_length
- + 4 /* strlen(" ()") + '\0' */);
- char *s = result;
- strcpy(s, pin_name);
- s += pin_name_length;
- *s++ = ' ';
- *s++ = '(';
- strcpy(s, name2);
- s += name2_length;
- *s++ = ')';
- *s++ = '\0';
- return result;
+ return stdstrPrint("%s (%s)", pin_name, name2);
}
float
@@ -3125,12 +3005,10 @@ ReportPath::reportLine(const char *what,
else if (field == field_fanout_) {
if (fanout == field_blank_)
reportFieldBlank(field, result);
- else {
- char *field = stringPrintTmp(field_fanout_->width() + 1, "%*d",
- field_fanout_->width(),
- static_cast(fanout));
- result += field;
- }
+ else
+ result += stdstrPrint("%*d",
+ field_fanout_->width(),
+ static_cast(fanout));
}
else if (field == field_capacitance_)
reportField(cap, field, result);
diff --git a/search/ReportPath.hh b/search/ReportPath.hh
index d9de9820..e0ea40b5 100644
--- a/search/ReportPath.hh
+++ b/search/ReportPath.hh
@@ -232,9 +232,9 @@ protected:
string &result);
void reportEndpoint(const PathEndGatedClock *end,
string &result);
- const char *pathEndpoint(PathEnd *end);
- const char *pathStartpoint(PathEnd *end,
- PathExpanded &expanded);
+ string pathEndpoint(PathEnd *end);
+ string pathStartpoint(PathEnd *end,
+ PathExpanded &expanded);
void reportBorrowing(const PathEndLatchCheck *end,
Arrival &borrow,
Arrival &time_given_to_startpoint,
@@ -243,8 +243,8 @@ protected:
string &result);
const char *clkNetworkDelayIdealProp(bool is_ideal);
- const char *checkRoleReason(const PathEnd *end);
- char *checkRoleString(const PathEnd *end);
+ string checkRoleReason(const PathEnd *end);
+ string checkRoleString(const PathEnd *end);
virtual void reportGroup(const PathEnd *end,
string &result);
void reportStartpoint(const PathEnd *end,
@@ -259,16 +259,16 @@ protected:
string &result);
const char *latchDesc(const PathEndLatchCheck *end);
void reportStartpoint(const char *start,
- const char *reason,
+ string reason,
string &result);
void reportEndpoint(const char *end,
- const char *reason,
+ string reason,
string &result);
void reportStartEndPoint(const char *pt,
- const char *reason,
+ string reason,
const char *key,
string &result);
- const char *tgtClkName(const PathEnd *end);
+ string tgtClkName(const PathEnd *end);
const char *clkRegLatchDesc(const PathEnd *end);
void reportSrcPath(const PathEnd *end,
PathExpanded &expanded,
@@ -344,7 +344,7 @@ protected:
const MinMax *min_max,
string &result);
void reportRequired(const PathEnd *end,
- const char *margin_msg,
+ string margin_msg,
string &result);
void reportSlack(const PathEnd *end,
string &result);
@@ -486,9 +486,10 @@ protected:
void reportDashLine(int line_width,
string &result);
void reportEndOfLine(string &result);
- char *descriptionField(Vertex *vertex);
+ string descriptionField(Vertex *vertex);
bool reportClkPath() const;
- const char *clkNameInverted(const char *clk_name);
+ string clkName(const Clock *clk,
+ bool inverted);;
bool hasExtInputDriver(const Pin *pin,
const TransRiseFall *tr,
const MinMax *min_max);
diff --git a/search/Sta.cc b/search/Sta.cc
index a02a6aa0..69a8924a 100644
--- a/search/Sta.cc
+++ b/search/Sta.cc
@@ -56,7 +56,7 @@
#include "Latches.hh"
#include "PathGroup.hh"
#include "CheckTiming.hh"
-#include "ReadParasitics.hh"
+#include "SpefReader.hh"
#include "CheckSlewLimits.hh"
#include "CheckMinPulseWidths.hh"
#include "CheckMinPeriods.hh"
@@ -231,6 +231,7 @@ initSta()
Transition::init();
TimingRole::init();
PortDirection::init();
+ initTmpStrings();
initLiberty();
initDelayConstants();
registerDelayCalcs();
@@ -3407,17 +3408,17 @@ Sta::setResistance(Net *net,
////////////////////////////////////////////////////////////////
bool
-Sta::readParasitics(const char *filename,
- Instance *instance,
- const MinMaxAll *min_max,
- bool increment,
- bool pin_cap_included,
- bool keep_coupling_caps,
- float coupling_cap_factor,
- ReduceParasiticsTo reduce_to,
- bool delete_after_reduce,
- bool save,
- bool quiet)
+Sta::readSpef(const char *filename,
+ Instance *instance,
+ const MinMaxAll *min_max,
+ bool increment,
+ bool pin_cap_included,
+ bool keep_coupling_caps,
+ float coupling_cap_factor,
+ ReduceParasiticsTo reduce_to,
+ bool delete_after_reduce,
+ bool save,
+ bool quiet)
{
Corner *corner = corners_->defaultCorner();
const MinMax *cnst_min_max;
@@ -3434,12 +3435,12 @@ Sta::readParasitics(const char *filename,
}
const OperatingConditions *op_cond =
sdc_->operatingConditions(cnst_min_max);
- bool success = readParasiticsFile(filename, instance, ap, increment,
- pin_cap_included,
- keep_coupling_caps, coupling_cap_factor,
- reduce_to, delete_after_reduce,
- op_cond, corner, cnst_min_max, save, quiet,
- report_, network_, parasitics_);
+ bool success = readSpefFile(filename, instance, ap, increment,
+ pin_cap_included,
+ keep_coupling_caps, coupling_cap_factor,
+ reduce_to, delete_after_reduce,
+ op_cond, corner, cnst_min_max, save, quiet,
+ report_, network_, parasitics_);
parasiticsChangedAfter();
return success;
}
diff --git a/search/Sta.hh b/search/Sta.hh
index 8d6e8f18..a7f143c2 100644
--- a/search/Sta.hh
+++ b/search/Sta.hh
@@ -1037,17 +1037,17 @@ public:
// networks (dspf) are reduced and deleted after reading each net
// with reduce_to and delete_after_reduce.
// Return true if successful.
- bool readParasitics(const char *filename,
- Instance *instance,
- const MinMaxAll *min_max,
- bool increment,
- bool pin_cap_included,
- bool keep_coupling_caps,
- float coupling_cap_factor,
- ReduceParasiticsTo reduce_to,
- bool delete_after_reduce,
- bool save,
- bool quiet);
+ bool readSpef(const char *filename,
+ Instance *instance,
+ const MinMaxAll *min_max,
+ bool increment,
+ bool pin_cap_included,
+ bool keep_coupling_caps,
+ float coupling_cap_factor,
+ ReduceParasiticsTo reduce_to,
+ bool delete_after_reduce,
+ bool save,
+ bool quiet);
// Parasitics.
void findPiElmore(Pin *drvr_pin,
const TransRiseFall *tr,
diff --git a/search/Tag.cc b/search/Tag.cc
index 22bec177..14226340 100644
--- a/search/Tag.cc
+++ b/search/Tag.cc
@@ -98,11 +98,11 @@ Tag::asString(bool report_index,
string str;
if (report_index)
- str += stringPrintTmp(6, "%4d ", index_);
+ str += stringPrintTmp("%4d ", index_);
const TransRiseFall *tr = transition();
PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index_);
- str += stringPrintTmp(25, "%s %s/%d ",
+ str += stringPrintTmp("%s %s/%d ",
tr->asString(),
path_ap->pathMinMax()->asString(),
path_ap_index_);
diff --git a/search/VisitPathEnds.cc b/search/VisitPathEnds.cc
index a1603006..6a3f4f15 100644
--- a/search/VisitPathEnds.cc
+++ b/search/VisitPathEnds.cc
@@ -359,8 +359,7 @@ VisitPathEnds::visitOutputDelayEnd1(OutputDelay *output_delay,
is_constrained = true;
}
else if (tgt_clk_edge
- && sdc_->sameClockGroup(path->clock(this),
- tgt_clk_edge->clock())
+ && sdc_->sameClockGroup(path->clock(this), tgt_clk_edge->clock())
// False paths and path delays override.
&& (exception == NULL
|| exception->isFilter()
diff --git a/search/WritePathSpice.cc b/search/WritePathSpice.cc
index ef7be1d0..83a0bc87 100644
--- a/search/WritePathSpice.cc
+++ b/search/WritePathSpice.cc
@@ -55,14 +55,11 @@ split(const string &text,
const string &delims,
// Return values.
StringVector &tokens);
+
void
streamPrint(ofstream &stream,
const char *fmt,
...) __attribute__((format (printf, 2, 3)));
-void
-stringPrint(string &str,
- const char *fmt,
- ...) __attribute__((format (printf, 2, 3)));
////////////////////////////////////////////////////////////////
@@ -231,6 +228,7 @@ WritePathSpice::WritePathSpice(Path *path,
WritePathSpice::~WritePathSpice()
{
+ stringDelete(net_name_);
cell_spice_port_names_.deleteContents();
}
@@ -257,17 +255,17 @@ WritePathSpice::writeSpice()
void
WritePathSpice::writeHeader()
{
- const MinMax *min_max = path_->minMax(this);
- const Pvt *pvt = sdc_->operatingConditions(min_max);
+ auto min_max = path_->minMax(this);
+ auto pvt = sdc_->operatingConditions(min_max);
if (pvt == NULL)
pvt = network_->defaultLibertyLibrary()->defaultOperatingConditions();
- float temp = pvt->temperature();
+ auto temp = pvt->temperature();
streamPrint(spice_stream_, ".temp %.1f\n", temp);
streamPrint(spice_stream_, ".include \"%s\"\n", model_filename_);
streamPrint(spice_stream_, ".include \"%s\"\n", subckt_filename_);
- float max_time = maxTime();
- float time_step = max_time / 1e+3;
+ auto max_time = maxTime();
+ auto time_step = max_time / 1e+3;
streamPrint(spice_stream_, ".tran %.3g %.3g\n\n",
time_step, max_time);
}
@@ -275,8 +273,8 @@ WritePathSpice::writeHeader()
float
WritePathSpice::maxTime()
{
- Stage input_stage = stageFirst();
- Path *input_path = stageDrvrPath(input_stage);
+ auto input_stage = stageFirst();
+ auto input_path = stageDrvrPath(input_stage);
auto input_slew = input_path->slew(this);
auto end_slew = path_->slew(this);
auto max_time = delayAsFloat(input_slew
@@ -293,7 +291,7 @@ WritePathSpice::writeStageInstances()
streamPrint(spice_stream_, "*****************\n\n");
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
- const char *stage_name = stageName(stage).c_str();
+ auto stage_name = stageName(stage).c_str();
if (stage == stageFirst())
streamPrint(spice_stream_, "x%s %s %s %s\n",
stage_name,
@@ -325,7 +323,7 @@ WritePathSpice::pgPortVoltage(LibertyPgPort *pg_port)
auto cell = pg_port->cell();
auto voltage_name = pg_port->voltageName();
auto lib = cell->libertyLibrary();
- float voltage = lib->supplyVoltage(voltage_name);
+ auto voltage = lib->supplyVoltage(voltage_name);
return voltage;
}
@@ -336,7 +334,7 @@ WritePathSpice::writeInputSource()
streamPrint(spice_stream_, "* Input source\n");
streamPrint(spice_stream_, "**************\n\n");
- Stage input_stage = stageFirst();
+ auto input_stage = stageFirst();
streamPrint(spice_stream_, "v1 %s 0 pwl(\n",
stageDrvrPinName(input_stage));
auto wire_arc = stageWireArc(input_stage);
@@ -349,13 +347,13 @@ WritePathSpice::writeInputSource()
volt0 = power_voltage_;
volt1 = gnd_voltage_;
}
- Path *input_path = stageDrvrPath(input_stage);
+ auto input_path = stageDrvrPath(input_stage);
auto input_slew = delayAsFloat(input_path->slew(this));
if (input_slew == 0.0)
input_slew = maxTime() / 1e+3;
// Arbitrary offset.
- float time0 = input_slew;
- float time1 = time0 + input_slew;
+ auto time0 = input_slew;
+ auto time1 = time0 + input_slew;
streamPrint(spice_stream_, "+%.3e %.3e\n", 0.0, volt0);
streamPrint(spice_stream_, "+%.3e %.3e\n", time0, volt0);
streamPrint(spice_stream_, "+%.3e %.3e\n", time1, volt1);
@@ -370,7 +368,7 @@ WritePathSpice::writeMeasureStmts()
streamPrint(spice_stream_, "* Measure statements\n");
streamPrint(spice_stream_, "********************\n\n");
- for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
+ for (auto stage = stageFirst(); stage <= stageLast(); stage++) {
auto input_path = (stage == stageFirst())
? stageDrvrPath(stage)
: stageGateInputPath(stage);
@@ -455,7 +453,7 @@ WritePathSpice::writeStageSubckts()
streamPrint(spice_stream_, "* Stage subckts\n");
streamPrint(spice_stream_, "***************\n\n");
- for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
+ for (auto stage = stageFirst(); stage <= stageLast(); stage++) {
if (stage == stageFirst())
writeInputStage(stage);
else
@@ -493,17 +491,17 @@ WritePathSpice::writeGateStage(Stage stage)
input_pin_name,
drvr_pin_name,
load_pin_name);
- Instance *inst = network_->instance(input_pin);
- const char *inst_name = network_->pathName(inst);
- LibertyCell *cell = network_->libertyCell(inst);
- const char *cell_name = cell->name();
+ auto inst = network_->instance(input_pin);
+ auto inst_name = network_->pathName(inst);
+ auto cell = network_->libertyCell(inst);
+ auto cell_name = cell->name();
auto spice_port_names = cell_spice_port_names_[cell_name];
// Instance subckt call.
streamPrint(spice_stream_, "x%s", inst_name);
StringVector::Iterator port_iter(spice_port_names);
while (port_iter.hasNext()) {
- const char *subckt_port_name = port_iter.next().c_str();
+ auto subckt_port_name = port_iter.next().c_str();
auto pin = network_->findPin(inst, subckt_port_name);
auto pg_port = cell->findPgPort(subckt_port_name);
const char *pin_name;
@@ -542,8 +540,8 @@ sensitizationValues(FuncExpr *expr,
break;
}
case FuncExpr::op_or: {
- FuncExpr *left = expr->left();
- FuncExpr *right = expr->right();
+ auto left = expr->left();
+ auto right = expr->right();
if (left->port() == from_port
&& right->op() == FuncExpr::op_port)
port_values[right->port()] = logic_zero;
@@ -553,8 +551,8 @@ sensitizationValues(FuncExpr *expr,
break;
}
case FuncExpr::op_and: {
- FuncExpr *left = expr->left();
- FuncExpr *right = expr->right();
+ auto left = expr->left();
+ auto right = expr->right();
if (left->port() == from_port
&& right->op() == FuncExpr::op_port)
port_values[right->port()] = logic_one;
@@ -565,8 +563,8 @@ sensitizationValues(FuncExpr *expr,
}
case FuncExpr::op_xor: {
// Need to know timing arc sense to get this right.
- FuncExpr *left = expr->left();
- FuncExpr *right = expr->right();
+ auto left = expr->left();
+ auto right = expr->right();
if (left->port() == from_port
&& right->op() == FuncExpr::op_port)
port_values[right->port()] = logic_zero;
@@ -591,7 +589,7 @@ WritePathSpice::writeStageVoltageSources(LibertyCell *cell,
{
auto from_port_name = from_port->name();
auto drvr_port_name = drvr_port->name();
- LibertyLibrary *lib = cell->libertyLibrary();
+ auto lib = cell->libertyLibrary();
LibertyPortLogicValues port_values;
sensitizationValues(drvr_port->function(), from_port, port_values);
int volt_source = 1;
@@ -613,7 +611,7 @@ WritePathSpice::writeStageVoltageSources(LibertyCell *cell,
} else if (!(stringEq(subckt_port_name, from_port_name)
|| stringEq(subckt_port_name, drvr_port_name))) {
// Input voltage to sensitize path from gate input to output.
- LibertyPort *port = cell->findLibertyPort(subckt_port_name);
+ auto port = cell->findLibertyPort(subckt_port_name);
if (port) {
const char *pg_port_name = NULL;
bool port_has_value;
@@ -795,8 +793,7 @@ WritePathSpice::nodeName(ParasiticNode *node)
node_index = next_node_index_++;
node_map_[node] = node_index;
}
- return stringPrintTmp(strlen(net_name_) + 10, "%s/%d",
- net_name_, node_index);
+ return stringPrintTmp("%s/%d", net_name_, node_index);
}
}
@@ -821,7 +818,7 @@ WritePathSpice::writeSubckts()
split(line, " \t", tokens);
if (tokens.size() >= 2
&& stringEqual(tokens[0].c_str(), ".subckt")) {
- const char *cell_name = tokens[1].c_str();
+ auto cell_name = tokens[1].c_str();
if (path_cell_names.hasKey(cell_name)) {
subckts_stream << line << "\n";
bool found_ends = false;
@@ -848,7 +845,7 @@ WritePathSpice::writeSubckts()
report_->error("The following subkcts are missing from %s\n",
lib_subckt_filename_);
while (cell_iter.hasNext()) {
- const char *cell_name = cell_iter.next();
+ auto cell_name = cell_iter.next();
report_->printError(" %s\n", cell_name);
}
}
@@ -866,10 +863,10 @@ void
WritePathSpice::findPathCellnames(// Return values.
StringSet &path_cell_names)
{
- for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
+ for (auto stage = stageFirst(); stage <= stageLast(); stage++) {
auto arc = stageGateArc(stage);
if (arc) {
- LibertyCell *cell = arc->set()->libertyCell();
+ auto cell = arc->set()->libertyCell();
if (cell) {
debugPrint1(debug_, "write_spice", 2, "cell %s\n", cell->name());
path_cell_names.insert(cell->name());
@@ -885,8 +882,8 @@ WritePathSpice::recordSpicePortNames(const char *cell_name,
auto cell = network_->findLibertyCell(cell_name);
if (cell) {
auto spice_port_names = new StringVector;
- for (int i = 2; i < tokens.size(); i++) {
- const char *port_name = tokens[i].c_str();
+ for (auto i = 2; i < tokens.size(); i++) {
+ auto port_name = tokens[i].c_str();
auto port = cell->findLibertyPort(port_name);
auto pg_port = cell->findPgPort(port_name);
if (port == NULL && pg_port == NULL)
@@ -941,28 +938,28 @@ WritePathSpice::stageLoadPathIndex(Stage stage)
PathRef *
WritePathSpice::stageGateInputPath(Stage stage)
{
- int path_index = stageGateInputPathIndex(stage);
+ auto path_index = stageGateInputPathIndex(stage);
return path_expanded_.path(path_index);
}
PathRef *
WritePathSpice::stageDrvrPath(Stage stage)
{
- int path_index = stageDrvrPathIndex(stage);
+ auto path_index = stageDrvrPathIndex(stage);
return path_expanded_.path(path_index);
}
PathRef *
WritePathSpice::stageLoadPath(Stage stage)
{
- int path_index = stageLoadPathIndex(stage);
+ auto path_index = stageLoadPathIndex(stage);
return path_expanded_.path(path_index);
}
TimingArc *
WritePathSpice::stageGateArc(Stage stage)
{
- int path_index = stageDrvrPathIndex(stage);
+ auto path_index = stageDrvrPathIndex(stage);
if (path_index >= 0)
return path_expanded_.prevArc(path_index);
else
@@ -972,70 +969,87 @@ WritePathSpice::stageGateArc(Stage stage)
TimingArc *
WritePathSpice::stageWireArc(Stage stage)
{
- int path_index = stageLoadPathIndex(stage);
+ auto path_index = stageLoadPathIndex(stage);
return path_expanded_.prevArc(path_index);
}
Edge *
WritePathSpice::stageGateEdge(Stage stage)
{
- PathRef *path = stageGateInputPath(stage);
- TimingArc *arc = stageGateArc(stage);
+ auto path = stageGateInputPath(stage);
+ auto arc = stageGateArc(stage);
return path->prevEdge(arc, this);
}
Edge *
WritePathSpice::stageWireEdge(Stage stage)
{
- PathRef *path = stageLoadPath(stage);
- TimingArc *arc = stageWireArc(stage);
+ auto path = stageLoadPath(stage);
+ auto arc = stageWireArc(stage);
return path->prevEdge(arc, this);
}
Pin *
WritePathSpice::stageInputPin(Stage stage)
{
- PathRef *path = stageGateInputPath(stage);
+ auto path = stageGateInputPath(stage);
return path->pin(this);
}
Pin *
WritePathSpice::stageDrvrPin(Stage stage)
{
- PathRef *path = stageDrvrPath(stage);
+ auto path = stageDrvrPath(stage);
return path->pin(this);
}
Pin *
WritePathSpice::stageLoadPin(Stage stage)
{
- PathRef *path = stageLoadPath(stage);
+ auto path = stageLoadPath(stage);
return path->pin(this);
}
const char *
WritePathSpice::stageGateInputPinName(Stage stage)
{
- const Pin *pin = stageInputPin(stage);
+ auto pin = stageInputPin(stage);
return network_->pathName(pin);
}
const char *
WritePathSpice::stageDrvrPinName(Stage stage)
{
- Pin *pin = stageDrvrPin(stage);
+ auto pin = stageDrvrPin(stage);
return network_->pathName(pin);
}
const char *
WritePathSpice::stageLoadPinName(Stage stage)
{
- const Pin *pin = stageLoadPin(stage);
+ auto pin = stageLoadPin(stage);
return network_->pathName(pin);
}
////////////////////////////////////////////////////////////////
+// fprintf for c++ streams.
+// Yes, I hate formatted output to ostream THAT much.
+void
+streamPrint(ofstream &stream,
+ const char *fmt,
+ ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ char *result;
+ vasprintf(&result, fmt, args);
+ stream << result;
+ free(result);
+ va_end(args);
+}
+
+
void
split(const string &text,
const string &delims,
@@ -1053,35 +1067,4 @@ split(const string &text,
tokens.push_back(text.substr(start));
}
-// fprintf for c++ streams.
-// Yes, I hate formatted output to ostream THAT much.
-void
-streamPrint(ofstream &stream,
- const char *fmt,
- ...)
-{
- va_list args;
- va_start(args, fmt);
- char *result;
- vasprintf(&result, fmt, args);
- stream << result;
- free(result);
- va_end(args);
-}
-
-// print for c++ strings.
-void
-stringPrint(string &str,
- const char *fmt,
- ...)
-{
- va_list args;
- va_start(args, fmt);
- char *result;
- vasprintf(&result, fmt, args);
- str = result;
- free(result);
- va_end(args);
-}
-
} // namespace
diff --git a/tcl/Cmds.tcl b/tcl/Cmds.tcl
index 5c412bc7..1a974dc3 100644
--- a/tcl/Cmds.tcl
+++ b/tcl/Cmds.tcl
@@ -22,6 +22,15 @@
namespace eval sta {
+proc_redirect read_parasitics {
+ variable native
+
+ if { $native } {
+ sta_warn "The read_parasitics command is deprecated. Use read_spef."
+ }
+ eval [concat read_spef $args]
+}
+
proc check_setup_cmd { cmd cmd_args } {
parse_key_args $cmd cmd_args keys {} flags {-verbose} 0
# When nothing is everything.
@@ -290,12 +299,12 @@ proc set_assigned_delay_cmd { cmd cmd_args } {
set inst [[lindex $from_pins 0] instance]
foreach pin $from_pins {
if {[$pin instance] != $inst} {
- sta_error "$cmd pin [$pin name] is not attached to instance [$inst path_name]."
+ sta_error "$cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]."
}
}
foreach pin $to_pins {
if {[$pin instance] != $inst} {
- sta_error "$cmd pin [$pin name] is not attached to instance [$inst path_name]"
+ sta_error "$cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]"
}
}
}
@@ -1068,7 +1077,7 @@ proc parse_clk_inst_port_pin_arg { objects clks_var insts_var pins_var } {
set ports {}
get_object_args $objects clks {} {} {} insts ports pins {} {} {}
foreach port $ports {
- lappend pins [[top_instance] find_pin [$port name]]
+ lappend pins [[top_instance] find_pin [get_name $port]]
}
}
@@ -1080,7 +1089,7 @@ proc parse_clk_port_pin_arg { objects clks_var pins_var } {
set ports {}
get_object_args $objects clks {} {} {} {} ports pins {} {} {}
foreach port $ports {
- lappend pins [[top_instance] find_pin [$port name]]
+ lappend pins [[top_instance] find_pin [get_name $port]]
}
}
@@ -1155,7 +1164,7 @@ proc parse_inst_port_pin_arg { objects insts_var pins_var } {
set ports {}
get_object_args $objects {} {} {} {} insts ports pins {} {} {}
foreach port $ports {
- lappend pins [[top_instance] find_pin [$port name]]
+ lappend pins [[top_instance] find_pin [get_name $port]]
}
}
@@ -1177,7 +1186,7 @@ proc parse_inst_port_pin_net_arg { objects insts_var pins_var nets_var } {
set nets {}
get_object_args $objects {} {} {} {} insts ports pins nets {} {}
foreach port $ports {
- lappend pins [[top_instance] find_pin [$port name]]
+ lappend pins [[top_instance] find_pin [get_name $port]]
}
}
@@ -1196,8 +1205,9 @@ proc parse_port_pin_net_arg { objects pins_var nets_var } {
set pins {}
set nets {}
get_object_args $objects {} {} {} {} {} ports pins nets {} {}
+
foreach port $ports {
- lappend pins [[top_instance] find_pin [$port name]]
+ lappend pins [[top_instance] find_pin [get_name $port]]
}
}
@@ -1497,7 +1507,7 @@ proc get_port_pin_arg { arg_name arg warn_error } {
set pin $arg
} elseif { $object_type == "Port" } {
# Explicit port arg - convert to pin.
- set pin [find_pin [$arg name]]
+ set pin [find_pin [get_name $arg]]
} else {
sta_warn_error $warn_error "$arg_name type '$object_type' is not a pin or port."
}
@@ -1508,7 +1518,7 @@ proc get_port_pin_arg { arg_name arg warn_error } {
if { $port == "NULL" } {
set pin [find_pin $arg]
} else {
- set pin [$top_instance find_pin [$port name]]
+ set pin [$top_instance find_pin [get_name $port]]
}
if { $pin == "NULL" } {
sta_warn_error $warn_error "pin $arg not found."
@@ -1531,7 +1541,7 @@ proc get_port_pins_error { arg_name arglist } {
lappend pins $arg
} elseif { $object_type == "Port" } {
# Convert port to pin.
- lappend pins [find_pin [$arg name]]
+ lappend pins [find_pin [get_name $arg]]
} else {
sta_error "$arg_name type '$object_type' is not a pin or port."
}
@@ -1769,10 +1779,14 @@ proc get_property_cmd { cmd type_key cmd_args } {
} else {
sta_error "$cmd $type_key must be specified with object name argument."
}
- set object [get_property_object $object_type $object $quiet]
+ set object [get_property_object_type $object_type $object $quiet]
}
- set object_type [object_type $object]
set prop [lindex $cmd_args 1]
+ return [get_object_property $object $prop]
+}
+
+proc get_object_property { object prop } {
+ set object_type [object_type $object]
if { $object_type == "Instance" } {
return [instance_property $object $prop]
} elseif { $object_type == "Pin" } {
@@ -1787,6 +1801,8 @@ proc get_property_cmd { cmd type_key cmd_args } {
return [liberty_port_property $object $prop]
} elseif { $object_type == "LibertyCell" } {
return [liberty_cell_property $object $prop]
+ } elseif { $object_type == "Cell" } {
+ return [cell_property $object $prop]
} elseif { $object_type == "Library" } {
return [library_property $object $prop]
} elseif { $object_type == "LibertyLibrary" } {
@@ -1797,12 +1813,14 @@ proc get_property_cmd { cmd type_key cmd_args } {
return [path_end_property $object $prop]
} elseif { $object_type == "PathRef" } {
return [path_ref_property $object $prop]
+ } elseif { $object_type == "TimingArcSet" } {
+ return [timing_arc_set_property $object $prop]
} else {
- sta_error "$cmd unsupported object type $object_type."
+ sta_error "get_property unsupported object type object_type."
}
}
-proc get_property_object { object_type object_name quiet } {
+proc get_property_object_type { object_type object_name quiet } {
set object "NULL"
if { $object_type == "cell" } {
set object [get_cells -quiet $object_name]
@@ -1856,8 +1874,46 @@ proc get_object_type { obj } {
}
}
-proc object_name_cmp { obj1 obj2 } {
- return [string compare [$obj1 object_name] [$obj2 object_name]]
+proc sort_by_full_name { objects } {
+ return [lsort -command full_name_cmp $objects]
+}
+
+proc sort_by_name { objects } {
+ return [lsort -command name_cmp $objects]
+}
+
+proc full_name_cmp { obj1 obj2 } {
+ return [string compare [get_full_name $obj1] [get_full_name $obj2]]
+}
+
+proc name_cmp { obj1 obj2 } {
+ return [string compare [get_name $obj1] [get_name $obj2]]
+}
+
+proc get_name { object } {
+ return [get_object_property $object "name"]
+}
+
+proc get_full_name { object } {
+ return [get_object_property $object "full_name"]
+}
+
+if {0} {
+proc get_name { objects } {
+ set names {}
+ foreach object $objects {
+ lappend names [get_object_property $object "name"]
+ }
+ return $names
+}
+
+proc get_full_name { objects } {
+ set names {}
+ foreach object $objects {
+ lappend names [get_object_property $object "full_name"]
+ }
+ return $names
+}
}
################################################################
diff --git a/tcl/Graph.tcl b/tcl/Graph.tcl
index 8b51d372..8aa15583 100644
--- a/tcl/Graph.tcl
+++ b/tcl/Graph.tcl
@@ -217,7 +217,7 @@ proc report_constant { obj } {
proc report_pin_constant { pin } {
set sim_value [pin_sim_logic_value $pin]
- puts -nonewline "[$pin port_name] $sim_value"
+ puts -nonewline "[pin_property $pin lib_pin_name] $sim_value"
set case_value [pin_case_logic_value $pin]
if { $case_value != "X" } {
puts -nonewline " case=$case_value"
@@ -234,15 +234,15 @@ proc report_pin_constant { pin } {
proc report_disabled_edges {} {
foreach edge [disabled_edges_sorted] {
if { [$edge role] == "wire" } {
- set from_pin_name [[[$edge from] pin] path_name]
- set to_pin_name [[[$edge to] pin] path_name]
+ set from_pin_name [get_full_name [[$edge from] pin]]
+ set to_pin_name [get_full_name [[$edge to] pin]]
puts -nonewline "$from_pin_name $to_pin_name"
} else {
set from_pin [[$edge from] pin]
set to_pin [[$edge to] pin]
- set inst_name [[$from_pin instance] path_name]
- set from_port_name [[$from_pin port] name]
- set to_port_name [[$to_pin port] name]
+ set inst_name [get_full_name [$from_pin instance]]
+ set from_port_name [get_name [$from_pin port]]
+ set to_port_name [get_name [$to_pin port]]
puts -nonewline "$inst_name $from_port_name $to_port_name"
set cond [$edge cond]
if { $cond != "" } {
@@ -267,8 +267,8 @@ proc edge_disable_reason_verbose { edge } {
append disables " $sense"
}
set const_pins [$edge disabled_constant_pins]
- foreach pin [lsort -command path_name_cmp $const_pins] {
- set port_name [$pin port_name]
+ foreach pin [sort_by_full_name $const_pins] {
+ set port_name [pin_property $pin lib_pin_name]
set value [pin_sim_logic_value $pin]
append disables " $port_name=$value"
}
@@ -302,18 +302,20 @@ proc report_slews { pin } {
}
proc vertex_path_name { vertex } {
- return [vertex_name_ $vertex path_name]
+ set pin [$vertex pin]
+ set pin_name [get_full_name $pin]
+ return [vertex_name_ $vertex $pin $pin_name]
}
proc vertex_port_name { vertex } {
- return [vertex_name_ $vertex port_name]
+ set pin [$vertex pin]
+ set pin_name [pin_property $pin lib_pin_name]
+ return [vertex_name_ $vertex $pin $pin_name]
}
# Append driver/load for bidirect pin vertices.
-proc vertex_name_ { vertex name_proc } {
- set pin [$vertex pin]
- set pin_name [$pin $name_proc]
- if { [$pin direction] == "bidirect" } {
+proc vertex_name_ { vertex pin pin_name } {
+ if { [pin_direction $pin] == "bidirect" } {
if [$vertex is_bidirect_driver] {
return "$pin_name driver"
} else {
diff --git a/tcl/Network.tcl b/tcl/Network.tcl
index 446cb8bb..750b4ff5 100644
--- a/tcl/Network.tcl
+++ b/tcl/Network.tcl
@@ -60,11 +60,12 @@ proc report_instance1 { instance connections verbose } {
if { $instance == [top_instance] } {
set inst_name "top"
} else {
- set inst_name [$instance path_name]
+ set inst_name [get_full_name $instance]
}
puts "Instance $inst_name"
- puts " Cell: [[$instance cell] name]"
- puts " Library: [[[$instance cell] library] name]"
+ set cell [instance_property $instance "cell"]
+ puts " Cell: [get_name $cell]"
+ puts " Library: [get_name [$cell library]]"
puts " Path cells: [instance_cell_path $instance]"
if { $connections } {
report_instance_pins $instance $verbose
@@ -92,7 +93,7 @@ proc report_instance_pins1 {instance verbose header header_optional dirs} {
set iter [$instance pin_iterator]
while {[$iter has_next]} {
set pin [$iter next]
- set dir [$pin direction]
+ set dir [pin_direction $pin]
if { [lsearch $dirs $dir] != -1 } {
if { !$header_shown } {
puts $header
@@ -105,20 +106,20 @@ proc report_instance_pins1 {instance verbose header header_optional dirs} {
}
proc report_instance_pin { pin verbose } {
- puts -nonewline " [$pin port_name] [$pin direction]"
+ puts -nonewline " [$pin port_name] [pin_direction $pin]"
set net [$pin net]
if { $net == "NULL" } {
puts " (unconnected)"
} else {
- puts " [[$net highest_connected_net] path_name]"
+ puts " [get_full_name [$net highest_connected_net]]"
if { $verbose } {
set pins [net_connected_pins_sorted $net]
foreach pin $pins {
if [$pin is_load] {
if [$pin is_top_level_port] {
- puts " [$pin path_name] [$pin direction] port"
+ puts " [get_full_name $pin] [pin_direction $pin] port"
} else {
- puts " [$pin path_name] [$pin direction]"
+ puts " [get_full_name $pin] [pin_direction $pin]"
}
}
}
@@ -128,11 +129,11 @@ proc report_instance_pin { pin verbose } {
# Concatenate the cell names of the instance parents.
proc instance_cell_path { instance } {
- set cell_path "[[$instance cell] name]"
+ set cell_path "[get_name [instance_property $instance "cell"]]"
set parent [$instance parent]
set top_instance [top_instance]
while { $parent != "NULL" && $parent != $top_instance } {
- set cell_path "[[$parent cell] name]/$cell_path"
+ set cell_path "[get_name [$parent cell]]/$cell_path"
set parent [$parent parent]
}
return $cell_path
@@ -143,7 +144,7 @@ proc report_instance_children_ { instance } {
if { $children != {} } {
puts " Children:"
foreach child $children {
- puts " [$child name] ([[$child cell] name])"
+ puts " [get_name $child] ([instance_property $child ref_name])"
}
}
}
@@ -155,15 +156,7 @@ proc instance_sorted_children { instance } {
lappend children [$iter next]
}
$iter finish
- return [lsort -command path_name_cmp $children]
-}
-
-proc path_name_cmp { obj1 obj2 } {
- return [string compare [$obj1 path_name] [$obj2 path_name]]
-}
-
-proc name_cmp { obj1 obj2 } {
- return [string compare [$obj1 name] [$obj2 name]]
+ return [sort_by_full_name $children]
}
################################################################
@@ -183,9 +176,9 @@ proc report_lib_cell_ { cell } {
global sta_report_default_digits
set lib [$cell liberty_library]
- puts "Cell [$cell name]"
- puts "Library [$lib name]"
- set filename [$cell filename]
+ puts "Cell [get_name $cell]"
+ puts "Library [get_name $lib]"
+ set filename [liberty_cell_property $cell "filename"]
if { $filename != "" } {
puts "File $filename"
}
@@ -193,9 +186,9 @@ proc report_lib_cell_ { cell } {
while {[$iter has_next]} {
set port [$iter next]
if { [$port is_bus] } {
- puts -nonewline " [$port bus_name] [$port direction]"
+ puts -nonewline " [$port bus_name] [liberty_port_direction $port]"
} else {
- puts -nonewline " [$port name] [$port direction]"
+ puts -nonewline " [get_name $port] [liberty_port_direction $port]"
}
set enable [$port tristate_enable]
if { $enable != "" } {
@@ -212,9 +205,9 @@ proc report_lib_cell_ { cell } {
proc report_cell_ { cell } {
set lib [$cell library]
- puts "Cell [$cell name]"
- puts "Library [$lib name]"
- set filename [$cell filename]
+ puts "Cell [get_name $cell]"
+ puts "Library [get_name $lib]"
+ set filename [liberty_cell_property $cell "filename"]
if { $filename != "" } {
puts "File $filename"
}
@@ -222,9 +215,9 @@ proc report_cell_ { cell } {
while {[$iter has_next]} {
set port [$iter next]
if { [$port is_bus] } {
- puts " [$port bus_name] [$port direction]"
+ puts " [$port bus_name] [port_direction $port]"
} else {
- puts " [$port name] [$port direction]"
+ puts " [get_name $port] [port_direction $port]"
}
}
$iter finish
@@ -292,7 +285,7 @@ proc report_net_ { net } {
}
proc report_net1 { net connections verbose hier_pins corner digits } {
- puts "Net [$net path_name]"
+ puts "Net [get_full_name $net]"
if {$connections} {
set pins [net_connected_pins_sorted $net]
if {$verbose} {
@@ -320,7 +313,7 @@ proc net_connected_pins_sorted { net } {
lappend pins $pin
}
$iter finish
- set pins [lsort -command path_name_cmp $pins]
+ set pins [sort_by_full_name $pins]
return $pins
}
@@ -380,8 +373,8 @@ proc report_net_other_pins { pins verbose corner digits } {
proc report_net_pin { pin verbose corner digits } {
if [$pin is_leaf] {
- set cell_name [[[$pin instance] cell] name]
- puts -nonewline " [$pin path_name] [$pin direction] ($cell_name)"
+ set cell_name [get_name [[$pin instance] cell]]
+ puts -nonewline " [get_full_name $pin] [pin_direction $pin] ($cell_name)"
if { $verbose } {
set liberty_port [$pin liberty_port]
if { $liberty_port != "NULL" } {
@@ -390,7 +383,7 @@ proc report_net_pin { pin verbose corner digits } {
}
puts ""
} elseif [$pin is_top_level_port] {
- puts -nonewline " [$pin path_name] [$pin direction] port"
+ puts -nonewline " [get_full_name $pin] [pin_direction $pin] port"
if { $verbose } {
set port [$pin port]
set cap_r_min [port_ext_wire_cap $port "rise" "min"]
@@ -412,7 +405,7 @@ proc report_net_pin { pin verbose corner digits } {
}
puts ""
} elseif [$pin is_hierarchical] {
- puts " [$pin path_name] [$pin direction]"
+ puts " [get_full_name $pin] [pin_direction $pin]"
}
}
@@ -421,7 +414,7 @@ proc report_net_pin { pin verbose corner digits } {
proc report_pin_ { pin } {
global sta_report_default_digits
- puts -nonewline "Pin [$pin path_name] [pin_direction_desc $pin]"
+ puts -nonewline "Pin [get_full_name $pin] [pin_direction_desc $pin]"
set liberty_port [$pin liberty_port]
if { $liberty_port != "NULL" } {
@@ -429,24 +422,29 @@ proc report_pin_ { pin } {
}
if { [$pin is_top_level_port] } {
- set net [[$pin term] net]
+ set term [$pin term]
+ if { $term == "NULL" } {
+ set net "NULL"
+ } else {
+ set net [$term net]
+ }
} else {
set net [$pin net]
}
if { $net == "NULL" } {
puts " (unconnected)"
} else {
- puts " [[$net highest_connected_net] path_name]"
+ puts " [get_full_name [$net highest_connected_net]]"
}
}
proc pin_direction_desc { pin } {
if [$pin is_hierarchical] {
- return "hierarchical [$pin direction]"
+ return "hierarchical [pin_direction $pin]"
} elseif [$pin is_top_level_port] {
- return "[$pin direction] port"
+ return "[pin_direction $pin] port"
} else {
- return [$pin direction]
+ return [pin_direction $pin]
}
}
diff --git a/tcl/NetworkEdit.tcl b/tcl/NetworkEdit.tcl
index 9d1f5eb3..5d9ec0ab 100644
--- a/tcl/NetworkEdit.tcl
+++ b/tcl/NetworkEdit.tcl
@@ -48,7 +48,7 @@ proc parse_connect_pins { arg } {
set port [$pin port]
} elseif { $object_type == "Port" } {
# Explicit port arg - convert to pin.
- set pin [find_pin [$obj name]]
+ set pin [find_pin [get_name $obj]]
set inst [$pin instance]
set port [$pin port]
} else {
diff --git a/tcl/Power.tcl b/tcl/Power.tcl
index 1f9cb3a1..df04e94c 100644
--- a/tcl/Power.tcl
+++ b/tcl/Power.tcl
@@ -106,9 +106,11 @@ proc report_power_col_percent { col_total total } {
}
proc report_power_inst { inst corner digits } {
- puts "Instance: [$inst path_name]"
- puts "Cell: [[$inst liberty_cell] name]"
- puts "Liberty file: [[[$inst liberty_cell] liberty_library] filename]"
+ puts "Instance: [get_full_name $inst]"
+ set cell [instance_property $inst "liberty_cell"]
+ puts "Cell: [get_name $cell]"
+ set library [liberty_cell_property $cell "library"]
+ puts "Liberty file: [liberty_library_property $library filename]"
set power_result [instance_power $inst $corner]
lassign $power_result internal switching leakage total
report_power_line "Internal power" $internal $digits
diff --git a/tcl/Sdc.tcl b/tcl/Sdc.tcl
index 2209c489..98960e88 100644
--- a/tcl/Sdc.tcl
+++ b/tcl/Sdc.tcl
@@ -159,7 +159,7 @@ proc current_instance { {inst ""} } {
} else {
set current_instance [get_instance_error "instance" $inst]
}
- set cell [[$current_instance cell] name]
+ set cell [get_name [$current_instance cell]]
puts "Current instance is $cell."
# Current instance state variable must be part of the sta state so
# the tcl interpreter can be shared by multiple sdc files.
@@ -289,7 +289,7 @@ proc all_ports_for_direction { direction } {
set iter [$top_cell port_iterator]
while {[$iter has_next]} {
set port [$iter next]
- set port_dir [$port direction]
+ set port_dir [port_direction $port]
if { $port_dir == $direction || $port_dir == "bidirect" } {
set ports [concat $ports [port_members $port]]
}
@@ -384,11 +384,11 @@ proc current_design { {design ""} } {
if { $design == "" } {
# top_instance errors if the network has not been linked.
- set current_design_name [[[top_instance] cell] name]
+ set current_design_name [get_name [get_object_property [top_instance] cell]]
} elseif { ![network_is_linked] } {
set current_design_name $design
return $design
- } elseif { [network_is_linked] && $design == [[[top_instance] cell] name] } {
+ } elseif { [network_is_linked] && $design == [get_name [get_object_property [top_instance] cell]] } {
set current_design_name $design
return $design
} else {
@@ -706,7 +706,7 @@ proc find_liberty_libraries_matching { pattern regexp nocase } {
set matches {}
while { [$lib_iter has_next] } {
set lib [$lib_iter next]
- set lib_name [$lib name]
+ set lib_name [get_name $lib]
if { (!$regexp && [string match $pattern2 $lib_name]) \
|| ($regexp && $nocase && [regexp -nocase $pattern2 $lib_name]) \
|| ($regexp && !$nocase && [regexp $pattern2 $lib_name]) } {
@@ -980,7 +980,7 @@ proc create_clock { args } {
sta_error "-add requires -name."
}
# Default clock name is the first pin name.
- set name [[lindex $pins 0] path_name]
+ set name [get_full_name [lindex $pins 0]]
} else {
sta_error "-name or port_pin_list must be specified."
}
@@ -1057,7 +1057,7 @@ proc create_generated_clock { args } {
sta_error "-add requires -name."
}
# Default clock name is the first pin name.
- set name [[lindex $pins 0] path_name]
+ set name [get_full_name [lindex $pins 0]]
} else {
sta_error "name or port_pin_list must be specified."
}
@@ -1410,7 +1410,7 @@ proc set_clock_latency { args } {
foreach pin $pins {
# Source only allowed on clocks and clock pins.
if { ![is_clock_src $pin] } {
- sta_error "-source '[$pin path_name]' is not a clock pin."
+ sta_error "-source '[get_full_name $pin]' is not a clock pin."
}
set_clock_insertion_cmd $pin_clk $pin $tr $min_max $early_late $delay
}
@@ -1465,7 +1465,7 @@ proc set_clock_sense { args } {
}
foreach pin $pins {
if {[$pin is_hierarchical]} {
- sta_warn "hierarchical pin '[$pin path_name]' not supported."
+ sta_warn "hierarchical pin '[get_full_name $pin]' not supported."
}
}
set_clock_sense_cmd $pins $clks $positive $negative $stop_propagation
@@ -1724,16 +1724,16 @@ proc parse_disable_inst_ports { inst port_name } {
if { $port_name == "" } {
set ports "NULL"
} else {
- set cell [$inst liberty_cell]
+ set cell [instance_property $inst liberty_cell]
set port [$cell find_liberty_port $port_name]
if { $port == "NULL" } {
- sta_error "pin '[$inst path_name]${hierarchy_separator}${port_name}' not found."
+ sta_error "pin '[get_full_name $inst]${hierarchy_separator}${port_name}' not found."
} else {
set ports [port_members $port]
foreach port $ports {
- set member_name [$port name]
+ set member_name [get_full_name $port]
if { [$inst find_pin $member_name] == "NULL" } {
- sta_error "pin '[$inst path_name]${hierarchy_separator}${member_name}' not found."
+ sta_error "pin '[get_full_name $inst]]${hierarchy_separator}${member_name}' not found."
}
}
}
@@ -1773,7 +1773,7 @@ proc parse_disable_cell_ports { cell port_name } {
} else {
set port [$cell find_liberty_port $port_name]
if { $port == "NULL" } {
- sta_error "pin '[$cell name]${hierarchy_separator}${port_name}' not found."
+ sta_error "pin '[get_name $cell]${hierarchy_separator}${port_name}' not found."
} else {
set ports [port_members $port]
}
@@ -1920,8 +1920,8 @@ proc set_port_delay { cmd sta_cmd cmd_args port_dirs } {
foreach pin $pins {
if { [$pin is_top_level_port] \
- && [lsearch $port_dirs [$pin direction]] == -1 } {
- sta_warn "$cmd not allowed on [$pin direction] port '[$pin name]'."
+ && [lsearch $port_dirs [pin_direction $pin]] == -1 } {
+ sta_warn "$cmd not allowed on [pin_direction $pin] port '[get_full_name $pin]'."
} elseif { $clk != "NULL" && [lsearch [$clk sources] $pin] != -1 } {
sta_warn "$cmd relative to a clock defined on the same port/pin not allowed."
} else {
@@ -2147,7 +2147,7 @@ proc set_propagated_clock { objects } {
parse_clk_port_pin_arg $objects clks pins
foreach clk $clks {
if { [$clk is_virtual] } {
- sta_warn "virtual clock [$clk name] can not be propagated."
+ sta_warn "virtual clock [get_name $clk] can not be propagated."
} else {
set_propagated_clock_cmd $clk
}
@@ -2257,7 +2257,7 @@ proc set_driving_cell { args } {
set output_count 0
while {[$port_iter has_next]} {
set port [$port_iter next]
- set dir [$port direction]
+ set dir [liberty_port_direction $port]
if { [port_direction_any_output $dir] } {
incr output_count
if { $output_count > 1 } {
@@ -2482,9 +2482,9 @@ proc set_fanout_limit { fanout min_max objects } {
check_positive_float "limit" $fanout
parse_cell_port_args $objects cells ports
foreach port $ports {
- set dir [$port direction]
+ set dir [port_direction $port]
if { !($dir == "input" || $dir == "bidirect") } {
- sta_error "port '[$port name]' is not an input."
+ sta_error "port '[get_name $port]' is not an input."
}
set_port_fanout_limit $port $min_max $fanout
}
diff --git a/tcl/Search.tcl b/tcl/Search.tcl
index 236bd0cf..001c3074 100644
--- a/tcl/Search.tcl
+++ b/tcl/Search.tcl
@@ -55,7 +55,7 @@ proc report_delays_wrt_clk { vertex what clk clk_tr } {
set rise_fmt [format_delays $rise]
set fall_fmt [format_delays $fall]
if {$clk != "NULL"} {
- set clk_str " ([$clk name] [rise_fall_short_name $clk_tr])"
+ set clk_str " ([get_name $clk] [rise_fall_short_name $clk_tr])"
} else {
set clk_str ""
}
@@ -90,7 +90,7 @@ proc report_wrt_clk { vertex what clk clk_tr } {
set rise_fmt [format_times $rise $sta_report_default_digits]
set fall_fmt [format_times $fall $sta_report_default_digits]
if {$clk != "NULL"} {
- set clk_str " ([$clk name] [rise_fall_short_name $clk_tr])"
+ set clk_str " ([get_name $clk] [rise_fall_short_name $clk_tr])"
} else {
set clk_str ""
}
diff --git a/tcl/Sta.tcl b/tcl/Sta.tcl
index 1909f781..a9d7d671 100644
--- a/tcl/Sta.tcl
+++ b/tcl/Sta.tcl
@@ -25,11 +25,13 @@ proc define_sta_cmd_args { cmd arglist } {
# Import Sta commands to global namespace.
proc define_sta_cmds {} {
variable sta_cmd_args
+ variable native
foreach cmd [array names sta_cmd_args] {
define_cmd_args $cmd $sta_cmd_args($cmd)
}
define_report_path_fields
+ set native 1
}
proc define_report_path_fields {} {
@@ -421,7 +423,7 @@ proc_redirect report_check_types {
set slack_min [expr -$sta::float_inf]
set slack_max $sta::float_inf
}
- set path_ends [find_path_ends "NULL" {} "NULL" \
+ set path_ends [find_path_ends "NULL" {} "NULL" 0 \
$corner $path_min_max $group_count 1 0 \
$slack_min $slack_max \
0 {} \
@@ -674,28 +676,16 @@ proc unset_timing_derate { args } {
define_sta_cmd_args "connect_pins" {net pins}
-################################################################
-
define_sta_cmd_args "delete_instance" {cell_list}
-################################################################
-
define_sta_cmd_args "delete_net" {net_list}
-################################################################
-
define_sta_cmd_args "disconnect_pins" {net -all|pins}
-################################################################
-
define_sta_cmd_args "make_instance" {inst_names lib_cell}
-################################################################
-
define_sta_cmd_args "make_net" {}
-################################################################
-
define_sta_cmd_args "replace_cell" {instances lib_cell}
################################################################
@@ -714,6 +704,22 @@ proc set_assigned_delay { args } {
set_assigned_delay_cmd "set_assigned_delay" $args
}
+# compatibility
+define_sta_cmd_args "read_parasitics" \
+ {[-min]\
+ [-max]\
+ [-elmore]\
+ [-path path]\
+ [-increment]\
+ [-pin_cap_included]\
+ [-keep_capacitive_coupling]\
+ [-coupling_reduction_factor factor]\
+ [-reduce_to pi_elmore|pi_pole_residue2]\
+ [-delete_after_reduce]\
+ [-quiet]\
+ [-save]\
+ filename}
+
################################################################a
define_sta_cmd_args "set_assigned_check" \
@@ -891,16 +897,8 @@ proc get_fanout { args } {
################################################################
-define_sta_cmd_args "get_name_of_object" {object}
-
-proc get_name_of_object { object } {
- if [is_object $object] {
- return [$object object_name]
- } elseif { [llength $object] > 1 } {
- # Should return list of names.
- sta_error "get_object_name cannot get the object name of multiple objects."
- }
-}
+define_sta_cmd_args "get_name" {objects}
+define_sta_cmd_args "get_full_name" {objects}
################################################################
@@ -968,6 +966,30 @@ proc report_clock1 { clk } {
################################################################
+define_sta_cmd_args "report_object_full_names" {[-verbose] objects}
+
+proc report_object_full_names { args } {
+ parse_key_args "report_object_names" args keys {} flags {-verbose}
+
+ set objects [lindex $args 0]
+ if { [info exists flags(-verbose)] } {
+ puts -nonewline "{"
+ set first 1
+ foreach obj [sort_by_full_name $objects] {
+ if { !$first } {
+ puts -nonewline ", "
+ }
+ puts -nonewline \"[get_object_type $obj]:[get_full_name $obj]\"
+ set first 0
+ }
+ puts "}"
+ } else {
+ foreach obj [sort_by_full_name $objects] {
+ puts [get_full_name $obj]
+ }
+ }
+}
+
define_sta_cmd_args "report_object_names" {[-verbose] objects}
proc report_object_names { args } {
@@ -977,17 +999,17 @@ proc report_object_names { args } {
if { [info exists flags(-verbose)] } {
puts -nonewline "{"
set first 1
- foreach obj [lsort -command object_name_cmp $objects] {
+ foreach obj [sort_name $objects] {
if { !$first } {
puts -nonewline ", "
}
- puts -nonewline \"[get_object_type $obj]:[get_name_of_object $obj]\"
+ puts -nonewline \"[get_object_type $obj]:[get_name $obj]\"
set first 0
}
puts "}"
} else {
- foreach obj [lsort -command object_name_cmp $objects] {
- puts [get_name_of_object $obj]
+ foreach obj [sort_by_full_name $objects] {
+ puts [get_name $obj]
}
}
}
diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i
index 945064ea..9385b6ae 100644
--- a/tcl/StaTcl.i
+++ b/tcl/StaTcl.i
@@ -458,7 +458,7 @@ tclError(Tcl_Interp *interp,
const char *msg,
const char *arg)
{
- char *error = stringPrint(strlen(msg) + strlen(arg) + 1, msg, arg);
+ char *error = stringPrint(msg, arg);
Tcl_SetResult(interp, error, TCL_VOLATILE);
stringDelete(error);
}
@@ -1529,10 +1529,10 @@ using namespace sta;
Tcl_SetResult(interp, const_cast(""), TCL_STATIC);
break;
case PropertyValue::Type::type_string:
- Tcl_SetResult(interp, const_cast(value.string()), TCL_VOLATILE);
+ Tcl_SetResult(interp, const_cast(value.stringValue()), TCL_VOLATILE);
break;
case PropertyValue::Type::type_float: {
- char *float_string = stringPrint(10, "%.5f", value.floatValue());
+ char *float_string = stringPrint("%.5f", value.floatValue());
Tcl_SetResult(interp, float_string, TCL_VOLATILE);
stringDelete(float_string);
}
@@ -1566,6 +1566,24 @@ using namespace sta;
Tcl_SetObjResult(interp, obj);
}
break;
+ case PropertyValue::Type::type_liberty_cell: {
+ Tcl_Obj *obj = SWIG_NewInstanceObj(value.libertyCell(),
+ SWIGTYPE_p_LibertyCell, false);
+ Tcl_SetObjResult(interp, obj);
+ }
+ break;
+ case PropertyValue::Type::type_liberty_library: {
+ Tcl_Obj *obj = SWIG_NewInstanceObj(value.libertyLibrary(),
+ SWIGTYPE_p_LibertyLibrary, false);
+ Tcl_SetObjResult(interp, obj);
+ }
+ break;
+ case PropertyValue::Type::type_cell: {
+ Tcl_Obj *obj = SWIG_NewInstanceObj(value.cell(),
+ SWIGTYPE_p_Cell, false);
+ Tcl_SetObjResult(interp, obj);
+ }
+ break;
case PropertyValue::Type::type_clock: {
Tcl_Obj *obj = SWIG_NewInstanceObj(value.clock(),
SWIGTYPE_p_Clock, false);
@@ -1597,9 +1615,6 @@ using namespace sta;
Tcl_SetObjResult(interp, list);
}
break;
- default:
- Tcl_SetResult(interp, const_cast(""), TCL_STATIC);
- break;
}
}
@@ -2267,6 +2282,24 @@ top_instance()
return cmdLinkedNetwork()->topInstance();
}
+const char *
+liberty_port_direction(const LibertyPort *port)
+{
+ return port->direction()->name();
+}
+
+const char *
+port_direction(const Port *port)
+{
+ return cmdLinkedNetwork()->direction(port)->name();
+}
+
+const char *
+pin_direction(const Pin *pin)
+{
+ return cmdLinkedNetwork()->direction(pin)->name();
+}
+
TmpPortSeq *
find_ports_matching(const char *pattern,
bool regexp,
@@ -2523,7 +2556,7 @@ filter_ports(const char *property,
while (port_iter.hasNext()) {
Port *port = port_iter.next();
PropertyValue value(getProperty(port, property, sta));
- const char *prop = value.string();
+ const char *prop = value.stringValue();
if (prop &&
((exact_match && stringEq(prop, pattern))
|| (!exact_match && patternMatch(pattern, prop))))
@@ -2547,7 +2580,7 @@ filter_insts(const char *property,
while (inst_iter.hasNext()) {
Instance *inst = inst_iter.next();
PropertyValue value(getProperty(inst, property, sta));
- const char *prop = value.string();
+ const char *prop = value.stringValue();
if (prop &&
((exact_match && stringEq(prop, pattern))
|| (!exact_match && patternMatch(pattern, prop))))
@@ -2570,7 +2603,7 @@ filter_pins(const char *property,
while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next();
PropertyValue value(getProperty(pin, property, sta));
- const char *prop = value.string();
+ const char *prop = value.stringValue();
if (prop &&
((exact_match && stringEq(prop, pattern))
|| (!exact_match && patternMatch(pattern, prop))))
@@ -2617,7 +2650,13 @@ PropertyValue
liberty_cell_property(const LibertyCell *cell,
const char *property)
{
- cmdLinkedNetwork();
+ return getProperty(cell, property, Sta::sta());
+}
+
+PropertyValue
+cell_property(const Cell *cell,
+ const char *property)
+{
return getProperty(cell, property, Sta::sta());
}
@@ -2625,7 +2664,6 @@ PropertyValue
liberty_port_property(const LibertyPort *port,
const char *property)
{
- cmdLinkedNetwork();
return getProperty(port, property, Sta::sta());
}
@@ -2633,7 +2671,6 @@ PropertyValue
library_property(const Library *lib,
const char *property)
{
- cmdLinkedNetwork();
return getProperty(lib, property, Sta::sta());
}
@@ -2676,6 +2713,14 @@ path_ref_property(PathRef *path,
return getProperty(path, property, Sta::sta());
}
+PropertyValue
+timing_arc_set_property(TimingArcSet *arc_set,
+ const char *property)
+{
+ cmdLinkedNetwork();
+ return getProperty(arc_set, property, Sta::sta());
+}
+
LeafInstanceIterator *
leaf_instance_iterator()
{
@@ -2747,7 +2792,7 @@ filter_timing_arcs(const char *property,
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
PropertyValue value(getProperty(edge, property, sta));
- const char *prop = value.string();
+ const char *prop = value.stringValue();
if (prop &&
((exact_match && stringEq(prop, pattern))
|| (!exact_match && patternMatch(pattern, prop))))
@@ -5093,8 +5138,6 @@ define_corners_cmd(StringSet *corner_names)
////////////////////////////////////////////////////////////////
%extend Library {
-const char *name() { return cmdNetwork()->name(self); }
-const char *object_name() { return cmdNetwork()->name(self); }
Cell *
find_cell(const char *name)
{
@@ -5116,10 +5159,6 @@ find_cells_matching(const char *pattern,
%extend LibertyLibrary {
-const char *name() { return self->name(); }
-const char *filename() { return self->filename(); }
-const char *object_name() { return self->name(); }
-
LibertyCell *
find_liberty_cell(const char *name)
{
@@ -5177,9 +5216,6 @@ void finish() { delete self; }
} // LibertyLibraryIterator methods
%extend Cell {
-const char *name() { return cmdNetwork()->name(self); }
-const char *filename() { return cmdNetwork()->filename(self); }
-const char *object_name() { return cmdNetwork()->name(self); }
Library *library() { return cmdNetwork()->library(self); }
LibertyCell *liberty_cell() { return cmdNetwork()->libertyCell(self); }
bool is_leaf() { return cmdNetwork()->isLeaf(self); }
@@ -5206,9 +5242,6 @@ find_ports_matching(const char *pattern,
} // Cell methods
%extend LibertyCell {
-const char *name() { return self->name(); }
-const char *filename() { return self->filename(); }
-const char *object_name() { return self->name(); }
bool is_leaf() { return self->isLeaf(); }
LibertyLibrary *liberty_library() { return self->libertyLibrary(); }
Cell *cell() { return reinterpret_cast| (self); }
@@ -5250,29 +5283,21 @@ void finish() { delete self; }
} // LibertyCellPortIterator methods
%extend Port {
-const char *name() { return cmdNetwork()->name(self); }
const char *bus_name() { return cmdNetwork()->busName(self); }
Cell *cell() { return cmdNetwork()->cell(self); }
LibertyPort *liberty_port() { return cmdNetwork()->libertyPort(self); }
-const char *object_name() { return cmdNetwork()->name(self); }
bool is_bus() { return cmdNetwork()->isBus(self); }
PortMemberIterator *
member_iterator() { return cmdNetwork()->memberIterator(self); }
-const char *
-direction() { return cmdNetwork()->direction(self)->name(); }
} // Port methods
%extend LibertyPort {
-const char *name() { return self->name(); }
const char *bus_name() { return self->busName(); }
Cell *cell() { return self->cell(); }
-const char *object_name() { return self->name(); }
bool is_bus() { return self->isBus(); }
LibertyPortMemberIterator *
member_iterator() { return new LibertyPortMemberIterator(self); }
-const char *
-direction() { return self->direction()->name(); }
const char *
function()
@@ -5306,7 +5331,6 @@ capacitance(const TransRiseFall *tr,
} // LibertyPort methods
%extend OperatingConditions {
-const char *name() { return self->name(); }
float process() { return self->process(); }
float voltage() { return self->voltage(); }
float temperature() { return self->temperature(); }
@@ -5331,13 +5355,12 @@ TimingRole *role() { return self->role(); }
const char *sdf_cond() { return self->sdfCond(); }
const char *
-object_name()
+full_name()
{
const char *from = self->from()->name();
const char *to = self->to()->name();
const char *cell_name = self->libertyCell()->name();
- return stringPrintTmp(strlen(from) + strlen(to) + strlen(cell_name) + 6,
- "%s %s -> %s",
+ return stringPrintTmp("%s %s -> %s",
cell_name,
from,
to);
@@ -5368,9 +5391,6 @@ void finish() { delete self; }
}
%extend Instance {
-const char *name() { return cmdLinkedNetwork()->name(self); }
-const char *object_name() { return cmdLinkedNetwork()->pathName(self); }
-const char *path_name() { return cmdLinkedNetwork()->pathName(self); }
Instance *parent() { return cmdLinkedNetwork()->parent(self); }
Cell *cell() { return cmdLinkedNetwork()->cell(self); }
LibertyCell *liberty_cell() { return cmdLinkedNetwork()->libertyCell(self); }
@@ -5413,16 +5433,12 @@ void finish() { delete self; }
} // InstanceNetIterator methods
%extend Pin {
-const char *name() { return cmdLinkedNetwork()->name(self); }
-const char *object_name() { return cmdLinkedNetwork()->pathName(self); }
const char *port_name() { return cmdLinkedNetwork()->portName(self); }
-const char *path_name() { return cmdLinkedNetwork()->pathName(self); }
Instance *instance() { return cmdLinkedNetwork()->instance(self); }
Net *net() { return cmdLinkedNetwork()->net(self); }
Port *port() { return cmdLinkedNetwork()->port(self); }
Term *term() { return cmdLinkedNetwork()->term(self); }
LibertyPort *liberty_port() { return cmdLinkedNetwork()->libertyPort(self); }
-const char *direction() { return cmdLinkedNetwork()->direction(self)->name(); }
bool is_driver() { return cmdLinkedNetwork()->isDriver(self); }
bool is_load() { return cmdLinkedNetwork()->isLoad(self); }
bool is_leaf() { return cmdLinkedNetwork()->isLeaf(self); }
@@ -5486,18 +5502,11 @@ void finish() { delete self; }
} // PinConnectedPinIterator methods
%extend Term {
-const char *name() { return cmdLinkedNetwork()->name(self); }
-const char *object_name() { return cmdLinkedNetwork()->pathName(self); }
-const char *port_name() { return cmdLinkedNetwork()->portName(self); }
-const char *path_name() { return cmdLinkedNetwork()->pathName(self); }
Net *net() { return cmdLinkedNetwork()->net(self); }
Pin *pin() { return cmdLinkedNetwork()->pin(self); }
} // Term methods
%extend Net {
-const char *name() { return cmdLinkedNetwork()->name(self); }
-const char *object_name() { return cmdLinkedNetwork()->pathName(self); }
-const char *path_name() { return cmdLinkedNetwork()->pathName(self); }
Instance *instance() { return cmdLinkedNetwork()->instance(self); }
Net *highest_connected_net()
{ return cmdLinkedNetwork()->highestConnectedNet(self); }
@@ -5579,8 +5588,6 @@ void finish() { delete self; }
} // NetConnectedPinIterator methods
%extend Clock {
-const char *name() { return self->name(); }
-const char *object_name() { return self->name(); }
float period() { return self->period(); }
FloatSeq *waveform() { return self->waveform(); }
float time(TransRiseFall *tr) { return self->edge(tr)->time(); }
@@ -5601,8 +5608,6 @@ slew(const TransRiseFall *tr,
}
%extend ClockEdge {
-const char *name() { return self->name(); }
-const char *object_name() { return self->name(); }
Clock *clock() { return self->clock(); }
TransRiseFall *transition() { return self->transition(); }
float time() { return self->time(); }
@@ -5909,18 +5914,6 @@ mode_value()
return self->timingArcSet()->modeValue();
}
-const char *
-object_name()
-{
- Sta *sta = Sta::sta();
- const Network *network = sta->cmdNetwork();
- const Graph *graph = sta->graph();
- const char *from = self->from(graph)->name(network);
- const char *to = self->to(graph)->name(network);
- return stringPrintTmp(strlen(from) + strlen(to) + 5,
- "%s -> %s", from, to);
-}
-
const char *
latch_d_to_q_en()
{
@@ -5937,8 +5930,7 @@ latch_d_to_q_en()
TransRiseFall *enable_tr;
lib_cell->latchEnable(d_q_set, enable_port, enable_func, enable_tr);
const char *en_name = enable_port->name();
- return stringPrintTmp(strlen(en_name) + 3,
- "%s %s", en_name, enable_tr->asString());
+ return stringPrintTmp("%s %s", en_name, enable_tr->asString());
}
return "";
diff --git a/util/Error.cc b/util/Error.cc
index 8c5651e2..2ba320a3 100644
--- a/util/Error.cc
+++ b/util/Error.cc
@@ -46,9 +46,7 @@ InternalError::InternalError(const char *filename,
const char *
InternalError::what() const throw()
{
- return stringPrintTmp(strlen("Internal error in : .")
- + strlen(filename_) + strlen(msg_) + 5,
- "Internal error in %s:%d %s.",
+ return stringPrintTmp("Internal error in %s:%d %s.",
filename_, line_, msg_);
}
@@ -60,9 +58,7 @@ FileNotReadable::FileNotReadable(const char *filename) :
const char *
FileNotReadable::what() const throw()
{
- return stringPrintTmp(strlen("Error: cannot read file .")
- + strlen(filename_) + 1,
- "Error: cannot read file %s.", filename_);
+ return stringPrintTmp("Error: cannot read file %s.", filename_);
}
FileNotWritable::FileNotWritable(const char *filename) :
@@ -73,10 +69,7 @@ FileNotWritable::FileNotWritable(const char *filename) :
const char *
FileNotWritable::what() const throw()
{
- return stringPrintTmp(strlen("Error: cannot write file .")
- + strlen(filename_) + 1,
- "Error: cannot write file %s.",
- filename_);
+ return stringPrintTmp("Error: cannot write file %s.", filename_);
}
} // namespace
diff --git a/util/Machine.cc b/util/Machine.cc
index da81658b..f8391f9d 100644
--- a/util/Machine.cc
+++ b/util/Machine.cc
@@ -149,11 +149,10 @@ systemRunTime()
size_t
memoryUsage()
{
- char *proc_filename = stringPrintTmp(strlen("/proc//status")+10,
- "/proc/%d/status",
- getpid());
+ string proc_filename;
+ stringPrint(proc_filename, "/proc/%d/status", getpid());
size_t memory = 0;
- FILE *status = fopen(proc_filename, "r");
+ FILE *status = fopen(proc_filename.c_str(), "r");
if (status) {
const size_t line_length = 128;
char line[line_length];
diff --git a/util/PatternMatch.cc b/util/PatternMatch.cc
index 278a929d..f3176065 100644
--- a/util/PatternMatch.cc
+++ b/util/PatternMatch.cc
@@ -117,7 +117,7 @@ RegexpCompileError::RegexpCompileError(const char *pattern) :
StaException()
{
const char *msg = "Error: TCL failed to compile regular expression '%s'.";
- error_ = stringPrintTmp(strlen(msg) + strlen(pattern) + 1, msg, pattern);
+ error_ = stringPrintTmp(msg, pattern);
}
const char *
diff --git a/util/StringUtil.cc b/util/StringUtil.cc
index 5f95309f..40e00441 100644
--- a/util/StringUtil.cc
+++ b/util/StringUtil.cc
@@ -23,6 +23,17 @@
namespace sta {
+static void
+stringPrintTmp(const char *fmt,
+ va_list args,
+ // Return values.
+ char *&str,
+ size_t &length);
+static void
+getTmpString(// Return values.
+ char *&str,
+ size_t &length);
+
char *
stringCopy(const char *str)
{
@@ -50,97 +61,119 @@ isDigits(const char *str)
char *
integerString(int number)
{
- // Leave room for sign and '\0'.
- return stringPrint(INT_DIGITS + 2, "%d", number);
+ return stringPrint("%d", number);
}
-char *
-stringPrint(int length_estimate,
+// print for c++ strings.
+void
+stringPrint(string &str,
const char *fmt,
...)
{
va_list args;
va_start(args, fmt);
- char *result = stringPrintArgs(length_estimate, fmt, args);
+ char *tmp;
+ size_t tmp_length;
+ stringPrintTmp(fmt, args, tmp, tmp_length);
+ va_end(args);
+ str = tmp;
+}
+
+string
+stdstrPrint(const char *fmt,
+ ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ char *tmp;
+ size_t tmp_length;
+ stringPrintTmp(fmt, args, tmp, tmp_length);
+ va_end(args);
+ return tmp;
+}
+
+char *
+stringPrint(const char *fmt,
+ ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ char *result = stringPrintArgs(fmt, args);
va_end(args);
return result;
}
char *
-stringPrintArgs(int length_estimate,
- const char *fmt,
+stringPrintArgs(const char *fmt,
va_list args)
{
- va_list args_copy;
- va_copy(args_copy, args);
- char *result = new char[length_estimate];
- int length = vsnprint(result, length_estimate, fmt, args);
- if (length >= length_estimate) {
- stringDelete(result);
- result = new char[length + 1];
- vsnprint(result, length + 1, fmt, args_copy);
- }
- va_end(args_copy);
+ char *tmp;
+ size_t tmp_length;
+ stringPrintTmp(fmt, args, tmp, tmp_length);
+ char *result = new char[tmp_length + 1];
+ strcpy(result, tmp);
return result;
}
char *
-stringPrintTmp(int length_estimate,
- const char *fmt,
+stringPrintTmp(const char *fmt,
...)
{
- char *result = makeTmpString(length_estimate);
va_list args;
-
va_start(args, fmt);
- int length = vsnprint(result, length_estimate, fmt, args);
+ char *tmp;
+ size_t tmp_length;
+ stringPrintTmp(fmt, args, tmp, tmp_length);
va_end(args);
+ return tmp;
+}
+static void
+stringPrintTmp(const char *fmt,
+ va_list args,
+ // Return values.
+ char *&tmp,
+ // strlen(tmp), not including terminating '\0'.
+ size_t &tmp_length)
+{
+ size_t tmp_length1;
+ getTmpString(tmp, tmp_length1);
+
+ va_list args_copy;
+ va_copy(args_copy, args);
// Returned length does NOT include trailing '\0'.
- if (length >= length_estimate) {
- result = makeTmpString(length + 1);
- va_start(args, fmt);
- vsnprint(result, length + 1, fmt, args);
- va_end(args);
+ tmp_length = vsnprint(tmp, tmp_length1, fmt, args_copy);
+ va_end(args_copy);
+
+ if (tmp_length >= tmp_length1) {
+ tmp_length1 = tmp_length + 1;
+ tmp = makeTmpString(tmp_length1);
+ va_copy(args_copy, args);
+ tmp_length = vsnprint(tmp, tmp_length1, fmt, args_copy);
+ va_end(args_copy);
}
- return result;
}
////////////////////////////////////////////////////////////////
static int tmp_string_count_ = 100;
-static size_t tmp_string_length_ = 100;
-static int tmp_string_next_ = 0;
static char **tmp_strings_ = NULL;
static size_t *tmp_string_lengths_ = NULL;
+static int tmp_string_next_;
static Mutex string_lock_;
-char *
-makeTmpString(size_t length)
+void
+initTmpStrings()
{
- string_lock_.lock();
- if (tmp_strings_ == NULL) {
- tmp_strings_ = new char*[tmp_string_count_];
- tmp_string_lengths_ = new size_t[tmp_string_count_];
- for (int i = 0; i < tmp_string_count_; i++) {
- tmp_strings_[i] = new char[tmp_string_length_];
- tmp_string_lengths_[i] = tmp_string_length_;
- }
+ size_t initial_length = 100;
+
+ tmp_strings_ = new char*[tmp_string_count_];
+ tmp_string_lengths_ = new size_t[tmp_string_count_];
+ for (int i = 0; i < tmp_string_count_; i++) {
+ tmp_strings_[i] = new char[initial_length];
+ tmp_string_lengths_[i] = initial_length;
}
- if (tmp_string_next_ == tmp_string_count_)
- tmp_string_next_ = 0;
- char *tmp_str = tmp_strings_[tmp_string_next_];
- size_t tmp_length = tmp_string_lengths_[tmp_string_next_];
- if (tmp_length < length) {
- // String isn't long enough. Make a new one.
- stringDelete(tmp_str);
- tmp_str = new char[length];
- tmp_strings_[tmp_string_next_] = tmp_str;
- tmp_string_lengths_[tmp_string_next_] = length;
- }
- tmp_string_next_++;
- string_lock_.unlock();
- return tmp_str;
+ tmp_string_next_ = 0;
}
void
@@ -157,6 +190,40 @@ deleteTmpStrings()
}
}
+static void
+getTmpString(// Return values.
+ char *&str,
+ size_t &length)
+{
+ string_lock_.lock();
+ if (tmp_string_next_ == tmp_string_count_)
+ tmp_string_next_ = 0;
+ str = tmp_strings_[tmp_string_next_];
+ length = tmp_string_lengths_[tmp_string_next_];
+ tmp_string_next_++;
+ string_lock_.unlock();
+}
+
+char *
+makeTmpString(size_t length)
+{
+ string_lock_.lock();
+ if (tmp_string_next_ == tmp_string_count_)
+ tmp_string_next_ = 0;
+ char *tmp_str = tmp_strings_[tmp_string_next_];
+ size_t tmp_length = tmp_string_lengths_[tmp_string_next_];
+ if (tmp_length < length) {
+ // String isn't long enough. Make a new one.
+ stringDelete(tmp_str);
+ tmp_str = new char[length];
+ tmp_strings_[tmp_string_next_] = tmp_str;
+ tmp_string_lengths_[tmp_string_next_] = length;
+ }
+ tmp_string_next_++;
+ string_lock_.unlock();
+ return tmp_str;
+}
+
////////////////////////////////////////////////////////////////
void
diff --git a/util/StringUtil.hh b/util/StringUtil.hh
index bf782336..d0f5ad54 100644
--- a/util/StringUtil.hh
+++ b/util/StringUtil.hh
@@ -132,21 +132,25 @@ bool
isDigits(const char *str);
// Print to a new string.
-// length_estimate should include room for the terminating '\0'.
+// Caller owns returned string.
char *
-stringPrint(int length_estimate,
- const char *fmt,
- ...);
+stringPrint(const char *fmt,
+ ...) __attribute__((format (printf, 1, 2)));
+string
+stdstrPrint(const char *fmt,
+ ...) __attribute__((format (printf, 1, 2)));
char *
-stringPrintArgs(int length_estimate,
- const char *fmt,
+stringPrintArgs(const char *fmt,
va_list args);
+void
+stringPrint(string &str,
+ const char *fmt,
+ ...) __attribute__((format (printf, 2, 3)));
+
// Print to a temporary string.
-// length_estimate should include room for the terminating '\0'.
char *
-stringPrintTmp(int length_estimate,
- const char *fmt,
- ...);
+stringPrintTmp(const char *fmt,
+ ...) __attribute__((format (printf, 1, 2)));
// Caller owns returned string.
char *
integerString(int number);
@@ -154,6 +158,8 @@ integerString(int number);
char *
makeTmpString(size_t length);
void
+initTmpStrings();
+void
deleteTmpStrings();
////////////////////////////////////////////////////////////////
diff --git a/util/ThreadException.cc b/util/ThreadException.cc
index 6738a457..295648c0 100644
--- a/util/ThreadException.cc
+++ b/util/ThreadException.cc
@@ -32,9 +32,7 @@ const char *
ThreadException::what() const throw()
{
const char *msg = strerror(error_);
- return stringPrintTmp(strlen(filename_) + strlen(msg) + 30,
- "Thread error in %s:%d %s.",
- filename_, line_, msg);
+ return stringPrintTmp("Thread error in %s:%d %s.", filename_, line_, msg);
}
}
diff --git a/util/TokenParser.hh b/util/TokenParser.hh
index 274dee39..d22cd0a8 100644
--- a/util/TokenParser.hh
+++ b/util/TokenParser.hh
@@ -31,7 +31,8 @@ namespace sta {
class TokenParser
{
public:
- TokenParser(const char *str, const char *delimiters);
+ TokenParser(const char *str,
+ const char *delimiters);
bool hasNext();
char *next();
diff --git a/verilog/VerilogReader.cc b/verilog/VerilogReader.cc
index 2662e9f4..c4b90e67 100644
--- a/verilog/VerilogReader.cc
+++ b/verilog/VerilogReader.cc
@@ -153,7 +153,7 @@ VerilogReader::VerilogReader(Report *report,
{
network->setLinkFunc(linkVerilogNetwork);
VerilogConstant10 constant10_max = 0;
- constant10_max_ = stringPrint(21, "%llu", ~constant10_max);
+ constant10_max_ = stringPrint("%llu", ~constant10_max);
constant10_max_length_ = strlen(constant10_max_);
}
@@ -851,8 +851,7 @@ VerilogModule::checkInstanceName(VerilogInst *inst,
do {
if (replacement_name)
stringDelete(replacement_name);
- replacement_name = stringPrint(strlen(inst_name) + 4,
- "%s_%d", inst_name, i);
+ replacement_name = stringPrint("%s_%d", inst_name, i);
} while (inst_names.findKey(replacement_name));
reader->warn(filename_, inst->line(),
"instance name %s duplicated - renamed to %s.\n",
@@ -1161,14 +1160,14 @@ static const char *
verilogBusBitNameTmp(const char *bus_name,
int index)
{
- return stringPrintTmp(strlen(bus_name) + 8, "%s[%d]", bus_name, index);
+ return stringPrintTmp("%s[%d]", bus_name, index);
}
static const char *
verilogBusBitName(const char *bus_name,
int index)
{
- return stringPrint(strlen(bus_name) + 8, "%s[%d]", bus_name, index);
+ return stringPrint("%s[%d]", bus_name, index);
}
class VerilogConstantNetNameIterator : public VerilogNetNameIterator
@@ -2041,10 +2040,11 @@ VerilogReader::makeBlackBoxOrderedPorts(Cell *cell,
while (pin_iter.hasNext()) {
VerilogNet *net = pin_iter.next();
size_t size = net->size(parent_module);
- char *port_name = stringPrintTmp(8, "p_%lu", port_index);
+ char *port_name = stringPrint("p_%d", port_index);
Port *port = (size == 1)
? network_->makePort(cell, port_name)
: network_->makeBusPort(cell, port_name, size - 1, 0);
+ stringDelete(port_name);
network_->setDirection(port, PortDirection::bidirect());
port_index++;
}
@@ -2161,7 +2161,7 @@ VerilogReader::linkWarn(const char *filename,
{
va_list args;
va_start(args, msg);
- char *msg_str = stringPrintArgs(strlen(msg) + 128, msg, args);
+ char *msg_str = stringPrintArgs(msg, args);
VerilogError *error = new VerilogError(filename, line, msg_str, true);
link_errors_.push_back(error);
va_end(args);
@@ -2174,7 +2174,7 @@ VerilogReader::linkError(const char *filename,
{
va_list args;
va_start(args, msg);
- char *msg_str = stringPrintArgs(strlen(msg) + 128, msg, args);
+ char *msg_str = stringPrintArgs(msg, args);
VerilogError *error = new VerilogError(filename, line, msg_str, false);
link_errors_.push_back(error);
va_end(args);
|