Merge branch 'master' into master

This commit is contained in:
Abdelrahman 2019-01-17 16:28:15 -05:00 committed by GitHub
commit 2c928b7f51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 1459 additions and 1138 deletions

View File

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

View File

@ -1,29 +1,30 @@
FROM ubuntu:18.04
RUN apt-get update && \
apt-get install -y wget apt-utils git libtool autoconf
apt-get install -y wget apt-utils git
# download CUDD
RUN wget https://www.davidkebo.com/source/cudd_versions/cudd-3.0.0.tar.gz && \
RUN wget https://www.davidkebo.com/source/cudd_versions/cudd-3.0.0.tar.gz && \
tar -xvf cudd-3.0.0.tar.gz
# install main dependencies
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y clang gcc tcl tcl-dev swig bison flex
apt-get install -y cmake gcc tcl tcl-dev swig bison flex
# install CUDD
RUN cd cudd-3.0.0 && \
./configure --enable-dddmp --enable-obj --enable-shared --enable-static && \
mkdir ../cudd && \
./configure --prefix=$HOME/cudd && \
make && \
make check
make install
# clone and install OpenSTA
RUN git clone https://github.com/abdelrahmanhosny/OpenSTA.git && \
RUN git clone https://github.com/abk-openroad/OpenSTA.git && \
cd OpenSTA && \
libtoolize && \
./bootstrap && \
./configure && \
mkdir build && \
cd build && \
cmake .. -DCUDD=$HOME/cudd && \
make
# Run sta on entry

16
INSTALL
View File

@ -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<var>=<value> 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=<prefix_path> 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
-----------------------

View File

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

View File

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

View File

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

Binary file not shown.

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<float>::digits10 + 10;
return stringPrintTmp(result_len, "%.*f%s", digits, scaled_value, suffix_);
return stringPrintTmp("%.*f%s", digits, scaled_value, suffix_);
}
}

View File

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

View File

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

View File

@ -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<Pin*>(cpin);
}
@ -1288,13 +1296,15 @@ ConcreteNetwork::disconnectPin(Pin *pin)
ConcretePin *cpin = reinterpret_cast<ConcretePin*>(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();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -17,14 +17,18 @@
#include <limits>
#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<int>(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);

View File

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

View File

@ -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<int,char*,std::less<int> > 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

View File

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

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cmath> // ceil
#include <algorithm> // 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();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -17,22 +17,32 @@
#ifndef STA_PROPERTY_H
#define STA_PROPERTY_H
#include <string>
#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

View File

@ -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<int>(fanout));
result += field;
}
else
result += stdstrPrint("%*d",
field_fanout_->width(),
static_cast<int>(fanout));
}
else if (field == field_capacitance_)
reportField(cap, field, result);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<char*>(""), TCL_STATIC);
break;
case PropertyValue::Type::type_string:
Tcl_SetResult(interp, const_cast<char*>(value.string()), TCL_VOLATILE);
Tcl_SetResult(interp, const_cast<char*>(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<char*>(""), 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<Cell*>(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 "";

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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