Merge origin/master into secure-sta-test-suite
Resolve add/add conflict in test/helpers.tcl by merging both versions: - Keep master's report_file, report_file_filter, sort_objects functions - Keep branch's diff_files, diff_files_sorted functions - Use master's result_dir setup with branch's mkdir logic in make_result_file Resolve content conflict in test/regression by keeping branch's bash/ctest launcher over master's Tcl regression script. Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
This commit is contained in:
commit
d4ad9312ea
|
|
@ -0,0 +1,6 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository_owner != 'The-OpenROAD-Project-private'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Set up dependencies
|
||||
run: |
|
||||
sudo apt-get update && sudo apt-get install -y flex libfl-dev bison tcl-dev tcl-tclreadline libeigen3-dev ninja-build
|
||||
|
||||
- name: Set up cudd-3.0.0
|
||||
run: |
|
||||
wget https://github.com/oscc-ip/artifact/releases/download/cudd-3.0.0/build.tar.gz
|
||||
mkdir -p cudd
|
||||
tar -zxvf build.tar.gz -Ccudd
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G Ninja -DCUDD_DIR=$(pwd)/../cudd -DCMAKE_INSTALL_PREFIX=$(pwd)/install -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build . --target all -- -j $(nproc)
|
||||
cmake --install .
|
||||
tar -zcvf build.tar.gz -Cinstall .
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
cd test
|
||||
./regression
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: artifact
|
||||
path: |
|
||||
build/install/*
|
||||
|
||||
- name: Upload Test Result
|
||||
uses: actions/upload-artifact@v7
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: result
|
||||
path: |
|
||||
test/results/*
|
||||
|
|
@ -241,10 +241,7 @@ set(STA_SOURCE
|
|||
util/RiseFallMinMaxDelay.cc
|
||||
util/RiseFallValues.cc
|
||||
util/Stats.cc
|
||||
util/StringSeq.cc
|
||||
util/StringSet.cc
|
||||
util/StringUtil.cc
|
||||
util/TokenParser.cc
|
||||
util/Transition.cc
|
||||
|
||||
verilog/VerilogReader.cc
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ LABEL maintainer="James Cherry <cherry@parallaxsw.com>"
|
|||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
git \
|
||||
wget \
|
||||
cmake \
|
||||
gcc \
|
||||
gdb \
|
||||
tcl-dev \
|
||||
tcl-tclreadline \
|
||||
libeigen3-dev \
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
# Static Timing Analysis
|
||||
|
||||
This is effectively a fork of [parallaxsw/OpenSTA](https://github.com/parallaxsw/OpenSTA). All issues and PRs should be filed there.
|
||||
|
||||
# Parallax Static Timing Analyzer
|
||||
|
||||
OpenSTA is a gate level static timing verifier. As a stand-alone
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ namespace sta {
|
|||
extern const char *tcl_inits[];
|
||||
}
|
||||
|
||||
using std::string;
|
||||
using sta::stringEq;
|
||||
using sta::findCmdLineFlag;
|
||||
using sta::Sta;
|
||||
|
|
@ -129,7 +128,7 @@ staTclAppInit(int argc,
|
|||
if (!findCmdLineFlag(argc, argv, "-no_init")) {
|
||||
const char *home = getenv("HOME");
|
||||
if (home) {
|
||||
string init_path = home;
|
||||
std::string init_path = home;
|
||||
init_path += "/";
|
||||
init_path += init_filename;
|
||||
if (std::filesystem::is_regular_file(init_path.c_str()))
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::make_shared;
|
||||
|
||||
Waveform
|
||||
ArcDcalcWaveforms::inputWaveform(ArcDcalcArg &dcalc_arg,
|
||||
const Scene *scene,
|
||||
|
|
@ -68,8 +66,8 @@ ArcDcalcWaveforms::inputWaveform(ArcDcalcArg &dcalc_arg,
|
|||
FloatSeq time_values;
|
||||
for (float time : in_waveform.axis1()->values())
|
||||
time_values.push_back(time + dcalc_arg.inputDelay());
|
||||
TableAxisPtr time_axis = make_shared<TableAxis>(TableAxisVariable::time,
|
||||
std::move(time_values));
|
||||
TableAxisPtr time_axis = std::make_shared<TableAxis>(TableAxisVariable::time,
|
||||
std::move(time_values));
|
||||
// Scale the waveform from 0:vdd.
|
||||
FloatSeq *scaled_values = new FloatSeq;
|
||||
for (float value : *in_waveform.values()) {
|
||||
|
|
|
|||
|
|
@ -63,10 +63,6 @@ namespace sta {
|
|||
// ra_get_r
|
||||
// ra_get_s
|
||||
|
||||
using std::string;
|
||||
using std::abs;
|
||||
using std::vector;
|
||||
|
||||
struct delay_work;
|
||||
struct delay_c;
|
||||
|
||||
|
|
@ -151,15 +147,15 @@ public:
|
|||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
string reportGateDelay(const Pin *drvr_pin,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits) override;
|
||||
std::string reportGateDelay(const Pin *drvr_pin,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits) override;
|
||||
void finishDrvrPin() override;
|
||||
void delay_work_set_thresholds(delay_work *D,
|
||||
double lo,
|
||||
|
|
@ -240,7 +236,7 @@ private:
|
|||
int pin_n_;
|
||||
ArnoldiReduce *reduce_;
|
||||
delay_work *delay_work_;
|
||||
vector<rcmodel*> unsaved_parasitics_;
|
||||
std::vector<rcmodel*> unsaved_parasitics_;
|
||||
bool pocv_enabled_;
|
||||
};
|
||||
|
||||
|
|
@ -469,7 +465,7 @@ ArnoldiDelayCalc::gateDelaySlew(const LibertyCell *drvr_cell,
|
|||
return dcalc_result;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
ArnoldiDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
|
|
@ -610,7 +606,8 @@ delay_work_get_residues(delay_work *D,int term_index)
|
|||
// calculate_poles_res
|
||||
//
|
||||
|
||||
void arnoldi1::calculate_poles_res(delay_work *D,double rdrive)
|
||||
void arnoldi1::calculate_poles_res(delay_work *D,
|
||||
double rdrive)
|
||||
{
|
||||
if (n > D->nmax) delay_work_alloc(D,n);
|
||||
double *p = D->poles;
|
||||
|
|
@ -689,7 +686,7 @@ tridiagEV(int n,double *din,double *ein,double *d,double **v)
|
|||
e[0] = 0.0;
|
||||
for (h=n-1;h>=1;h--) {
|
||||
iter = 0;
|
||||
while (abs(e[h])>1e-18) { // 1e-6ps
|
||||
while (std::abs(e[h])>1e-18) { // 1e-6ps
|
||||
m=0;
|
||||
if (m != h) {
|
||||
if (iter++ == 20)
|
||||
|
|
@ -819,14 +816,14 @@ solve_t_bracketed(double s,int order,double *p,double *rr,
|
|||
if (0.0<f2) return x2;
|
||||
if (f1<0.0) return x1;
|
||||
}
|
||||
dxold = abs(x2-x1);
|
||||
dxold = std::abs(x2-x1);
|
||||
dx = dxold;
|
||||
get_dv(rts,s,order,p,rr,&f,&df);
|
||||
f -= val;
|
||||
double flast = 0.0;
|
||||
for (j=1;j<10;j++) {
|
||||
if ((((rts-xh)*df-f)*((rts-xl)*df-f) >= 0.0)
|
||||
|| (abs(2.0*f) > abs(dxold*df))) {
|
||||
|| (std::abs(2.0*f) > std::abs(dxold*df))) {
|
||||
dxold = dx;
|
||||
dx = 0.5*(xh-xl);
|
||||
if (flast*f >0.0) {
|
||||
|
|
@ -850,7 +847,7 @@ solve_t_bracketed(double s,int order,double *p,double *rr,
|
|||
return rts;
|
||||
}
|
||||
}
|
||||
if (abs(dx) < xacc) {
|
||||
if (std::abs(dx) < xacc) {
|
||||
return rts;
|
||||
}
|
||||
get_dv(rts,s,order,p,rr,&f,&df); f -= val;
|
||||
|
|
@ -859,7 +856,7 @@ solve_t_bracketed(double s,int order,double *p,double *rr,
|
|||
else
|
||||
xh = rts;
|
||||
}
|
||||
if (abs(f)<1e-6) // 1uV
|
||||
if (std::abs(f)<1e-6) // 1uV
|
||||
return rts;
|
||||
return 0.5*(xl+xh);
|
||||
}
|
||||
|
|
@ -1265,28 +1262,28 @@ ArnoldiDelayCalc::ra_solve_for_s(delay_work *D,
|
|||
f = (ptlo-pthi)/p - tlohi;
|
||||
df = dlo-dhi;
|
||||
s = s - f/df;
|
||||
if (abs(f)<.001e-12) return; // .001ps
|
||||
if (std::abs(f)<.001e-12) return; // .001ps
|
||||
|
||||
ra_solve_for_pt(p*s,vlo,&ptlo,&dlo);
|
||||
ra_solve_for_pt(p*s,vhi,&pthi,&dhi);
|
||||
f = (ptlo-pthi)/p - tlohi;
|
||||
df = dlo-dhi;
|
||||
s = s - f/df;
|
||||
if (abs(f)<.001e-12) return; // .001ps
|
||||
if (std::abs(f)<.001e-12) return; // .001ps
|
||||
|
||||
ra_solve_for_pt(p*s,vlo,&ptlo,&dlo);
|
||||
ra_solve_for_pt(p*s,vhi,&pthi,&dhi);
|
||||
f = (ptlo-pthi)/p - tlohi;
|
||||
df = dlo-dhi;
|
||||
s = s - f/df;
|
||||
if (abs(f)<.001e-12) return; // .001ps
|
||||
if (std::abs(f)<.001e-12) return; // .001ps
|
||||
|
||||
ra_solve_for_pt(p*s,vlo,&ptlo,&dlo);
|
||||
ra_solve_for_pt(p*s,vhi,&pthi,&dhi);
|
||||
f = (ptlo-pthi)/p - tlohi;
|
||||
df = dlo-dhi;
|
||||
s = s - f/df;
|
||||
if (abs(f)<.001e-12) return; // .001ps
|
||||
if (std::abs(f)<.001e-12) return; // .001ps
|
||||
|
||||
ra_solve_for_pt(p*s,vlo,&ptlo,&dlo);
|
||||
ra_solve_for_pt(p*s,vhi,&pthi,&dhi);
|
||||
|
|
@ -1294,7 +1291,7 @@ ArnoldiDelayCalc::ra_solve_for_s(delay_work *D,
|
|||
df = dlo-dhi;
|
||||
s = s - f/df;
|
||||
|
||||
if (abs(f)>.5e-12) // .5ps
|
||||
if (std::abs(f)>.5e-12) // .5ps
|
||||
debugPrint(debug_, "arnoldi", 1, "ra_solve_for_s p %g tlohi %s err %s",
|
||||
p,
|
||||
units_->timeUnit()->asString(tlohi),
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
rcmodel::rcmodel() :
|
||||
pinV(nullptr)
|
||||
{
|
||||
|
|
@ -621,7 +619,7 @@ ArnoldiReduce::makeRcmodelFromTs()
|
|||
report_->reportLine(" d[%d] %s",
|
||||
h,
|
||||
units_->timeUnit()->asString(d[h]));
|
||||
string line = stdstrPrint("U[%d]",h);
|
||||
std::string line = stdstrPrint("U[%d]",h);
|
||||
for (i=0;i<nterms;i++)
|
||||
line += stdstrPrint(" %6.2e",U[h][i]);
|
||||
report_->reportLineString(line);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include "CcsCeffDelayCalc.hh"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "Debug.hh"
|
||||
#include "Units.hh"
|
||||
#include "Liberty.hh"
|
||||
|
|
@ -38,17 +40,11 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
// Implementaion based on:
|
||||
// "Gate Delay Estimation with Library Compatible Current Source Models
|
||||
// and Effective Capacitance", D. Garyfallou et al,
|
||||
// IEEE Transactions on Very Large Scale Integration (VLSI) Systems, March 2021
|
||||
|
||||
using std::abs;
|
||||
using std::exp;
|
||||
using std::make_shared;
|
||||
|
||||
ArcDelayCalc *
|
||||
makeCcsCeffDelayCalc(StaState *sta)
|
||||
{
|
||||
|
|
@ -122,7 +118,7 @@ CcsCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
ref_time_ = output_waveforms_->referenceTime(in_slew_);
|
||||
debugPrint(debug_, "ccs_dcalc", 1, "%s %s",
|
||||
drvr_cell->name(),
|
||||
drvr_rf_->to_string().c_str());
|
||||
drvr_rf_->shortName());
|
||||
ArcDelay gate_delay;
|
||||
Slew drvr_slew;
|
||||
gateDelaySlew(drvr_library, drvr_rf_, gate_delay, drvr_slew);
|
||||
|
|
@ -144,7 +140,7 @@ CcsCeffDelayCalc::gateDelaySlew(const LibertyLibrary *drvr_library,
|
|||
findCsmWaveform();
|
||||
ref_time_ = output_waveforms_->referenceTime(in_slew_);
|
||||
gate_delay = region_times_[region_vth_idx_] - ref_time_;
|
||||
drvr_slew = abs(region_times_[region_vh_idx_] - region_times_[region_vl_idx_]);
|
||||
drvr_slew = std::abs(region_times_[region_vh_idx_] - region_times_[region_vl_idx_]);
|
||||
debugPrint(debug_, "ccs_dcalc", 2,
|
||||
"gate_delay %s drvr_slew %s (initial)",
|
||||
delayAsString(gate_delay, this),
|
||||
|
|
@ -184,12 +180,12 @@ CcsCeffDelayCalc::gateDelaySlew(const LibertyLibrary *drvr_library,
|
|||
}
|
||||
findCsmWaveform();
|
||||
gate_delay = region_times_[region_vth_idx_] - ref_time_;
|
||||
drvr_slew = abs(region_times_[region_vh_idx_] - region_times_[region_vl_idx_]);
|
||||
drvr_slew = std::abs(region_times_[region_vh_idx_] - region_times_[region_vl_idx_]);
|
||||
debugPrint(debug_, "ccs_dcalc", 2,
|
||||
"gate_delay %s drvr_slew %s",
|
||||
delayAsString(gate_delay, this),
|
||||
delayAsString(drvr_slew, this));
|
||||
if (abs(delayAsFloat(drvr_slew) - prev_drvr_slew) < .01 * prev_drvr_slew)
|
||||
if (std::abs(delayAsFloat(drvr_slew) - prev_drvr_slew) < .01 * prev_drvr_slew)
|
||||
break;
|
||||
prev_drvr_slew = delayAsFloat(drvr_slew);
|
||||
}
|
||||
|
|
@ -529,8 +525,8 @@ CcsCeffDelayCalc::drvrWaveform()
|
|||
drvr_volts->push_back(v);
|
||||
}
|
||||
}
|
||||
TableAxisPtr drvr_time_axis = make_shared<TableAxis>(TableAxisVariable::time,
|
||||
std::move(*drvr_times));
|
||||
TableAxisPtr drvr_time_axis = std::make_shared<TableAxis>(TableAxisVariable::time,
|
||||
std::move(*drvr_times));
|
||||
delete drvr_times;
|
||||
Table drvr_table(drvr_volts, drvr_time_axis);
|
||||
return drvr_table;
|
||||
|
|
@ -561,8 +557,8 @@ CcsCeffDelayCalc::loadWaveform(const Pin *load_pin)
|
|||
double v1 = (drvr_rf_ == RiseFall::rise()) ? v : vdd_ - v;
|
||||
load_volts->push_back(v1);
|
||||
}
|
||||
TableAxisPtr load_time_axis = make_shared<TableAxis>(TableAxisVariable::time,
|
||||
std::move(*load_times));
|
||||
TableAxisPtr load_time_axis = std::make_shared<TableAxis>(TableAxisVariable::time,
|
||||
std::move(*load_times));
|
||||
delete load_times;
|
||||
Table load_table(load_volts, load_time_axis);
|
||||
return load_table;
|
||||
|
|
@ -606,8 +602,8 @@ CcsCeffDelayCalc::drvrRampWaveform(const Pin *in_pin,
|
|||
double v1 = (drvr_rf == RiseFall::rise()) ? v : vdd_ - v;
|
||||
load_volts->push_back(v1);
|
||||
}
|
||||
TableAxisPtr load_time_axis = make_shared<TableAxis>(TableAxisVariable::time,
|
||||
std::move(*load_times));
|
||||
TableAxisPtr load_time_axis = std::make_shared<TableAxis>(TableAxisVariable::time,
|
||||
std::move(*load_times));
|
||||
delete load_times;
|
||||
Table load_table(load_volts, load_time_axis);
|
||||
return load_table;
|
||||
|
|
@ -663,7 +659,7 @@ CcsCeffDelayCalc::makeWaveformPreamble(const Pin *in_pin,
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
string
|
||||
std::string
|
||||
CcsCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
|
|
@ -680,7 +676,7 @@ CcsCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
|||
pi_elmore = parasitics_->reduceToPiElmore(parasitic, drvr_pin_, rf,
|
||||
scene, min_max);
|
||||
}
|
||||
string report = table_dcalc_->reportGateDelay(drvr_pin, arc, in_slew, load_cap,
|
||||
std::string report = table_dcalc_->reportGateDelay(drvr_pin, arc, in_slew, load_cap,
|
||||
pi_elmore, load_pin_index_map,
|
||||
scene, min_max, digits);
|
||||
parasitics_->deleteDrvrReducedParasitics(drvr_pin);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "DelayCalc.hh"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "ContainerHelpers.hh"
|
||||
#include "StringUtil.hh"
|
||||
|
|
@ -37,9 +38,9 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
typedef std::map<const char*, MakeArcDelayCalc, CharPtrLess> DelayCalcMap;
|
||||
typedef std::map<std::string, MakeArcDelayCalc> DelayCalcMap;
|
||||
|
||||
static DelayCalcMap *delay_calcs = nullptr;
|
||||
static DelayCalcMap delay_calcs;
|
||||
|
||||
void
|
||||
registerDelayCalcs()
|
||||
|
|
@ -54,26 +55,23 @@ registerDelayCalcs()
|
|||
}
|
||||
|
||||
void
|
||||
registerDelayCalc(const char *name,
|
||||
registerDelayCalc(const std::string &name,
|
||||
MakeArcDelayCalc maker)
|
||||
{
|
||||
if (delay_calcs == nullptr)
|
||||
delay_calcs = new DelayCalcMap;
|
||||
(*delay_calcs)[name] = maker;
|
||||
delay_calcs[name] = maker;
|
||||
}
|
||||
|
||||
void
|
||||
deleteDelayCalcs()
|
||||
{
|
||||
delete delay_calcs;
|
||||
delay_calcs = nullptr;
|
||||
delay_calcs.clear();
|
||||
}
|
||||
|
||||
ArcDelayCalc *
|
||||
makeDelayCalc(const char *name,
|
||||
makeDelayCalc(const std::string &name,
|
||||
StaState *sta)
|
||||
{
|
||||
MakeArcDelayCalc maker = findKey(delay_calcs, name);
|
||||
MakeArcDelayCalc maker = findKey(&delay_calcs, name);
|
||||
if (maker)
|
||||
return maker(sta);
|
||||
else
|
||||
|
|
@ -81,16 +79,16 @@ makeDelayCalc(const char *name,
|
|||
}
|
||||
|
||||
bool
|
||||
isDelayCalcName(const char *name)
|
||||
isDelayCalcName(const std::string &name)
|
||||
{
|
||||
return delay_calcs->contains(name);
|
||||
return delay_calcs.contains(name);
|
||||
}
|
||||
|
||||
StringSeq
|
||||
delayCalcNames()
|
||||
{
|
||||
StringSeq names;
|
||||
for (const auto [name, make_dcalc] : *delay_calcs)
|
||||
for (const auto &[name, make_dcalc] : delay_calcs)
|
||||
names.push_back(name);
|
||||
return names;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,9 +38,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
using std::log;
|
||||
|
||||
DelayCalcBase::DelayCalcBase(StaState *sta) :
|
||||
ArcDelayCalc(sta)
|
||||
{
|
||||
|
|
@ -101,9 +98,9 @@ DelayCalcBase::dspfWireDelaySlew(const Pin *load_pin,
|
|||
vh = load_library->slewUpperThreshold(rf);
|
||||
slew_derate = load_library->slewDerateFromLibrary();
|
||||
}
|
||||
wire_delay = -elmore * log(1.0 - vth);
|
||||
load_slew = drvr_slew + elmore * log((1.0 - vl) / (1.0 - vh)) / slew_derate;
|
||||
load_slew = drvr_slew + elmore * log((1.0 - vl) / (1.0 - vh)) / slew_derate;
|
||||
wire_delay = -elmore * std::log(1.0 - vth);
|
||||
load_slew = drvr_slew + elmore * std::log((1.0 - vl) / (1.0 - vh)) / slew_derate;
|
||||
load_slew = drvr_slew + elmore * std::log((1.0 - vl) / (1.0 - vh)) / slew_derate;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -173,7 +170,7 @@ DelayCalcBase::checkDelay(const Pin *check_pin,
|
|||
return delay_zero;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
DelayCalcBase::reportCheckDelay(const Pin *check_pin,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
|
|
|
|||
|
|
@ -32,8 +32,9 @@
|
|||
|
||||
#include "DmpCeff.hh"
|
||||
|
||||
#include <algorithm> // abs, min
|
||||
#include <cmath> // sqrt, log
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
|
||||
#include "Report.hh"
|
||||
#include "Debug.hh"
|
||||
|
|
@ -50,15 +51,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
using std::abs;
|
||||
using std::min;
|
||||
using std::max;
|
||||
using std::sqrt;
|
||||
using std::log;
|
||||
using std::isnan;
|
||||
using std::function;
|
||||
|
||||
// Tolerance (as a scale of value) for driver parameters (Ceff, delta t, t0).
|
||||
static const double driver_param_tol = .01;
|
||||
// Waveform threshold crossing time tolerance (1.0 = 100%).
|
||||
|
|
@ -107,7 +99,7 @@ newtonRaphson(const int max_iter,
|
|||
const int n,
|
||||
const double x_tol,
|
||||
// eval(state) is called to fill fvec and fjac.
|
||||
function<void ()> eval,
|
||||
std::function<void ()> eval,
|
||||
// Temporaries supplied by caller.
|
||||
double *fvec,
|
||||
double **fjac,
|
||||
|
|
@ -133,7 +125,7 @@ class DmpAlg : public StaState
|
|||
{
|
||||
public:
|
||||
DmpAlg(int nr_order, StaState *sta);
|
||||
virtual ~DmpAlg();
|
||||
~DmpAlg() override = default;
|
||||
virtual const char *name() = 0;
|
||||
// Set driver model and pi model parameters for delay calculation.
|
||||
virtual void init(const LibertyLibrary *library,
|
||||
|
|
@ -164,7 +156,7 @@ public:
|
|||
// Return values.
|
||||
double &vo,
|
||||
double &dol_dt);
|
||||
// Load responce to driver waveform.
|
||||
// Load response to driver waveform.
|
||||
void Vl(double t,
|
||||
// Return values.
|
||||
double &vl,
|
||||
|
|
@ -296,8 +288,6 @@ DmpAlg::DmpAlg(int nr_order,
|
|||
fjac_[i] = fjac_storage_ + i * max_nr_order_;
|
||||
}
|
||||
|
||||
DmpAlg::~DmpAlg() = default;
|
||||
|
||||
void
|
||||
DmpAlg::init(const LibertyLibrary *drvr_library,
|
||||
const LibertyCell *drvr_cell,
|
||||
|
|
@ -337,7 +327,7 @@ DmpAlg::findDriverParams(double ceff)
|
|||
gateDelays(ceff, t_vth, t_vl, slew);
|
||||
// Scale slew to 0-100%
|
||||
double dt = slew / (vh_ - vl_);
|
||||
double t0 = t_vth + log(1.0 - vth_) * rd_ * ceff - vth_ * dt;
|
||||
double t0 = t_vth + std::log(1.0 - vth_) * rd_ * ceff - vth_ * dt;
|
||||
x_[DmpParam::dt] = dt;
|
||||
x_[DmpParam::t0] = t0;
|
||||
newtonRaphson(100, x_, nr_order_, driver_param_tol,
|
||||
|
|
@ -461,7 +451,7 @@ DmpAlg::showFvec()
|
|||
void
|
||||
DmpAlg::showJacobian()
|
||||
{
|
||||
string line = " ";
|
||||
std::string line = " ";
|
||||
for (int j = 0; j < nr_order_; j++)
|
||||
line += stdstrPrint("%12s", dmp_param_index_strings[j]);
|
||||
report_->reportLineString(line);
|
||||
|
|
@ -894,7 +884,7 @@ DmpPi::init(const LibertyLibrary *drvr_library,
|
|||
k0_ = 1.0 / (rd_ * c2_);
|
||||
double a = rpi_ * rd_ * c1_ * c2_;
|
||||
double b = rd_ * (c1_ + c2_) + rpi_ * c1_;
|
||||
double sqrt_ = sqrt(b * b - 4 * a);
|
||||
double sqrt_ = std::sqrt(b * b - 4 * a);
|
||||
p1_ = (b + sqrt_) / (2 * a);
|
||||
p2_ = (b - sqrt_) / (2 * a);
|
||||
|
||||
|
|
@ -1282,7 +1272,7 @@ newtonRaphson(const int max_iter,
|
|||
double x[],
|
||||
const int size,
|
||||
const double x_tol,
|
||||
function<void ()> eval,
|
||||
std::function<void ()> eval,
|
||||
// Temporaries supplied by caller.
|
||||
double *fvec,
|
||||
double **fjac,
|
||||
|
|
@ -1300,7 +1290,7 @@ newtonRaphson(const int max_iter,
|
|||
|
||||
bool all_under_x_tol = true;
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (abs(p[i]) > abs(x[i]) * x_tol)
|
||||
if (std::abs(p[i]) > std::abs(x[i]) * x_tol)
|
||||
all_under_x_tol = false;
|
||||
x[i] += p[i];
|
||||
}
|
||||
|
|
@ -1334,7 +1324,7 @@ luDecomp(double **a,
|
|||
for (int i = 0; i < size; i++) {
|
||||
double big = 0.0;
|
||||
for (int j = 0; j < size; j++) {
|
||||
double temp = abs(a[i][j]);
|
||||
double temp = std::abs(a[i][j]);
|
||||
if (temp > big)
|
||||
big = temp;
|
||||
}
|
||||
|
|
@ -1363,7 +1353,7 @@ luDecomp(double **a,
|
|||
for (int k = 0; k < j; k++)
|
||||
sum -= a[i][k] * a[k][j];
|
||||
a[i][j] = sum;
|
||||
double dum = scale[i] * abs(sum);
|
||||
double dum = scale[i] * std::abs(sum);
|
||||
if (dum >= big) {
|
||||
big = dum;
|
||||
imax = i;
|
||||
|
|
@ -1507,7 +1497,7 @@ DmpCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
float in_slew1 = delayAsFloat(in_slew);
|
||||
float c2, rpi, c1;
|
||||
parasitics_->piModel(parasitic, c2, rpi, c1);
|
||||
if (isnan(c2) || isnan(c1) || isnan(rpi))
|
||||
if (std::isnan(c2) || std::isnan(c1) || std::isnan(rpi))
|
||||
report_->error(1040, "parasitic Pi model has NaNs.");
|
||||
setCeffAlgorithm(drvr_library, drvr_cell, pinPvt(drvr_pin, scene, min_max),
|
||||
table_model, rf, in_slew1, c2, rpi, c1);
|
||||
|
|
@ -1583,7 +1573,7 @@ DmpCeffDelayCalc::setCeffAlgorithm(const LibertyLibrary *drvr_library,
|
|||
dmp_alg_->name());
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
|
|
@ -1598,7 +1588,7 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
|||
parasitic, load_pin_index_map, scene, min_max);
|
||||
GateTableModel *model = arc->gateTableModel(scene, min_max);
|
||||
float c_eff = 0.0;
|
||||
string result;
|
||||
std::string result;
|
||||
const LibertyCell *drvr_cell = arc->to()->libertyCell();
|
||||
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
|
||||
const Units *units = drvr_library->units();
|
||||
|
|
@ -1653,7 +1643,8 @@ gateModelRd(const LibertyCell *cell,
|
|||
gate_model->gateDelay(pvt, in_slew, cap1, pocv_enabled, d1, s1);
|
||||
gate_model->gateDelay(pvt, in_slew, cap2, pocv_enabled, d2, s2);
|
||||
double vth = cell->libertyLibrary()->outputThreshold(rf);
|
||||
float rd = -log(vth) * abs(delayAsFloat(d1) - delayAsFloat(d2)) / (cap2 - cap1);
|
||||
float rd = -std::log(vth) * std::abs(delayAsFloat(d1) - delayAsFloat(d2))
|
||||
/ (cap2 - cap1);
|
||||
return rd;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::abs;
|
||||
|
||||
double
|
||||
findRoot(FindRootFunc func,
|
||||
double x1,
|
||||
|
|
@ -76,7 +74,7 @@ findRoot(FindRootFunc func,
|
|||
// Swap x1/x2 so func(x1) < 0.
|
||||
std::swap(x1, x2);
|
||||
double root = (x1 + x2) * 0.5;
|
||||
double dx_prev = abs(x2 - x1);
|
||||
double dx_prev = std::abs(x2 - x1);
|
||||
double dx = dx_prev;
|
||||
double y, dy;
|
||||
func(root, y, dy);
|
||||
|
|
@ -84,7 +82,7 @@ findRoot(FindRootFunc func,
|
|||
// Newton/raphson out of range.
|
||||
if ((((root - x2) * dy - y) * ((root - x1) * dy - y) > 0.0)
|
||||
// Not decreasing fast enough.
|
||||
|| (abs(2.0 * y) > abs(dx_prev * dy))) {
|
||||
|| (std::abs(2.0 * y) > std::abs(dx_prev * dy))) {
|
||||
// Bisect x1/x2 interval.
|
||||
dx_prev = dx;
|
||||
dx = (x2 - x1) * 0.5;
|
||||
|
|
@ -95,7 +93,7 @@ findRoot(FindRootFunc func,
|
|||
dx = y / dy;
|
||||
root -= dx;
|
||||
}
|
||||
if (abs(dx) <= x_tol * abs(root)) {
|
||||
if (std::abs(dx) <= x_tol * std::abs(root)) {
|
||||
// Converged.
|
||||
fail = false;
|
||||
return root;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include "GraphDelayCalc.hh"
|
||||
|
||||
#include <cmath>
|
||||
#include <array>
|
||||
#include <set>
|
||||
|
||||
#include "ContainerHelpers.hh"
|
||||
|
|
@ -53,10 +55,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
using std::abs;
|
||||
using std::array;
|
||||
|
||||
static const Slew default_slew = 0.0;
|
||||
|
||||
static bool
|
||||
|
|
@ -606,7 +604,7 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell,
|
|||
{
|
||||
debugPrint(debug_, "delay_calc", 2, " driver cell %s %s",
|
||||
drvr_cell->name(),
|
||||
rf->to_string().c_str());
|
||||
rf->shortName());
|
||||
for (TimingArcSet *arc_set : drvr_cell->timingArcSets(from_port, to_port)) {
|
||||
for (TimingArc *arc : arc_set->arcs()) {
|
||||
if (arc->toEdge()->asRiseFall() == rf) {
|
||||
|
|
@ -941,7 +939,7 @@ GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex,
|
|||
initSlew(drvr_vertex);
|
||||
initWireDelays(drvr_vertex);
|
||||
bool delay_changed = false;
|
||||
array<bool, RiseFall::index_count> delay_exists = {false, false};
|
||||
std::array<bool, RiseFall::index_count> delay_exists = {false, false};
|
||||
VertexInEdgeIterator edge_iter(drvr_vertex, graph_);
|
||||
while (edge_iter.hasNext()) {
|
||||
Edge *edge = edge_iter.next();
|
||||
|
|
@ -983,7 +981,7 @@ GraphDelayCalc::findLatchEdgeDelays(Edge *edge)
|
|||
Instance *drvr_inst = network_->instance(drvr_pin);
|
||||
debugPrint(debug_, "delay_calc", 2, "find latch D->Q %s",
|
||||
sdc_network_->pathName(drvr_inst));
|
||||
array<bool, RiseFall::index_count> delay_exists = {false, false};
|
||||
std::array<bool, RiseFall::index_count> delay_exists = {false, false};
|
||||
LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
|
||||
bool delay_changed = findDriverEdgeDelays(drvr_vertex, nullptr, edge,
|
||||
arc_delay_calc_, load_pin_index_map,
|
||||
|
|
@ -999,7 +997,7 @@ GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex,
|
|||
ArcDelayCalc *arc_delay_calc,
|
||||
LoadPinIndexMap &load_pin_index_map,
|
||||
// Return value.
|
||||
array<bool, RiseFall::index_count> &delay_exists)
|
||||
std::array<bool, RiseFall::index_count> &delay_exists)
|
||||
{
|
||||
Vertex *from_vertex = edge->from(graph_);
|
||||
const TimingArcSet *arc_set = edge->timingArcSet();
|
||||
|
|
@ -1116,8 +1114,7 @@ GraphDelayCalc::makeArcDcalcArgs(Vertex *drvr_vertex,
|
|||
const Pin *from_pin = from_vertex->pin();
|
||||
const RiseFall *from_rf = arc1->fromEdge()->asRiseFall();
|
||||
const RiseFall *drvr_rf = arc1->toEdge()->asRiseFall();
|
||||
Slew in_slew = edgeFromSlew(from_vertex, from_rf, edge1, scene, min_max);
|
||||
in_slew = edgeFromSlew(from_vertex, from_rf, edge1, scene, min_max);
|
||||
const Slew in_slew = edgeFromSlew(from_vertex, from_rf, edge1, scene, min_max);
|
||||
|
||||
const Pin *drvr_pin1 = drvr_vertex1->pin();
|
||||
float load_cap;
|
||||
|
|
@ -1231,7 +1228,7 @@ GraphDelayCalc::annotateDelaySlew(Edge *edge,
|
|||
float gate_delay1 = delayAsFloat(gate_delay);
|
||||
float prev_gate_delay1 = delayAsFloat(prev_gate_delay);
|
||||
if (prev_gate_delay1 == 0.0
|
||||
|| (abs(gate_delay1 - prev_gate_delay1) / prev_gate_delay1
|
||||
|| (std::abs(gate_delay1 - prev_gate_delay1) / prev_gate_delay1
|
||||
> incremental_delay_tolerance_))
|
||||
delay_changed = true;
|
||||
graph_->setArcDelay(edge, arc, ap_index, gate_delay);
|
||||
|
|
@ -1660,7 +1657,7 @@ GraphDelayCalc::checkEdgeClkSlew(const Vertex *from_vertex,
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
string
|
||||
std::string
|
||||
GraphDelayCalc::reportDelayCalc(const Edge *edge,
|
||||
const TimingArc *arc,
|
||||
const Scene *scene,
|
||||
|
|
@ -1673,7 +1670,7 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge,
|
|||
const TimingRole *role = arc->role();
|
||||
const Instance *inst = network_->instance(to_pin);
|
||||
const TimingArcSet *arc_set = edge->timingArcSet();
|
||||
string result;
|
||||
std::string result;
|
||||
const RiseFall *from_rf = arc->fromEdge()->asRiseFall();
|
||||
const RiseFall *to_rf = arc->toEdge()->asRiseFall();
|
||||
if (from_rf && to_rf) {
|
||||
|
|
@ -1696,7 +1693,7 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge,
|
|||
related_out_cap, scene, min_max, digits);
|
||||
}
|
||||
else {
|
||||
const Slew &from_slew = edgeFromSlew(from_vertex, from_rf, edge, scene, min_max);
|
||||
const Slew from_slew = edgeFromSlew(from_vertex, from_rf, edge, scene, min_max);
|
||||
const Parasitic *to_parasitic;
|
||||
float load_cap;
|
||||
parasiticLoad(to_pin, to_rf, scene, min_max, nullptr, arc_delay_calc_,
|
||||
|
|
|
|||
|
|
@ -40,9 +40,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
using std::isnan;
|
||||
|
||||
ArcDelayCalc *
|
||||
makeLumpedCapDelayCalc(StaState *sta)
|
||||
{
|
||||
|
|
@ -146,7 +143,7 @@ LumpedCapDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
Slew drvr_slew;
|
||||
float in_slew1 = delayAsFloat(in_slew);
|
||||
// NaNs cause seg faults during table lookup.
|
||||
if (isnan(load_cap) || isnan(delayAsFloat(in_slew)))
|
||||
if (std::isnan(load_cap) || std::isnan(delayAsFloat(in_slew)))
|
||||
report_->error(1350, "gate delay input variable is NaN");
|
||||
model->gateDelay(pinPvt(drvr_pin, scene, min_max), in_slew1, load_cap,
|
||||
variables_->pocvEnabled(),
|
||||
|
|
@ -170,14 +167,15 @@ LumpedCapDelayCalc::makeResult(const LibertyLibrary *drvr_library,
|
|||
|
||||
for (const auto [load_pin, load_idx] : load_pin_index_map) {
|
||||
ArcDelay wire_delay = 0.0;
|
||||
Slew load_slew = drvr_slew;
|
||||
thresholdAdjust(load_pin, drvr_library, rf, wire_delay, drvr_slew);
|
||||
dcalc_result.setWireDelay(load_idx, wire_delay);
|
||||
dcalc_result.setLoadSlew(load_idx, drvr_slew);
|
||||
dcalc_result.setLoadSlew(load_idx, load_slew);
|
||||
}
|
||||
return dcalc_result;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
LumpedCapDelayCalc::reportGateDelay(const Pin *check_pin,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::vector;
|
||||
|
||||
ParallelDelayCalc::ParallelDelayCalc(StaState *sta):
|
||||
DelayCalcBase(sta)
|
||||
{
|
||||
|
|
@ -71,8 +69,8 @@ ParallelDelayCalc::gateDelaysParallel(ArcDcalcArgSeq &dcalc_args,
|
|||
ArcDcalcResultSeq dcalc_results(drvr_count);
|
||||
Slew slew_sum = 0.0;
|
||||
ArcDelay load_delay_sum = 0.0;
|
||||
vector<ArcDelay> intrinsic_delays(dcalc_args.size());
|
||||
vector<ArcDelay> load_delays(dcalc_args.size());
|
||||
std::vector<ArcDelay> intrinsic_delays(dcalc_args.size());
|
||||
std::vector<ArcDelay> load_delays(dcalc_args.size());
|
||||
for (size_t drvr_idx = 0; drvr_idx < drvr_count; drvr_idx++) {
|
||||
ArcDcalcArg &dcalc_arg = dcalc_args[drvr_idx];
|
||||
ArcDcalcResult &dcalc_result = dcalc_results[drvr_idx];
|
||||
|
|
|
|||
|
|
@ -44,9 +44,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
using std::abs;
|
||||
using std::make_shared;
|
||||
using Eigen::SparseLU;
|
||||
using Eigen::HouseholderQR;
|
||||
using Eigen::ColPivHouseholderQR;
|
||||
|
|
@ -234,7 +231,7 @@ PrimaDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
|||
output_waveforms_[drvr_idx] = output_waveforms;
|
||||
debugPrint(debug_, "ccs_dcalc", 1, "%s %s",
|
||||
dcalc_arg.drvrCell()->name(),
|
||||
drvr_rf_->to_string().c_str());
|
||||
drvr_rf_->shortName());
|
||||
LibertyCell *drvr_cell = dcalc_arg.drvrCell();
|
||||
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
|
||||
bool vdd_exists;
|
||||
|
|
@ -726,7 +723,7 @@ PrimaDelayCalc::dcalcResults()
|
|||
ThresholdTimes &drvr_times = threshold_times_[drvr_node];
|
||||
float ref_time = output_waveforms_[drvr_idx]->referenceTime(dcalc_arg.inSlewFlt());
|
||||
ArcDelay gate_delay = drvr_times[threshold_vth] - ref_time;
|
||||
Slew drvr_slew = abs(drvr_times[threshold_vh] - drvr_times[threshold_vl]);
|
||||
Slew drvr_slew = std::abs(drvr_times[threshold_vh] - drvr_times[threshold_vl]);
|
||||
dcalc_result.setGateDelay(gate_delay);
|
||||
dcalc_result.setDrvrSlew(drvr_slew);
|
||||
debugPrint(debug_, "ccs_dcalc", 2,
|
||||
|
|
@ -743,11 +740,11 @@ PrimaDelayCalc::dcalcResults()
|
|||
ThresholdTimes &wire_times = threshold_times_[load_node];
|
||||
ThresholdTimes &drvr_times = threshold_times_[drvr_node];
|
||||
ArcDelay wire_delay = wire_times[threshold_vth] - drvr_times[threshold_vth];
|
||||
Slew load_slew = abs(wire_times[threshold_vh] - wire_times[threshold_vl]);
|
||||
Slew load_slew = std::abs(wire_times[threshold_vh] - wire_times[threshold_vl]);
|
||||
debugPrint(debug_, "ccs_dcalc", 2,
|
||||
"load %s %s delay %s slew %s",
|
||||
network_->pathName(load_pin),
|
||||
drvr_rf_->to_string().c_str(),
|
||||
drvr_rf_->shortName(),
|
||||
delayAsString(wire_delay, this),
|
||||
delayAsString(load_slew, this));
|
||||
|
||||
|
|
@ -908,7 +905,7 @@ PrimaDelayCalc::recordWaveformStep(double time)
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
string
|
||||
std::string
|
||||
PrimaDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
|
|
@ -959,8 +956,8 @@ Waveform
|
|||
PrimaDelayCalc::watchWaveform(const Pin *pin)
|
||||
{
|
||||
FloatSeq &voltages = watch_pin_values_[pin];
|
||||
TableAxisPtr time_axis = make_shared<TableAxis>(TableAxisVariable::time,
|
||||
FloatSeq(times_));
|
||||
TableAxisPtr time_axis = std::make_shared<TableAxis>(TableAxisVariable::time,
|
||||
FloatSeq(times_));
|
||||
Table waveform(new FloatSeq(voltages), time_axis);
|
||||
return waveform;
|
||||
}
|
||||
|
|
@ -1003,7 +1000,7 @@ void
|
|||
PrimaDelayCalc::reportMatrix(MatrixSd &matrix)
|
||||
{
|
||||
for (Eigen::Index i = 0; i < matrix.rows(); i++) {
|
||||
string line = "| ";
|
||||
std::string line = "| ";
|
||||
for (Eigen::Index j = 0; j < matrix.cols(); j++) {
|
||||
std::string entry = stdstrPrint("%10.3e", matrix.coeff(i, j));
|
||||
line += entry;
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
ArcDelayCalc *
|
||||
makeUnitDelayCalc(StaState *sta)
|
||||
{
|
||||
|
|
@ -142,7 +140,7 @@ UnitDelayCalc::unitDelayResult(const LoadPinIndexMap &load_pin_index_map)
|
|||
return dcalc_result;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
UnitDelayCalc::reportGateDelay(const Pin *,
|
||||
const TimingArc *,
|
||||
const Slew &,
|
||||
|
|
@ -153,7 +151,7 @@ UnitDelayCalc::reportGateDelay(const Pin *,
|
|||
const MinMax *,
|
||||
int)
|
||||
{
|
||||
string result("Delay = 1.0\n");
|
||||
std::string result("Delay = 1.0\n");
|
||||
result += "Slew = 0.0\n";
|
||||
return result;
|
||||
}
|
||||
|
|
@ -170,7 +168,7 @@ UnitDelayCalc::checkDelay(const Pin *,
|
|||
return units_->timeUnit()->scale();
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
UnitDelayCalc::reportCheckDelay(const Pin *,
|
||||
const TimingArc *,
|
||||
const Slew &,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ StaState::clk_network__ moved to Mode
|
|||
StaState::parasitics_ moved to Scene
|
||||
|
||||
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
|
||||
to StdStringSeq&.
|
||||
to StringSeq&.
|
||||
|
||||
Sta::isClock has been removed. Use mode->clkNetwork()->isClock instead.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ OpenSTA Timing Analyzer Release Notes
|
|||
|
||||
This file summarizes user visible changes for each release.
|
||||
|
||||
2025/02/24
|
||||
2026/02/24
|
||||
----------
|
||||
|
||||
The define_scene -library argument now takes a the library name or a
|
||||
|
|
@ -201,7 +201,7 @@ to remove paths through identical pins and rise/fall edges.
|
|||
Instances now have pins for verilog netlist power/ground connections,
|
||||
|
||||
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
|
||||
to StdStringSeq&.
|
||||
to StringSeq&.
|
||||
|
||||
Release 2.6.1 2025/03/30
|
||||
-------------------------
|
||||
|
|
|
|||
3507
doc/OpenSTA.fodt
3507
doc/OpenSTA.fodt
File diff suppressed because it is too large
Load Diff
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -61,7 +61,7 @@ foreach subdir $subdirs {
|
|||
set files [glob -nocomplain [file join $subdir "*.{cc,hh,yy,ll,i}"]]
|
||||
set files_c [concat $files_c $files]
|
||||
}
|
||||
set warn_regexp_c {(?:(?:->critical|->warn|->fileWarn|->error|->fileError|libWarn|libError| warn)\(|tclArgError\(interp,\s*)([0-9]+),.*(".+")}
|
||||
set warn_regexp_c {(?:(?:->critical|->warn|->fileWarn|->error|->fileError|criticalError|libWarn|libError)\(|tclArgError\(interp,\s*)([0-9]+),.*(".+")}
|
||||
|
||||
set files_tcl {}
|
||||
foreach subdir $subdirs {
|
||||
|
|
|
|||
|
|
@ -17,4 +17,3 @@ define_scene ff -liberty NangateOpenCellLibrary_fast
|
|||
report_checks -path_delay min_max
|
||||
# report typical scene
|
||||
report_checks -scene tt
|
||||
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Graph
|
||||
|
|
@ -985,12 +983,12 @@ Vertex::setObjectIdx(ObjectIdx idx)
|
|||
object_idx_ = idx;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
Vertex::to_string(const StaState *sta) const
|
||||
{
|
||||
const Network *network = sta->sdcNetwork();
|
||||
if (network->direction(pin_)->isBidirect()) {
|
||||
string str = network->pathName(pin_);
|
||||
std::string str = network->pathName(pin_);
|
||||
str += ' ';
|
||||
str += is_bidirect_drvr_ ? "driver" : "load";
|
||||
return str;
|
||||
|
|
@ -1002,7 +1000,7 @@ Vertex::to_string(const StaState *sta) const
|
|||
const char *
|
||||
Vertex::name(const Network *network) const
|
||||
{
|
||||
string name = to_string(network);
|
||||
std::string name = to_string(network);
|
||||
return makeTmpString(name);
|
||||
}
|
||||
|
||||
|
|
@ -1229,13 +1227,15 @@ Edge::setObjectIdx(ObjectIdx idx)
|
|||
object_idx_ = idx;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
Edge::to_string(const StaState *sta) const
|
||||
{
|
||||
const Graph *graph = sta->graph();
|
||||
string str = from(graph)->to_string(sta);
|
||||
std::string str = from(graph)->to_string(sta);
|
||||
str += " -> ";
|
||||
str += to(graph)->to_string(sta);
|
||||
str += " ";
|
||||
str += role()->to_string();
|
||||
FuncExpr *when = arc_set_->cond();
|
||||
if (when) {
|
||||
str += " ";
|
||||
|
|
|
|||
|
|
@ -171,6 +171,7 @@ path_iterator(const RiseFall *rf,
|
|||
} // Vertex methods
|
||||
|
||||
%extend Edge {
|
||||
std::string to_string() { return self->to_string(Sta::sta()); };
|
||||
Vertex *from() { return self->from(Sta::sta()->graph()); }
|
||||
Vertex *to() { return self->to(Sta::sta()->graph()); }
|
||||
Pin *from_pin() { return self->from(Sta::sta()->graph())->pin(); }
|
||||
|
|
@ -298,7 +299,7 @@ latch_d_to_q_en()
|
|||
if (enable_port)
|
||||
return stringPrintTmp("%s %s",
|
||||
enable_port->name(),
|
||||
enable_rf->to_string().c_str());
|
||||
enable_rf->shortName());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,9 +77,9 @@ public:
|
|||
void remove(Vertex *vertex);
|
||||
void reportEntries() const;
|
||||
|
||||
virtual bool hasNext();
|
||||
bool hasNext() override;
|
||||
bool hasNext(Level to_level);
|
||||
virtual Vertex *next();
|
||||
Vertex *next() override;
|
||||
|
||||
// Apply visitor to all vertices in the queue in level order.
|
||||
// Returns the number of vertices that are visited.
|
||||
|
|
@ -131,19 +131,19 @@ public:
|
|||
SearchPred *search_pred,
|
||||
StaState *sta);
|
||||
virtual ~BfsFwdIterator();
|
||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred);
|
||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred,
|
||||
const Mode *mode);
|
||||
void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred) override;
|
||||
void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred,
|
||||
const Mode *mode) override;
|
||||
using BfsIterator::enqueueAdjacentVertices;
|
||||
|
||||
protected:
|
||||
virtual bool levelLessOrEqual(Level level1,
|
||||
Level level2) const;
|
||||
virtual bool levelLess(Level level1,
|
||||
Level level2) const;
|
||||
virtual void incrLevel(Level &level) const;
|
||||
bool levelLessOrEqual(Level level1,
|
||||
Level level2) const override;
|
||||
bool levelLess(Level level1,
|
||||
Level level2) const override;
|
||||
void incrLevel(Level &level) const override;
|
||||
};
|
||||
|
||||
class BfsBkwdIterator : public BfsIterator
|
||||
|
|
@ -153,19 +153,19 @@ public:
|
|||
SearchPred *search_pred,
|
||||
StaState *sta);
|
||||
virtual ~BfsBkwdIterator();
|
||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred);
|
||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred,
|
||||
const Mode *mode);
|
||||
void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred) override;
|
||||
void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred,
|
||||
const Mode *mode) override;
|
||||
using BfsIterator::enqueueAdjacentVertices;
|
||||
|
||||
protected:
|
||||
virtual bool levelLessOrEqual(Level level1,
|
||||
Level level2) const;
|
||||
virtual bool levelLess(Level level1,
|
||||
Level level2) const;
|
||||
virtual void incrLevel(Level &level) const;
|
||||
bool levelLessOrEqual(Level level1,
|
||||
Level level2) const override;
|
||||
bool levelLess(Level level1,
|
||||
Level level2) const override;
|
||||
void incrLevel(Level &level) const override;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ public:
|
|||
comp_(comp),
|
||||
min_heap_comp_(comp)
|
||||
{
|
||||
heap_.reserve(max_size);
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
|
|
@ -107,7 +106,12 @@ public:
|
|||
setMaxSize(size_t max_size)
|
||||
{
|
||||
max_size_ = max_size;
|
||||
heap_.reserve(max_size);
|
||||
}
|
||||
|
||||
void
|
||||
reserve(size_t size)
|
||||
{
|
||||
heap_.reserve(size);
|
||||
}
|
||||
|
||||
// Insert an element into the heap.
|
||||
|
|
@ -172,8 +176,6 @@ public:
|
|||
{
|
||||
// Convert heap to sorted vector (best to worst)
|
||||
std::sort_heap(heap_.begin(), heap_.end(), min_heap_comp_);
|
||||
// Reverse to get best first (according to user's comparison)
|
||||
std::reverse(heap_.begin(), heap_.end());
|
||||
std::vector<T> result = std::move(heap_);
|
||||
heap_.clear();
|
||||
return result;
|
||||
|
|
@ -181,11 +183,10 @@ public:
|
|||
|
||||
// Extract all elements sorted from best to worst (const version).
|
||||
// Creates a copy since we can't modify the heap.
|
||||
std::vector<T> extract() const
|
||||
std::vector<T> contents() const
|
||||
{
|
||||
std::vector<T> temp_heap = heap_;
|
||||
std::sort_heap(temp_heap.begin(), temp_heap.end(), min_heap_comp_);
|
||||
std::reverse(temp_heap.begin(), temp_heap.end());
|
||||
return temp_heap;
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +246,7 @@ private:
|
|||
Compare comp_;
|
||||
explicit MinHeapCompare(const Compare& c) : comp_(c) {}
|
||||
bool operator()(const T& a, const T& b) const {
|
||||
return comp_(b, a); // Inverted: worst is at root
|
||||
return comp_(a, b); // comp = less puts largest at root (worst)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -264,8 +264,8 @@ class ConcreteCellPortBitIterator : public Iterator<ConcretePort*>
|
|||
{
|
||||
public:
|
||||
ConcreteCellPortBitIterator(const ConcreteCell *cell);
|
||||
virtual bool hasNext();
|
||||
virtual ConcretePort *next();
|
||||
bool hasNext() override;
|
||||
ConcretePort *next() override;
|
||||
|
||||
private:
|
||||
void findNext();
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "StringSeq.hh"
|
||||
#include <string>
|
||||
|
||||
#include "StringUtil.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -38,10 +40,10 @@ void
|
|||
registerDelayCalcs();
|
||||
// Register a delay calculator for the set_delay_calc command.
|
||||
void
|
||||
registerDelayCalc(const char *name,
|
||||
registerDelayCalc(const std::string &name,
|
||||
MakeArcDelayCalc maker);
|
||||
bool
|
||||
isDelayCalcName(const char *name);
|
||||
isDelayCalcName(const std::string &name);
|
||||
StringSeq
|
||||
delayCalcNames();
|
||||
void
|
||||
|
|
@ -49,7 +51,7 @@ deleteDelayCalcs();
|
|||
|
||||
// Make a registered delay calculator by name.
|
||||
ArcDelayCalc *
|
||||
makeDelayCalc(const char *name,
|
||||
makeDelayCalc(const std::string &name,
|
||||
StaState *sta);
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -427,8 +427,8 @@ class VertexIterator : public Iterator<Vertex*>
|
|||
{
|
||||
public:
|
||||
VertexIterator(Graph *graph);
|
||||
virtual bool hasNext() { return vertex_ || bidir_vertex_; }
|
||||
virtual Vertex *next();
|
||||
bool hasNext() override { return vertex_ || bidir_vertex_; }
|
||||
Vertex *next() override;
|
||||
|
||||
private:
|
||||
bool findNextPin();
|
||||
|
|
@ -450,8 +450,8 @@ public:
|
|||
const Graph *graph);
|
||||
VertexInEdgeIterator(VertexId vertex_id,
|
||||
const Graph *graph);
|
||||
bool hasNext() { return (next_ != nullptr); }
|
||||
Edge *next();
|
||||
bool hasNext() override { return (next_ != nullptr); }
|
||||
Edge *next() override;
|
||||
|
||||
private:
|
||||
Edge *next_;
|
||||
|
|
@ -463,8 +463,8 @@ class VertexOutEdgeIterator : public VertexEdgeIterator
|
|||
public:
|
||||
VertexOutEdgeIterator(Vertex *vertex,
|
||||
const Graph *graph);
|
||||
bool hasNext() { return (next_ != nullptr); }
|
||||
Edge *next();
|
||||
bool hasNext() override { return (next_ != nullptr); }
|
||||
Edge *next() override;
|
||||
|
||||
private:
|
||||
Edge *next_;
|
||||
|
|
@ -478,8 +478,8 @@ public:
|
|||
EdgesThruHierPinIterator(const Pin *hpin,
|
||||
Network *network,
|
||||
Graph *graph);
|
||||
virtual bool hasNext();
|
||||
virtual Edge *next();
|
||||
bool hasNext() override;
|
||||
Edge *next() override;
|
||||
|
||||
private:
|
||||
EdgeSet edges_;
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
bool hasNext() { return seq_ && itr_ != seq_->end(); }
|
||||
OBJ_TYPE next() { return *itr_++; }
|
||||
bool hasNext() override { return seq_ && itr_ != seq_->end(); }
|
||||
OBJ_TYPE next() override { return *itr_++; }
|
||||
|
||||
protected:
|
||||
const VECTOR_TYPE *seq_;
|
||||
|
|
@ -80,8 +80,8 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
bool hasNext() { return map_ && itr_ != map_->end(); }
|
||||
OBJ_TYPE next() {
|
||||
bool hasNext() override { return map_ && itr_ != map_->end(); }
|
||||
OBJ_TYPE next() override {
|
||||
OBJ_TYPE next = itr_->second;
|
||||
itr_++;
|
||||
return next;
|
||||
|
|
@ -108,8 +108,8 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
bool hasNext() { return set_ && itr_ != set_->end(); }
|
||||
OBJ_TYPE next() { return *itr_++; }
|
||||
bool hasNext() override { return set_ && itr_ != set_->end(); }
|
||||
OBJ_TYPE next() override { return *itr_++; }
|
||||
|
||||
protected:
|
||||
const SET_TYPE *set_;
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ public:
|
|||
float wire_delay) const;
|
||||
// Check for supported axis variables.
|
||||
// Return true if axes are supported.
|
||||
static bool checkSlewDegradationAxes(const TablePtr &table);
|
||||
static bool checkSlewDegradationAxes(const TableModel *table_model);
|
||||
|
||||
float defaultInputPinCap() const { return default_input_pin_cap_; }
|
||||
void setDefaultInputPinCap(float cap);
|
||||
|
|
@ -458,8 +458,8 @@ class LibertyCellIterator : public Iterator<LibertyCell*>
|
|||
{
|
||||
public:
|
||||
LibertyCellIterator(const LibertyLibrary *library);
|
||||
bool hasNext();
|
||||
LibertyCell *next();
|
||||
bool hasNext() override;
|
||||
LibertyCell *next() override;
|
||||
|
||||
private:
|
||||
ConcreteLibraryCellIterator iter_;
|
||||
|
|
@ -715,8 +715,8 @@ class LibertyCellPortIterator : public Iterator<LibertyPort*>
|
|||
{
|
||||
public:
|
||||
LibertyCellPortIterator(const LibertyCell *cell);
|
||||
bool hasNext();
|
||||
LibertyPort *next();
|
||||
bool hasNext() override;
|
||||
LibertyPort *next() override;
|
||||
|
||||
private:
|
||||
ConcreteCellPortIterator iter_;
|
||||
|
|
@ -727,8 +727,8 @@ class LibertyCellPortBitIterator : public Iterator<LibertyPort*>
|
|||
public:
|
||||
LibertyCellPortBitIterator(const LibertyCell *cell);
|
||||
virtual ~LibertyCellPortBitIterator();
|
||||
bool hasNext();
|
||||
LibertyPort *next();
|
||||
bool hasNext() override;
|
||||
LibertyPort *next() override;
|
||||
|
||||
private:
|
||||
ConcreteCellPortBitIterator *iter_;
|
||||
|
|
@ -892,10 +892,6 @@ public:
|
|||
float clkTreeDelay(float in_slew,
|
||||
const RiseFall *from_rf,
|
||||
const MinMax *min_max) const;
|
||||
// deprecated 2024-06-22
|
||||
RiseFallMinMax clkTreeDelays() const __attribute__ ((deprecated));
|
||||
// deprecated 2024-02-27
|
||||
RiseFallMinMax clockTreePathDelays() const __attribute__ ((deprecated));
|
||||
|
||||
static bool equiv(const LibertyPort *port1,
|
||||
const LibertyPort *port2);
|
||||
|
|
@ -916,7 +912,6 @@ protected:
|
|||
void setMinPort(LibertyPort *min);
|
||||
void addScaledPort(OperatingConditions *op_cond,
|
||||
LibertyPort *scaled_port);
|
||||
RiseFallMinMax clkTreeDelays1() const;
|
||||
void setMemberFlag(bool value,
|
||||
const std::function<void(LibertyPort*, bool)> &setter);
|
||||
void setMemberFloat(float value,
|
||||
|
|
@ -985,8 +980,8 @@ class LibertyPortMemberIterator : public Iterator<LibertyPort*>
|
|||
public:
|
||||
LibertyPortMemberIterator(const LibertyPort *port);
|
||||
virtual ~LibertyPortMemberIterator();
|
||||
virtual bool hasNext();
|
||||
virtual LibertyPort *next();
|
||||
bool hasNext() override;
|
||||
LibertyPort *next() override;
|
||||
|
||||
private:
|
||||
ConcretePortMemberIterator *iter_;
|
||||
|
|
@ -1051,7 +1046,7 @@ public:
|
|||
void setScale(ScaleFactorType type,
|
||||
ScaleFactorPvt pvt,
|
||||
float scale);
|
||||
void print();
|
||||
void report(Report *report);
|
||||
|
||||
protected:
|
||||
std::string name_;
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ public:
|
|||
bool unique_edges,
|
||||
float min_slack,
|
||||
float max_slack,
|
||||
StdStringSeq &group_names,
|
||||
StringSeq &group_names,
|
||||
bool setup,
|
||||
bool hold,
|
||||
bool recovery,
|
||||
|
|
|
|||
|
|
@ -204,8 +204,8 @@ public:
|
|||
const MinMax *min_max,
|
||||
const StaState *sta);
|
||||
virtual ~VertexPathIterator();
|
||||
virtual bool hasNext();
|
||||
virtual Path *next();
|
||||
bool hasNext() override;
|
||||
Path *next() override;
|
||||
|
||||
private:
|
||||
void findNext();
|
||||
|
|
|
|||
|
|
@ -153,9 +153,13 @@ public:
|
|||
|
||||
static bool less(const PathEnd *path_end1,
|
||||
const PathEnd *path_end2,
|
||||
// Compare slack (if constrained), or arrival when false.
|
||||
bool cmp_slack,
|
||||
const StaState *sta);
|
||||
static int cmp(const PathEnd *path_end1,
|
||||
const PathEnd *path_end2,
|
||||
// Compare slack (if constrained), or arrival when false.
|
||||
bool cmp_slack,
|
||||
const StaState *sta);
|
||||
static int cmpSlack(const PathEnd *path_end1,
|
||||
const PathEnd *path_end2,
|
||||
|
|
@ -611,11 +615,13 @@ protected:
|
|||
class PathEndLess
|
||||
{
|
||||
public:
|
||||
PathEndLess(const StaState *sta);
|
||||
PathEndLess(bool cmp_slack,
|
||||
const StaState *sta);
|
||||
bool operator()(const PathEnd *path_end1,
|
||||
const PathEnd *path_end2) const;
|
||||
|
||||
protected:
|
||||
bool cmp_slack_;
|
||||
const StaState *sta_;
|
||||
};
|
||||
|
||||
|
|
@ -623,11 +629,13 @@ protected:
|
|||
class PathEndSlackLess
|
||||
{
|
||||
public:
|
||||
PathEndSlackLess(const StaState *sta);
|
||||
PathEndSlackLess(bool cmp_slack,
|
||||
const StaState *sta);
|
||||
bool operator()(const PathEnd *path_end1,
|
||||
const PathEnd *path_end2) const;
|
||||
|
||||
protected:
|
||||
bool cmp_slack_;
|
||||
const StaState *sta_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -29,9 +29,12 @@
|
|||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
#include "BoundedHeap.hh"
|
||||
#include "SdcClass.hh"
|
||||
#include "StaState.hh"
|
||||
#include "SearchClass.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "PathEnd.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -42,13 +45,11 @@ using PathGroupIterator = PathEndSeq::iterator;
|
|||
using PathGroupClkMap = std::map<const Clock*, PathGroup*>;
|
||||
using PathGroupNamedMap = std::map<const char*, PathGroup*, CharPtrLess>;
|
||||
using PathGroupSeq = std::vector<PathGroup*>;
|
||||
using StdStringSeq = std::vector<std::string>;
|
||||
|
||||
// A collection of PathEnds grouped and sorted for reporting.
|
||||
class PathGroup
|
||||
{
|
||||
public:
|
||||
~PathGroup();
|
||||
// Path group that compares compare slacks.
|
||||
static PathGroup *makePathGroupArrival(const char *name,
|
||||
int group_path_count,
|
||||
|
|
@ -66,9 +67,9 @@ public:
|
|||
float min_slack,
|
||||
float max_slack,
|
||||
const StaState *sta);
|
||||
const char *name() const { return name_.c_str(); }
|
||||
const std::string &name() const { return name_; }
|
||||
const MinMax *minMax() const { return min_max_;}
|
||||
const PathEndSeq &pathEnds() const { return path_ends_; }
|
||||
PathEndSeq pathEnds() const;
|
||||
void insert(PathEnd *path_end);
|
||||
// Push group_path_count into path_ends.
|
||||
void pushEnds(PathEndSeq &path_ends);
|
||||
|
|
@ -76,15 +77,14 @@ public:
|
|||
bool saveable(PathEnd *path_end);
|
||||
bool enumMinSlackUnderMin(PathEnd *path_end);
|
||||
int maxPaths() const { return group_path_count_; }
|
||||
PathEndSeq &pathEnds() { return path_ends_; }
|
||||
// This does NOT delete the path ends.
|
||||
void clear();
|
||||
static size_t group_path_count_max;
|
||||
static int group_path_count_max;
|
||||
|
||||
protected:
|
||||
PathGroup(const char *name,
|
||||
size_t group_path_count,
|
||||
size_t endpoint_path_count,
|
||||
int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float min_slack,
|
||||
|
|
@ -92,21 +92,17 @@ protected:
|
|||
bool cmp_slack,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta);
|
||||
void ensureSortedMaxPaths();
|
||||
void prune();
|
||||
void sort();
|
||||
|
||||
std::string name_;
|
||||
size_t group_path_count_;
|
||||
size_t endpoint_path_count_;
|
||||
int group_path_count_;
|
||||
int endpoint_path_count_;
|
||||
bool unique_pins_;
|
||||
bool unique_edges_;
|
||||
float slack_min_;
|
||||
float slack_max_;
|
||||
PathEndSeq path_ends_;
|
||||
const MinMax *min_max_;
|
||||
bool compare_slack_;
|
||||
float threshold_;
|
||||
bool cmp_slack_;
|
||||
BoundedHeap<PathEnd*, PathEndLess> heap_;
|
||||
std::mutex lock_;
|
||||
const StaState *sta_;
|
||||
};
|
||||
|
|
@ -120,7 +116,7 @@ public:
|
|||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
StdStringSeq &group_names,
|
||||
StringSeq &group_names,
|
||||
bool setup,
|
||||
bool hold,
|
||||
bool recovery,
|
||||
|
|
@ -144,7 +140,7 @@ public:
|
|||
PathGroup *findPathGroup(const Clock *clock,
|
||||
const MinMax *min_max) const;
|
||||
PathGroupSeq pathGroups(const PathEnd *path_end) const;
|
||||
static StdStringSeq pathGroupNames(const PathEnd *path_end,
|
||||
static StringSeq pathGroupNames(const PathEnd *path_end,
|
||||
const StaState *sta);
|
||||
static const char *asyncPathGroupName() { return async_group_name_; }
|
||||
static const char *pathDelayGroupName() { return path_delay_group_name_; }
|
||||
|
|
@ -184,17 +180,17 @@ protected:
|
|||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
StdStringSet &group_names,
|
||||
StringSet &group_names,
|
||||
bool setup_hold,
|
||||
bool async,
|
||||
bool gated_clk,
|
||||
bool unconstrained,
|
||||
const MinMax *min_max);
|
||||
bool reportGroup(const char *group_name,
|
||||
StdStringSet &group_names) const;
|
||||
StringSet &group_names) const;
|
||||
static GroupPath *groupPathTo(const PathEnd *path_end,
|
||||
const StaState *sta);
|
||||
StdStringSeq pathGroupNames();
|
||||
StringSeq pathGroupNames();
|
||||
|
||||
const Mode *mode_;
|
||||
int group_path_count_;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ enum class PwrActivityOrigin
|
|||
propagated,
|
||||
clock,
|
||||
constant,
|
||||
defaulted,
|
||||
unknown
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include "StringSeq.hh"
|
||||
#include "GraphClass.hh"
|
||||
#include "SearchClass.hh"
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
#include <mutex>
|
||||
|
||||
#include "StringUtil.hh"
|
||||
#include "StringSet.hh"
|
||||
#include "MinMax.hh"
|
||||
#include "StaState.hh"
|
||||
#include "NetworkClass.hh"
|
||||
|
|
@ -149,7 +148,7 @@ using ExceptionPathPtHash = std::map<size_t, ExceptionPathSet>;
|
|||
using ClockLatencies = std::set<ClockLatency*, ClockLatencyLess>;
|
||||
using EdgeClockLatencyMap = std::map<PinPair, ClockLatency*, PinPairLess>;
|
||||
using PinClockUncertaintyMap = std::map<const Pin*, ClockUncertainties*>;
|
||||
using InterClockUncertaintySet = std::set<InterClockUncertainty*, InterClockUncertaintyLess>;
|
||||
using InterClockUncertaintySet=std::set<InterClockUncertainty*,InterClockUncertaintyLess>;
|
||||
using ClockGatingCheckMap = std::map<const Clock*, ClockGatingCheck*>;
|
||||
using InstanceClockGatingCheckMap = std::map<const Instance*, ClockGatingCheck*>;
|
||||
using PinClockGatingCheckMap = std::map<const Pin*, ClockGatingCheck*>;
|
||||
|
|
@ -1306,6 +1305,7 @@ protected:
|
|||
bool clk_hpin_disables_valid_;
|
||||
PinSet propagated_clk_pins_;
|
||||
ClockLatencies clk_latencies_;
|
||||
PinSet clk_latency_pins_;
|
||||
EdgeClockLatencyMap edge_clk_latency_map_;
|
||||
ClockInsertions clk_insertions_;
|
||||
PinClockUncertaintyMap pin_clk_uncertainty_map_;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "SearchPred.hh"
|
||||
#include "VertexVisitor.hh"
|
||||
#include "Path.hh"
|
||||
#include "StringUtil.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -70,7 +71,6 @@ using VertexSlackMapSeq = std::vector<VertexSlackMap>;
|
|||
using WorstSlacksSeq = std::vector<WorstSlacks>;
|
||||
using DelayDblSeq = std::vector<DelayDbl>;
|
||||
using ExceptionPathSeq = std::vector<ExceptionPath*>;
|
||||
using StdStringSeq = std::vector<std::string>;
|
||||
|
||||
class Search : public StaState
|
||||
{
|
||||
|
|
@ -100,14 +100,14 @@ public:
|
|||
bool unconstrained,
|
||||
const SceneSeq &scenes,
|
||||
const MinMaxAll *min_max,
|
||||
size_t group_path_count,
|
||||
size_t endpoint_path_count,
|
||||
int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
bool sort_by_slack,
|
||||
StdStringSeq &group_names,
|
||||
StringSeq &group_names,
|
||||
bool setup,
|
||||
bool hold,
|
||||
bool recovery,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
#include <map>
|
||||
|
||||
#include "VectorMap.hh"
|
||||
#include "StringSet.hh"
|
||||
#include "MinMaxValues.hh"
|
||||
#include "Delay.hh"
|
||||
#include "NetworkClass.hh"
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include <string_view>
|
||||
#include <functional>
|
||||
|
||||
#include "StringSeq.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "LibertyClass.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "SdcClass.hh"
|
||||
|
|
@ -80,7 +80,6 @@ using SceneNameMap = std::map<std::string, Scene*>;
|
|||
using SlowDrvrIterator = Iterator<Instance*>;
|
||||
using CheckError = StringSeq;
|
||||
using CheckErrorSeq = std::vector<CheckError*>;
|
||||
using StdStringSeq = std::vector<std::string>;
|
||||
enum class CmdNamespace { sta, sdc };
|
||||
using ParasiticsNameMap = std::map<std::string, Parasitics*>;
|
||||
// Path::slack/arrival/required function.
|
||||
|
|
@ -126,11 +125,11 @@ public:
|
|||
void setThreadCount(int thread_count);
|
||||
|
||||
// define_corners compatibility.
|
||||
void makeScenes(StringSeq *scene_names);
|
||||
void makeScenes(const StringSeq &scene_names);
|
||||
void makeScene(const std::string &name,
|
||||
const std::string &mode_name,
|
||||
const StdStringSeq &liberty_min_files,
|
||||
const StdStringSeq &liberty_max_files,
|
||||
const StringSeq &liberty_min_files,
|
||||
const StringSeq &liberty_max_files,
|
||||
const std::string &spef_min_file,
|
||||
const std::string &spef_max_file);
|
||||
Scene *findScene(const std::string &name) const;
|
||||
|
|
@ -653,7 +652,7 @@ public:
|
|||
const Sdc *sdc) __attribute__ ((deprecated));
|
||||
bool isPathGroupName(const char *group_name,
|
||||
const Sdc *sdc) const;
|
||||
StdStringSeq pathGroupNames(const Sdc *sdc) const;
|
||||
StringSeq pathGroupNames(const Sdc *sdc) const;
|
||||
void resetPath(ExceptionFrom *from,
|
||||
ExceptionThruSeq *thrus,
|
||||
ExceptionTo *to,
|
||||
|
|
@ -966,7 +965,7 @@ public:
|
|||
bool sort_by_slack,
|
||||
// Path groups to report.
|
||||
// Empty list reports all groups.
|
||||
StdStringSeq &group_names,
|
||||
StringSeq &group_names,
|
||||
// Predicates to filter the type of path
|
||||
// ends returned.
|
||||
bool setup,
|
||||
|
|
@ -976,7 +975,7 @@ public:
|
|||
bool clk_gating_setup,
|
||||
bool clk_gating_hold);
|
||||
void setReportPathFormat(ReportPathFormat format);
|
||||
void setReportPathFieldOrder(StringSeq *field_names);
|
||||
void setReportPathFieldOrder(const StringSeq &field_names);
|
||||
void setReportPathFields(bool report_input_pin,
|
||||
bool report_hier_pins,
|
||||
bool report_net,
|
||||
|
|
@ -988,16 +987,6 @@ public:
|
|||
void setReportPathDigits(int digits);
|
||||
void setReportPathNoSplit(bool no_split);
|
||||
void setReportPathSigmas(bool report_sigmas);
|
||||
// Header above reportPathEnd results.
|
||||
void reportPathEndHeader();
|
||||
// Footer below reportPathEnd results.
|
||||
void reportPathEndFooter();
|
||||
// Format report_path_endpoint only:
|
||||
// Previous path end is used to detect path group changes
|
||||
// so headers are reported by group.
|
||||
void reportPathEnd(PathEnd *end,
|
||||
PathEnd *prev_end,
|
||||
bool last);
|
||||
void reportPathEnd(PathEnd *end);
|
||||
void reportPathEnds(PathEndSeq *ends);
|
||||
ReportPath *reportPath() { return report_path_; }
|
||||
|
|
@ -1302,13 +1291,13 @@ public:
|
|||
void clkPinsInvalid(const Mode *mode);
|
||||
// The following functions assume ensureClkNetwork() has been called.
|
||||
bool isClock(const Pin *pin,
|
||||
const Mode *mode) const;
|
||||
const Mode *mode);
|
||||
bool isClock(const Net *net,
|
||||
const Mode *mode) const;
|
||||
const Mode *mode);
|
||||
bool isIdealClock(const Pin *pin,
|
||||
const Mode *mode) const;
|
||||
const Mode *mode);
|
||||
bool isPropagatedClock(const Pin *pin,
|
||||
const Mode *mode) const;
|
||||
const Mode *mode);
|
||||
const PinSet *pins(const Clock *clk,
|
||||
const Mode *mode);
|
||||
|
||||
|
|
@ -1398,7 +1387,7 @@ public:
|
|||
LibertyLibrarySeq *map_libs);
|
||||
LibertyCellSeq *equivCells(LibertyCell *cell);
|
||||
|
||||
void writePathSpice(Path *path,
|
||||
void writePathSpice(const Path *path,
|
||||
const char *spice_filename,
|
||||
const char *subckt_filename,
|
||||
const char *lib_subckt_filename,
|
||||
|
|
@ -1522,10 +1511,12 @@ protected:
|
|||
void reportDelaysWrtClks(const Pin *pin,
|
||||
const Scene *scene,
|
||||
int digits,
|
||||
bool find_required,
|
||||
PathDelayFunc get_path_delay);
|
||||
void reportDelaysWrtClks(Vertex *vertex,
|
||||
const Scene *scene,
|
||||
int digits,
|
||||
bool find_required,
|
||||
PathDelayFunc get_path_delay);
|
||||
void reportDelaysWrtClks(Vertex *vertex,
|
||||
const ClockEdge *clk_edge,
|
||||
|
|
@ -1596,8 +1587,8 @@ protected:
|
|||
void setThreadCount1(int thread_count);
|
||||
void updateLibertyScenes();
|
||||
void updateSceneLiberty(Scene *scene,
|
||||
const StdStringSeq &liberty_min_files,
|
||||
const StdStringSeq &liberty_max_files);
|
||||
const StringSeq &liberty_min_files,
|
||||
const StringSeq &liberty_max_files);
|
||||
|
||||
Scene *makeScene(const std::string &name,
|
||||
Mode *mode,
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2025, Parallax Software, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
// The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software.
|
||||
//
|
||||
// Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "StringUtil.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
using StringSeq = std::vector<const char*>;
|
||||
using StdStringSeq = std::vector<std::string>;
|
||||
|
||||
void
|
||||
deleteContents(StringSeq *strings);
|
||||
|
||||
} // namespace
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2025, Parallax Software, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
// The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software.
|
||||
//
|
||||
// Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// This notice may not be removed or altered from any source distribution.
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "StringUtil.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
using StringSet = std::set<const char*, CharPtrLess>;
|
||||
using StdStringSet = std::set<std::string>;
|
||||
using StdStringSeq = std::vector<std::string>;
|
||||
|
||||
void
|
||||
deleteContents(StringSet *strings);
|
||||
|
||||
} // namespace
|
||||
|
|
@ -28,11 +28,15 @@
|
|||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include "Machine.hh" // __attribute__
|
||||
|
||||
namespace sta {
|
||||
|
||||
using StringSeq = std::vector<std::string>;
|
||||
using StringSet = std::set<std::string>;
|
||||
|
||||
inline bool
|
||||
stringEq(const char *str1,
|
||||
const char *str2)
|
||||
|
|
@ -201,12 +205,9 @@ deleteTmpStrings();
|
|||
void
|
||||
trimRight(std::string &str);
|
||||
|
||||
using StringVector = std::vector<std::string>;
|
||||
|
||||
void
|
||||
split(const std::string &text,
|
||||
const std::string &delims,
|
||||
// Return values.
|
||||
StringVector &tokens);
|
||||
// Spit text into delimiter separated tokens and skip whitepace.
|
||||
StringSeq
|
||||
parseTokens(const std::string &s,
|
||||
const char delimiter);
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ using FloatTable = std::vector<FloatSeq>;
|
|||
// Sequence of 1D tables (order 1).
|
||||
using Table1Seq = std::vector<Table*>;
|
||||
using Waveform = Table;
|
||||
using TableModelsEarlyLate = std::array<TableModel*, EarlyLate::index_count>;
|
||||
|
||||
TableAxisVariable
|
||||
stringTableAxisVariable(const char *variable);
|
||||
|
|
@ -63,11 +64,14 @@ class GateTableModel : public GateTimingModel
|
|||
public:
|
||||
GateTableModel(LibertyCell *cell,
|
||||
TableModel *delay_model,
|
||||
TableModel *delay_sigma_models[EarlyLate::index_count],
|
||||
TableModelsEarlyLate delay_sigma_models,
|
||||
TableModel *slew_model,
|
||||
TableModel *slew_sigma_models[EarlyLate::index_count],
|
||||
TableModelsEarlyLate slew_sigma_models,
|
||||
ReceiverModelPtr receiver_model,
|
||||
OutputWaveforms *output_waveforms);
|
||||
GateTableModel(LibertyCell *cell,
|
||||
TableModel *delay_model,
|
||||
TableModel *slew_model);
|
||||
~GateTableModel() override;
|
||||
void gateDelay(const Pvt *pvt,
|
||||
float in_slew,
|
||||
|
|
@ -100,7 +104,7 @@ public:
|
|||
OutputWaveforms *outputWaveforms() const { return output_waveforms_.get(); }
|
||||
// Check the axes before making the model.
|
||||
// Return true if the model axes are supported.
|
||||
static bool checkAxes(const TablePtr &table);
|
||||
static bool checkAxes(const TableModel *table);
|
||||
|
||||
protected:
|
||||
void maxCapSlew(float in_slew,
|
||||
|
|
@ -135,9 +139,9 @@ protected:
|
|||
static bool checkAxis(const TableAxis *axis);
|
||||
|
||||
std::unique_ptr<TableModel> delay_model_;
|
||||
std::array<std::unique_ptr<TableModel>, EarlyLate::index_count> delay_sigma_models_;
|
||||
TableModelsEarlyLate delay_sigma_models_;
|
||||
std::unique_ptr<TableModel> slew_model_;
|
||||
std::array<std::unique_ptr<TableModel>, EarlyLate::index_count> slew_sigma_models_;
|
||||
TableModelsEarlyLate slew_sigma_models_;
|
||||
ReceiverModelPtr receiver_model_;
|
||||
std::unique_ptr<OutputWaveforms> output_waveforms_;
|
||||
};
|
||||
|
|
@ -147,7 +151,9 @@ class CheckTableModel : public CheckTimingModel
|
|||
public:
|
||||
CheckTableModel(LibertyCell *cell,
|
||||
TableModel *model,
|
||||
TableModel *sigma_models[EarlyLate::index_count]);
|
||||
TableModelsEarlyLate sigma_models);
|
||||
CheckTableModel(LibertyCell *cell,
|
||||
TableModel *model);
|
||||
~CheckTableModel() override;
|
||||
ArcDelay checkDelay(const Pvt *pvt,
|
||||
float from_slew,
|
||||
|
|
@ -166,7 +172,7 @@ public:
|
|||
|
||||
// Check the axes before making the model.
|
||||
// Return true if the model axes are supported.
|
||||
static bool checkAxes(const TablePtr table);
|
||||
static bool checkAxes(const TableModel *table);
|
||||
|
||||
protected:
|
||||
void setIsScaled(bool is_scaled) override;
|
||||
|
|
@ -197,7 +203,7 @@ protected:
|
|||
static bool checkAxis(const TableAxis *axis);
|
||||
|
||||
std::unique_ptr<TableModel> model_;
|
||||
std::array<std::unique_ptr<TableModel>, EarlyLate::index_count> sigma_models_;
|
||||
TableModelsEarlyLate sigma_models_;
|
||||
};
|
||||
|
||||
class TableAxis
|
||||
|
|
@ -254,6 +260,8 @@ public:
|
|||
const TableAxis *axis2() const { return axis2_.get(); }
|
||||
const TableAxis *axis3() const { return axis3_.get(); }
|
||||
const TableAxisPtr axis1ptr() const { return axis1_; }
|
||||
const TableAxisPtr axis2ptr() const { return axis2_; }
|
||||
const TableAxisPtr axis3ptr() const { return axis3_; }
|
||||
void setIsScaled(bool is_scaled);
|
||||
|
||||
float value(size_t axis_idx1,
|
||||
|
|
@ -409,7 +417,7 @@ public:
|
|||
void setCapacitanceModel(TableModel table_model,
|
||||
size_t segment,
|
||||
const RiseFall *rf);
|
||||
static bool checkAxes(TablePtr table);
|
||||
static bool checkAxes(const TableModel *table);
|
||||
|
||||
private:
|
||||
std::vector<TableModel> capacitance_models_;
|
||||
|
|
|
|||
|
|
@ -22,33 +22,24 @@
|
|||
//
|
||||
// This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "ArcDelayCalc.hh"
|
||||
#include "StringSet.hh"
|
||||
#include "StringSeq.hh"
|
||||
|
||||
#include <tcl.h>
|
||||
|
||||
#include "ArcDelayCalc.hh"
|
||||
#include "StringUtil.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
#if TCL_MAJOR_VERSION < 9
|
||||
typedef int Tcl_Size;
|
||||
#endif
|
||||
|
||||
StringSet *
|
||||
tclListSetConstChar(Tcl_Obj *const source,
|
||||
Tcl_Interp *interp);
|
||||
|
||||
StringSeq *
|
||||
tclListSeqConstChar(Tcl_Obj *const source,
|
||||
Tcl_Interp *interp);
|
||||
|
||||
StdStringSeq
|
||||
StringSeq
|
||||
tclListSeqStdString(Tcl_Obj *const source,
|
||||
Tcl_Interp *interp);
|
||||
StdStringSeq *
|
||||
StringSeq *
|
||||
tclListSeqStdStringPtr(Tcl_Obj *const source,
|
||||
Tcl_Interp *interp);
|
||||
StdStringSet *
|
||||
StringSet *
|
||||
tclListSetStdString(Tcl_Obj *const source,
|
||||
Tcl_Interp *interp);
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ class TimingArcAttrs
|
|||
public:
|
||||
TimingArcAttrs();
|
||||
TimingArcAttrs(TimingSense sense);
|
||||
virtual ~TimingArcAttrs();
|
||||
~TimingArcAttrs();
|
||||
TimingType timingType() const { return timing_type_; }
|
||||
void setTimingType(TimingType type);
|
||||
TimingSense timingSense() const { return timing_sense_; }
|
||||
|
|
@ -145,7 +145,8 @@ class TimingArcSet
|
|||
friend class LibertyCell;
|
||||
|
||||
public:
|
||||
virtual ~TimingArcSet();
|
||||
~TimingArcSet();
|
||||
std::string to_string();
|
||||
LibertyCell *libertyCell() const;
|
||||
LibertyPort *from() const { return from_; }
|
||||
LibertyPort *to() const { return to_; }
|
||||
|
|
@ -175,6 +176,7 @@ public:
|
|||
// other conditional timing arcs between the same pins.
|
||||
bool isCondDefault() const { return is_cond_default_; }
|
||||
void setIsCondDefault(bool is_default);
|
||||
const FuncExpr *when() const { return attrs_->cond(); }
|
||||
// SDF IOPATHs match sdfCond.
|
||||
// sdfCond (IOPATH) reuses sdfCondStart (timing check) variable.
|
||||
const std::string &sdfCond() const { return attrs_->sdfCondStart(); }
|
||||
|
|
@ -249,7 +251,7 @@ public:
|
|||
TimingArcSet *set() const { return set_; }
|
||||
TimingSense sense() const;
|
||||
// Index in TimingArcSet.
|
||||
unsigned index() const { return index_; }
|
||||
size_t index() const { return index_; }
|
||||
TimingModel *model() const { return model_; }
|
||||
GateTimingModel *gateModel(const Scene *scene,
|
||||
const MinMax *min_max) const;
|
||||
|
|
@ -270,7 +272,7 @@ public:
|
|||
protected:
|
||||
TimingModel *model(const Scene *scene,
|
||||
const MinMax *min_max) const;
|
||||
void setIndex(unsigned index);
|
||||
void setIndex(size_t index);
|
||||
void addScaledModel(const OperatingConditions *op_cond,
|
||||
TimingModel *scaled_model);
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ public:
|
|||
[[nodiscard]] bool isNonSeqTimingCheck() const { return is_non_seq_check_; }
|
||||
[[nodiscard]] bool isDataCheck() const;
|
||||
[[nodiscard]] bool isLatchDtoQ() const;
|
||||
[[nodiscard]] bool isLatchEnToQ() const;
|
||||
const TimingRole *genericRole() const;
|
||||
const TimingRole *sdfRole() const;
|
||||
// Timing check data path min/max.
|
||||
|
|
|
|||
|
|
@ -1,52 +0,0 @@
|
|||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2025, Parallax Software, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
// The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software.
|
||||
//
|
||||
// Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace sta {
|
||||
|
||||
// Iterate over the tokens in str separated by character sep.
|
||||
// Similar in functionality to strtok, but does not leave the string
|
||||
// side-effected. This is preferable to using strtok because it leaves
|
||||
// string terminators where the separators were.
|
||||
// Using STL string functions to parse tokens is messy and extremely slow
|
||||
// on the RogueWave/Solaris implementation, apparently because of mutexes
|
||||
// on temporary strings.
|
||||
class TokenParser
|
||||
{
|
||||
public:
|
||||
TokenParser(const char *str,
|
||||
const char *delimiters);
|
||||
bool hasNext();
|
||||
char *next();
|
||||
|
||||
private:
|
||||
const char *delimiters_;
|
||||
char *token_;
|
||||
char *token_end_;
|
||||
char token_delimiter_;
|
||||
bool first_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
@ -48,7 +48,7 @@ public:
|
|||
static const RiseFall *fall() { return &fall_; }
|
||||
static int riseIndex() { return rise_.sdf_triple_index_; }
|
||||
static int fallIndex() { return fall_.sdf_triple_index_; }
|
||||
const std::string &to_string() const { return short_name_; }
|
||||
const std::string &to_string(bool use_short = false) const;
|
||||
const char *name() const { return name_.c_str(); }
|
||||
const char *shortName() const { return short_name_.c_str(); }
|
||||
int index() const { return sdf_triple_index_; }
|
||||
|
|
@ -93,7 +93,7 @@ public:
|
|||
static const RiseFallBoth *rise() { return &rise_; }
|
||||
static const RiseFallBoth *fall() { return &fall_; }
|
||||
static const RiseFallBoth *riseFall() { return &rise_fall_; }
|
||||
const std::string &to_string() const { return short_name_; }
|
||||
const std::string &to_string(bool use_short = false) const;
|
||||
const char *name() const { return name_.c_str(); }
|
||||
const char *shortName() const { return short_name_.c_str(); }
|
||||
int index() const { return sdf_triple_index_; }
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "StringSet.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "NetworkClass.hh"
|
||||
|
||||
namespace sta {
|
||||
|
|
@ -173,7 +173,7 @@ protected:
|
|||
void makeNamedPortRefCellPorts(Cell *cell,
|
||||
VerilogModule *module,
|
||||
VerilogNet *mod_port,
|
||||
StdStringSet &port_names);
|
||||
StringSet &port_names);
|
||||
void checkModuleDcls(VerilogModule *module,
|
||||
std::set<std::string> &port_names);
|
||||
void makeModuleInstBody(VerilogModule *module,
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::max;
|
||||
|
||||
static unsigned
|
||||
hashCell(const LibertyCell *cell);
|
||||
static unsigned
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
FuncExpr *
|
||||
FuncExpr::makePort(LibertyPort *port)
|
||||
{
|
||||
|
|
@ -199,20 +197,20 @@ FuncExpr::portTimingSense(const LibertyPort *port) const
|
|||
return TimingSense::unknown;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
FuncExpr::to_string() const
|
||||
{
|
||||
return to_string(false);
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
FuncExpr::to_string(bool with_parens) const
|
||||
{
|
||||
switch (op_) {
|
||||
case Op::port:
|
||||
return port_->name();
|
||||
case Op::not_: {
|
||||
string result = "!";
|
||||
std::string result = "!";
|
||||
result += left_ ? left_->to_string(true) : "?";
|
||||
return result;
|
||||
}
|
||||
|
|
@ -231,12 +229,12 @@ FuncExpr::to_string(bool with_parens) const
|
|||
}
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
FuncExpr::to_string(bool with_parens,
|
||||
char op) const
|
||||
{
|
||||
string right = right_->to_string(true);
|
||||
string result;
|
||||
std::string right = right_->to_string(true);
|
||||
std::string result;
|
||||
if (with_parens)
|
||||
result += '(';
|
||||
result += left_ ? left_->to_string(true) : "?";
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace sta {
|
|||
|
||||
FuncExpr *
|
||||
parseFuncExpr(const char *func,
|
||||
LibertyCell *cell,
|
||||
const LibertyCell *cell,
|
||||
const char *error_msg,
|
||||
Report *report)
|
||||
{
|
||||
|
|
@ -56,7 +56,7 @@ parseFuncExpr(const char *func,
|
|||
}
|
||||
|
||||
LibExprReader::LibExprReader(const char *func,
|
||||
LibertyCell *cell,
|
||||
const LibertyCell *cell,
|
||||
const char *error_msg,
|
||||
Report *report) :
|
||||
func_(func),
|
||||
|
|
@ -69,7 +69,7 @@ LibExprReader::LibExprReader(const char *func,
|
|||
|
||||
// defined in LibertyReader.cc
|
||||
LibertyPort *
|
||||
libertyReaderFindPort(LibertyCell *cell,
|
||||
libertyReaderFindPort(const LibertyCell *cell,
|
||||
const char *port_name);
|
||||
|
||||
FuncExpr *
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class LibertyCell;
|
|||
|
||||
FuncExpr *
|
||||
parseFuncExpr(const char *func,
|
||||
LibertyCell *cell,
|
||||
const LibertyCell *cell,
|
||||
const char *error_msg,
|
||||
Report *report);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class LibExprReader
|
|||
{
|
||||
public:
|
||||
LibExprReader(const char *func,
|
||||
LibertyCell *cell,
|
||||
const LibertyCell *cell,
|
||||
const char *error_msg,
|
||||
Report *report);
|
||||
FuncExpr *makeFuncExprPort(const char *port_name);
|
||||
|
|
@ -55,7 +55,7 @@ public:
|
|||
|
||||
private:
|
||||
const char *func_;
|
||||
LibertyCell *cell_;
|
||||
const LibertyCell *cell_;
|
||||
const char *error_msg_;
|
||||
Report *report_;
|
||||
FuncExpr *result_;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include "Debug.hh"
|
||||
#include "Error.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "StringSet.hh"
|
||||
#include "PatternMatch.hh"
|
||||
#include "Units.hh"
|
||||
#include "Transition.hh"
|
||||
|
|
@ -50,8 +49,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
void
|
||||
initLiberty()
|
||||
{
|
||||
|
|
@ -111,8 +108,6 @@ LibertyLibrary::LibertyLibrary(const char *name,
|
|||
|
||||
LibertyLibrary::~LibertyLibrary()
|
||||
{
|
||||
delete scale_factors_;
|
||||
|
||||
for (auto rf_index : RiseFall::rangeIndex()) {
|
||||
TableModel *model = wire_slew_degradation_tbls_[rf_index];
|
||||
delete model;
|
||||
|
|
@ -271,14 +266,14 @@ LibertyLibrary::setScaleFactors(ScaleFactors *scales)
|
|||
ScaleFactors *
|
||||
LibertyLibrary::makeScaleFactors(const char *name)
|
||||
{
|
||||
auto [it, inserted] = scale_factors_map_.emplace(std::string(name), name);
|
||||
auto [it, inserted] = scale_factors_map_.emplace(name, name);
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
ScaleFactors *
|
||||
LibertyLibrary::findScaleFactors(const char *name)
|
||||
{
|
||||
return findKeyValuePtr(scale_factors_map_, std::string(name));
|
||||
return findKeyValuePtr(scale_factors_map_, name);
|
||||
}
|
||||
|
||||
float
|
||||
|
|
@ -400,20 +395,20 @@ LibertyLibrary::degradeWireSlew(const TableModel *model,
|
|||
// Check for supported axis variables.
|
||||
// Return true if axes are supported.
|
||||
bool
|
||||
LibertyLibrary::checkSlewDegradationAxes(const TablePtr &table)
|
||||
LibertyLibrary::checkSlewDegradationAxes(const TableModel *table_model)
|
||||
{
|
||||
switch (table->order()) {
|
||||
switch (table_model->order()) {
|
||||
case 0:
|
||||
return true;
|
||||
case 1: {
|
||||
const TableAxis *axis1 = table->axis1();
|
||||
const TableAxis *axis1 = table_model->axis1();
|
||||
TableAxisVariable var1 = axis1->variable();
|
||||
return var1 == TableAxisVariable::output_pin_transition
|
||||
|| var1 == TableAxisVariable::connect_delay;
|
||||
}
|
||||
case 2: {
|
||||
const TableAxis *axis1 = table->axis1();
|
||||
const TableAxis *axis2 = table->axis2();
|
||||
const TableAxis *axis1 = table_model->axis1();
|
||||
const TableAxis *axis2 = table_model->axis2();
|
||||
TableAxisVariable var1 = axis1->variable();
|
||||
TableAxisVariable var2 = axis2->variable();
|
||||
return (var1 == TableAxisVariable::output_pin_transition
|
||||
|
|
@ -1269,8 +1264,7 @@ LibertyCell::makeInternalPower(LibertyPort *port,
|
|||
const std::shared_ptr<FuncExpr> &when,
|
||||
InternalPowerModels &models)
|
||||
{
|
||||
internal_powers_.emplace_back(port, related_port, related_pg_pin,
|
||||
when, models);
|
||||
internal_powers_.emplace_back(port, related_port, related_pg_pin, when, models);
|
||||
port_internal_powers_[port].push_back(internal_powers_.size() - 1);
|
||||
}
|
||||
|
||||
|
|
@ -1372,17 +1366,14 @@ LibertyCell::makeTimingArcPortMaps()
|
|||
LibertyPort *from = arc_set->from();
|
||||
LibertyPort *to = arc_set->to();
|
||||
if (from && to) {
|
||||
LibertyPortPair from_to_pair(from, to);
|
||||
TimingArcSetSeq &sets = port_timing_arc_set_map_[from_to_pair];
|
||||
TimingArcSetSeq &sets = port_timing_arc_set_map_[{from, to}];
|
||||
sets.push_back(arc_set);
|
||||
}
|
||||
|
||||
LibertyPortPair from_pair(from, nullptr);
|
||||
TimingArcSetSeq &from_sets = port_timing_arc_set_map_[from_pair];
|
||||
TimingArcSetSeq &from_sets = port_timing_arc_set_map_[{from, nullptr}];
|
||||
from_sets.push_back(arc_set);
|
||||
|
||||
LibertyPortPair to_pair(nullptr, to);
|
||||
TimingArcSetSeq &to_sets = port_timing_arc_set_map_[to_pair];
|
||||
TimingArcSetSeq &to_sets = port_timing_arc_set_map_[{nullptr, to}];
|
||||
to_sets.push_back(arc_set);
|
||||
|
||||
const TimingRole *role = arc_set->role();
|
||||
|
|
@ -1416,8 +1407,7 @@ LibertyCell::timingArcSets(const LibertyPort *from,
|
|||
const LibertyPort *to) const
|
||||
{
|
||||
static const TimingArcSetSeq null_set;
|
||||
const LibertyPortPair port_pair(from, to);
|
||||
auto itr = port_timing_arc_set_map_.find(port_pair);
|
||||
auto itr = port_timing_arc_set_map_.find({from, to});
|
||||
return (itr == port_timing_arc_set_map_.end()) ? null_set : itr->second;
|
||||
}
|
||||
|
||||
|
|
@ -1442,8 +1432,8 @@ LibertyCell::timingArcSetCount() const
|
|||
bool
|
||||
LibertyCell::hasTimingArcs(LibertyPort *port) const
|
||||
{
|
||||
return port_timing_arc_set_map_.contains(LibertyPortPair(port, nullptr))
|
||||
|| port_timing_arc_set_map_.contains(LibertyPortPair(nullptr, port));
|
||||
return port_timing_arc_set_map_.contains({port, nullptr})
|
||||
|| port_timing_arc_set_map_.contains({nullptr, port});
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1485,6 +1475,10 @@ LibertyCell::makeSequential(int size,
|
|||
port_to_seq_map_[sequentials_.back().output()] = idx;
|
||||
port_to_seq_map_[sequentials_.back().outputInv()] = idx;
|
||||
}
|
||||
delete clk;
|
||||
delete data;
|
||||
delete clear;
|
||||
delete preset;
|
||||
}
|
||||
|
||||
Sequential *
|
||||
|
|
@ -1680,45 +1674,58 @@ LibertyCell::makeLatchEnables(Report *report,
|
|||
{
|
||||
if (hasSequentials()
|
||||
|| hasInferedRegTimingArcs()) {
|
||||
for (auto en_to_q : timing_arc_sets_) {
|
||||
if (en_to_q->role() == TimingRole::latchEnToQ()) {
|
||||
LibertyPort *en = en_to_q->from();
|
||||
LibertyPort *q = en_to_q->to();
|
||||
for (TimingArcSet *d_to_q : timingArcSetsTo(q)) {
|
||||
if (d_to_q->role() == TimingRole::latchDtoQ()
|
||||
&& condMatch(en_to_q, d_to_q)) {
|
||||
LibertyPort *d = d_to_q->from();
|
||||
const RiseFall *en_rf = en_to_q->isRisingFallingEdge();
|
||||
if (en_rf) {
|
||||
TimingArcSet *setup_check = findLatchSetup(d, en, en_rf, q, d_to_q,
|
||||
report);
|
||||
LatchEnable *latch_enable = makeLatchEnable(d, en, en_rf, q, d_to_q,
|
||||
en_to_q,
|
||||
setup_check,
|
||||
debug);
|
||||
FuncExpr *en_func = latch_enable->enableFunc();
|
||||
if (en_func) {
|
||||
TimingSense en_sense = en_func->portTimingSense(en);
|
||||
if (en_sense == TimingSense::positive_unate
|
||||
&& en_rf != RiseFall::rise())
|
||||
report->warn(1114, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function positive sense.",
|
||||
library_->name(),
|
||||
name(),
|
||||
en->name(),
|
||||
q->name(),
|
||||
en_rf == RiseFall::rise()?"rising":"falling");
|
||||
else if (en_sense == TimingSense::negative_unate
|
||||
&& en_rf != RiseFall::fall())
|
||||
report->warn(1115, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function negative sense.",
|
||||
library_->name(),
|
||||
name(),
|
||||
en->name(),
|
||||
q->name(),
|
||||
en_rf == RiseFall::rise()?"rising":"falling");
|
||||
}
|
||||
for (TimingArcSet *d_to_q : timing_arc_sets_) {
|
||||
if (d_to_q->role() == TimingRole::latchDtoQ()) {
|
||||
LibertyPort *d = d_to_q->from();
|
||||
LibertyPort *q = d_to_q->to();
|
||||
TimingArcSet *en_to_q = nullptr;
|
||||
TimingArcSet *en_to_q_when = nullptr;
|
||||
// Prefer en_to_q with matching when.
|
||||
for (TimingArcSet *arc_to_q : timingArcSetsTo(q)) {
|
||||
if (arc_to_q->role() == TimingRole::latchEnToQ()) {
|
||||
if (condMatch(arc_to_q, d_to_q))
|
||||
en_to_q_when = arc_to_q;
|
||||
else
|
||||
en_to_q = arc_to_q;
|
||||
}
|
||||
}
|
||||
if (en_to_q_when)
|
||||
en_to_q = en_to_q_when;
|
||||
if (en_to_q) {
|
||||
LibertyPort *en = en_to_q->from();
|
||||
const RiseFall *en_rf = en_to_q->isRisingFallingEdge();
|
||||
if (en_rf) {
|
||||
TimingArcSet *setup_check = findLatchSetup(d, en, en_rf, q, d_to_q, report);
|
||||
LatchEnable *latch_enable = makeLatchEnable(d, en, en_rf, q, d_to_q,
|
||||
en_to_q, setup_check, debug);
|
||||
FuncExpr *en_func = latch_enable->enableFunc();
|
||||
if (en_func) {
|
||||
TimingSense en_sense = en_func->portTimingSense(en);
|
||||
if (en_sense == TimingSense::positive_unate
|
||||
&& en_rf != RiseFall::rise())
|
||||
report->warn(1114, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function positive sense.",
|
||||
library_->name(),
|
||||
name(),
|
||||
en->name(),
|
||||
q->name(),
|
||||
en_rf == RiseFall::rise()?"rising":"falling");
|
||||
else if (en_sense == TimingSense::negative_unate
|
||||
&& en_rf != RiseFall::fall())
|
||||
report->warn(1115, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function negative sense.",
|
||||
library_->name(),
|
||||
name(),
|
||||
en->name(),
|
||||
q->name(),
|
||||
en_rf == RiseFall::rise()?"rising":"falling");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
report->warn(1121, "cell %s/%s no latch enable found for %s -> %s.",
|
||||
library_->name(),
|
||||
name(),
|
||||
d->name(),
|
||||
q->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1811,8 +1818,7 @@ LibertyCell::makeLatchEnable(LibertyPort *d,
|
|||
Debug *debug)
|
||||
{
|
||||
FuncExpr *en_func = findLatchEnableFunc(d, en, en_rf);
|
||||
latch_enables_.emplace_back(d, en, en_rf, en_func, q, d_to_q, en_to_q,
|
||||
setup_check);
|
||||
latch_enables_.emplace_back(d, en, en_rf, en_func, q, d_to_q, en_to_q, setup_check);
|
||||
size_t idx = latch_enables_.size() - 1;
|
||||
latch_d_to_q_map_[d_to_q] = idx;
|
||||
latch_check_map_[setup_check] = idx;
|
||||
|
|
@ -2703,13 +2709,13 @@ LibertyPort::setReceiverModel(ReceiverModelPtr receiver_model)
|
|||
receiver_model_ = receiver_model;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
portLibertyToSta(const char *port_name)
|
||||
{
|
||||
constexpr char bus_brkt_left = '[';
|
||||
constexpr char bus_brkt_right = ']';
|
||||
size_t name_length = strlen(port_name);
|
||||
string sta_name;
|
||||
std::string sta_name;
|
||||
for (size_t i = 0; i < name_length; i++) {
|
||||
char ch = port_name[i];
|
||||
if (ch == bus_brkt_left
|
||||
|
|
@ -2735,33 +2741,6 @@ LibertyPort::setDriverWaveform(DriverWaveform *driver_waveform,
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
RiseFallMinMax
|
||||
LibertyPort::clockTreePathDelays() const
|
||||
{
|
||||
return clkTreeDelays1();
|
||||
}
|
||||
|
||||
RiseFallMinMax
|
||||
LibertyPort::clkTreeDelays() const
|
||||
{
|
||||
return clkTreeDelays1();
|
||||
}
|
||||
|
||||
RiseFallMinMax
|
||||
LibertyPort::clkTreeDelays1() const
|
||||
{
|
||||
RiseFallMinMax delays;
|
||||
for (const RiseFall *from_rf : RiseFall::range()) {
|
||||
for (const RiseFall *to_rf : RiseFall::range()) {
|
||||
for (const MinMax *min_max : MinMax::range()) {
|
||||
float delay = clkTreeDelay(0.0, from_rf, to_rf, min_max);
|
||||
delays.setValue(from_rf, min_max, delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
return delays;
|
||||
}
|
||||
|
||||
float
|
||||
LibertyPort::clkTreeDelay(float in_slew,
|
||||
const RiseFall *rf,
|
||||
|
|
@ -3087,7 +3066,8 @@ OperatingConditions::setWireloadTree(WireloadTree tree)
|
|||
|
||||
static EnumNameMap<ScaleFactorType> scale_factor_type_map =
|
||||
{{ScaleFactorType::pin_cap, "pin_cap"},
|
||||
{ScaleFactorType::wire_cap, "wire_res"},
|
||||
{ScaleFactorType::wire_cap, "wire_cap"},
|
||||
{ScaleFactorType::wire_res, "wire_res"},
|
||||
{ScaleFactorType::min_period, "min_period"},
|
||||
{ScaleFactorType::cell, "cell"},
|
||||
{ScaleFactorType::hold, "hold"},
|
||||
|
|
@ -3124,7 +3104,9 @@ scaleFactorTypeRiseFallSuffix(ScaleFactorType type)
|
|||
|| type == ScaleFactorType::recovery
|
||||
|| type == ScaleFactorType::removal
|
||||
|| type == ScaleFactorType::nochange
|
||||
|| type == ScaleFactorType::skew;
|
||||
|| type == ScaleFactorType::skew
|
||||
|| type == ScaleFactorType::leakage_power
|
||||
|| type == ScaleFactorType::internal_power;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -3144,7 +3126,8 @@ scaleFactorTypeLowHighSuffix(ScaleFactorType type)
|
|||
EnumNameMap<ScaleFactorPvt> scale_factor_pvt_names =
|
||||
{{ScaleFactorPvt::process, "process"},
|
||||
{ScaleFactorPvt::volt, "volt"},
|
||||
{ScaleFactorPvt::temp, "temp"}
|
||||
{ScaleFactorPvt::temp, "temp"},
|
||||
{ScaleFactorPvt::unknown, "unknown"}
|
||||
};
|
||||
|
||||
ScaleFactorPvt
|
||||
|
|
@ -3214,31 +3197,32 @@ ScaleFactors::scale(ScaleFactorType type,
|
|||
}
|
||||
|
||||
void
|
||||
ScaleFactors::print()
|
||||
ScaleFactors::report(Report *report)
|
||||
{
|
||||
printf("%10s", " ");
|
||||
std::string line = " ";
|
||||
for (int pvt_index = 0; pvt_index < scale_factor_pvt_count; pvt_index++) {
|
||||
ScaleFactorPvt pvt = (ScaleFactorPvt) pvt_index;
|
||||
printf("%10s", scaleFactorPvtName(pvt));
|
||||
stringAppend(line, "%10s", scaleFactorPvtName(pvt));
|
||||
}
|
||||
printf("\n");
|
||||
report->reportLineString(line);
|
||||
|
||||
for (int type_index = 0; type_index < scale_factor_type_count; type_index++) {
|
||||
ScaleFactorType type = (ScaleFactorType) type_index;
|
||||
printf("%10s ", scaleFactorTypeName(type));
|
||||
stringPrint(line, "%10s ", scaleFactorTypeName(type));
|
||||
for (int pvt_index = 0; pvt_index < scale_factor_pvt_count; pvt_index++) {
|
||||
if (scaleFactorTypeRiseFallSuffix(type)
|
||||
|| scaleFactorTypeRiseFallPrefix(type)
|
||||
|| scaleFactorTypeLowHighSuffix(type)) {
|
||||
printf(" %.3f,%.3f",
|
||||
scales_[type_index][pvt_index][RiseFall::riseIndex()],
|
||||
scales_[type_index][pvt_index][RiseFall::fallIndex()]);
|
||||
stringAppend(line, " %.3f,%.3f",
|
||||
scales_[type_index][pvt_index][RiseFall::riseIndex()],
|
||||
scales_[type_index][pvt_index][RiseFall::fallIndex()]);
|
||||
}
|
||||
else {
|
||||
printf(" %.3f",
|
||||
scales_[type_index][pvt_index][0]);
|
||||
stringAppend(line, " %.3f",
|
||||
scales_[type_index][pvt_index][0]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
report->reportLineString(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -363,6 +363,7 @@ scan_signal_type()
|
|||
%extend TimingArcSet {
|
||||
LibertyPort *from() { return self->from(); }
|
||||
LibertyPort *to() { return self->to(); }
|
||||
std::string to_string() { return self->to_string(); }
|
||||
const TimingRole *role() { return self->role(); }
|
||||
const char *sdf_cond() { return self->sdfCond().c_str(); }
|
||||
|
||||
|
|
@ -378,6 +379,16 @@ full_name()
|
|||
to);
|
||||
}
|
||||
|
||||
const std::string
|
||||
when()
|
||||
{
|
||||
const FuncExpr *when = self->when();
|
||||
if (when)
|
||||
return when->to_string();
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
TimingArcSeq &
|
||||
timing_arcs() { return self->arcs(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,11 @@ proc report_lib_cell_ { cell scene } {
|
|||
if { $filename != "" } {
|
||||
report_line "File $filename"
|
||||
}
|
||||
report_lib_ports $cell $scene
|
||||
report_timing_arcs $cell
|
||||
}
|
||||
|
||||
proc report_lib_ports { cell scene } {
|
||||
set iter [$cell liberty_port_iterator]
|
||||
while {[$iter has_next]} {
|
||||
set port [$iter next]
|
||||
|
|
@ -115,5 +120,24 @@ proc report_lib_port { port scene } {
|
|||
report_line " ${indent}$port_name [liberty_port_direction $port]$enable$func[port_capacitance_str $port $scene $sta_report_default_digits]"
|
||||
}
|
||||
|
||||
proc report_timing_arcs { cell } {
|
||||
set timing_arcs [$cell timing_arc_sets]
|
||||
if { [llength $timing_arcs] > 0 } {
|
||||
puts ""
|
||||
puts "Timing arcs"
|
||||
foreach timing_arc $timing_arcs {
|
||||
puts " [$timing_arc to_string]"
|
||||
puts " [$timing_arc role]"
|
||||
set when [$timing_arc when]
|
||||
if { $when != "" } {
|
||||
puts " when $when"
|
||||
}
|
||||
foreach arc [$timing_arc timing_arcs] {
|
||||
puts " [$arc from_edge] -> [$arc to_edge]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# sta namespace end
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,14 +35,11 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
void
|
||||
LibertyBuilder::init(Debug *debug,
|
||||
Report *report)
|
||||
LibertyBuilder::LibertyBuilder(Debug *debug,
|
||||
Report *report) :
|
||||
debug_(debug),
|
||||
report_(report)
|
||||
{
|
||||
debug_ = debug;
|
||||
report_ = report;
|
||||
}
|
||||
|
||||
LibertyCell *
|
||||
|
|
@ -105,7 +102,7 @@ LibertyBuilder::makeBusPortBit(ConcreteLibrary *library,
|
|||
const char *bus_name,
|
||||
int bit_index)
|
||||
{
|
||||
string bit_name;
|
||||
std::string bit_name;
|
||||
stringPrint(bit_name, "%s%c%d%c",
|
||||
bus_name,
|
||||
library->busBrktLeft(),
|
||||
|
|
@ -189,6 +186,7 @@ LibertyBuilder::makeTimingArcs(LibertyCell *cell,
|
|||
case TimingType::combinational:
|
||||
if (seq
|
||||
&& seq->isLatch()
|
||||
&& seq->data()
|
||||
&& seq->data()->hasPort(from_port))
|
||||
// Latch D->Q timing arcs.
|
||||
return makeLatchDtoQArcs(cell, from_port, to_port,
|
||||
|
|
@ -307,8 +305,9 @@ LibertyBuilder::makeCombinationalArcs(LibertyCell *cell,
|
|||
{
|
||||
FuncExpr *func = to_port->function();
|
||||
FuncExpr *enable = to_port->tristateEnable();
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
|
||||
TimingRole::combinational(), attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(from_port, to_port, nullptr,
|
||||
TimingRole::combinational(),
|
||||
attrs);
|
||||
TimingSense sense = attrs->timingSense();
|
||||
if (sense == TimingSense::unknown) {
|
||||
// Timing sense not specified - find it from function.
|
||||
|
|
@ -388,8 +387,9 @@ LibertyBuilder::makeLatchDtoQArcs(LibertyCell *cell,
|
|||
TimingSense sense,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
|
||||
TimingRole::latchDtoQ(), attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(from_port, to_port, nullptr,
|
||||
TimingRole::latchDtoQ(),
|
||||
attrs);
|
||||
TimingModel *model;
|
||||
const RiseFall *to_rf = RiseFall::rise();
|
||||
model = attrs->model(to_rf);
|
||||
|
|
@ -456,8 +456,8 @@ LibertyBuilder::makeFromTransitionArcs(LibertyCell *cell,
|
|||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
|
||||
related_out, role, attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(from_port, to_port,
|
||||
related_out, role, attrs);
|
||||
for (auto to_rf : RiseFall::range()) {
|
||||
TimingModel *model = attrs->model(to_rf);
|
||||
if (model)
|
||||
|
|
@ -476,8 +476,8 @@ LibertyBuilder::makePresetClrArcs(LibertyCell *cell,
|
|||
TimingArcSet *arc_set = nullptr;
|
||||
TimingModel *model = attrs->model(to_rf);
|
||||
if (model) {
|
||||
arc_set = makeTimingArcSet(cell, from_port, to_port,
|
||||
TimingRole::regSetClr(), attrs);
|
||||
arc_set = cell->makeTimingArcSet(from_port, to_port, nullptr,
|
||||
TimingRole::regSetClr(), attrs);
|
||||
const RiseFall *opp_rf = to_rf->opposite();
|
||||
switch (attrs->timingSense()) {
|
||||
case TimingSense::positive_unate:
|
||||
|
|
@ -509,8 +509,9 @@ LibertyBuilder::makeTristateEnableArcs(LibertyCell *cell,
|
|||
bool to_fall,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
|
||||
TimingRole::tristateEnable(), attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(from_port, to_port, nullptr,
|
||||
TimingRole::tristateEnable(),
|
||||
attrs);
|
||||
FuncExpr *tristate_enable = to_port->tristateEnable();
|
||||
TimingSense sense = attrs->timingSense();
|
||||
if (sense == TimingSense::unknown && tristate_enable)
|
||||
|
|
@ -579,9 +580,9 @@ LibertyBuilder::makeTristateDisableArcs(LibertyCell *cell,
|
|||
bool to_fall,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
|
||||
TimingRole::tristateDisable(),
|
||||
attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(from_port, to_port, nullptr,
|
||||
TimingRole::tristateDisable(),
|
||||
attrs);
|
||||
TimingSense sense = attrs->timingSense();
|
||||
FuncExpr *tristate_enable = to_port->tristateEnable();
|
||||
if (sense == TimingSense::unknown && tristate_enable)
|
||||
|
|
@ -648,7 +649,8 @@ LibertyBuilder::makeClockTreePathArcs(LibertyCell *cell,
|
|||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, nullptr, to_port, role, attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(nullptr, to_port, nullptr,
|
||||
role, attrs);
|
||||
for (const RiseFall *to_rf : RiseFall::range()) {
|
||||
TimingModel *model = attrs->model(to_rf);
|
||||
if (model) {
|
||||
|
|
@ -683,8 +685,8 @@ LibertyBuilder::makeMinPulseWidthArcs(LibertyCell *cell,
|
|||
{
|
||||
if (from_port == nullptr)
|
||||
from_port = to_port;
|
||||
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port, related_out,
|
||||
role, attrs);
|
||||
TimingArcSet *arc_set = cell->makeTimingArcSet(from_port, to_port, related_out,
|
||||
role, attrs);
|
||||
for (const RiseFall *from_rf : RiseFall::range()) {
|
||||
TimingModel *model = attrs->model(from_rf);
|
||||
if (model)
|
||||
|
|
@ -695,27 +697,6 @@ LibertyBuilder::makeMinPulseWidthArcs(LibertyCell *cell,
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
TimingArcSet *
|
||||
LibertyBuilder::makeTimingArcSet(LibertyCell *cell,
|
||||
LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
return cell->makeTimingArcSet(from, to, nullptr, role, attrs);
|
||||
}
|
||||
|
||||
TimingArcSet *
|
||||
LibertyBuilder::makeTimingArcSet(LibertyCell *cell,
|
||||
LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
LibertyPort *related_out,
|
||||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
return cell->makeTimingArcSet(from, to, related_out, role, attrs);
|
||||
}
|
||||
|
||||
TimingArc *
|
||||
LibertyBuilder::makeTimingArc(TimingArcSet *set,
|
||||
const RiseFall *from_rf,
|
||||
|
|
|
|||
|
|
@ -38,23 +38,21 @@ class Report;
|
|||
class LibertyBuilder
|
||||
{
|
||||
public:
|
||||
LibertyBuilder() {}
|
||||
virtual ~LibertyBuilder() {}
|
||||
void init(Debug *debug,
|
||||
Report *report);
|
||||
virtual LibertyCell *makeCell(LibertyLibrary *library,
|
||||
const char *name,
|
||||
const char *filename);
|
||||
virtual LibertyPort *makePort(LibertyCell *cell,
|
||||
const char *name);
|
||||
virtual LibertyPort *makeBusPort(LibertyCell *cell,
|
||||
const char *bus_name,
|
||||
int from_index,
|
||||
int to_index,
|
||||
BusDcl *bus_dcl);
|
||||
virtual LibertyPort *makeBundlePort(LibertyCell *cell,
|
||||
const char *name,
|
||||
ConcretePortSeq *members);
|
||||
LibertyBuilder(Debug *debug,
|
||||
Report *report);
|
||||
LibertyCell *makeCell(LibertyLibrary *library,
|
||||
const char *name,
|
||||
const char *filename);
|
||||
LibertyPort *makePort(LibertyCell *cell,
|
||||
const char *name);
|
||||
LibertyPort *makeBusPort(LibertyCell *cell,
|
||||
const char *bus_name,
|
||||
int from_index,
|
||||
int to_index,
|
||||
BusDcl *bus_dcl);
|
||||
LibertyPort *makeBundlePort(LibertyCell *cell,
|
||||
const char *name,
|
||||
ConcretePortSeq *members);
|
||||
// Build timing arc sets and their arcs given a type and sense.
|
||||
// Port functions and cell latches are also used by this builder
|
||||
// to get the correct roles.
|
||||
|
|
@ -100,29 +98,18 @@ protected:
|
|||
int from_index,
|
||||
int to_index);
|
||||
// Bus port bit (internal to makeBusPortBits).
|
||||
virtual LibertyPort *makePort(LibertyCell *cell,
|
||||
const char *bit_name,
|
||||
int bit_index);
|
||||
LibertyPort *makePort(LibertyCell *cell,
|
||||
const char *bit_name,
|
||||
int bit_index);
|
||||
void makeBusPortBit(ConcreteLibrary *library,
|
||||
LibertyCell *cell,
|
||||
ConcretePort *bus_port,
|
||||
const char *bus_name,
|
||||
int index);
|
||||
virtual TimingArcSet *makeTimingArcSet(LibertyCell *cell,
|
||||
LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs);
|
||||
virtual TimingArcSet *makeTimingArcSet(LibertyCell *cell,
|
||||
LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
LibertyPort *related_out,
|
||||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs);
|
||||
virtual TimingArc *makeTimingArc(TimingArcSet *set,
|
||||
const Transition *from_rf,
|
||||
const Transition *to_rf,
|
||||
TimingModel *model);
|
||||
TimingArc *makeTimingArc(TimingArcSet *set,
|
||||
const Transition *from_rf,
|
||||
const Transition *to_rf,
|
||||
TimingModel *model);
|
||||
TimingArc *makeTimingArc(TimingArcSet *set,
|
||||
const RiseFall *from_rf,
|
||||
const RiseFall *to_rf,
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ using sta::Report;
|
|||
using sta::Debug;
|
||||
using sta::Network;
|
||||
using sta::LibertyReader;
|
||||
using sta::LibertyAttr;
|
||||
using sta::LibertyGroup;
|
||||
using sta::LibertySimpleAttr;
|
||||
using sta::TimingGroup;
|
||||
using sta::LibertyCell;
|
||||
using sta::LibertyPort;
|
||||
|
|
@ -164,13 +164,6 @@ class BigcoLibertyBuilder : public LibertyBuilder
|
|||
public:
|
||||
virtual LibertyCell *makeCell(LibertyLibrary *library, const char *name,
|
||||
const char *filename);
|
||||
|
||||
protected:
|
||||
virtual TimingArcSet *makeTimingArcSet(LibertyCell *cell, LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
LibertyPort *related_out,
|
||||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs) override;
|
||||
};
|
||||
|
||||
LibertyCell *
|
||||
|
|
@ -182,16 +175,6 @@ BigcoLibertyBuilder::makeCell(LibertyLibrary *library, const char *name,
|
|||
return cell;
|
||||
}
|
||||
|
||||
TimingArcSet *
|
||||
BigcoLibertyBuilder::makeTimingArcSet(LibertyCell *cell, LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
LibertyPort *related_out,
|
||||
const TimingRole *role,
|
||||
TimingArcAttrsPtr attrs)
|
||||
{
|
||||
return cell->makeTimingArcSet(from, to, related_out, role, attrs);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Liberty reader to parse Bigco attributes.
|
||||
|
|
@ -201,22 +184,18 @@ public:
|
|||
BigcoLibertyReader(LibertyBuilder *builder);
|
||||
|
||||
protected:
|
||||
virtual void visitAttr1(LibertyAttr *attr);
|
||||
virtual void visitAttr2(LibertyAttr *attr);
|
||||
virtual void beginLibrary(LibertyGroup *group);
|
||||
virtual void visitAttr1(const LibertySimpleAttr *attr);
|
||||
virtual void visitAttr2(const LibertySimpleAttr *attr);
|
||||
virtual void beginLibrary(const LibertyGroup *group,
|
||||
const LibertyGroup *library_group);
|
||||
virtual TimingGroup *makeTimingGroup(int line);
|
||||
virtual void beginCell(LibertyGroup *group);
|
||||
virtual void beginCell(const LibertyGroup *group,
|
||||
const LibertyGroup *library_group);
|
||||
};
|
||||
|
||||
BigcoLibertyReader::BigcoLibertyReader(LibertyBuilder *builder) :
|
||||
LibertyReader(builder)
|
||||
{
|
||||
// Define a visitor for the "thingy" attribute.
|
||||
// Note that the function descriptor passed to defineAttrVisitor
|
||||
// must be defined by the LibertyVisitor class, so a number of
|
||||
// extra visitor functions are pre-defined for extensions.
|
||||
defineAttrVisitor("thingy", &LibertyReader::visitAttr1);
|
||||
defineAttrVisitor("frob", &LibertyReader::visitAttr2);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -228,12 +207,13 @@ libertyCellRequired(const char *)
|
|||
|
||||
// Prune cells from liberty file based on libertyCellRequired predicate.
|
||||
void
|
||||
BigcoLibertyReader::beginCell(LibertyGroup *group)
|
||||
BigcoLibertyReader::beginCell(const LibertyGroup *group,
|
||||
const LibertyGroup *library_group)
|
||||
{
|
||||
const char *name = group->firstName();
|
||||
if (name
|
||||
&& libertyCellRequired(name))
|
||||
LibertyReader::beginCell(group);
|
||||
LibertyReader::beginCell(group, library_group);
|
||||
}
|
||||
|
||||
TimingGroup *
|
||||
|
|
@ -244,15 +224,16 @@ BigcoLibertyReader::makeTimingGroup(int line)
|
|||
|
||||
// Called at the beginning of a library group.
|
||||
void
|
||||
BigcoLibertyReader::beginLibrary(LibertyGroup *group)
|
||||
BigcoLibertyReader::beginLibrary(const LibertyGroup *group,
|
||||
const LibertyGroup *library_group)
|
||||
{
|
||||
LibertyReader::beginLibrary(group);
|
||||
LibertyReader::beginLibrary(group, library_group);
|
||||
// Do Bigco stuff here.
|
||||
printf("Bigco was here.\n");
|
||||
}
|
||||
|
||||
void
|
||||
BigcoLibertyReader::visitAttr1(LibertyAttr *attr)
|
||||
BigcoLibertyReader::visitAttr1(const LibertySimpleAttr *attr)
|
||||
{
|
||||
const char *thingy = getAttrString(attr);
|
||||
if (thingy) {
|
||||
|
|
@ -263,7 +244,7 @@ BigcoLibertyReader::visitAttr1(LibertyAttr *attr)
|
|||
}
|
||||
|
||||
void
|
||||
BigcoLibertyReader::visitAttr2(LibertyAttr *attr)
|
||||
BigcoLibertyReader::visitAttr2(const LibertySimpleAttr *attr)
|
||||
{
|
||||
const char *frob = getAttrString(attr);
|
||||
if (frob) {
|
||||
|
|
|
|||
|
|
@ -87,14 +87,14 @@ EOL \r?\n
|
|||
{FLOAT}{TOKEN_END} {
|
||||
/* Push back the TOKEN_END character. */
|
||||
yyless(yyleng - 1);
|
||||
yylval->emplace<float>(strtod(yytext, nullptr));
|
||||
yylval->emplace<float>(strtof(yytext, nullptr));
|
||||
return token::FLOAT;
|
||||
}
|
||||
|
||||
{ALPHA}({ALPHA}|_|{DIGIT})*{TOKEN_END} {
|
||||
/* Push back the TOKEN_END character. */
|
||||
yyless(yyleng - 1);
|
||||
yylval->emplace<std::string>(yytext);
|
||||
yylval->emplace<std::string>(yytext, yyleng);
|
||||
return token::KEYWORD;
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ EOL \r?\n
|
|||
{TOKEN}{TOKEN_END} {
|
||||
/* Push back the TOKEN_END character. */
|
||||
yyless(yyleng - 1);
|
||||
yylval->emplace<std::string>(yytext);
|
||||
yylval->emplace<std::string>(yytext, yyleng);
|
||||
return token::STRING;
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ EOL \r?\n
|
|||
<qstring>{EOL} {
|
||||
error("unterminated string constant");
|
||||
BEGIN(INITIAL);
|
||||
yylval->emplace<std::string>(token_);
|
||||
yylval->emplace<std::string>(token_);
|
||||
return token::STRING;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ sta::LibertyParse::error(const location_type &loc,
|
|||
|
||||
%require "3.2"
|
||||
%skeleton "lalr1.cc"
|
||||
%debug
|
||||
//%debug
|
||||
%define api.namespace {sta}
|
||||
%locations
|
||||
%define api.location.file "LibertyLocation.hh"
|
||||
|
|
@ -72,7 +72,7 @@ sta::LibertyParse::error(const location_type &loc,
|
|||
%left '^'
|
||||
%left '!'
|
||||
|
||||
%type <sta::LibertyStmt *> statement complex_attr simple_attr variable group file
|
||||
%type <void *> statement complex_attr simple_attr variable group file
|
||||
%type <sta::LibertyAttrValueSeq *> attr_values
|
||||
%type <sta::LibertyAttrValue *> attr_value
|
||||
%type <std::string> string expr expr_term expr_term1 volt_expr
|
||||
|
|
@ -158,11 +158,11 @@ string:
|
|||
|
||||
attr_value:
|
||||
FLOAT
|
||||
{ $$ = reader->makeFloatAttrValue($1); }
|
||||
{ $$ = reader->makeAttrValueFloat($1); }
|
||||
| expr
|
||||
{ $$ = reader->makeStringAttrValue(std::move($1)); }
|
||||
{ $$ = reader->makeAttrValueString(std::move($1)); }
|
||||
| volt_expr
|
||||
{ $$ = reader->makeStringAttrValue(std::move($1)); }
|
||||
{ $$ = reader->makeAttrValueString(std::move($1)); }
|
||||
;
|
||||
|
||||
/* Voltage expressions are ignored. */
|
||||
|
|
|
|||
|
|
@ -37,8 +37,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
void
|
||||
parseLibertyFile(const char *filename,
|
||||
LibertyGroupVisitor *library_visitor,
|
||||
|
|
@ -65,26 +63,28 @@ LibertyParser::LibertyParser(const char *filename,
|
|||
}
|
||||
|
||||
void
|
||||
LibertyParser::setFilename(const string &filename)
|
||||
LibertyParser::setFilename(const std::string &filename)
|
||||
{
|
||||
filename_ = filename;
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
LibertyParser::makeDefine(LibertyAttrValueSeq *values,
|
||||
LibertyDefine *
|
||||
LibertyParser::makeDefine(const LibertyAttrValueSeq *values,
|
||||
int line)
|
||||
{
|
||||
LibertyDefine *define = nullptr;
|
||||
if (values->size() == 3) {
|
||||
std::string define_name = (*values)[0]->stringValue();
|
||||
const std::string &define_name = (*values)[0]->stringValue();
|
||||
const std::string &group_type_name = (*values)[1]->stringValue();
|
||||
const std::string &value_type_name = (*values)[2]->stringValue();
|
||||
LibertyAttrType value_type = attrValueType(value_type_name.c_str());
|
||||
LibertyGroupType group_type = groupType(group_type_name.c_str());
|
||||
define = new LibertyDefine(std::move(define_name), group_type,
|
||||
value_type, line);
|
||||
LibertyAttrType value_type = attrValueType(value_type_name);
|
||||
LibertyGroupType group_type = groupType(group_type_name);
|
||||
define = new LibertyDefine(std::move(define_name), group_type, value_type, line);
|
||||
LibertyGroup *group = this->group();
|
||||
group->addStmt(define);
|
||||
group->addDefine(define);
|
||||
for (auto value : *values)
|
||||
delete value;
|
||||
delete values;
|
||||
}
|
||||
else
|
||||
report_->fileWarn(24, filename_.c_str(), line,
|
||||
|
|
@ -96,42 +96,47 @@ LibertyParser::makeDefine(LibertyAttrValueSeq *values,
|
|||
// used to define valid attribute types. Beyond "string" these are
|
||||
// guesses.
|
||||
LibertyAttrType
|
||||
LibertyParser::attrValueType(const char *value_type_name)
|
||||
LibertyParser::attrValueType(const std::string &value_type_name)
|
||||
{
|
||||
if (stringEq(value_type_name, "string"))
|
||||
if (value_type_name == "string")
|
||||
return LibertyAttrType::attr_string;
|
||||
else if (stringEq(value_type_name, "integer"))
|
||||
else if (value_type_name == "integer")
|
||||
return LibertyAttrType::attr_int;
|
||||
else if (stringEq(value_type_name, "float"))
|
||||
else if (value_type_name == "float")
|
||||
return LibertyAttrType::attr_double;
|
||||
else if (stringEq(value_type_name, "boolean"))
|
||||
else if (value_type_name == "boolean")
|
||||
return LibertyAttrType::attr_boolean;
|
||||
else
|
||||
return LibertyAttrType::attr_unknown;
|
||||
}
|
||||
|
||||
LibertyGroupType
|
||||
LibertyParser::groupType(const char *group_type_name)
|
||||
LibertyParser::groupType(const std::string &group_type_name)
|
||||
{
|
||||
if (stringEq(group_type_name, "library"))
|
||||
if (group_type_name == "library")
|
||||
return LibertyGroupType::library;
|
||||
else if (stringEq(group_type_name, "cell"))
|
||||
else if (group_type_name == "cell")
|
||||
return LibertyGroupType::cell;
|
||||
else if (stringEq(group_type_name, "pin"))
|
||||
else if (group_type_name == "pin")
|
||||
return LibertyGroupType::pin;
|
||||
else if (stringEq(group_type_name, "timing"))
|
||||
else if (group_type_name == "timing")
|
||||
return LibertyGroupType::timing;
|
||||
else
|
||||
return LibertyGroupType::unknown;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyParser::groupBegin(std::string type,
|
||||
LibertyParser::groupBegin(const std::string type,
|
||||
LibertyAttrValueSeq *params,
|
||||
int line)
|
||||
{
|
||||
LibertyGroup *group = new LibertyGroup(std::move(type), params, line);
|
||||
group_visitor_->begin(group);
|
||||
LibertyGroup *group =
|
||||
new LibertyGroup(std::move(type),
|
||||
params ? std::move(*params) : LibertyAttrValueSeq(),
|
||||
line);
|
||||
delete params;
|
||||
LibertyGroup *parent_group = group_stack_.empty() ? nullptr : group_stack_.back();
|
||||
group_visitor_->begin(group, parent_group);
|
||||
group_stack_.push_back(group);
|
||||
}
|
||||
|
||||
|
|
@ -139,20 +144,13 @@ LibertyGroup *
|
|||
LibertyParser::groupEnd()
|
||||
{
|
||||
LibertyGroup *group = this->group();
|
||||
group_visitor_->end(group);
|
||||
group_stack_.pop_back();
|
||||
LibertyGroup *parent =
|
||||
group_stack_.empty() ? nullptr : group_stack_.back();
|
||||
if (parent && group_visitor_->save(group)) {
|
||||
parent->addStmt(group);
|
||||
return group;
|
||||
}
|
||||
else if (group_visitor_->save(group))
|
||||
return group;
|
||||
else {
|
||||
delete group;
|
||||
return nullptr;
|
||||
}
|
||||
if (parent)
|
||||
parent->addSubgroup(group);
|
||||
group_visitor_->end(group, parent);
|
||||
return group;
|
||||
}
|
||||
|
||||
LibertyGroup *
|
||||
|
|
@ -167,240 +165,65 @@ LibertyParser::deleteGroups()
|
|||
deleteContents(group_stack_);
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
LibertyParser::makeSimpleAttr(std::string name,
|
||||
LibertyAttrValue *value,
|
||||
LibertySimpleAttr *
|
||||
LibertyParser::makeSimpleAttr(const std::string name,
|
||||
const LibertyAttrValue *value,
|
||||
int line)
|
||||
{
|
||||
LibertyAttr *attr = new LibertySimpleAttr(std::move(name), value, line);
|
||||
group_visitor_->visitAttr(attr);
|
||||
LibertySimpleAttr *attr = new LibertySimpleAttr(std::move(name),
|
||||
std::move(*value), line);
|
||||
delete value;
|
||||
LibertyGroup *group = this->group();
|
||||
if (group && group_visitor_->save(attr)) {
|
||||
group->addStmt(attr);
|
||||
return attr;
|
||||
}
|
||||
else {
|
||||
delete attr;
|
||||
return nullptr;
|
||||
}
|
||||
group->addAttr(attr);
|
||||
group_visitor_->visitAttr(attr);
|
||||
return attr;
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
LibertyParser::makeComplexAttr(std::string name,
|
||||
LibertyAttrValueSeq *values,
|
||||
LibertyComplexAttr *
|
||||
LibertyParser::makeComplexAttr(const std::string name,
|
||||
const LibertyAttrValueSeq *values,
|
||||
int line)
|
||||
{
|
||||
// Defines have the same syntax as complex attributes.
|
||||
// Detect and convert them.
|
||||
if (name == "define") {
|
||||
LibertyStmt *define = makeDefine(values, line);
|
||||
deleteContents(values);
|
||||
delete values;
|
||||
return define;
|
||||
makeDefine(values, line);
|
||||
return nullptr; // Define is not a complex attr; already added to group
|
||||
}
|
||||
else {
|
||||
LibertyAttr *attr = new LibertyComplexAttr(std::move(name), values, line);
|
||||
LibertyComplexAttr *attr = new LibertyComplexAttr(std::move(name),
|
||||
std::move(*values),
|
||||
line);
|
||||
delete values;
|
||||
LibertyGroup *group = this->group();
|
||||
group->addAttr(attr);
|
||||
group_visitor_->visitAttr(attr);
|
||||
if (group_visitor_->save(attr)) {
|
||||
LibertyGroup *group = this->group();
|
||||
group->addStmt(attr);
|
||||
return attr;
|
||||
}
|
||||
delete attr;
|
||||
return nullptr;
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
LibertyParser::makeVariable(std::string var,
|
||||
LibertyVariable *
|
||||
LibertyParser::makeVariable(const std::string var,
|
||||
float value,
|
||||
int line)
|
||||
{
|
||||
LibertyVariable *variable = new LibertyVariable(std::move(var), value, line);
|
||||
LibertyGroup *group = this->group();
|
||||
group->addVariable(variable);
|
||||
group_visitor_->visitVariable(variable);
|
||||
if (group_visitor_->save(variable))
|
||||
return variable;
|
||||
else {
|
||||
delete variable;
|
||||
return nullptr;
|
||||
}
|
||||
return variable;
|
||||
}
|
||||
|
||||
LibertyAttrValue *
|
||||
LibertyParser::makeStringAttrValue(std::string value)
|
||||
LibertyParser::makeAttrValueString(std::string value)
|
||||
{
|
||||
return new LibertyStringAttrValue(std::move(value));
|
||||
return new LibertyAttrValue(std::move(value));
|
||||
}
|
||||
|
||||
LibertyAttrValue *
|
||||
LibertyParser::makeFloatAttrValue(float value)
|
||||
{
|
||||
return new LibertyFloatAttrValue(value);
|
||||
}
|
||||
|
||||
const std::string &
|
||||
LibertyFloatAttrValue::stringValue() const
|
||||
{
|
||||
criticalError(1127, "LibertyStringAttrValue called for float value");
|
||||
static std::string null;
|
||||
return null;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyStmt::LibertyStmt(int line) :
|
||||
line_(line)
|
||||
{
|
||||
}
|
||||
|
||||
LibertyGroup::LibertyGroup(std::string type,
|
||||
LibertyAttrValueSeq *params,
|
||||
int line) :
|
||||
LibertyStmt(line),
|
||||
type_(std::move(type)),
|
||||
params_(params),
|
||||
stmts_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::addStmt(LibertyStmt *stmt)
|
||||
{
|
||||
if (stmts_ == nullptr)
|
||||
stmts_ = new LibertyStmtSeq;
|
||||
stmts_->push_back(stmt);
|
||||
}
|
||||
|
||||
LibertyGroup::~LibertyGroup()
|
||||
{
|
||||
if (params_) {
|
||||
deleteContents(params_);
|
||||
delete params_;
|
||||
}
|
||||
if (stmts_) {
|
||||
deleteContents(stmts_);
|
||||
delete stmts_;
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
LibertyGroup::firstName()
|
||||
{
|
||||
if (params_ && params_->size() > 0) {
|
||||
LibertyAttrValue *value = (*params_)[0];
|
||||
if (value->isString())
|
||||
return value->stringValue().c_str();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *
|
||||
LibertyGroup::secondName()
|
||||
{
|
||||
if (params_ && params_->size() > 1) {
|
||||
LibertyAttrValue *value = (*params_)[1];
|
||||
if (value->isString())
|
||||
return value->stringValue().c_str();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyAttr::LibertyAttr(std::string name,
|
||||
int line) :
|
||||
LibertyStmt(line),
|
||||
name_(std::move(name))
|
||||
{
|
||||
}
|
||||
|
||||
LibertySimpleAttr::LibertySimpleAttr(std::string name,
|
||||
LibertyAttrValue *value,
|
||||
int line) :
|
||||
LibertyAttr(std::move(name), line),
|
||||
value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
LibertySimpleAttr::~LibertySimpleAttr()
|
||||
{
|
||||
delete value_;
|
||||
}
|
||||
|
||||
LibertyAttrValueSeq *
|
||||
LibertySimpleAttr::values() const
|
||||
{
|
||||
criticalError(1125, "valueIterator called for LibertySimpleAttribute");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyComplexAttr::LibertyComplexAttr(std::string name,
|
||||
LibertyAttrValueSeq *values,
|
||||
int line) :
|
||||
LibertyAttr(std::move(name), line),
|
||||
values_(values)
|
||||
{
|
||||
}
|
||||
|
||||
LibertyComplexAttr::~LibertyComplexAttr()
|
||||
{
|
||||
if (values_) {
|
||||
deleteContents(values_);
|
||||
delete values_;
|
||||
}
|
||||
}
|
||||
|
||||
LibertyAttrValue *
|
||||
LibertyComplexAttr::firstValue()
|
||||
{
|
||||
if (values_ && values_->size() > 0)
|
||||
return (*values_)[0];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LibertyStringAttrValue::LibertyStringAttrValue(std::string value) :
|
||||
LibertyAttrValue(),
|
||||
value_(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
float
|
||||
LibertyStringAttrValue::floatValue() const
|
||||
{
|
||||
criticalError(1126, "LibertyStringAttrValue called for float value");
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
LibertyFloatAttrValue::LibertyFloatAttrValue(float value) :
|
||||
value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyDefine::LibertyDefine(std::string name,
|
||||
LibertyGroupType group_type,
|
||||
LibertyAttrType value_type,
|
||||
int line) :
|
||||
LibertyStmt(line),
|
||||
name_(std::move(name)),
|
||||
group_type_(group_type),
|
||||
value_type_(value_type)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyVariable::LibertyVariable(std::string var,
|
||||
float value,
|
||||
int line) :
|
||||
LibertyStmt(line),
|
||||
var_(std::move(var)),
|
||||
value_(value)
|
||||
LibertyParser::makeAttrValueFloat(float value)
|
||||
{
|
||||
return new LibertyAttrValue(value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -425,13 +248,13 @@ LibertyScanner::includeBegin()
|
|||
error("nested include_file's are not supported");
|
||||
else {
|
||||
// include_file(filename);
|
||||
std::regex include_regexp("include_file *\\( *([^)]+) *\\) *;?");
|
||||
static const std::regex include_regexp("include_file *\\( *([^)]+) *\\) *;?");
|
||||
std::cmatch matches;
|
||||
if (std::regex_match(yytext, matches, include_regexp)) {
|
||||
string filename = matches[1].str();
|
||||
std::string filename = matches[1].str();
|
||||
gzstream::igzstream *stream = new gzstream::igzstream(filename.c_str());
|
||||
if (stream->is_open()) {
|
||||
yypush_buffer_state(yy_create_buffer(stream, 256));
|
||||
yypush_buffer_state(yy_create_buffer(stream, 16384));
|
||||
|
||||
filename_prev_ = filename_;
|
||||
stream_prev_ = stream_;
|
||||
|
|
@ -471,4 +294,323 @@ LibertyScanner::error(const char *msg)
|
|||
report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyGroup::LibertyGroup(std::string type,
|
||||
LibertyAttrValueSeq params,
|
||||
int line) :
|
||||
type_(std::move(type)),
|
||||
params_(std::move(params)),
|
||||
line_(line)
|
||||
{
|
||||
}
|
||||
|
||||
LibertyGroup::~LibertyGroup()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::clear()
|
||||
{
|
||||
deleteContents(params_);
|
||||
deleteContents(simple_attr_map_);
|
||||
for (auto &attr : complex_attr_map_)
|
||||
deleteContents(attr.second);
|
||||
complex_attr_map_.clear();
|
||||
deleteContents(subgroups_);
|
||||
subgroup_map_.clear();
|
||||
deleteContents(define_map_);
|
||||
deleteContents(variables_);
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::addSubgroup(LibertyGroup *subgroup)
|
||||
{
|
||||
subgroups_.push_back(subgroup);
|
||||
subgroup_map_[subgroup->type()].push_back(subgroup);
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::deleteSubgroup(const LibertyGroup *subgroup)
|
||||
{
|
||||
if (subgroup == subgroups_.back()) {
|
||||
subgroups_.pop_back();
|
||||
subgroup_map_[subgroup->type()].pop_back();
|
||||
delete subgroup;
|
||||
}
|
||||
else
|
||||
criticalError(1128, "LibertyAttrValue::floatValue() called on string");
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::addDefine(LibertyDefine *define)
|
||||
{
|
||||
const std::string &define_name = define->name();
|
||||
LibertyDefine *prev_define = findKey(define_map_, define_name);
|
||||
if (prev_define) {
|
||||
define_map_.erase(define_name);
|
||||
delete prev_define;
|
||||
}
|
||||
define_map_[define_name] = define;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::addAttr(LibertySimpleAttr *attr)
|
||||
{
|
||||
// Only keep the most recent simple attribute value.
|
||||
const auto &itr = simple_attr_map_.find(attr->name());
|
||||
if (itr != simple_attr_map_.end())
|
||||
delete itr->second;
|
||||
simple_attr_map_[attr->name()] = attr;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::addAttr(LibertyComplexAttr *attr)
|
||||
{
|
||||
complex_attr_map_[attr->name()].push_back(attr);
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::addVariable(LibertyVariable *var)
|
||||
{
|
||||
variables_.push_back(var);
|
||||
}
|
||||
|
||||
const char *
|
||||
LibertyGroup::firstName() const
|
||||
{
|
||||
if (params_.size() >= 1) {
|
||||
LibertyAttrValue *value = params_[0];
|
||||
if (value->isString())
|
||||
return value->stringValue().c_str();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *
|
||||
LibertyGroup::secondName() const
|
||||
{
|
||||
LibertyAttrValue *value = params_[1];
|
||||
if (value->isString())
|
||||
return value->stringValue().c_str();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const LibertyGroupSeq &
|
||||
LibertyGroup::findSubgroups(const std::string type) const
|
||||
{
|
||||
return findKeyValue(subgroup_map_, type);
|
||||
}
|
||||
|
||||
const LibertyGroup *
|
||||
LibertyGroup::findSubgroup(const std::string type) const
|
||||
{
|
||||
const LibertyGroupSeq &groups = findKeyValue(subgroup_map_, type);
|
||||
if (groups.size() >= 1)
|
||||
return groups[0];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const LibertySimpleAttr *
|
||||
LibertyGroup::findSimpleAttr(const std::string attr_name) const
|
||||
{
|
||||
return findKeyValue(simple_attr_map_, attr_name);
|
||||
}
|
||||
|
||||
const LibertyComplexAttrSeq &
|
||||
LibertyGroup::findComplexAttrs(const std::string attr_name) const
|
||||
{
|
||||
return findKeyValue(complex_attr_map_, attr_name);
|
||||
}
|
||||
|
||||
const LibertyComplexAttr *
|
||||
LibertyGroup::findComplexAttr(const std::string attr_name) const
|
||||
{
|
||||
const LibertyComplexAttrSeq &attrs = findKeyValue(complex_attr_map_, attr_name);
|
||||
if (attrs.size() >= 1)
|
||||
return attrs[0];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::string *
|
||||
LibertyGroup::findAttrString(const std::string attr_name) const
|
||||
{
|
||||
const LibertySimpleAttr *attr = findSimpleAttr(attr_name);
|
||||
if (attr)
|
||||
return &attr->value().stringValue();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::findAttrFloat(const std::string attr_name,
|
||||
// Return values.
|
||||
float &value,
|
||||
bool &exists) const
|
||||
{
|
||||
const LibertySimpleAttr *attr = findSimpleAttr(attr_name);
|
||||
if (attr) {
|
||||
const LibertyAttrValue &attr_value = attr->value();
|
||||
if (attr_value.isFloat()) {
|
||||
value = attr_value.floatValue();
|
||||
exists = true;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// Possibly quoted string float.
|
||||
const std::string &float_str = attr_value.stringValue();
|
||||
char *end = nullptr;
|
||||
value = std::strtof(float_str.c_str(), &end);
|
||||
if (end) {
|
||||
exists = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
exists = false;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyGroup::findAttrInt(const std::string attr_name,
|
||||
// Return values.
|
||||
int &value,
|
||||
bool &exists) const
|
||||
{
|
||||
const LibertySimpleAttr *attr = findSimpleAttr(attr_name);
|
||||
if (attr) {
|
||||
const LibertyAttrValue &attr_value = attr->value();
|
||||
if (attr_value.isFloat()) {
|
||||
value = static_cast<int>(attr_value.floatValue());
|
||||
exists = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
exists = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertySimpleAttr::LibertySimpleAttr(const std::string name,
|
||||
const LibertyAttrValue value,
|
||||
int line) :
|
||||
name_(std::move(name)),
|
||||
line_(line),
|
||||
value_(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
const std::string *
|
||||
LibertySimpleAttr::stringValue() const
|
||||
{
|
||||
return &value().stringValue();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyComplexAttr::LibertyComplexAttr(std::string name,
|
||||
const LibertyAttrValueSeq values,
|
||||
int line) :
|
||||
name_(std::move(name)),
|
||||
values_(std::move(values)),
|
||||
line_(line)
|
||||
{
|
||||
}
|
||||
|
||||
LibertyComplexAttr::~LibertyComplexAttr()
|
||||
{
|
||||
deleteContents(values_);
|
||||
}
|
||||
|
||||
const LibertyAttrValue *
|
||||
LibertyComplexAttr::firstValue() const
|
||||
{
|
||||
if (values_.size() > 0)
|
||||
return values_[0];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyAttrValue::LibertyAttrValue(std::string value) :
|
||||
string_value_(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
LibertyAttrValue::LibertyAttrValue(float value) :
|
||||
float_value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
LibertyAttrValue::isFloat() const
|
||||
{
|
||||
return string_value_.empty();
|
||||
}
|
||||
|
||||
bool
|
||||
LibertyAttrValue::isString() const
|
||||
{
|
||||
return !string_value_.empty();
|
||||
}
|
||||
|
||||
float
|
||||
LibertyAttrValue::floatValue() const
|
||||
{
|
||||
if (!string_value_.empty())
|
||||
criticalError(1127, "LibertyAttrValue::floatValue() called on string");
|
||||
return float_value_;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyAttrValue::floatValue(// Return values.
|
||||
float &value,
|
||||
bool &valid) const
|
||||
{
|
||||
valid = false;
|
||||
if (string_value_.empty()) {
|
||||
value = float_value_;
|
||||
valid = true;
|
||||
}
|
||||
else {
|
||||
// Some floats are enclosed in quotes.
|
||||
char *end;
|
||||
value = strtof(string_value_.c_str(), &end);
|
||||
if ((*end == '\0'
|
||||
|| isspace(*end))
|
||||
// strtof support INF as a valid float.
|
||||
&& string_value_ != "inf") {
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyDefine::LibertyDefine(std::string name,
|
||||
LibertyGroupType group_type,
|
||||
LibertyAttrType value_type,
|
||||
int line) :
|
||||
name_(std::move(name)),
|
||||
group_type_(group_type),
|
||||
value_type_(value_type),
|
||||
line_(line)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyVariable::LibertyVariable(std::string var,
|
||||
float value,
|
||||
int line) :
|
||||
var_(std::move(var)),
|
||||
value_(value),
|
||||
line_(line)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -34,20 +34,22 @@ namespace sta {
|
|||
|
||||
class Report;
|
||||
class LibertyGroupVisitor;
|
||||
class LibertyStmt;
|
||||
class LibertyGroup;
|
||||
class LibertyAttr;
|
||||
class LibertyDefine;
|
||||
class LibertySimpleAttr;
|
||||
class LibertyComplexAttr;
|
||||
class LibertyAttrValue;
|
||||
class LibertyVariable;
|
||||
class LibertyScanner;
|
||||
|
||||
using LibertyStmtSeq = std::vector<LibertyStmt*>;
|
||||
using LibertyGroupSeq = std::vector<LibertyGroup*>;
|
||||
using LibertyAttrSeq = std::vector<LibertyAttr*>;
|
||||
using LibertyAttrMap = std::map<std::string, LibertyAttr*>;
|
||||
using LibertySubGroupMap = std::map<std::string, LibertyGroupSeq>;
|
||||
using LibertySimpleAttrMap = std::map<std::string, LibertySimpleAttr*>;
|
||||
using LibertyComplexAttrSeq = std::vector<LibertyComplexAttr*>;
|
||||
using LibertyComplexAttrMap = std::map<std::string, LibertyComplexAttrSeq>;
|
||||
using LibertyDefineMap = std::map<std::string, LibertyDefine*>;
|
||||
using LibertyAttrValueSeq = std::vector<LibertyAttrValue*>;
|
||||
using LibertyVariableSeq = std::vector<LibertyVariable*>;
|
||||
using LibertyVariableMap = std::map<std::string, float>;
|
||||
using LibertyGroupVisitorMap = std::map<std::string, LibertyGroupVisitor*>;
|
||||
|
||||
|
|
@ -65,27 +67,27 @@ public:
|
|||
const std::string &filename() const { return filename_; }
|
||||
void setFilename(const std::string &filename);
|
||||
Report *report() const { return report_; }
|
||||
LibertyStmt *makeDefine(LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
LibertyAttrType attrValueType(const char *value_type_name);
|
||||
LibertyGroupType groupType(const char *group_type_name);
|
||||
void groupBegin(std::string type,
|
||||
LibertyDefine *makeDefine(const LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
LibertyAttrType attrValueType(const std::string &value_type_name);
|
||||
LibertyGroupType groupType(const std::string &group_type_name);
|
||||
void groupBegin(const std::string type,
|
||||
LibertyAttrValueSeq *params,
|
||||
int line);
|
||||
LibertyGroup *groupEnd();
|
||||
LibertyGroup *group();
|
||||
void deleteGroups();
|
||||
LibertyStmt *makeSimpleAttr(std::string name,
|
||||
LibertyAttrValue *value,
|
||||
int line);
|
||||
LibertyStmt *makeComplexAttr(std::string name,
|
||||
LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
LibertyAttrValue *makeStringAttrValue(std::string value);
|
||||
LibertyAttrValue *makeFloatAttrValue(float value);
|
||||
LibertyStmt *makeVariable(std::string var,
|
||||
float value,
|
||||
int line);
|
||||
LibertySimpleAttr *makeSimpleAttr(const std::string name,
|
||||
const LibertyAttrValue *value,
|
||||
int line);
|
||||
LibertyComplexAttr *makeComplexAttr(const std::string name,
|
||||
const LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
LibertyAttrValue *makeAttrValueString(const std::string value);
|
||||
LibertyAttrValue *makeAttrValueFloat(float value);
|
||||
LibertyVariable *makeVariable(const std::string var,
|
||||
float value,
|
||||
int line);
|
||||
|
||||
private:
|
||||
std::string filename_;
|
||||
|
|
@ -94,178 +96,171 @@ private:
|
|||
LibertyGroupSeq group_stack_;
|
||||
};
|
||||
|
||||
// Abstract base class for liberty statements.
|
||||
class LibertyStmt
|
||||
{
|
||||
public:
|
||||
LibertyStmt(int line);
|
||||
virtual ~LibertyStmt() {}
|
||||
int line() const { return line_; }
|
||||
virtual bool isGroup() const { return false; }
|
||||
virtual bool isAttribute() const { return false; }
|
||||
virtual bool isSimpleAttr() const { return false; }
|
||||
virtual bool isComplexAttr() const { return false; }
|
||||
virtual bool isDefine() const { return false; }
|
||||
virtual bool isVariable() const { return false; }
|
||||
|
||||
protected:
|
||||
int line_;
|
||||
};
|
||||
|
||||
// Groups are a type keyword with a set of parameters and statements
|
||||
// enclosed in brackets.
|
||||
// type([param1][, param2]...) { stmts.. }
|
||||
class LibertyGroup : public LibertyStmt
|
||||
{
|
||||
public:
|
||||
LibertyGroup(std::string type,
|
||||
LibertyAttrValueSeq *params,
|
||||
int line);
|
||||
virtual ~LibertyGroup();
|
||||
virtual bool isGroup() const { return true; }
|
||||
const std::string &type() const { return type_; }
|
||||
LibertyAttrValueSeq *params() const { return params_; }
|
||||
// First param as a string.
|
||||
const char *firstName();
|
||||
// Second param as a string.
|
||||
const char *secondName();
|
||||
void addStmt(LibertyStmt *stmt);
|
||||
LibertyStmtSeq *stmts() const { return stmts_; }
|
||||
|
||||
protected:
|
||||
void parseNames(LibertyAttrValueSeq *values);
|
||||
|
||||
std::string type_;
|
||||
LibertyAttrValueSeq *params_;
|
||||
LibertyStmtSeq *stmts_;
|
||||
};
|
||||
|
||||
// Abstract base class for attributes.
|
||||
class LibertyAttr : public LibertyStmt
|
||||
{
|
||||
public:
|
||||
LibertyAttr(std::string name,
|
||||
int line);
|
||||
const std::string &name() const { return name_; }
|
||||
virtual LibertyAttrValueSeq *values() const = 0;
|
||||
virtual LibertyAttrValue *firstValue() = 0;
|
||||
|
||||
protected:
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
// Abstract base class for simple attributes.
|
||||
// name : value;
|
||||
class LibertySimpleAttr : public LibertyAttr
|
||||
{
|
||||
public:
|
||||
LibertySimpleAttr(std::string name,
|
||||
LibertyAttrValue *value,
|
||||
int line);
|
||||
virtual ~LibertySimpleAttr();
|
||||
bool isSimpleAttr() const override { return true; };
|
||||
LibertyAttrValue *firstValue() override { return value_; };
|
||||
LibertyAttrValueSeq *values() const override;
|
||||
|
||||
private:
|
||||
LibertyAttrValue *value_;
|
||||
};
|
||||
|
||||
// Complex attributes have multiple values.
|
||||
// name(attr_value1[, attr_value2]...);
|
||||
class LibertyComplexAttr : public LibertyAttr
|
||||
{
|
||||
public:
|
||||
LibertyComplexAttr(std::string name,
|
||||
LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
virtual ~LibertyComplexAttr();
|
||||
bool isComplexAttr() const override { return true; };
|
||||
LibertyAttrValue *firstValue() override ;
|
||||
LibertyAttrValueSeq *values() const override { return values_; }
|
||||
|
||||
private:
|
||||
LibertyAttrValueSeq *values_;
|
||||
};
|
||||
|
||||
// Attribute values are a string or float.
|
||||
class LibertyAttrValue
|
||||
{
|
||||
public:
|
||||
LibertyAttrValue() {}
|
||||
virtual ~LibertyAttrValue() {}
|
||||
virtual bool isString() const = 0;
|
||||
virtual bool isFloat() const = 0;
|
||||
virtual float floatValue() const = 0;
|
||||
virtual const std::string &stringValue() const = 0;
|
||||
};
|
||||
|
||||
class LibertyStringAttrValue : public LibertyAttrValue
|
||||
{
|
||||
public:
|
||||
LibertyStringAttrValue(std::string value);
|
||||
virtual ~LibertyStringAttrValue() {}
|
||||
bool isFloat() const override { return false; }
|
||||
bool isString() const override { return true; }
|
||||
float floatValue() const override ;
|
||||
const std::string &stringValue() const override { return value_; }
|
||||
LibertyAttrValue(float value);
|
||||
LibertyAttrValue(std::string value);
|
||||
bool isString() const;
|
||||
bool isFloat() const;
|
||||
float floatValue() const;
|
||||
void floatValue(// Return values.
|
||||
float &value,
|
||||
bool &valid) const;
|
||||
const std::string &stringValue() const { return string_value_; }
|
||||
|
||||
private:
|
||||
std::string value_;
|
||||
float float_value_;
|
||||
std::string string_value_;
|
||||
};
|
||||
|
||||
class LibertyFloatAttrValue : public LibertyAttrValue
|
||||
// Groups are a type keyword with a set of parameters and statements
|
||||
// enclosed in brackets.
|
||||
// type([param1][, param2]...) { stmts.. }
|
||||
class LibertyGroup
|
||||
{
|
||||
public:
|
||||
LibertyFloatAttrValue(float value);
|
||||
virtual ~LibertyFloatAttrValue() {}
|
||||
bool isString() const override { return false; }
|
||||
bool isFloat() const override { return true; }
|
||||
float floatValue() const override { return value_; }
|
||||
const std::string &stringValue() const override;
|
||||
LibertyGroup(const std::string type,
|
||||
const LibertyAttrValueSeq params,
|
||||
int line);
|
||||
~LibertyGroup();
|
||||
void clear();
|
||||
const std::string &type() const { return type_; }
|
||||
const LibertyAttrValueSeq ¶ms() const { return params_; }
|
||||
// First param as a string.
|
||||
const char *firstName() const;
|
||||
// Second param as a string.
|
||||
const char *secondName() const;
|
||||
int line() const { return line_; }
|
||||
|
||||
const LibertyGroupSeq &findSubgroups(const std::string type) const;
|
||||
const LibertyGroup *findSubgroup(const std::string type) const;
|
||||
const LibertySimpleAttr *findSimpleAttr(const std::string attr_name) const;
|
||||
const LibertyComplexAttrSeq &findComplexAttrs(const std::string attr_name) const;
|
||||
const LibertyComplexAttr *findComplexAttr(const std::string attr_name) const;
|
||||
const std::string *findAttrString(const std::string attr_name) const;
|
||||
void findAttrFloat(const std::string attr_name,
|
||||
// Return values.
|
||||
float &value,
|
||||
bool &exists) const;
|
||||
void findAttrInt(const std::string attr_name,
|
||||
// Return values.
|
||||
int &value,
|
||||
bool &exists) const;
|
||||
|
||||
const LibertyGroupSeq &subgroups() const { return subgroups_; }
|
||||
const LibertyDefineMap &defineMap() const { return define_map_; }
|
||||
|
||||
void addSubgroup(LibertyGroup *subgroup);
|
||||
void deleteSubgroup(const LibertyGroup *subgroup);
|
||||
void addAttr(LibertySimpleAttr *attr);
|
||||
void addAttr(LibertyComplexAttr *attr);
|
||||
void addDefine(LibertyDefine *define);
|
||||
void addVariable(LibertyVariable *var);
|
||||
|
||||
protected:
|
||||
std::string type_;
|
||||
LibertyAttrValueSeq params_;
|
||||
int line_;
|
||||
|
||||
LibertySimpleAttrMap simple_attr_map_;
|
||||
LibertyComplexAttrMap complex_attr_map_;
|
||||
LibertyGroupSeq subgroups_;
|
||||
LibertySubGroupMap subgroup_map_;
|
||||
LibertyDefineMap define_map_;
|
||||
LibertyVariableSeq variables_;
|
||||
};
|
||||
|
||||
class LibertyGroupLineLess
|
||||
{
|
||||
public:
|
||||
bool
|
||||
operator()(const LibertyGroup *group1,
|
||||
const LibertyGroup *group2) const {
|
||||
return group1->line() < group2->line();
|
||||
}
|
||||
};
|
||||
|
||||
// Simple attributes: name : value;
|
||||
class LibertySimpleAttr
|
||||
{
|
||||
public:
|
||||
LibertySimpleAttr(const std::string name,
|
||||
const LibertyAttrValue value,
|
||||
int line);
|
||||
const std::string &name() const { return name_; }
|
||||
const LibertyAttrValue &value() const { return value_; };
|
||||
const std::string *stringValue() const;
|
||||
int line() const { return line_; }
|
||||
|
||||
private:
|
||||
float value_;
|
||||
std::string name_;
|
||||
int line_;
|
||||
LibertyAttrValue value_;
|
||||
};
|
||||
|
||||
// Complex attributes have multiple values.
|
||||
// name(attr_value1[, attr_value2]...);
|
||||
class LibertyComplexAttr
|
||||
{
|
||||
public:
|
||||
LibertyComplexAttr(const std::string name,
|
||||
const LibertyAttrValueSeq values,
|
||||
int line);
|
||||
~LibertyComplexAttr();
|
||||
const std::string &name() const { return name_; }
|
||||
const LibertyAttrValue *firstValue() const;
|
||||
const LibertyAttrValueSeq &values() const { return values_; }
|
||||
int line() const { return line_; }
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
LibertyAttrValueSeq values_;
|
||||
int line_;
|
||||
};
|
||||
|
||||
// Define statements define new simple attributes.
|
||||
// define(attribute_name, group_name, attribute_type);
|
||||
// attribute_type is string|integer|float.
|
||||
class LibertyDefine : public LibertyStmt
|
||||
class LibertyDefine
|
||||
{
|
||||
public:
|
||||
LibertyDefine(std::string name,
|
||||
LibertyGroupType group_type,
|
||||
LibertyAttrType value_type,
|
||||
int line);
|
||||
virtual bool isDefine() const { return true; }
|
||||
const std::string &name() const { return name_; }
|
||||
LibertyGroupType groupType() const { return group_type_; }
|
||||
LibertyAttrType valueType() const { return value_type_; }
|
||||
int line() const { return line_; }
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
LibertyGroupType group_type_;
|
||||
LibertyAttrType value_type_;
|
||||
int line_;
|
||||
};
|
||||
|
||||
// The Liberty User Guide Version 2003.12 fails to document variables.
|
||||
// var = value;
|
||||
// The only example I have only uses float values, so I am assuming
|
||||
// that is all that is supported (which is probably wrong).
|
||||
class LibertyVariable : public LibertyStmt
|
||||
class LibertyVariable
|
||||
{
|
||||
public:
|
||||
LibertyVariable(std::string var,
|
||||
float value,
|
||||
int line);
|
||||
bool isVariable() const override { return true; }
|
||||
int line() const { return line_; }
|
||||
const std::string &variable() const { return var_; }
|
||||
float value() const { return value_; }
|
||||
|
||||
private:
|
||||
std::string var_;
|
||||
float value_;
|
||||
int line_;
|
||||
};
|
||||
|
||||
class LibertyGroupVisitor
|
||||
|
|
@ -273,14 +268,13 @@ class LibertyGroupVisitor
|
|||
public:
|
||||
LibertyGroupVisitor() {}
|
||||
virtual ~LibertyGroupVisitor() {}
|
||||
virtual void begin(LibertyGroup *group) = 0;
|
||||
virtual void end(LibertyGroup *group) = 0;
|
||||
virtual void visitAttr(LibertyAttr *attr) = 0;
|
||||
virtual void begin(const LibertyGroup *group,
|
||||
LibertyGroup *parent_group) = 0;
|
||||
virtual void end(const LibertyGroup *group,
|
||||
LibertyGroup *parent_group) = 0;
|
||||
virtual void visitAttr(const LibertySimpleAttr *attr) = 0;
|
||||
virtual void visitAttr(const LibertyComplexAttr *attr) = 0;
|
||||
virtual void visitVariable(LibertyVariable *variable) = 0;
|
||||
// Predicates to save parse structure after visits.
|
||||
virtual bool save(LibertyGroup *group) = 0;
|
||||
virtual bool save(LibertyAttr *attr) = 0;
|
||||
virtual bool save(LibertyVariable *variable) = 0;
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -25,7 +25,7 @@
|
|||
#include "LibertyWriter.hh"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "Units.hh"
|
||||
#include "FuncExpr.hh"
|
||||
|
|
@ -39,8 +39,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::abs;
|
||||
|
||||
class LibertyWriter
|
||||
{
|
||||
public:
|
||||
|
|
@ -271,7 +269,7 @@ LibertyWriter::writeBusDcls()
|
|||
fprintf(stream_, " type (\"%s\") {\n", dcl->name().c_str());
|
||||
fprintf(stream_, " base_type : array;\n");
|
||||
fprintf(stream_, " data_type : bit;\n");
|
||||
fprintf(stream_, " bit_width : %d;\n", abs(dcl->from() - dcl->to() + 1));
|
||||
fprintf(stream_, " bit_width : %d;\n", std::abs(dcl->from() - dcl->to() + 1));
|
||||
fprintf(stream_, " bit_from : %d;\n", dcl->from());
|
||||
fprintf(stream_, " bit_to : %d;\n", dcl->to());
|
||||
fprintf(stream_, " }\n");
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
GateLinearModel::GateLinearModel(LibertyCell *cell,
|
||||
float intrinsic,
|
||||
float resistance) :
|
||||
|
|
@ -53,7 +51,7 @@ GateLinearModel::gateDelay(const Pvt *,
|
|||
drvr_slew = 0.0;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
GateLinearModel::reportGateDelay(const Pvt *,
|
||||
float,
|
||||
float load_cap,
|
||||
|
|
@ -65,7 +63,7 @@ GateLinearModel::reportGateDelay(const Pvt *,
|
|||
const Unit *time_unit = units->timeUnit();
|
||||
const Unit *res_unit = units->resistanceUnit();
|
||||
const Unit *cap_unit = units->capacitanceUnit();
|
||||
string result = "Delay = ";
|
||||
std::string result = "Delay = ";
|
||||
result += time_unit->asString(intrinsic_, digits);
|
||||
result += " + ";
|
||||
result += res_unit->asString(resistance_, digits);
|
||||
|
|
@ -105,7 +103,7 @@ CheckLinearModel::checkDelay(const Pvt *,
|
|||
return intrinsic_;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
CheckLinearModel::reportCheckDelay(const Pvt *,
|
||||
float,
|
||||
const char *,
|
||||
|
|
@ -117,7 +115,7 @@ CheckLinearModel::reportCheckDelay(const Pvt *,
|
|||
const LibertyLibrary *library = cell_->libertyLibrary();
|
||||
const Units *units = library->units();
|
||||
const Unit *time_unit = units->timeUnit();
|
||||
string result = "Check = ";
|
||||
std::string result = "Check = ";
|
||||
result += time_unit->asString(intrinsic_, digits);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,25 +35,17 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
using std::min;
|
||||
using std::max;
|
||||
using std::abs;
|
||||
using std::make_shared;
|
||||
|
||||
size_t
|
||||
findValueIndex(float value,
|
||||
const FloatSeq *values);
|
||||
static void
|
||||
sigmaModelsMvOwner(TableModel *models[EarlyLate::index_count],
|
||||
std::array<std::unique_ptr<TableModel>,
|
||||
EarlyLate::index_count> &out);
|
||||
static string
|
||||
sigmaModelsDelete(TableModelsEarlyLate &models);
|
||||
static std::string
|
||||
reportPvt(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
int digits);
|
||||
static void
|
||||
appendSpaces(string &result,
|
||||
appendSpaces(std::string &result,
|
||||
int count);
|
||||
|
||||
TimingModel::TimingModel(LibertyCell *cell) :
|
||||
|
|
@ -63,40 +55,50 @@ TimingModel::TimingModel(LibertyCell *cell) :
|
|||
|
||||
GateTableModel::GateTableModel(LibertyCell *cell,
|
||||
TableModel *delay_model,
|
||||
TableModel *delay_sigma_models[EarlyLate::index_count],
|
||||
TableModelsEarlyLate delay_sigma_models,
|
||||
TableModel *slew_model,
|
||||
TableModel *slew_sigma_models[EarlyLate::index_count],
|
||||
TableModelsEarlyLate slew_sigma_models,
|
||||
ReceiverModelPtr receiver_model,
|
||||
OutputWaveforms *output_waveforms) :
|
||||
GateTimingModel(cell),
|
||||
delay_model_(delay_model),
|
||||
delay_sigma_models_(std::move(delay_sigma_models)),
|
||||
slew_model_(slew_model),
|
||||
slew_sigma_models_(std::move(slew_sigma_models)),
|
||||
receiver_model_(receiver_model),
|
||||
output_waveforms_(output_waveforms)
|
||||
{
|
||||
sigmaModelsMvOwner(delay_sigma_models, delay_sigma_models_);
|
||||
sigmaModelsMvOwner(slew_sigma_models, slew_sigma_models_);
|
||||
}
|
||||
|
||||
GateTableModel::~GateTableModel() = default;
|
||||
GateTableModel::GateTableModel(LibertyCell *cell,
|
||||
TableModel *delay_model,
|
||||
TableModel *slew_model) :
|
||||
GateTimingModel(cell),
|
||||
delay_model_(delay_model),
|
||||
delay_sigma_models_{},
|
||||
slew_model_(slew_model),
|
||||
slew_sigma_models_{},
|
||||
receiver_model_(nullptr),
|
||||
output_waveforms_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
GateTableModel::~GateTableModel()
|
||||
{
|
||||
sigmaModelsDelete(slew_sigma_models_);
|
||||
sigmaModelsDelete(delay_sigma_models_);
|
||||
}
|
||||
|
||||
static void
|
||||
sigmaModelsMvOwner(TableModel *models[EarlyLate::index_count],
|
||||
std::array<std::unique_ptr<TableModel>,
|
||||
EarlyLate::index_count> &out)
|
||||
sigmaModelsDelete(TableModelsEarlyLate &models)
|
||||
{
|
||||
TableModel *early_model = models ? models[EarlyLate::earlyIndex()] : nullptr;
|
||||
TableModel *late_model = models ? models[EarlyLate::lateIndex()] : nullptr;
|
||||
if (early_model) {
|
||||
out[EarlyLate::earlyIndex()].reset(early_model);
|
||||
if (late_model && late_model != early_model) {
|
||||
out[EarlyLate::lateIndex()].reset(late_model);
|
||||
} else if (late_model == early_model) {
|
||||
out[EarlyLate::lateIndex()] =
|
||||
std::make_unique<TableModel>(*out[EarlyLate::earlyIndex()]);
|
||||
}
|
||||
} else if (late_model) {
|
||||
out[EarlyLate::lateIndex()].reset(late_model);
|
||||
TableModel *early_model = models[EarlyLate::earlyIndex()];
|
||||
TableModel *late_model = models[EarlyLate::lateIndex()];
|
||||
if (early_model == late_model)
|
||||
delete early_model;
|
||||
else {
|
||||
delete early_model;
|
||||
delete late_model;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -122,19 +124,19 @@ GateTableModel::gateDelay(const Pvt *pvt,
|
|||
float sigma_early = 0.0;
|
||||
float sigma_late = 0.0;
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::earlyIndex()])
|
||||
sigma_early = findValue(pvt, delay_sigma_models_[EarlyLate::earlyIndex()].get(),
|
||||
sigma_early = findValue(pvt, delay_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, 0.0);
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::lateIndex()])
|
||||
sigma_late = findValue(pvt, delay_sigma_models_[EarlyLate::lateIndex()].get(),
|
||||
sigma_late = findValue(pvt, delay_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, 0.0);
|
||||
gate_delay = makeDelay(delay, sigma_early, sigma_late);
|
||||
|
||||
float slew = findValue(pvt, slew_model_.get(), in_slew, load_cap, 0.0);
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::earlyIndex()])
|
||||
sigma_early = findValue(pvt, slew_sigma_models_[EarlyLate::earlyIndex()].get(),
|
||||
sigma_early = findValue(pvt, slew_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, 0.0);
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::lateIndex()])
|
||||
sigma_late = findValue(pvt, slew_sigma_models_[EarlyLate::lateIndex()].get(),
|
||||
sigma_late = findValue(pvt, slew_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, 0.0);
|
||||
// Clip negative slews to zero.
|
||||
if (slew < 0.0)
|
||||
|
|
@ -154,34 +156,34 @@ GateTableModel::gateDelay(const Pvt *pvt,
|
|||
gateDelay(pvt, in_slew, load_cap, pocv_enabled, gate_delay, drvr_slew);
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
GateTableModel::reportGateDelay(const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
bool pocv_enabled,
|
||||
int digits) const
|
||||
{
|
||||
string result = reportPvt(cell_, pvt, digits);
|
||||
std::string result = reportPvt(cell_, pvt, digits);
|
||||
result += reportTableLookup("Delay", pvt, delay_model_.get(), in_slew,
|
||||
load_cap, 0.0, digits);
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::earlyIndex()])
|
||||
result += reportTableLookup("Delay sigma(early)", pvt,
|
||||
delay_sigma_models_[EarlyLate::earlyIndex()].get(),
|
||||
delay_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, 0.0, digits);
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::lateIndex()])
|
||||
result += reportTableLookup("Delay sigma(late)", pvt,
|
||||
delay_sigma_models_[EarlyLate::lateIndex()].get(),
|
||||
delay_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, 0.0, digits);
|
||||
result += '\n';
|
||||
result += reportTableLookup("Slew", pvt, slew_model_.get(), in_slew,
|
||||
load_cap, 9.0, digits);
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::earlyIndex()])
|
||||
result += reportTableLookup("Slew sigma(early)", pvt,
|
||||
slew_sigma_models_[EarlyLate::earlyIndex()].get(),
|
||||
slew_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, 0.0, digits);
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::lateIndex()])
|
||||
result += reportTableLookup("Slew sigma(late)", pvt,
|
||||
slew_sigma_models_[EarlyLate::lateIndex()].get(),
|
||||
slew_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, 0.0, digits);
|
||||
float drvr_slew = findValue(pvt, slew_model_.get(), in_slew, load_cap, 0.0);
|
||||
if (drvr_slew < 0.0)
|
||||
|
|
@ -189,7 +191,7 @@ GateTableModel::reportGateDelay(const Pvt *pvt,
|
|||
return result;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
GateTableModel::reportTableLookup(const char *result_name,
|
||||
const Pvt *pvt,
|
||||
const TableModel *model,
|
||||
|
|
@ -285,13 +287,13 @@ GateTableModel::driveResistance(const Pvt *pvt) const
|
|||
const TableModel *
|
||||
GateTableModel::delaySigmaModel(const EarlyLate *el) const
|
||||
{
|
||||
return delay_sigma_models_[el->index()].get();
|
||||
return delay_sigma_models_[el->index()];
|
||||
}
|
||||
|
||||
const TableModel *
|
||||
GateTableModel::slewSigmaModel(const EarlyLate *el) const
|
||||
{
|
||||
return slew_sigma_models_[el->index()].get();
|
||||
return slew_sigma_models_[el->index()];
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -354,7 +356,7 @@ GateTableModel::axisValue(const TableAxis *axis,
|
|||
}
|
||||
|
||||
bool
|
||||
GateTableModel::checkAxes(const TablePtr &table)
|
||||
GateTableModel::checkAxes(const TableModel *table)
|
||||
{
|
||||
const TableAxis *axis1 = table->axis1();
|
||||
const TableAxis *axis2 = table->axis2();
|
||||
|
|
@ -395,7 +397,7 @@ ReceiverModel::setCapacitanceModel(TableModel table_model,
|
|||
}
|
||||
|
||||
bool
|
||||
ReceiverModel::checkAxes(TablePtr table)
|
||||
ReceiverModel::checkAxes(const TableModel *table)
|
||||
{
|
||||
const TableAxis *axis1 = table->axis1();
|
||||
const TableAxis *axis2 = table->axis2();
|
||||
|
|
@ -415,14 +417,25 @@ ReceiverModel::checkAxes(TablePtr table)
|
|||
|
||||
CheckTableModel::CheckTableModel(LibertyCell *cell,
|
||||
TableModel *model,
|
||||
TableModel *sigma_models[EarlyLate::index_count]) :
|
||||
TableModelsEarlyLate sigma_models) :
|
||||
CheckTimingModel(cell),
|
||||
model_(model)
|
||||
model_(model),
|
||||
sigma_models_(std::move(sigma_models))
|
||||
{
|
||||
sigmaModelsMvOwner(sigma_models, sigma_models_);
|
||||
}
|
||||
|
||||
CheckTableModel::~CheckTableModel() = default;
|
||||
CheckTableModel::CheckTableModel(LibertyCell *cell,
|
||||
TableModel *model) :
|
||||
CheckTimingModel(cell),
|
||||
model_(model),
|
||||
sigma_models_{}
|
||||
{
|
||||
}
|
||||
|
||||
CheckTableModel::~CheckTableModel()
|
||||
{
|
||||
sigmaModelsDelete(sigma_models_);
|
||||
}
|
||||
|
||||
void
|
||||
CheckTableModel::setIsScaled(bool is_scaled)
|
||||
|
|
@ -434,7 +447,7 @@ CheckTableModel::setIsScaled(bool is_scaled)
|
|||
const TableModel *
|
||||
CheckTableModel::sigmaModel(const EarlyLate *el) const
|
||||
{
|
||||
return sigma_models_[el->index()].get();
|
||||
return sigma_models_[el->index()];
|
||||
}
|
||||
|
||||
ArcDelay
|
||||
|
|
@ -449,10 +462,10 @@ CheckTableModel::checkDelay(const Pvt *pvt,
|
|||
float sigma_early = 0.0;
|
||||
float sigma_late = 0.0;
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::earlyIndex()])
|
||||
sigma_early = findValue(pvt, sigma_models_[EarlyLate::earlyIndex()].get(),
|
||||
sigma_early = findValue(pvt, sigma_models_[EarlyLate::earlyIndex()],
|
||||
from_slew, to_slew, related_out_cap);
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::lateIndex()])
|
||||
sigma_late = findValue(pvt, sigma_models_[EarlyLate::lateIndex()].get(),
|
||||
sigma_late = findValue(pvt, sigma_models_[EarlyLate::lateIndex()],
|
||||
from_slew, to_slew, related_out_cap);
|
||||
return makeDelay(mean, sigma_early, sigma_late);
|
||||
}
|
||||
|
|
@ -477,7 +490,7 @@ CheckTableModel::findValue(const Pvt *pvt,
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
CheckTableModel::reportCheckDelay(const Pvt *pvt,
|
||||
float from_slew,
|
||||
const char *from_slew_annotation,
|
||||
|
|
@ -486,23 +499,23 @@ CheckTableModel::reportCheckDelay(const Pvt *pvt,
|
|||
bool pocv_enabled,
|
||||
int digits) const
|
||||
{
|
||||
string result = reportTableDelay("Check", pvt, model_.get(),
|
||||
std::string result = reportTableDelay("Check", pvt, model_.get(),
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits);
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::earlyIndex()])
|
||||
result += reportTableDelay("Check sigma early", pvt,
|
||||
sigma_models_[EarlyLate::earlyIndex()].get(),
|
||||
sigma_models_[EarlyLate::earlyIndex()],
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits);
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::lateIndex()])
|
||||
result += reportTableDelay("Check sigma late", pvt,
|
||||
sigma_models_[EarlyLate::lateIndex()].get(),
|
||||
sigma_models_[EarlyLate::lateIndex()],
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits);
|
||||
return result;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
CheckTableModel::reportTableDelay(const char *result_name,
|
||||
const Pvt *pvt,
|
||||
const TableModel *model,
|
||||
|
|
@ -516,7 +529,7 @@ CheckTableModel::reportTableDelay(const char *result_name,
|
|||
float axis_value1, axis_value2, axis_value3;
|
||||
findAxisValues(from_slew, to_slew, related_out_cap,
|
||||
axis_value1, axis_value2, axis_value3);
|
||||
string result = reportPvt(cell_, pvt, digits);
|
||||
std::string result = reportPvt(cell_, pvt, digits);
|
||||
result += model_->reportValue(result_name, cell_, pvt,
|
||||
axis_value1, from_slew_annotation, axis_value2,
|
||||
axis_value3,
|
||||
|
|
@ -587,7 +600,7 @@ CheckTableModel::axisValue(const TableAxis *axis,
|
|||
}
|
||||
|
||||
bool
|
||||
CheckTableModel::checkAxes(const TablePtr table)
|
||||
CheckTableModel::checkAxes(const TableModel *table)
|
||||
{
|
||||
const TableAxis *axis1 = table->axis1();
|
||||
const TableAxis *axis2 = table->axis2();
|
||||
|
|
@ -716,7 +729,7 @@ TableModel::scaleFactor(const LibertyCell *cell,
|
|||
rf_index_, cell, pvt);
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
TableModel::reportValue(const char *result_name,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
|
|
@ -727,7 +740,7 @@ TableModel::reportValue(const char *result_name,
|
|||
const Unit *table_unit,
|
||||
int digits) const
|
||||
{
|
||||
string result = table_->reportValue("Table value", cell, pvt, value1,
|
||||
std::string result = table_->reportValue("Table value", cell, pvt, value1,
|
||||
comment1, value2, value3, table_unit, digits);
|
||||
|
||||
result += reportPvtScaleFactor(cell, pvt, digits);
|
||||
|
|
@ -739,7 +752,7 @@ TableModel::reportValue(const char *result_name,
|
|||
return result;
|
||||
}
|
||||
|
||||
static string
|
||||
static std::string
|
||||
reportPvt(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
int digits)
|
||||
|
|
@ -748,7 +761,7 @@ reportPvt(const LibertyCell *cell,
|
|||
if (pvt == nullptr)
|
||||
pvt = library->defaultOperatingConditions();
|
||||
if (pvt) {
|
||||
string result;
|
||||
std::string result;
|
||||
stringPrint(result, "P = %.*f V = %.*f T = %.*f\n",
|
||||
digits, pvt->process(),
|
||||
digits, pvt->voltage(),
|
||||
|
|
@ -758,7 +771,7 @@ reportPvt(const LibertyCell *cell,
|
|||
return "";
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
TableModel::reportPvtScaleFactor(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
int digits) const
|
||||
|
|
@ -766,7 +779,7 @@ TableModel::reportPvtScaleFactor(const LibertyCell *cell,
|
|||
if (pvt == nullptr)
|
||||
pvt = cell->libertyLibrary()->defaultOperatingConditions();
|
||||
if (pvt) {
|
||||
string result;
|
||||
std::string result;
|
||||
stringPrint(result, "PVT scale factor = %.*f\n",
|
||||
digits,
|
||||
scaleFactor(cell, pvt));
|
||||
|
|
@ -1147,7 +1160,7 @@ Table::reportValueOrder0(const char *result_name,
|
|||
const Unit *table_unit,
|
||||
int digits) const
|
||||
{
|
||||
string result = result_name;
|
||||
std::string result = result_name;
|
||||
result += " constant = ";
|
||||
result += table_unit->asString(value_, digits);
|
||||
if (comment1)
|
||||
|
|
@ -1168,7 +1181,7 @@ Table::reportValueOrder1(const char *result_name,
|
|||
{
|
||||
const Units *units = cell->libertyLibrary()->units();
|
||||
const Unit *unit1 = axis1_->unit(units);
|
||||
string result = "Table is indexed by\n ";
|
||||
std::string result = "Table is indexed by\n ";
|
||||
result += axis1_->variableString();
|
||||
result += " = ";
|
||||
result += unit1->asString(value1, digits);
|
||||
|
|
@ -1209,7 +1222,7 @@ Table::reportValueOrder2(const char *result_name,
|
|||
const Units *units = cell->libertyLibrary()->units();
|
||||
const Unit *unit1 = axis1_->unit(units);
|
||||
const Unit *unit2 = axis2_->unit(units);
|
||||
string result = "------- ";
|
||||
std::string result = "------- ";
|
||||
result += axis1_->variableString();
|
||||
result += " = ";
|
||||
result += unit1->asString(value1, digits);
|
||||
|
|
@ -1270,7 +1283,7 @@ Table::reportValueOrder3(const char *result_name,
|
|||
const Unit *unit1 = axis1_->unit(units);
|
||||
const Unit *unit2 = axis2_->unit(units);
|
||||
const Unit *unit3 = axis3_->unit(units);
|
||||
string result = " --------- ";
|
||||
std::string result = " --------- ";
|
||||
result += axis1_->variableString();
|
||||
result += " = ";
|
||||
result += unit1->asString(value1, digits);
|
||||
|
|
@ -1372,7 +1385,7 @@ Table::report(const Units *units,
|
|||
const Unit *unit1 = axis1_->unit(units);
|
||||
report->reportLine("%s", tableVariableString(axis1_->variable()));
|
||||
report->reportLine("------------------------------");
|
||||
string line;
|
||||
std::string line;
|
||||
for (size_t index1 = 0; index1 < axis1_->size(); index1++) {
|
||||
line += unit1->asString(axis1_->axisValue(index1), digits);
|
||||
line += " ";
|
||||
|
|
@ -1391,7 +1404,7 @@ Table::report(const Units *units,
|
|||
const Unit *unit2 = axis2_->unit(units);
|
||||
report->reportLine("%s", tableVariableString(axis2_->variable()));
|
||||
report->reportLine(" ------------------------------");
|
||||
string line = " ";
|
||||
std::string line = " ";
|
||||
for (size_t index2 = 0; index2 < axis2_->size(); index2++) {
|
||||
line += unit2->asString(axis2_->axisValue(index2), digits);
|
||||
line += " ";
|
||||
|
|
@ -1417,7 +1430,7 @@ Table::report(const Units *units,
|
|||
unit1->asString(axis1_->axisValue(axis_index1), digits));
|
||||
report->reportLine("%s", tableVariableString(axis3_->variable()));
|
||||
report->reportLine(" ------------------------------");
|
||||
string line = " ";
|
||||
std::string line = " ";
|
||||
for (size_t axis_index3 = 0; axis_index3 < axis3_->size(); axis_index3++) {
|
||||
line += unit3->asString(axis3_->axisValue(axis_index3), digits);
|
||||
line += " ";
|
||||
|
|
@ -1436,7 +1449,7 @@ Table::report(const Units *units,
|
|||
}
|
||||
|
||||
static void
|
||||
appendSpaces(string &result,
|
||||
appendSpaces(std::string &result,
|
||||
int count)
|
||||
{
|
||||
while (count--)
|
||||
|
|
@ -1736,7 +1749,7 @@ OutputWaveforms::findVoltages(size_t wave_index,
|
|||
// Make voltage -> current table.
|
||||
FloatSeq axis_volts = volts;
|
||||
TableAxisPtr volt_axis =
|
||||
make_shared<TableAxis>(TableAxisVariable::input_voltage, std::move(axis_volts));
|
||||
std::make_shared<TableAxis>(TableAxisVariable::input_voltage, std::move(axis_volts));
|
||||
FloatSeq *currents1 = new FloatSeq(*currents->values());
|
||||
Table *volt_currents = new Table(currents1, volt_axis);
|
||||
voltage_currents_[wave_index] = volt_currents;
|
||||
|
|
@ -1755,7 +1768,7 @@ OutputWaveforms::currentWaveform(float slew,
|
|||
times->push_back(time);
|
||||
currents->push_back(current);
|
||||
}
|
||||
TableAxisPtr time_axis = make_shared<TableAxis>(TableAxisVariable::time, std::move(*times));
|
||||
TableAxisPtr time_axis = std::make_shared<TableAxis>(TableAxisVariable::time, std::move(*times));
|
||||
delete times;
|
||||
return Table(currents, time_axis);
|
||||
}
|
||||
|
|
@ -1932,7 +1945,7 @@ OutputWaveforms::voltageWaveform(float slew,
|
|||
times.push_back(time);
|
||||
volts.push_back(volt);
|
||||
}
|
||||
TableAxisPtr time_axis = make_shared<TableAxis>(TableAxisVariable::time,
|
||||
TableAxisPtr time_axis = std::make_shared<TableAxis>(TableAxisVariable::time,
|
||||
std::move(times));
|
||||
return Table(std::move(volts), time_axis);
|
||||
}
|
||||
|
|
@ -2057,7 +2070,7 @@ OutputWaveforms::voltageCurrentWaveform(float slew,
|
|||
currents->push_back(current);
|
||||
}
|
||||
TableAxisPtr volt_axis =
|
||||
make_shared<TableAxis>(TableAxisVariable::input_voltage, std::move(*volts));
|
||||
std::make_shared<TableAxis>(TableAxisVariable::input_voltage, std::move(*volts));
|
||||
delete volts;
|
||||
return Table(currents, volt_axis);
|
||||
}
|
||||
|
|
@ -2076,12 +2089,12 @@ OutputWaveforms::finalResistance()
|
|||
const FloatSeq &voltages = voltage_currents->axis1()->values();
|
||||
FloatSeq *currents = voltage_currents->values();
|
||||
size_t idx_last1 = voltages.size() - 2;
|
||||
return (vdd_ - voltages[idx_last1]) / abs((*currents)[idx_last1]);
|
||||
return (vdd_ - voltages[idx_last1]) / std::abs((*currents)[idx_last1]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
DriverWaveform::DriverWaveform(const string &name,
|
||||
DriverWaveform::DriverWaveform(const std::string &name,
|
||||
TablePtr waveforms) :
|
||||
name_(name),
|
||||
waveforms_(waveforms)
|
||||
|
|
@ -2099,7 +2112,7 @@ DriverWaveform::waveform(float slew)
|
|||
time_values->push_back(time);
|
||||
volt_values->push_back(volt);
|
||||
}
|
||||
TableAxisPtr time_axis = make_shared<TableAxis>(TableAxisVariable::time,
|
||||
TableAxisPtr time_axis = std::make_shared<TableAxis>(TableAxisVariable::time,
|
||||
std::move(*time_values));
|
||||
delete time_values;
|
||||
Table waveform(volt_values, time_axis);
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
using std::make_shared;
|
||||
|
||||
static bool
|
||||
timingArcsEquiv(const TimingArcSet *set1,
|
||||
const TimingArcSet *set2);
|
||||
|
|
@ -204,6 +201,15 @@ TimingArcSet::TimingArcSet(const TimingRole *role,
|
|||
{
|
||||
}
|
||||
|
||||
std::string
|
||||
TimingArcSet::to_string()
|
||||
{
|
||||
std::string str = from_->name();
|
||||
str += " -> ";
|
||||
str += to_->name();
|
||||
return str;
|
||||
}
|
||||
|
||||
TimingArcSet::~TimingArcSet()
|
||||
{
|
||||
deleteContents(arcs_);
|
||||
|
|
@ -326,7 +332,7 @@ TimingArcSet::isRisingFallingEdge() const
|
|||
if (from_rf1 == from_rf2)
|
||||
return from_rf1;
|
||||
}
|
||||
if (arcs_.size() == 1)
|
||||
if (arc_count == 1)
|
||||
return arcs_[0]->fromEdge()->asRiseFall();
|
||||
else
|
||||
return nullptr;
|
||||
|
|
@ -501,7 +507,7 @@ TimingArcSet::wireArcIndex(const RiseFall *rf)
|
|||
void
|
||||
TimingArcSet::init()
|
||||
{
|
||||
wire_timing_arc_attrs_ = make_shared<TimingArcAttrs>(TimingSense::positive_unate);
|
||||
wire_timing_arc_attrs_ = std::make_shared<TimingArcAttrs>(TimingSense::positive_unate);
|
||||
wire_timing_arc_set_ = new TimingArcSet(TimingRole::wire(), wire_timing_arc_attrs_);
|
||||
new TimingArc(wire_timing_arc_set_, Transition::rise(),
|
||||
Transition::rise(), nullptr);
|
||||
|
|
@ -539,18 +545,18 @@ TimingArc::~TimingArc()
|
|||
delete scaled_models_;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
TimingArc::to_string() const
|
||||
{
|
||||
if (set_->role()->isWire()) {
|
||||
string str = "wire ";
|
||||
std::string str = "wire ";
|
||||
str += from_rf_->to_string();
|
||||
str += " -> ";
|
||||
str += to_rf_->to_string();
|
||||
return str;
|
||||
}
|
||||
else {
|
||||
string str = set_->from()->name();
|
||||
std::string str = set_->from()->name();
|
||||
str += " ";
|
||||
str += from_rf_->to_string();
|
||||
str += " -> ";
|
||||
|
|
@ -622,7 +628,7 @@ TimingArc::equiv(const TimingArc *arc1,
|
|||
}
|
||||
|
||||
void
|
||||
TimingArc::setIndex(unsigned index)
|
||||
TimingArc::setIndex(size_t index)
|
||||
{
|
||||
index_ = index;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,6 +163,12 @@ TimingRole::isLatchDtoQ() const
|
|||
return this == &latch_d_q_;
|
||||
}
|
||||
|
||||
bool
|
||||
TimingRole::isLatchEnToQ() const
|
||||
{
|
||||
return this == &latch_en_q_;
|
||||
}
|
||||
|
||||
bool
|
||||
TimingRole::isTimingCheckBetween() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,9 +32,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::abs;
|
||||
|
||||
|
||||
Unit::Unit(const char *suffix) :
|
||||
scale_(1.0),
|
||||
suffix_(suffix),
|
||||
|
|
@ -175,12 +172,12 @@ Unit::asString(float value,
|
|||
int digits) const
|
||||
{
|
||||
// Special case INF because it blows up otherwise.
|
||||
if (abs(value) >= INF * .1)
|
||||
if (std::abs(value) >= INF * .1)
|
||||
return (value > 0.0) ? "INF" : "-INF";
|
||||
else {
|
||||
float scaled_value = value / scale_;
|
||||
// prevent "-0.00" on slowaris
|
||||
if (abs(scaled_value) < 1E-6)
|
||||
if (std::abs(scaled_value) < 1E-6)
|
||||
scaled_value = 0.0;
|
||||
return stringPrintTmp("%.*f", digits, scaled_value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "ConcreteLibrary.hh"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
|
||||
|
|
@ -35,13 +36,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
using std::map;
|
||||
using std::min;
|
||||
using std::max;
|
||||
using std::abs;
|
||||
using std::swap;
|
||||
|
||||
static constexpr char escape_ = '\\';
|
||||
|
||||
ConcreteLibrary::ConcreteLibrary(const char *name,
|
||||
|
|
@ -228,7 +222,7 @@ ConcreteCell::makeBusPortBit(ConcretePort *bus_port,
|
|||
const char *bus_name,
|
||||
int bit_index)
|
||||
{
|
||||
string bit_name;
|
||||
std::string bit_name;
|
||||
stringPrint(bit_name, "%s%c%d%c",
|
||||
bus_name,
|
||||
library_->busBrktLeft(),
|
||||
|
|
@ -272,14 +266,14 @@ ConcreteCell::setIsLeaf(bool is_leaf)
|
|||
}
|
||||
|
||||
void
|
||||
ConcreteCell::setAttribute(const string &key,
|
||||
const string &value)
|
||||
ConcreteCell::setAttribute(const std::string &key,
|
||||
const std::string &value)
|
||||
{
|
||||
attribute_map_[key] = value;
|
||||
}
|
||||
|
||||
string
|
||||
ConcreteCell::getAttribute(const string &key) const
|
||||
std::string
|
||||
ConcreteCell::getAttribute(const std::string &key) const
|
||||
{
|
||||
const auto &itr = attribute_map_.find(key);
|
||||
if (itr != attribute_map_.end())
|
||||
|
|
@ -350,8 +344,8 @@ void
|
|||
BusPort::addBusBit(ConcretePort *port,
|
||||
int index)
|
||||
{
|
||||
from_ = min(from_, index);
|
||||
to_ = max(to_, index);
|
||||
from_ = std::min(from_, index);
|
||||
to_ = std::max(to_, index);
|
||||
members_.push_back(port);
|
||||
}
|
||||
|
||||
|
|
@ -362,7 +356,7 @@ ConcreteCell::groupBusPorts(const char bus_brkt_left,
|
|||
{
|
||||
const char bus_brkts_left[2]{bus_brkt_left, '\0'};
|
||||
const char bus_brkts_right[2]{bus_brkt_right, '\0'};
|
||||
map<string, BusPort> bus_map;
|
||||
std::map<std::string, BusPort> bus_map;
|
||||
// Find ungrouped bus ports.
|
||||
// Remove bus bit ports from the ports_ vector during the scan by
|
||||
// keeping an index to the next insertion index and skipping over
|
||||
|
|
@ -372,7 +366,7 @@ ConcreteCell::groupBusPorts(const char bus_brkt_left,
|
|||
for (ConcretePort *port : ports) {
|
||||
const char *port_name = port->name();
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
std::string bus_name;
|
||||
int index;
|
||||
parseBusName(port_name, bus_brkts_left, bus_brkts_right, escape_,
|
||||
is_bus, bus_name, index);
|
||||
|
|
@ -402,7 +396,7 @@ ConcreteCell::groupBusPorts(const char bus_brkt_left,
|
|||
(*members)[member_index] = bus_bit;
|
||||
}
|
||||
if (msb_first)
|
||||
swap(from, to);
|
||||
std::swap(from, to);
|
||||
ConcretePort *port = makeBusPort(bus_name.c_str(), from, to, members);
|
||||
port->setDirection(bus_port.direction());
|
||||
}
|
||||
|
|
@ -505,7 +499,7 @@ int
|
|||
ConcretePort::size() const
|
||||
{
|
||||
if (is_bus_)
|
||||
return abs(to_index_ - from_index_) + 1;
|
||||
return std::abs(to_index_ - from_index_) + 1;
|
||||
else if (is_bundle_)
|
||||
return static_cast<int>(member_ports_->size());
|
||||
else
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
static void
|
||||
makeChildNetwork(Instance *proto,
|
||||
Instance *parent,
|
||||
|
|
@ -64,8 +62,8 @@ class ConcreteInstanceChildIterator : public InstanceChildIterator
|
|||
{
|
||||
public:
|
||||
ConcreteInstanceChildIterator(ConcreteInstanceChildMap *map);
|
||||
bool hasNext();
|
||||
Instance *next();
|
||||
bool hasNext() override;
|
||||
Instance *next() override;
|
||||
|
||||
private:
|
||||
ConcreteInstanceChildMap *map_;
|
||||
|
|
@ -98,8 +96,8 @@ class ConcreteInstanceNetIterator : public InstanceNetIterator
|
|||
{
|
||||
public:
|
||||
ConcreteInstanceNetIterator(ConcreteInstanceNetMap *nets);
|
||||
bool hasNext();
|
||||
Net *next();
|
||||
bool hasNext() override;
|
||||
Net *next() override;
|
||||
|
||||
private:
|
||||
void findNext();
|
||||
|
|
@ -154,8 +152,8 @@ class ConcreteInstancePinIterator : public InstancePinIterator
|
|||
public:
|
||||
ConcreteInstancePinIterator(const ConcreteInstance *inst,
|
||||
int pin_count);
|
||||
bool hasNext();
|
||||
Pin *next();
|
||||
bool hasNext() override;
|
||||
Pin *next() override;
|
||||
|
||||
private:
|
||||
void findNext();
|
||||
|
|
@ -208,8 +206,8 @@ class ConcreteNetPinIterator : public NetPinIterator
|
|||
{
|
||||
public:
|
||||
ConcreteNetPinIterator(const ConcreteNet *net);
|
||||
bool hasNext();
|
||||
Pin *next();
|
||||
bool hasNext() override;
|
||||
Pin *next() override;
|
||||
|
||||
private:
|
||||
ConcretePin *next_;
|
||||
|
|
@ -240,8 +238,8 @@ class ConcreteNetTermIterator : public NetTermIterator
|
|||
{
|
||||
public:
|
||||
ConcreteNetTermIterator(const ConcreteNet *net);
|
||||
bool hasNext();
|
||||
Term *next();
|
||||
bool hasNext() override;
|
||||
Term *next() override;
|
||||
|
||||
private:
|
||||
ConcreteTerm *next_;
|
||||
|
|
@ -324,8 +322,8 @@ class ConcreteLibraryIterator1 : public Iterator<Library*>
|
|||
{
|
||||
public:
|
||||
ConcreteLibraryIterator1(const ConcreteLibrarySeq &libs);
|
||||
virtual bool hasNext();
|
||||
virtual Library *next();
|
||||
bool hasNext() override;
|
||||
Library *next() override;
|
||||
|
||||
private:
|
||||
const ConcreteLibrarySeq &libs_;
|
||||
|
|
@ -363,8 +361,8 @@ class ConcreteLibertyLibraryIterator : public Iterator<LibertyLibrary*>
|
|||
public:
|
||||
ConcreteLibertyLibraryIterator(const ConcreteNetwork *network);
|
||||
virtual ~ConcreteLibertyLibraryIterator();
|
||||
virtual bool hasNext();
|
||||
virtual LibertyLibrary *next();
|
||||
bool hasNext() override;
|
||||
LibertyLibrary *next() override;
|
||||
|
||||
private:
|
||||
void findNext();
|
||||
|
|
@ -581,8 +579,8 @@ ConcreteNetwork::setIsLeaf(Cell *cell,
|
|||
|
||||
void
|
||||
ConcreteNetwork::setAttribute(Cell *cell,
|
||||
const string &key,
|
||||
const string &value)
|
||||
const std::string &key,
|
||||
const std::string &value)
|
||||
{
|
||||
ConcreteCell *ccell = reinterpret_cast<ConcreteCell*>(cell);
|
||||
ccell->setAttribute(key, value);
|
||||
|
|
@ -628,9 +626,9 @@ ConcreteNetwork::filename(const Cell *cell)
|
|||
return ccell->filename();
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
ConcreteNetwork::getAttribute(const Cell *cell,
|
||||
const string &key) const
|
||||
const std::string &key) const
|
||||
{
|
||||
const ConcreteCell *ccell = reinterpret_cast<const ConcreteCell*>(cell);
|
||||
return ccell->getAttribute(key);
|
||||
|
|
@ -721,8 +719,8 @@ class ConcreteCellPortIterator1 : public CellPortIterator
|
|||
public:
|
||||
ConcreteCellPortIterator1(const ConcreteCell *cell);
|
||||
~ConcreteCellPortIterator1();
|
||||
virtual bool hasNext() { return iter_->hasNext(); }
|
||||
virtual Port *next();
|
||||
bool hasNext() override { return iter_->hasNext(); }
|
||||
Port *next() override;
|
||||
|
||||
private:
|
||||
ConcreteCellPortIterator *iter_;
|
||||
|
|
@ -758,8 +756,8 @@ class ConcreteCellPortBitIterator1 : public CellPortIterator
|
|||
public:
|
||||
ConcreteCellPortBitIterator1(const ConcreteCell *cell);
|
||||
~ConcreteCellPortBitIterator1();
|
||||
virtual bool hasNext() { return iter_->hasNext(); }
|
||||
virtual Port *next();
|
||||
bool hasNext() override { return iter_->hasNext(); }
|
||||
Port *next() override;
|
||||
|
||||
private:
|
||||
ConcreteCellPortBitIterator *iter_;
|
||||
|
|
@ -905,8 +903,8 @@ class ConcretePortMemberIterator1 : public PortMemberIterator
|
|||
public:
|
||||
ConcretePortMemberIterator1(const ConcretePort *port);
|
||||
~ConcretePortMemberIterator1();
|
||||
virtual bool hasNext();
|
||||
virtual Port *next();
|
||||
bool hasNext() override;
|
||||
Port *next() override;
|
||||
|
||||
private:
|
||||
ConcretePortMemberIterator *iter_;
|
||||
|
|
@ -967,9 +965,9 @@ ConcreteNetwork::id(const Instance *instance) const
|
|||
return inst->id();
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
ConcreteNetwork::getAttribute(const Instance *inst,
|
||||
const string &key) const
|
||||
const std::string &key) const
|
||||
{
|
||||
const ConcreteInstance *cinst = reinterpret_cast<const ConcreteInstance*>(inst);
|
||||
return cinst->getAttribute(key);
|
||||
|
|
@ -1389,8 +1387,8 @@ ConcreteNetwork::connect(Instance *inst,
|
|||
|
||||
void
|
||||
ConcreteNetwork::setAttribute(Instance *inst,
|
||||
const string &key,
|
||||
const string &value)
|
||||
const std::string &key,
|
||||
const std::string &value)
|
||||
{
|
||||
ConcreteInstance *cinst = reinterpret_cast<ConcreteInstance*>(inst);
|
||||
cinst->setAttribute(key, value);
|
||||
|
|
@ -1718,14 +1716,14 @@ ConcreteInstance::childIterator() const
|
|||
}
|
||||
|
||||
void
|
||||
ConcreteInstance::setAttribute(const string &key,
|
||||
const string &value)
|
||||
ConcreteInstance::setAttribute(const std::string &key,
|
||||
const std::string &value)
|
||||
{
|
||||
attribute_map_[key] = value;
|
||||
}
|
||||
|
||||
string
|
||||
ConcreteInstance::getAttribute(const string &key) const
|
||||
std::string
|
||||
ConcreteInstance::getAttribute(const std::string &key) const
|
||||
{
|
||||
const auto &itr = attribute_map_.find(key);
|
||||
if (itr != attribute_map_.end())
|
||||
|
|
|
|||
|
|
@ -37,8 +37,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
Network::Network() :
|
||||
default_liberty_(nullptr),
|
||||
divider_('/'),
|
||||
|
|
@ -76,7 +74,7 @@ Network::findPortsMatching(const Cell *cell,
|
|||
{
|
||||
PortSeq matches;
|
||||
bool is_bus, is_range, subscript_wild;
|
||||
string bus_name;
|
||||
std::string bus_name;
|
||||
int from, to;
|
||||
parseBusName(pattern->pattern(), '[', ']', '\\',
|
||||
is_bus, is_range, bus_name, from, to, subscript_wild);
|
||||
|
|
@ -1043,12 +1041,12 @@ Network::findInstPinsHierMatching(const Instance *instance,
|
|||
// Return value.
|
||||
PinSeq &matches) const
|
||||
{
|
||||
string inst_name = name(instance);
|
||||
std::string inst_name = name(instance);
|
||||
InstancePinIterator *pin_iter = pinIterator(instance);
|
||||
while (pin_iter->hasNext()) {
|
||||
const Pin *pin = pin_iter->next();
|
||||
const char *port_name = name(port(pin));
|
||||
string pin_name = inst_name + divider_ + port_name;
|
||||
std::string pin_name = inst_name + divider_ + port_name;
|
||||
if (pattern->match(pin_name.c_str()))
|
||||
matches.push_back(pin);
|
||||
}
|
||||
|
|
@ -1223,8 +1221,8 @@ class LeafInstanceIterator1 : public LeafInstanceIterator
|
|||
public:
|
||||
LeafInstanceIterator1(const Instance *inst,
|
||||
const Network *network);
|
||||
bool hasNext() { return next_; }
|
||||
Instance *next();
|
||||
bool hasNext() override { return next_; }
|
||||
Instance *next() override;
|
||||
|
||||
private:
|
||||
void nextInst();
|
||||
|
|
@ -1368,8 +1366,8 @@ class ConnectedPinIterator1 : public ConnectedPinIterator
|
|||
public:
|
||||
ConnectedPinIterator1(PinSet *pins);
|
||||
virtual ~ConnectedPinIterator1();
|
||||
virtual bool hasNext();
|
||||
virtual const Pin *next();
|
||||
bool hasNext() override;
|
||||
const Pin *next() override;
|
||||
|
||||
protected:
|
||||
PinSet *pins_;
|
||||
|
|
|
|||
|
|
@ -638,13 +638,16 @@ InstancePinIterator *
|
|||
pin_iterator() { return Sta::sta()->ensureLinked()->pinIterator(self); }
|
||||
InstanceNetIterator *
|
||||
net_iterator() { return Sta::sta()->ensureLinked()->netIterator(self); }
|
||||
|
||||
Pin *
|
||||
find_pin(const char *name)
|
||||
{
|
||||
return Sta::sta()->ensureLinked()->findPin(self, name);
|
||||
}
|
||||
|
||||
std::string
|
||||
get_attribute(const char *key) {
|
||||
get_attribute(const char *key)
|
||||
{
|
||||
return Sta::sta()->ensureLinked()->getAttribute(self, key);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
bool
|
||||
isBusName(const char *name,
|
||||
const char brkt_left,
|
||||
|
|
@ -60,7 +58,7 @@ parseBusName(const char *name,
|
|||
const char escape,
|
||||
// Return values.
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
std::string &bus_name,
|
||||
int &index)
|
||||
{
|
||||
const char brkts_left[2] = {brkt_left, '\0'};
|
||||
|
|
@ -76,7 +74,7 @@ parseBusName(const char *name,
|
|||
char escape,
|
||||
// Return values.
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
std::string &bus_name,
|
||||
int &index)
|
||||
{
|
||||
is_bus = false;
|
||||
|
|
@ -110,7 +108,7 @@ parseBusName(const char *name,
|
|||
// Return values.
|
||||
bool &is_bus,
|
||||
bool &is_range,
|
||||
string &bus_name,
|
||||
std::string &bus_name,
|
||||
int &from,
|
||||
int &to,
|
||||
bool &subscript_wild)
|
||||
|
|
@ -129,7 +127,7 @@ parseBusName(const char *name,
|
|||
// Return values.
|
||||
bool &is_bus,
|
||||
bool &is_range,
|
||||
string &bus_name,
|
||||
std::string &bus_name,
|
||||
int &from,
|
||||
int &to,
|
||||
bool &subscript_wild)
|
||||
|
|
@ -173,13 +171,13 @@ parseBusName(const char *name,
|
|||
}
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
escapeChars(const char *token,
|
||||
const char ch1,
|
||||
const char ch2,
|
||||
const char escape)
|
||||
{
|
||||
string escaped;
|
||||
std::string escaped;
|
||||
for (const char *s = token; *s; s++) {
|
||||
char ch = *s;
|
||||
if (ch == escape) {
|
||||
|
|
|
|||
|
|
@ -30,13 +30,10 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
using std::to_string;
|
||||
|
||||
static string
|
||||
static std::string
|
||||
escapeDividers(const char *token,
|
||||
const Network *network);
|
||||
static string
|
||||
static std::string
|
||||
escapeBrackets(const char *token,
|
||||
const Network *network);
|
||||
|
||||
|
|
@ -137,9 +134,9 @@ NetworkNameAdapter::id(const Cell *cell) const
|
|||
return network_->id(cell);
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
NetworkNameAdapter::getAttribute(const Cell *cell,
|
||||
const string &key) const
|
||||
const std::string &key) const
|
||||
{
|
||||
return network_->getAttribute(cell, key);
|
||||
}
|
||||
|
|
@ -355,9 +352,9 @@ NetworkNameAdapter::cell(const Instance *instance) const
|
|||
return network_->cell(instance);
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
NetworkNameAdapter::getAttribute(const Instance *inst,
|
||||
const string &key) const
|
||||
const std::string &key) const
|
||||
{
|
||||
return network_->getAttribute(inst, key);
|
||||
}
|
||||
|
|
@ -675,16 +672,16 @@ SdcNetwork::findPort(const Cell *cell,
|
|||
if (port == nullptr) {
|
||||
// Look for matches after escaping brackets.
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
std::string bus_name;
|
||||
int index;
|
||||
parseBusName(name, '[', ']', pathEscape(), is_bus, bus_name, index);
|
||||
if (is_bus) {
|
||||
string escaped1 = escapeBrackets(name, this);
|
||||
std::string escaped1 = escapeBrackets(name, this);
|
||||
port = network_->findPort(cell, escaped1.c_str());
|
||||
if (port == nullptr) {
|
||||
// Try escaping base foo\[0\][1]
|
||||
string escaped2;
|
||||
string escaped_bus_name = escapeBrackets(bus_name.c_str(), this);
|
||||
std::string escaped2;
|
||||
std::string escaped_bus_name = escapeBrackets(bus_name.c_str(), this);
|
||||
stringPrint(escaped2, "%s[%d]",
|
||||
escaped_bus_name.c_str(),
|
||||
index);
|
||||
|
|
@ -693,7 +690,7 @@ SdcNetwork::findPort(const Cell *cell,
|
|||
}
|
||||
else {
|
||||
// Try escaping brackets foo\[0\].bar
|
||||
string escaped = escapeBrackets(name, this);
|
||||
std::string escaped = escapeBrackets(name, this);
|
||||
port = network_->findPort(cell, escaped.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -708,19 +705,19 @@ SdcNetwork::findPortsMatching(const Cell *cell,
|
|||
if (matches.empty()) {
|
||||
// Look for matches after escaping brackets.
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
std::string bus_name;
|
||||
int index;
|
||||
parseBusName(pattern->pattern(), '[', ']', pathEscape(),
|
||||
is_bus, bus_name, index);
|
||||
if (is_bus) {
|
||||
string escaped1 = escapeBrackets(pattern->pattern(), this);
|
||||
std::string escaped1 = escapeBrackets(pattern->pattern(), this);
|
||||
PatternMatch escaped_pattern1(escaped1.c_str(), pattern);
|
||||
matches = network_->findPortsMatching(cell, &escaped_pattern1);
|
||||
if (matches.empty()) {
|
||||
// Try escaping base foo\[0\][1]
|
||||
string escaped_name = escapeBrackets(bus_name.c_str(), this);
|
||||
std::string escaped_name = escapeBrackets(bus_name.c_str(), this);
|
||||
escaped_name += '[';
|
||||
escaped_name += to_string(index);
|
||||
escaped_name += std::to_string(index);
|
||||
escaped_name += ']';
|
||||
PatternMatch escaped_pattern2(escaped_name.c_str(), pattern);
|
||||
matches = network_->findPortsMatching(cell, &escaped_pattern2);
|
||||
|
|
@ -728,7 +725,7 @@ SdcNetwork::findPortsMatching(const Cell *cell,
|
|||
}
|
||||
else {
|
||||
// Try escaping brackets foo\[0\].bar
|
||||
string escaped = escapeBrackets(pattern->pattern(), this);
|
||||
std::string escaped = escapeBrackets(pattern->pattern(), this);
|
||||
PatternMatch escaped_pattern(escaped.c_str(), pattern);
|
||||
matches = network_->findPortsMatching(cell, &escaped_pattern);
|
||||
}
|
||||
|
|
@ -796,7 +793,7 @@ SdcNetwork::findInstance(const char *path_name) const
|
|||
parent = network_->topInstance();
|
||||
Instance *child = findChild(parent, child_name);
|
||||
if (child == nullptr) {
|
||||
string escaped_name = escapeDividers(child_name, this);
|
||||
std::string escaped_name = escapeDividers(child_name, this);
|
||||
child = findChild(parent, escaped_name.c_str());
|
||||
}
|
||||
return child;
|
||||
|
|
@ -808,10 +805,10 @@ SdcNetwork::findInstanceRelative(const Instance *inst,
|
|||
{
|
||||
Instance *inst1 = network_->findInstanceRelative(inst, path_name);
|
||||
if (inst1 == nullptr) {
|
||||
string path_name1 = escapeBrackets(path_name, this);
|
||||
std::string path_name1 = escapeBrackets(path_name, this);
|
||||
inst1 = network_->findInstanceRelative(inst, path_name1.c_str());
|
||||
if (inst1 == nullptr) {
|
||||
string path_name2 = escapeDividers(path_name1.c_str(), network_);
|
||||
std::string path_name2 = escapeDividers(path_name1.c_str(), network_);
|
||||
inst1 = network_->findInstanceRelative(inst, path_name2.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -848,7 +845,7 @@ SdcNetwork::findChild(const Instance *parent,
|
|||
{
|
||||
Instance *child = network_->findChild(parent, name);
|
||||
if (child == nullptr) {
|
||||
string escaped = escapeBrackets(name, this);
|
||||
std::string escaped = escapeBrackets(name, this);
|
||||
child = network_->findChild(parent, escaped.c_str());
|
||||
}
|
||||
return child;
|
||||
|
|
@ -873,8 +870,8 @@ SdcNetwork::findNet(const Instance *instance,
|
|||
{
|
||||
Net *net = network_->findNet(instance, net_name);
|
||||
if (net == nullptr) {
|
||||
string net_name1 = escapeBrackets(net_name, this);
|
||||
string net_name2 = escapeDividers(net_name1.c_str(), network_);
|
||||
std::string net_name1 = escapeBrackets(net_name, this);
|
||||
std::string net_name2 = escapeDividers(net_name1.c_str(), network_);
|
||||
net = network_->findNet(instance, net_name2.c_str());
|
||||
}
|
||||
return net;
|
||||
|
|
@ -886,15 +883,15 @@ SdcNetwork::findNetRelative(const Instance *inst,
|
|||
{
|
||||
Net *net = network_->findNetRelative(inst, path_name);
|
||||
if (net == nullptr) {
|
||||
string path_name1 = escapeDividers(path_name, network_);
|
||||
std::string path_name1 = escapeDividers(path_name, network_);
|
||||
net = network_->findNetRelative(inst, path_name1.c_str());
|
||||
|
||||
if (net == nullptr) {
|
||||
string path_name2 = escapeBrackets(path_name, network_);
|
||||
std::string path_name2 = escapeBrackets(path_name, network_);
|
||||
net = network_->findNetRelative(inst, path_name2.c_str());
|
||||
|
||||
if (net == nullptr) {
|
||||
string path_name3 = escapeDividers(path_name2.c_str(), network_);
|
||||
std::string path_name3 = escapeDividers(path_name2.c_str(), network_);
|
||||
net = network_->findNetRelative(inst, path_name3.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -926,12 +923,12 @@ SdcNetwork::findInstNetsMatching(const Instance *instance,
|
|||
network_->findInstNetsMatching(instance, pattern, matches);
|
||||
if (matches.empty()) {
|
||||
// Look for matches after escaping path dividers.
|
||||
string escaped_pattern = escapeDividers(pattern->pattern(), this);
|
||||
std::string escaped_pattern = escapeDividers(pattern->pattern(), this);
|
||||
const PatternMatch escaped_dividers(escaped_pattern.c_str(), pattern);
|
||||
network_->findInstNetsMatching(instance, &escaped_dividers, matches);
|
||||
if (matches.empty()) {
|
||||
// Look for matches after escaping brackets.
|
||||
string escaped_pattern2 = escapeBrackets(pattern->pattern(),this);
|
||||
std::string escaped_pattern2 = escapeBrackets(pattern->pattern(),this);
|
||||
const PatternMatch escaped_brkts(escaped_pattern2.c_str(), pattern);
|
||||
network_->findInstNetsMatching(instance, &escaped_brkts, matches);
|
||||
}
|
||||
|
|
@ -959,24 +956,24 @@ SdcNetwork::findPin(const Instance *instance,
|
|||
if (pin == nullptr) {
|
||||
// Look for match after escaping brackets.
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
std::string bus_name;
|
||||
int index;
|
||||
parseBusName(port_name, '[', ']', pathEscape(),
|
||||
is_bus, bus_name, index);
|
||||
if (is_bus) {
|
||||
string escaped1 = escapeBrackets(port_name, this);
|
||||
std::string escaped1 = escapeBrackets(port_name, this);
|
||||
pin = network_->findPin(instance, escaped1.c_str());
|
||||
if (pin == nullptr) {
|
||||
// Try escaping base foo\[0\][1]
|
||||
string escaped_bus_name = escapeBrackets(bus_name.c_str(), this);
|
||||
string escaped2;
|
||||
std::string escaped_bus_name = escapeBrackets(bus_name.c_str(), this);
|
||||
std::string escaped2;
|
||||
stringPrint(escaped2, "%s[%d]", escaped_bus_name.c_str(), index);
|
||||
pin = network_->findPin(instance, escaped2.c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Try escaping port brackets foo\[0\].bar
|
||||
string escaped = escapeBrackets(port_name, this);
|
||||
std::string escaped = escapeBrackets(port_name, this);
|
||||
pin = network_->findPin(instance, escaped.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -1028,7 +1025,7 @@ SdcNetwork::visitPinTail(const Instance *instance,
|
|||
if (network_->hasMembers(port)) {
|
||||
bool bus_matches = tail->match(port_name);
|
||||
if (!bus_matches) {
|
||||
string escaped_name = escapeDividers(port_name, network_);
|
||||
std::string escaped_name = escapeDividers(port_name, network_);
|
||||
bus_matches = tail->match(escaped_name);
|
||||
}
|
||||
PortMemberIterator *member_iter = network_->memberIterator(port);
|
||||
|
|
@ -1044,7 +1041,7 @@ SdcNetwork::visitPinTail(const Instance *instance,
|
|||
const char *member_name = network_->name(member_port);
|
||||
bool member_matches = tail->match(member_name);
|
||||
if (!member_matches) {
|
||||
string escaped_name = escapeDividers(member_name, network_);
|
||||
std::string escaped_name = escapeDividers(member_name, network_);
|
||||
member_matches = tail->match(escaped_name);
|
||||
}
|
||||
if (member_matches) {
|
||||
|
|
@ -1059,7 +1056,7 @@ SdcNetwork::visitPinTail(const Instance *instance,
|
|||
else {
|
||||
bool port_matches = tail->match(port_name);
|
||||
if (!port_matches) {
|
||||
string escaped_name = escapeDividers(port_name, network_);
|
||||
std::string escaped_name = escapeDividers(port_name, network_);
|
||||
port_matches = tail->match(escaped_name);
|
||||
}
|
||||
if (port_matches) {
|
||||
|
|
@ -1081,7 +1078,7 @@ SdcNetwork::makeInstance(LibertyCell *cell,
|
|||
const char *name,
|
||||
Instance *parent)
|
||||
{
|
||||
string escaped_name = escapeDividers(name, this);
|
||||
std::string escaped_name = escapeDividers(name, this);
|
||||
return network_edit_->makeInstance(cell, escaped_name.c_str(), parent);
|
||||
}
|
||||
|
||||
|
|
@ -1089,7 +1086,7 @@ Net *
|
|||
SdcNetwork::makeNet(const char *name,
|
||||
Instance *parent)
|
||||
{
|
||||
string escaped_name = escapeDividers(name, this);
|
||||
std::string escaped_name = escapeDividers(name, this);
|
||||
return network_edit_->makeNet(escaped_name.c_str(), parent);
|
||||
}
|
||||
|
||||
|
|
@ -1188,7 +1185,7 @@ SdcNetwork::parsePath(const char *path,
|
|||
else
|
||||
*p++ = ch;
|
||||
if (p - inst_path + 1 > inst_path_length)
|
||||
report_->critical(1500, "inst path string lenth estimate busted");
|
||||
report_->critical(1500, "inst path std::string lenth estimate busted");
|
||||
}
|
||||
*p = '\0';
|
||||
stringDelete(inst_path);
|
||||
|
|
@ -1235,7 +1232,7 @@ SdcNetwork::visitMatches(const Instance *parent,
|
|||
network_->findChildrenMatching(parent, &matcher, matches);
|
||||
if (has_brkts && matches.empty()) {
|
||||
// Look for matches after escaping brackets.
|
||||
string escaped_brkts = escapeBrackets(inst_path, this);
|
||||
std::string escaped_brkts = escapeBrackets(inst_path, this);
|
||||
const PatternMatch escaped_pattern(escaped_brkts, pattern);
|
||||
network_->findChildrenMatching(parent, &escaped_pattern, matches);
|
||||
}
|
||||
|
|
@ -1257,7 +1254,7 @@ SdcNetwork::visitMatches(const Instance *parent,
|
|||
*p++ = ch;
|
||||
}
|
||||
if (p - inst_path + 1 > inst_path_length)
|
||||
report_->critical(1501, "inst path string lenth estimate exceeded");
|
||||
report_->critical(1501, "inst path std::string lenth estimate exceeded");
|
||||
}
|
||||
*p = '\0';
|
||||
if (!found_match) {
|
||||
|
|
@ -1265,7 +1262,7 @@ SdcNetwork::visitMatches(const Instance *parent,
|
|||
found_match |= visit_tail(parent, &tail_pattern);
|
||||
if (!found_match && has_brkts) {
|
||||
// Look for matches after escaping brackets.
|
||||
string escaped_path = escapeBrackets(inst_path, this);
|
||||
std::string escaped_path = escapeBrackets(inst_path, this);
|
||||
const PatternMatch escaped_tail(escaped_path, pattern);
|
||||
found_match |= visit_tail(parent, &escaped_tail);
|
||||
}
|
||||
|
|
@ -1276,7 +1273,7 @@ SdcNetwork::visitMatches(const Instance *parent,
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
static string
|
||||
static std::string
|
||||
escapeDividers(const char *token,
|
||||
const Network *network)
|
||||
{
|
||||
|
|
@ -1284,7 +1281,7 @@ escapeDividers(const char *token,
|
|||
network->pathEscape());
|
||||
}
|
||||
|
||||
static string
|
||||
static std::string
|
||||
escapeBrackets(const char *token,
|
||||
const Network *network)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,39 +31,37 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
constexpr char verilog_escape = '\\';
|
||||
|
||||
static string
|
||||
static std::string
|
||||
staToVerilog(const char *sta_name);
|
||||
static string
|
||||
static std::string
|
||||
staToVerilog2(const char *sta_name);
|
||||
static string
|
||||
verilogToSta(const string *verilog_name);
|
||||
static std::string
|
||||
verilogToSta(const std::string *verilog_name);
|
||||
|
||||
string
|
||||
std::string
|
||||
cellVerilogName(const char *sta_name)
|
||||
{
|
||||
return staToVerilog(sta_name);
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
instanceVerilogName(const char *sta_name)
|
||||
{
|
||||
return staToVerilog(sta_name);
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
netVerilogName(const char *sta_name)
|
||||
{
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
std::string bus_name;
|
||||
int index;
|
||||
parseBusName(sta_name, '[', ']', verilog_escape, is_bus, bus_name, index);
|
||||
if (is_bus) {
|
||||
string bus_vname = staToVerilog(bus_name.c_str());
|
||||
string vname;
|
||||
std::string bus_vname = staToVerilog(bus_name.c_str());
|
||||
std::string vname;
|
||||
stringPrint(vname, "%s[%d]", bus_vname.c_str(), index);
|
||||
return vname;
|
||||
}
|
||||
|
|
@ -71,19 +69,19 @@ netVerilogName(const char *sta_name)
|
|||
return staToVerilog2(sta_name);
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
portVerilogName(const char *sta_name)
|
||||
{
|
||||
return staToVerilog2(sta_name);
|
||||
}
|
||||
|
||||
static string
|
||||
static std::string
|
||||
staToVerilog(const char *sta_name)
|
||||
{
|
||||
// Leave room for leading escape and trailing space if the name
|
||||
// needs to be escaped.
|
||||
// Assume the name has to be escaped and start copying while scanning.
|
||||
string escaped_name = "\\";
|
||||
std::string escaped_name = "\\";
|
||||
bool escaped = false;
|
||||
for (const char *s = sta_name; *s ; s++) {
|
||||
char ch = s[0];
|
||||
|
|
@ -107,17 +105,17 @@ staToVerilog(const char *sta_name)
|
|||
return escaped_name;
|
||||
}
|
||||
else
|
||||
return string(sta_name);
|
||||
return std::string(sta_name);
|
||||
}
|
||||
|
||||
static string
|
||||
static std::string
|
||||
staToVerilog2(const char *sta_name)
|
||||
{
|
||||
constexpr char bus_brkt_left = '[';
|
||||
constexpr char bus_brkt_right = ']';
|
||||
// Leave room for leading escape and trailing space if the name
|
||||
// needs to be escaped.
|
||||
string escaped_name = "\\";
|
||||
std::string escaped_name = "\\";
|
||||
// Assume the name has to be escaped and start copying while scanning.
|
||||
bool escaped = false;
|
||||
for (const char *s = sta_name; *s ; s++) {
|
||||
|
|
@ -144,37 +142,37 @@ staToVerilog2(const char *sta_name)
|
|||
return escaped_name;
|
||||
}
|
||||
else
|
||||
return string(sta_name);
|
||||
return std::string(sta_name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
string
|
||||
moduleVerilogToSta(const string *module_name)
|
||||
std::string
|
||||
moduleVerilogToSta(const std::string *module_name)
|
||||
{
|
||||
return verilogToSta(module_name);
|
||||
}
|
||||
|
||||
string
|
||||
instanceVerilogToSta(const string *inst_name)
|
||||
std::string
|
||||
instanceVerilogToSta(const std::string *inst_name)
|
||||
{
|
||||
return verilogToSta(inst_name);
|
||||
}
|
||||
|
||||
string
|
||||
netVerilogToSta(const string *net_name)
|
||||
std::string
|
||||
netVerilogToSta(const std::string *net_name)
|
||||
{
|
||||
return verilogToSta(net_name);
|
||||
}
|
||||
|
||||
string
|
||||
portVerilogToSta(const string *port_name)
|
||||
std::string
|
||||
portVerilogToSta(const std::string *port_name)
|
||||
{
|
||||
return verilogToSta(port_name);
|
||||
}
|
||||
|
||||
static string
|
||||
verilogToSta(const string *verilog_name)
|
||||
static std::string
|
||||
verilogToSta(const std::string *verilog_name)
|
||||
{
|
||||
if (verilog_name->front() == '\\') {
|
||||
constexpr char divider = '/';
|
||||
|
|
@ -184,7 +182,7 @@ verilogToSta(const string *verilog_name)
|
|||
size_t verilog_name_length = verilog_name->size();
|
||||
if (isspace(verilog_name->back()))
|
||||
verilog_name_length--;
|
||||
string sta_name;
|
||||
std::string sta_name;
|
||||
// Ignore leading '\'.
|
||||
for (size_t i = 1; i < verilog_name_length; i++) {
|
||||
char ch = verilog_name->at(i);
|
||||
|
|
@ -199,7 +197,7 @@ verilogToSta(const string *verilog_name)
|
|||
return sta_name;
|
||||
}
|
||||
else
|
||||
return string(*verilog_name);
|
||||
return std::string(*verilog_name);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -45,8 +45,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::max;
|
||||
|
||||
ConcreteParasitic::~ConcreteParasitic()
|
||||
{
|
||||
}
|
||||
|
|
@ -620,7 +618,7 @@ ConcreteParasiticNetwork::ensureParasiticNode(const Net *net,
|
|||
node = new ConcreteParasiticNode(net, id, network->highestNetAbove(net1) != net_);
|
||||
sub_nodes_[net_id] = node;
|
||||
if (net == net_)
|
||||
max_node_id_ = max((int) max_node_id_, id);
|
||||
max_node_id_ = std::max((int) max_node_id_, id);
|
||||
}
|
||||
else
|
||||
node = id_node->second;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "ReduceParasitics.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
|
|
@ -38,8 +39,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::max;
|
||||
|
||||
typedef std::map<ParasiticNode*, double> ParasiticNodeValueMap;
|
||||
typedef std::map<ParasiticResistor*, double> ResistorCurrentMap;
|
||||
typedef std::set<ParasiticResistor*> ParasiticResistorSet;
|
||||
|
|
@ -174,7 +173,7 @@ ReduceToPi::reducePiDfs(const Pin *drvr_pin,
|
|||
+ pinCapacitance(node);
|
||||
y1 = dwn_cap;
|
||||
y2 = y3 = 0.0;
|
||||
max_resistance = max(max_resistance, src_resistance);
|
||||
max_resistance = std::max(max_resistance, src_resistance);
|
||||
|
||||
visit(node);
|
||||
ParasiticResistorSeq &resistors = resistor_map_[node];
|
||||
|
|
@ -312,7 +311,7 @@ reduceToPiElmore(const Parasitic *parasitic_network,
|
|||
if (drvr_node) {
|
||||
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s %s %s",
|
||||
sta->network()->pathName(drvr_pin),
|
||||
rf->to_string().c_str(),
|
||||
rf->shortName(),
|
||||
min_max->to_string().c_str());
|
||||
ReduceToPiElmore reducer(sta);
|
||||
return reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include "Report.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "StringSeq.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "parasitics/SpefReaderPvt.hh"
|
||||
#include "parasitics/SpefScanner.hh"
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ sta::SpefParse::error(const location_type &loc,
|
|||
char *string;
|
||||
int integer;
|
||||
float number;
|
||||
sta::StringSeq *string_seq;
|
||||
sta::StringSeq *std_string_seq;
|
||||
sta::PortDirection *port_dir;
|
||||
sta::SpefRspfPi *pi;
|
||||
sta::SpefTriple *triple;
|
||||
|
|
@ -105,7 +105,7 @@ sta::SpefParse::error(const location_type &loc,
|
|||
|
||||
%type <ch> hchar suffix_bus_delim prefix_bus_delim
|
||||
|
||||
%type <string_seq> qstrings
|
||||
%type <std_string_seq> qstrings
|
||||
%type<port_dir> direction
|
||||
|
||||
%type<triple> par_value total_cap
|
||||
|
|
@ -222,9 +222,12 @@ qstrings:
|
|||
QSTRING
|
||||
{ $$ = new sta::StringSeq;
|
||||
$$->push_back($1);
|
||||
sta::stringDelete($1);
|
||||
}
|
||||
| qstrings QSTRING
|
||||
{ $$->push_back($2); }
|
||||
{ $$->push_back($2);
|
||||
sta::stringDelete($2);
|
||||
}
|
||||
;
|
||||
|
||||
hierarchy_div_def:
|
||||
|
|
|
|||
|
|
@ -43,8 +43,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
bool
|
||||
readSpefFile(const std::string &filename,
|
||||
Instance *instance,
|
||||
|
|
@ -94,7 +92,6 @@ SpefReader::SpefReader(const std::string &filename,
|
|||
cap_scale_(1.0),
|
||||
res_scale_(1.0),
|
||||
induct_scale_(1.0),
|
||||
design_flow_(nullptr),
|
||||
parasitics_(parasitics),
|
||||
parasitic_(nullptr)
|
||||
{
|
||||
|
|
@ -103,11 +100,6 @@ SpefReader::SpefReader(const std::string &filename,
|
|||
|
||||
SpefReader::~SpefReader()
|
||||
{
|
||||
if (design_flow_) {
|
||||
deleteContents(design_flow_);
|
||||
delete design_flow_;
|
||||
design_flow_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -301,7 +293,8 @@ SpefReader::portDirection(char *spef_dir)
|
|||
void
|
||||
SpefReader::setDesignFlow(StringSeq *flow)
|
||||
{
|
||||
design_flow_ = flow;
|
||||
design_flow_ = std::move(*flow);
|
||||
delete flow;
|
||||
}
|
||||
|
||||
Pin *
|
||||
|
|
@ -616,7 +609,7 @@ SpefTriple::value(int index) const
|
|||
////////////////////////////////////////////////////////////////
|
||||
|
||||
SpefScanner::SpefScanner(std::istream *stream,
|
||||
const string &filename,
|
||||
const std::string &filename,
|
||||
SpefReader *reader,
|
||||
Report *report) :
|
||||
yyFlexLexer(stream),
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
#include <map>
|
||||
|
||||
#include "Zlib.hh"
|
||||
#include "StringSeq.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "ParasiticsClass.hh"
|
||||
#include "StaState.hh"
|
||||
|
|
@ -139,7 +139,7 @@ private:
|
|||
float res_scale_;
|
||||
float induct_scale_;
|
||||
SpefNameMap name_map_;
|
||||
StringSeq *design_flow_;
|
||||
StringSeq design_flow_;
|
||||
Parasitics *parasitics_;
|
||||
Parasitic *parasitic_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -72,13 +72,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::abs;
|
||||
using std::max;
|
||||
using std::min;
|
||||
using std::isnormal;
|
||||
using std::vector;
|
||||
using std::map;
|
||||
|
||||
static bool
|
||||
isPositiveUnate(const LibertyCell *cell,
|
||||
const LibertyPort *from,
|
||||
|
|
@ -93,7 +86,6 @@ static EnumNameMap<PwrActivityOrigin> pwr_activity_origin_map =
|
|||
{PwrActivityOrigin::propagated, "propagated"},
|
||||
{PwrActivityOrigin::clock, "clock"},
|
||||
{PwrActivityOrigin::constant, "constant"},
|
||||
{PwrActivityOrigin::defaulted, "defaulted"},
|
||||
{PwrActivityOrigin::unknown, "unknown"}};
|
||||
|
||||
Power::Power(StaState *sta) :
|
||||
|
|
@ -292,7 +284,7 @@ Power::reportDesign(const Scene *scene,
|
|||
PowerResult total, sequential, combinational, clock, macro, pad;
|
||||
power(scene, total, sequential, combinational, clock, macro, pad);
|
||||
ReportPower report_power(this);
|
||||
report_power.reportDesign(total, sequential, combinational, clock, macro, pad, digits);
|
||||
report_power.reportDesign(total, sequential, combinational, clock, macro, pad, digits);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -734,7 +726,7 @@ percentChange(float value,
|
|||
return 1.0;
|
||||
}
|
||||
else
|
||||
return abs(value - prev) / prev;
|
||||
return std::abs(value - prev) / prev;
|
||||
}
|
||||
|
||||
// Return true if the activity changed.
|
||||
|
|
@ -842,7 +834,7 @@ Power::evalBddDuty(DdNode *bdd,
|
|||
else if (bdd == Cudd_ReadLogicZero(bdd_.cuddMgr()))
|
||||
return 0.0;
|
||||
else
|
||||
criticalError(1100, "unknown cudd constant");
|
||||
criticalError(2400, "unknown cudd constant");
|
||||
}
|
||||
else {
|
||||
float duty0 = evalBddDuty(Cudd_E(bdd), inst);
|
||||
|
|
@ -1837,7 +1829,7 @@ Power::clockMinPeriod(const Sdc *sdc)
|
|||
if (!clks.empty()) {
|
||||
float min_period = INF;
|
||||
for (const Clock *clk : clks)
|
||||
min_period = min(min_period, clk->period());
|
||||
min_period = std::min(min_period, clk->period());
|
||||
return min_period;
|
||||
}
|
||||
else
|
||||
|
|
@ -1963,7 +1955,7 @@ PwrActivity::check()
|
|||
// Densities can get very small from multiplying probabilities
|
||||
// through deep chains of logic. Clip them to prevent floating
|
||||
// point anomalies.
|
||||
if (abs(density_) < min_density)
|
||||
if (std::abs(density_) < min_density)
|
||||
density_ = 0.0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
|
||||
#include "Error.hh"
|
||||
#include "Debug.hh"
|
||||
|
|
@ -42,9 +43,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
using std::min;
|
||||
|
||||
bool
|
||||
readSaif(const char *filename,
|
||||
const char *scope,
|
||||
|
|
@ -129,9 +127,9 @@ SaifReader::instancePush(const char *instance_name)
|
|||
// Check for a match to the annotation scope.
|
||||
saif_scope_.push_back(instance_name);
|
||||
|
||||
string saif_scope;
|
||||
std::string saif_scope;
|
||||
bool first = true;
|
||||
for (string &inst : saif_scope_) {
|
||||
for (std::string &inst : saif_scope_) {
|
||||
if (!first)
|
||||
saif_scope += sdc_network_->pathDivider();
|
||||
saif_scope += inst;
|
||||
|
|
@ -167,7 +165,7 @@ SaifReader::setNetDurations(const char *net_name,
|
|||
if (in_scope_level_ > 0) {
|
||||
Instance *parent = path_.empty() ? sdc_network_->topInstance() : path_.back();
|
||||
if (parent) {
|
||||
string unescaped_name = unescaped(net_name);
|
||||
std::string unescaped_name = unescaped(net_name);
|
||||
const Pin *pin = sdc_network_->findPin(parent, unescaped_name.c_str());
|
||||
LibertyPort *liberty_port = pin ? sdc_network_->libertyPort(pin) : nullptr;
|
||||
if (pin
|
||||
|
|
@ -194,10 +192,10 @@ SaifReader::setNetDurations(const char *net_name,
|
|||
stringDelete(net_name);
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
SaifReader::unescaped(const char *token)
|
||||
{
|
||||
string unescaped;
|
||||
std::string unescaped;
|
||||
for (const char *t = token; *t; t++) {
|
||||
char ch = *t;
|
||||
if (ch != escape_)
|
||||
|
|
@ -211,7 +209,7 @@ SaifReader::unescaped(const char *token)
|
|||
////////////////////////////////////////////////////////////////
|
||||
|
||||
SaifScanner::SaifScanner(std::istream *stream,
|
||||
const string &filename,
|
||||
const std::string &filename,
|
||||
SaifReader *reader,
|
||||
Report *report) :
|
||||
yyFlexLexer(stream),
|
||||
|
|
|
|||
|
|
@ -35,10 +35,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::isspace;
|
||||
|
||||
// Very imprecise syntax definition
|
||||
// https://en.wikipedia.org/wiki/Value_change_dump#Structure.2FSyntax
|
||||
// Much better syntax definition
|
||||
|
|
@ -125,7 +121,7 @@ VcdParse::VcdParse(Report *report,
|
|||
void
|
||||
VcdParse::parseTimescale()
|
||||
{
|
||||
vector<string> tokens = readStmtTokens();
|
||||
std::vector<std::string> tokens = readStmtTokens();
|
||||
if (tokens.size() == 1) {
|
||||
size_t last;
|
||||
double time_scale = std::stod(tokens[0], &last);
|
||||
|
|
@ -140,7 +136,7 @@ VcdParse::parseTimescale()
|
|||
}
|
||||
|
||||
void
|
||||
VcdParse::setTimeUnit(const string &time_unit,
|
||||
VcdParse::setTimeUnit(const std::string &time_unit,
|
||||
double time_scale)
|
||||
{
|
||||
double time_unit_scale = 1.0;
|
||||
|
|
@ -177,19 +173,19 @@ static EnumNameMap<VcdVarType> vcd_var_type_map =
|
|||
void
|
||||
VcdParse::parseVar()
|
||||
{
|
||||
vector<string> tokens = readStmtTokens();
|
||||
std::vector<std::string> tokens = readStmtTokens();
|
||||
if (tokens.size() == 4
|
||||
|| tokens.size() == 5) {
|
||||
string type_name = tokens[0];
|
||||
std::string type_name = tokens[0];
|
||||
VcdVarType type = vcd_var_type_map.find(type_name, VcdVarType::unknown);
|
||||
if (type == VcdVarType::unknown)
|
||||
report_->fileWarn(1370, filename_, file_line_,
|
||||
"Unknown variable type %s.",
|
||||
type_name.c_str());
|
||||
else {
|
||||
size_t width = stoi(tokens[1]);
|
||||
string &id = tokens[2];
|
||||
string name = tokens[3];
|
||||
size_t width = std::stoi(tokens[1]);
|
||||
std::string &id = tokens[2];
|
||||
std::string name = tokens[3];
|
||||
// iverilog separates bus base name from bit range.
|
||||
if (tokens.size() == 5) {
|
||||
// Preserve space after esacaped name.
|
||||
|
|
@ -208,8 +204,8 @@ VcdParse::parseVar()
|
|||
void
|
||||
VcdParse::parseScope()
|
||||
{
|
||||
vector<string> tokens = readStmtTokens();
|
||||
string &scope = tokens[1];
|
||||
std::vector<std::string> tokens = readStmtTokens();
|
||||
std::string &scope = tokens[1];
|
||||
scope_.push_back(scope);
|
||||
}
|
||||
|
||||
|
|
@ -223,11 +219,11 @@ VcdParse::parseUpscope()
|
|||
void
|
||||
VcdParse::parseVarValues()
|
||||
{
|
||||
string token = getToken();
|
||||
std::string token = getToken();
|
||||
while (!token.empty()) {
|
||||
char char0 = toupper(token[0]);
|
||||
if (char0 == '#' && token.size() > 1) {
|
||||
VcdTime time = stoll(token.substr(1));
|
||||
VcdTime time = std::stoll(token.substr(1));
|
||||
prev_time_ = time_;
|
||||
time_ = time;
|
||||
if (time_ > prev_time_)
|
||||
|
|
@ -238,15 +234,15 @@ VcdParse::parseVarValues()
|
|||
|| char0 == 'X'
|
||||
|| char0 == 'U'
|
||||
|| char0 == 'Z') {
|
||||
string id = token.substr(1);
|
||||
std::string id = token.substr(1);
|
||||
if (!reader_->varIdValid(id))
|
||||
report_->fileError(805, filename_, file_line_,
|
||||
"unknown variable %s", id.c_str());
|
||||
reader_->varAppendValue(id, time_, char0);
|
||||
}
|
||||
else if (char0 == 'B') {
|
||||
string bus_value = token.substr(1);
|
||||
string id = getToken();
|
||||
std::string bus_value = token.substr(1);
|
||||
std::string id = getToken();
|
||||
if (!reader_->varIdValid(id))
|
||||
report_->fileError(807, filename_, file_line_,
|
||||
"unknown variable %s", id.c_str());
|
||||
|
|
@ -261,12 +257,12 @@ VcdParse::parseVarValues()
|
|||
reader_->setTimeMax(time_);
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
VcdParse::readStmtString()
|
||||
{
|
||||
stmt_line_ = file_line_;
|
||||
string line;
|
||||
string token = getToken();
|
||||
std::string line;
|
||||
std::string token = getToken();
|
||||
while (!token.empty() && token != "$end") {
|
||||
if (!line.empty())
|
||||
line += " ";
|
||||
|
|
@ -276,12 +272,12 @@ VcdParse::readStmtString()
|
|||
return line;
|
||||
}
|
||||
|
||||
vector<string>
|
||||
std::vector<std::string>
|
||||
VcdParse::readStmtTokens()
|
||||
{
|
||||
stmt_line_ = file_line_;
|
||||
vector<string> tokens;
|
||||
string token = getToken();
|
||||
std::vector<std::string> tokens;
|
||||
std::string token = getToken();
|
||||
while (!token.empty() && token != "$end") {
|
||||
tokens.push_back(token);
|
||||
token = getToken();
|
||||
|
|
@ -289,18 +285,18 @@ VcdParse::readStmtTokens()
|
|||
return tokens;
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
VcdParse::getToken()
|
||||
{
|
||||
string token;
|
||||
std::string token;
|
||||
int ch = gzgetc(stream_);
|
||||
// skip whitespace
|
||||
while (ch != EOF && isspace(ch)) {
|
||||
while (ch != EOF && std::isspace(ch)) {
|
||||
if (ch == '\n')
|
||||
file_line_++;
|
||||
ch = gzgetc(stream_);
|
||||
}
|
||||
while (ch != EOF && !isspace(ch)) {
|
||||
while (ch != EOF && !std::isspace(ch)) {
|
||||
token.push_back(ch);
|
||||
ch = gzgetc(stream_);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,10 @@
|
|||
|
||||
#include "VcdReader.hh"
|
||||
|
||||
#include <cmath>
|
||||
#include <inttypes.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "VcdParse.hh"
|
||||
#include "Debug.hh"
|
||||
|
|
@ -41,13 +43,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
using std::abs;
|
||||
using std::min;
|
||||
using std::to_string;
|
||||
using std::vector;
|
||||
using std::unordered_map;
|
||||
|
||||
// Transition count and high time for duty cycle for a group of pins
|
||||
// for one bit of vcd ID.
|
||||
class VcdCount
|
||||
|
|
@ -117,9 +112,9 @@ VcdCount::highTime(VcdTime time_max) const
|
|||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// VcdCount[bit]
|
||||
typedef vector<VcdCount> VcdCounts;
|
||||
using VcdCounts = std::vector<VcdCount>;
|
||||
// ID -> VcdCount[bit]
|
||||
typedef unordered_map<string, VcdCounts> VcdIdCountsMap;
|
||||
using VcdIdCountsMap = std::unordered_map<std::string, VcdCounts>;
|
||||
|
||||
class VcdCountReader : public VcdReader
|
||||
{
|
||||
|
|
@ -134,31 +129,31 @@ public:
|
|||
double timeScale() const { return time_scale_; }
|
||||
|
||||
// VcdParse callbacks.
|
||||
void setDate(const string &) override {}
|
||||
void setComment(const string &) override {}
|
||||
void setVersion(const string &) override {}
|
||||
void setTimeUnit(const string &time_unit,
|
||||
void setDate(const std::string &) override {}
|
||||
void setComment(const std::string &) override {}
|
||||
void setVersion(const std::string &) override {}
|
||||
void setTimeUnit(const std::string &time_unit,
|
||||
double time_unit_scale,
|
||||
double time_scale) override;
|
||||
void setTimeMin(VcdTime time) override;
|
||||
void setTimeMax(VcdTime time) override;
|
||||
void varMinDeltaTime(VcdTime) override {}
|
||||
bool varIdValid(const string &id) override;
|
||||
bool varIdValid(const std::string &id) override;
|
||||
void makeVar(const VcdScope &scope,
|
||||
const string &name,
|
||||
const std::string &name,
|
||||
VcdVarType type,
|
||||
size_t width,
|
||||
const string &id) override;
|
||||
void varAppendValue(const string &id,
|
||||
const std::string &id) override;
|
||||
void varAppendValue(const std::string &id,
|
||||
VcdTime time,
|
||||
char value) override;
|
||||
void varAppendBusValue(const string &id,
|
||||
void varAppendBusValue(const std::string &id,
|
||||
VcdTime time,
|
||||
const string &bus_value) override;
|
||||
const std::string &bus_value) override;
|
||||
|
||||
private:
|
||||
void addVarPin(const string &pin_name,
|
||||
const string &id,
|
||||
void addVarPin(const std::string &pin_name,
|
||||
const std::string &id,
|
||||
size_t width,
|
||||
size_t bit_idx);
|
||||
|
||||
|
|
@ -189,7 +184,7 @@ VcdCountReader::VcdCountReader(const std::string &scope,
|
|||
}
|
||||
|
||||
void
|
||||
VcdCountReader::setTimeUnit(const string &,
|
||||
VcdCountReader::setTimeUnit(const std::string &,
|
||||
double time_unit_scale,
|
||||
double time_scale)
|
||||
{
|
||||
|
|
@ -209,23 +204,23 @@ VcdCountReader::setTimeMax(VcdTime time)
|
|||
}
|
||||
|
||||
bool
|
||||
VcdCountReader::varIdValid(const string &)
|
||||
VcdCountReader::varIdValid(const std::string &)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
VcdCountReader::makeVar(const VcdScope &scope,
|
||||
const string &name,
|
||||
const std::string &name,
|
||||
VcdVarType type,
|
||||
size_t width,
|
||||
const string &id)
|
||||
const std::string &id)
|
||||
{
|
||||
if (type == VcdVarType::wire
|
||||
|| type == VcdVarType::reg) {
|
||||
string path_name;
|
||||
std::string path_name;
|
||||
bool first = true;
|
||||
for (const string &context : scope) {
|
||||
for (const std::string &context : scope) {
|
||||
if (!first)
|
||||
path_name += '/';
|
||||
path_name += context;
|
||||
|
|
@ -238,25 +233,25 @@ VcdCountReader::makeVar(const VcdScope &scope,
|
|||
path_name += '/';
|
||||
path_name += name;
|
||||
// Strip the scope from the name.
|
||||
string var_scoped = path_name.substr(scope_length + 1);
|
||||
std::string var_scoped = path_name.substr(scope_length + 1);
|
||||
if (width == 1) {
|
||||
string pin_name = netVerilogToSta(&var_scoped);
|
||||
std::string pin_name = netVerilogToSta(&var_scoped);
|
||||
addVarPin(pin_name, id, width, 0);
|
||||
}
|
||||
else {
|
||||
bool is_bus, is_range, subscript_wild;
|
||||
string bus_name;
|
||||
std::string bus_name;
|
||||
int from, to;
|
||||
parseBusName(var_scoped.c_str(), '[', ']', '\\',
|
||||
is_bus, is_range, bus_name, from, to, subscript_wild);
|
||||
if (is_bus) {
|
||||
string sta_bus_name = netVerilogToSta(&bus_name);
|
||||
std::string sta_bus_name = netVerilogToSta(&bus_name);
|
||||
int bit_idx = 0;
|
||||
if (to < from) {
|
||||
for (int bus_bit = to; bus_bit <= from; bus_bit++) {
|
||||
string pin_name = sta_bus_name;
|
||||
std::string pin_name = sta_bus_name;
|
||||
pin_name += '[';
|
||||
pin_name += to_string(bus_bit);
|
||||
pin_name += std::to_string(bus_bit);
|
||||
pin_name += ']';
|
||||
addVarPin(pin_name, id, width, bit_idx);
|
||||
bit_idx++;
|
||||
|
|
@ -264,9 +259,9 @@ VcdCountReader::makeVar(const VcdScope &scope,
|
|||
}
|
||||
else {
|
||||
for (int bus_bit = to; bus_bit >= from; bus_bit--) {
|
||||
string pin_name = sta_bus_name;
|
||||
std::string pin_name = sta_bus_name;
|
||||
pin_name += '[';
|
||||
pin_name += to_string(bus_bit);
|
||||
pin_name += std::to_string(bus_bit);
|
||||
pin_name += ']';
|
||||
addVarPin(pin_name, id, width, bit_idx);
|
||||
bit_idx++;
|
||||
|
|
@ -281,8 +276,8 @@ VcdCountReader::makeVar(const VcdScope &scope,
|
|||
}
|
||||
|
||||
void
|
||||
VcdCountReader::addVarPin(const string &pin_name,
|
||||
const string &id,
|
||||
VcdCountReader::addVarPin(const std::string &pin_name,
|
||||
const std::string &id,
|
||||
size_t width,
|
||||
size_t bit_idx)
|
||||
{
|
||||
|
|
@ -303,7 +298,7 @@ VcdCountReader::addVarPin(const string &pin_name,
|
|||
}
|
||||
|
||||
void
|
||||
VcdCountReader::varAppendValue(const string &id,
|
||||
VcdCountReader::varAppendValue(const std::string &id,
|
||||
VcdTime time,
|
||||
char value)
|
||||
{
|
||||
|
|
@ -329,9 +324,9 @@ VcdCountReader::varAppendValue(const string &id,
|
|||
}
|
||||
|
||||
void
|
||||
VcdCountReader::varAppendBusValue(const string &id,
|
||||
VcdCountReader::varAppendBusValue(const std::string &id,
|
||||
VcdTime time,
|
||||
const string &bus_value)
|
||||
const std::string &bus_value)
|
||||
{
|
||||
const auto &itr = vcd_count_map_.find(id);
|
||||
if (itr != vcd_count_map_.end()) {
|
||||
|
|
@ -476,7 +471,7 @@ ReadVcdActivities::checkClkPeriod(const Pin *pin,
|
|||
sdc_network_->pathName(pin));
|
||||
else {
|
||||
double clk_period = clk->period();
|
||||
if (abs((clk_period - sim_period) / clk_period) > sim_clk_period_tolerance_)
|
||||
if (std::abs((clk_period - sim_period) / clk_period) > sim_clk_period_tolerance_)
|
||||
// Warn if sim clock period differs from SDC by more than 10%.
|
||||
report_->warn(1452, "clock %s vcd period %s differs from SDC clock period %s",
|
||||
clk->name(),
|
||||
|
|
|
|||
|
|
@ -531,7 +531,7 @@ ClockEdge::ClockEdge(Clock *clock,
|
|||
const RiseFall *rf) :
|
||||
clock_(clock),
|
||||
rf_(rf),
|
||||
name_(stringPrint("%s %s", clock_->name(), rf_->to_string().c_str())),
|
||||
name_(stringPrint("%s %s", clock_->name(), rf_->shortName())),
|
||||
time_(0.0),
|
||||
index_(clock_->index() * RiseFall::index_count + rf_->index())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -96,18 +96,15 @@ DisabledPorts::setDisabledFromTo(LibertyPort *from,
|
|||
{
|
||||
if (from_to_ == nullptr)
|
||||
from_to_ = new LibertyPortPairSet;
|
||||
LibertyPortPair pair(from, to);
|
||||
from_to_->insert(pair);
|
||||
from_to_->insert({from, to});
|
||||
}
|
||||
|
||||
void
|
||||
DisabledPorts::removeDisabledFromTo(LibertyPort *from,
|
||||
LibertyPort *to)
|
||||
{
|
||||
if (from_to_) {
|
||||
LibertyPortPair from_to(from, to);
|
||||
from_to_->erase(from_to);
|
||||
}
|
||||
if (from_to_)
|
||||
from_to_->erase({from, to});
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -115,12 +112,11 @@ DisabledPorts::isDisabled(LibertyPort *from,
|
|||
LibertyPort *to,
|
||||
const TimingRole *role)
|
||||
{
|
||||
LibertyPortPair from_to(from, to);
|
||||
// set_disable_timing instance does not disable timing checks.
|
||||
return (all_ && !role->isTimingCheck())
|
||||
|| (from_ && from_->contains(from))
|
||||
|| (to_ && to_->contains(to))
|
||||
|| (from_to_ && from_to_->contains(from_to));
|
||||
|| (from_to_ && from_to_->contains({from, to}));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
static bool
|
||||
thrusIntersectPts(ExceptionThruSeq *thrus1,
|
||||
ExceptionThruSeq *thrus2,
|
||||
|
|
@ -326,7 +324,7 @@ ExceptionPath::intersectsPts(ExceptionPath *exception,
|
|||
const char *
|
||||
ExceptionPath::fromThruToString(const Network *network) const
|
||||
{
|
||||
string str;
|
||||
std::string str;
|
||||
if (min_max_ != MinMaxAll::all()) {
|
||||
str += " -";
|
||||
str += min_max_->to_string();
|
||||
|
|
@ -1186,7 +1184,7 @@ ExceptionFromTo::deletePinBefore(const Pin *pin,
|
|||
const char *
|
||||
ExceptionFromTo::asString(const Network *network) const
|
||||
{
|
||||
string str;
|
||||
std::string str;
|
||||
str += " ";
|
||||
str += cmdKeyword();
|
||||
str += " {";
|
||||
|
|
@ -1360,7 +1358,7 @@ ExceptionTo::clone(const Network *network)
|
|||
const char *
|
||||
ExceptionTo::asString(const Network *network) const
|
||||
{
|
||||
string str;
|
||||
std::string str;
|
||||
if (hasObjects())
|
||||
str += ExceptionFromTo::asString(network);
|
||||
|
||||
|
|
@ -1679,7 +1677,7 @@ ExceptionThru::~ExceptionThru()
|
|||
const char *
|
||||
ExceptionThru::asString(const Network *network) const
|
||||
{
|
||||
string str;
|
||||
std::string str;
|
||||
bool first = true;
|
||||
int obj_count = 0;
|
||||
if (pins_) {
|
||||
|
|
@ -2429,8 +2427,7 @@ void
|
|||
InsertPinPairsThru::visit(const Pin *drvr,
|
||||
const Pin *load)
|
||||
{
|
||||
PinPair pair(drvr, load);
|
||||
pairs_->insert(pair);
|
||||
pairs_->insert({drvr, load});
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2477,8 +2474,7 @@ void
|
|||
DeletePinPairsThru::visit(const Pin *drvr,
|
||||
const Pin *load)
|
||||
{
|
||||
PinPair pair(drvr, load);
|
||||
pairs_->erase(pair);
|
||||
pairs_->erase({drvr, load});
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
64
sdc/Sdc.cc
64
sdc/Sdc.cc
|
|
@ -62,8 +62,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::swap;
|
||||
|
||||
bool
|
||||
ClockPairLess::operator()(const ClockPair &pair1,
|
||||
const ClockPair &pair2) const
|
||||
|
|
@ -103,6 +101,7 @@ Sdc::Sdc(Mode *mode,
|
|||
clk_hpin_disables_(network_),
|
||||
propagated_clk_pins_(network_),
|
||||
clk_latencies_(network_),
|
||||
clk_latency_pins_(network_),
|
||||
edge_clk_latency_map_(network_),
|
||||
clk_insertions_(network_),
|
||||
clk_sense_map_(network_),
|
||||
|
|
@ -171,6 +170,7 @@ Sdc::clear()
|
|||
clock_pin_map_.clear();
|
||||
clock_leaf_pin_map_.clear();
|
||||
clk_latencies_.clear();
|
||||
clk_latency_pins_.clear();
|
||||
edge_clk_latency_map_.clear();
|
||||
clk_insertions_.clear();
|
||||
|
||||
|
|
@ -693,10 +693,10 @@ void
|
|||
Sdc::swapDeratingFactors(Sdc *sdc1,
|
||||
Sdc *sdc2)
|
||||
{
|
||||
swap(sdc1->derating_factors_, sdc2->derating_factors_);
|
||||
swap(sdc1->net_derating_factors_, sdc2->net_derating_factors_);
|
||||
swap(sdc1->inst_derating_factors_, sdc2->inst_derating_factors_);
|
||||
swap(sdc1->cell_derating_factors_, sdc2->cell_derating_factors_);
|
||||
std::swap(sdc1->derating_factors_, sdc2->derating_factors_);
|
||||
std::swap(sdc1->net_derating_factors_, sdc2->net_derating_factors_);
|
||||
std::swap(sdc1->inst_derating_factors_, sdc2->inst_derating_factors_);
|
||||
std::swap(sdc1->cell_derating_factors_, sdc2->cell_derating_factors_);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1346,8 +1346,7 @@ bool
|
|||
FindClkHpinDisables::drvrLoadExists(const Pin *drvr,
|
||||
const Pin *load)
|
||||
{
|
||||
PinPair probe(drvr, load);
|
||||
return drvr_loads_.contains(probe);
|
||||
return drvr_loads_.contains({drvr, load});
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1510,6 +1509,8 @@ Sdc::setClockLatency(Clock *clk,
|
|||
}
|
||||
}
|
||||
latency->setDelay(rf, min_max, delay);
|
||||
if (pin)
|
||||
clk_latency_pins_.insert(pin);
|
||||
|
||||
// set_clock_latency removes set_propagated_clock on the same object.
|
||||
if (clk && pin == nullptr)
|
||||
|
|
@ -1582,8 +1583,7 @@ Sdc::deleteClockLatenciesReferencing(Clock *clk)
|
|||
bool
|
||||
Sdc::hasClockLatency(const Pin *pin) const
|
||||
{
|
||||
ClockLatency probe(nullptr, pin);
|
||||
return clk_latencies_.contains(&probe);
|
||||
return clk_latency_pins_.contains(pin);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1818,7 +1818,7 @@ void
|
|||
Sdc::swapClockInsertions(Sdc *sdc1,
|
||||
Sdc *sdc2)
|
||||
{
|
||||
swap(sdc1->clk_insertions_, sdc2->clk_insertions_);
|
||||
std::swap(sdc1->clk_insertions_, sdc2->clk_insertions_);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2825,17 +2825,17 @@ void
|
|||
Sdc::swapPortDelays(Sdc *sdc1,
|
||||
Sdc *sdc2)
|
||||
{
|
||||
swap(sdc1->input_delays_, sdc2->input_delays_);
|
||||
swap(sdc1->input_delay_pin_map_, sdc2->input_delay_pin_map_);
|
||||
swap(sdc1->input_delay_ref_pin_map_, sdc2->input_delay_ref_pin_map_);
|
||||
swap(sdc1->input_delay_leaf_pin_map_, sdc2->input_delay_leaf_pin_map_);
|
||||
swap(sdc1->input_delay_internal_pin_map_, sdc2->input_delay_internal_pin_map_);
|
||||
swap(sdc1->input_delay_index_, sdc2->input_delay_index_);
|
||||
std::swap(sdc1->input_delays_, sdc2->input_delays_);
|
||||
std::swap(sdc1->input_delay_pin_map_, sdc2->input_delay_pin_map_);
|
||||
std::swap(sdc1->input_delay_ref_pin_map_, sdc2->input_delay_ref_pin_map_);
|
||||
std::swap(sdc1->input_delay_leaf_pin_map_, sdc2->input_delay_leaf_pin_map_);
|
||||
std::swap(sdc1->input_delay_internal_pin_map_, sdc2->input_delay_internal_pin_map_);
|
||||
std::swap(sdc1->input_delay_index_, sdc2->input_delay_index_);
|
||||
|
||||
swap(sdc1->output_delays_, sdc2->output_delays_);
|
||||
swap(sdc1->output_delay_pin_map_, sdc2->output_delay_pin_map_);
|
||||
swap(sdc1->output_delay_ref_pin_map_, sdc2->output_delay_ref_pin_map_);
|
||||
swap(sdc1->output_delay_leaf_pin_map_, sdc2->output_delay_leaf_pin_map_);
|
||||
std::swap(sdc1->output_delays_, sdc2->output_delays_);
|
||||
std::swap(sdc1->output_delay_pin_map_, sdc2->output_delay_pin_map_);
|
||||
std::swap(sdc1->output_delay_ref_pin_map_, sdc2->output_delay_ref_pin_map_);
|
||||
std::swap(sdc1->output_delay_leaf_pin_map_, sdc2->output_delay_leaf_pin_map_);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -3374,8 +3374,8 @@ void
|
|||
Sdc::swapPortExtCaps(Sdc *sdc1,
|
||||
Sdc *sdc2)
|
||||
{
|
||||
swap(sdc1->port_ext_cap_map_, sdc2->port_ext_cap_map_);
|
||||
swap(sdc1->net_wire_cap_map_, sdc2->net_wire_cap_map_);
|
||||
std::swap(sdc1->port_ext_cap_map_, sdc2->port_ext_cap_map_);
|
||||
std::swap(sdc1->net_wire_cap_map_, sdc2->net_wire_cap_map_);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -3505,24 +3505,21 @@ void
|
|||
Sdc::disableWire(const Pin *from,
|
||||
const Pin *to)
|
||||
{
|
||||
PinPair pair(from, to);
|
||||
disabled_wire_edges_.insert(pair);
|
||||
disabled_wire_edges_.insert({from, to});
|
||||
}
|
||||
|
||||
void
|
||||
Sdc::removeDisableWire(Pin *from,
|
||||
Pin *to)
|
||||
{
|
||||
PinPair probe(from, to);
|
||||
disabled_wire_edges_.erase(probe);
|
||||
disabled_wire_edges_.erase({from, to});
|
||||
}
|
||||
|
||||
bool
|
||||
Sdc::isDisabledWire(const Pin *from,
|
||||
const Pin *to) const
|
||||
{
|
||||
PinPair pair(from, to);
|
||||
return disabled_wire_edges_.contains(pair);
|
||||
return disabled_wire_edges_.contains({from, to});
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3582,8 +3579,7 @@ void
|
|||
DisableEdgesThruHierPin::visit(const Pin *drvr,
|
||||
const Pin *load)
|
||||
{
|
||||
PinPair pair(drvr, load);
|
||||
pairs_->insert(pair);
|
||||
pairs_->insert({drvr, load});
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3624,8 +3620,7 @@ void
|
|||
RemoveDisableEdgesThruHierPin::visit(const Pin *drvr,
|
||||
const Pin *load)
|
||||
{
|
||||
PinPair pair(drvr, load);
|
||||
pairs_->erase(pair);
|
||||
pairs_->erase({drvr, load});
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3658,8 +3653,7 @@ Sdc::isDisabled(const Instance *inst,
|
|||
{
|
||||
if (role == TimingRole::wire()) {
|
||||
// Hierarchical thru pin disables.
|
||||
PinPair pair(from_pin, to_pin);
|
||||
return disabled_wire_edges_.contains(pair);
|
||||
return disabled_wire_edges_.contains({from_pin, to_pin});
|
||||
}
|
||||
else {
|
||||
LibertyCell *cell = network_->libertyCell(inst);
|
||||
|
|
|
|||
|
|
@ -1654,6 +1654,14 @@ set_propagate_all_clocks(bool prop)
|
|||
Sta::sta()->setPropagateAllClocks(prop);
|
||||
}
|
||||
|
||||
bool
|
||||
pin_is_constrained(const Pin *pin)
|
||||
{
|
||||
Sta *sta = Sta::sta();
|
||||
Sdc *sdc = sta->cmdSdc();
|
||||
return sdc->isConstrained(pin);
|
||||
}
|
||||
|
||||
%} // inline
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <ctime>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "ContainerHelpers.hh"
|
||||
#include "Zlib.hh"
|
||||
|
|
@ -63,8 +64,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
typedef std::set<ClockSense*> ClockSenseSet;
|
||||
typedef std::vector<ClockSense*> ClockSenseSeq;
|
||||
|
||||
|
|
@ -1167,7 +1166,7 @@ WriteSdc::writeDisabledEdgeSense(Edge *edge) const
|
|||
{
|
||||
gzprintf(stream_, "set_disable_timing ");
|
||||
const char *sense = to_string(edge->sense());
|
||||
string filter;
|
||||
std::string filter;
|
||||
stringPrint(filter, "sense == %s", sense);
|
||||
writeGetTimingArcs(edge, filter.c_str());
|
||||
gzprintf(stream_, "\n");
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue