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. # Copyright (c) 2019, Parallax Software, Inc.
# All rights reserved.
# #
# This program is free software: you can redistribute it and/or modify # No part of this document may be copied, transmitted or
# it under the terms of the GNU General Public License as published by # disclosed in any form or fashion without the express
# the Free Software Foundation, either version 3 of the License, or # written consent of Parallax Software, Inc.
# (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/>.
cmake_minimum_required (VERSION 3.9) 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_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
@ -113,19 +105,12 @@ set(STA_SOURCE
parasitics/EstimateParasitics.cc parasitics/EstimateParasitics.cc
parasitics/NullParasitics.cc parasitics/NullParasitics.cc
parasitics/Parasitics.cc parasitics/Parasitics.cc
parasitics/ReadParasitics.cc
parasitics/ReduceParasitics.cc parasitics/ReduceParasitics.cc
parasitics/SpefLex.cc parasitics/SpefLex.cc
parasitics/SpefNamespace.cc parasitics/SpefNamespace.cc
parasitics/SpefParse.cc parasitics/SpefParse.cc
parasitics/SpefReader.cc parasitics/SpefReader.cc
parasitics/SpefReaderPvt.hh 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/Clock.cc
sdc/ClockGatingCheck.cc sdc/ClockGatingCheck.cc
@ -288,11 +273,9 @@ set(STA_HEADERS
parasitics/NullParasitics.hh parasitics/NullParasitics.hh
parasitics/Parasitics.hh parasitics/Parasitics.hh
parasitics/ParasiticsClass.hh parasitics/ParasiticsClass.hh
parasitics/ReadParasitics.hh
parasitics/ReduceParasitics.hh parasitics/ReduceParasitics.hh
parasitics/SpefNamespace.hh parasitics/SpefNamespace.hh
parasitics/SpefReader.hh parasitics/SpefReader.hh
parasitics/SpfReader.hh
sdc/Clock.hh sdc/Clock.hh
sdc/ClockGatingCheck.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) 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. # Verilog scan/parse.
bison_target(VerilogParser verilog/VerilogParse.yy ${STA_HOME}/verilog/VerilogParse.cc bison_target(VerilogParser verilog/VerilogParse.yy ${STA_HOME}/verilog/VerilogParse.cc
DEFINES_FILE ${STA_HOME}/verilog/VerilogParse.hh DEFINES_FILE ${STA_HOME}/verilog/VerilogParse.hh

View File

@ -1,7 +1,7 @@
FROM ubuntu:18.04 FROM ubuntu:18.04
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y wget apt-utils git libtool autoconf apt-get install -y wget apt-utils git
# download CUDD # 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 && \
@ -10,20 +10,21 @@ RUN wget https://www.davidkebo.com/source/cudd_versions/cudd-3.0.0.tar.gz && \
# install main dependencies # install main dependencies
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \ 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 # install CUDD
RUN cd cudd-3.0.0 && \ RUN cd cudd-3.0.0 && \
./configure --enable-dddmp --enable-obj --enable-shared --enable-static && \ mkdir ../cudd && \
./configure --prefix=$HOME/cudd && \
make && \ make && \
make check make install
# clone and install OpenSTA # 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 && \ cd OpenSTA && \
libtoolize && \ mkdir build && \
./bootstrap && \ cd build && \
./configure && \ cmake .. -DCUDD=$HOME/cudd && \
make make
# Run sta on entry # 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 version 3.0. This build only supports the 3.0 layout but only small
changes to configure.ac are required to support older versions. 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, The Zlib library is an optional. If the configure script finds libz,
OpenSTA can read Verilog, SDF, SPF, and SPEF files compressed with OpenSTA can read Verilog, SDF, SPF, and SPEF files compressed with
gzip. gzip.
@ -70,8 +80,10 @@ Optional cmake variables passed as -D<var>=<value> arguments to cmake
are show below. are show below.
CMAKE_BUILD_TYPE DEBUG|RELEASE CMAKE_BUILD_TYPE DEBUG|RELEASE
CMAKE_CXX_FLAGS - additional compiler flags
TCL_LIB - path to tcl library TCL_LIB - path to tcl library
TCL_HEADER - path to tcl.h TCL_HEADER - path to tcl.h
ZLIB_ROOT - path to zlib
CMAKE_INSTALL_PREFIX CMAKE_INSTALL_PREFIX
If TCL_LIB is specified the cmake script will attempt to locate the 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 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 Building from a tarfile
----------------------- -----------------------

View File

@ -188,11 +188,9 @@ static void
sourceTclFileEchoVerbose(const char *filename, sourceTclFileEchoVerbose(const char *filename,
Tcl_Interp *interp) Tcl_Interp *interp)
{ {
const char *source_cmd = "source -echo -verbose "; string cmd;
size_t cmd_length = strlen(source_cmd) + strlen(filename) + 1; stringPrint(cmd, "source -echo -verbose %s", filename);
char *cmd = stringPrint(cmd_length, "%s%s", source_cmd, filename); Tcl_Eval(interp, cmd.c_str());
Tcl_Eval(interp, cmd);
delete [] cmd;
} }
void void

View File

@ -16,7 +16,7 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
AC_INIT(sta, 2.0.4) AC_INIT(sta, 2.0.5)
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS(config.h) AC_CONFIG_HEADERS(config.h)

View File

@ -82,17 +82,17 @@ proc report_edge_dcalc { edge corner min_max digits } {
# Filter timing checks based on min_max. # Filter timing checks based on min_max.
if {!(($min_max == "max" && $role == "hold") \ if {!(($min_max == "max" && $role == "hold") \
|| ($min_max=="min" && $role=="setup"))} { || ($min_max=="min" && $role=="setup"))} {
puts "Library: [$library name]" puts "Library: [get_name $library]"
puts "Cell: [$cell name]" puts "Cell: [get_name $cell]"
puts "Arc sense: [$edge sense]" puts "Arc sense: [$edge sense]"
puts "Arc type: $role" puts "Arc type: $role"
set arc_iter [$edge timing_arc_iterator] set arc_iter [$edge timing_arc_iterator]
while {[$arc_iter has_next]} { while {[$arc_iter has_next]} {
set arc [$arc_iter 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 from_tr [$arc from_trans]
set to [[$to_pin port] name] set to [get_name [$to_pin port]]
set to_tr [$arc to_trans] set to_tr [$arc to_trans]
puts "$from $from_tr -> $to $to_tr" puts "$from $from_tr -> $to $to_tr"
puts -nonewline [report_delay_calc_cmd $edge $arc $corner $min_max $digits] 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_early = delay.sigma(EarlyLate::early());
float sigma_late = delay.sigma(EarlyLate::late()); float sigma_late = delay.sigma(EarlyLate::late());
if (fuzzyEqual(sigma_early, sigma_late)) if (fuzzyEqual(sigma_early, sigma_late))
return stringPrintTmp((digits + 4) * 2 + 2, return stringPrintTmp("%s|%s",
"%s|%s",
unit->asString(delay.mean(), digits), unit->asString(delay.mean(), digits),
unit->asString(sigma_early, digits)); unit->asString(sigma_early, digits));
else else
return stringPrintTmp((digits + 4) * 3 + 3, return stringPrintTmp("%s|%s:%s",
"%s|%s:%s",
unit->asString(delay.mean(), digits), unit->asString(delay.mean(), digits),
unit->asString(sigma_early, digits), unit->asString(sigma_early, digits),
unit->asString(sigma_late, digits)); unit->asString(sigma_late, digits));

View File

@ -1169,8 +1169,7 @@ Vertex::name(const Network *network) const
{ {
if (network->direction(pin_)->isBidirect()) { if (network->direction(pin_)->isBidirect()) {
const char *pin_name = network->pathName(pin_); const char *pin_name = network->pathName(pin_);
int result_len = strlen(pin_name) + strlen("driver") + 2; return stringPrintTmp("%s %s",
return stringPrintTmp(result_len, "%s %s",
pin_name, pin_name,
is_bidirect_drvr_ ? "driver" : "load"); is_bidirect_drvr_ ? "driver" : "load");
} }

View File

@ -385,7 +385,7 @@ public:
const char *name, const char *name,
const char *filename); const char *filename);
virtual ~LibertyCell(); virtual ~LibertyCell();
const LibertyLibrary *libertyLibrary() const { return liberty_library_; } LibertyLibrary *libertyLibrary() const { return liberty_library_; }
LibertyLibrary *libertyLibrary() { return liberty_library_; } LibertyLibrary *libertyLibrary() { return liberty_library_; }
LibertyPort *findLibertyPort(const char *name) const; LibertyPort *findLibertyPort(const char *name) const;
void findLibertyPortsMatching(PatternMatch *pattern, void findLibertyPortsMatching(PatternMatch *pattern,

View File

@ -84,7 +84,7 @@ LibertyBuilder::makeBusPortBit(ConcreteLibrary *library,
const char *bus_name, const char *bus_name,
int bit_index) 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, bus_name,
library->busBrktLeft(), library->busBrktLeft(),
bit_index, bit_index,

View File

@ -107,7 +107,7 @@ simple_attr_value:
/* Unquoted NOT function. */ /* Unquoted NOT function. */
/* clocked_on : !CP; */ /* clocked_on : !CP; */
| '!' string | '!' string
{ $$ = sta::makeLibertyStringAttrValue(sta::stringPrint(strlen($2)+1, "!%s", $2)); sta::stringDelete($2); } { $$ = sta::makeLibertyStringAttrValue(sta::stringPrint("!%s", $2)); sta::stringDelete($2); }
; ;
complex_attr: complex_attr:

View File

@ -461,11 +461,7 @@ LibertyReader::defineScalingFactorVisitors()
while (tr_iter.hasNext()) { while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next(); TransRiseFall *tr = tr_iter.next();
const char *tr_name = (tr == TransRiseFall::rise()) ? "rise":"fall"; const char *tr_name = (tr == TransRiseFall::rise()) ? "rise":"fall";
const char *attr_name = stringPrintTmp(strlen(pvt_name) const char *attr_name = stringPrintTmp("k_%s_%s_%s",
+ strlen(type_name)
+ strlen(tr_name)
+ 5, // k___\0
"k_%s_%s_%s",
pvt_name, pvt_name,
type_name, type_name,
tr_name); tr_name);
@ -477,11 +473,7 @@ LibertyReader::defineScalingFactorVisitors()
while (tr_iter.hasNext()) { while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next(); TransRiseFall *tr = tr_iter.next();
const char *tr_name = (tr == TransRiseFall::rise()) ? "rise":"fall"; const char *tr_name = (tr == TransRiseFall::rise()) ? "rise":"fall";
const char *attr_name = stringPrintTmp(strlen(pvt_name) const char *attr_name = stringPrintTmp("k_%s_%s_%s",
+ strlen(type_name)
+ strlen(tr_name)
+ 5, // k___\0
"k_%s_%s_%s",
pvt_name, pvt_name,
tr_name, tr_name,
type_name); type_name);
@ -493,11 +485,7 @@ LibertyReader::defineScalingFactorVisitors()
while (tr_iter.hasNext()) { while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next(); TransRiseFall *tr = tr_iter.next();
const char *tr_name = (tr == TransRiseFall::rise()) ? "high":"low"; const char *tr_name = (tr == TransRiseFall::rise()) ? "high":"low";
const char *attr_name = stringPrintTmp(strlen(pvt_name) const char *attr_name = stringPrintTmp("k_%s_%s_%s",
+ strlen(type_name)
+ strlen(tr_name)
+ 5, // k___\0
"k_%s_%s_%s",
pvt_name, pvt_name,
tr_name, tr_name,
type_name); type_name);
@ -505,10 +493,7 @@ LibertyReader::defineScalingFactorVisitors()
} }
} }
else { else {
const char *attr_name = stringPrintTmp(strlen(pvt_name) const char *attr_name = stringPrintTmp("k_%s_%s",
+ strlen(type_name)
+ 4, // k__\0
"k_%s_%s",
pvt_name, pvt_name,
type_name); type_name);
defineAttrVisitor(attr_name,&LibertyReader::visitScaleFactor); defineAttrVisitor(attr_name,&LibertyReader::visitScaleFactor);
@ -4327,12 +4312,7 @@ LibertyReader::parseFunc(const char *func,
const char *attr_name, const char *attr_name,
int line) int line)
{ {
const char *error_msg = stringPrintTmp(strlen(filename_) const char *error_msg = stringPrintTmp("%s, line %d %s",
+ strlen(", line ")
+ 8
+ strlen(attr_name)
+ 2,
"%s, line %d %s",
filename_, filename_,
line, line,
attr_name); attr_name);
@ -5221,8 +5201,7 @@ PortNameBitIterator::findRangeBusNameNext()
? range_bit_ >= range_to_ ? range_bit_ >= range_to_
: range_bit_ <= range_to_) { : range_bit_ <= range_to_) {
LibertyLibrary *library = visitor_->library(); LibertyLibrary *library = visitor_->library();
const char *bus_bit_name = stringPrintTmp(strlen(range_bus_name_) + 10, const char *bus_bit_name = stringPrintTmp("%s%c%d%c",
"%s%c%d%c",
range_bus_name_, range_bus_name_,
library->busBrktLeft(), library->busBrktLeft(),
range_bit_, range_bit_,

View File

@ -592,14 +592,12 @@ reportPvt(const LibertyLibrary *library,
if (pvt == NULL) if (pvt == NULL)
pvt = library->defaultOperatingConditions(); pvt = library->defaultOperatingConditions();
if (pvt) { if (pvt) {
const char *pvt_str = stringPrint(strlen("P = %.*f V = %.*f T = %.*f\n") string pvt_str;
+ (digits + 10) * 3 + 1, stringPrint(pvt_str, "P = %.*f V = %.*f T = %.*f\n",
"P = %.*f V = %.*f T = %.*f\n",
digits, pvt->process(), digits, pvt->process(),
digits, pvt->voltage(), digits, pvt->voltage(),
digits, pvt->temperature()); digits, pvt->temperature());
*result += pvt_str; *result += pvt_str;
stringDelete(pvt_str);
} }
} }
@ -613,13 +611,11 @@ TableModel::reportPvtScaleFactor(const LibertyLibrary *library,
if (pvt == NULL) if (pvt == NULL)
pvt = library->defaultOperatingConditions(); pvt = library->defaultOperatingConditions();
if (pvt) { if (pvt) {
const char *scale_str = stringPrint(strlen("PVT scale factor = %.*f\n") string scale_str;
+ digits + 10 + 1, stringPrint(scale_str, "PVT scale factor = %.*f\n",
"PVT scale factor = %.*f\n",
digits, digits,
scaleFactor(library, cell, pvt)); scaleFactor(library, cell, pvt));
*result += scale_str; *result += scale_str;
stringDelete(scale_str);
} }
} }

View File

@ -106,9 +106,7 @@ Unit::asString(float value,
// prevent "-0.00" on slowaris // prevent "-0.00" on slowaris
if (abs(scaled_value) < 1E-6) if (abs(scaled_value) < 1E-6)
scaled_value = 0.0; scaled_value = 0.0;
// Leave room for sign, E+-exponent. return stringPrintTmp("%.*f%s", digits, scaled_value, suffix_);
const int result_len = std::numeric_limits<float>::digits10 + 10;
return stringPrintTmp(result_len, "%.*f%s", digits, scaled_value, suffix_);
} }
} }

View File

@ -41,7 +41,9 @@ ConcreteLibrary::~ConcreteLibrary()
} }
ConcreteCell * 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); ConcreteCell *cell = new ConcreteCell(this, name, is_leaf, filename);
addCell(cell); addCell(cell);
@ -55,7 +57,8 @@ ConcreteLibrary::addCell(ConcreteCell *cell)
} }
void void
ConcreteLibrary::renameCell(ConcreteCell *cell, const char *cell_name) ConcreteLibrary::renameCell(ConcreteCell *cell,
const char *cell_name)
{ {
cell_map_.eraseKey(cell->name()); cell_map_.eraseKey(cell->name());
cell_map_[cell_name] = cell; cell_map_[cell_name] = cell;
@ -93,7 +96,8 @@ ConcreteLibrary::findCellsMatching(const PatternMatch *pattern,
} }
void void
ConcreteLibrary::setBusBrkts(char left, char right) ConcreteLibrary::setBusBrkts(char left,
char right)
{ {
bus_brkt_left_ = left; bus_brkt_left_ = left;
bus_brkt_right_ = right; bus_brkt_right_ = right;
@ -101,8 +105,10 @@ ConcreteLibrary::setBusBrkts(char left, char right)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
ConcreteCell::ConcreteCell(ConcreteLibrary *library, const char *name, ConcreteCell::ConcreteCell(ConcreteLibrary *library,
bool is_leaf, const char *filename): const char *name,
bool is_leaf,
const char *filename):
library_(library), library_(library),
name_(stringCopy(name)), name_(stringCopy(name)),
filename_(stringCopy(filename)), filename_(stringCopy(filename)),
@ -137,7 +143,8 @@ ConcreteCell::makePort(const char *name)
} }
ConcretePort * ConcretePort *
ConcreteCell::makeBundlePort(const char *name, ConcretePortSeq *members) ConcreteCell::makeBundlePort(const char *name,
ConcretePortSeq *members)
{ {
ConcretePort *port = new ConcretePort(this, name, false, -1, -1, ConcretePort *port = new ConcretePort(this, name, false, -1, -1,
true, members); true, members);
@ -146,7 +153,9 @@ ConcreteCell::makeBundlePort(const char *name, ConcretePortSeq *members)
} }
ConcretePort * 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, ConcretePort *port = new ConcretePort(this, name, true, from_index, to_index,
false, new ConcretePortSeq); false, new ConcretePortSeq);
@ -156,7 +165,9 @@ ConcreteCell::makeBusPort(const char *name, int from_index, int to_index)
} }
ConcretePort * 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) ConcretePortSeq *members)
{ {
ConcretePort *port = new ConcretePort(this, name, true, from_index, to_index, 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 void
ConcreteCell::makeBusPortBits(ConcretePort *bus_port, const char *name, ConcreteCell::makeBusPortBits(ConcretePort *bus_port,
int from_index, int to_index) const char *name,
int from_index,
int to_index)
{ {
if (from_index < to_index) { if (from_index < to_index) {
for (int index = from_index; index <= to_index; index++) for (int index = from_index; index <= to_index; index++)
@ -180,21 +193,24 @@ ConcreteCell::makeBusPortBits(ConcretePort *bus_port, const char *name,
} }
void void
ConcreteCell::makeBusPortBit(ConcretePort *bus_port, const char *bus_name, ConcreteCell::makeBusPortBit(ConcretePort *bus_port,
const char *bus_name,
int bit_index) int bit_index)
{ {
char *bit_name = stringPrintTmp(strlen(bus_name) + 8, "%s%c%d%c", string bit_name;
stringPrint(bit_name, "%s%c%d%c",
bus_name, bus_name,
library_->busBrktLeft(), library_->busBrktLeft(),
bit_index, bit_index,
library_->busBrktRight()); library_->busBrktRight());
ConcretePort *port = makePort(bit_name, bit_index); ConcretePort *port = makePort(bit_name.c_str(), bit_index);
bus_port->addPortBit(port); bus_port->addPortBit(port);
addPortBit(port); addPortBit(port);
} }
ConcretePort * 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, ConcretePort *port = new ConcretePort(this, bit_name, false, bit_index,
bit_index, false, NULL); bit_index, false, NULL);
@ -278,7 +294,9 @@ ConcreteCell::portBitIterator() const
class BusPort class BusPort
{ {
public: public:
BusPort(const char *name, int from, PortDirection *direction); BusPort(const char *name,
int from,
PortDirection *direction);
~BusPort(); ~BusPort();
const char *name() const { return name_; } const char *name() const { return name_; }
void pushMember(ConcretePort *port); void pushMember(ConcretePort *port);
@ -298,7 +316,9 @@ private:
ConcretePortSeq *members_; ConcretePortSeq *members_;
}; };
BusPort::BusPort(const char *name, int from, PortDirection *direction) : BusPort::BusPort(const char *name,
int from,
PortDirection *direction) :
name_(name), name_(name),
from_(from), from_(from),
to_(from), to_(from),
@ -392,9 +412,13 @@ ConcreteCell::groupBusPorts(const char *bus_brkts_left,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
ConcretePort::ConcretePort(ConcreteCell *cell, const char *name, ConcretePort::ConcretePort(ConcreteCell *cell,
bool is_bus, int from_index, int to_index, const char *name,
bool is_bundle, ConcretePortSeq *member_ports) : bool is_bus,
int from_index,
int to_index,
bool is_bundle,
ConcretePortSeq *member_ports) :
name_(stringCopy(name)), name_(stringCopy(name)),
cell_(cell), cell_(cell),
direction_(PortDirection::unknown()), direction_(PortDirection::unknown()),
@ -428,8 +452,7 @@ ConcretePort::busName() const
{ {
if (is_bus_) { if (is_bus_) {
ConcreteLibrary *lib = cell_->library(); ConcreteLibrary *lib = cell_->library();
return stringPrintTmp(strlen(name_) + 10, return stringPrintTmp("%s%c%d:%d%c",
"%s%c%d:%d%c",
name_, name_,
lib->busBrktLeft(), lib->busBrktLeft(),
from_index_, from_index_,

View File

@ -52,7 +52,8 @@ public:
void setName(const char *name); void setName(const char *name);
virtual const char *filename() const { return filename_; } virtual const char *filename() const { return filename_; }
void addCell(ConcreteCell *cell); 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); const char *filename);
void deleteCell(ConcreteCell *cell); void deleteCell(ConcreteCell *cell);
ConcreteLibraryCellIterator *cellIterator() const; ConcreteLibraryCellIterator *cellIterator() const;
@ -61,10 +62,12 @@ public:
CellSeq *cells) const; CellSeq *cells) const;
virtual char busBrktLeft() { return bus_brkt_left_; } virtual char busBrktLeft() { return bus_brkt_left_; }
virtual char busBrktRight() { return bus_brkt_right_; } virtual char busBrktRight() { return bus_brkt_right_; }
void setBusBrkts(char left, char right); void setBusBrkts(char left,
char right);
protected: protected:
void renameCell(ConcreteCell *cell, const char *cell_name); void renameCell(ConcreteCell *cell,
const char *cell_name);
const char *name_; const char *name_;
const char *filename_; const char *filename_;
@ -98,26 +101,39 @@ public:
// Cell acts as port factory. // Cell acts as port factory.
ConcretePort *makePort(const char *name); ConcretePort *makePort(const char *name);
// Bus port. // 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. // Bundle port.
ConcretePort *makeBundlePort(const char *name, ConcretePortSeq *members); ConcretePort *makeBundlePort(const char *name,
ConcretePortSeq *members);
// Group previously defined bus bit ports together. // 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; size_t portCount() const;
void setName(const char *name); void setName(const char *name);
virtual void addPort(ConcretePort *port); virtual void addPort(ConcretePort *port);
void addPortBit(ConcretePort *port); void addPortBit(ConcretePort *port);
protected: protected:
ConcreteCell(ConcreteLibrary *library, const char *name, ConcreteCell(ConcreteLibrary *library,
bool is_leaf, const char *filename); const char *name,
ConcretePort *makeBusPort(const char *name, int from_index, int to_index, bool is_leaf,
const char *filename);
ConcretePort *makeBusPort(const char *name,
int from_index,
int to_index,
ConcretePortSeq *members); ConcretePortSeq *members);
void makeBusPortBits(ConcretePort *bus_port, const char *name, void makeBusPortBits(ConcretePort *bus_port,
int from_index, int to_index); const char *name,
int from_index,
int to_index);
// Bus port bit (internal to makeBusPortBits). // Bus port bit (internal to makeBusPortBits).
virtual ConcretePort *makePort(const char *bit_name, int bit_index); virtual ConcretePort *makePort(const char *bit_name,
void makeBusPortBit(ConcretePort *bus_port, const char *name, int index); int bit_index);
void makeBusPortBit(ConcretePort *bus_port,
const char *name,
int index);
ConcreteLibrary *library_; ConcreteLibrary *library_;
const char *name_; const char *name_;
@ -182,9 +198,13 @@ public:
protected: protected:
// Constructors for factory in cell class. // Constructors for factory in cell class.
ConcretePort(ConcreteCell *cell, const char *name, ConcretePort(ConcreteCell *cell,
bool is_bus, int from_index, int to_index, const char *name,
bool is_bundle, ConcretePortSeq *member_ports); bool is_bus,
int from_index,
int to_index,
bool is_bundle,
ConcretePortSeq *member_ports);
const char *name_; const char *name_;
ConcreteCell *cell_; ConcreteCell *cell_;

View File

@ -1250,14 +1250,22 @@ ConcreteNetwork::connect(Instance *inst,
ConcreteNet *prev_net = cpin->net_; ConcreteNet *prev_net = cpin->net_;
if (prev_net) if (prev_net)
disconnectNetPin(prev_net, cpin); disconnectNetPin(prev_net, cpin);
cpin->net_ = cnet;
} }
else { else {
cpin = new ConcretePin(cinst, cport, cnet); cpin = new ConcretePin(cinst, cport, cnet);
cinst->addPin(cpin); 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); connectNetPin(cnet, cpin);
}
return reinterpret_cast<Pin*>(cpin); return reinterpret_cast<Pin*>(cpin);
} }
@ -1288,6 +1296,7 @@ ConcreteNetwork::disconnectPin(Pin *pin)
ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin); ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin);
if (cpin->instance() == top_instance_) { if (cpin->instance() == top_instance_) {
ConcreteTerm *cterm = cpin->term_; ConcreteTerm *cterm = cpin->term_;
if (cterm) {
ConcreteNet *cnet = cterm->net_; ConcreteNet *cnet = cterm->net_;
if (cnet) { if (cnet) {
cnet->deleteTerm(cterm); cnet->deleteTerm(cterm);
@ -1296,6 +1305,7 @@ ConcreteNetwork::disconnectPin(Pin *pin)
cpin->term_ = NULL; cpin->term_ = NULL;
delete cterm; delete cterm;
} }
}
else { else {
ConcreteNet *cnet = cpin->net(); ConcreteNet *cnet = cpin->net();
if (cnet) if (cnet)

View File

@ -901,17 +901,13 @@ Network::findInstPinsHierMatching(const Instance *instance,
PinSeq *pins) const PinSeq *pins) const
{ {
const char *inst_name = name(instance); const char *inst_name = name(instance);
size_t inst_length = strlen(inst_name);
InstancePinIterator *pin_iter = pinIterator(instance); InstancePinIterator *pin_iter = pinIterator(instance);
while (pin_iter->hasNext()) { while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next(); Pin *pin = pin_iter->next();
const char *port_name = name(port(pin)); const char *port_name = name(port(pin));
const char *pin_name = stringPrintTmp(inst_length+strlen(port_name)+2, string pin_name;
"%s%c%s", stringPrint(pin_name, "%s%c%s", inst_name,divider_, port_name);
inst_name, if (pattern->match(pin_name.c_str()))
divider_,
port_name);
if (pattern->match(pin_name))
pins->push_back(pin); pins->push_back(pin);
} }
delete pin_iter; delete pin_iter;

View File

@ -528,8 +528,7 @@ const char *
ConcreteParasiticSubNode::name(const Network *network) const ConcreteParasiticSubNode::name(const Network *network) const
{ {
const char *net_name = network->pathName(net_); const char *net_name = network->pathName(net_);
return stringPrintTmp(strlen(net_name) + INT_DIGITS + 2, return stringPrintTmp("%s:%d", net_name, id_);
"%s:%d", net_name, id_);
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -20,51 +20,31 @@ include_HEADERS = \
ConcreteParasitics.hh \ ConcreteParasitics.hh \
ConcreteParasiticsPvt.hh \ ConcreteParasiticsPvt.hh \
EstimateParasitics.hh \ EstimateParasitics.hh \
MakeConcreteParasitics.hh \
NullParasitics.hh \ NullParasitics.hh \
Parasitics.hh \ Parasitics.hh \
ParasiticsClass.hh \ ParasiticsClass.hh \
ReadParasitics.hh \
ReduceParasitics.hh \ ReduceParasitics.hh \
SpefNamespace.hh \ SpefNamespace.hh \
SpefReader.hh \ SpefReader.hh
SpfReader.hh
libparasitics_la_SOURCES = \ libparasitics_la_SOURCES = \
ConcreteParasitics.cc \ ConcreteParasitics.cc \
EstimateParasitics.cc \ EstimateParasitics.cc \
NullParasitics.cc \ NullParasitics.cc \
Parasitics.cc \ Parasitics.cc \
ReadParasitics.cc \
ReduceParasitics.cc \ ReduceParasitics.cc \
SpefLex.ll \ SpefLex.ll \
SpefNamespace.cc \ SpefNamespace.cc \
SpefParse.yy \ SpefParse.yy \
SpefReader.cc \ SpefReader.cc \
SpefReaderPvt.hh \ SpefReaderPvt.hh \
SpfLex.ll \ SpfReaderPvt.hh
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
SpefLex.ll: SpefParse.hh SpefLex.ll: SpefParse.hh
SpefLex.cc: SpefLex.ll SpefLex.cc: SpefLex.ll
$(LEX) $(LFLAGS) -o SpefLex.cc --prefix=SpefLex_ --header-file=SpefLex.hh 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 SpefParse.hh: SpefParse.cc
if test -f SpefParse.h; then \ if test -f SpefParse.h; then \
cp SpefParse.h SpefParse.hh; \ cp SpefParse.h SpefParse.hh; \
@ -76,7 +56,6 @@ TCL_SRCS = \
EXTRA_DIST = \ EXTRA_DIST = \
$(TCL_SRCS) \ $(TCL_SRCS) \
SpfParse.hh \
SpefParse.hh SpefParse.hh
libs: $(lib_LTLIBRARIES) libs: $(lib_LTLIBRARIES)

View File

@ -51,8 +51,13 @@ Parasitics::findParasiticNet(const Pin *pin) const
Net *net = network_->net(pin); Net *net = network_->net(pin);
// Pins on the top level instance may not have nets. // Pins on the top level instance may not have nets.
// Use the net connected to the pin's terminal. // Use the net connected to the pin's terminal.
if (net == NULL && network_->isTopLevelPort(pin)) if (net == NULL && network_->isTopLevelPort(pin)) {
net = network_->net(network_->term(pin)); Term *term = network_->term(pin);
if (term)
return network_->net(term);
else
return NULL;
}
if (net) if (net)
return network_->highestConnectedNet(net); return network_->highestConnectedNet(net);
else else

View File

@ -34,7 +34,7 @@ using sta::TmpFloatSeq;
%inline %{ %inline %{
bool bool
read_parasitics_cmd(const char *filename, read_spef_cmd(const char *filename,
Instance *instance, Instance *instance,
MinMaxAll *min_max, MinMaxAll *min_max,
bool increment, bool increment,
@ -47,7 +47,7 @@ read_parasitics_cmd(const char *filename,
bool save) bool save)
{ {
cmdLinkedNetwork(); cmdLinkedNetwork();
return Sta::sta()->readParasitics(filename, instance, min_max, return Sta::sta()->readSpef(filename, instance, min_max,
increment, pin_cap_included, increment, pin_cap_included,
keep_coupling_caps, coupling_cap_factor, keep_coupling_caps, coupling_cap_factor,
reduce_to, delete_after_reduce, reduce_to, delete_after_reduce,

View File

@ -16,7 +16,7 @@
namespace eval sta { namespace eval sta {
define_cmd_args "read_parasitics" \ define_cmd_args "read_spef" \
{[-min]\ {[-min]\
[-max]\ [-max]\
[-elmore]\ [-elmore]\
@ -31,14 +31,13 @@ define_cmd_args "read_parasitics" \
[-save]\ [-save]\
filename} filename}
proc_redirect read_parasitics { proc_redirect read_spef {
# The -elmore flag is required by dc. parse_key_args "read_spef" args \
parse_key_args "read_parasitics" args \
keys {-path -coupling_reduction_factor -reduce_to} \ keys {-path -coupling_reduction_factor -reduce_to} \
flags {-min -max -elmore -increment -pin_cap_included \ flags {-min -max -elmore -increment -pin_cap_included \
-keep_capacitive_coupling \ -keep_capacitive_coupling \
-delete_after_reduce -quiet -save} -delete_after_reduce -quiet -save}
check_argc_eq1 "report_parasitics" $args check_argc_eq1 "report_spef" $args
set instance [top_instance] set instance [top_instance]
if [info exists keys(-path)] { if [info exists keys(-path)] {
@ -69,7 +68,7 @@ proc_redirect read_parasitics {
set quiet [info exists flags(-quiet)] set quiet [info exists flags(-quiet)]
set save [info exists flags(-save)] set save [info exists flags(-save)]
set filename $args 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 \ $pin_cap_included $keep_coupling_caps $coupling_reduction_factor \
$reduce_to $delete_after_reduce \ $reduce_to $delete_after_reduce \
$save $quiet] $save $quiet]

View File

@ -91,6 +91,7 @@ INDEX "*"{POS_INTEGER}
"*CELL" { return CELL; } "*CELL" { return CELL; }
"*CONN" { return CONN; } "*CONN" { return CONN; }
"*C_UNIT" { return C_UNIT; } "*C_UNIT" { return C_UNIT; }
"*SPEF" { return SPEF; }
"*DATE" { return DATE; } "*DATE" { return DATE; }
"*DEFINE" { return DEFINE; } "*DEFINE" { return DEFINE; }
"*DELIMITER" { return DELIMITER; } "*DELIMITER" { return DELIMITER; }

View File

@ -42,7 +42,7 @@ int SpefLex_lex();
sta::Net *net; sta::Net *net;
} }
%token DESIGN DATE VENDOR PROGRAM DESIGN_FLOW %token SPEF DESIGN DATE VENDOR PROGRAM DESIGN_FLOW
%token PVERSION DIVIDER DELIMITER %token PVERSION DIVIDER DELIMITER
%token BUS_DELIMITER T_UNIT C_UNIT R_UNIT L_UNIT NAME_MAP %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 %token POWER_NETS GROUND_NETS KW_C KW_L KW_S KW_D KW_V
@ -142,6 +142,7 @@ hchar:
/****************************************************************/ /****************************************************************/
header_def: header_def:
spef_version
design_name design_name
date date
vendor vendor
@ -154,6 +155,11 @@ header_def:
unit_def unit_def
; ;
spef_version:
SPEF QSTRING
{ sta::stringDelete($2); }
;
design_name: design_name:
DESIGN QSTRING DESIGN QSTRING
{ sta::stringDelete($2); } { sta::stringDelete($2); }

View File

@ -17,14 +17,18 @@
#include <limits> #include <limits>
#include "Machine.hh" #include "Machine.hh"
#include "Zlib.hh" #include "Zlib.hh"
#include "Report.hh"
#include "Debug.hh" #include "Debug.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "Map.hh" #include "Map.hh"
#include "PortDirection.hh" #include "PortDirection.hh"
#include "Transition.hh" #include "Transition.hh"
#include "Network.hh" #include "Network.hh"
#include "Liberty.hh"
#include "Sdc.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
#include "SpefReaderPvt.hh" #include "SpefReaderPvt.hh"
#include "SpefNamespace.hh"
#include "SpefReader.hh" #include "SpefReader.hh"
int int
@ -38,8 +42,6 @@ SpefReader *spef_reader;
bool bool
readSpefFile(const char *filename, readSpefFile(const char *filename,
gzFile stream,
int line,
Instance *instance, Instance *instance,
ParasiticAnalysisPt *ap, ParasiticAnalysisPt *ap,
bool increment, bool increment,
@ -57,14 +59,22 @@ readSpefFile(const char *filename,
Network *network, Network *network,
Parasitics *parasitics) Parasitics *parasitics)
{ {
SpefReader reader(filename, stream, line, instance, ap, increment, 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, pin_cap_included, keep_coupling_caps, coupling_cap_factor,
reduce_to, delete_after_reduce, op_cond, corner, reduce_to, delete_after_reduce, op_cond, corner,
cnst_min_max, quiet, report, network, parasitics); cnst_min_max, quiet, report, network, parasitics);
spef_reader = &reader; spef_reader = &reader;
::spefResetScanner(); ::spefResetScanner();
// yyparse returns 0 on success. // yyparse returns 0 on success.
bool success = (::SpefParse_parse() == 0); success = (::SpefParse_parse() == 0);
gzclose(stream);
}
else
throw FileNotReadable(filename);
if (success && save) if (success && save)
parasitics->save(); parasitics->save();
return success; return success;
@ -72,7 +82,6 @@ readSpefFile(const char *filename,
SpefReader::SpefReader(const char *filename, SpefReader::SpefReader(const char *filename,
gzFile stream, gzFile stream,
int line,
Instance *instance, Instance *instance,
ParasiticAnalysisPt *ap, ParasiticAnalysisPt *ap,
bool increment, bool increment,
@ -88,16 +97,35 @@ SpefReader::SpefReader(const char *filename,
Report *report, Report *report,
Network *network, Network *network,
Parasitics *parasitics) : Parasitics *parasitics) :
SpfSpefReader(filename, stream, line, instance, ap, filename_(filename),
increment, pin_cap_included, instance_(instance),
keep_coupling_caps, coupling_cap_factor, ap_(ap),
reduce_to, delete_after_reduce, increment_(increment),
op_cond, corner, cnst_min_max, quiet, pin_cap_included_(pin_cap_included),
report, network, parasitics), 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), triple_index_(0),
design_flow_(NULL), design_flow_(NULL),
parasitic_(NULL) parasitic_(NULL)
{ {
ap->setCouplingCapFactor(coupling_cap_factor);
} }
SpefReader::~SpefReader() SpefReader::~SpefReader()
@ -117,6 +145,18 @@ SpefReader::~SpefReader()
} }
} }
void
SpefReader::setDivider(char divider)
{
divider_ = divider;
}
void
SpefReader::setDelimiter(char delimiter)
{
delimiter_ = delimiter;
}
void void
SpefReader::setBusBrackets(char left, char right) SpefReader::setBusBrackets(char left, char right)
{ {
@ -127,7 +167,78 @@ SpefReader::setBusBrackets(char left, char right)
|| (left == ':' && right == '\0') || (left == ':' && right == '\0')
|| (left == '.' && right == '\0'))) || (left == '.' && right == '\0')))
warn("illegal bus delimiters.\n"); 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 void
@ -510,10 +621,11 @@ SpefReader::makeCouplingCap(int id,
char *node_name2, char *node_name2,
float cap) float cap)
{ {
const char *name = 0; const char *name = NULL;
const char *name_tmp = NULL;
if (keep_device_names_) if (keep_device_names_)
// Prepend device type because OA uses one namespace for all devices. // 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; ParasiticNode *node1, *node2;
Net *ext_net1, *ext_net2; Net *ext_net1, *ext_net2;
@ -537,6 +649,7 @@ SpefReader::makeCouplingCap(int id,
else if (ext_pin1) else if (ext_pin1)
parasitics_->makeCouplingCap(name, node2, ext_pin1, cap, ap_); parasitics_->makeCouplingCap(name, node2, ext_pin1, cap, ap_);
} }
stringDelete(name_tmp);
} }
void void
@ -549,11 +662,13 @@ SpefReader::makeResistor(int id,
ParasiticNode *node2 = findParasiticNode(node_name2); ParasiticNode *node2 = findParasiticNode(node_name2);
if (node1 && node2) { if (node1 && node2) {
float res1 = res->value(triple_index_) * res_scale_; 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_) if (keep_device_names_)
// Prepend device type because OA uses one namespace for all devices. // 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_); parasitics_->makeResistor(name, node1, node2, res1, ap_);
stringDelete(name_tmp);
} }
delete res; delete res;
stringDelete(node_name1); stringDelete(node_name1);

View File

@ -33,8 +33,6 @@ class Instance;
// Return true if successful. // Return true if successful.
bool bool
readSpefFile(const char *filename, readSpefFile(const char *filename,
gzFile stream,
int line,
Instance *instance, Instance *instance,
ParasiticAnalysisPt *ap, ParasiticAnalysisPt *ap,
bool increment, bool increment,

View File

@ -21,7 +21,7 @@
#include "Map.hh" #include "Map.hh"
#include "StringSeq.hh" #include "StringSeq.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
#include "SpfSpefReader.hh" #include "ParasiticsClass.hh"
// Global namespace. // Global namespace.
#define YY_INPUT(buf,result,max_size) \ #define YY_INPUT(buf,result,max_size) \
@ -34,21 +34,20 @@ SpefParse_error(const char *msg);
namespace sta { namespace sta {
class Parasitic; class Report;
class ParasiticNode; class OperatingConditions;
class ParasiticNetwork; class MinMax;
class SpefRspfPi; class SpefRspfPi;
class SpefTriple; class SpefTriple;
class Corner; class Corner;
typedef Map<int,char*,std::less<int> > SpefNameMap; typedef Map<int,char*,std::less<int> > SpefNameMap;
class SpefReader : public SpfSpefReader class SpefReader
{ {
public: public:
SpefReader(const char *filename, SpefReader(const char *filename,
gzFile stream, gzFile stream,
int line,
Instance *instance, Instance *instance,
ParasiticAnalysisPt *ap, ParasiticAnalysisPt *ap,
bool increment, bool increment,
@ -65,6 +64,25 @@ public:
Network *network, Network *network,
Parasitics *parasitics); Parasitics *parasitics);
virtual ~SpefReader(); 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, void setBusBrackets(char left,
char right); char right);
void setTimeScale(float scale, void setTimeScale(float scale,
@ -106,6 +124,10 @@ public:
PortDirection *portDirection(char *spef_dir); PortDirection *portDirection(char *spef_dir);
private: 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, void makeCouplingCap(int id,
char *node_name1, char *node_name1,
char *node_name2, char *node_name2,
@ -117,6 +139,31 @@ private:
int &ext_node_id, int &ext_node_id,
Pin *&ext_pin); 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_; int triple_index_;
float time_scale_; float time_scale_;
float cap_scale_; float cap_scale_;
@ -125,10 +172,6 @@ private:
SpefNameMap name_map_; SpefNameMap name_map_;
StringSeq *design_flow_; StringSeq *design_flow_;
Parasitic *parasitic_; Parasitic *parasitic_;
using SpfSpefReader::findPortPinRelative;
using SpfSpefReader::findNetRelative;
using SpfSpefReader::findInstanceRelative;
}; };
class SpefTriple class SpefTriple

View File

@ -548,8 +548,7 @@ ClockEdge::ClockEdge(Clock *clock,
TransRiseFall *tr) : TransRiseFall *tr) :
clock_(clock), clock_(clock),
tr_(tr), tr_(tr),
name_(stringPrint(strlen(clock_->name())+strlen(tr_->asString()) + 2, name_(stringPrint("%s %s", clock_->name(), tr_->asString())),
"%s %s", clock_->name(), tr_->asString())),
time_(0.0), time_(0.0),
index_(clock_->index() * TransRiseFall::index_count + tr_->index()) 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 // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cmath> // ceil
#include <algorithm> // max
#include "Machine.hh" #include "Machine.hh"
#include "Debug.hh" #include "Debug.hh"
#include "Fuzzy.hh" #include "Fuzzy.hh"
@ -53,59 +55,60 @@ CycleAccting::findDelays(StaState *sta)
const int gclk_hold_index = TimingRole::gatedClockHold()->index(); const int gclk_hold_index = TimingRole::gatedClockHold()->index();
Clock *src_clk = src_->clock(); Clock *src_clk = src_->clock();
Clock *tgt_clk = tgt_->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 tgt_period = tgt_clk->period();
double src_period = src_clk->period(); double src_period = src_clk->period();
if (tgt_period > 0.0 && src_period > 0.0) { if (tgt_period > 0.0 && src_period > 0.0) {
int tgt_max_cycle_count, src_max_cycle_count; // If the clocks are related (ie, generated clock and its source) allow
if (tgt_period > src_period) { // allow enough cycles to match up the common period.
tgt_max_cycle_count = small_period_clk_expansion_cycle_count; int tgt_max_cycle;
src_max_cycle_count = large_period_clk_expansion_cycle_count; if (tgt_period > src_period)
} tgt_max_cycle = 100;
else { else {
tgt_max_cycle_count = large_period_clk_expansion_cycle_count; int ratio = std::ceil(src_period / tgt_period);
src_max_cycle_count = small_period_clk_expansion_cycle_count; tgt_max_cycle = std::max(ratio, 100);
} }
int tgt_cycle;
bool tgt_past_src = false; bool tgt_past_src = false;
bool src_past_tgt = false; bool src_past_tgt = false;
int tgt_cycle, src_cycle;
for (tgt_cycle = (tgt_->time() < tgt_period) ? 0 : -1; for (tgt_cycle = (tgt_->time() < tgt_period) ? 0 : -1;
tgt_cycle < tgt_max_cycle_count; tgt_cycle <= tgt_max_cycle;
tgt_cycle++) { tgt_cycle++) {
double tgt_cycle_start = tgt_cycle * tgt_period; double tgt_cycle_start = tgt_cycle * tgt_period;
double tgt_time = tgt_cycle_start + tgt_->time(); double tgt_time = tgt_cycle_start + tgt_->time();
double tgt_opp_time = tgt_cycle_start + tgt_opp->time(); double tgt_opp_time = tgt_cycle_start + tgt_opp_time1;
int src_cycle;
for (src_cycle = (src_->time() < src_period) ? 0 : -1; for (src_cycle = (src_->time() < src_period) ? 0 : -1;
src_cycle < src_max_cycle_count; ;
src_cycle++) { src_cycle++) {
double src_cycle_start = src_cycle * src_period; double src_cycle_start = src_cycle * src_period;
double src_time = src_cycle_start + src_->time(); 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 if (tgt_past_src && src_past_tgt
// Synchronicity achieved.
&& fuzzyEqual(src_cycle_start, tgt_cycle_start)) { && fuzzyEqual(src_cycle_start, tgt_cycle_start)) {
debugPrint2(debug, "cycle_acct", 1, debugPrint2(debug, "cycle_acct", 1, " setup = %s, required = %s\n",
" setup = %s, required = %s\n",
time_unit->asString(delay_[setup_index]), time_unit->asString(delay_[setup_index]),
time_unit->asString(required_[setup_index])); time_unit->asString(required_[setup_index]));
debugPrint2(debug, "cycle_acct", 1, debugPrint2(debug, "cycle_acct", 1, " hold = %s, required = %s\n",
" hold = %s, required = %s\n",
time_unit->asString(delay_[hold_index]), time_unit->asString(delay_[hold_index]),
time_unit->asString(required_[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; return;
} }
if (fuzzyGreater(src_cycle_start, tgt_cycle_start + tgt_period) if (fuzzyGreater(src_cycle_start, tgt_cycle_start + tgt_period)
&& src_past_tgt) && src_past_tgt)
break; break;
debugPrint5(debug, "cycle_acct", 2, debugPrint5(debug, "cycle_acct", 2, " %s src cycle %d %s + %s = %s\n",
" %s src cycle %d %s + %s = %s\n",
src_->name(), src_->name(),
src_cycle, src_cycle,
time_unit->asString(src_cycle_start), time_unit->asString(src_cycle_start),
time_unit->asString(src_->time()), time_unit->asString(src_->time()),
time_unit->asString(src_time)); time_unit->asString(src_time));
debugPrint5(debug, "cycle_acct", 2, debugPrint5(debug, "cycle_acct", 2, " %s tgt cycle %d %s + %s = %s\n",
" %s tgt cycle %d %s + %s = %s\n",
tgt_->name(), tgt_->name(),
tgt_cycle, tgt_cycle,
time_unit->asString(tgt_cycle_start), time_unit->asString(tgt_cycle_start),
@ -125,6 +128,7 @@ CycleAccting::findDelays(StaState *sta)
time_unit->asString(required_[setup_index])); time_unit->asString(required_[setup_index]));
} }
} }
// Data check setup checks are zero cycle. // Data check setup checks are zero cycle.
if (fuzzyLessEqual(tgt_time, src_time)) { if (fuzzyLessEqual(tgt_time, src_time)) {
double setup_delay = src_time - tgt_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); src_cycle + 1, tgt_cycle, hold_delay, hold_required);
} }
} }
// Latch setup cycle accting for the enable is the data clk edge // Latch setup cycle accting for the enable is the data clk edge
// closest to the disable (opposite) edge. // closest to the disable (opposite) edge.
if (fuzzyGreater(tgt_opp_time, src_time)) { if (fuzzyGreater(tgt_opp_time, src_time)) {
@ -159,6 +164,7 @@ CycleAccting::findDelays(StaState *sta)
time_unit->asString(required_[latch_setup_index])); time_unit->asString(required_[latch_setup_index]));
} }
} }
// For hold checks, target has to be BEFORE source. // For hold checks, target has to be BEFORE source.
if (fuzzyLessEqual(tgt_time, src_time)) { if (fuzzyLessEqual(tgt_time, src_time)) {
double delay = src_time - tgt_time; double delay = src_time - tgt_time;
@ -172,6 +178,7 @@ CycleAccting::findDelays(StaState *sta)
time_unit->asString(required_[hold_index])); time_unit->asString(required_[hold_index]));
} }
} }
// Gated clock hold checks are in the same cycle as the // Gated clock hold checks are in the same cycle as the
// setup check. // setup check.
if (fuzzyLessEqual(tgt_opp_time, src_time)) { 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; 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) else if (tgt_period > 0.0)
findDefaultArrivalSrcDelays(); findDefaultArrivalSrcDelays();

View File

@ -25,15 +25,11 @@
namespace sta { 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 class CycleAccting
{ {
public: public:
CycleAccting(const ClockEdge *src, const ClockEdge *tgt); CycleAccting(const ClockEdge *src,
const ClockEdge *tgt);
// Fill in required times. // Fill in required times.
void findDelays(StaState *sta); void findDelays(StaState *sta);
// Find delays when source clk edge is the default arrival clock edge // Find delays when source clk edge is the default arrival clock edge
@ -88,7 +84,8 @@ private:
class CycleAcctingLess class CycleAcctingLess
{ {
public: public:
bool operator()(const CycleAccting *acct1, const CycleAccting *acct2) const; bool operator()(const CycleAccting *acct1,
const CycleAccting *acct2) const;
}; };
} // namespace } // namespace

View File

@ -583,9 +583,7 @@ const char *
PathDelay::asString(const Network *network) const PathDelay::asString(const Network *network) const
{ {
const char *from_thru_to = fromThruToString(network); const char *from_thru_to = fromThruToString(network);
const char *result = stringPrintTmp(strlen("PathDelay") + 10 const char *result = stringPrintTmp("PathDelay %.3fns%s",
+ strlen(from_thru_to) + 1,
"PathDelay %.3fns%s",
delay_ * 1E+9F, delay_ * 1E+9F,
from_thru_to); from_thru_to);
return result; return result;
@ -776,9 +774,7 @@ const char *
MultiCyclePath::asString(const Network *network) const MultiCyclePath::asString(const Network *network) const
{ {
const char *from_thru_to = fromThruToString(network); const char *from_thru_to = fromThruToString(network);
const char *result = stringPrintTmp(strlen("Multicycle -max ") + 5 const char *result = stringPrintTmp("Multicycle %s %d%s",
+ strlen(from_thru_to) + 1,
"Multicycle %s %d%s",
(use_end_clk_) ? "-end" : "-start", (use_end_clk_) ? "-end" : "-start",
path_multiplier_, path_multiplier_,
from_thru_to); from_thru_to);

View File

@ -2033,15 +2033,20 @@ Sdc::makeClockGroups(const char *name,
bool allow_paths, bool allow_paths,
const char *comment) const char *comment)
{ {
char *gen_name = NULL;
if (name == NULL if (name == NULL
|| name[0] == '\0') || name[0] == '\0')
name = makeClockGroupsName(); name = gen_name = makeClockGroupsName();
else {
ClockGroups *groups = clk_groups_name_map_.findKey(name); ClockGroups *groups = clk_groups_name_map_.findKey(name);
if (groups) if (groups)
removeClockGroups(groups); removeClockGroups(groups);
groups = new ClockGroups(name, logically_exclusive, physically_exclusive, }
ClockGroups *groups = new ClockGroups(name, logically_exclusive,
physically_exclusive,
asynchronous, allow_paths, comment); asynchronous, allow_paths, comment);
clk_groups_name_map_[groups->name()] = groups; clk_groups_name_map_[groups->name()] = groups;
stringDelete(gen_name);
return groups; return groups;
} }
@ -2049,11 +2054,12 @@ Sdc::makeClockGroups(const char *name,
char * char *
Sdc::makeClockGroupsName() Sdc::makeClockGroupsName()
{ {
char *name; char *name = NULL;
int i = 0; int i = 0;
do { do {
i++; i++;
name = stringPrintTmp(10, "group%d", i); stringDelete(name);
name = stringPrint("group%d", i);
} while (clk_groups_name_map_.hasKey(name)); } while (clk_groups_name_map_.hasKey(name));
return name; return name;
} }
@ -2609,10 +2615,9 @@ Sdc::reportClkToClkMaxCycleWarnings()
ClockPairSeq::Iterator pair_iter2(clk_warnings2); ClockPairSeq::Iterator pair_iter2(clk_warnings2);
while (pair_iter2.hasNext()) { while (pair_iter2.hasNext()) {
ClockPair *pair = pair_iter2.next(); 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->first->name(),
pair->second->name(), pair->second->name());
large_period_clk_expansion_cycle_count);
delete pair; delete pair;
} }
} }

View File

@ -1265,9 +1265,9 @@ WriteSdc::writeDisabledEdgeSense(Edge *edge) const
{ {
fprintf(stream_, "set_disable_timing "); fprintf(stream_, "set_disable_timing ");
const char *sense = timingSenseString(edge->sense()); const char *sense = timingSenseString(edge->sense());
const char *filter = stringPrintTmp(strlen(sense) + strlen("sense == ") + 1, string filter;
"sense == %s", sense); stringPrint(filter, "sense == %s", sense);
writeGetTimingArcs(edge, filter); writeGetTimingArcs(edge, filter.c_str());
fprintf(stream_, "\n"); fprintf(stream_, "\n");
} }

View File

@ -283,11 +283,9 @@ ReportAnnotated::reportCheckCount(TimingRole *role,
int index = role->index(); int index = role->index();
if (edge_count_[index] > 0) { if (edge_count_[index] > 0) {
const char *role_name = role->asString(); const char *role_name = role->asString();
const char *title = stringPrintTmp(strlen("cell arcs") string title;
+ strlen(role_name) + 1, stringPrint(title, "cell %s arcs", role_name);
"cell %s arcs", reportCount(title.c_str(), index, total, annotated_total);
role_name);
reportCount(title, index, total, annotated_total);
} }
} }

View File

@ -1043,23 +1043,25 @@ SdfReader::sdfError(const char *fmt, ...)
Pin * Pin *
SdfReader::findPin(const char *name) SdfReader::findPin(const char *name)
{ {
const char *path_name = (path_) if (path_) {
? stringPrintTmp(strlen(name) + strlen(name) + 2, "%s%c%s", string path_name;
path_, divider_, name) stringPrint(path_name, path_, divider_, name);
: name; Pin *pin = network_->findPin(path_name.c_str());
return network_->findPin(path_name); return pin;
}
else
return network_->findPin(name);
} }
Instance * Instance *
SdfReader::findInstance(const char *name) SdfReader::findInstance(const char *name)
{ {
const char *path_name = (path_) string inst_name = name;
? stringPrintTmp(strlen(name) + strlen(name) + 2, "%s%c%s", if (path_)
path_, divider_, name) stringPrint(inst_name, "%s%c%s", path_, divider_, name);
: name; Instance *inst = network_->findInstance(inst_name.c_str());
Instance *inst = network_->findInstance(path_name);
if (inst == NULL) if (inst == NULL)
sdfError("instance %s not found.\n", path_name); sdfError("instance %s not found.\n", inst_name.c_str());
return inst; return inst;
} }

View File

@ -116,7 +116,7 @@ ClkInfo::asString(const StaState *sta) const
string str; string str;
PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index_); PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index_);
str += stringPrintTmp(15, "%s/%d ", str += stringPrintTmp("%s/%d ",
path_ap->pathMinMax()->asString(), path_ap->pathMinMax()->asString(),
path_ap_index_); path_ap_index_);
if (clk_edge_) if (clk_edge_)

View File

@ -87,13 +87,14 @@ CheckCrpr::maxCrpr(ClkInfo *clk_info)
const PathVertexRep &crpr_clk_path = clk_info->crprClkPath(); const PathVertexRep &crpr_clk_path = clk_info->crprClkPath();
if (!crpr_clk_path.isNull()) { if (!crpr_clk_path.isNull()) {
PathVertex crpr_clk_vpath(crpr_clk_path, this); PathVertex crpr_clk_vpath(crpr_clk_path, this);
if (!crpr_clk_vpath.isNull()) {
Arrival other_arrival = otherMinMaxArrival(&crpr_clk_vpath); Arrival other_arrival = otherMinMaxArrival(&crpr_clk_vpath);
float crpr_diff = abs(delayAsFloat(crpr_clk_vpath.arrival(this), float crpr_diff = abs(delayAsFloat(crpr_clk_vpath.arrival(this),
EarlyLate::late()) EarlyLate::late())
- delayAsFloat(other_arrival, EarlyLate::early())); - delayAsFloat(other_arrival, EarlyLate::early()));
return crpr_diff; return crpr_diff;
} }
else }
return 0.0F; return 0.0F;
} }

View File

@ -40,9 +40,7 @@ Path::name(const StaState *sta) const
int ap_index = path_ap->index(); int ap_index = path_ap->index();
const char *min_max = path_ap->pathMinMax()->asString(); const char *min_max = path_ap->pathMinMax()->asString();
TagIndex tag_index = tagIndex(sta); TagIndex tag_index = tagIndex(sta);
size_t result_len = strlen(vertex_name) + strlen(tr_str) return stringPrintTmp("%s %s %s/%d %d",
+ 2 + strlen(min_max) + 16;
return stringPrintTmp(result_len, "%s %s %s/%d %d",
vertex_name, tr_str, min_max, vertex_name, tr_str, min_max,
ap_index, tag_index); ap_index, tag_index);
} }

View File

@ -104,17 +104,19 @@ PathVertex::init(Vertex *vertex,
Tag *tag, Tag *tag,
const StaState *sta) const StaState *sta)
{ {
vertex_ = vertex; vertex_ = NULL;
tag_ = NULL; tag_ = NULL;
arrival_index_ = 0; arrival_index_ = 0;
const Search *search = sta->search(); const Search *search = sta->search();
TagGroup *tag_group = search->tagGroup(vertex_); TagGroup *tag_group = search->tagGroup(vertex);
if (tag_group) { if (tag_group) {
bool arrival_exists; bool arrival_exists;
tag_group->arrivalIndex(tag, arrival_index_, arrival_exists); tag_group->arrivalIndex(tag, arrival_index_, arrival_exists);
if (arrival_exists) if (arrival_exists) {
vertex_ = vertex;
tag_ = tag; tag_ = tag;
} }
}
} }
void void

View File

@ -31,9 +31,12 @@
#include "PathRef.hh" #include "PathRef.hh"
#include "Property.hh" #include "Property.hh"
#include "Sta.hh" #include "Sta.hh"
#include "Property.hh"
namespace sta { namespace sta {
using std::string;
static PropertyValue static PropertyValue
pinSlewProperty(const Pin *pin, pinSlewProperty(const Pin *pin,
const TransRiseFall *tr, const TransRiseFall *tr,
@ -78,6 +81,13 @@ PropertyValue::PropertyValue(const char *value) :
string_ = stringCopy(value); string_ = stringCopy(value);
} }
PropertyValue::PropertyValue(std::string &value) :
type_(type_string)
{
init();
string_ = stringCopy(value.c_str());
}
PropertyValue::PropertyValue(float value) : PropertyValue::PropertyValue(float value) :
type_(type_float) type_(type_float)
{ {
@ -85,6 +95,27 @@ PropertyValue::PropertyValue(float value) :
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) : PropertyValue::PropertyValue(Instance *value) :
type_(type_instance) type_(type_instance)
{ {
@ -162,6 +193,9 @@ PropertyValue::PropertyValue(const PropertyValue &value) :
type_(value.type_), type_(value.type_),
string_(stringCopy(value.string_)), string_(stringCopy(value.string_)),
float_(value.float_), float_(value.float_),
liberty_library_(value.liberty_library_),
liberty_cell_(value.liberty_cell_),
cell_(value.cell_),
inst_(value.inst_), inst_(value.inst_),
pin_(value.pin_), pin_(value.pin_),
pins_(value.pins_ ? new PinSeq(*value.pins_) : NULL), pins_(value.pins_ ? new PinSeq(*value.pins_) : NULL),
@ -177,6 +211,9 @@ PropertyValue::init()
{ {
string_ = NULL; string_ = NULL;
float_ = 0.0; float_ = 0.0;
liberty_library_ = NULL;
liberty_cell_ = NULL;
cell_ = NULL;
inst_ = NULL; inst_ = NULL;
pin_ = NULL; pin_ = NULL;
pins_ = NULL; pins_ = NULL;
@ -200,6 +237,9 @@ PropertyValue::operator=(const PropertyValue &value)
type_ = value.type_; type_ = value.type_;
string_ = stringCopy(value.string_); string_ = stringCopy(value.string_);
float_ = value.float_; float_ = value.float_;
liberty_library_ = value.liberty_library_;
liberty_cell_ = value.liberty_cell_;
cell_ = value.cell_;
inst_ = value.inst_; inst_ = value.inst_;
pin_ = value.pin_; pin_ = value.pin_;
pins_ = value.pins_ ? new PinSeq(*value.pins_) : NULL; 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; 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 PropertyValue
getProperty(const Instance *inst, getProperty(const Instance *inst,
const char *property, const char *property,
Sta *sta) Sta *sta)
{ {
Network *network = sta->network(); auto network = sta->cmdNetwork();
if (stringEqual(property, "ref_name")) if (stringEqual(property, "name"))
return PropertyValue(network->name(network->cell(inst))); return PropertyValue(network->name(inst));
else if (stringEqual(property, "full_name")) else if (stringEqual(property, "full_name"))
return PropertyValue(network->pathName(inst)); 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 else
return PropertyValue(); throw PropertyError("instance", property);
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -230,7 +469,7 @@ getProperty(const Pin *pin,
const char *property, const char *property,
Sta *sta) Sta *sta)
{ {
Network *network = sta->network(); auto network = sta->cmdNetwork();
if (stringEqual(property, "direction")) if (stringEqual(property, "direction"))
return PropertyValue(network->direction(pin)->name()); return PropertyValue(network->direction(pin)->name());
else if (stringEqual(property, "full_name")) else if (stringEqual(property, "full_name"))
@ -262,7 +501,7 @@ getProperty(const Pin *pin,
return pinSlewProperty(pin, TransRiseFall::fall(), MinMax::min(), sta); return pinSlewProperty(pin, TransRiseFall::fall(), MinMax::min(), sta);
else else
return PropertyValue(); throw PropertyError("pin", property);
} }
static PropertyValue static PropertyValue
@ -305,135 +544,11 @@ getProperty(const Net *net,
const char *property, const char *property,
Sta *sta) Sta *sta)
{ {
Network *network = sta->network(); auto network = sta->cmdNetwork();
if (stringEqual(property, "full_name")) if (stringEqual(property, "full_name"))
return PropertyValue(network->pathName(net)); return PropertyValue(network->pathName(net));
else else
return PropertyValue(); throw PropertyError("net", property);
}
////////////////////////////////////////////////////////////////
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();
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -443,6 +558,13 @@ getProperty(Edge *edge,
const char *property, const char *property,
Sta *sta) 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")) if (stringEqual(property, "delay_min_fall"))
return edgeDelayProperty(edge, TransRiseFall::fall(), MinMax::min(), sta); return edgeDelayProperty(edge, TransRiseFall::fall(), MinMax::min(), sta);
else if (stringEqual(property, "delay_max_fall")) else if (stringEqual(property, "delay_max_fall"))
@ -458,7 +580,7 @@ getProperty(Edge *edge,
else if (stringEqual(property, "to_pin")) else if (stringEqual(property, "to_pin"))
return PropertyValue(edge->to(sta->graph())->pin()); return PropertyValue(edge->to(sta->graph())->pin());
else else
return PropertyValue(); throw PropertyError("edge", property);
} }
static PropertyValue 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 PropertyValue
getProperty(Clock *clk, getProperty(Clock *clk,
const char *property, const char *property,
Sta *sta) Sta *sta)
{ {
if (stringEqual(property, "name")) if (stringEqual(property, "name")
|| stringEqual(property, "full_name"))
return PropertyValue(clk->name()); return PropertyValue(clk->name());
else if (stringEqual(property, "period")) else if (stringEqual(property, "period"))
return PropertyValue(sta->units()->timeUnit()->asString(clk->period(), 8)); return PropertyValue(sta->units()->timeUnit()->asString(clk->period(), 8));
@ -508,7 +651,7 @@ getProperty(Clock *clk,
else if (stringEqual(property, "propagated")) else if (stringEqual(property, "propagated"))
return PropertyValue(clk->isPropagated() ? "1" : "0"); return PropertyValue(clk->isPropagated() ? "1" : "0");
else else
return PropertyValue(); throw PropertyError("clock", property);
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -542,7 +685,7 @@ getProperty(PathEnd *end,
return PropertyValue(&paths); return PropertyValue(&paths);
} }
else else
return PropertyValue(); throw PropertyError("path end", property);
} }
PropertyValue PropertyValue
@ -559,7 +702,7 @@ getProperty(PathRef *path,
else if (stringEqual(property, "slack")) else if (stringEqual(property, "slack"))
return PropertyValue(delayPropertyValue(path->slack(sta), sta)); return PropertyValue(delayPropertyValue(path->slack(sta), sta));
else else
return PropertyValue(); throw PropertyError("path", property);
} }
static float static float

View File

@ -17,22 +17,32 @@
#ifndef STA_PROPERTY_H #ifndef STA_PROPERTY_H
#define STA_PROPERTY_H #define STA_PROPERTY_H
#include <string>
#include "LibertyClass.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
#include "SearchClass.hh" #include "SearchClass.hh"
#include "SdcClass.hh"
namespace sta { namespace sta {
using std::string;
class Sta; class Sta;
class PropertyValue class PropertyValue
{ {
public: public:
enum Type { type_none, type_string, type_float, 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_instance, type_pin, type_pins, type_net,
type_clock, type_clocks, type_path_refs }; type_clock, type_clocks, type_path_refs };
PropertyValue(); PropertyValue();
PropertyValue(const char *value); PropertyValue(const char *value);
PropertyValue(string &value);
PropertyValue(float value); PropertyValue(float value);
PropertyValue(LibertyLibrary *value);
PropertyValue(LibertyCell *value);
PropertyValue(Cell *value);
PropertyValue(Instance *value); PropertyValue(Instance *value);
PropertyValue(Pin *value); PropertyValue(Pin *value);
PropertyValue(PinSeq *value); PropertyValue(PinSeq *value);
@ -46,8 +56,11 @@ public:
PropertyValue(const PropertyValue &props); PropertyValue(const PropertyValue &props);
~PropertyValue(); ~PropertyValue();
Type type() const { return type_; } Type type() const { return type_; }
const char *string() const { return string_; } const char *stringValue() const { return string_; }
float floatValue() const { return float_; } 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_; } Instance *instance() const { return inst_; }
Pin *pin() const { return pin_; } Pin *pin() const { return pin_; }
PinSeq *pins() const { return pins_; } PinSeq *pins() const { return pins_; }
@ -63,6 +76,9 @@ private:
Type type_; Type type_;
const char *string_; const char *string_;
float float_; float float_;
LibertyLibrary *liberty_library_;
LibertyCell *liberty_cell_;
Cell *cell_;
Instance *inst_; Instance *inst_;
Pin *pin_; Pin *pin_;
PinSeq *pins_; PinSeq *pins_;
@ -92,6 +108,11 @@ getProperty(const Port *port,
const char *property, const char *property,
Sta *sta); Sta *sta);
PropertyValue
getProperty(const Cell *cell,
const char *property,
Sta *sta);
PropertyValue PropertyValue
getProperty(const LibertyCell *cell, getProperty(const LibertyCell *cell,
const char *property, const char *property,
@ -132,5 +153,10 @@ getProperty(PathRef *end,
const char *property, const char *property,
Sta *sta); Sta *sta);
PropertyValue
getProperty(TimingArcSet *arc_set,
const char *property,
Sta *sta);
} // namespace } // namespace
#endif #endif

View File

@ -137,10 +137,8 @@ ReportPath::~ReportPath()
delete field_edge_; delete field_edge_;
delete field_case_; delete field_case_;
if (plus_zero_) {
stringDelete(plus_zero_); stringDelete(plus_zero_);
stringDelete(minus_zero_); stringDelete(minus_zero_);
}
} }
void void
@ -250,8 +248,8 @@ ReportPath::setDigits(int digits)
stringDelete(plus_zero_); stringDelete(plus_zero_);
stringDelete(minus_zero_); stringDelete(minus_zero_);
} }
minus_zero_ = stringPrint(digits_ + 4, "-%.*f", digits_, 0.0); minus_zero_ = stringPrint("-%.*f", digits_, 0.0);
plus_zero_ = stringPrint(digits_ + 3, "%.*f", digits_, 0.0); plus_zero_ = stringPrint("%.*f", digits_, 0.0);
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -461,14 +459,11 @@ ReportPath::reportFull(const PathEndCheck *end,
reportSlack(end, result); reportSlack(end, result);
} }
char * string
ReportPath::checkRoleString(const PathEnd *end) ReportPath::checkRoleString(const PathEnd *end)
{ {
const char *check_role = end->checkRole(this)->asString(); const char *check_role = end->checkRole(this)->asString();
return stringPrintTmp(strlen("library time") return stdstrPrint("library %s time", check_role);
+ strlen(check_role) + 1,
"library %s time",
check_role);
} }
void void
@ -477,42 +472,30 @@ ReportPath::reportEndpoint(const PathEndCheck *end,
{ {
Instance *inst = network_->instance(end->vertex(this)->pin()); Instance *inst = network_->instance(end->vertex(this)->pin());
const char *inst_name = cmd_network_->pathName(inst); 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 char *rise_fall = asRisingFalling(end->targetClkEndTrans(this));
const TimingRole *check_role = end->checkRole(this); const TimingRole *check_role = end->checkRole(this);
const TimingRole *check_generic_role = check_role->genericRole(); const TimingRole *check_generic_role = check_role->genericRole();
if (check_role == TimingRole::recovery() if (check_role == TimingRole::recovery()
|| check_role == TimingRole::removal()) { || check_role == TimingRole::removal()) {
const char *check_role_name = check_role->asString(); const char *check_role_name = check_role->asString();
char *reason = stringPrintTmp(strlen(" check against -edge clock ") auto reason = stdstrPrint("%s check against %s-edge clock %s",
+ strlen(check_role_name)
+ strlen(rise_fall)
+ strlen(clk_name) + 1,
"%s check against %s-edge clock %s",
check_role_name, check_role_name,
rise_fall, rise_fall,
clk_name); clk_name.c_str());
reportEndpoint(inst_name, reason, result); reportEndpoint(inst_name, reason, result);
} }
else if (check_generic_role == TimingRole::setup() else if (check_generic_role == TimingRole::setup()
|| check_generic_role == TimingRole::hold()) { || check_generic_role == TimingRole::hold()) {
LibertyCell *cell = network_->libertyCell(inst); LibertyCell *cell = network_->libertyCell(inst);
if (cell->isClockGate()) { if (cell->isClockGate()) {
const char *reason = auto reason = stdstrPrint("%s clock gating-check end-point clocked by %s",
stringPrintTmp(strlen( " clock gating-check end-point clocked by ") rise_fall, clk_name.c_str());
+ strlen(rise_fall)
+ strlen(clk_name) + 1,
"%s clock gating-check end-point clocked by %s",
rise_fall, clk_name);
reportEndpoint(inst_name, reason, result); reportEndpoint(inst_name, reason, result);
} }
else { else {
const char *reg_desc = clkRegLatchDesc(end); const char *reg_desc = clkRegLatchDesc(end);
const char *reason = stringPrintTmp(strlen( " clocked by ") auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str());
+ strlen(reg_desc)
+ strlen(clk_name) + 1,
"%s clocked by %s",
reg_desc, clk_name);
reportEndpoint(inst_name, reason, result); reportEndpoint(inst_name, reason, result);
} }
} }
@ -604,13 +587,9 @@ ReportPath::reportEndpoint(const PathEndLatchCheck *end,
{ {
Instance *inst = network_->instance(end->vertex(this)->pin()); Instance *inst = network_->instance(end->vertex(this)->pin());
const char *inst_name = cmd_network_->pathName(inst); 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 *reg_desc = latchDesc(end);
const char *reason = stringPrintTmp(strlen( " clocked by ") auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str());
+ strlen(reg_desc)
+ strlen(clk_name) + 1,
"%s clocked by %s",
reg_desc, clk_name);
reportEndpoint(inst_name, reason, result); reportEndpoint(inst_name, reason, result);
} }
@ -646,25 +625,19 @@ ReportPath::reportBorrowing(const PathEndLatchCheck *end,
if (borrow_limit_exists) if (borrow_limit_exists)
reportLineTotal("user max time borrow", max_borrow, early_late, result); reportLineTotal("user max time borrow", max_borrow, early_late, result);
else { else {
const char *tgt_clk_name = tgtClkName(end); string tgt_clk_name = tgtClkName(end);
Arrival tgt_clk_width = end->targetClkWidth(this); Arrival tgt_clk_width = end->targetClkWidth(this);
const Path *tgt_clk_path = end->targetClkPath(); const Path *tgt_clk_path = end->targetClkPath();
if (tgt_clk_path->clkInfo(search_)->isPropagated()) { if (tgt_clk_path->clkInfo(search_)->isPropagated()) {
const char *width_msg = stringPrintTmp(strlen(" nominal pulse width") auto width_msg = stdstrPrint("%s nominal pulse width", tgt_clk_name.c_str());
+ strlen(tgt_clk_name) + 1, reportLineTotal(width_msg.c_str(), nom_pulse_width, early_late, result);
"%s nominal pulse width",
tgt_clk_name);
reportLineTotal(width_msg, nom_pulse_width, early_late, result);
if (!delayFuzzyZero(latency_diff)) if (!delayFuzzyZero(latency_diff))
reportLineTotalMinus("clock latency difference", latency_diff, reportLineTotalMinus("clock latency difference", latency_diff,
early_late, result); early_late, result);
} }
else { else {
const char *width_msg = stringPrintTmp(strlen(" pulse width") auto width_msg = stdstrPrint("%s pulse width", tgt_clk_name.c_str());
+ strlen(tgt_clk_name) + 1, reportLineTotal(width_msg.c_str(), tgt_clk_width, early_late, result);
"%s pulse width",
tgt_clk_name);
reportLineTotal(width_msg, tgt_clk_width, early_late, result);
} }
ArcDelay margin = end->margin(this); ArcDelay margin = end->margin(this);
reportLineTotalMinus("library setup time", margin, early_late, result); 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()); Instance *inst = network_->instance(end->vertex(this)->pin());
const char *inst_name = cmd_network_->pathName(inst); 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 *reg_desc = clkRegLatchDesc(end);
const char *reason = stringPrintTmp(strlen(" clocked by ") auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str());
+ strlen(reg_desc)
+ strlen(clk_name) + 1,
"%s clocked by %s",
reg_desc,
clk_name);
reportEndpoint(inst_name, reason, result); reportEndpoint(inst_name, reason, result);
} }
@ -760,18 +728,10 @@ ReportPath::reportFull(const PathEndPathDelay *end,
if (min_max == MinMax::max()) if (min_max == MinMax::max())
margin = -margin; 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(); const char *min_max_str = min_max->asString();
char *delay_msg = stringPrintTmp(strlen(" delay") auto delay_msg = stdstrPrint("%s_delay", min_max_str);
+ strlen(min_max_str) + 1,
"%s_delay",
min_max_str);
float delay = path_delay->delay(); 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()) { if (!path_delay->ignoreClkLatency()) {
const Path *tgt_clk_path = end->targetClkPath(); const Path *tgt_clk_path = end->targetClkPath();
if (tgt_clk_path) { 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); reportSlack(end, result);
} }
@ -864,11 +827,8 @@ ReportPath::reportEndpoint(const PathEndOutputDelay *end,
if (network_->isTopLevelPort(pin)) { if (network_->isTopLevelPort(pin)) {
// Pin direction is "output" even for bidirects. // Pin direction is "output" even for bidirects.
if (tgt_clk) { if (tgt_clk) {
const char *clk_name = tgtClkName(end); string clk_name = tgtClkName(end);
const char *reason = stringPrintTmp(strlen("output port clocked by ") auto reason = stdstrPrint("output port clocked by %s", clk_name.c_str());
+ strlen(clk_name) + 1,
"output port clocked by %s",
clk_name);
reportEndpoint(pin_name, reason, result); reportEndpoint(pin_name, reason, result);
} }
else else
@ -876,11 +836,8 @@ ReportPath::reportEndpoint(const PathEndOutputDelay *end,
} }
else { else {
if (tgt_clk) { if (tgt_clk) {
const char *clk_name = tgtClkName(end); string clk_name = tgtClkName(end);
const char *reason = stringPrintTmp(strlen("internal path endpoint clocked by ") auto reason = stdstrPrint("internal path endpoint clocked by %s", clk_name.c_str());
+ strlen(clk_name) + 1,
"internal path endpoint clocked by %s",
clk_name);
reportEndpoint(pin_name, reason, result); reportEndpoint(pin_name, reason, result);
} }
else else
@ -926,18 +883,15 @@ ReportPath::reportEndpoint(const PathEndGatedClock *end,
{ {
Instance *inst = network_->instance(end->vertex(this)->pin()); Instance *inst = network_->instance(end->vertex(this)->pin());
const char *inst_name = cmd_network_->pathName(inst); 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_end_tr = end->targetClkEndTrans(this);
const TransRiseFall *clk_tr = const TransRiseFall *clk_tr =
(end->minMax(this) == MinMax::max()) ? clk_end_tr : clk_end_tr->opposite(); (end->minMax(this) == MinMax::max()) ? clk_end_tr : clk_end_tr->opposite();
const char *rise_fall = asRisingFalling(clk_tr); const char *rise_fall = asRisingFalling(clk_tr);
// Note that target clock transition is ignored. // Note that target clock transition is ignored.
const char *reason = stringPrintTmp(strlen(" clock gating-check end-point clocked by ") auto reason = stdstrPrint("%s clock gating-check end-point clocked by %s",
+ strlen(rise_fall)
+ strlen(clk_name) + 1,
"%s clock gating-check end-point clocked by %s",
rise_fall, rise_fall,
clk_name); clk_name.c_str());
reportEndpoint(inst_name, reason, result); reportEndpoint(inst_name, reason, result);
} }
@ -1002,10 +956,7 @@ ReportPath::reportEndpoint(const PathEndDataCheck *end,
const char *inst_name = cmd_network_->pathName(inst); const char *inst_name = cmd_network_->pathName(inst);
const char *tgt_clk_tr = asRisingFalling(end->dataClkPath()->transition(this)); const char *tgt_clk_tr = asRisingFalling(end->dataClkPath()->transition(this));
const char *tgt_clk_name = end->targetClk(this)->name(); const char *tgt_clk_name = end->targetClk(this)->name();
char *reason = stringPrintTmp(strlen(" edge-triggered data to data check clocked by ") auto reason = stdstrPrint("%s edge-triggered data to data check clocked by %s",
+ strlen(tgt_clk_tr)
+ strlen(tgt_clk_name) + 1,
"%s edge-triggered data to data check clocked by %s",
tgt_clk_tr, tgt_clk_tr,
tgt_clk_name); tgt_clk_name);
@ -1044,7 +995,8 @@ ReportPath::reportEndLine(PathEnd *end,
string &result) string &result)
{ {
const EarlyLate *early_late = end->pathEarlyLate(this); 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->requiredTimeOffset(this), early_late, result);
reportSpaceFieldDelay(end->dataArrivalTimeOffset(this), early_late, result); reportSpaceFieldDelay(end->dataArrivalTimeOffset(this), early_late, result);
Slack slack = end->slack(this); Slack slack = end->slack(this);
@ -1074,8 +1026,10 @@ ReportPath::reportSummaryLine(PathEnd *end,
{ {
PathExpanded expanded(end->path(), this); PathExpanded expanded(end->path(), this);
const EarlyLate *early_late = end->pathEarlyLate(this); const EarlyLate *early_late = end->pathEarlyLate(this);
reportDescription(pathStartpoint(end, expanded), result); auto startpoint = pathStartpoint(end, expanded);
reportDescription(pathEndpoint(end), result); reportDescription(startpoint.c_str(), result);
auto endpoint = pathEndpoint(end);
reportDescription(endpoint.c_str(), result);
if (end->isUnconstrained()) if (end->isUnconstrained())
reportSpaceFieldDelay(end->dataArrivalTimeOffset(this), early_late, result); reportSpaceFieldDelay(end->dataArrivalTimeOffset(this), early_late, result);
else else
@ -1083,7 +1037,7 @@ ReportPath::reportSummaryLine(PathEnd *end,
reportEndOfLine(result); reportEndOfLine(result);
} }
const char * string
ReportPath::pathStartpoint(PathEnd *end, ReportPath::pathStartpoint(PathEnd *end,
PathExpanded &expanded) PathExpanded &expanded)
{ {
@ -1092,40 +1046,28 @@ ReportPath::pathStartpoint(PathEnd *end,
const char *pin_name = cmd_network_->pathName(pin); const char *pin_name = cmd_network_->pathName(pin);
if (network_->isTopLevelPort(pin)) { if (network_->isTopLevelPort(pin)) {
PortDirection *dir = network_->direction(pin); PortDirection *dir = network_->direction(pin);
const char *dir_str = dir->name(); return stdstrPrint("%s (%s)", pin_name, dir->name());
return stringPrintTmp(strlen(pin_name) + strlen(dir_str) + 4,
"%s (%s)",
pin_name, dir_str);
} }
else { else {
Instance *inst = network_->instance(end->vertex(this)->pin()); Instance *inst = network_->instance(end->vertex(this)->pin());
const char *cell_name = cmd_network_->name(network_->cell(inst)); const char *cell_name = cmd_network_->name(network_->cell(inst));
return stringPrintTmp(strlen(pin_name) + strlen(cell_name) + 4, return stdstrPrint("%s (%s)", pin_name, cell_name);
"%s (%s)",
pin_name,
cell_name);
} }
} }
const char * string
ReportPath::pathEndpoint(PathEnd *end) ReportPath::pathEndpoint(PathEnd *end)
{ {
Pin *pin = end->vertex(this)->pin(); Pin *pin = end->vertex(this)->pin();
const char *pin_name = cmd_network_->pathName(pin); const char *pin_name = cmd_network_->pathName(pin);
if (network_->isTopLevelPort(pin)) { if (network_->isTopLevelPort(pin)) {
PortDirection *dir = network_->direction(pin); PortDirection *dir = network_->direction(pin);
const char *dir_str = dir->name(); return stdstrPrint("%s (%s)", pin_name, dir->name());
return stringPrintTmp(strlen(pin_name) + strlen(dir_str) + 4,
"%s (%s)",
pin_name, dir_str);
} }
else { else {
Instance *inst = network_->instance(end->vertex(this)->pin()); Instance *inst = network_->instance(end->vertex(this)->pin());
const char *cell_name = cmd_network_->name(network_->cell(inst)); const char *cell_name = cmd_network_->name(network_->cell(inst));
return stringPrintTmp(strlen(pin_name) + strlen(cell_name) + 4, return stdstrPrint("%s (%s)", pin_name, cell_name);
"%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 *pin_name = cmd_network_->pathName(check->pin(this));
const char *hi_low = mpwCheckHiLow(check); const char *hi_low = mpwCheckHiLow(check);
char *what = stringPrintTmp(strlen(" ()") auto what = stdstrPrint("%s (%s)", pin_name, hi_low);
+ strlen(pin_name) reportDescription(what.c_str(), result);
+ strlen(hi_low) + 1,
"%s (%s)",
pin_name,
hi_low);
reportDescription(what, result);
reportSpaceFieldTime(check->minWidth(this), result); reportSpaceFieldTime(check->minWidth(this), result);
reportSpaceFieldDelay(check->width(this), EarlyLate::late(), result); reportSpaceFieldDelay(check->width(this), EarlyLate::late(), result);
Slack slack = check->slack(this); Slack slack = check->slack(this);
@ -1271,13 +1208,8 @@ ReportPath::reportVerbose(MinPulseWidthCheck *check,
const char *open_clk_name = open_clk->name(); const char *open_clk_name = open_clk->name();
const char *open_rise_fall = asRiseFall(open_clk_edge->transition()); const char *open_rise_fall = asRiseFall(open_clk_edge->transition());
float open_clk_time = open_clk_edge->time(); float open_clk_time = open_clk_edge->time();
const char *open_clk_msg = stringPrintTmp(strlen("clock ( edge)") auto open_clk_msg = stdstrPrint("clock %s (%s edge)", open_clk_name, open_rise_fall);
+ strlen(open_clk_name) reportLine(open_clk_msg.c_str(), open_clk_time, open_clk_time,
+ 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,
open_el, result); open_el, result);
Arrival open_arrival = check->openArrival(this); Arrival open_arrival = check->openArrival(this);
bool is_prop = isPropagated(check->openPath()); bool is_prop = isPropagated(check->openPath());
@ -1295,13 +1227,8 @@ ReportPath::reportVerbose(MinPulseWidthCheck *check,
const char *close_rise_fall = asRiseFall(close_clk_edge->transition()); const char *close_rise_fall = asRiseFall(close_clk_edge->transition());
float close_offset = check->closeOffset(this); float close_offset = check->closeOffset(this);
float close_clk_time = close_clk_edge->time() + close_offset; float close_clk_time = close_clk_edge->time() + close_offset;
const char *close_clk_msg = stringPrintTmp(strlen("clock ( edge)") auto close_clk_msg = stdstrPrint("clock %s (%s edge)", close_clk_name, close_rise_fall);
+ strlen(close_clk_name) reportLine(close_clk_msg.c_str(), close_clk_time, close_clk_time, close_el, result);
+ 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);
Arrival close_arrival = check->closeArrival(this) + close_offset; Arrival close_arrival = check->closeArrival(this) + close_offset;
reportLine(clk_ideal_prop, check->closeDelay(this), close_arrival, reportLine(clk_ideal_prop, check->closeDelay(this), close_arrival,
close_el, result); close_el, result);
@ -1318,13 +1245,9 @@ ReportPath::reportVerbose(MinPulseWidthCheck *check,
reportDashLine(result); reportDashLine(result);
float min_width = check->minWidth(this); float min_width = check->minWidth(this);
const char *hi_low = mpwCheckHiLow(check); const char *hi_low = mpwCheckHiLow(check);
const char *rpw_msg = stringPrintTmp(strlen("required pulse width ()") auto rpw_msg = stdstrPrint("required pulse width (%s)", hi_low);
+ strlen(hi_low) + 1, reportLine(rpw_msg.c_str(), min_width, EarlyLate::early(), result);
"required pulse width (%s)", reportLine("actual pulse width", check->width(this), EarlyLate::early(), result);
hi_low);
reportLine(rpw_msg, min_width, EarlyLate::early(), result);
reportLine("actual pulse width", check->width(this),
EarlyLate::early(), result);
reportDashLine(result); reportDashLine(result);
reportSlack(check->slack(this), result); reportSlack(check->slack(this), result);
} }
@ -1530,13 +1453,11 @@ ReportPath::reportShort(MaxSkewCheck *check,
Pin *clk_pin = check->clkPin(this); Pin *clk_pin = check->clkPin(this);
const char *clk_pin_name = network_->pathName(clk_pin); const char *clk_pin_name = network_->pathName(clk_pin);
TimingArc *check_arc = check->checkArc(); TimingArc *check_arc = check->checkArc();
const char *what = stringPrintTmp(strlen(clk_pin_name) auto what = stdstrPrint("%s (%s->%s)",
+ strlen(" (r->r)") + 1,
"%s (%s->%s)",
clk_pin_name, clk_pin_name,
check_arc->fromTrans()->asString(), check_arc->fromTrans()->asString(),
check_arc->toTrans()->asString()); check_arc->toTrans()->asString());
reportDescription(what, result); reportDescription(what.c_str(), result);
reportSpaceFieldDelay(check->maxSkew(this), EarlyLate::early(), result); reportSpaceFieldDelay(check->maxSkew(this), EarlyLate::early(), result);
reportSpaceFieldDelay(check->skew(this), EarlyLate::early(), result); reportSpaceFieldDelay(check->skew(this), EarlyLate::early(), result);
Slack slack = check->slack(this); Slack slack = check->slack(this);
@ -1586,16 +1507,15 @@ ReportPath::reportSkewClkPath(const char *arrival_msg,
const EarlyLate *early_late = clk_path->minMax(this); const EarlyLate *early_late = clk_path->minMax(this);
const TransRiseFall *clk_tr = clk_edge->transition(); const TransRiseFall *clk_tr = clk_edge->transition();
const TransRiseFall *clk_end_tr = clk_path->transition(this); const TransRiseFall *clk_end_tr = clk_path->transition(this);
const char *clk_name = (clk_end_tr == clk_tr) string clk_name = clkName(clk, clk_end_tr != clk_tr);
? clk->name()
: clkNameInverted(clk->name());
float clk_time = clk_edge->time(); float clk_time = clk_edge->time();
const Arrival &clk_arrival = search_->clkPathArrival(clk_path); const Arrival &clk_arrival = search_->clkPathArrival(clk_path);
Arrival clk_delay = clk_arrival - clk_time; Arrival clk_delay = clk_arrival - clk_time;
PathAnalysisPt *path_ap = clk_path->pathAnalysisPt(this); PathAnalysisPt *path_ap = clk_path->pathAnalysisPt(this);
const MinMax *min_max = path_ap->pathMinMax(); const MinMax *min_max = path_ap->pathMinMax();
Vertex *clk_vertex = clk_path->vertex(this); 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); bool is_prop = isPropagated(clk_path);
if (is_prop && reportClkPath()) { if (is_prop && reportClkPath()) {
const EarlyLate *early_late = TimingRole::skew()->tgtClkEarlyLate(); const EarlyLate *early_late = TimingRole::skew()->tgtClkEarlyLate();
@ -1614,8 +1534,8 @@ ReportPath::reportSkewClkPath(const char *arrival_msg,
else { else {
reportLine(clkNetworkDelayIdealProp(is_prop), clk_delay, clk_arrival, reportLine(clkNetworkDelayIdealProp(is_prop), clk_delay, clk_arrival,
early_late, result); early_late, result);
reportLine(descriptionField(clk_vertex), clk_arrival, early_late, reportLine(descriptionField(clk_vertex).c_str(), clk_arrival,
clk_end_tr, result); early_late, clk_end_tr, result);
} }
reportLine(arrival_msg, search_->clkPathArrival(clk_path), reportLine(arrival_msg, search_->clkPathArrival(clk_path),
early_late, result); early_late, result);
@ -1741,9 +1661,7 @@ ReportPath::reportStartpoint(const PathEnd *end,
const char *pin_name = cmd_network_->pathName(pin); const char *pin_name = cmd_network_->pathName(pin);
if (pathFromClkPin(path, pin)) { if (pathFromClkPin(path, pin)) {
const char *clk_name = clk->name(); const char *clk_name = clk->name();
const char *reason = stringPrintTmp(strlen("clock source ''") auto reason = stdstrPrint("clock source '%s'", clk_name);
+ strlen(clk_name) + 1,
"clock source '%s'", clk_name);
reportStartpoint(pin_name, reason, result); reportStartpoint(pin_name, reason, result);
} }
else if (network_->isTopLevelPort(pin)) { else if (network_->isTopLevelPort(pin)) {
@ -1751,10 +1669,7 @@ ReportPath::reportStartpoint(const PathEnd *end,
&& clk != sdc_->defaultArrivalClock()) { && clk != sdc_->defaultArrivalClock()) {
const char *clk_name = clk->name(); const char *clk_name = clk->name();
// Pin direction is "input" even for bidirects. // Pin direction is "input" even for bidirects.
const char *reason=stringPrintTmp(strlen("input port clocked by ") auto reason = stdstrPrint("input port clocked by %s", clk_name);
+ strlen(clk_name) + 1,
"input port clocked by %s",
clk_name);
reportStartpoint(pin_name, reason, result); reportStartpoint(pin_name, reason, result);
} }
else else
@ -1764,22 +1679,14 @@ ReportPath::reportStartpoint(const PathEnd *end,
Instance *inst = network_->instance(pin); Instance *inst = network_->instance(pin);
const char *inst_name = cmd_network_->pathName(inst); const char *inst_name = cmd_network_->pathName(inst);
if (clk_edge) { if (clk_edge) {
const char *clk_name = clk->name();
const TransRiseFall *clk_tr = clk_edge->transition(); const TransRiseFall *clk_tr = clk_edge->transition();
const TransRiseFall *clk_end_tr = clk_tr;
PathRef clk_path; PathRef clk_path;
expanded.clkPath(clk_path); expanded.clkPath(clk_path);
if (!clk_path.isNull()) { bool clk_inverted = !clk_path.isNull()
clk_end_tr = clk_path.transition(this); && clk_tr != clk_path.transition(this);
if (clk_end_tr != clk_tr) string clk_name = clkName(clk, clk_inverted);
clk_name = clkNameInverted(clk_name);
}
const char *reg_desc = edgeRegLatchDesc(prev_edge, prev_arc); const char *reg_desc = edgeRegLatchDesc(prev_edge, prev_arc);
const char *reason = stringPrintTmp(strlen(" clocked by ") auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str());
+ strlen(reg_desc)
+ strlen(clk_name) + 1,
"%s clocked by %s",
reg_desc, clk_name);
reportStartpoint(inst_name, reason, result); reportStartpoint(inst_name, reason, result);
} }
else { else {
@ -1792,11 +1699,7 @@ ReportPath::reportStartpoint(const PathEnd *end,
Clock *clk = clk_edge->clock(); Clock *clk = clk_edge->clock();
if (clk != sdc_->defaultArrivalClock()) { if (clk != sdc_->defaultArrivalClock()) {
const char *clk_name = clk->name(); const char *clk_name = clk->name();
const char *reason = auto reason = stdstrPrint("internal path startpoint clocked by %s", clk_name);
stringPrintTmp(strlen("internal path startpoint clocked by ")
+ strlen(clk_name) + 1,
"internal path startpoint clocked by %s",
clk_name);
reportStartpoint(pin_name, reason, result); reportStartpoint(pin_name, reason, result);
} }
else else
@ -1830,7 +1733,7 @@ ReportPath::pathFromClkPin(const Path *path,
void void
ReportPath::reportStartpoint(const char *start, ReportPath::reportStartpoint(const char *start,
const char *reason, string reason,
string &result) string &result)
{ {
reportStartEndPoint(start, reason, "Startpoint", result); reportStartEndPoint(start, reason, "Startpoint", result);
@ -1880,19 +1783,21 @@ ReportPath::reportUnclockedEndpoint(const PathEnd *end,
} }
void 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); reportStartEndPoint(end, reason, "Endpoint", result);
} }
void void
ReportPath::reportStartEndPoint(const char *pt, ReportPath::reportStartEndPoint(const char *pt,
const char *reason, string reason,
const char *key, const char *key,
string &result) string &result)
{ {
// Account for punctuation in the line. // 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_ if (!no_split_
&& line_len > start_end_pt_width_) { && line_len > start_end_pt_width_) {
result += key; result += key;
@ -1936,34 +1841,31 @@ ReportPath::reportGroup(const PathEnd *end,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
const char * string
ReportPath::checkRoleReason(const PathEnd *end) ReportPath::checkRoleReason(const PathEnd *end)
{ {
const char *setup_hold = end->checkRole(this)->asString(); const char *setup_hold = end->checkRole(this)->asString();
return stringPrintTmp(strlen(" time") return stdstrPrint("%s time", setup_hold);
+ strlen(setup_hold) + 1,
"%s time",
setup_hold);
} }
const char * string
ReportPath::tgtClkName(const PathEnd *end) ReportPath::tgtClkName(const PathEnd *end)
{ {
ClockEdge *tgt_clk_edge = end->targetClkEdge(this); ClockEdge *tgt_clk_edge = end->targetClkEdge(this);
const Clock *tgt_clk = tgt_clk_edge->clock(); const Clock *tgt_clk = tgt_clk_edge->clock();
const TransRiseFall *clk_tr = tgt_clk_edge->transition(); const TransRiseFall *clk_tr = tgt_clk_edge->transition();
const TransRiseFall *clk_end_tr = end->targetClkEndTrans(this); const TransRiseFall *clk_end_tr = end->targetClkEndTrans(this);
const char *clk_name = tgt_clk->name(); return clkName(tgt_clk, clk_end_tr != clk_tr);
if (clk_end_tr == clk_tr)
return clk_name;
else
return clkNameInverted(clk_name);
} }
const char * string
ReportPath::clkNameInverted(const char *clk_name) 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 * const char *
@ -2055,18 +1957,13 @@ ReportPath::reportSrcClkAndPath(const Path *path,
PathRef clk_path; PathRef clk_path;
expanded.clkPath(clk_path); expanded.clkPath(clk_path);
const TransRiseFall *clk_end_tr; const TransRiseFall *clk_end_tr;
const char *clk_name;
if (!clk_path.isNull()) { if (!clk_path.isNull()) {
clk_end_time = search_->clkPathArrival(&clk_path) + time_offset; clk_end_time = search_->clkPathArrival(&clk_path) + time_offset;
clk_delay = clk_end_time - clk_time; clk_delay = clk_end_time - clk_time;
clk_end_tr = clk_path.transition(this); clk_end_tr = clk_path.transition(this);
clk_name = (clk_end_tr == clk_tr)
? clk->name()
: clkNameInverted(clk->name());
} }
else { else {
// Path from input port or clk used as data. // Path from input port or clk used as data.
clk_name = clk->name();
clk_end_tr = clk_tr; clk_end_tr = clk_tr;
clk_delay = clk_insertion + clk_latency; clk_delay = clk_insertion + clk_latency;
clk_end_time = clk_time + clk_delay; 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 clk_used_as_data = pathFromClkPin(expanded);
bool is_prop = isPropagated(path); bool is_prop = isPropagated(path);
@ -2095,7 +1993,8 @@ ReportPath::reportSrcClkAndPath(const Path *path,
if (reportGenClkSrcPath(clk_path.isNull() ? NULL : &clk_path, if (reportGenClkSrcPath(clk_path.isNull() ? NULL : &clk_path,
clk, clk_tr, min_max, early_late) clk, clk_tr, min_max, early_late)
&& !(path_from_input && !input_has_ref_path)) { && !(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); const PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
reportGenClkSrcAndPath(path, clk, clk_tr, early_late, path_ap, reportGenClkSrcAndPath(path, clk, clk_tr, early_late, path_ap,
time_offset, time_offset, clk_used_as_data, time_offset, time_offset, clk_used_as_data,
@ -2103,7 +2002,8 @@ ReportPath::reportSrcClkAndPath(const Path *path,
} }
else if (clk_used_as_data else if (clk_used_as_data
&& pathFromGenPropClk(path, path->minMax(this))) { && 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(); ClkInfo *clk_info = path->tag(search_)->clkInfo();
if (clk_info->isPropagated()) if (clk_info->isPropagated())
reportClkSrcLatency(clk_insertion, clk_time, early_late, result); reportClkSrcLatency(clk_insertion, clk_time, early_late, result);
@ -2112,12 +2012,14 @@ ReportPath::reportSrcClkAndPath(const Path *path,
else if (is_prop else if (is_prop
&& reportClkPath() && reportClkPath()
&& !(path_from_input && !input_has_ref_path)) { && !(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); reportClkSrcLatency(clk_insertion, clk_time, early_late, result);
reportPath1(path, expanded, false, time_offset, result); reportPath1(path, expanded, false, time_offset, result);
} }
else if (clk_used_as_data) { 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) if (clk_insertion > 0.0)
reportClkSrcLatency(clk_insertion, clk_time, early_late, result); reportClkSrcLatency(clk_insertion, clk_time, early_late, result);
reportPath1(path, expanded, true, time_offset, result); reportPath1(path, expanded, true, time_offset, result);
@ -2129,7 +2031,8 @@ ReportPath::reportSrcClkAndPath(const Path *path,
clk_end_time, early_late, result); clk_end_time, early_late, result);
} }
else { 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; Arrival clk_arrival = clk_end_time;
reportLine(clkNetworkDelayIdealProp(is_prop), clk_delay, reportLine(clkNetworkDelayIdealProp(is_prop), clk_delay,
clk_arrival, early_late, result); clk_arrival, early_late, result);
@ -2170,9 +2073,7 @@ ReportPath::reportTgtClk(const PathEnd *end,
Clock *clk = clk_edge->clock(); Clock *clk = clk_edge->clock();
const TransRiseFall *clk_tr = clk_edge->transition(); const TransRiseFall *clk_tr = clk_edge->transition();
const TransRiseFall *clk_end_tr = end->targetClkEndTrans(this); const TransRiseFall *clk_end_tr = end->targetClkEndTrans(this);
const char *clk_name = (clk_end_tr == clk_tr) string clk_name = clkName(clk, clk_end_tr != clk_tr);
? clk->name()
: clkNameInverted(clk->name());
float clk_time = prev_time float clk_time = prev_time
+ end->targetClkTime(this) + end->targetClkTime(this)
+ end->targetClkMcpAdjustment(this) + end->targetClkMcpAdjustment(this)
@ -2182,7 +2083,8 @@ ReportPath::reportTgtClk(const PathEnd *end,
PathAnalysisPt *path_ap = end->pathAnalysisPt(this)->tgtClkAnalysisPt(); PathAnalysisPt *path_ap = end->pathAnalysisPt(this)->tgtClkAnalysisPt();
const MinMax *min_max = path_ap->pathMinMax(); const MinMax *min_max = path_ap->pathMinMax();
const Path *clk_path = end->targetClkPath(); 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); TimingRole *check_role = end->checkRole(this);
if (is_prop && reportClkPath()) { if (is_prop && reportClkPath()) {
float time_offset = prev_time float time_offset = prev_time
@ -2224,7 +2126,7 @@ ReportPath::reportTgtClk(const PathEnd *end,
reportCommonClkPessimism(end, clk_arrival, result); reportCommonClkPessimism(end, clk_arrival, result);
if (clk_path) { if (clk_path) {
Vertex *clk_vertex = clk_path->vertex(this); Vertex *clk_vertex = clk_path->vertex(this);
reportLine(descriptionField(clk_vertex), reportLine(descriptionField(clk_vertex).c_str(),
prev_time prev_time
+ end->targetClkArrival(this) + end->targetClkArrival(this)
+ end->sourceClkOffset(this), + end->sourceClkOffset(this),
@ -2311,18 +2213,13 @@ ReportPath::reportClkLine(const Clock *clk,
string &result) string &result)
{ {
const char *rise_fall = asRiseFall(clk_tr); const char *rise_fall = asRiseFall(clk_tr);
const char *clk_msg = stringPrintTmp(strlen("clock ( edge)") auto clk_msg = stdstrPrint("clock %s (%s edge)", clk_name, rise_fall);
+ strlen(clk_name)
+ strlen(rise_fall) + 1,
"clock %s (%s edge)",
clk_name,
rise_fall);
if (clk->isPropagated()) 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 { else {
// Report ideal clock slew. // Report ideal clock slew.
float clk_slew = clk->slew(clk_tr, min_max); 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); min_max, result);
} }
} }
@ -2453,7 +2350,7 @@ ReportPath::reportPathLine(const Path *path,
{ {
Vertex *vertex = path->vertex(this); Vertex *vertex = path->vertex(this);
Pin *pin = vertex->pin(); Pin *pin = vertex->pin();
const char *what = descriptionField(vertex); auto what = descriptionField(vertex);
const TransRiseFall *tr = path->transition(this); const TransRiseFall *tr = path->transition(this);
bool is_driver = network_->isDriver(pin); bool is_driver = network_->isDriver(pin);
PathAnalysisPt *path_ap = path->pathAnalysisPt(this); PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
@ -2465,13 +2362,13 @@ ReportPath::reportPathLine(const Path *path,
// Don't show capacitance field for input pins. // Don't show capacitance field for input pins.
if (is_driver && field_capacitance_->enabled()) if (is_driver && field_capacitance_->enabled())
cap = loadCap(pin, tr, dcalc_ap); 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); incr, time, false, early_late, tr, line_case, result);
} }
void void
ReportPath::reportRequired(const PathEnd *end, ReportPath::reportRequired(const PathEnd *end,
const char *margin_msg, string margin_msg,
string &result) string &result)
{ {
Required req_time = end->requiredTimeOffset(this); Required req_time = end->requiredTimeOffset(this);
@ -2479,7 +2376,7 @@ ReportPath::reportRequired(const PathEnd *end,
ArcDelay margin = end->margin(this); ArcDelay margin = end->margin(this);
if (end->minMax(this) == MinMax::max()) if (end->minMax(this) == MinMax::max())
margin = -margin; 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); reportLine("data required time", req_time, early_late, result);
reportDashLine(result); reportDashLine(result);
} }
@ -2784,36 +2681,33 @@ ReportPath::reportPath5(const Path *path,
// Don't show capacitance field for input pins. // Don't show capacitance field for input pins.
if (is_driver && field_capacitance_->enabled()) if (is_driver && field_capacitance_->enabled())
cap = loadCap(pin, tr, dcalc_ap); cap = loadCap(pin, tr, dcalc_ap);
const char *what = descriptionField(vertex); auto what = descriptionField(vertex);
if (report_net_ && is_driver) { if (report_net_ && is_driver) {
// Capacitance field is reported on the net line. // 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); incr, time, false, min_max, tr, line_case, result);
string what2;
if (network_->isTopLevelPort(pin)) { if (network_->isTopLevelPort(pin)) {
const char *pin_name = cmd_network_->pathName(pin); const char *pin_name = cmd_network_->pathName(pin);
what = stringPrintTmp(strlen(" (net)") what2 = stdstrPrint("%s (net)", pin_name);
+ strlen(pin_name) + 1,
"%s (net)", pin_name);
} }
else { else {
Net *net = network_->net(pin); Net *net = network_->net(pin);
if (net) { if (net) {
Net *highest_net = network_->highestNetAbove(net); Net *highest_net = network_->highestNetAbove(net);
const char *net_name = cmd_network_->pathName(highest_net); const char *net_name = cmd_network_->pathName(highest_net);
what = stringPrintTmp(strlen(" (net)") what2 = stdstrPrint("%s (net)", net_name);
+ strlen(net_name) + 1,
"%s (net)", net_name);
} }
else else
what = "(unconnected)"; what2 = "(unconnected)";
} }
float fanout = drvrFanout(vertex, min_max); 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, field_blank_, field_blank_, false, min_max, NULL,
line_case, result); line_case, result);
} }
else else
reportLine(what, cap, slew, field_blank_, reportLine(what.c_str(), cap, slew, field_blank_,
incr, time, false, min_max, tr, line_case, result); incr, time, false, min_max, tr, line_case, result);
prev_time = time; prev_time = time;
} }
@ -2834,7 +2728,7 @@ ReportPath::nextArcAnnotated(const PathRef *next_path,
return graph_->arcDelayAnnotated(edge, arc, ap_index); return graph_->arcDelayAnnotated(edge, arc, ap_index);
} }
char * string
ReportPath::descriptionField(Vertex *vertex) ReportPath::descriptionField(Vertex *vertex)
{ {
Pin *pin = vertex->pin(); Pin *pin = vertex->pin();
@ -2858,21 +2752,7 @@ ReportPath::descriptionField(Vertex *vertex)
Instance *inst = network_->instance(pin); Instance *inst = network_->instance(pin);
name2 = network_->cellName(inst); name2 = network_->cellName(inst);
} }
// stringPrintTmp("%s (%s)", pin_name, name2) return stdstrPrint("%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;
} }
float float
@ -3125,12 +3005,10 @@ ReportPath::reportLine(const char *what,
else if (field == field_fanout_) { else if (field == field_fanout_) {
if (fanout == field_blank_) if (fanout == field_blank_)
reportFieldBlank(field, result); reportFieldBlank(field, result);
else { else
char *field = stringPrintTmp(field_fanout_->width() + 1, "%*d", result += stdstrPrint("%*d",
field_fanout_->width(), field_fanout_->width(),
static_cast<int>(fanout)); static_cast<int>(fanout));
result += field;
}
} }
else if (field == field_capacitance_) else if (field == field_capacitance_)
reportField(cap, field, result); reportField(cap, field, result);

View File

@ -232,8 +232,8 @@ protected:
string &result); string &result);
void reportEndpoint(const PathEndGatedClock *end, void reportEndpoint(const PathEndGatedClock *end,
string &result); string &result);
const char *pathEndpoint(PathEnd *end); string pathEndpoint(PathEnd *end);
const char *pathStartpoint(PathEnd *end, string pathStartpoint(PathEnd *end,
PathExpanded &expanded); PathExpanded &expanded);
void reportBorrowing(const PathEndLatchCheck *end, void reportBorrowing(const PathEndLatchCheck *end,
Arrival &borrow, Arrival &borrow,
@ -243,8 +243,8 @@ protected:
string &result); string &result);
const char *clkNetworkDelayIdealProp(bool is_ideal); const char *clkNetworkDelayIdealProp(bool is_ideal);
const char *checkRoleReason(const PathEnd *end); string checkRoleReason(const PathEnd *end);
char *checkRoleString(const PathEnd *end); string checkRoleString(const PathEnd *end);
virtual void reportGroup(const PathEnd *end, virtual void reportGroup(const PathEnd *end,
string &result); string &result);
void reportStartpoint(const PathEnd *end, void reportStartpoint(const PathEnd *end,
@ -259,16 +259,16 @@ protected:
string &result); string &result);
const char *latchDesc(const PathEndLatchCheck *end); const char *latchDesc(const PathEndLatchCheck *end);
void reportStartpoint(const char *start, void reportStartpoint(const char *start,
const char *reason, string reason,
string &result); string &result);
void reportEndpoint(const char *end, void reportEndpoint(const char *end,
const char *reason, string reason,
string &result); string &result);
void reportStartEndPoint(const char *pt, void reportStartEndPoint(const char *pt,
const char *reason, string reason,
const char *key, const char *key,
string &result); string &result);
const char *tgtClkName(const PathEnd *end); string tgtClkName(const PathEnd *end);
const char *clkRegLatchDesc(const PathEnd *end); const char *clkRegLatchDesc(const PathEnd *end);
void reportSrcPath(const PathEnd *end, void reportSrcPath(const PathEnd *end,
PathExpanded &expanded, PathExpanded &expanded,
@ -344,7 +344,7 @@ protected:
const MinMax *min_max, const MinMax *min_max,
string &result); string &result);
void reportRequired(const PathEnd *end, void reportRequired(const PathEnd *end,
const char *margin_msg, string margin_msg,
string &result); string &result);
void reportSlack(const PathEnd *end, void reportSlack(const PathEnd *end,
string &result); string &result);
@ -486,9 +486,10 @@ protected:
void reportDashLine(int line_width, void reportDashLine(int line_width,
string &result); string &result);
void reportEndOfLine(string &result); void reportEndOfLine(string &result);
char *descriptionField(Vertex *vertex); string descriptionField(Vertex *vertex);
bool reportClkPath() const; bool reportClkPath() const;
const char *clkNameInverted(const char *clk_name); string clkName(const Clock *clk,
bool inverted);;
bool hasExtInputDriver(const Pin *pin, bool hasExtInputDriver(const Pin *pin,
const TransRiseFall *tr, const TransRiseFall *tr,
const MinMax *min_max); const MinMax *min_max);

View File

@ -56,7 +56,7 @@
#include "Latches.hh" #include "Latches.hh"
#include "PathGroup.hh" #include "PathGroup.hh"
#include "CheckTiming.hh" #include "CheckTiming.hh"
#include "ReadParasitics.hh" #include "SpefReader.hh"
#include "CheckSlewLimits.hh" #include "CheckSlewLimits.hh"
#include "CheckMinPulseWidths.hh" #include "CheckMinPulseWidths.hh"
#include "CheckMinPeriods.hh" #include "CheckMinPeriods.hh"
@ -231,6 +231,7 @@ initSta()
Transition::init(); Transition::init();
TimingRole::init(); TimingRole::init();
PortDirection::init(); PortDirection::init();
initTmpStrings();
initLiberty(); initLiberty();
initDelayConstants(); initDelayConstants();
registerDelayCalcs(); registerDelayCalcs();
@ -3407,7 +3408,7 @@ Sta::setResistance(Net *net,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
bool bool
Sta::readParasitics(const char *filename, Sta::readSpef(const char *filename,
Instance *instance, Instance *instance,
const MinMaxAll *min_max, const MinMaxAll *min_max,
bool increment, bool increment,
@ -3434,7 +3435,7 @@ Sta::readParasitics(const char *filename,
} }
const OperatingConditions *op_cond = const OperatingConditions *op_cond =
sdc_->operatingConditions(cnst_min_max); sdc_->operatingConditions(cnst_min_max);
bool success = readParasiticsFile(filename, instance, ap, increment, bool success = readSpefFile(filename, instance, ap, increment,
pin_cap_included, pin_cap_included,
keep_coupling_caps, coupling_cap_factor, keep_coupling_caps, coupling_cap_factor,
reduce_to, delete_after_reduce, reduce_to, delete_after_reduce,

View File

@ -1037,7 +1037,7 @@ public:
// networks (dspf) are reduced and deleted after reading each net // networks (dspf) are reduced and deleted after reading each net
// with reduce_to and delete_after_reduce. // with reduce_to and delete_after_reduce.
// Return true if successful. // Return true if successful.
bool readParasitics(const char *filename, bool readSpef(const char *filename,
Instance *instance, Instance *instance,
const MinMaxAll *min_max, const MinMaxAll *min_max,
bool increment, bool increment,

View File

@ -98,11 +98,11 @@ Tag::asString(bool report_index,
string str; string str;
if (report_index) if (report_index)
str += stringPrintTmp(6, "%4d ", index_); str += stringPrintTmp("%4d ", index_);
const TransRiseFall *tr = transition(); const TransRiseFall *tr = transition();
PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index_); PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index_);
str += stringPrintTmp(25, "%s %s/%d ", str += stringPrintTmp("%s %s/%d ",
tr->asString(), tr->asString(),
path_ap->pathMinMax()->asString(), path_ap->pathMinMax()->asString(),
path_ap_index_); path_ap_index_);

View File

@ -359,8 +359,7 @@ VisitPathEnds::visitOutputDelayEnd1(OutputDelay *output_delay,
is_constrained = true; is_constrained = true;
} }
else if (tgt_clk_edge else if (tgt_clk_edge
&& sdc_->sameClockGroup(path->clock(this), && sdc_->sameClockGroup(path->clock(this), tgt_clk_edge->clock())
tgt_clk_edge->clock())
// False paths and path delays override. // False paths and path delays override.
&& (exception == NULL && (exception == NULL
|| exception->isFilter() || exception->isFilter()

View File

@ -55,14 +55,11 @@ split(const string &text,
const string &delims, const string &delims,
// Return values. // Return values.
StringVector &tokens); StringVector &tokens);
void void
streamPrint(ofstream &stream, streamPrint(ofstream &stream,
const char *fmt, const char *fmt,
...) __attribute__((format (printf, 2, 3))); ...) __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() WritePathSpice::~WritePathSpice()
{ {
stringDelete(net_name_);
cell_spice_port_names_.deleteContents(); cell_spice_port_names_.deleteContents();
} }
@ -257,17 +255,17 @@ WritePathSpice::writeSpice()
void void
WritePathSpice::writeHeader() WritePathSpice::writeHeader()
{ {
const MinMax *min_max = path_->minMax(this); auto min_max = path_->minMax(this);
const Pvt *pvt = sdc_->operatingConditions(min_max); auto pvt = sdc_->operatingConditions(min_max);
if (pvt == NULL) if (pvt == NULL)
pvt = network_->defaultLibertyLibrary()->defaultOperatingConditions(); pvt = network_->defaultLibertyLibrary()->defaultOperatingConditions();
float temp = pvt->temperature(); auto temp = pvt->temperature();
streamPrint(spice_stream_, ".temp %.1f\n", temp); streamPrint(spice_stream_, ".temp %.1f\n", temp);
streamPrint(spice_stream_, ".include \"%s\"\n", model_filename_); streamPrint(spice_stream_, ".include \"%s\"\n", model_filename_);
streamPrint(spice_stream_, ".include \"%s\"\n", subckt_filename_); streamPrint(spice_stream_, ".include \"%s\"\n", subckt_filename_);
float max_time = maxTime(); auto max_time = maxTime();
float time_step = max_time / 1e+3; auto time_step = max_time / 1e+3;
streamPrint(spice_stream_, ".tran %.3g %.3g\n\n", streamPrint(spice_stream_, ".tran %.3g %.3g\n\n",
time_step, max_time); time_step, max_time);
} }
@ -275,8 +273,8 @@ WritePathSpice::writeHeader()
float float
WritePathSpice::maxTime() WritePathSpice::maxTime()
{ {
Stage input_stage = stageFirst(); auto input_stage = stageFirst();
Path *input_path = stageDrvrPath(input_stage); auto input_path = stageDrvrPath(input_stage);
auto input_slew = input_path->slew(this); auto input_slew = input_path->slew(this);
auto end_slew = path_->slew(this); auto end_slew = path_->slew(this);
auto max_time = delayAsFloat(input_slew auto max_time = delayAsFloat(input_slew
@ -293,7 +291,7 @@ WritePathSpice::writeStageInstances()
streamPrint(spice_stream_, "*****************\n\n"); streamPrint(spice_stream_, "*****************\n\n");
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { 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()) if (stage == stageFirst())
streamPrint(spice_stream_, "x%s %s %s %s\n", streamPrint(spice_stream_, "x%s %s %s %s\n",
stage_name, stage_name,
@ -325,7 +323,7 @@ WritePathSpice::pgPortVoltage(LibertyPgPort *pg_port)
auto cell = pg_port->cell(); auto cell = pg_port->cell();
auto voltage_name = pg_port->voltageName(); auto voltage_name = pg_port->voltageName();
auto lib = cell->libertyLibrary(); auto lib = cell->libertyLibrary();
float voltage = lib->supplyVoltage(voltage_name); auto voltage = lib->supplyVoltage(voltage_name);
return voltage; return voltage;
} }
@ -336,7 +334,7 @@ WritePathSpice::writeInputSource()
streamPrint(spice_stream_, "* Input source\n"); streamPrint(spice_stream_, "* Input source\n");
streamPrint(spice_stream_, "**************\n\n"); streamPrint(spice_stream_, "**************\n\n");
Stage input_stage = stageFirst(); auto input_stage = stageFirst();
streamPrint(spice_stream_, "v1 %s 0 pwl(\n", streamPrint(spice_stream_, "v1 %s 0 pwl(\n",
stageDrvrPinName(input_stage)); stageDrvrPinName(input_stage));
auto wire_arc = stageWireArc(input_stage); auto wire_arc = stageWireArc(input_stage);
@ -349,13 +347,13 @@ WritePathSpice::writeInputSource()
volt0 = power_voltage_; volt0 = power_voltage_;
volt1 = gnd_voltage_; volt1 = gnd_voltage_;
} }
Path *input_path = stageDrvrPath(input_stage); auto input_path = stageDrvrPath(input_stage);
auto input_slew = delayAsFloat(input_path->slew(this)); auto input_slew = delayAsFloat(input_path->slew(this));
if (input_slew == 0.0) if (input_slew == 0.0)
input_slew = maxTime() / 1e+3; input_slew = maxTime() / 1e+3;
// Arbitrary offset. // Arbitrary offset.
float time0 = input_slew; auto time0 = input_slew;
float time1 = time0 + input_slew; auto time1 = time0 + input_slew;
streamPrint(spice_stream_, "+%.3e %.3e\n", 0.0, volt0); streamPrint(spice_stream_, "+%.3e %.3e\n", 0.0, volt0);
streamPrint(spice_stream_, "+%.3e %.3e\n", time0, volt0); streamPrint(spice_stream_, "+%.3e %.3e\n", time0, volt0);
streamPrint(spice_stream_, "+%.3e %.3e\n", time1, volt1); streamPrint(spice_stream_, "+%.3e %.3e\n", time1, volt1);
@ -370,7 +368,7 @@ WritePathSpice::writeMeasureStmts()
streamPrint(spice_stream_, "* Measure statements\n"); streamPrint(spice_stream_, "* Measure statements\n");
streamPrint(spice_stream_, "********************\n\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()) auto input_path = (stage == stageFirst())
? stageDrvrPath(stage) ? stageDrvrPath(stage)
: stageGateInputPath(stage); : stageGateInputPath(stage);
@ -455,7 +453,7 @@ WritePathSpice::writeStageSubckts()
streamPrint(spice_stream_, "* Stage subckts\n"); streamPrint(spice_stream_, "* Stage subckts\n");
streamPrint(spice_stream_, "***************\n\n"); streamPrint(spice_stream_, "***************\n\n");
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { for (auto stage = stageFirst(); stage <= stageLast(); stage++) {
if (stage == stageFirst()) if (stage == stageFirst())
writeInputStage(stage); writeInputStage(stage);
else else
@ -493,17 +491,17 @@ WritePathSpice::writeGateStage(Stage stage)
input_pin_name, input_pin_name,
drvr_pin_name, drvr_pin_name,
load_pin_name); load_pin_name);
Instance *inst = network_->instance(input_pin); auto inst = network_->instance(input_pin);
const char *inst_name = network_->pathName(inst); auto inst_name = network_->pathName(inst);
LibertyCell *cell = network_->libertyCell(inst); auto cell = network_->libertyCell(inst);
const char *cell_name = cell->name(); auto cell_name = cell->name();
auto spice_port_names = cell_spice_port_names_[cell_name]; auto spice_port_names = cell_spice_port_names_[cell_name];
// Instance subckt call. // Instance subckt call.
streamPrint(spice_stream_, "x%s", inst_name); streamPrint(spice_stream_, "x%s", inst_name);
StringVector::Iterator port_iter(spice_port_names); StringVector::Iterator port_iter(spice_port_names);
while (port_iter.hasNext()) { 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 pin = network_->findPin(inst, subckt_port_name);
auto pg_port = cell->findPgPort(subckt_port_name); auto pg_port = cell->findPgPort(subckt_port_name);
const char *pin_name; const char *pin_name;
@ -542,8 +540,8 @@ sensitizationValues(FuncExpr *expr,
break; break;
} }
case FuncExpr::op_or: { case FuncExpr::op_or: {
FuncExpr *left = expr->left(); auto left = expr->left();
FuncExpr *right = expr->right(); auto right = expr->right();
if (left->port() == from_port if (left->port() == from_port
&& right->op() == FuncExpr::op_port) && right->op() == FuncExpr::op_port)
port_values[right->port()] = logic_zero; port_values[right->port()] = logic_zero;
@ -553,8 +551,8 @@ sensitizationValues(FuncExpr *expr,
break; break;
} }
case FuncExpr::op_and: { case FuncExpr::op_and: {
FuncExpr *left = expr->left(); auto left = expr->left();
FuncExpr *right = expr->right(); auto right = expr->right();
if (left->port() == from_port if (left->port() == from_port
&& right->op() == FuncExpr::op_port) && right->op() == FuncExpr::op_port)
port_values[right->port()] = logic_one; port_values[right->port()] = logic_one;
@ -565,8 +563,8 @@ sensitizationValues(FuncExpr *expr,
} }
case FuncExpr::op_xor: { case FuncExpr::op_xor: {
// Need to know timing arc sense to get this right. // Need to know timing arc sense to get this right.
FuncExpr *left = expr->left(); auto left = expr->left();
FuncExpr *right = expr->right(); auto right = expr->right();
if (left->port() == from_port if (left->port() == from_port
&& right->op() == FuncExpr::op_port) && right->op() == FuncExpr::op_port)
port_values[right->port()] = logic_zero; port_values[right->port()] = logic_zero;
@ -591,7 +589,7 @@ WritePathSpice::writeStageVoltageSources(LibertyCell *cell,
{ {
auto from_port_name = from_port->name(); auto from_port_name = from_port->name();
auto drvr_port_name = drvr_port->name(); auto drvr_port_name = drvr_port->name();
LibertyLibrary *lib = cell->libertyLibrary(); auto lib = cell->libertyLibrary();
LibertyPortLogicValues port_values; LibertyPortLogicValues port_values;
sensitizationValues(drvr_port->function(), from_port, port_values); sensitizationValues(drvr_port->function(), from_port, port_values);
int volt_source = 1; int volt_source = 1;
@ -613,7 +611,7 @@ WritePathSpice::writeStageVoltageSources(LibertyCell *cell,
} else if (!(stringEq(subckt_port_name, from_port_name) } else if (!(stringEq(subckt_port_name, from_port_name)
|| stringEq(subckt_port_name, drvr_port_name))) { || stringEq(subckt_port_name, drvr_port_name))) {
// Input voltage to sensitize path from gate input to output. // 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) { if (port) {
const char *pg_port_name = NULL; const char *pg_port_name = NULL;
bool port_has_value; bool port_has_value;
@ -795,8 +793,7 @@ WritePathSpice::nodeName(ParasiticNode *node)
node_index = next_node_index_++; node_index = next_node_index_++;
node_map_[node] = node_index; node_map_[node] = node_index;
} }
return stringPrintTmp(strlen(net_name_) + 10, "%s/%d", return stringPrintTmp("%s/%d", net_name_, node_index);
net_name_, node_index);
} }
} }
@ -821,7 +818,7 @@ WritePathSpice::writeSubckts()
split(line, " \t", tokens); split(line, " \t", tokens);
if (tokens.size() >= 2 if (tokens.size() >= 2
&& stringEqual(tokens[0].c_str(), ".subckt")) { && 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)) { if (path_cell_names.hasKey(cell_name)) {
subckts_stream << line << "\n"; subckts_stream << line << "\n";
bool found_ends = false; bool found_ends = false;
@ -848,7 +845,7 @@ WritePathSpice::writeSubckts()
report_->error("The following subkcts are missing from %s\n", report_->error("The following subkcts are missing from %s\n",
lib_subckt_filename_); lib_subckt_filename_);
while (cell_iter.hasNext()) { while (cell_iter.hasNext()) {
const char *cell_name = cell_iter.next(); auto cell_name = cell_iter.next();
report_->printError(" %s\n", cell_name); report_->printError(" %s\n", cell_name);
} }
} }
@ -866,10 +863,10 @@ void
WritePathSpice::findPathCellnames(// Return values. WritePathSpice::findPathCellnames(// Return values.
StringSet &path_cell_names) StringSet &path_cell_names)
{ {
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { for (auto stage = stageFirst(); stage <= stageLast(); stage++) {
auto arc = stageGateArc(stage); auto arc = stageGateArc(stage);
if (arc) { if (arc) {
LibertyCell *cell = arc->set()->libertyCell(); auto cell = arc->set()->libertyCell();
if (cell) { if (cell) {
debugPrint1(debug_, "write_spice", 2, "cell %s\n", cell->name()); debugPrint1(debug_, "write_spice", 2, "cell %s\n", cell->name());
path_cell_names.insert(cell->name()); path_cell_names.insert(cell->name());
@ -885,8 +882,8 @@ WritePathSpice::recordSpicePortNames(const char *cell_name,
auto cell = network_->findLibertyCell(cell_name); auto cell = network_->findLibertyCell(cell_name);
if (cell) { if (cell) {
auto spice_port_names = new StringVector; auto spice_port_names = new StringVector;
for (int i = 2; i < tokens.size(); i++) { for (auto i = 2; i < tokens.size(); i++) {
const char *port_name = tokens[i].c_str(); auto port_name = tokens[i].c_str();
auto port = cell->findLibertyPort(port_name); auto port = cell->findLibertyPort(port_name);
auto pg_port = cell->findPgPort(port_name); auto pg_port = cell->findPgPort(port_name);
if (port == NULL && pg_port == NULL) if (port == NULL && pg_port == NULL)
@ -941,28 +938,28 @@ WritePathSpice::stageLoadPathIndex(Stage stage)
PathRef * PathRef *
WritePathSpice::stageGateInputPath(Stage stage) WritePathSpice::stageGateInputPath(Stage stage)
{ {
int path_index = stageGateInputPathIndex(stage); auto path_index = stageGateInputPathIndex(stage);
return path_expanded_.path(path_index); return path_expanded_.path(path_index);
} }
PathRef * PathRef *
WritePathSpice::stageDrvrPath(Stage stage) WritePathSpice::stageDrvrPath(Stage stage)
{ {
int path_index = stageDrvrPathIndex(stage); auto path_index = stageDrvrPathIndex(stage);
return path_expanded_.path(path_index); return path_expanded_.path(path_index);
} }
PathRef * PathRef *
WritePathSpice::stageLoadPath(Stage stage) WritePathSpice::stageLoadPath(Stage stage)
{ {
int path_index = stageLoadPathIndex(stage); auto path_index = stageLoadPathIndex(stage);
return path_expanded_.path(path_index); return path_expanded_.path(path_index);
} }
TimingArc * TimingArc *
WritePathSpice::stageGateArc(Stage stage) WritePathSpice::stageGateArc(Stage stage)
{ {
int path_index = stageDrvrPathIndex(stage); auto path_index = stageDrvrPathIndex(stage);
if (path_index >= 0) if (path_index >= 0)
return path_expanded_.prevArc(path_index); return path_expanded_.prevArc(path_index);
else else
@ -972,70 +969,87 @@ WritePathSpice::stageGateArc(Stage stage)
TimingArc * TimingArc *
WritePathSpice::stageWireArc(Stage stage) WritePathSpice::stageWireArc(Stage stage)
{ {
int path_index = stageLoadPathIndex(stage); auto path_index = stageLoadPathIndex(stage);
return path_expanded_.prevArc(path_index); return path_expanded_.prevArc(path_index);
} }
Edge * Edge *
WritePathSpice::stageGateEdge(Stage stage) WritePathSpice::stageGateEdge(Stage stage)
{ {
PathRef *path = stageGateInputPath(stage); auto path = stageGateInputPath(stage);
TimingArc *arc = stageGateArc(stage); auto arc = stageGateArc(stage);
return path->prevEdge(arc, this); return path->prevEdge(arc, this);
} }
Edge * Edge *
WritePathSpice::stageWireEdge(Stage stage) WritePathSpice::stageWireEdge(Stage stage)
{ {
PathRef *path = stageLoadPath(stage); auto path = stageLoadPath(stage);
TimingArc *arc = stageWireArc(stage); auto arc = stageWireArc(stage);
return path->prevEdge(arc, this); return path->prevEdge(arc, this);
} }
Pin * Pin *
WritePathSpice::stageInputPin(Stage stage) WritePathSpice::stageInputPin(Stage stage)
{ {
PathRef *path = stageGateInputPath(stage); auto path = stageGateInputPath(stage);
return path->pin(this); return path->pin(this);
} }
Pin * Pin *
WritePathSpice::stageDrvrPin(Stage stage) WritePathSpice::stageDrvrPin(Stage stage)
{ {
PathRef *path = stageDrvrPath(stage); auto path = stageDrvrPath(stage);
return path->pin(this); return path->pin(this);
} }
Pin * Pin *
WritePathSpice::stageLoadPin(Stage stage) WritePathSpice::stageLoadPin(Stage stage)
{ {
PathRef *path = stageLoadPath(stage); auto path = stageLoadPath(stage);
return path->pin(this); return path->pin(this);
} }
const char * const char *
WritePathSpice::stageGateInputPinName(Stage stage) WritePathSpice::stageGateInputPinName(Stage stage)
{ {
const Pin *pin = stageInputPin(stage); auto pin = stageInputPin(stage);
return network_->pathName(pin); return network_->pathName(pin);
} }
const char * const char *
WritePathSpice::stageDrvrPinName(Stage stage) WritePathSpice::stageDrvrPinName(Stage stage)
{ {
Pin *pin = stageDrvrPin(stage); auto pin = stageDrvrPin(stage);
return network_->pathName(pin); return network_->pathName(pin);
} }
const char * const char *
WritePathSpice::stageLoadPinName(Stage stage) WritePathSpice::stageLoadPinName(Stage stage)
{ {
const Pin *pin = stageLoadPin(stage); auto pin = stageLoadPin(stage);
return network_->pathName(pin); 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 void
split(const string &text, split(const string &text,
const string &delims, const string &delims,
@ -1053,35 +1067,4 @@ split(const string &text,
tokens.push_back(text.substr(start)); 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 } // namespace

View File

@ -22,6 +22,15 @@
namespace eval sta { 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 } { proc check_setup_cmd { cmd cmd_args } {
parse_key_args $cmd cmd_args keys {} flags {-verbose} 0 parse_key_args $cmd cmd_args keys {} flags {-verbose} 0
# When nothing is everything. # When nothing is everything.
@ -290,12 +299,12 @@ proc set_assigned_delay_cmd { cmd cmd_args } {
set inst [[lindex $from_pins 0] instance] set inst [[lindex $from_pins 0] instance]
foreach pin $from_pins { foreach pin $from_pins {
if {[$pin instance] != $inst} { 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 { foreach pin $to_pins {
if {[$pin instance] != $inst} { 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 {} set ports {}
get_object_args $objects clks {} {} {} insts ports pins {} {} {} get_object_args $objects clks {} {} {} insts ports pins {} {} {}
foreach port $ports { 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 {} set ports {}
get_object_args $objects clks {} {} {} {} ports pins {} {} {} get_object_args $objects clks {} {} {} {} ports pins {} {} {}
foreach port $ports { 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 {} set ports {}
get_object_args $objects {} {} {} {} insts ports pins {} {} {} get_object_args $objects {} {} {} {} insts ports pins {} {} {}
foreach port $ports { 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 {} set nets {}
get_object_args $objects {} {} {} {} insts ports pins nets {} {} get_object_args $objects {} {} {} {} insts ports pins nets {} {}
foreach port $ports { 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 pins {}
set nets {} set nets {}
get_object_args $objects {} {} {} {} {} ports pins nets {} {} get_object_args $objects {} {} {} {} {} ports pins nets {} {}
foreach port $ports { 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 set pin $arg
} elseif { $object_type == "Port" } { } elseif { $object_type == "Port" } {
# Explicit port arg - convert to pin. # Explicit port arg - convert to pin.
set pin [find_pin [$arg name]] set pin [find_pin [get_name $arg]]
} else { } else {
sta_warn_error $warn_error "$arg_name type '$object_type' is not a pin or port." 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" } { if { $port == "NULL" } {
set pin [find_pin $arg] set pin [find_pin $arg]
} else { } else {
set pin [$top_instance find_pin [$port name]] set pin [$top_instance find_pin [get_name $port]]
} }
if { $pin == "NULL" } { if { $pin == "NULL" } {
sta_warn_error $warn_error "pin $arg not found." sta_warn_error $warn_error "pin $arg not found."
@ -1531,7 +1541,7 @@ proc get_port_pins_error { arg_name arglist } {
lappend pins $arg lappend pins $arg
} elseif { $object_type == "Port" } { } elseif { $object_type == "Port" } {
# Convert port to pin. # Convert port to pin.
lappend pins [find_pin [$arg name]] lappend pins [find_pin [get_name $arg]]
} else { } else {
sta_error "$arg_name type '$object_type' is not a pin or port." 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 { } else {
sta_error "$cmd $type_key must be specified with object name argument." 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] 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" } { if { $object_type == "Instance" } {
return [instance_property $object $prop] return [instance_property $object $prop]
} elseif { $object_type == "Pin" } { } elseif { $object_type == "Pin" } {
@ -1787,6 +1801,8 @@ proc get_property_cmd { cmd type_key cmd_args } {
return [liberty_port_property $object $prop] return [liberty_port_property $object $prop]
} elseif { $object_type == "LibertyCell" } { } elseif { $object_type == "LibertyCell" } {
return [liberty_cell_property $object $prop] return [liberty_cell_property $object $prop]
} elseif { $object_type == "Cell" } {
return [cell_property $object $prop]
} elseif { $object_type == "Library" } { } elseif { $object_type == "Library" } {
return [library_property $object $prop] return [library_property $object $prop]
} elseif { $object_type == "LibertyLibrary" } { } elseif { $object_type == "LibertyLibrary" } {
@ -1797,12 +1813,14 @@ proc get_property_cmd { cmd type_key cmd_args } {
return [path_end_property $object $prop] return [path_end_property $object $prop]
} elseif { $object_type == "PathRef" } { } elseif { $object_type == "PathRef" } {
return [path_ref_property $object $prop] return [path_ref_property $object $prop]
} elseif { $object_type == "TimingArcSet" } {
return [timing_arc_set_property $object $prop]
} else { } 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" set object "NULL"
if { $object_type == "cell" } { if { $object_type == "cell" } {
set object [get_cells -quiet $object_name] set object [get_cells -quiet $object_name]
@ -1856,8 +1874,46 @@ proc get_object_type { obj } {
} }
} }
proc object_name_cmp { obj1 obj2 } { proc sort_by_full_name { objects } {
return [string compare [$obj1 object_name] [$obj2 object_name]] 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 } { proc report_pin_constant { pin } {
set sim_value [pin_sim_logic_value $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] set case_value [pin_case_logic_value $pin]
if { $case_value != "X" } { if { $case_value != "X" } {
puts -nonewline " case=$case_value" puts -nonewline " case=$case_value"
@ -234,15 +234,15 @@ proc report_pin_constant { pin } {
proc report_disabled_edges {} { proc report_disabled_edges {} {
foreach edge [disabled_edges_sorted] { foreach edge [disabled_edges_sorted] {
if { [$edge role] == "wire" } { if { [$edge role] == "wire" } {
set from_pin_name [[[$edge from] pin] path_name] set from_pin_name [get_full_name [[$edge from] pin]]
set to_pin_name [[[$edge to] pin] path_name] set to_pin_name [get_full_name [[$edge to] pin]]
puts -nonewline "$from_pin_name $to_pin_name" puts -nonewline "$from_pin_name $to_pin_name"
} else { } else {
set from_pin [[$edge from] pin] set from_pin [[$edge from] pin]
set to_pin [[$edge to] pin] set to_pin [[$edge to] pin]
set inst_name [[$from_pin instance] path_name] set inst_name [get_full_name [$from_pin instance]]
set from_port_name [[$from_pin port] name] set from_port_name [get_name [$from_pin port]]
set to_port_name [[$to_pin port] name] set to_port_name [get_name [$to_pin port]]
puts -nonewline "$inst_name $from_port_name $to_port_name" puts -nonewline "$inst_name $from_port_name $to_port_name"
set cond [$edge cond] set cond [$edge cond]
if { $cond != "" } { if { $cond != "" } {
@ -267,8 +267,8 @@ proc edge_disable_reason_verbose { edge } {
append disables " $sense" append disables " $sense"
} }
set const_pins [$edge disabled_constant_pins] set const_pins [$edge disabled_constant_pins]
foreach pin [lsort -command path_name_cmp $const_pins] { foreach pin [sort_by_full_name $const_pins] {
set port_name [$pin port_name] set port_name [pin_property $pin lib_pin_name]
set value [pin_sim_logic_value $pin] set value [pin_sim_logic_value $pin]
append disables " $port_name=$value" append disables " $port_name=$value"
} }
@ -302,18 +302,20 @@ proc report_slews { pin } {
} }
proc vertex_path_name { vertex } { 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 } { 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. # Append driver/load for bidirect pin vertices.
proc vertex_name_ { vertex name_proc } { proc vertex_name_ { vertex pin pin_name } {
set pin [$vertex pin] if { [pin_direction $pin] == "bidirect" } {
set pin_name [$pin $name_proc]
if { [$pin direction] == "bidirect" } {
if [$vertex is_bidirect_driver] { if [$vertex is_bidirect_driver] {
return "$pin_name driver" return "$pin_name driver"
} else { } else {

View File

@ -60,11 +60,12 @@ proc report_instance1 { instance connections verbose } {
if { $instance == [top_instance] } { if { $instance == [top_instance] } {
set inst_name "top" set inst_name "top"
} else { } else {
set inst_name [$instance path_name] set inst_name [get_full_name $instance]
} }
puts "Instance $inst_name" puts "Instance $inst_name"
puts " Cell: [[$instance cell] name]" set cell [instance_property $instance "cell"]
puts " Library: [[[$instance cell] library] name]" puts " Cell: [get_name $cell]"
puts " Library: [get_name [$cell library]]"
puts " Path cells: [instance_cell_path $instance]" puts " Path cells: [instance_cell_path $instance]"
if { $connections } { if { $connections } {
report_instance_pins $instance $verbose report_instance_pins $instance $verbose
@ -92,7 +93,7 @@ proc report_instance_pins1 {instance verbose header header_optional dirs} {
set iter [$instance pin_iterator] set iter [$instance pin_iterator]
while {[$iter has_next]} { while {[$iter has_next]} {
set pin [$iter next] set pin [$iter next]
set dir [$pin direction] set dir [pin_direction $pin]
if { [lsearch $dirs $dir] != -1 } { if { [lsearch $dirs $dir] != -1 } {
if { !$header_shown } { if { !$header_shown } {
puts $header puts $header
@ -105,20 +106,20 @@ proc report_instance_pins1 {instance verbose header header_optional dirs} {
} }
proc report_instance_pin { pin verbose } { 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] set net [$pin net]
if { $net == "NULL" } { if { $net == "NULL" } {
puts " (unconnected)" puts " (unconnected)"
} else { } else {
puts " [[$net highest_connected_net] path_name]" puts " [get_full_name [$net highest_connected_net]]"
if { $verbose } { if { $verbose } {
set pins [net_connected_pins_sorted $net] set pins [net_connected_pins_sorted $net]
foreach pin $pins { foreach pin $pins {
if [$pin is_load] { if [$pin is_load] {
if [$pin is_top_level_port] { if [$pin is_top_level_port] {
puts " [$pin path_name] [$pin direction] port" puts " [get_full_name $pin] [pin_direction $pin] port"
} else { } 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. # Concatenate the cell names of the instance parents.
proc instance_cell_path { instance } { 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 parent [$instance parent]
set top_instance [top_instance] set top_instance [top_instance]
while { $parent != "NULL" && $parent != $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] set parent [$parent parent]
} }
return $cell_path return $cell_path
@ -143,7 +144,7 @@ proc report_instance_children_ { instance } {
if { $children != {} } { if { $children != {} } {
puts " Children:" puts " Children:"
foreach child $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] lappend children [$iter next]
} }
$iter finish $iter finish
return [lsort -command path_name_cmp $children] return [sort_by_full_name $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]]
} }
################################################################ ################################################################
@ -183,9 +176,9 @@ proc report_lib_cell_ { cell } {
global sta_report_default_digits global sta_report_default_digits
set lib [$cell liberty_library] set lib [$cell liberty_library]
puts "Cell [$cell name]" puts "Cell [get_name $cell]"
puts "Library [$lib name]" puts "Library [get_name $lib]"
set filename [$cell filename] set filename [liberty_cell_property $cell "filename"]
if { $filename != "" } { if { $filename != "" } {
puts "File $filename" puts "File $filename"
} }
@ -193,9 +186,9 @@ proc report_lib_cell_ { cell } {
while {[$iter has_next]} { while {[$iter has_next]} {
set port [$iter next] set port [$iter next]
if { [$port is_bus] } { if { [$port is_bus] } {
puts -nonewline " [$port bus_name] [$port direction]" puts -nonewline " [$port bus_name] [liberty_port_direction $port]"
} else { } else {
puts -nonewline " [$port name] [$port direction]" puts -nonewline " [get_name $port] [liberty_port_direction $port]"
} }
set enable [$port tristate_enable] set enable [$port tristate_enable]
if { $enable != "" } { if { $enable != "" } {
@ -212,9 +205,9 @@ proc report_lib_cell_ { cell } {
proc report_cell_ { cell } { proc report_cell_ { cell } {
set lib [$cell library] set lib [$cell library]
puts "Cell [$cell name]" puts "Cell [get_name $cell]"
puts "Library [$lib name]" puts "Library [get_name $lib]"
set filename [$cell filename] set filename [liberty_cell_property $cell "filename"]
if { $filename != "" } { if { $filename != "" } {
puts "File $filename" puts "File $filename"
} }
@ -222,9 +215,9 @@ proc report_cell_ { cell } {
while {[$iter has_next]} { while {[$iter has_next]} {
set port [$iter next] set port [$iter next]
if { [$port is_bus] } { if { [$port is_bus] } {
puts " [$port bus_name] [$port direction]" puts " [$port bus_name] [port_direction $port]"
} else { } else {
puts " [$port name] [$port direction]" puts " [get_name $port] [port_direction $port]"
} }
} }
$iter finish $iter finish
@ -292,7 +285,7 @@ proc report_net_ { net } {
} }
proc report_net1 { net connections verbose hier_pins corner digits } { proc report_net1 { net connections verbose hier_pins corner digits } {
puts "Net [$net path_name]" puts "Net [get_full_name $net]"
if {$connections} { if {$connections} {
set pins [net_connected_pins_sorted $net] set pins [net_connected_pins_sorted $net]
if {$verbose} { if {$verbose} {
@ -320,7 +313,7 @@ proc net_connected_pins_sorted { net } {
lappend pins $pin lappend pins $pin
} }
$iter finish $iter finish
set pins [lsort -command path_name_cmp $pins] set pins [sort_by_full_name $pins]
return $pins return $pins
} }
@ -380,8 +373,8 @@ proc report_net_other_pins { pins verbose corner digits } {
proc report_net_pin { pin verbose corner digits } { proc report_net_pin { pin verbose corner digits } {
if [$pin is_leaf] { if [$pin is_leaf] {
set cell_name [[[$pin instance] cell] name] set cell_name [get_name [[$pin instance] cell]]
puts -nonewline " [$pin path_name] [$pin direction] ($cell_name)" puts -nonewline " [get_full_name $pin] [pin_direction $pin] ($cell_name)"
if { $verbose } { if { $verbose } {
set liberty_port [$pin liberty_port] set liberty_port [$pin liberty_port]
if { $liberty_port != "NULL" } { if { $liberty_port != "NULL" } {
@ -390,7 +383,7 @@ proc report_net_pin { pin verbose corner digits } {
} }
puts "" puts ""
} elseif [$pin is_top_level_port] { } 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 } { if { $verbose } {
set port [$pin port] set port [$pin port]
set cap_r_min [port_ext_wire_cap $port "rise" "min"] set cap_r_min [port_ext_wire_cap $port "rise" "min"]
@ -412,7 +405,7 @@ proc report_net_pin { pin verbose corner digits } {
} }
puts "" puts ""
} elseif [$pin is_hierarchical] { } 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 } { proc report_pin_ { pin } {
global sta_report_default_digits 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] set liberty_port [$pin liberty_port]
if { $liberty_port != "NULL" } { if { $liberty_port != "NULL" } {
@ -429,24 +422,29 @@ proc report_pin_ { pin } {
} }
if { [$pin is_top_level_port] } { 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 { } else {
set net [$pin net] set net [$pin net]
} }
if { $net == "NULL" } { if { $net == "NULL" } {
puts " (unconnected)" puts " (unconnected)"
} else { } else {
puts " [[$net highest_connected_net] path_name]" puts " [get_full_name [$net highest_connected_net]]"
} }
} }
proc pin_direction_desc { pin } { proc pin_direction_desc { pin } {
if [$pin is_hierarchical] { if [$pin is_hierarchical] {
return "hierarchical [$pin direction]" return "hierarchical [pin_direction $pin]"
} elseif [$pin is_top_level_port] { } elseif [$pin is_top_level_port] {
return "[$pin direction] port" return "[pin_direction $pin] port"
} else { } else {
return [$pin direction] return [pin_direction $pin]
} }
} }

View File

@ -48,7 +48,7 @@ proc parse_connect_pins { arg } {
set port [$pin port] set port [$pin port]
} elseif { $object_type == "Port" } { } elseif { $object_type == "Port" } {
# Explicit port arg - convert to pin. # Explicit port arg - convert to pin.
set pin [find_pin [$obj name]] set pin [find_pin [get_name $obj]]
set inst [$pin instance] set inst [$pin instance]
set port [$pin port] set port [$pin port]
} else { } else {

View File

@ -106,9 +106,11 @@ proc report_power_col_percent { col_total total } {
} }
proc report_power_inst { inst corner digits } { proc report_power_inst { inst corner digits } {
puts "Instance: [$inst path_name]" puts "Instance: [get_full_name $inst]"
puts "Cell: [[$inst liberty_cell] name]" set cell [instance_property $inst "liberty_cell"]
puts "Liberty file: [[[$inst liberty_cell] liberty_library] filename]" 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] set power_result [instance_power $inst $corner]
lassign $power_result internal switching leakage total lassign $power_result internal switching leakage total
report_power_line "Internal power" $internal $digits report_power_line "Internal power" $internal $digits

View File

@ -159,7 +159,7 @@ proc current_instance { {inst ""} } {
} else { } else {
set current_instance [get_instance_error "instance" $inst] 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." puts "Current instance is $cell."
# Current instance state variable must be part of the sta state so # Current instance state variable must be part of the sta state so
# the tcl interpreter can be shared by multiple sdc files. # 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] set iter [$top_cell port_iterator]
while {[$iter has_next]} { while {[$iter has_next]} {
set port [$iter next] set port [$iter next]
set port_dir [$port direction] set port_dir [port_direction $port]
if { $port_dir == $direction || $port_dir == "bidirect" } { if { $port_dir == $direction || $port_dir == "bidirect" } {
set ports [concat $ports [port_members $port]] set ports [concat $ports [port_members $port]]
} }
@ -384,11 +384,11 @@ proc current_design { {design ""} } {
if { $design == "" } { if { $design == "" } {
# top_instance errors if the network has not been linked. # 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] } { } elseif { ![network_is_linked] } {
set current_design_name $design set current_design_name $design
return $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 set current_design_name $design
return $design return $design
} else { } else {
@ -706,7 +706,7 @@ proc find_liberty_libraries_matching { pattern regexp nocase } {
set matches {} set matches {}
while { [$lib_iter has_next] } { while { [$lib_iter has_next] } {
set lib [$lib_iter next] set lib [$lib_iter next]
set lib_name [$lib name] set lib_name [get_name $lib]
if { (!$regexp && [string match $pattern2 $lib_name]) \ if { (!$regexp && [string match $pattern2 $lib_name]) \
|| ($regexp && $nocase && [regexp -nocase $pattern2 $lib_name]) \ || ($regexp && $nocase && [regexp -nocase $pattern2 $lib_name]) \
|| ($regexp && !$nocase && [regexp $pattern2 $lib_name]) } { || ($regexp && !$nocase && [regexp $pattern2 $lib_name]) } {
@ -980,7 +980,7 @@ proc create_clock { args } {
sta_error "-add requires -name." sta_error "-add requires -name."
} }
# Default clock name is the first pin 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 { } else {
sta_error "-name or port_pin_list must be specified." sta_error "-name or port_pin_list must be specified."
} }
@ -1057,7 +1057,7 @@ proc create_generated_clock { args } {
sta_error "-add requires -name." sta_error "-add requires -name."
} }
# Default clock name is the first pin 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 { } else {
sta_error "name or port_pin_list must be specified." sta_error "name or port_pin_list must be specified."
} }
@ -1410,7 +1410,7 @@ proc set_clock_latency { args } {
foreach pin $pins { foreach pin $pins {
# Source only allowed on clocks and clock pins. # Source only allowed on clocks and clock pins.
if { ![is_clock_src $pin] } { 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 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 { foreach pin $pins {
if {[$pin is_hierarchical]} { 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 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 == "" } { if { $port_name == "" } {
set ports "NULL" set ports "NULL"
} else { } else {
set cell [$inst liberty_cell] set cell [instance_property $inst liberty_cell]
set port [$cell find_liberty_port $port_name] set port [$cell find_liberty_port $port_name]
if { $port == "NULL" } { 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 { } else {
set ports [port_members $port] set ports [port_members $port]
foreach port $ports { foreach port $ports {
set member_name [$port name] set member_name [get_full_name $port]
if { [$inst find_pin $member_name] == "NULL" } { 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 { } else {
set port [$cell find_liberty_port $port_name] set port [$cell find_liberty_port $port_name]
if { $port == "NULL" } { 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 { } else {
set ports [port_members $port] set ports [port_members $port]
} }
@ -1920,8 +1920,8 @@ proc set_port_delay { cmd sta_cmd cmd_args port_dirs } {
foreach pin $pins { foreach pin $pins {
if { [$pin is_top_level_port] \ if { [$pin is_top_level_port] \
&& [lsearch $port_dirs [$pin direction]] == -1 } { && [lsearch $port_dirs [pin_direction $pin]] == -1 } {
sta_warn "$cmd not allowed on [$pin direction] port '[$pin name]'." sta_warn "$cmd not allowed on [pin_direction $pin] port '[get_full_name $pin]'."
} elseif { $clk != "NULL" && [lsearch [$clk sources] $pin] != -1 } { } elseif { $clk != "NULL" && [lsearch [$clk sources] $pin] != -1 } {
sta_warn "$cmd relative to a clock defined on the same port/pin not allowed." sta_warn "$cmd relative to a clock defined on the same port/pin not allowed."
} else { } else {
@ -2147,7 +2147,7 @@ proc set_propagated_clock { objects } {
parse_clk_port_pin_arg $objects clks pins parse_clk_port_pin_arg $objects clks pins
foreach clk $clks { foreach clk $clks {
if { [$clk is_virtual] } { 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 { } else {
set_propagated_clock_cmd $clk set_propagated_clock_cmd $clk
} }
@ -2257,7 +2257,7 @@ proc set_driving_cell { args } {
set output_count 0 set output_count 0
while {[$port_iter has_next]} { while {[$port_iter has_next]} {
set port [$port_iter next] set port [$port_iter next]
set dir [$port direction] set dir [liberty_port_direction $port]
if { [port_direction_any_output $dir] } { if { [port_direction_any_output $dir] } {
incr output_count incr output_count
if { $output_count > 1 } { if { $output_count > 1 } {
@ -2482,9 +2482,9 @@ proc set_fanout_limit { fanout min_max objects } {
check_positive_float "limit" $fanout check_positive_float "limit" $fanout
parse_cell_port_args $objects cells ports parse_cell_port_args $objects cells ports
foreach port $ports { foreach port $ports {
set dir [$port direction] set dir [port_direction $port]
if { !($dir == "input" || $dir == "bidirect") } { 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 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 rise_fmt [format_delays $rise]
set fall_fmt [format_delays $fall] set fall_fmt [format_delays $fall]
if {$clk != "NULL"} { 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 { } else {
set clk_str "" 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 rise_fmt [format_times $rise $sta_report_default_digits]
set fall_fmt [format_times $fall $sta_report_default_digits] set fall_fmt [format_times $fall $sta_report_default_digits]
if {$clk != "NULL"} { 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 { } else {
set clk_str "" set clk_str ""
} }

View File

@ -25,11 +25,13 @@ proc define_sta_cmd_args { cmd arglist } {
# Import Sta commands to global namespace. # Import Sta commands to global namespace.
proc define_sta_cmds {} { proc define_sta_cmds {} {
variable sta_cmd_args variable sta_cmd_args
variable native
foreach cmd [array names sta_cmd_args] { foreach cmd [array names sta_cmd_args] {
define_cmd_args $cmd $sta_cmd_args($cmd) define_cmd_args $cmd $sta_cmd_args($cmd)
} }
define_report_path_fields define_report_path_fields
set native 1
} }
proc define_report_path_fields {} { proc define_report_path_fields {} {
@ -421,7 +423,7 @@ proc_redirect report_check_types {
set slack_min [expr -$sta::float_inf] set slack_min [expr -$sta::float_inf]
set slack_max $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 \ $corner $path_min_max $group_count 1 0 \
$slack_min $slack_max \ $slack_min $slack_max \
0 {} \ 0 {} \
@ -674,28 +676,16 @@ proc unset_timing_derate { args } {
define_sta_cmd_args "connect_pins" {net pins} define_sta_cmd_args "connect_pins" {net pins}
################################################################
define_sta_cmd_args "delete_instance" {cell_list} define_sta_cmd_args "delete_instance" {cell_list}
################################################################
define_sta_cmd_args "delete_net" {net_list} define_sta_cmd_args "delete_net" {net_list}
################################################################
define_sta_cmd_args "disconnect_pins" {net -all|pins} define_sta_cmd_args "disconnect_pins" {net -all|pins}
################################################################
define_sta_cmd_args "make_instance" {inst_names lib_cell} define_sta_cmd_args "make_instance" {inst_names lib_cell}
################################################################
define_sta_cmd_args "make_net" {} define_sta_cmd_args "make_net" {}
################################################################
define_sta_cmd_args "replace_cell" {instances lib_cell} 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 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 ################################################################a
define_sta_cmd_args "set_assigned_check" \ define_sta_cmd_args "set_assigned_check" \
@ -891,16 +897,8 @@ proc get_fanout { args } {
################################################################ ################################################################
define_sta_cmd_args "get_name_of_object" {object} define_sta_cmd_args "get_name" {objects}
define_sta_cmd_args "get_full_name" {objects}
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."
}
}
################################################################ ################################################################
@ -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} define_sta_cmd_args "report_object_names" {[-verbose] objects}
proc report_object_names { args } { proc report_object_names { args } {
@ -977,17 +999,17 @@ proc report_object_names { args } {
if { [info exists flags(-verbose)] } { if { [info exists flags(-verbose)] } {
puts -nonewline "{" puts -nonewline "{"
set first 1 set first 1
foreach obj [lsort -command object_name_cmp $objects] { foreach obj [sort_name $objects] {
if { !$first } { if { !$first } {
puts -nonewline ", " 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 set first 0
} }
puts "}" puts "}"
} else { } else {
foreach obj [lsort -command object_name_cmp $objects] { foreach obj [sort_by_full_name $objects] {
puts [get_name_of_object $obj] puts [get_name $obj]
} }
} }
} }

View File

@ -458,7 +458,7 @@ tclError(Tcl_Interp *interp,
const char *msg, const char *msg,
const char *arg) const char *arg)
{ {
char *error = stringPrint(strlen(msg) + strlen(arg) + 1, msg, arg); char *error = stringPrint(msg, arg);
Tcl_SetResult(interp, error, TCL_VOLATILE); Tcl_SetResult(interp, error, TCL_VOLATILE);
stringDelete(error); stringDelete(error);
} }
@ -1529,10 +1529,10 @@ using namespace sta;
Tcl_SetResult(interp, const_cast<char*>(""), TCL_STATIC); Tcl_SetResult(interp, const_cast<char*>(""), TCL_STATIC);
break; break;
case PropertyValue::Type::type_string: 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; break;
case PropertyValue::Type::type_float: { 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); Tcl_SetResult(interp, float_string, TCL_VOLATILE);
stringDelete(float_string); stringDelete(float_string);
} }
@ -1566,6 +1566,24 @@ using namespace sta;
Tcl_SetObjResult(interp, obj); Tcl_SetObjResult(interp, obj);
} }
break; 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: { case PropertyValue::Type::type_clock: {
Tcl_Obj *obj = SWIG_NewInstanceObj(value.clock(), Tcl_Obj *obj = SWIG_NewInstanceObj(value.clock(),
SWIGTYPE_p_Clock, false); SWIGTYPE_p_Clock, false);
@ -1597,9 +1615,6 @@ using namespace sta;
Tcl_SetObjResult(interp, list); Tcl_SetObjResult(interp, list);
} }
break; break;
default:
Tcl_SetResult(interp, const_cast<char*>(""), TCL_STATIC);
break;
} }
} }
@ -2267,6 +2282,24 @@ top_instance()
return cmdLinkedNetwork()->topInstance(); 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 * TmpPortSeq *
find_ports_matching(const char *pattern, find_ports_matching(const char *pattern,
bool regexp, bool regexp,
@ -2523,7 +2556,7 @@ filter_ports(const char *property,
while (port_iter.hasNext()) { while (port_iter.hasNext()) {
Port *port = port_iter.next(); Port *port = port_iter.next();
PropertyValue value(getProperty(port, property, sta)); PropertyValue value(getProperty(port, property, sta));
const char *prop = value.string(); const char *prop = value.stringValue();
if (prop && if (prop &&
((exact_match && stringEq(prop, pattern)) ((exact_match && stringEq(prop, pattern))
|| (!exact_match && patternMatch(pattern, prop)))) || (!exact_match && patternMatch(pattern, prop))))
@ -2547,7 +2580,7 @@ filter_insts(const char *property,
while (inst_iter.hasNext()) { while (inst_iter.hasNext()) {
Instance *inst = inst_iter.next(); Instance *inst = inst_iter.next();
PropertyValue value(getProperty(inst, property, sta)); PropertyValue value(getProperty(inst, property, sta));
const char *prop = value.string(); const char *prop = value.stringValue();
if (prop && if (prop &&
((exact_match && stringEq(prop, pattern)) ((exact_match && stringEq(prop, pattern))
|| (!exact_match && patternMatch(pattern, prop)))) || (!exact_match && patternMatch(pattern, prop))))
@ -2570,7 +2603,7 @@ filter_pins(const char *property,
while (pin_iter.hasNext()) { while (pin_iter.hasNext()) {
Pin *pin = pin_iter.next(); Pin *pin = pin_iter.next();
PropertyValue value(getProperty(pin, property, sta)); PropertyValue value(getProperty(pin, property, sta));
const char *prop = value.string(); const char *prop = value.stringValue();
if (prop && if (prop &&
((exact_match && stringEq(prop, pattern)) ((exact_match && stringEq(prop, pattern))
|| (!exact_match && patternMatch(pattern, prop)))) || (!exact_match && patternMatch(pattern, prop))))
@ -2617,7 +2650,13 @@ PropertyValue
liberty_cell_property(const LibertyCell *cell, liberty_cell_property(const LibertyCell *cell,
const char *property) 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()); return getProperty(cell, property, Sta::sta());
} }
@ -2625,7 +2664,6 @@ PropertyValue
liberty_port_property(const LibertyPort *port, liberty_port_property(const LibertyPort *port,
const char *property) const char *property)
{ {
cmdLinkedNetwork();
return getProperty(port, property, Sta::sta()); return getProperty(port, property, Sta::sta());
} }
@ -2633,7 +2671,6 @@ PropertyValue
library_property(const Library *lib, library_property(const Library *lib,
const char *property) const char *property)
{ {
cmdLinkedNetwork();
return getProperty(lib, property, Sta::sta()); return getProperty(lib, property, Sta::sta());
} }
@ -2676,6 +2713,14 @@ path_ref_property(PathRef *path,
return getProperty(path, property, Sta::sta()); 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 * LeafInstanceIterator *
leaf_instance_iterator() leaf_instance_iterator()
{ {
@ -2747,7 +2792,7 @@ filter_timing_arcs(const char *property,
while (edge_iter.hasNext()) { while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next(); Edge *edge = edge_iter.next();
PropertyValue value(getProperty(edge, property, sta)); PropertyValue value(getProperty(edge, property, sta));
const char *prop = value.string(); const char *prop = value.stringValue();
if (prop && if (prop &&
((exact_match && stringEq(prop, pattern)) ((exact_match && stringEq(prop, pattern))
|| (!exact_match && patternMatch(pattern, prop)))) || (!exact_match && patternMatch(pattern, prop))))
@ -5093,8 +5138,6 @@ define_corners_cmd(StringSet *corner_names)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
%extend Library { %extend Library {
const char *name() { return cmdNetwork()->name(self); }
const char *object_name() { return cmdNetwork()->name(self); }
Cell * Cell *
find_cell(const char *name) find_cell(const char *name)
{ {
@ -5116,10 +5159,6 @@ find_cells_matching(const char *pattern,
%extend LibertyLibrary { %extend LibertyLibrary {
const char *name() { return self->name(); }
const char *filename() { return self->filename(); }
const char *object_name() { return self->name(); }
LibertyCell * LibertyCell *
find_liberty_cell(const char *name) find_liberty_cell(const char *name)
{ {
@ -5177,9 +5216,6 @@ void finish() { delete self; }
} // LibertyLibraryIterator methods } // LibertyLibraryIterator methods
%extend Cell { %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); } Library *library() { return cmdNetwork()->library(self); }
LibertyCell *liberty_cell() { return cmdNetwork()->libertyCell(self); } LibertyCell *liberty_cell() { return cmdNetwork()->libertyCell(self); }
bool is_leaf() { return cmdNetwork()->isLeaf(self); } bool is_leaf() { return cmdNetwork()->isLeaf(self); }
@ -5206,9 +5242,6 @@ find_ports_matching(const char *pattern,
} // Cell methods } // Cell methods
%extend LibertyCell { %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(); } bool is_leaf() { return self->isLeaf(); }
LibertyLibrary *liberty_library() { return self->libertyLibrary(); } LibertyLibrary *liberty_library() { return self->libertyLibrary(); }
Cell *cell() { return reinterpret_cast<Cell*>(self); } Cell *cell() { return reinterpret_cast<Cell*>(self); }
@ -5250,29 +5283,21 @@ void finish() { delete self; }
} // LibertyCellPortIterator methods } // LibertyCellPortIterator methods
%extend Port { %extend Port {
const char *name() { return cmdNetwork()->name(self); }
const char *bus_name() { return cmdNetwork()->busName(self); } const char *bus_name() { return cmdNetwork()->busName(self); }
Cell *cell() { return cmdNetwork()->cell(self); } Cell *cell() { return cmdNetwork()->cell(self); }
LibertyPort *liberty_port() { return cmdNetwork()->libertyPort(self); } LibertyPort *liberty_port() { return cmdNetwork()->libertyPort(self); }
const char *object_name() { return cmdNetwork()->name(self); }
bool is_bus() { return cmdNetwork()->isBus(self); } bool is_bus() { return cmdNetwork()->isBus(self); }
PortMemberIterator * PortMemberIterator *
member_iterator() { return cmdNetwork()->memberIterator(self); } member_iterator() { return cmdNetwork()->memberIterator(self); }
const char *
direction() { return cmdNetwork()->direction(self)->name(); }
} // Port methods } // Port methods
%extend LibertyPort { %extend LibertyPort {
const char *name() { return self->name(); }
const char *bus_name() { return self->busName(); } const char *bus_name() { return self->busName(); }
Cell *cell() { return self->cell(); } Cell *cell() { return self->cell(); }
const char *object_name() { return self->name(); }
bool is_bus() { return self->isBus(); } bool is_bus() { return self->isBus(); }
LibertyPortMemberIterator * LibertyPortMemberIterator *
member_iterator() { return new LibertyPortMemberIterator(self); } member_iterator() { return new LibertyPortMemberIterator(self); }
const char *
direction() { return self->direction()->name(); }
const char * const char *
function() function()
@ -5306,7 +5331,6 @@ capacitance(const TransRiseFall *tr,
} // LibertyPort methods } // LibertyPort methods
%extend OperatingConditions { %extend OperatingConditions {
const char *name() { return self->name(); }
float process() { return self->process(); } float process() { return self->process(); }
float voltage() { return self->voltage(); } float voltage() { return self->voltage(); }
float temperature() { return self->temperature(); } float temperature() { return self->temperature(); }
@ -5331,13 +5355,12 @@ TimingRole *role() { return self->role(); }
const char *sdf_cond() { return self->sdfCond(); } const char *sdf_cond() { return self->sdfCond(); }
const char * const char *
object_name() full_name()
{ {
const char *from = self->from()->name(); const char *from = self->from()->name();
const char *to = self->to()->name(); const char *to = self->to()->name();
const char *cell_name = self->libertyCell()->name(); const char *cell_name = self->libertyCell()->name();
return stringPrintTmp(strlen(from) + strlen(to) + strlen(cell_name) + 6, return stringPrintTmp("%s %s -> %s",
"%s %s -> %s",
cell_name, cell_name,
from, from,
to); to);
@ -5368,9 +5391,6 @@ void finish() { delete self; }
} }
%extend Instance { %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); } Instance *parent() { return cmdLinkedNetwork()->parent(self); }
Cell *cell() { return cmdLinkedNetwork()->cell(self); } Cell *cell() { return cmdLinkedNetwork()->cell(self); }
LibertyCell *liberty_cell() { return cmdLinkedNetwork()->libertyCell(self); } LibertyCell *liberty_cell() { return cmdLinkedNetwork()->libertyCell(self); }
@ -5413,16 +5433,12 @@ void finish() { delete self; }
} // InstanceNetIterator methods } // InstanceNetIterator methods
%extend Pin { %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 *port_name() { return cmdLinkedNetwork()->portName(self); }
const char *path_name() { return cmdLinkedNetwork()->pathName(self); }
Instance *instance() { return cmdLinkedNetwork()->instance(self); } Instance *instance() { return cmdLinkedNetwork()->instance(self); }
Net *net() { return cmdLinkedNetwork()->net(self); } Net *net() { return cmdLinkedNetwork()->net(self); }
Port *port() { return cmdLinkedNetwork()->port(self); } Port *port() { return cmdLinkedNetwork()->port(self); }
Term *term() { return cmdLinkedNetwork()->term(self); } Term *term() { return cmdLinkedNetwork()->term(self); }
LibertyPort *liberty_port() { return cmdLinkedNetwork()->libertyPort(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_driver() { return cmdLinkedNetwork()->isDriver(self); }
bool is_load() { return cmdLinkedNetwork()->isLoad(self); } bool is_load() { return cmdLinkedNetwork()->isLoad(self); }
bool is_leaf() { return cmdLinkedNetwork()->isLeaf(self); } bool is_leaf() { return cmdLinkedNetwork()->isLeaf(self); }
@ -5486,18 +5502,11 @@ void finish() { delete self; }
} // PinConnectedPinIterator methods } // PinConnectedPinIterator methods
%extend Term { %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); } Net *net() { return cmdLinkedNetwork()->net(self); }
Pin *pin() { return cmdLinkedNetwork()->pin(self); } Pin *pin() { return cmdLinkedNetwork()->pin(self); }
} // Term methods } // Term methods
%extend Net { %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); } Instance *instance() { return cmdLinkedNetwork()->instance(self); }
Net *highest_connected_net() Net *highest_connected_net()
{ return cmdLinkedNetwork()->highestConnectedNet(self); } { return cmdLinkedNetwork()->highestConnectedNet(self); }
@ -5579,8 +5588,6 @@ void finish() { delete self; }
} // NetConnectedPinIterator methods } // NetConnectedPinIterator methods
%extend Clock { %extend Clock {
const char *name() { return self->name(); }
const char *object_name() { return self->name(); }
float period() { return self->period(); } float period() { return self->period(); }
FloatSeq *waveform() { return self->waveform(); } FloatSeq *waveform() { return self->waveform(); }
float time(TransRiseFall *tr) { return self->edge(tr)->time(); } float time(TransRiseFall *tr) { return self->edge(tr)->time(); }
@ -5601,8 +5608,6 @@ slew(const TransRiseFall *tr,
} }
%extend ClockEdge { %extend ClockEdge {
const char *name() { return self->name(); }
const char *object_name() { return self->name(); }
Clock *clock() { return self->clock(); } Clock *clock() { return self->clock(); }
TransRiseFall *transition() { return self->transition(); } TransRiseFall *transition() { return self->transition(); }
float time() { return self->time(); } float time() { return self->time(); }
@ -5909,18 +5914,6 @@ mode_value()
return self->timingArcSet()->modeValue(); 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 * const char *
latch_d_to_q_en() latch_d_to_q_en()
{ {
@ -5937,8 +5930,7 @@ latch_d_to_q_en()
TransRiseFall *enable_tr; TransRiseFall *enable_tr;
lib_cell->latchEnable(d_q_set, enable_port, enable_func, enable_tr); lib_cell->latchEnable(d_q_set, enable_port, enable_func, enable_tr);
const char *en_name = enable_port->name(); const char *en_name = enable_port->name();
return stringPrintTmp(strlen(en_name) + 3, return stringPrintTmp("%s %s", en_name, enable_tr->asString());
"%s %s", en_name, enable_tr->asString());
} }
return ""; return "";

View File

@ -46,9 +46,7 @@ InternalError::InternalError(const char *filename,
const char * const char *
InternalError::what() const throw() InternalError::what() const throw()
{ {
return stringPrintTmp(strlen("Internal error in : .") return stringPrintTmp("Internal error in %s:%d %s.",
+ strlen(filename_) + strlen(msg_) + 5,
"Internal error in %s:%d %s.",
filename_, line_, msg_); filename_, line_, msg_);
} }
@ -60,9 +58,7 @@ FileNotReadable::FileNotReadable(const char *filename) :
const char * const char *
FileNotReadable::what() const throw() FileNotReadable::what() const throw()
{ {
return stringPrintTmp(strlen("Error: cannot read file .") return stringPrintTmp("Error: cannot read file %s.", filename_);
+ strlen(filename_) + 1,
"Error: cannot read file %s.", filename_);
} }
FileNotWritable::FileNotWritable(const char *filename) : FileNotWritable::FileNotWritable(const char *filename) :
@ -73,10 +69,7 @@ FileNotWritable::FileNotWritable(const char *filename) :
const char * const char *
FileNotWritable::what() const throw() FileNotWritable::what() const throw()
{ {
return stringPrintTmp(strlen("Error: cannot write file .") return stringPrintTmp("Error: cannot write file %s.", filename_);
+ strlen(filename_) + 1,
"Error: cannot write file %s.",
filename_);
} }
} // namespace } // namespace

View File

@ -149,11 +149,10 @@ systemRunTime()
size_t size_t
memoryUsage() memoryUsage()
{ {
char *proc_filename = stringPrintTmp(strlen("/proc//status")+10, string proc_filename;
"/proc/%d/status", stringPrint(proc_filename, "/proc/%d/status", getpid());
getpid());
size_t memory = 0; size_t memory = 0;
FILE *status = fopen(proc_filename, "r"); FILE *status = fopen(proc_filename.c_str(), "r");
if (status) { if (status) {
const size_t line_length = 128; const size_t line_length = 128;
char line[line_length]; char line[line_length];

View File

@ -117,7 +117,7 @@ RegexpCompileError::RegexpCompileError(const char *pattern) :
StaException() StaException()
{ {
const char *msg = "Error: TCL failed to compile regular expression '%s'."; 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 * const char *

View File

@ -23,6 +23,17 @@
namespace sta { 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 * char *
stringCopy(const char *str) stringCopy(const char *str)
{ {
@ -50,97 +61,119 @@ isDigits(const char *str)
char * char *
integerString(int number) integerString(int number)
{ {
// Leave room for sign and '\0'. return stringPrint("%d", number);
return stringPrint(INT_DIGITS + 2, "%d", number);
} }
char * // print for c++ strings.
stringPrint(int length_estimate, void
stringPrint(string &str,
const char *fmt, const char *fmt,
...) ...)
{ {
va_list args; va_list args;
va_start(args, fmt); 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); va_end(args);
return result; return result;
} }
char * char *
stringPrintArgs(int length_estimate, stringPrintArgs(const char *fmt,
const char *fmt,
va_list args) va_list args)
{ {
va_list args_copy; char *tmp;
va_copy(args_copy, args); size_t tmp_length;
char *result = new char[length_estimate]; stringPrintTmp(fmt, args, tmp, tmp_length);
int length = vsnprint(result, length_estimate, fmt, args); char *result = new char[tmp_length + 1];
if (length >= length_estimate) { strcpy(result, tmp);
stringDelete(result);
result = new char[length + 1];
vsnprint(result, length + 1, fmt, args_copy);
}
va_end(args_copy);
return result; return result;
} }
char * char *
stringPrintTmp(int length_estimate, stringPrintTmp(const char *fmt,
const char *fmt,
...) ...)
{ {
char *result = makeTmpString(length_estimate);
va_list args; va_list args;
va_start(args, fmt); 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); 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'. // Returned length does NOT include trailing '\0'.
if (length >= length_estimate) { tmp_length = vsnprint(tmp, tmp_length1, fmt, args_copy);
result = makeTmpString(length + 1); va_end(args_copy);
va_start(args, fmt);
vsnprint(result, length + 1, fmt, args); if (tmp_length >= tmp_length1) {
va_end(args); 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 int tmp_string_count_ = 100;
static size_t tmp_string_length_ = 100;
static int tmp_string_next_ = 0;
static char **tmp_strings_ = NULL; static char **tmp_strings_ = NULL;
static size_t *tmp_string_lengths_ = NULL; static size_t *tmp_string_lengths_ = NULL;
static int tmp_string_next_;
static Mutex string_lock_; static Mutex string_lock_;
char * void
makeTmpString(size_t length) initTmpStrings()
{ {
string_lock_.lock(); size_t initial_length = 100;
if (tmp_strings_ == NULL) {
tmp_strings_ = new char*[tmp_string_count_]; tmp_strings_ = new char*[tmp_string_count_];
tmp_string_lengths_ = new size_t[tmp_string_count_]; tmp_string_lengths_ = new size_t[tmp_string_count_];
for (int i = 0; i < tmp_string_count_; i++) { for (int i = 0; i < tmp_string_count_; i++) {
tmp_strings_[i] = new char[tmp_string_length_]; tmp_strings_[i] = new char[initial_length];
tmp_string_lengths_[i] = tmp_string_length_; tmp_string_lengths_[i] = initial_length;
} }
}
if (tmp_string_next_ == tmp_string_count_)
tmp_string_next_ = 0; 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 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 void

View File

@ -132,21 +132,25 @@ bool
isDigits(const char *str); isDigits(const char *str);
// Print to a new string. // Print to a new string.
// length_estimate should include room for the terminating '\0'. // Caller owns returned string.
char * char *
stringPrint(int length_estimate, stringPrint(const char *fmt,
const char *fmt, ...) __attribute__((format (printf, 1, 2)));
...); string
stdstrPrint(const char *fmt,
...) __attribute__((format (printf, 1, 2)));
char * char *
stringPrintArgs(int length_estimate, stringPrintArgs(const char *fmt,
const char *fmt,
va_list args); va_list args);
// Print to a temporary string. void
// length_estimate should include room for the terminating '\0'. stringPrint(string &str,
char *
stringPrintTmp(int length_estimate,
const char *fmt, const char *fmt,
...); ...) __attribute__((format (printf, 2, 3)));
// Print to a temporary string.
char *
stringPrintTmp(const char *fmt,
...) __attribute__((format (printf, 1, 2)));
// Caller owns returned string. // Caller owns returned string.
char * char *
integerString(int number); integerString(int number);
@ -154,6 +158,8 @@ integerString(int number);
char * char *
makeTmpString(size_t length); makeTmpString(size_t length);
void void
initTmpStrings();
void
deleteTmpStrings(); deleteTmpStrings();
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -32,9 +32,7 @@ const char *
ThreadException::what() const throw() ThreadException::what() const throw()
{ {
const char *msg = strerror(error_); const char *msg = strerror(error_);
return stringPrintTmp(strlen(filename_) + strlen(msg) + 30, return stringPrintTmp("Thread error in %s:%d %s.", filename_, line_, msg);
"Thread error in %s:%d %s.",
filename_, line_, msg);
} }
} }

View File

@ -31,7 +31,8 @@ namespace sta {
class TokenParser class TokenParser
{ {
public: public:
TokenParser(const char *str, const char *delimiters); TokenParser(const char *str,
const char *delimiters);
bool hasNext(); bool hasNext();
char *next(); char *next();

View File

@ -153,7 +153,7 @@ VerilogReader::VerilogReader(Report *report,
{ {
network->setLinkFunc(linkVerilogNetwork); network->setLinkFunc(linkVerilogNetwork);
VerilogConstant10 constant10_max = 0; VerilogConstant10 constant10_max = 0;
constant10_max_ = stringPrint(21, "%llu", ~constant10_max); constant10_max_ = stringPrint("%llu", ~constant10_max);
constant10_max_length_ = strlen(constant10_max_); constant10_max_length_ = strlen(constant10_max_);
} }
@ -851,8 +851,7 @@ VerilogModule::checkInstanceName(VerilogInst *inst,
do { do {
if (replacement_name) if (replacement_name)
stringDelete(replacement_name); stringDelete(replacement_name);
replacement_name = stringPrint(strlen(inst_name) + 4, replacement_name = stringPrint("%s_%d", inst_name, i);
"%s_%d", inst_name, i);
} while (inst_names.findKey(replacement_name)); } while (inst_names.findKey(replacement_name));
reader->warn(filename_, inst->line(), reader->warn(filename_, inst->line(),
"instance name %s duplicated - renamed to %s.\n", "instance name %s duplicated - renamed to %s.\n",
@ -1161,14 +1160,14 @@ static const char *
verilogBusBitNameTmp(const char *bus_name, verilogBusBitNameTmp(const char *bus_name,
int index) int index)
{ {
return stringPrintTmp(strlen(bus_name) + 8, "%s[%d]", bus_name, index); return stringPrintTmp("%s[%d]", bus_name, index);
} }
static const char * static const char *
verilogBusBitName(const char *bus_name, verilogBusBitName(const char *bus_name,
int index) int index)
{ {
return stringPrint(strlen(bus_name) + 8, "%s[%d]", bus_name, index); return stringPrint("%s[%d]", bus_name, index);
} }
class VerilogConstantNetNameIterator : public VerilogNetNameIterator class VerilogConstantNetNameIterator : public VerilogNetNameIterator
@ -2041,10 +2040,11 @@ VerilogReader::makeBlackBoxOrderedPorts(Cell *cell,
while (pin_iter.hasNext()) { while (pin_iter.hasNext()) {
VerilogNet *net = pin_iter.next(); VerilogNet *net = pin_iter.next();
size_t size = net->size(parent_module); 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) Port *port = (size == 1)
? network_->makePort(cell, port_name) ? network_->makePort(cell, port_name)
: network_->makeBusPort(cell, port_name, size - 1, 0); : network_->makeBusPort(cell, port_name, size - 1, 0);
stringDelete(port_name);
network_->setDirection(port, PortDirection::bidirect()); network_->setDirection(port, PortDirection::bidirect());
port_index++; port_index++;
} }
@ -2161,7 +2161,7 @@ VerilogReader::linkWarn(const char *filename,
{ {
va_list args; va_list args;
va_start(args, msg); 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); VerilogError *error = new VerilogError(filename, line, msg_str, true);
link_errors_.push_back(error); link_errors_.push_back(error);
va_end(args); va_end(args);
@ -2174,7 +2174,7 @@ VerilogReader::linkError(const char *filename,
{ {
va_list args; va_list args;
va_start(args, msg); 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); VerilogError *error = new VerilogError(filename, line, msg_str, false);
link_errors_.push_back(error); link_errors_.push_back(error);
va_end(args); va_end(args);