rel 3.0
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
7f65853afa
commit
d42b821c00
|
|
@ -32,7 +32,7 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.14)
|
||||||
cmake_policy(SET CMP0086 NEW)
|
cmake_policy(SET CMP0086 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(STA VERSION 2.7.0
|
project(STA VERSION 3.0.0
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -77,7 +77,6 @@ set(STA_SOURCE
|
||||||
dcalc/ArnoldiDelayCalc.cc
|
dcalc/ArnoldiDelayCalc.cc
|
||||||
dcalc/ArnoldiReduce.cc
|
dcalc/ArnoldiReduce.cc
|
||||||
dcalc/CcsCeffDelayCalc.cc
|
dcalc/CcsCeffDelayCalc.cc
|
||||||
dcalc/DcalcAnalysisPt.cc
|
|
||||||
dcalc/DelayCalc.cc
|
dcalc/DelayCalc.cc
|
||||||
dcalc/DelayCalcBase.cc
|
dcalc/DelayCalcBase.cc
|
||||||
dcalc/DmpCeff.cc
|
dcalc/DmpCeff.cc
|
||||||
|
|
@ -135,6 +134,7 @@ set(STA_SOURCE
|
||||||
parasitics/SpefReaderPvt.hh
|
parasitics/SpefReaderPvt.hh
|
||||||
|
|
||||||
power/Power.cc
|
power/Power.cc
|
||||||
|
power/ReportPower.cc
|
||||||
power/VcdReader.cc
|
power/VcdReader.cc
|
||||||
power/SaifReader.cc
|
power/SaifReader.cc
|
||||||
power/VcdParse.cc
|
power/VcdParse.cc
|
||||||
|
|
@ -154,7 +154,6 @@ set(STA_SOURCE
|
||||||
sdc/PortDelay.cc
|
sdc/PortDelay.cc
|
||||||
sdc/PortExtCap.cc
|
sdc/PortExtCap.cc
|
||||||
sdc/Sdc.cc
|
sdc/Sdc.cc
|
||||||
sdc/SdcGraph.cc
|
|
||||||
sdc/SdcCmdComment.cc
|
sdc/SdcCmdComment.cc
|
||||||
sdc/Variables.cc
|
sdc/Variables.cc
|
||||||
sdc/WriteSdc.cc
|
sdc/WriteSdc.cc
|
||||||
|
|
@ -168,15 +167,14 @@ set(STA_SOURCE
|
||||||
search/CheckMaxSkews.cc
|
search/CheckMaxSkews.cc
|
||||||
search/CheckMinPeriods.cc
|
search/CheckMinPeriods.cc
|
||||||
search/CheckMinPulseWidths.cc
|
search/CheckMinPulseWidths.cc
|
||||||
search/CheckCapacitanceLimits.cc
|
search/CheckCapacitances.cc
|
||||||
search/CheckFanoutLimits.cc
|
search/CheckFanouts.cc
|
||||||
search/CheckSlewLimits.cc
|
search/CheckSlews.cc
|
||||||
search/CheckTiming.cc
|
search/CheckTiming.cc
|
||||||
search/ClkInfo.cc
|
search/ClkInfo.cc
|
||||||
search/ClkLatency.cc
|
search/ClkLatency.cc
|
||||||
search/ClkNetwork.cc
|
search/ClkNetwork.cc
|
||||||
search/ClkSkew.cc
|
search/ClkSkew.cc
|
||||||
search/Corner.cc
|
|
||||||
search/Crpr.cc
|
search/Crpr.cc
|
||||||
search/FindRegister.cc
|
search/FindRegister.cc
|
||||||
search/GatedClk.cc
|
search/GatedClk.cc
|
||||||
|
|
@ -184,8 +182,8 @@ set(STA_SOURCE
|
||||||
search/Latches.cc
|
search/Latches.cc
|
||||||
search/Levelize.cc
|
search/Levelize.cc
|
||||||
search/MakeTimingModel.cc
|
search/MakeTimingModel.cc
|
||||||
|
search/Mode.cc
|
||||||
search/Path.cc
|
search/Path.cc
|
||||||
search/PathAnalysisPt.cc
|
|
||||||
search/Path.cc
|
search/Path.cc
|
||||||
search/PathEnd.cc
|
search/PathEnd.cc
|
||||||
search/PathEnum.cc
|
search/PathEnum.cc
|
||||||
|
|
@ -195,6 +193,7 @@ set(STA_SOURCE
|
||||||
search/ReportPath.cc
|
search/ReportPath.cc
|
||||||
search/Search.cc
|
search/Search.cc
|
||||||
search/SearchPred.cc
|
search/SearchPred.cc
|
||||||
|
search/Scene.cc
|
||||||
search/Sim.cc
|
search/Sim.cc
|
||||||
search/Sta.cc
|
search/Sta.cc
|
||||||
search/StaState.cc
|
search/StaState.cc
|
||||||
|
|
@ -222,6 +221,7 @@ set(STA_SOURCE
|
||||||
util/ReportStd.cc
|
util/ReportStd.cc
|
||||||
util/ReportTcl.cc
|
util/ReportTcl.cc
|
||||||
util/RiseFallMinMax.cc
|
util/RiseFallMinMax.cc
|
||||||
|
util/RiseFallMinMaxDelay.cc
|
||||||
util/RiseFallValues.cc
|
util/RiseFallValues.cc
|
||||||
util/Stats.cc
|
util/Stats.cc
|
||||||
util/StringSeq.cc
|
util/StringSeq.cc
|
||||||
|
|
@ -549,14 +549,14 @@ endif()
|
||||||
|
|
||||||
target_compile_options(OpenSTA
|
target_compile_options(OpenSTA
|
||||||
PRIVATE
|
PRIVATE
|
||||||
$<$<CXX_COMPILER_ID:GNU>:${CXX_FLAGS}>
|
$<$<CXX_COMPILER_ID:GNU>:${CXX_FLAGS} -Wno-format-zero-length>
|
||||||
$<$<CXX_COMPILER_ID:Clang>:${CXX_FLAGS} -Wno-gnu-zero-variadic-macro-arguments>
|
$<$<CXX_COMPILER_ID:Clang>:${CXX_FLAGS} -Wno-gnu-zero-variadic-macro-arguments>
|
||||||
$<$<CXX_COMPILER_ID:AppleClang>:${CXX_FLAGS} -Wno-gnu-zero-variadic-macro-arguments>
|
$<$<CXX_COMPILER_ID:AppleClang>:${CXX_FLAGS} -Wno-gnu-zero-variadic-macro-arguments>
|
||||||
)
|
)
|
||||||
|
|
||||||
# Disable compiler specific extensions like gnu++11.
|
# Disable compiler specific extensions like gnu++11.
|
||||||
set_target_properties(OpenSTA PROPERTIES CXX_EXTENSIONS OFF)
|
set_target_properties(OpenSTA PROPERTIES CXX_EXTENSIONS OFF)
|
||||||
target_compile_features(OpenSTA PUBLIC cxx_std_17)
|
target_compile_features(OpenSTA PUBLIC cxx_std_20)
|
||||||
|
|
||||||
message(STATUS "STA library: ${CMAKE_BINARY_DIR}/libOpenSTA.a")
|
message(STATUS "STA library: ${CMAKE_BINARY_DIR}/libOpenSTA.a")
|
||||||
|
|
||||||
|
|
|
||||||
17
app/Main.cc
17
app/Main.cc
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <cstdlib> // exit
|
#include <cstdlib> // exit
|
||||||
|
#include <filesystem>
|
||||||
#include <tcl.h>
|
#include <tcl.h>
|
||||||
#if TCL_READLINE
|
#if TCL_READLINE
|
||||||
#include <tclreadline.h>
|
#include <tclreadline.h>
|
||||||
|
|
@ -47,7 +48,6 @@ using sta::evalTclInit;
|
||||||
using sta::sourceTclFile;
|
using sta::sourceTclFile;
|
||||||
using sta::parseThreadsArg;
|
using sta::parseThreadsArg;
|
||||||
using sta::tcl_inits;
|
using sta::tcl_inits;
|
||||||
using sta::is_regular_file;
|
|
||||||
|
|
||||||
// Swig uses C linkage for init functions.
|
// Swig uses C linkage for init functions.
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
@ -87,20 +87,11 @@ main(int argc,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Set argc to 1 so Tcl_Main doesn't source any files.
|
// Set argc to 1 so Tcl_Main doesn't source any files.
|
||||||
// Tcl_Main never returns.
|
// Store argc and argv in static variables for tclAppInit.
|
||||||
#if 0
|
|
||||||
// It should be possible to pass argc/argv to staTclAppInit with
|
|
||||||
// a closure but I couldn't get the signature to match Tcl_AppInitProc.
|
|
||||||
Tcl_Main(1, argv, [=](Tcl_Interp *interp)
|
|
||||||
{ sta::staTclAppInit(argc, argv, interp);
|
|
||||||
return 1;
|
|
||||||
});
|
|
||||||
#else
|
|
||||||
// Workaround.
|
|
||||||
cmd_argc = argc;
|
cmd_argc = argc;
|
||||||
cmd_argv = argv;
|
cmd_argv = argv;
|
||||||
|
// Tcl_Main never returns.
|
||||||
Tcl_Main(1, argv, tclAppInit);
|
Tcl_Main(1, argv, tclAppInit);
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -141,7 +132,7 @@ staTclAppInit(int argc,
|
||||||
string init_path = home;
|
string init_path = home;
|
||||||
init_path += "/";
|
init_path += "/";
|
||||||
init_path += init_filename;
|
init_path += init_filename;
|
||||||
if (is_regular_file(init_path.c_str()))
|
if (std::filesystem::is_regular_file(init_path.c_str()))
|
||||||
sourceTclFile(init_path.c_str(), true, true, interp);
|
sourceTclFile(init_path.c_str(), true, true, interp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@
|
||||||
|
|
||||||
#include "Machine.hh"
|
#include "Machine.hh"
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "Vector.hh"
|
|
||||||
#include "Sta.hh"
|
#include "Sta.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -148,12 +147,4 @@ unencode(const char *inits[])
|
||||||
return unencoded;
|
return unencoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hack until c++17 filesystem is better supported.
|
|
||||||
bool
|
|
||||||
is_regular_file(const char *filename)
|
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
return stat(filename, &sb) == 0 && S_ISREG(sb.st_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "Graph.hh"
|
#include "Graph.hh"
|
||||||
#include "ArcDelayCalc.hh"
|
#include "ArcDelayCalc.hh"
|
||||||
#include "DcalcAnalysisPt.hh"
|
|
||||||
#include "GraphDelayCalc.hh"
|
#include "GraphDelayCalc.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -40,7 +39,8 @@ using std::make_shared;
|
||||||
|
|
||||||
Waveform
|
Waveform
|
||||||
ArcDcalcWaveforms::inputWaveform(ArcDcalcArg &dcalc_arg,
|
ArcDcalcWaveforms::inputWaveform(ArcDcalcArg &dcalc_arg,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
const StaState *sta)
|
const StaState *sta)
|
||||||
{
|
{
|
||||||
const Network *network = sta->network();
|
const Network *network = sta->network();
|
||||||
|
|
@ -55,7 +55,8 @@ ArcDcalcWaveforms::inputWaveform(ArcDcalcArg &dcalc_arg,
|
||||||
const Vertex *in_vertex = graph->pinLoadVertex(in_pin);
|
const Vertex *in_vertex = graph->pinLoadVertex(in_pin);
|
||||||
GraphDelayCalc *graph_dcalc = sta->graphDelayCalc();
|
GraphDelayCalc *graph_dcalc = sta->graphDelayCalc();
|
||||||
Slew in_slew = graph_dcalc->edgeFromSlew(in_vertex, in_rf,
|
Slew in_slew = graph_dcalc->edgeFromSlew(in_vertex, in_rf,
|
||||||
dcalc_arg.arc()->role(), dcalc_ap);
|
dcalc_arg.arc()->role(),
|
||||||
|
scene, min_max);
|
||||||
LibertyLibrary *library = port->libertyLibrary();
|
LibertyLibrary *library = port->libertyLibrary();
|
||||||
float vdd;
|
float vdd;
|
||||||
bool vdd_exists;
|
bool vdd_exists;
|
||||||
|
|
@ -67,7 +68,8 @@ ArcDcalcWaveforms::inputWaveform(ArcDcalcArg &dcalc_arg,
|
||||||
FloatSeq *time_values = new FloatSeq;
|
FloatSeq *time_values = new FloatSeq;
|
||||||
for (float time : *in_waveform.axis1()->values())
|
for (float time : *in_waveform.axis1()->values())
|
||||||
time_values->push_back(time + dcalc_arg.inputDelay());
|
time_values->push_back(time + dcalc_arg.inputDelay());
|
||||||
TableAxisPtr time_axis = make_shared<TableAxis>(TableAxisVariable::time, time_values);
|
TableAxisPtr time_axis = make_shared<TableAxis>(TableAxisVariable::time,
|
||||||
|
time_values);
|
||||||
// Scale the waveform from 0:vdd.
|
// Scale the waveform from 0:vdd.
|
||||||
FloatSeq *scaled_values = new FloatSeq;
|
FloatSeq *scaled_values = new FloatSeq;
|
||||||
for (float value : *in_waveform.values()) {
|
for (float value : *in_waveform.values()) {
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,7 @@
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
class StaState;
|
class StaState;
|
||||||
class Corner;
|
class Scene;
|
||||||
class DcalcAnalysisPt;
|
|
||||||
class ArcDcalcArg;
|
class ArcDcalcArg;
|
||||||
|
|
||||||
// Abstract class for delay calculation waveforms for ploting.
|
// Abstract class for delay calculation waveforms for ploting.
|
||||||
|
|
@ -47,7 +46,8 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Waveform inputWaveform(ArcDcalcArg &dcalc_arg,
|
Waveform inputWaveform(ArcDcalcArg &dcalc_arg,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,14 +46,15 @@ ArcDelayCalc::gateDelay(const TimingArc *arc,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
float,
|
float,
|
||||||
const Pvt *,
|
const Pvt *,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
// Return values.
|
// Return values.
|
||||||
ArcDelay &gate_delay,
|
ArcDelay &gate_delay,
|
||||||
Slew &drvr_slew)
|
Slew &drvr_slew)
|
||||||
{
|
{
|
||||||
LoadPinIndexMap load_pin_index_map(network_);
|
LoadPinIndexMap load_pin_index_map(network_);
|
||||||
ArcDcalcResult dcalc_result = gateDelay(nullptr, arc, in_slew, load_cap, parasitic,
|
ArcDcalcResult dcalc_result = gateDelay(nullptr, arc, in_slew, load_cap, parasitic,
|
||||||
load_pin_index_map, dcalc_ap);
|
load_pin_index_map, scene, min_max);
|
||||||
gate_delay = dcalc_result.gateDelay();
|
gate_delay = dcalc_result.gateDelay();
|
||||||
drvr_slew = dcalc_result.drvrSlew();
|
drvr_slew = dcalc_result.drvrSlew();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@
|
||||||
#include "Graph.hh"
|
#include "Graph.hh"
|
||||||
#include "Parasitics.hh"
|
#include "Parasitics.hh"
|
||||||
#include "Sdc.hh"
|
#include "Sdc.hh"
|
||||||
#include "DcalcAnalysisPt.hh"
|
|
||||||
#include "DelayCalc.hh"
|
#include "DelayCalc.hh"
|
||||||
#include "ArcDelayCalc.hh"
|
#include "ArcDelayCalc.hh"
|
||||||
#include "LumpedCapDelayCalc.hh"
|
#include "LumpedCapDelayCalc.hh"
|
||||||
|
|
@ -129,17 +128,20 @@ public:
|
||||||
const char *name() const override { return "arnoldi"; }
|
const char *name() const override { return "arnoldi"; }
|
||||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||||
float in_slew,
|
float in_slew,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &in_slew,
|
const Slew &in_slew,
|
||||||
|
|
@ -147,14 +149,16 @@ public:
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
string reportGateDelay(const Pin *drvr_pin,
|
string reportGateDelay(const Pin *drvr_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &in_slew,
|
const Slew &in_slew,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits) override;
|
int digits) override;
|
||||||
void finishDrvrPin() override;
|
void finishDrvrPin() override;
|
||||||
void delay_work_set_thresholds(delay_work *D,
|
void delay_work_set_thresholds(delay_work *D,
|
||||||
|
|
@ -273,35 +277,34 @@ ArnoldiDelayCalc::~ArnoldiDelayCalc()
|
||||||
Parasitic *
|
Parasitic *
|
||||||
ArnoldiDelayCalc::findParasitic(const Pin *drvr_pin,
|
ArnoldiDelayCalc::findParasitic(const Pin *drvr_pin,
|
||||||
const RiseFall *drvr_rf,
|
const RiseFall *drvr_rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
Parasitic *parasitic = nullptr;
|
Parasitic *parasitic = nullptr;
|
||||||
const Corner *corner = dcalc_ap->corner();
|
const Sdc *sdc = scene->sdc();
|
||||||
|
Parasitics *parasitics = scene->parasitics(min_max);
|
||||||
|
if (parasitics == nullptr
|
||||||
// set_load net has precedence over parasitics.
|
// set_load net has precedence over parasitics.
|
||||||
if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|
|
||||||
|| network_->direction(drvr_pin)->isInternal())
|
|| network_->direction(drvr_pin)->isInternal())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
|
||||||
Parasitic *parasitic_network =
|
Parasitic *parasitic_network =
|
||||||
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
|
parasitics->findParasiticNetwork(drvr_pin);
|
||||||
const MinMax *min_max = dcalc_ap->constraintMinMax();
|
|
||||||
if (parasitic_network == nullptr) {
|
if (parasitic_network == nullptr) {
|
||||||
Wireload *wireload = sdc_->wireload(min_max);
|
Wireload *wireload = sdc->wireload(min_max);
|
||||||
if (wireload) {
|
if (wireload) {
|
||||||
float pin_cap, wire_cap, fanout;
|
float pin_cap, wire_cap, fanout;
|
||||||
bool has_wire_cap;
|
bool has_wire_cap;
|
||||||
graph_delay_calc_->netCaps(drvr_pin, drvr_rf, dcalc_ap,
|
graph_delay_calc_->netCaps(drvr_pin, drvr_rf, scene, min_max,
|
||||||
pin_cap, wire_cap, fanout, has_wire_cap);
|
pin_cap, wire_cap, fanout, has_wire_cap);
|
||||||
parasitic_network = parasitics_->makeWireloadNetwork(drvr_pin, wireload,
|
parasitic_network = parasitics->makeWireloadNetwork(drvr_pin, wireload,
|
||||||
fanout, min_max,
|
fanout, scene, min_max);
|
||||||
parasitic_ap);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parasitic_network) {
|
if (parasitic_network) {
|
||||||
rcmodel *rcmodel = reduce_->reduceToArnoldi(parasitic_network, drvr_pin,
|
rcmodel *rcmodel = reduce_->reduceToArnoldi(parasitic_network, drvr_pin,
|
||||||
parasitic_ap->couplingCapFactor(),
|
parasitics->couplingCapFactor(),
|
||||||
drvr_rf, corner, min_max, parasitic_ap);
|
drvr_rf, scene, min_max);
|
||||||
// Arnoldi parasitics are their own class that are not saved in the parasitic db.
|
// Arnoldi parasitics are their own class that are not saved in the parasitic db.
|
||||||
unsaved_parasitics_.push_back(rcmodel);
|
unsaved_parasitics_.push_back(rcmodel);
|
||||||
parasitic = rcmodel;
|
parasitic = rcmodel;
|
||||||
|
|
@ -313,7 +316,8 @@ Parasitic *
|
||||||
ArnoldiDelayCalc::reduceParasitic(const Parasitic *,
|
ArnoldiDelayCalc::reduceParasitic(const Parasitic *,
|
||||||
const Pin *,
|
const Pin *,
|
||||||
const RiseFall *,
|
const RiseFall *,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *,
|
||||||
|
const MinMax *)
|
||||||
{
|
{
|
||||||
// Decline because reduced arnoldi parasitics are not stored in the parasitics db.
|
// Decline because reduced arnoldi parasitics are not stored in the parasitics db.
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -333,7 +337,8 @@ ArnoldiDelayCalc::inputPortDelay(const Pin *,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *,
|
||||||
|
const MinMax *)
|
||||||
{
|
{
|
||||||
rcmodel_ = nullptr;
|
rcmodel_ = nullptr;
|
||||||
_delayV[0] = 0.0;
|
_delayV[0] = 0.0;
|
||||||
|
|
@ -389,21 +394,22 @@ ArnoldiDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
const LibertyCell *drvr_cell = arc->from()->libertyCell();
|
const LibertyCell *drvr_cell = arc->from()->libertyCell();
|
||||||
ConcreteParasitic *cparasitic =
|
ConcreteParasitic *cparasitic =
|
||||||
reinterpret_cast<ConcreteParasitic*>(const_cast<Parasitic*>(parasitic));
|
reinterpret_cast<ConcreteParasitic*>(const_cast<Parasitic*>(parasitic));
|
||||||
rcmodel_ = dynamic_cast<rcmodel*>(cparasitic);
|
rcmodel_ = dynamic_cast<rcmodel*>(cparasitic);
|
||||||
pocv_enabled_ = variables_->pocvEnabled();
|
pocv_enabled_ = variables_->pocvEnabled();
|
||||||
GateTableModel *table_model = arc->gateTableModel(dcalc_ap);
|
GateTableModel *table_model = arc->gateTableModel(scene, min_max);
|
||||||
if (table_model && rcmodel_) {
|
if (table_model && rcmodel_) {
|
||||||
const Pvt *pvt = pinPvt(drvr_pin, dcalc_ap);
|
const Pvt *pvt = pinPvt(drvr_pin, scene, min_max);
|
||||||
return gateDelaySlew(drvr_cell, arc, table_model, in_slew, load_pin_index_map, pvt);
|
return gateDelaySlew(drvr_cell, arc, table_model, in_slew, load_pin_index_map, pvt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return LumpedCapDelayCalc::gateDelay(drvr_pin, arc, in_slew, load_cap,
|
return LumpedCapDelayCalc::gateDelay(drvr_pin, arc, in_slew, load_cap,
|
||||||
parasitic, load_pin_index_map, dcalc_ap);
|
parasitic, load_pin_index_map, scene, min_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArcDcalcResult
|
ArcDcalcResult
|
||||||
|
|
@ -470,12 +476,13 @@ ArnoldiDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits)
|
int digits)
|
||||||
{
|
{
|
||||||
return LumpedCapDelayCalc::reportGateDelay(drvr_pin, arc, in_slew, load_cap,
|
return LumpedCapDelayCalc::reportGateDelay(drvr_pin, arc, in_slew, load_cap,
|
||||||
parasitic, load_pin_index_map,
|
parasitic, load_pin_index_map,
|
||||||
dcalc_ap, digits);
|
scene, min_max, digits);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -154,17 +154,17 @@ ArnoldiReduce::reduceToArnoldi(Parasitic *parasitic,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
float coupling_cap_factor,
|
float coupling_cap_factor,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max)
|
||||||
const ParasiticAnalysisPt *ap)
|
|
||||||
{
|
{
|
||||||
parasitic_network_ = reinterpret_cast<ConcreteParasiticNetwork*>(parasitic);
|
|
||||||
drvr_pin_ = drvr_pin;
|
drvr_pin_ = drvr_pin;
|
||||||
coupling_cap_factor_ = coupling_cap_factor;
|
coupling_cap_factor_ = coupling_cap_factor;
|
||||||
rf_ = rf;
|
rf_ = rf;
|
||||||
corner_ = corner;
|
scene_ = scene;
|
||||||
min_max_ = min_max;
|
min_max_ = min_max;
|
||||||
ap_ = ap;
|
parasitics_ = scene->parasitics(min_max);
|
||||||
|
parasitic_network_ = reinterpret_cast<ConcreteParasiticNetwork*>(parasitic);
|
||||||
|
|
||||||
loadWork();
|
loadWork();
|
||||||
return makeRcmodelDrv();
|
return makeRcmodelDrv();
|
||||||
}
|
}
|
||||||
|
|
@ -444,7 +444,7 @@ ArnoldiReduce::getRC()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (ParasiticCapacitor *capacitor : parasitics_->capacitors(parasitic_network_)) {
|
for (ParasiticCapacitor *capacitor : parasitics_->capacitors(parasitic_network_)) {
|
||||||
float cap = parasitics_->value(capacitor) * ap_->couplingCapFactor();
|
float cap = parasitics_->value(capacitor) * parasitics_->couplingCapFactor();
|
||||||
ParasiticNode *node1 = parasitics_->node1(capacitor);
|
ParasiticNode *node1 = parasitics_->node1(capacitor);
|
||||||
if (!parasitics_->isExternal(node1)) {
|
if (!parasitics_->isExternal(node1)) {
|
||||||
ts_point *pt = findPt(node1);
|
ts_point *pt = findPt(node1);
|
||||||
|
|
@ -466,10 +466,11 @@ ArnoldiReduce::pinCapacitance(ParasiticNode *node)
|
||||||
if (pin) {
|
if (pin) {
|
||||||
Port *port = network_->port(pin);
|
Port *port = network_->port(pin);
|
||||||
LibertyPort *lib_port = network_->libertyPort(port);
|
LibertyPort *lib_port = network_->libertyPort(port);
|
||||||
|
const Sdc *sdc = scene_->sdc();
|
||||||
if (lib_port)
|
if (lib_port)
|
||||||
pin_cap = sdc_->pinCapacitance(pin,rf_, corner_, min_max_);
|
pin_cap = sdc->pinCapacitance(pin,rf_, scene_, min_max_);
|
||||||
else if (network_->isTopLevelPort(pin))
|
else if (network_->isTopLevelPort(pin))
|
||||||
pin_cap = sdc_->portExtCap(port, rf_, corner_, min_max_);
|
pin_cap = sdc->portExtCap(port, rf_, min_max_);
|
||||||
}
|
}
|
||||||
return pin_cap;
|
return pin_cap;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Map.hh"
|
#include <map>
|
||||||
|
|
||||||
#include "Transition.hh"
|
#include "Transition.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
#include "ParasiticsClass.hh"
|
#include "ParasiticsClass.hh"
|
||||||
|
|
@ -39,13 +40,13 @@ namespace sta {
|
||||||
|
|
||||||
class ConcreteParasiticNetwork;
|
class ConcreteParasiticNetwork;
|
||||||
class ConcreteParasiticNode;
|
class ConcreteParasiticNode;
|
||||||
class Corner;
|
class Scene;
|
||||||
|
|
||||||
class rcmodel;
|
class rcmodel;
|
||||||
struct ts_edge;
|
struct ts_edge;
|
||||||
struct ts_point;
|
struct ts_point;
|
||||||
|
|
||||||
typedef Map<ParasiticNode*, int> ArnolidPtMap;
|
using ArnolidPtMap = std::map<ParasiticNode*, int>;
|
||||||
|
|
||||||
class ArnoldiReduce : public StaState
|
class ArnoldiReduce : public StaState
|
||||||
{
|
{
|
||||||
|
|
@ -56,9 +57,8 @@ public:
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
float coupling_cap_factor,
|
float coupling_cap_factor,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *cnst_min_max,
|
const MinMax *min_max);
|
||||||
const ParasiticAnalysisPt *ap);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void loadWork();
|
void loadWork();
|
||||||
|
|
@ -73,13 +73,13 @@ protected:
|
||||||
void makeRcmodelFromTs();
|
void makeRcmodelFromTs();
|
||||||
rcmodel *makeRcmodelFromW();
|
rcmodel *makeRcmodelFromW();
|
||||||
|
|
||||||
|
Parasitics *parasitics_;
|
||||||
ConcreteParasiticNetwork *parasitic_network_;
|
ConcreteParasiticNetwork *parasitic_network_;
|
||||||
const Pin *drvr_pin_;
|
const Pin *drvr_pin_;
|
||||||
float coupling_cap_factor_;
|
float coupling_cap_factor_;
|
||||||
const RiseFall *rf_;
|
const RiseFall *rf_;
|
||||||
const Corner *corner_;
|
const Scene *scene_;
|
||||||
const MinMax *min_max_;
|
const MinMax *min_max_;
|
||||||
const ParasiticAnalysisPt *ap_;
|
|
||||||
// ParasiticNode -> ts_point index.
|
// ParasiticNode -> ts_point index.
|
||||||
ArnolidPtMap pt_map_;
|
ArnolidPtMap pt_map_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,7 @@
|
||||||
#include "TimingArc.hh"
|
#include "TimingArc.hh"
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "Graph.hh"
|
#include "Graph.hh"
|
||||||
#include "Corner.hh"
|
#include "Scene.hh"
|
||||||
#include "DcalcAnalysisPt.hh"
|
|
||||||
#include "Parasitics.hh"
|
#include "Parasitics.hh"
|
||||||
#include "GraphDelayCalc.hh"
|
#include "GraphDelayCalc.hh"
|
||||||
#include "DmpDelayCalc.hh"
|
#include "DmpDelayCalc.hh"
|
||||||
|
|
@ -86,17 +85,20 @@ CcsCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
in_slew_ = delayAsFloat(in_slew);
|
in_slew_ = delayAsFloat(in_slew);
|
||||||
load_cap_ = load_cap;
|
load_cap_ = load_cap;
|
||||||
|
parasitics_ = scene->parasitics(min_max);
|
||||||
parasitic_ = parasitic;
|
parasitic_ = parasitic;
|
||||||
output_waveforms_ = nullptr;
|
output_waveforms_ = nullptr;
|
||||||
|
|
||||||
GateTableModel *table_model = arc->gateTableModel(dcalc_ap);
|
GateTableModel *table_model = arc->gateTableModel(scene, min_max);
|
||||||
if (table_model && parasitic) {
|
if (table_model && parasitic) {
|
||||||
OutputWaveforms *output_waveforms = table_model->outputWaveforms();
|
OutputWaveforms *output_waveforms = table_model->outputWaveforms();
|
||||||
parasitics_->piModel(parasitic, c2_, rpi_, c1_);
|
Parasitics *parasitics = scene->parasitics(min_max);
|
||||||
|
parasitics->piModel(parasitic, c2_, rpi_, c1_);
|
||||||
if (output_waveforms
|
if (output_waveforms
|
||||||
&& rpi_ > 0.0 && c1_ > 0.0
|
&& rpi_ > 0.0 && c1_ > 0.0
|
||||||
// Bounds check because extrapolating waveforms does not work for shit.
|
// Bounds check because extrapolating waveforms does not work for shit.
|
||||||
|
|
@ -114,8 +116,7 @@ CcsCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||||
vl_ = drvr_library->slewLowerThreshold(drvr_rf_) * vdd_;
|
vl_ = drvr_library->slewLowerThreshold(drvr_rf_) * vdd_;
|
||||||
vh_ = drvr_library->slewUpperThreshold(drvr_rf_) * vdd_;
|
vh_ = drvr_library->slewUpperThreshold(drvr_rf_) * vdd_;
|
||||||
|
|
||||||
const DcalcAnalysisPtSeq &dcalc_aps = corners_->dcalcAnalysisPts();
|
drvr_cell->ensureVoltageWaveforms(scenes_);
|
||||||
drvr_cell->ensureVoltageWaveforms(dcalc_aps);
|
|
||||||
in_slew_ = delayAsFloat(in_slew);
|
in_slew_ = delayAsFloat(in_slew);
|
||||||
output_waveforms_ = output_waveforms;
|
output_waveforms_ = output_waveforms;
|
||||||
ref_time_ = output_waveforms_->referenceTime(in_slew_);
|
ref_time_ = output_waveforms_->referenceTime(in_slew_);
|
||||||
|
|
@ -129,7 +130,7 @@ CcsCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return table_dcalc_->gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic,
|
return table_dcalc_->gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic,
|
||||||
load_pin_index_map, dcalc_ap);
|
load_pin_index_map, scene, min_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -574,7 +575,7 @@ CcsCeffDelayCalc::drvrRampWaveform(const Pin *in_pin,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *drvr_rf,
|
const RiseFall *drvr_rf,
|
||||||
const Pin *load_pin,
|
const Pin *load_pin,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *min_max)
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
bool elmore_exists = false;
|
bool elmore_exists = false;
|
||||||
|
|
@ -582,7 +583,7 @@ CcsCeffDelayCalc::drvrRampWaveform(const Pin *in_pin,
|
||||||
if (parasitic_) {
|
if (parasitic_) {
|
||||||
parasitics_->findElmore(parasitic_, load_pin, elmore, elmore_exists);
|
parasitics_->findElmore(parasitic_, load_pin, elmore, elmore_exists);
|
||||||
bool dcalc_success = makeWaveformPreamble(in_pin, in_rf, drvr_pin,
|
bool dcalc_success = makeWaveformPreamble(in_pin, in_rf, drvr_pin,
|
||||||
drvr_rf, corner, min_max);
|
drvr_rf, scene, min_max);
|
||||||
if (dcalc_success
|
if (dcalc_success
|
||||||
&& elmore_exists) {
|
&& elmore_exists) {
|
||||||
FloatSeq *load_times = new FloatSeq;
|
FloatSeq *load_times = new FloatSeq;
|
||||||
|
|
@ -617,7 +618,7 @@ CcsCeffDelayCalc::makeWaveformPreamble(const Pin *in_pin,
|
||||||
const RiseFall *in_rf,
|
const RiseFall *in_rf,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *drvr_rf,
|
const RiseFall *drvr_rf,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *min_max)
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
Vertex *in_vertex = graph_->pinLoadVertex(in_pin);
|
Vertex *in_vertex = graph_->pinLoadVertex(in_pin);
|
||||||
|
|
@ -641,15 +642,15 @@ CcsCeffDelayCalc::makeWaveformPreamble(const Pin *in_pin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (arc) {
|
if (arc) {
|
||||||
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
DcalcAPIndex slew_index = scene->dcalcAnalysisPtIndex(min_max);
|
||||||
const Slew &in_slew = graph_->slew(in_vertex, in_rf, dcalc_ap->index());
|
const Slew &in_slew = graph_->slew(in_vertex, in_rf, slew_index);
|
||||||
parasitic_ = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf, dcalc_ap);
|
parasitic_ = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf, scene, min_max);
|
||||||
if (parasitic_) {
|
if (parasitic_) {
|
||||||
parasitics_->piModel(parasitic_, c2_, rpi_, c1_);
|
parasitics_->piModel(parasitic_, c2_, rpi_, c1_);
|
||||||
LoadPinIndexMap load_pin_index_map =
|
LoadPinIndexMap load_pin_index_map =
|
||||||
graph_delay_calc_->makeLoadPinIndexMap(drvr_vertex);
|
graph_delay_calc_->makeLoadPinIndexMap(drvr_vertex);
|
||||||
gateDelay(drvr_pin, arc, in_slew, load_cap_, parasitic_,
|
gateDelay(drvr_pin, arc, in_slew, load_cap_, parasitic_,
|
||||||
load_pin_index_map, dcalc_ap);
|
load_pin_index_map, scene, min_max);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -666,20 +667,19 @@ CcsCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits)
|
int digits)
|
||||||
{
|
{
|
||||||
Parasitic *pi_elmore = nullptr;
|
Parasitic *pi_elmore = nullptr;
|
||||||
const RiseFall *rf = arc->toEdge()->asRiseFall();
|
const RiseFall *rf = arc->toEdge()->asRiseFall();
|
||||||
if (parasitic && !parasitics_->isPiElmore(parasitic)) {
|
if (parasitic && !parasitics_->isPiElmore(parasitic)) {
|
||||||
const ParasiticAnalysisPt *ap = dcalc_ap->parasiticAnalysisPt();
|
|
||||||
pi_elmore = parasitics_->reduceToPiElmore(parasitic, drvr_pin_, rf,
|
pi_elmore = parasitics_->reduceToPiElmore(parasitic, drvr_pin_, rf,
|
||||||
dcalc_ap->corner(),
|
scene, min_max);
|
||||||
dcalc_ap->constraintMinMax(), ap);
|
|
||||||
}
|
}
|
||||||
string report = table_dcalc_->reportGateDelay(drvr_pin, arc, in_slew, load_cap,
|
string report = table_dcalc_->reportGateDelay(drvr_pin, arc, in_slew, load_cap,
|
||||||
pi_elmore, load_pin_index_map,
|
pi_elmore, load_pin_index_map,
|
||||||
dcalc_ap, digits);
|
scene, min_max, digits);
|
||||||
parasitics_->deleteDrvrReducedParasitics(drvr_pin);
|
parasitics_->deleteDrvrReducedParasitics(drvr_pin);
|
||||||
return report;
|
return report;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef std::map<const Pin*, FloatSeq, PinIdLess> WatchPinValuesMap;
|
using WatchPinValuesMap = std::map<const Pin*, FloatSeq, PinIdLess>;
|
||||||
|
|
||||||
ArcDelayCalc *
|
ArcDelayCalc *
|
||||||
makeCcsCeffDelayCalc(StaState *sta);
|
makeCcsCeffDelayCalc(StaState *sta);
|
||||||
|
|
@ -49,14 +49,16 @@ public:
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
std::string reportGateDelay(const Pin *drvr_pin,
|
std::string reportGateDelay(const Pin *drvr_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &in_slew,
|
const Slew &in_slew,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits) override;
|
int digits) override;
|
||||||
|
|
||||||
// Record waveform for drvr/load pin.
|
// Record waveform for drvr/load pin.
|
||||||
|
|
@ -100,7 +102,7 @@ protected:
|
||||||
const RiseFall *in_rf,
|
const RiseFall *in_rf,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *drvr_rf,
|
const RiseFall *drvr_rf,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
Waveform drvrWaveform();
|
Waveform drvrWaveform();
|
||||||
Waveform loadWaveform(const Pin *load_pin);
|
Waveform loadWaveform(const Pin *load_pin);
|
||||||
|
|
@ -109,7 +111,7 @@ protected:
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *drvr_rf,
|
const RiseFall *drvr_rf,
|
||||||
const Pin *load_pin,
|
const Pin *load_pin,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
void vl(double t,
|
void vl(double t,
|
||||||
double elmore,
|
double elmore,
|
||||||
|
|
@ -124,6 +126,7 @@ protected:
|
||||||
const RiseFall *drvr_rf_;
|
const RiseFall *drvr_rf_;
|
||||||
double in_slew_;
|
double in_slew_;
|
||||||
double load_cap_;
|
double load_cap_;
|
||||||
|
Parasitics *parasitics_;
|
||||||
const Parasitic *parasitic_;
|
const Parasitic *parasitic_;
|
||||||
|
|
||||||
OutputWaveforms *output_waveforms_;
|
OutputWaveforms *output_waveforms_;
|
||||||
|
|
|
||||||
|
|
@ -1,68 +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.
|
|
||||||
|
|
||||||
#include "StringUtil.hh"
|
|
||||||
#include "DcalcAnalysisPt.hh"
|
|
||||||
#include "Corner.hh"
|
|
||||||
|
|
||||||
namespace sta {
|
|
||||||
|
|
||||||
DcalcAnalysisPt::DcalcAnalysisPt(Corner *corner,
|
|
||||||
DcalcAPIndex index,
|
|
||||||
const OperatingConditions *op_cond,
|
|
||||||
const MinMax *min_max,
|
|
||||||
const MinMax *check_clk_slew_min_max) :
|
|
||||||
corner_(corner),
|
|
||||||
index_(index),
|
|
||||||
op_cond_(op_cond),
|
|
||||||
min_max_(min_max),
|
|
||||||
check_clk_slew_min_max_(check_clk_slew_min_max)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DcalcAnalysisPt::setOperatingConditions(const OperatingConditions *op_cond)
|
|
||||||
{
|
|
||||||
op_cond_ = op_cond;
|
|
||||||
}
|
|
||||||
|
|
||||||
ParasiticAnalysisPt *
|
|
||||||
DcalcAnalysisPt::parasiticAnalysisPt() const
|
|
||||||
{
|
|
||||||
return corner_->findParasiticAnalysisPt(min_max_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DcalcAnalysisPt::setCheckClkSlewIndex(DcalcAPIndex index)
|
|
||||||
{
|
|
||||||
check_clk_slew_index_ = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
DcalcAnalysisPt::libertyIndex() const
|
|
||||||
{
|
|
||||||
return corner_->libertyIndex(min_max_);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
@ -24,7 +24,9 @@
|
||||||
|
|
||||||
#include "DelayCalc.hh"
|
#include "DelayCalc.hh"
|
||||||
|
|
||||||
#include "Map.hh"
|
#include <map>
|
||||||
|
|
||||||
|
#include "ContainerHelpers.hh"
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "UnitDelayCalc.hh"
|
#include "UnitDelayCalc.hh"
|
||||||
#include "LumpedCapDelayCalc.hh"
|
#include "LumpedCapDelayCalc.hh"
|
||||||
|
|
@ -35,7 +37,7 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef Map<const char*, MakeArcDelayCalc, CharPtrLess> DelayCalcMap;
|
typedef std::map<const char*, MakeArcDelayCalc, CharPtrLess> DelayCalcMap;
|
||||||
|
|
||||||
static DelayCalcMap *delay_calcs = nullptr;
|
static DelayCalcMap *delay_calcs = nullptr;
|
||||||
|
|
||||||
|
|
@ -71,7 +73,7 @@ ArcDelayCalc *
|
||||||
makeDelayCalc(const char *name,
|
makeDelayCalc(const char *name,
|
||||||
StaState *sta)
|
StaState *sta)
|
||||||
{
|
{
|
||||||
MakeArcDelayCalc maker = delay_calcs->findKey(name);
|
MakeArcDelayCalc maker = findKey(delay_calcs, name);
|
||||||
if (maker)
|
if (maker)
|
||||||
return maker(sta);
|
return maker(sta);
|
||||||
else
|
else
|
||||||
|
|
@ -81,7 +83,7 @@ makeDelayCalc(const char *name,
|
||||||
bool
|
bool
|
||||||
isDelayCalcName(const char *name)
|
isDelayCalcName(const char *name)
|
||||||
{
|
{
|
||||||
return delay_calcs->hasKey(name);
|
return delay_calcs->contains(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringSeq
|
StringSeq
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,6 @@
|
||||||
#include "dcalc/PrimaDelayCalc.hh"
|
#include "dcalc/PrimaDelayCalc.hh"
|
||||||
#include "Sta.hh"
|
#include "Sta.hh"
|
||||||
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
|
|
@ -62,15 +60,15 @@ set_delay_calc_incremental_tolerance(float tol)
|
||||||
Sta::sta()->setIncrementalDelayTolerance(tol);
|
Sta::sta()->setIncrementalDelayTolerance(tol);
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
std::string
|
||||||
report_delay_calc_cmd(Edge *edge,
|
report_delay_calc_cmd(Edge *edge,
|
||||||
TimingArc *arc,
|
TimingArc *arc,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
int digits)
|
int digits)
|
||||||
{
|
{
|
||||||
Sta *sta = Sta::sta();
|
Sta *sta = Sta::sta();
|
||||||
return sta->reportDelayCalc(edge, arc, corner, min_max, digits);
|
return sta->reportDelayCalc(edge, arc, scene, min_max, digits);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
namespace eval sta {
|
namespace eval sta {
|
||||||
|
|
||||||
define_cmd_args "report_dcalc" \
|
define_cmd_args "report_dcalc" \
|
||||||
{[-from from_pin] [-to to_pin] [-corner corner] [-min] [-max] [-digits digits]}
|
{[-from from_pin] [-to to_pin] [-scene scene] [-min] [-max] [-digits digits]}
|
||||||
|
|
||||||
proc_redirect report_dcalc {
|
proc_redirect report_dcalc {
|
||||||
report_dcalc_cmd "report_dcalc" $args "-digits"
|
report_dcalc_cmd "report_dcalc" $args "-digits"
|
||||||
|
|
@ -36,9 +36,9 @@ proc report_dcalc_cmd { cmd cmd_args digits_key } {
|
||||||
global sta_report_default_digits
|
global sta_report_default_digits
|
||||||
|
|
||||||
parse_key_args $cmd cmd_args \
|
parse_key_args $cmd cmd_args \
|
||||||
keys "$digits_key -from -to -corner" \
|
keys "$digits_key -from -to -scene -corner" \
|
||||||
flags {-min -max}
|
flags {-min -max}
|
||||||
set corner [parse_corner keys]
|
set scene [parse_scene keys]
|
||||||
set min_max [parse_min_max_flags flags]
|
set min_max [parse_min_max_flags flags]
|
||||||
check_argc_eq0 $cmd $cmd_args
|
check_argc_eq0 $cmd $cmd_args
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ proc report_dcalc_cmd { cmd cmd_args digits_key } {
|
||||||
while {[$iter has_next]} {
|
while {[$iter has_next]} {
|
||||||
set edge [$iter next]
|
set edge [$iter next]
|
||||||
if { [$edge to] == $to_vertex } {
|
if { [$edge to] == $to_vertex } {
|
||||||
report_edge_dcalc $edge $corner $min_max $digits
|
report_edge_dcalc $edge $scene $min_max $digits
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$iter finish
|
$iter finish
|
||||||
|
|
@ -68,7 +68,7 @@ proc report_dcalc_cmd { cmd cmd_args digits_key } {
|
||||||
set iter [$from_vertex out_edge_iterator]
|
set iter [$from_vertex out_edge_iterator]
|
||||||
while {[$iter has_next]} {
|
while {[$iter has_next]} {
|
||||||
set edge [$iter next]
|
set edge [$iter next]
|
||||||
report_edge_dcalc $edge $corner $min_max $digits
|
report_edge_dcalc $edge $scene $min_max $digits
|
||||||
}
|
}
|
||||||
$iter finish
|
$iter finish
|
||||||
}
|
}
|
||||||
|
|
@ -78,14 +78,14 @@ proc report_dcalc_cmd { cmd cmd_args digits_key } {
|
||||||
set iter [$to_vertex in_edge_iterator]
|
set iter [$to_vertex in_edge_iterator]
|
||||||
while {[$iter has_next]} {
|
while {[$iter has_next]} {
|
||||||
set edge [$iter next]
|
set edge [$iter next]
|
||||||
report_edge_dcalc $edge $corner $min_max $digits
|
report_edge_dcalc $edge $scene $min_max $digits
|
||||||
}
|
}
|
||||||
$iter finish
|
$iter finish
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc report_edge_dcalc { edge corner min_max digits } {
|
proc report_edge_dcalc { edge scene min_max digits } {
|
||||||
set role [$edge role]
|
set role [$edge role]
|
||||||
if { $role != "wire" } {
|
if { $role != "wire" } {
|
||||||
set from_vertex [$edge from]
|
set from_vertex [$edge from]
|
||||||
|
|
@ -111,9 +111,9 @@ proc report_edge_dcalc { edge corner min_max digits } {
|
||||||
set to [get_name [$to_pin port]]
|
set to [get_name [$to_pin port]]
|
||||||
set to_rf [$arc to_edge]
|
set to_rf [$arc to_edge]
|
||||||
report_line "$from $from_rf -> $to $to_rf"
|
report_line "$from $from_rf -> $to $to_rf"
|
||||||
report_line [report_delay_calc_cmd $edge $arc $corner $min_max $digits]
|
report_line [report_delay_calc_cmd $edge $arc $scene $min_max $digits]
|
||||||
if { [$edge delay_annotated $arc $corner $min_max] } {
|
if { [$edge delay_annotated $arc $scene $min_max] } {
|
||||||
set delay [$edge arc_delay $arc $corner $min_max]
|
set delay [$edge arc_delay $arc $scene $min_max]
|
||||||
report_line "Annotated value = [format_time $delay $digits]"
|
report_line "Annotated value = [format_time $delay $digits]"
|
||||||
}
|
}
|
||||||
report_line "............................................."
|
report_line "............................................."
|
||||||
|
|
@ -140,16 +140,16 @@ define_cmd_args "set_pocv_sigma_factor" { factor }
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
define_cmd_args "set_assigned_delay" \
|
define_cmd_args "set_assigned_delay" \
|
||||||
{-cell|-net [-rise] [-fall] [-corner corner] [-min] [-max]\
|
{-cell|-net [-rise] [-fall] [-scene scene] [-min] [-max]\
|
||||||
[-from from_pins] [-to to_pins] delay}
|
[-from from_pins] [-to to_pins] delay}
|
||||||
|
|
||||||
# Change the delay for timing arcs between from_pins and to_pins matching
|
# Change the delay for timing arcs between from_pins and to_pins matching
|
||||||
# on cell (instance) or net.
|
# on cell (instance) or net.
|
||||||
proc set_assigned_delay { args } {
|
proc set_assigned_delay { args } {
|
||||||
parse_key_args "set_assigned_delay" args keys {-corner -from -to} \
|
parse_key_args "set_assigned_delay" args keys {-scene -corner -from -to} \
|
||||||
flags {-cell -net -rise -fall -max -min}
|
flags {-cell -net -rise -fall -max -min}
|
||||||
check_argc_eq1 "set_assigned_delay" $args
|
check_argc_eq1 "set_assigned_delay" $args
|
||||||
set corner [parse_corner keys]
|
set scene [parse_scene keys]
|
||||||
set min_max [parse_min_max_all_check_flags flags]
|
set min_max [parse_min_max_all_check_flags flags]
|
||||||
set to_rf [parse_rise_fall_flags flags]
|
set to_rf [parse_rise_fall_flags flags]
|
||||||
|
|
||||||
|
|
@ -192,28 +192,28 @@ proc set_assigned_delay { args } {
|
||||||
foreach from_pin $from_pins {
|
foreach from_pin $from_pins {
|
||||||
set from_vertices [$from_pin vertices]
|
set from_vertices [$from_pin vertices]
|
||||||
set_assigned_delay1 [lindex $from_vertices 0] \
|
set_assigned_delay1 [lindex $from_vertices 0] \
|
||||||
$to_pins $to_rf $corner $min_max $delay
|
$to_pins $to_rf $scene $min_max $delay
|
||||||
if { [llength $from_vertices] == 2 } {
|
if { [llength $from_vertices] == 2 } {
|
||||||
set_assigned_delay1 [lindex $from_vertices 1] \
|
set_assigned_delay1 [lindex $from_vertices 1] \
|
||||||
$to_pins $to_rf $corner $min_max $delay
|
$to_pins $to_rf $scene $min_max $delay
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc set_assigned_delay1 { from_vertex to_pins to_rf corner min_max delay } {
|
proc set_assigned_delay1 { from_vertex to_pins to_rf scene min_max delay } {
|
||||||
foreach to_pin $to_pins {
|
foreach to_pin $to_pins {
|
||||||
set to_vertices [$to_pin vertices]
|
set to_vertices [$to_pin vertices]
|
||||||
set_assigned_delay2 $from_vertex [lindex $to_vertices 0] \
|
set_assigned_delay2 $from_vertex [lindex $to_vertices 0] \
|
||||||
$to_rf $corner $min_max $delay
|
$to_rf $scene $min_max $delay
|
||||||
if { [llength $to_vertices] == 2 } {
|
if { [llength $to_vertices] == 2 } {
|
||||||
# Bidirect driver.
|
# Bidirect driver.
|
||||||
set_assigned_delay2 $from_vertex [lindex $to_vertices 1] \
|
set_assigned_delay2 $from_vertex [lindex $to_vertices 1] \
|
||||||
$to_rf $corner $min_max $delay
|
$to_rf $scene $min_max $delay
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc set_assigned_delay2 {from_vertex to_vertex to_rf corner min_max delay} {
|
proc set_assigned_delay2 {from_vertex to_vertex to_rf scene min_max delay} {
|
||||||
set matched 0
|
set matched 0
|
||||||
set edge_iter [$from_vertex out_edge_iterator]
|
set edge_iter [$from_vertex out_edge_iterator]
|
||||||
while {[$edge_iter has_next]} {
|
while {[$edge_iter has_next]} {
|
||||||
|
|
@ -223,7 +223,7 @@ proc set_assigned_delay2 {from_vertex to_vertex to_rf corner min_max delay} {
|
||||||
foreach arc [$edge timing_arcs] {
|
foreach arc [$edge timing_arcs] {
|
||||||
if { $to_rf == "rise_fall" \
|
if { $to_rf == "rise_fall" \
|
||||||
|| $to_rf eq [$arc to_edge_name] } {
|
|| $to_rf eq [$arc to_edge_name] } {
|
||||||
set_arc_delay $edge $arc $corner $min_max $delay
|
set_arc_delay $edge $arc $scene $min_max $delay
|
||||||
set matched 1
|
set matched 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -239,13 +239,13 @@ proc set_assigned_delay2 {from_vertex to_vertex to_rf corner min_max delay} {
|
||||||
|
|
||||||
define_cmd_args "set_assigned_check" \
|
define_cmd_args "set_assigned_check" \
|
||||||
{-setup|-hold|-recovery|-removal [-rise] [-fall]\
|
{-setup|-hold|-recovery|-removal [-rise] [-fall]\
|
||||||
[-corner corner] [-min] [-max]\
|
[-scene scene] [-min] [-max]\
|
||||||
[-from from_pins] [-to to_pins] [-clock rise|fall]\
|
[-from from_pins] [-to to_pins] [-clock rise|fall]\
|
||||||
[-cond sdf_cond] check_value}
|
[-cond sdf_cond] check_value}
|
||||||
|
|
||||||
proc set_assigned_check { args } {
|
proc set_assigned_check { args } {
|
||||||
parse_key_args "set_assigned_check" args \
|
parse_key_args "set_assigned_check" args \
|
||||||
keys {-from -to -corner -clock -cond} \
|
keys {-from -to -scene -corner -clock -cond} \
|
||||||
flags {-setup -hold -recovery -removal -rise -fall -max -min}
|
flags {-setup -hold -recovery -removal -rise -fall -max -min}
|
||||||
check_argc_eq1 "set_assigned_check" $args
|
check_argc_eq1 "set_assigned_check" $args
|
||||||
|
|
||||||
|
|
@ -271,7 +271,7 @@ proc set_assigned_check { args } {
|
||||||
sta_error 190 "set_assigned_check missing -to argument."
|
sta_error 190 "set_assigned_check missing -to argument."
|
||||||
}
|
}
|
||||||
set to_rf [parse_rise_fall_flags flags]
|
set to_rf [parse_rise_fall_flags flags]
|
||||||
set corner [parse_corner keys]
|
set scene [parse_scene keys]
|
||||||
set min_max [parse_min_max_all_check_flags flags]
|
set min_max [parse_min_max_all_check_flags flags]
|
||||||
|
|
||||||
if { [info exists flags(-setup)] } {
|
if { [info exists flags(-setup)] } {
|
||||||
|
|
@ -298,31 +298,31 @@ proc set_assigned_check { args } {
|
||||||
foreach from_pin $from_pins {
|
foreach from_pin $from_pins {
|
||||||
set from_vertices [$from_pin vertices]
|
set from_vertices [$from_pin vertices]
|
||||||
set_assigned_check1 [lindex $from_vertices 0] $from_rf \
|
set_assigned_check1 [lindex $from_vertices 0] $from_rf \
|
||||||
$to_pins $to_rf $role $corner $min_max $cond $check_value
|
$to_pins $to_rf $role $scene $min_max $cond $check_value
|
||||||
if { [llength $from_vertices] == 2 } {
|
if { [llength $from_vertices] == 2 } {
|
||||||
set_assigned_check1 [lindex $from_vertices 1] $from_rf \
|
set_assigned_check1 [lindex $from_vertices 1] $from_rf \
|
||||||
$to_pins $to_rf $role $corner $min_max $cond $check_value
|
$to_pins $to_rf $role $scene $min_max $cond $check_value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc set_assigned_check1 { from_vertex from_rf to_pins to_rf \
|
proc set_assigned_check1 { from_vertex from_rf to_pins to_rf \
|
||||||
role corner min_max cond check_value } {
|
role scene min_max cond check_value } {
|
||||||
foreach to_pin $to_pins {
|
foreach to_pin $to_pins {
|
||||||
set to_vertices [$to_pin vertices]
|
set to_vertices [$to_pin vertices]
|
||||||
set_assigned_check2 $from_vertex $from_rf [lindex $to_vertices 0] \
|
set_assigned_check2 $from_vertex $from_rf [lindex $to_vertices 0] \
|
||||||
$to_rf $role $corner $min_max $cond $check_value
|
$to_rf $role $scene $min_max $cond $check_value
|
||||||
if { [llength $to_vertices] == 2 } {
|
if { [llength $to_vertices] == 2 } {
|
||||||
# Bidirect driver.
|
# Bidirect driver.
|
||||||
set_assigned_check2 $from_vertex $from_rf \
|
set_assigned_check2 $from_vertex $from_rf \
|
||||||
[lindex $to_vertices 1] $to_rf $role $corner $min_max \
|
[lindex $to_vertices 1] $to_rf $role $scene $min_max \
|
||||||
$cond $check_value
|
$cond $check_value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc set_assigned_check2 { from_vertex from_rf to_vertex to_rf \
|
proc set_assigned_check2 { from_vertex from_rf to_vertex to_rf \
|
||||||
role corner min_max cond check_value } {
|
role scene min_max cond check_value } {
|
||||||
set edge_iter [$from_vertex out_edge_iterator]
|
set edge_iter [$from_vertex out_edge_iterator]
|
||||||
set matched 0
|
set matched 0
|
||||||
while {[$edge_iter has_next]} {
|
while {[$edge_iter has_next]} {
|
||||||
|
|
@ -335,7 +335,7 @@ proc set_assigned_check2 { from_vertex from_rf to_vertex to_rf \
|
||||||
|| $to_rf eq [$arc to_edge_name]) \
|
|| $to_rf eq [$arc to_edge_name]) \
|
||||||
&& [$arc role] eq $role \
|
&& [$arc role] eq $role \
|
||||||
&& ($cond eq "" || [$arc sdf_cond] eq $cond) } {
|
&& ($cond eq "" || [$arc sdf_cond] eq $cond) } {
|
||||||
set_arc_delay $edge $arc $corner $min_max $check_value
|
set_arc_delay $edge $arc $scene $min_max $check_value
|
||||||
set matched 1
|
set matched 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -350,14 +350,14 @@ proc set_assigned_check2 { from_vertex from_rf to_vertex to_rf \
|
||||||
################################################################a
|
################################################################a
|
||||||
|
|
||||||
define_cmd_args "set_assigned_transition" \
|
define_cmd_args "set_assigned_transition" \
|
||||||
{[-rise] [-fall] [-corner corner] [-min] [-max] slew pins}
|
{[-rise] [-fall] [-scene scene] [-min] [-max] slew pins}
|
||||||
|
|
||||||
# Change the slew on a list of ports.
|
# Change the slew on a list of ports.
|
||||||
proc set_assigned_transition { args } {
|
proc set_assigned_transition { args } {
|
||||||
parse_key_args "set_assigned_transition" args keys {-corner} \
|
parse_key_args "set_assigned_transition" args keys {-scene -corner} \
|
||||||
flags {-rise -fall -max -min}
|
flags {-rise -fall -max -min}
|
||||||
|
|
||||||
set corner [parse_corner keys]
|
set scene [parse_scene keys]
|
||||||
set min_max [parse_min_max_all_check_flags flags]
|
set min_max [parse_min_max_all_check_flags flags]
|
||||||
set tr [parse_rise_fall_flags flags]
|
set tr [parse_rise_fall_flags flags]
|
||||||
check_argc_eq2 "set_assigned_transition" $args
|
check_argc_eq2 "set_assigned_transition" $args
|
||||||
|
|
@ -371,7 +371,7 @@ proc set_assigned_transition { args } {
|
||||||
foreach pin $pins {
|
foreach pin $pins {
|
||||||
set vertices [$pin vertices]
|
set vertices [$pin vertices]
|
||||||
set vertex [lindex $vertices 0]
|
set vertex [lindex $vertices 0]
|
||||||
set_annotated_slew $vertex $corner $min_max $tr $slew
|
set_annotated_slew $vertex $scene $min_max $tr $slew
|
||||||
if { [llength $vertices] == 2 } {
|
if { [llength $vertices] == 2 } {
|
||||||
# Bidirect driver.
|
# Bidirect driver.
|
||||||
set vertex [lindex $vertices 1]
|
set vertex [lindex $vertices 1]
|
||||||
|
|
@ -380,5 +380,27 @@ proc set_assigned_transition { args } {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
define_cmd_args "report_slews" {[-scenes scenes] pin}
|
||||||
|
|
||||||
|
proc report_slews { args } {
|
||||||
|
global sta_report_default_digits
|
||||||
|
|
||||||
|
parse_key_args "report_slews" args keys {-corner -scenes} flags {}
|
||||||
|
check_argc_eq1 "report_slews" $args
|
||||||
|
|
||||||
|
set scenes [parse_scenes_or_all keys]
|
||||||
|
set pin [get_port_pin_error "pin" [lindex $args 0]]
|
||||||
|
set digits $sta_report_default_digits
|
||||||
|
foreach vertex [$pin vertices] {
|
||||||
|
set rise_min [format_time [$vertex slew_scenes rise $scenes min] $digits]
|
||||||
|
set rise_max [format_time [$vertex slew_scenes rise $scenes max] $digits]
|
||||||
|
set fall_min [format_time [$vertex slew_scenes fall $scenes min] $digits]
|
||||||
|
set fall_max [format_time [$vertex slew_scenes fall $scenes max] $digits]
|
||||||
|
report_line "[vertex_path_name $vertex] [rise_short_name] $rise_min:$rise_max [fall_short_name] $fall_min:$fall_max"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# sta namespace end
|
# sta namespace end
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,7 @@
|
||||||
#include "Parasitics.hh"
|
#include "Parasitics.hh"
|
||||||
#include "Graph.hh"
|
#include "Graph.hh"
|
||||||
#include "Sdc.hh"
|
#include "Sdc.hh"
|
||||||
#include "Corner.hh"
|
#include "Scene.hh"
|
||||||
#include "DcalcAnalysisPt.hh"
|
|
||||||
#include "GraphDelayCalc.hh"
|
#include "GraphDelayCalc.hh"
|
||||||
#include "Variables.hh"
|
#include "Variables.hh"
|
||||||
|
|
||||||
|
|
@ -50,7 +49,7 @@ DelayCalcBase::DelayCalcBase(StaState *sta) :
|
||||||
void
|
void
|
||||||
DelayCalcBase::reduceParasitic(const Parasitic *parasitic_network,
|
DelayCalcBase::reduceParasitic(const Parasitic *parasitic_network,
|
||||||
const Net *net,
|
const Net *net,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMaxAll *min_max)
|
const MinMaxAll *min_max)
|
||||||
{
|
{
|
||||||
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
|
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
|
||||||
|
|
@ -59,16 +58,12 @@ DelayCalcBase::reduceParasitic(const Parasitic *parasitic_network,
|
||||||
if (network_->isDriver(pin)) {
|
if (network_->isDriver(pin)) {
|
||||||
for (const RiseFall *rf : RiseFall::range()) {
|
for (const RiseFall *rf : RiseFall::range()) {
|
||||||
for (const MinMax *min_max : min_max->range()) {
|
for (const MinMax *min_max : min_max->range()) {
|
||||||
if (corner == nullptr) {
|
if (scene == nullptr) {
|
||||||
for (const Corner *corner1 : *corners_) {
|
for (const Scene *scene1 : scenes_)
|
||||||
DcalcAnalysisPt *dcalc_ap = corner1->findDcalcAnalysisPt(min_max);
|
reduceParasitic(parasitic_network, pin, rf, scene1, min_max);
|
||||||
reduceParasitic(parasitic_network, pin, rf, dcalc_ap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
|
||||||
reduceParasitic(parasitic_network, pin, rf, dcalc_ap);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
reduceParasitic(parasitic_network, pin, rf, scene, min_max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -162,13 +157,15 @@ DelayCalcBase::checkDelay(const Pin *check_pin,
|
||||||
const Slew &from_slew,
|
const Slew &from_slew,
|
||||||
const Slew &to_slew,
|
const Slew &to_slew,
|
||||||
float related_out_cap,
|
float related_out_cap,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
CheckTimingModel *model = arc->checkModel(dcalc_ap);
|
CheckTimingModel *model = arc->checkModel(scene, min_max);
|
||||||
if (model) {
|
if (model) {
|
||||||
float from_slew1 = delayAsFloat(from_slew);
|
float from_slew1 = delayAsFloat(from_slew);
|
||||||
float to_slew1 = delayAsFloat(to_slew);
|
float to_slew1 = delayAsFloat(to_slew);
|
||||||
return model->checkDelay(pinPvt(check_pin, dcalc_ap), from_slew1, to_slew1,
|
return model->checkDelay(pinPvt(check_pin, scene, min_max),
|
||||||
|
from_slew1, to_slew1,
|
||||||
related_out_cap,
|
related_out_cap,
|
||||||
variables_->pocvEnabled());
|
variables_->pocvEnabled());
|
||||||
}
|
}
|
||||||
|
|
@ -183,40 +180,46 @@ DelayCalcBase::reportCheckDelay(const Pin *check_pin,
|
||||||
const char *from_slew_annotation,
|
const char *from_slew_annotation,
|
||||||
const Slew &to_slew,
|
const Slew &to_slew,
|
||||||
float related_out_cap,
|
float related_out_cap,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits)
|
int digits)
|
||||||
{
|
{
|
||||||
CheckTimingModel *model = arc->checkModel(dcalc_ap);
|
CheckTimingModel *model = arc->checkModel(scene, min_max);
|
||||||
if (model) {
|
if (model) {
|
||||||
float from_slew1 = delayAsFloat(from_slew);
|
float from_slew1 = delayAsFloat(from_slew);
|
||||||
float to_slew1 = delayAsFloat(to_slew);
|
float to_slew1 = delayAsFloat(to_slew);
|
||||||
return model->reportCheckDelay(pinPvt(check_pin, dcalc_ap), from_slew1,
|
return model->reportCheckDelay(pinPvt(check_pin, scene, min_max),
|
||||||
from_slew_annotation, to_slew1,
|
from_slew1, from_slew_annotation,
|
||||||
related_out_cap, false, digits);
|
to_slew1, related_out_cap, false,
|
||||||
|
digits);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
const Pvt *
|
const Pvt *
|
||||||
DelayCalcBase::pinPvt(const Pin *pin,
|
DelayCalcBase::pinPvt(const Pin *pin,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
const Instance *drvr_inst = network_->instance(pin);
|
const Instance *drvr_inst = network_->instance(pin);
|
||||||
const Pvt *pvt = sdc_->pvt(drvr_inst, dcalc_ap->constraintMinMax());
|
const Sdc *sdc = scene->sdc();
|
||||||
|
const Pvt *pvt = sdc->pvt(drvr_inst, min_max);
|
||||||
if (pvt == nullptr)
|
if (pvt == nullptr)
|
||||||
pvt = dcalc_ap->operatingConditions();
|
pvt = sdc->operatingConditions(min_max);
|
||||||
return pvt;
|
return pvt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DelayCalcBase::setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
DelayCalcBase::setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
const Pin *drvr_pin = gate.drvrPin();
|
const Pin *drvr_pin = gate.drvrPin();
|
||||||
if (drvr_pin) {
|
if (drvr_pin) {
|
||||||
const Parasitic *parasitic;
|
const Parasitic *parasitic;
|
||||||
float load_cap;
|
float load_cap;
|
||||||
graph_delay_calc_->parasiticLoad(drvr_pin, gate.drvrEdge(), dcalc_ap,
|
graph_delay_calc_->parasiticLoad(drvr_pin, gate.drvrEdge(),
|
||||||
|
scene, min_max,
|
||||||
nullptr, this, load_cap,
|
nullptr, this, load_cap,
|
||||||
parasitic);
|
parasitic);
|
||||||
gate.setLoadCap(load_cap);
|
gate.setLoadCap(load_cap);
|
||||||
|
|
@ -224,17 +227,19 @@ DelayCalcBase::setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
||||||
const Pin *in_pin = gate.inPin();
|
const Pin *in_pin = gate.inPin();
|
||||||
const Vertex *in_vertex = graph_->pinLoadVertex(in_pin);
|
const Vertex *in_vertex = graph_->pinLoadVertex(in_pin);
|
||||||
const Slew &in_slew = graph_delay_calc_->edgeFromSlew(in_vertex, gate.inEdge(),
|
const Slew &in_slew = graph_delay_calc_->edgeFromSlew(in_vertex, gate.inEdge(),
|
||||||
gate.edge(), dcalc_ap);
|
gate.edge(),
|
||||||
|
scene, min_max);
|
||||||
gate.setInSlew(in_slew);
|
gate.setInSlew(in_slew);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DelayCalcBase::setDcalcArgParasiticSlew(ArcDcalcArgSeq &gates,
|
DelayCalcBase::setDcalcArgParasiticSlew(ArcDcalcArgSeq &gates,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
for (ArcDcalcArg &gate : gates)
|
for (ArcDcalcArg &gate : gates)
|
||||||
setDcalcArgParasiticSlew(gate, dcalc_ap);
|
setDcalcArgParasiticSlew(gate, scene, min_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -34,23 +34,26 @@ class GateTableModel;
|
||||||
class DelayCalcBase : public ArcDelayCalc
|
class DelayCalcBase : public ArcDelayCalc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit DelayCalcBase(StaState *sta);
|
DelayCalcBase(StaState *sta);
|
||||||
void finishDrvrPin() override;
|
void finishDrvrPin() override;
|
||||||
|
|
||||||
void reduceParasitic(const Parasitic *parasitic_network,
|
void reduceParasitic(const Parasitic *parasitic_network,
|
||||||
const Net *net,
|
const Net *net,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMaxAll *min_max) override;
|
const MinMaxAll *min_max) override;
|
||||||
void setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
void setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
void setDcalcArgParasiticSlew(ArcDcalcArgSeq &gates,
|
void setDcalcArgParasiticSlew(ArcDcalcArgSeq &gates,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDelay checkDelay(const Pin *check_pin,
|
ArcDelay checkDelay(const Pin *check_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &from_slew,
|
const Slew &from_slew,
|
||||||
const Slew &to_slew,
|
const Slew &to_slew,
|
||||||
float related_out_cap,
|
float related_out_cap,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
|
|
||||||
std::string reportCheckDelay(const Pin *check_pin,
|
std::string reportCheckDelay(const Pin *check_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
|
|
@ -58,7 +61,8 @@ public:
|
||||||
const char *from_slew_annotation,
|
const char *from_slew_annotation,
|
||||||
const Slew &to_slew,
|
const Slew &to_slew,
|
||||||
float related_out_cap,
|
float related_out_cap,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits) override;
|
int digits) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -79,7 +83,8 @@ protected:
|
||||||
ArcDelay &wire_delay,
|
ArcDelay &wire_delay,
|
||||||
Slew &load_slew);
|
Slew &load_slew);
|
||||||
const Pvt *pinPvt(const Pin *pin,
|
const Pvt *pinPvt(const Pin *pin,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const Scene *scene,
|
||||||
|
const MinMax *min_max);
|
||||||
|
|
||||||
using ArcDelayCalc::reduceParasitic;
|
using ArcDelayCalc::reduceParasitic;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "Sdc.hh"
|
#include "Sdc.hh"
|
||||||
#include "Parasitics.hh"
|
#include "Parasitics.hh"
|
||||||
#include "DcalcAnalysisPt.hh"
|
|
||||||
#include "ArcDelayCalc.hh"
|
#include "ArcDelayCalc.hh"
|
||||||
#include "FindRoot.hh"
|
#include "FindRoot.hh"
|
||||||
#include "Variables.hh"
|
#include "Variables.hh"
|
||||||
|
|
@ -1495,20 +1494,22 @@ DmpCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
|
parasitics_ = scene->parasitics(min_max);
|
||||||
const RiseFall *rf = arc->toEdge()->asRiseFall();
|
const RiseFall *rf = arc->toEdge()->asRiseFall();
|
||||||
const LibertyCell *drvr_cell = arc->from()->libertyCell();
|
const LibertyCell *drvr_cell = arc->from()->libertyCell();
|
||||||
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
|
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
|
||||||
|
|
||||||
GateTableModel *table_model = arc->gateTableModel(dcalc_ap);
|
GateTableModel *table_model = arc->gateTableModel(scene, min_max);
|
||||||
if (table_model && parasitic) {
|
if (table_model && parasitic) {
|
||||||
float in_slew1 = delayAsFloat(in_slew);
|
float in_slew1 = delayAsFloat(in_slew);
|
||||||
float c2, rpi, c1;
|
float c2, rpi, c1;
|
||||||
parasitics_->piModel(parasitic, c2, rpi, c1);
|
parasitics_->piModel(parasitic, c2, rpi, c1);
|
||||||
if (isnan(c2) || isnan(c1) || isnan(rpi))
|
if (isnan(c2) || isnan(c1) || isnan(rpi))
|
||||||
report_->error(1040, "parasitic Pi model has NaNs.");
|
report_->error(1040, "parasitic Pi model has NaNs.");
|
||||||
setCeffAlgorithm(drvr_library, drvr_cell, pinPvt(drvr_pin, dcalc_ap),
|
setCeffAlgorithm(drvr_library, drvr_cell, pinPvt(drvr_pin, scene, min_max),
|
||||||
table_model, rf, in_slew1, c2, rpi, c1);
|
table_model, rf, in_slew1, c2, rpi, c1);
|
||||||
double gate_delay, drvr_slew;
|
double gate_delay, drvr_slew;
|
||||||
gateDelaySlew(gate_delay, drvr_slew);
|
gateDelaySlew(gate_delay, drvr_slew);
|
||||||
|
|
@ -1529,7 +1530,7 @@ DmpCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||||
else {
|
else {
|
||||||
ArcDcalcResult dcalc_result =
|
ArcDcalcResult dcalc_result =
|
||||||
LumpedCapDelayCalc::gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic,
|
LumpedCapDelayCalc::gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic,
|
||||||
load_pin_index_map, dcalc_ap);
|
load_pin_index_map, scene, min_max);
|
||||||
if (parasitic
|
if (parasitic
|
||||||
&& !unsuppored_model_warned_) {
|
&& !unsuppored_model_warned_) {
|
||||||
unsuppored_model_warned_ = true;
|
unsuppored_model_warned_ = true;
|
||||||
|
|
@ -1589,12 +1590,13 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits)
|
int digits)
|
||||||
{
|
{
|
||||||
ArcDcalcResult dcalc_result = gateDelay(drvr_pin, arc, in_slew, load_cap,
|
ArcDcalcResult dcalc_result = gateDelay(drvr_pin, arc, in_slew, load_cap,
|
||||||
parasitic, load_pin_index_map, dcalc_ap);
|
parasitic, load_pin_index_map, scene, min_max);
|
||||||
GateTableModel *model = arc->gateTableModel(dcalc_ap);
|
GateTableModel *model = arc->gateTableModel(scene, min_max);
|
||||||
float c_eff = 0.0;
|
float c_eff = 0.0;
|
||||||
string result;
|
string result;
|
||||||
const LibertyCell *drvr_cell = arc->to()->libertyCell();
|
const LibertyCell *drvr_cell = arc->to()->libertyCell();
|
||||||
|
|
@ -1603,9 +1605,11 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
||||||
const Unit *cap_unit = units->capacitanceUnit();
|
const Unit *cap_unit = units->capacitanceUnit();
|
||||||
const Unit *res_unit = units->resistanceUnit();
|
const Unit *res_unit = units->resistanceUnit();
|
||||||
if (parasitic && dmp_alg_) {
|
if (parasitic && dmp_alg_) {
|
||||||
|
Parasitics *parasitics = scene->parasitics(min_max);
|
||||||
|
|
||||||
c_eff = dmp_alg_->ceff();
|
c_eff = dmp_alg_->ceff();
|
||||||
float c2, rpi, c1;
|
float c2, rpi, c1;
|
||||||
parasitics_->piModel(parasitic, c2, rpi, c1);
|
parasitics->piModel(parasitic, c2, rpi, c1);
|
||||||
result += "Pi model C2=";
|
result += "Pi model C2=";
|
||||||
result += cap_unit->asString(c2, digits);
|
result += cap_unit->asString(c2, digits);
|
||||||
result += " Rpi=";
|
result += " Rpi=";
|
||||||
|
|
@ -1621,7 +1625,8 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
||||||
if (model) {
|
if (model) {
|
||||||
const Unit *time_unit = units->timeUnit();
|
const Unit *time_unit = units->timeUnit();
|
||||||
float in_slew1 = delayAsFloat(in_slew);
|
float in_slew1 = delayAsFloat(in_slew);
|
||||||
result += model->reportGateDelay(pinPvt(drvr_pin, dcalc_ap), in_slew1, c_eff,
|
result += model->reportGateDelay(pinPvt(drvr_pin, scene, min_max),
|
||||||
|
in_slew1, c_eff,
|
||||||
variables_->pocvEnabled(), digits);
|
variables_->pocvEnabled(), digits);
|
||||||
result += "Driver waveform slew = ";
|
result += "Driver waveform slew = ";
|
||||||
float drvr_slew = delayAsFloat(dcalc_result.drvrSlew());
|
float drvr_slew = delayAsFloat(dcalc_result.drvrSlew());
|
||||||
|
|
|
||||||
|
|
@ -49,14 +49,16 @@ public:
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
std::string reportGateDelay(const Pin *drvr_pin,
|
std::string reportGateDelay(const Pin *drvr_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &in_slew,
|
const Slew &in_slew,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits) override;
|
int digits) override;
|
||||||
void copyState(const StaState *sta) override;
|
void copyState(const StaState *sta) override;
|
||||||
|
|
||||||
|
|
@ -87,6 +89,7 @@ protected:
|
||||||
double rpi,
|
double rpi,
|
||||||
double c1);
|
double c1);
|
||||||
|
|
||||||
|
const Parasitics *parasitics_;
|
||||||
static bool unsuppored_model_warned_;
|
static bool unsuppored_model_warned_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "Sdc.hh"
|
#include "Sdc.hh"
|
||||||
#include "Parasitics.hh"
|
#include "Parasitics.hh"
|
||||||
#include "DcalcAnalysisPt.hh"
|
|
||||||
#include "GraphDelayCalc.hh"
|
#include "GraphDelayCalc.hh"
|
||||||
#include "DmpCeff.hh"
|
#include "DmpCeff.hh"
|
||||||
|
|
||||||
|
|
@ -50,7 +49,8 @@ public:
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void loadDelaySlew(const Pin *load_pin,
|
void loadDelaySlew(const Pin *load_pin,
|
||||||
|
|
@ -86,8 +86,10 @@ DmpCeffElmoreDelayCalc::inputPortDelay(const Pin *,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
|
Parasitics *parasitics = scene->parasitics(min_max);
|
||||||
ArcDcalcResult dcalc_result(load_pin_index_map.size());
|
ArcDcalcResult dcalc_result(load_pin_index_map.size());
|
||||||
LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
|
LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
|
||||||
for (auto [load_pin, load_idx] : load_pin_index_map) {
|
for (auto [load_pin, load_idx] : load_pin_index_map) {
|
||||||
|
|
@ -96,7 +98,7 @@ DmpCeffElmoreDelayCalc::inputPortDelay(const Pin *,
|
||||||
bool elmore_exists = false;
|
bool elmore_exists = false;
|
||||||
float elmore = 0.0;
|
float elmore = 0.0;
|
||||||
if (parasitic)
|
if (parasitic)
|
||||||
parasitics_->findElmore(parasitic, load_pin, elmore, elmore_exists);
|
parasitics->findElmore(parasitic, load_pin, elmore, elmore_exists);
|
||||||
if (elmore_exists)
|
if (elmore_exists)
|
||||||
// Input port with no external driver.
|
// Input port with no external driver.
|
||||||
dspfWireDelaySlew(load_pin, rf, in_slew, elmore, wire_delay, load_slew);
|
dspfWireDelaySlew(load_pin, rf, in_slew, elmore, wire_delay, load_slew);
|
||||||
|
|
@ -140,20 +142,23 @@ public:
|
||||||
const char *name() const override { return "dmp_ceff_two_pole"; }
|
const char *name() const override { return "dmp_ceff_two_pole"; }
|
||||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||||
float in_slew,
|
float in_slew,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &in_slew,
|
const Slew &in_slew,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadDelaySlew(const Pin *load_pin,
|
void loadDelaySlew(const Pin *load_pin,
|
||||||
|
|
@ -213,42 +218,40 @@ DmpCeffTwoPoleDelayCalc::copy()
|
||||||
Parasitic *
|
Parasitic *
|
||||||
DmpCeffTwoPoleDelayCalc::findParasitic(const Pin *drvr_pin,
|
DmpCeffTwoPoleDelayCalc::findParasitic(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
Parasitic *parasitic = nullptr;
|
Parasitic *parasitic = nullptr;
|
||||||
const Corner *corner = dcalc_ap->corner();
|
const Sdc *sdc = scene->sdc();
|
||||||
|
Parasitics *parasitics = scene->parasitics(min_max);
|
||||||
|
if (parasitics == nullptr
|
||||||
// set_load net has precedence over parasitics.
|
// set_load net has precedence over parasitics.
|
||||||
if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|
|
||||||
|| network_->direction(drvr_pin)->isInternal())
|
|| network_->direction(drvr_pin)->isInternal())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
|
||||||
// Prefer PiPoleResidue.
|
// Prefer PiPoleResidue.
|
||||||
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap);
|
parasitic = parasitics->findPiPoleResidue(drvr_pin, rf, min_max);
|
||||||
if (parasitic)
|
if (parasitic)
|
||||||
return parasitic;
|
return parasitic;
|
||||||
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
|
parasitic = parasitics->findPiElmore(drvr_pin, rf, min_max);
|
||||||
if (parasitic)
|
if (parasitic)
|
||||||
return parasitic;
|
return parasitic;
|
||||||
Parasitic *parasitic_network =
|
Parasitic *parasitic_network =
|
||||||
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
|
parasitics->findParasiticNetwork(drvr_pin);
|
||||||
if (parasitic_network) {
|
if (parasitic_network) {
|
||||||
parasitic = parasitics_->reduceToPiPoleResidue2(parasitic_network, drvr_pin, rf,
|
parasitic = parasitics->reduceToPiPoleResidue2(parasitic_network, drvr_pin, rf,
|
||||||
corner,
|
scene, min_max);
|
||||||
dcalc_ap->constraintMinMax(),
|
|
||||||
parasitic_ap);
|
|
||||||
if (parasitic)
|
if (parasitic)
|
||||||
return parasitic;
|
return parasitic;
|
||||||
}
|
}
|
||||||
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
|
Wireload *wireload = sdc->wireload(min_max);
|
||||||
Wireload *wireload = sdc_->wireload(cnst_min_max);
|
|
||||||
if (wireload) {
|
if (wireload) {
|
||||||
float pin_cap, wire_cap, fanout;
|
float pin_cap, wire_cap, fanout;
|
||||||
bool has_wire_cap;
|
bool has_wire_cap;
|
||||||
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap, pin_cap, wire_cap,
|
graph_delay_calc_->netCaps(drvr_pin, rf, scene, min_max, pin_cap, wire_cap,
|
||||||
fanout, has_wire_cap);
|
fanout, has_wire_cap);
|
||||||
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload,
|
parasitic = parasitics->estimatePiElmore(drvr_pin, rf, wireload,
|
||||||
fanout, pin_cap, corner,
|
fanout, pin_cap,
|
||||||
cnst_min_max);
|
scene, min_max);
|
||||||
}
|
}
|
||||||
return parasitic;
|
return parasitic;
|
||||||
}
|
}
|
||||||
|
|
@ -259,21 +262,23 @@ DmpCeffTwoPoleDelayCalc::inputPortDelay(const Pin *,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
|
const Parasitics *parasitics = scene->parasitics(min_max);
|
||||||
ArcDcalcResult dcalc_result(load_pin_index_map.size());
|
ArcDcalcResult dcalc_result(load_pin_index_map.size());
|
||||||
ArcDelay wire_delay = 0.0;
|
ArcDelay wire_delay = 0.0;
|
||||||
Slew load_slew = in_slew;
|
Slew load_slew = in_slew;
|
||||||
LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
|
LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
|
||||||
for (const auto [load_pin, load_idx] : load_pin_index_map) {
|
for (const auto [load_pin, load_idx] : load_pin_index_map) {
|
||||||
if (parasitics_->isPiPoleResidue(parasitic)) {
|
if (parasitics->isPiPoleResidue(parasitic)) {
|
||||||
const Parasitic *pole_residue = parasitics_->findPoleResidue(parasitic, load_pin);
|
const Parasitic *pole_residue = parasitics->findPoleResidue(parasitic, load_pin);
|
||||||
if (pole_residue) {
|
if (pole_residue) {
|
||||||
size_t pole_count = parasitics_->poleResidueCount(pole_residue);
|
size_t pole_count = parasitics->poleResidueCount(pole_residue);
|
||||||
if (pole_count >= 1) {
|
if (pole_count >= 1) {
|
||||||
ComplexFloat pole1, residue1;
|
ComplexFloat pole1, residue1;
|
||||||
// Find the 1st (elmore) pole.
|
// Find the 1st (elmore) pole.
|
||||||
parasitics_->poleResidue(pole_residue, 0, pole1, residue1);
|
parasitics->poleResidue(pole_residue, 0, pole1, residue1);
|
||||||
if (pole1.imag() == 0.0
|
if (pole1.imag() == 0.0
|
||||||
&& residue1.imag() == 0.0) {
|
&& residue1.imag() == 0.0) {
|
||||||
float p1 = pole1.real();
|
float p1 = pole1.real();
|
||||||
|
|
@ -297,8 +302,10 @@ DmpCeffTwoPoleDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
|
parasitics_ = scene->parasitics(min_max);
|
||||||
const LibertyLibrary *drvr_library = arc->to()->libertyLibrary();
|
const LibertyLibrary *drvr_library = arc->to()->libertyLibrary();
|
||||||
const RiseFall *rf = arc->toEdge()->asRiseFall();
|
const RiseFall *rf = arc->toEdge()->asRiseFall();
|
||||||
vth_ = drvr_library->outputThreshold(rf);
|
vth_ = drvr_library->outputThreshold(rf);
|
||||||
|
|
@ -306,7 +313,7 @@ DmpCeffTwoPoleDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||||
vh_ = drvr_library->slewUpperThreshold(rf);
|
vh_ = drvr_library->slewUpperThreshold(rf);
|
||||||
slew_derate_ = drvr_library->slewDerateFromLibrary();
|
slew_derate_ = drvr_library->slewDerateFromLibrary();
|
||||||
return DmpCeffDelayCalc::gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic,
|
return DmpCeffDelayCalc::gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic,
|
||||||
load_pin_index_map, dcalc_ap) ;
|
load_pin_index_map, scene, min_max) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,10 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef const std::function<void (double x,
|
using FindRootFunc = const std::function<void (double x,
|
||||||
// Return values.
|
// Return values.
|
||||||
double &y,
|
double &y,
|
||||||
double &dy)> FindRootFunc;
|
double &dy)>;
|
||||||
|
|
||||||
double
|
double
|
||||||
findRoot(FindRootFunc func,
|
findRoot(FindRootFunc func,
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -35,7 +35,6 @@
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "Sdc.hh"
|
#include "Sdc.hh"
|
||||||
#include "Parasitics.hh"
|
#include "Parasitics.hh"
|
||||||
#include "DcalcAnalysisPt.hh"
|
|
||||||
#include "GraphDelayCalc.hh"
|
#include "GraphDelayCalc.hh"
|
||||||
#include "Variables.hh"
|
#include "Variables.hh"
|
||||||
|
|
||||||
|
|
@ -64,35 +63,37 @@ LumpedCapDelayCalc::copy()
|
||||||
Parasitic *
|
Parasitic *
|
||||||
LumpedCapDelayCalc::findParasitic(const Pin *drvr_pin,
|
LumpedCapDelayCalc::findParasitic(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
Parasitic *parasitic = nullptr;
|
Parasitic *parasitic = nullptr;
|
||||||
const Corner *corner = dcalc_ap->corner();
|
Parasitics *parasitics = scene->parasitics(min_max);
|
||||||
|
const Sdc *sdc = scene->sdc();
|
||||||
|
if (parasitics == nullptr
|
||||||
// set_load net has precedence over parasitics.
|
// set_load net has precedence over parasitics.
|
||||||
if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|
|| sdc->drvrPinHasWireCap(drvr_pin)
|
||||||
|| network_->direction(drvr_pin)->isInternal())
|
|| network_->direction(drvr_pin)->isInternal())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
|
||||||
// Prefer PiElmore.
|
// Prefer PiElmore.
|
||||||
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
|
parasitic = parasitics->findPiElmore(drvr_pin, rf, min_max);
|
||||||
if (parasitic)
|
if (parasitic)
|
||||||
return parasitic;
|
return parasitic;
|
||||||
Parasitic *parasitic_network = parasitics_->findParasiticNetwork(drvr_pin,
|
Parasitic *parasitic_network = parasitics->findParasiticNetwork(drvr_pin);
|
||||||
parasitic_ap);
|
|
||||||
if (parasitic_network) {
|
if (parasitic_network) {
|
||||||
parasitic = reduceParasitic(parasitic_network, drvr_pin, rf, dcalc_ap);
|
parasitic = reduceParasitic(parasitic_network, drvr_pin, rf, scene, min_max);
|
||||||
if (parasitic)
|
if (parasitic)
|
||||||
return parasitic;
|
return parasitic;
|
||||||
}
|
}
|
||||||
const MinMax *min_max = dcalc_ap->constraintMinMax();
|
|
||||||
Wireload *wireload = sdc_->wireload(min_max);
|
Wireload *wireload = sdc->wireload(min_max);
|
||||||
if (wireload) {
|
if (wireload) {
|
||||||
float pin_cap, wire_cap, fanout;
|
float pin_cap, wire_cap, fanout;
|
||||||
bool has_net_load;
|
bool has_net_load;
|
||||||
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap,
|
graph_delay_calc_->netCaps(drvr_pin, rf, scene, min_max,
|
||||||
pin_cap, wire_cap, fanout, has_net_load);
|
pin_cap, wire_cap, fanout, has_net_load);
|
||||||
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload, fanout,
|
parasitic = parasitics->estimatePiElmore(drvr_pin, rf, wireload, fanout,
|
||||||
pin_cap, corner, min_max);
|
pin_cap, scene, min_max);
|
||||||
}
|
}
|
||||||
return parasitic;
|
return parasitic;
|
||||||
}
|
}
|
||||||
|
|
@ -101,14 +102,13 @@ Parasitic *
|
||||||
LumpedCapDelayCalc::reduceParasitic(const Parasitic *parasitic_network,
|
LumpedCapDelayCalc::reduceParasitic(const Parasitic *parasitic_network,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
|
|
||||||
{
|
{
|
||||||
const Corner *corner = dcalc_ap->corner();
|
Parasitics *parasitics = scene->parasitics(min_max);
|
||||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
return parasitics->reduceToPiElmore(parasitic_network, drvr_pin, rf,
|
||||||
return parasitics_->reduceToPiElmore(parasitic_network, drvr_pin, rf,
|
scene, min_max);
|
||||||
corner, dcalc_ap->constraintMinMax(),
|
|
||||||
parasitic_ap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArcDcalcResult
|
ArcDcalcResult
|
||||||
|
|
@ -117,7 +117,8 @@ LumpedCapDelayCalc::inputPortDelay(const Pin *,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Parasitic *,
|
const Parasitic *,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *,
|
||||||
|
const MinMax *)
|
||||||
{
|
{
|
||||||
const LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
|
const LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
|
||||||
return makeResult(drvr_library,rf, 0.0, in_slew, load_pin_index_map);
|
return makeResult(drvr_library,rf, 0.0, in_slew, load_pin_index_map);
|
||||||
|
|
@ -130,9 +131,10 @@ LumpedCapDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *,
|
const Parasitic *,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
GateTimingModel *model = arc->gateModel(dcalc_ap);
|
GateTimingModel *model = arc->gateModel(scene, min_max);
|
||||||
debugPrint(debug_, "delay_calc", 3,
|
debugPrint(debug_, "delay_calc", 3,
|
||||||
" in_slew = %s load_cap = %s lumped",
|
" in_slew = %s load_cap = %s lumped",
|
||||||
delayAsString(in_slew, this),
|
delayAsString(in_slew, this),
|
||||||
|
|
@ -146,7 +148,7 @@ LumpedCapDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||||
// NaNs cause seg faults during table lookup.
|
// NaNs cause seg faults during table lookup.
|
||||||
if (isnan(load_cap) || isnan(delayAsFloat(in_slew)))
|
if (isnan(load_cap) || isnan(delayAsFloat(in_slew)))
|
||||||
report_->error(1350, "gate delay input variable is NaN");
|
report_->error(1350, "gate delay input variable is NaN");
|
||||||
model->gateDelay(pinPvt(drvr_pin, dcalc_ap), in_slew1, load_cap,
|
model->gateDelay(pinPvt(drvr_pin, scene, min_max), in_slew1, load_cap,
|
||||||
variables_->pocvEnabled(),
|
variables_->pocvEnabled(),
|
||||||
gate_delay, drvr_slew);
|
gate_delay, drvr_slew);
|
||||||
return makeResult(drvr_library, rf, gate_delay, drvr_slew, load_pin_index_map);
|
return makeResult(drvr_library, rf, gate_delay, drvr_slew, load_pin_index_map);
|
||||||
|
|
@ -182,14 +184,15 @@ LumpedCapDelayCalc::reportGateDelay(const Pin *check_pin,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *,
|
const Parasitic *,
|
||||||
const LoadPinIndexMap &,
|
const LoadPinIndexMap &,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits)
|
int digits)
|
||||||
{
|
{
|
||||||
GateTimingModel *model = arc->gateModel(dcalc_ap);
|
GateTimingModel *model = arc->gateModel(scene, min_max);
|
||||||
if (model) {
|
if (model) {
|
||||||
float in_slew1 = delayAsFloat(in_slew);
|
float in_slew1 = delayAsFloat(in_slew);
|
||||||
return model->reportGateDelay(pinPvt(check_pin, dcalc_ap), in_slew1, load_cap,
|
return model->reportGateDelay(pinPvt(check_pin, scene, min_max),
|
||||||
false, digits);
|
in_slew1, load_cap, false, digits);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,32 +38,37 @@ public:
|
||||||
const char *name() const override { return "lumped_cap"; }
|
const char *name() const override { return "lumped_cap"; }
|
||||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
bool reduceSupported() const override { return true; }
|
bool reduceSupported() const override { return true; }
|
||||||
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||||
float in_slew,
|
float in_slew,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &in_slew,
|
const Slew &in_slew,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
std::string reportGateDelay(const Pin *drvr_pin,
|
std::string reportGateDelay(const Pin *drvr_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &in_slew,
|
const Slew &in_slew,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits) override;
|
int digits) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
#include "ParallelDelayCalc.hh"
|
#include "ParallelDelayCalc.hh"
|
||||||
|
|
||||||
#include "TimingArc.hh"
|
#include "TimingArc.hh"
|
||||||
#include "Corner.hh"
|
#include "Scene.hh"
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "Graph.hh"
|
#include "Graph.hh"
|
||||||
#include "Sdc.hh"
|
#include "Sdc.hh"
|
||||||
|
|
@ -44,25 +44,28 @@ ParallelDelayCalc::ParallelDelayCalc(StaState *sta):
|
||||||
ArcDcalcResultSeq
|
ArcDcalcResultSeq
|
||||||
ParallelDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
ParallelDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
if (dcalc_args.size() == 1) {
|
if (dcalc_args.size() == 1) {
|
||||||
ArcDcalcArg &dcalc_arg = dcalc_args[0];
|
ArcDcalcArg &dcalc_arg = dcalc_args[0];
|
||||||
ArcDcalcResult dcalc_result = gateDelay(dcalc_arg.drvrPin(), dcalc_arg.arc(),
|
ArcDcalcResult dcalc_result = gateDelay(dcalc_arg.drvrPin(), dcalc_arg.arc(),
|
||||||
dcalc_arg.inSlew(), dcalc_arg.loadCap(),
|
dcalc_arg.inSlew(), dcalc_arg.loadCap(),
|
||||||
dcalc_arg.parasitic(),
|
dcalc_arg.parasitic(),
|
||||||
load_pin_index_map, dcalc_ap);
|
load_pin_index_map,
|
||||||
|
scene, min_max);
|
||||||
ArcDcalcResultSeq dcalc_results;
|
ArcDcalcResultSeq dcalc_results;
|
||||||
dcalc_results.push_back(dcalc_result);
|
dcalc_results.push_back(dcalc_result);
|
||||||
return dcalc_results;
|
return dcalc_results;
|
||||||
}
|
}
|
||||||
return gateDelaysParallel(dcalc_args, load_pin_index_map, dcalc_ap);
|
return gateDelaysParallel(dcalc_args, load_pin_index_map, scene, min_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArcDcalcResultSeq
|
ArcDcalcResultSeq
|
||||||
ParallelDelayCalc::gateDelaysParallel(ArcDcalcArgSeq &dcalc_args,
|
ParallelDelayCalc::gateDelaysParallel(ArcDcalcArgSeq &dcalc_args,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
size_t drvr_count = dcalc_args.size();
|
size_t drvr_count = dcalc_args.size();
|
||||||
ArcDcalcResultSeq dcalc_results(drvr_count);
|
ArcDcalcResultSeq dcalc_results(drvr_count);
|
||||||
|
|
@ -75,16 +78,16 @@ ParallelDelayCalc::gateDelaysParallel(ArcDcalcArgSeq &dcalc_args,
|
||||||
ArcDcalcResult &dcalc_result = dcalc_results[drvr_idx];
|
ArcDcalcResult &dcalc_result = dcalc_results[drvr_idx];
|
||||||
const Pin *drvr_pin = dcalc_arg.drvrPin();
|
const Pin *drvr_pin = dcalc_arg.drvrPin();
|
||||||
const TimingArc *arc = dcalc_arg.arc();
|
const TimingArc *arc = dcalc_arg.arc();
|
||||||
Slew in_slew = dcalc_arg.inSlew();
|
const Slew &in_slew = dcalc_arg.inSlew();
|
||||||
|
|
||||||
ArcDcalcResult intrinsic_result = gateDelay(drvr_pin, arc, in_slew, 0.0, nullptr,
|
ArcDcalcResult intrinsic_result = gateDelay(drvr_pin, arc, in_slew, 0.0, nullptr,
|
||||||
load_pin_index_map, dcalc_ap);
|
load_pin_index_map, scene, min_max);
|
||||||
ArcDelay intrinsic_delay = intrinsic_result.gateDelay();
|
ArcDelay intrinsic_delay = intrinsic_result.gateDelay();
|
||||||
intrinsic_delays[drvr_idx] = intrinsic_result.gateDelay();
|
intrinsic_delays[drvr_idx] = intrinsic_result.gateDelay();
|
||||||
|
|
||||||
ArcDcalcResult gate_result = gateDelay(drvr_pin, arc, in_slew, dcalc_arg.loadCap(),
|
ArcDcalcResult gate_result = gateDelay(drvr_pin, arc, in_slew, dcalc_arg.loadCap(),
|
||||||
dcalc_arg.parasitic(),
|
dcalc_arg.parasitic(),
|
||||||
load_pin_index_map, dcalc_ap);
|
load_pin_index_map, scene, min_max);
|
||||||
ArcDelay gate_delay = gate_result.gateDelay();
|
ArcDelay gate_delay = gate_result.gateDelay();
|
||||||
Slew drvr_slew = gate_result.drvrSlew();
|
Slew drvr_slew = gate_result.drvrSlew();
|
||||||
ArcDelay load_delay = gate_delay - intrinsic_delay;
|
ArcDelay load_delay = gate_delay - intrinsic_delay;
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,13 @@ public:
|
||||||
ParallelDelayCalc(StaState *sta);
|
ParallelDelayCalc(StaState *sta);
|
||||||
ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &dcalc_args,
|
ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &dcalc_args,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
protected:
|
protected:
|
||||||
ArcDcalcResultSeq gateDelaysParallel(ArcDcalcArgSeq &dcalc_args,
|
ArcDcalcResultSeq gateDelaysParallel(ArcDcalcArgSeq &dcalc_args,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const Scene *scene,
|
||||||
|
const MinMax *min_max);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,7 @@
|
||||||
#include "PortDirection.hh"
|
#include "PortDirection.hh"
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "Sdc.hh"
|
#include "Sdc.hh"
|
||||||
#include "DcalcAnalysisPt.hh"
|
#include "Scene.hh"
|
||||||
#include "Corner.hh"
|
|
||||||
#include "Graph.hh"
|
#include "Graph.hh"
|
||||||
#include "Parasitics.hh"
|
#include "Parasitics.hh"
|
||||||
#include "GraphDelayCalc.hh"
|
#include "GraphDelayCalc.hh"
|
||||||
|
|
@ -64,9 +63,12 @@ makePrimaDelayCalc(StaState *sta)
|
||||||
PrimaDelayCalc::PrimaDelayCalc(StaState *sta) :
|
PrimaDelayCalc::PrimaDelayCalc(StaState *sta) :
|
||||||
DelayCalcBase(sta),
|
DelayCalcBase(sta),
|
||||||
dcalc_args_(nullptr),
|
dcalc_args_(nullptr),
|
||||||
|
scene_(nullptr),
|
||||||
|
min_max_(nullptr),
|
||||||
|
parasitics_(nullptr),
|
||||||
|
parasitic_network_(nullptr),
|
||||||
load_pin_index_map_(nullptr),
|
load_pin_index_map_(nullptr),
|
||||||
pin_node_map_(network_),
|
pin_node_map_(network_),
|
||||||
node_index_map_(ParasiticNodeLess(parasitics_, network_)),
|
|
||||||
prima_order_(3),
|
prima_order_(3),
|
||||||
make_waveforms_(false),
|
make_waveforms_(false),
|
||||||
waveform_drvr_pin_(nullptr),
|
waveform_drvr_pin_(nullptr),
|
||||||
|
|
@ -81,7 +83,7 @@ PrimaDelayCalc::PrimaDelayCalc(const PrimaDelayCalc &dcalc) :
|
||||||
dcalc_args_(nullptr),
|
dcalc_args_(nullptr),
|
||||||
load_pin_index_map_(nullptr),
|
load_pin_index_map_(nullptr),
|
||||||
pin_node_map_(network_),
|
pin_node_map_(network_),
|
||||||
node_index_map_(ParasiticNodeLess(parasitics_, network_)),
|
node_index_map_(dcalc.node_index_map_),
|
||||||
prima_order_(dcalc.prima_order_),
|
prima_order_(dcalc.prima_order_),
|
||||||
make_waveforms_(false),
|
make_waveforms_(false),
|
||||||
waveform_drvr_pin_(nullptr),
|
waveform_drvr_pin_(nullptr),
|
||||||
|
|
@ -113,27 +115,26 @@ PrimaDelayCalc::copyState(const StaState *sta)
|
||||||
Parasitic *
|
Parasitic *
|
||||||
PrimaDelayCalc::findParasitic(const Pin *drvr_pin,
|
PrimaDelayCalc::findParasitic(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
const Corner *corner = dcalc_ap->corner();
|
const Sdc *sdc = scene->sdc();
|
||||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
Parasitics *parasitics = scene->parasitics(min_max);
|
||||||
// set_load net has precidence over parasitics.
|
if (parasitics == nullptr
|
||||||
if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|
// set_load net has precedence over parasitics.
|
||||||
|| network_->direction(drvr_pin)->isInternal())
|
|| network_->direction(drvr_pin)->isInternal())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
Parasitic *parasitic = parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
|
Parasitic *parasitic = parasitics->findParasiticNetwork(drvr_pin);
|
||||||
if (parasitic)
|
if (parasitic)
|
||||||
return parasitic;
|
return parasitic;
|
||||||
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
|
Wireload *wireload = sdc->wireload(min_max);
|
||||||
Wireload *wireload = sdc_->wireload(cnst_min_max);
|
|
||||||
if (wireload) {
|
if (wireload) {
|
||||||
float pin_cap, wire_cap, fanout;
|
float pin_cap, wire_cap, fanout;
|
||||||
bool has_wire_cap;
|
bool has_wire_cap;
|
||||||
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap, pin_cap, wire_cap,
|
graph_delay_calc_->netCaps(drvr_pin, rf, scene, min_max, pin_cap, wire_cap,
|
||||||
fanout, has_wire_cap);
|
fanout, has_wire_cap);
|
||||||
parasitic = parasitics_->makeWireloadNetwork(drvr_pin, wireload,
|
parasitic = parasitics->makeWireloadNetwork(drvr_pin, wireload,
|
||||||
fanout, cnst_min_max,
|
fanout, scene, min_max);
|
||||||
parasitic_ap);
|
|
||||||
}
|
}
|
||||||
return parasitic;
|
return parasitic;
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +143,8 @@ Parasitic *
|
||||||
PrimaDelayCalc::reduceParasitic(const Parasitic *,
|
PrimaDelayCalc::reduceParasitic(const Parasitic *,
|
||||||
const Pin *,
|
const Pin *,
|
||||||
const RiseFall *,
|
const RiseFall *,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *,
|
||||||
|
const MinMax *)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -153,18 +155,16 @@ PrimaDelayCalc::inputPortDelay(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
|
Parasitics *parasitics = scene->parasitics(min_max);
|
||||||
ArcDcalcResult dcalc_result(load_pin_index_map.size());
|
ArcDcalcResult dcalc_result(load_pin_index_map.size());
|
||||||
LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
|
LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
|
||||||
|
|
||||||
const Parasitic *pi_elmore = nullptr;
|
const Parasitic *pi_elmore = nullptr;
|
||||||
if (parasitic && parasitics_->isParasiticNetwork(parasitic)) {
|
if (parasitic && parasitics->isParasiticNetwork(parasitic))
|
||||||
const ParasiticAnalysisPt *ap = dcalc_ap->parasiticAnalysisPt();
|
pi_elmore = parasitics->reduceToPiElmore(parasitic, drvr_pin, rf,
|
||||||
pi_elmore = parasitics_->reduceToPiElmore(parasitic, drvr_pin, rf,
|
scene, min_max);
|
||||||
dcalc_ap->corner(),
|
|
||||||
dcalc_ap->constraintMinMax(), ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto load_pin_index : load_pin_index_map) {
|
for (auto load_pin_index : load_pin_index_map) {
|
||||||
const Pin *load_pin = load_pin_index.first;
|
const Pin *load_pin = load_pin_index.first;
|
||||||
|
|
@ -174,7 +174,7 @@ PrimaDelayCalc::inputPortDelay(const Pin *drvr_pin,
|
||||||
bool elmore_exists = false;
|
bool elmore_exists = false;
|
||||||
float elmore = 0.0;
|
float elmore = 0.0;
|
||||||
if (pi_elmore)
|
if (pi_elmore)
|
||||||
parasitics_->findElmore(pi_elmore, load_pin, elmore, elmore_exists);
|
parasitics->findElmore(pi_elmore, load_pin, elmore, elmore_exists);
|
||||||
if (elmore_exists)
|
if (elmore_exists)
|
||||||
// Input port with no external driver.
|
// Input port with no external driver.
|
||||||
dspfWireDelaySlew(load_pin, rf, in_slew, elmore, wire_delay, load_slew);
|
dspfWireDelaySlew(load_pin, rf, in_slew, elmore, wire_delay, load_slew);
|
||||||
|
|
@ -192,33 +192,37 @@ PrimaDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
ArcDcalcArgSeq dcalc_args;
|
ArcDcalcArgSeq dcalc_args;
|
||||||
dcalc_args.emplace_back(nullptr, drvr_pin, nullptr, arc, in_slew, load_cap, parasitic);
|
dcalc_args.emplace_back(nullptr, drvr_pin, nullptr, arc, in_slew, load_cap, parasitic);
|
||||||
ArcDcalcResultSeq dcalc_results = gateDelays(dcalc_args, load_pin_index_map, dcalc_ap);
|
ArcDcalcResultSeq dcalc_results = gateDelays(dcalc_args, load_pin_index_map, scene, min_max);
|
||||||
return dcalc_results[0];
|
return dcalc_results[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
ArcDcalcResultSeq
|
ArcDcalcResultSeq
|
||||||
PrimaDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
PrimaDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap)
|
const Scene *scene,
|
||||||
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
dcalc_args_ = &dcalc_args;
|
dcalc_args_ = &dcalc_args;
|
||||||
load_pin_index_map_ = &load_pin_index_map;
|
load_pin_index_map_ = &load_pin_index_map;
|
||||||
drvr_count_ = dcalc_args.size();
|
drvr_count_ = dcalc_args.size();
|
||||||
dcalc_ap_ = dcalc_ap;
|
scene_ = scene;
|
||||||
|
min_max_ = min_max;
|
||||||
drvr_rf_ = dcalc_args[0].arc()->toEdge()->asRiseFall();
|
drvr_rf_ = dcalc_args[0].arc()->toEdge()->asRiseFall();
|
||||||
parasitic_network_ = dcalc_args[0].parasitic();
|
parasitic_network_ = dcalc_args[0].parasitic();
|
||||||
load_cap_ = dcalc_args[0].loadCap();
|
load_cap_ = dcalc_args[0].loadCap();
|
||||||
|
parasitics_ = scene->parasitics(min_max);
|
||||||
|
node_index_map_ = NodeIndexMap(ParasiticNodeLess(parasitics_, network_));
|
||||||
|
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
output_waveforms_.resize(drvr_count_);
|
output_waveforms_.resize(drvr_count_);
|
||||||
const DcalcAnalysisPtSeq &dcalc_aps = corners_->dcalcAnalysisPts();
|
|
||||||
for (size_t drvr_idx = 0; drvr_idx < drvr_count_; drvr_idx++) {
|
for (size_t drvr_idx = 0; drvr_idx < drvr_count_; drvr_idx++) {
|
||||||
ArcDcalcArg &dcalc_arg = dcalc_args[drvr_idx];
|
ArcDcalcArg &dcalc_arg = dcalc_args[drvr_idx];
|
||||||
GateTableModel *table_model = dcalc_arg.arc()->gateTableModel(dcalc_ap);
|
GateTableModel *table_model = dcalc_arg.arc()->gateTableModel(scene, min_max);
|
||||||
if (table_model && dcalc_arg.parasitic()) {
|
if (table_model && dcalc_arg.parasitic()) {
|
||||||
OutputWaveforms *output_waveforms = table_model->outputWaveforms();
|
OutputWaveforms *output_waveforms = table_model->outputWaveforms();
|
||||||
float in_slew = dcalc_arg.inSlewFlt();
|
float in_slew = dcalc_arg.inSlewFlt();
|
||||||
|
|
@ -236,7 +240,7 @@ PrimaDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
||||||
drvr_library->supplyVoltage("VDD", vdd_, vdd_exists);
|
drvr_library->supplyVoltage("VDD", vdd_, vdd_exists);
|
||||||
if (!vdd_exists)
|
if (!vdd_exists)
|
||||||
report_->error(1720, "VDD not defined in library %s", drvr_library->name());
|
report_->error(1720, "VDD not defined in library %s", drvr_library->name());
|
||||||
drvr_cell->ensureVoltageWaveforms(dcalc_aps);
|
drvr_cell->ensureVoltageWaveforms(scenes_);
|
||||||
if (drvr_idx == 0) {
|
if (drvr_idx == 0) {
|
||||||
vth_ = drvr_library->outputThreshold(drvr_rf_) * vdd_;
|
vth_ = drvr_library->outputThreshold(drvr_rf_) * vdd_;
|
||||||
vl_ = drvr_library->slewLowerThreshold(drvr_rf_) * vdd_;
|
vl_ = drvr_library->slewLowerThreshold(drvr_rf_) * vdd_;
|
||||||
|
|
@ -266,11 +270,13 @@ PrimaDelayCalc::tableDcalcResults()
|
||||||
const Pin *drvr_pin = dcalc_arg.drvrPin();
|
const Pin *drvr_pin = dcalc_arg.drvrPin();
|
||||||
if (drvr_pin) {
|
if (drvr_pin) {
|
||||||
const RiseFall *rf = dcalc_arg.drvrEdge();
|
const RiseFall *rf = dcalc_arg.drvrEdge();
|
||||||
const Parasitic *parasitic = table_dcalc_->findParasitic(drvr_pin, rf, dcalc_ap_);
|
const Parasitic *parasitic = table_dcalc_->findParasitic(drvr_pin, rf,
|
||||||
|
scene_, min_max_);
|
||||||
dcalc_arg.setParasitic(parasitic);
|
dcalc_arg.setParasitic(parasitic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return table_dcalc_->gateDelays(*dcalc_args_, *load_pin_index_map_, dcalc_ap_);
|
return table_dcalc_->gateDelays(*dcalc_args_, *load_pin_index_map_,
|
||||||
|
scene_, min_max_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -388,8 +394,7 @@ PrimaDelayCalc::driverResistance()
|
||||||
{
|
{
|
||||||
const Pin *drvr_pin = (*dcalc_args_)[0].drvrPin();
|
const Pin *drvr_pin = (*dcalc_args_)[0].drvrPin();
|
||||||
LibertyPort *drvr_port = network_->libertyPort(drvr_pin);
|
LibertyPort *drvr_port = network_->libertyPort(drvr_pin);
|
||||||
const MinMax *min_max = dcalc_ap_->delayMinMax();
|
return drvr_port->driveResistance(drvr_rf_, min_max_);
|
||||||
return drvr_port->driveResistance(drvr_rf_, min_max);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -458,17 +463,16 @@ PrimaDelayCalc::pinCapacitance(ParasiticNode *node)
|
||||||
{
|
{
|
||||||
const Pin *pin = parasitics_->pin(node);
|
const Pin *pin = parasitics_->pin(node);
|
||||||
float pin_cap = 0.0;
|
float pin_cap = 0.0;
|
||||||
|
const Sdc *sdc = scene_->sdc();
|
||||||
if (pin) {
|
if (pin) {
|
||||||
Port *port = network_->port(pin);
|
Port *port = network_->port(pin);
|
||||||
LibertyPort *lib_port = network_->libertyPort(port);
|
LibertyPort *lib_port = network_->libertyPort(port);
|
||||||
const Corner *corner = dcalc_ap_->corner();
|
|
||||||
const MinMax *cnst_min_max = dcalc_ap_->constraintMinMax();
|
|
||||||
if (lib_port) {
|
if (lib_port) {
|
||||||
if (!includes_pin_caps_)
|
if (!includes_pin_caps_)
|
||||||
pin_cap = sdc_->pinCapacitance(pin, drvr_rf_, corner, cnst_min_max);
|
pin_cap = sdc->pinCapacitance(pin, drvr_rf_, scene_, min_max_);
|
||||||
}
|
}
|
||||||
else if (network_->isTopLevelPort(pin))
|
else if (network_->isTopLevelPort(pin))
|
||||||
pin_cap = sdc_->portExtCap(port, drvr_rf_, corner, cnst_min_max);
|
pin_cap = sdc->portExtCap(port, drvr_rf_, min_max_);
|
||||||
}
|
}
|
||||||
return pin_cap;
|
return pin_cap;
|
||||||
}
|
}
|
||||||
|
|
@ -910,14 +914,15 @@ PrimaDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *,
|
const Parasitic *,
|
||||||
const LoadPinIndexMap &,
|
const LoadPinIndexMap &,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits)
|
int digits)
|
||||||
{
|
{
|
||||||
GateTimingModel *model = arc->gateModel(dcalc_ap);
|
GateTimingModel *model = arc->gateModel(scene, min_max);
|
||||||
if (model) {
|
if (model) {
|
||||||
float in_slew1 = delayAsFloat(in_slew);
|
float in_slew1 = delayAsFloat(in_slew);
|
||||||
return model->reportGateDelay(pinPvt(drvr_pin, dcalc_ap), in_slew1, load_cap,
|
return model->reportGateDelay(pinPvt(drvr_pin, scene, min_max),
|
||||||
false, digits);
|
in_slew1, load_cap, false, digits);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
#include <Eigen/SparseCore>
|
#include <Eigen/SparseCore>
|
||||||
#include <Eigen/SparseLU>
|
#include <Eigen/SparseLU>
|
||||||
|
|
||||||
#include "Map.hh"
|
|
||||||
#include "LumpedCapDelayCalc.hh"
|
#include "LumpedCapDelayCalc.hh"
|
||||||
#include "ArcDcalcWaveforms.hh"
|
#include "ArcDcalcWaveforms.hh"
|
||||||
#include "Parasitics.hh"
|
#include "Parasitics.hh"
|
||||||
|
|
@ -38,16 +37,16 @@ namespace sta {
|
||||||
|
|
||||||
class ArcDelayCalc;
|
class ArcDelayCalc;
|
||||||
class StaState;
|
class StaState;
|
||||||
class Corner;
|
class Scene;
|
||||||
|
|
||||||
typedef Map<const Pin*, size_t, PinIdLess> PinNodeMap;
|
using PinNodeMap = std::map<const Pin*, size_t, PinIdLess>;
|
||||||
typedef std::map<const ParasiticNode*, size_t, ParasiticNodeLess> NodeIndexMap;
|
using NodeIndexMap = std::map<const ParasiticNode*, size_t, ParasiticNodeLess>;
|
||||||
typedef Map<const Pin*, size_t> PortIndexMap;
|
using PortIndexMap = std::map<const Pin*, size_t>;
|
||||||
typedef Eigen::SparseMatrix<double> MatrixSd;
|
using MatrixSd = Eigen::SparseMatrix<double>;
|
||||||
typedef Map<const Pin*, Eigen::VectorXd, PinIdLess> PinLMap;
|
using PinLMap = std::map<const Pin*, Eigen::VectorXd, PinIdLess>;
|
||||||
typedef std::map<const Pin*, FloatSeq, PinIdLess> WatchPinValuesMap;
|
using WatchPinValuesMap = std::map<const Pin*, FloatSeq, PinIdLess>;
|
||||||
|
|
||||||
typedef Table1 Waveform;
|
using Waveform = Table1;
|
||||||
|
|
||||||
ArcDelayCalc *
|
ArcDelayCalc *
|
||||||
makePrimaDelayCalc(StaState *sta);
|
makePrimaDelayCalc(StaState *sta);
|
||||||
|
|
@ -65,35 +64,41 @@ public:
|
||||||
void setPrimaReduceOrder(size_t order);
|
void setPrimaReduceOrder(size_t order);
|
||||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
bool reduceSupported() const override { return false; }
|
bool reduceSupported() const override { return false; }
|
||||||
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDcalcResult inputPortDelay(const Pin *drvr_pin,
|
ArcDcalcResult inputPortDelay(const Pin *drvr_pin,
|
||||||
float in_slew,
|
float in_slew,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &in_slew,
|
const Slew &in_slew,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &dcalc_args,
|
ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &dcalc_args,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
std::string reportGateDelay(const Pin *drvr_pin,
|
std::string reportGateDelay(const Pin *drvr_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &in_slew,
|
const Slew &in_slew,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits) override;
|
int digits) override;
|
||||||
|
|
||||||
// Record waveform for drvr/load pin.
|
// Record waveform for drvr/load pin.
|
||||||
|
|
@ -147,7 +152,7 @@ protected:
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *drvr_rf,
|
const RiseFall *drvr_rf,
|
||||||
const Pin *load_pin,
|
const Pin *load_pin,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
void primaReduce();
|
void primaReduce();
|
||||||
void primaReduce2();
|
void primaReduce2();
|
||||||
|
|
@ -168,7 +173,9 @@ protected:
|
||||||
ArcDcalcArgSeq *dcalc_args_;
|
ArcDcalcArgSeq *dcalc_args_;
|
||||||
size_t drvr_count_;
|
size_t drvr_count_;
|
||||||
float load_cap_;
|
float load_cap_;
|
||||||
const DcalcAnalysisPt *dcalc_ap_;
|
const Scene *scene_;
|
||||||
|
const MinMax *min_max_;
|
||||||
|
Parasitics *parasitics_;
|
||||||
const Parasitic *parasitic_network_;
|
const Parasitic *parasitic_network_;
|
||||||
const RiseFall *drvr_rf_;
|
const RiseFall *drvr_rf_;
|
||||||
const LoadPinIndexMap *load_pin_index_map_;
|
const LoadPinIndexMap *load_pin_index_map_;
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,8 @@ UnitDelayCalc::copy()
|
||||||
Parasitic *
|
Parasitic *
|
||||||
UnitDelayCalc::findParasitic(const Pin *,
|
UnitDelayCalc::findParasitic(const Pin *,
|
||||||
const RiseFall *,
|
const RiseFall *,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *,
|
||||||
|
const MinMax *)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +60,8 @@ Parasitic *
|
||||||
UnitDelayCalc::reduceParasitic(const Parasitic *,
|
UnitDelayCalc::reduceParasitic(const Parasitic *,
|
||||||
const Pin *,
|
const Pin *,
|
||||||
const RiseFall *,
|
const RiseFall *,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *,
|
||||||
|
const MinMax *)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -67,20 +69,22 @@ UnitDelayCalc::reduceParasitic(const Parasitic *,
|
||||||
void
|
void
|
||||||
UnitDelayCalc::reduceParasitic(const Parasitic *,
|
UnitDelayCalc::reduceParasitic(const Parasitic *,
|
||||||
const Net *,
|
const Net *,
|
||||||
const Corner *,
|
const Scene *,
|
||||||
const MinMaxAll *)
|
const MinMaxAll *)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UnitDelayCalc::setDcalcArgParasiticSlew(ArcDcalcArg &,
|
UnitDelayCalc::setDcalcArgParasiticSlew(ArcDcalcArg &,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *,
|
||||||
|
const MinMax *)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UnitDelayCalc::setDcalcArgParasiticSlew(ArcDcalcArgSeq &,
|
UnitDelayCalc::setDcalcArgParasiticSlew(ArcDcalcArgSeq &,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *,
|
||||||
|
const MinMax *)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,7 +94,8 @@ UnitDelayCalc::inputPortDelay(const Pin *,
|
||||||
const RiseFall *,
|
const RiseFall *,
|
||||||
const Parasitic *,
|
const Parasitic *,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *,
|
||||||
|
const MinMax *)
|
||||||
{
|
{
|
||||||
return unitDelayResult(load_pin_index_map);
|
return unitDelayResult(load_pin_index_map);
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +107,8 @@ UnitDelayCalc::gateDelay(const Pin *,
|
||||||
float,
|
float,
|
||||||
const Parasitic *,
|
const Parasitic *,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *,
|
||||||
|
const MinMax *)
|
||||||
{
|
{
|
||||||
return unitDelayResult(load_pin_index_map);
|
return unitDelayResult(load_pin_index_map);
|
||||||
}
|
}
|
||||||
|
|
@ -110,7 +116,8 @@ UnitDelayCalc::gateDelay(const Pin *,
|
||||||
ArcDcalcResultSeq
|
ArcDcalcResultSeq
|
||||||
UnitDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
UnitDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *,
|
||||||
|
const MinMax *)
|
||||||
{
|
{
|
||||||
size_t drvr_count = dcalc_args.size();
|
size_t drvr_count = dcalc_args.size();
|
||||||
ArcDcalcResultSeq dcalc_results(drvr_count);
|
ArcDcalcResultSeq dcalc_results(drvr_count);
|
||||||
|
|
@ -142,7 +149,8 @@ UnitDelayCalc::reportGateDelay(const Pin *,
|
||||||
float,
|
float,
|
||||||
const Parasitic *,
|
const Parasitic *,
|
||||||
const LoadPinIndexMap &,
|
const LoadPinIndexMap &,
|
||||||
const DcalcAnalysisPt *,
|
const Scene *,
|
||||||
|
const MinMax *,
|
||||||
int)
|
int)
|
||||||
{
|
{
|
||||||
string result("Delay = 1.0\n");
|
string result("Delay = 1.0\n");
|
||||||
|
|
@ -156,7 +164,8 @@ UnitDelayCalc::checkDelay(const Pin *,
|
||||||
const Slew &,
|
const Slew &,
|
||||||
const Slew &,
|
const Slew &,
|
||||||
float,
|
float,
|
||||||
const DcalcAnalysisPt *)
|
const Scene *,
|
||||||
|
const MinMax *)
|
||||||
{
|
{
|
||||||
return units_->timeUnit()->scale();
|
return units_->timeUnit()->scale();
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +177,8 @@ UnitDelayCalc::reportCheckDelay(const Pin *,
|
||||||
const char *,
|
const char *,
|
||||||
const Slew &,
|
const Slew &,
|
||||||
float,
|
float,
|
||||||
const DcalcAnalysisPt *,
|
const Scene *,
|
||||||
|
const MinMax *,
|
||||||
int)
|
int)
|
||||||
{
|
{
|
||||||
return "Check = 1.0\n";
|
return "Check = 1.0\n";
|
||||||
|
|
|
||||||
|
|
@ -37,26 +37,31 @@ public:
|
||||||
const char *name() const override { return "unit"; }
|
const char *name() const override { return "unit"; }
|
||||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
bool reduceSupported() const override { return false; }
|
bool reduceSupported() const override { return false; }
|
||||||
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
void reduceParasitic(const Parasitic *parasitic_network,
|
void reduceParasitic(const Parasitic *parasitic_network,
|
||||||
const Net *net,
|
const Net *net,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMaxAll *min_max) override;
|
const MinMaxAll *min_max) override;
|
||||||
void setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
void setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
void setDcalcArgParasiticSlew(ArcDcalcArgSeq &gates,
|
void setDcalcArgParasiticSlew(ArcDcalcArgSeq &gates,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||||
float in_slew,
|
float in_slew,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &in_slew,
|
const Slew &in_slew,
|
||||||
|
|
@ -64,23 +69,27 @@ public:
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &args,
|
ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &args,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
ArcDelay checkDelay(const Pin *check_pin,
|
ArcDelay checkDelay(const Pin *check_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &from_slew,
|
const Slew &from_slew,
|
||||||
const Slew &to_slew,
|
const Slew &to_slew,
|
||||||
float related_out_cap,
|
float related_out_cap,
|
||||||
const DcalcAnalysisPt *dcalc_ap) override;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) override;
|
||||||
std::string reportGateDelay(const Pin *drvr_pin,
|
std::string reportGateDelay(const Pin *drvr_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Slew &in_slew,
|
const Slew &in_slew,
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits) override;
|
int digits) override;
|
||||||
std::string reportCheckDelay(const Pin *check_pin,
|
std::string reportCheckDelay(const Pin *check_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
|
|
@ -88,7 +97,8 @@ public:
|
||||||
const char *from_slew_annotation,
|
const char *from_slew_annotation,
|
||||||
const Slew &to_slew,
|
const Slew &to_slew,
|
||||||
float related_out_cap,
|
float related_out_cap,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits) override;
|
int digits) override;
|
||||||
void finishDrvrPin() override;
|
void finishDrvrPin() override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,45 @@
|
||||||
|
|
||||||
This file summarizes STA API changes for each release.
|
This file summarizes STA API changes for each release.
|
||||||
|
|
||||||
|
Release 3.0.0 2025/11/26
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
OpenSTA now requires c++ 20.
|
||||||
|
|
||||||
|
Corner replaced by Scene
|
||||||
|
mode()
|
||||||
|
parasitics(min_max)
|
||||||
|
DcalcAnalysisPt replaced by scene/min_min
|
||||||
|
DcalcAnalysisPt replaced by scene/min_min
|
||||||
|
PathAnalysisPt replaced by scene/min_min
|
||||||
|
StaState::sdc_ moved to Mode
|
||||||
|
StaState::sim_ moved to Mode
|
||||||
|
StaState::clk_network__ moved to Mode
|
||||||
|
StaState::parasitics_ moved to Scene
|
||||||
|
|
||||||
|
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
|
||||||
|
to StdStringSeq&.
|
||||||
|
|
||||||
|
Sta::isClock has been removed. Use mode->clkNetwork()->isClock instead.
|
||||||
|
|
||||||
|
Sta::vertexSlew renamed to slew
|
||||||
|
Sta::vertexSlack renamed to slack
|
||||||
|
Sta::vertexSlacks renamed to slacks
|
||||||
|
Sta::vertexArrival renamed to arrival
|
||||||
|
Sta::vertexRequired renamed to required
|
||||||
|
Sta::pinSlack renamed to slack
|
||||||
|
Sta::pinArrival renamed to arrival
|
||||||
|
|
||||||
|
FuncExpr::Operator::op_* renamed to FuncExpr::Op::*
|
||||||
|
FuncExprPortIterator has been removed. Use FuncExpr::ports().
|
||||||
|
|
||||||
|
Sdc::clocks() now returns ClockSeq&.
|
||||||
|
Sdc::clks() has been removed.
|
||||||
|
|
||||||
|
The Vector/Map/Set/UnorderedSet classes have been removed and replaced by
|
||||||
|
the std containers. The member functions are now templated functions found
|
||||||
|
in ContainerHelpers.hh.
|
||||||
|
|
||||||
Release 2.6.2 2025/03/30
|
Release 2.6.2 2025/03/30
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,180 @@ OpenSTA Timing Analyzer Release Notes
|
||||||
|
|
||||||
This file summarizes user visible changes for each release.
|
This file summarizes user visible changes for each release.
|
||||||
|
|
||||||
|
Release 3.0.0 2025/11/26
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
This release adds multi-corner multi-mode (mcmm) support. The SDC
|
||||||
|
constraints in each mode describe a different operating mode, such as
|
||||||
|
mission mode or scan mode.
|
||||||
|
|
||||||
|
A "scene" is the combination of a mode and corner. Each scene can have
|
||||||
|
separate min/max liberty and spef files.
|
||||||
|
|
||||||
|
THe basic structure of a multi-corner/multi-mode command file is
|
||||||
|
read_liberty
|
||||||
|
read_verilog
|
||||||
|
link_design
|
||||||
|
read_sdc -mode... or set_mode followed by sdc commands
|
||||||
|
read_spef -name...
|
||||||
|
define_scene...
|
||||||
|
report_checks [-scenes]
|
||||||
|
|
||||||
|
This is an example script with 2 corners, 2 modes and 3 scenes.
|
||||||
|
|
||||||
|
read_liberty bc.lib
|
||||||
|
read_liberty wc.lib
|
||||||
|
|
||||||
|
read_verilog design.v
|
||||||
|
link_design top
|
||||||
|
|
||||||
|
read_sdc -mode run design.sdc
|
||||||
|
read_sdc -mode scan design_scan.sdc
|
||||||
|
|
||||||
|
read_spef -name bc bc.spef
|
||||||
|
read_spef -name wc wc.spef
|
||||||
|
|
||||||
|
define_scene bc \
|
||||||
|
-mode run \
|
||||||
|
-liberty bc \
|
||||||
|
-spef bc
|
||||||
|
define_scene wc \
|
||||||
|
-mode run \
|
||||||
|
-liberty wc \
|
||||||
|
-spef wc
|
||||||
|
define_scene scan \
|
||||||
|
-mode scan \
|
||||||
|
-liberty wc \
|
||||||
|
-spef wc
|
||||||
|
|
||||||
|
report_checks
|
||||||
|
report_checks -scenes bc
|
||||||
|
report_checks -scenes wc
|
||||||
|
report_checks -scenes scan
|
||||||
|
|
||||||
|
................
|
||||||
|
|
||||||
|
Alternatively, the set_mode command can be used to define commands
|
||||||
|
for each mode at the command level instead of using SDC files.
|
||||||
|
|
||||||
|
set_mode run
|
||||||
|
create_clock -period 10 clock
|
||||||
|
set_input_delay 0 -clock clock [all_inputs -no_clocks]
|
||||||
|
set_output_delay 0 -clock clock [all_outputs]
|
||||||
|
|
||||||
|
set_mode scan
|
||||||
|
create_clock -period 100 scan_clock
|
||||||
|
set_input_delay 0 -clock scan_clock scan_in
|
||||||
|
set_output_delay 0 -clock scan_clock scan_out
|
||||||
|
|
||||||
|
................
|
||||||
|
|
||||||
|
The define_corners command is supported for compatiblity but should
|
||||||
|
not be used with mcmm flows. Similarly, the -min/-max arguemnts to
|
||||||
|
read_liberty and read_spaf are supported for compabibility but should
|
||||||
|
not be used with mcmm flows.
|
||||||
|
|
||||||
|
................
|
||||||
|
|
||||||
|
An initial mode and scene named "default" are defined for single mode,
|
||||||
|
single corner analysis. SDC commands defined interactively and read
|
||||||
|
with read_sdc without a -mode argument are defined in the "default"
|
||||||
|
mode.
|
||||||
|
|
||||||
|
Use the set_mode command to define a mode or set the command
|
||||||
|
interpreter to add following commands to mode mode_name.
|
||||||
|
|
||||||
|
set_mode mode_name
|
||||||
|
|
||||||
|
If mode_name does not exist it is created. When modes are created the
|
||||||
|
default mode is deleted.
|
||||||
|
|
||||||
|
The read_sdc command has a -mode argument to assign the commands in the file
|
||||||
|
to a mode.
|
||||||
|
|
||||||
|
read_sdc [-mode mode_name]
|
||||||
|
|
||||||
|
If the mode does not exist it is created. Multiple SDC files can
|
||||||
|
append commands to a mode by using the -mode_name argument for each
|
||||||
|
one. If no -mode arguement is is used the commands are added to the
|
||||||
|
current mode.
|
||||||
|
|
||||||
|
................
|
||||||
|
|
||||||
|
The define_scene command defines a scene for a mode (SDC), liberty files
|
||||||
|
and spef parasitics.
|
||||||
|
|
||||||
|
define_scene -mode mode_name
|
||||||
|
-liberty liberty_files | -liberty_min liberty_min_files -liberty_max liberty_max_files
|
||||||
|
[-spef spef_file | -spef_min spef_min_file -spef_max spef_max_file]
|
||||||
|
|
||||||
|
Use get_scenes to find defined scenes.
|
||||||
|
|
||||||
|
get_scenes [-modes mode_names] scene_name
|
||||||
|
|
||||||
|
................
|
||||||
|
|
||||||
|
Use the read_spef -name argument to append multiple parasitics files
|
||||||
|
to annotate hierarchical blocks. Scene definitions use the spef_name
|
||||||
|
to specify which parasitices to use for each scene.
|
||||||
|
|
||||||
|
read_spef -name spef_name
|
||||||
|
report_parasitic_annotation [-name spef_name]
|
||||||
|
|
||||||
|
If -name is omitted the base name of the file name is used.
|
||||||
|
|
||||||
|
The read_spef -corner/-min/-max arguments are supported for comppatibility
|
||||||
|
but will be removed in a future release.
|
||||||
|
|
||||||
|
The read_spef -reduce options don't work because sdc, liberty ap isn't known
|
||||||
|
|
||||||
|
................
|
||||||
|
|
||||||
|
The report_checks and report_check_typescommands support a -scenes
|
||||||
|
argument to report timing checks/paths from multiple scenes.
|
||||||
|
|
||||||
|
report_checks -scenes
|
||||||
|
report_check_types -scenes
|
||||||
|
report_slews -scenes
|
||||||
|
report_clock_latency -scenes
|
||||||
|
|
||||||
|
................
|
||||||
|
|
||||||
|
To annotate delays with SDF when there are multiple scenes, use
|
||||||
|
the -scene argument.
|
||||||
|
|
||||||
|
read_sdf -scene
|
||||||
|
report_annotated_delay -scene
|
||||||
|
report_annotated_check -scene
|
||||||
|
|
||||||
|
SDF annotation for mcmm analysis must follow the scene definitions.
|
||||||
|
|
||||||
|
................
|
||||||
|
|
||||||
|
VCD annotation with read_vcd now supports a -mode arguement.
|
||||||
|
|
||||||
|
read_vcd [-mode mode_name]
|
||||||
|
|
||||||
|
................
|
||||||
|
|
||||||
|
The -corner args has been removed from the following commands because they are no
|
||||||
|
longer necessary.
|
||||||
|
set_load -corner
|
||||||
|
set_port_fanout_number -corner
|
||||||
|
|
||||||
|
................
|
||||||
|
|
||||||
|
The report_pulse_width_checks command is no longer supported. Use
|
||||||
|
report_check_types -min_pulse_width.
|
||||||
|
|
||||||
|
................
|
||||||
|
|
||||||
|
Delay calculation slew values now propagate through set_case_analysis
|
||||||
|
and set_logic_zero, set_logic_one, set_logic_dc constraints.
|
||||||
|
|
||||||
|
Power analysis now ignores set_case_analysis and set_logic_zero,
|
||||||
|
set_logic_one, set_logic_dc.
|
||||||
|
|
||||||
Release 2.7.0 2025/05/19
|
Release 2.7.0 2025/05/19
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
|
@ -19,6 +193,9 @@ to remove paths through identical pins and rise/fall edges.
|
||||||
|
|
||||||
Instances now have pins for verilog netlist power/ground connections,
|
Instances now have pins for verilog netlist power/ground connections,
|
||||||
|
|
||||||
|
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
|
||||||
|
to StdStringSeq&.
|
||||||
|
|
||||||
Release 2.6.1 2025/03/30
|
Release 2.6.1 2025/03/30
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
|
@ -93,6 +270,8 @@ timing groups.
|
||||||
report_clock_skew -include_internal_latency
|
report_clock_skew -include_internal_latency
|
||||||
report_clock_latency -include_internal_latency
|
report_clock_latency -include_internal_latency
|
||||||
|
|
||||||
|
The report_clock_skew requires a -scene argument if multiple scenes are defined.
|
||||||
|
|
||||||
The all_inputs command now supports the -no_clocks argument to exclude
|
The all_inputs command now supports the -no_clocks argument to exclude
|
||||||
clocks from the list.
|
clocks from the list.
|
||||||
|
|
||||||
|
|
|
||||||
6688
doc/OpenSTA.fodt
6688
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.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,2 @@
|
||||||
|
create_clock -name m1_clk -period 1000 {clk1 clk2 clk3}
|
||||||
|
set_input_delay -clock m1_clk 100 {in1 in2}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
create_clock -name m2_clk -period 500 {clk1 clk3}
|
||||||
|
set_output_delay -clock m2_clk 100 out
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# mmcm reg1 parasitics
|
||||||
|
read_liberty asap7_small_ff.lib.gz
|
||||||
|
read_liberty asap7_small_ss.lib.gz
|
||||||
|
read_verilog reg1_asap7.v
|
||||||
|
link_design top
|
||||||
|
|
||||||
|
read_sdc -mode mode1 mcmm2_mode1.sdc
|
||||||
|
read_sdc -mode mode2 mcmm2_mode2.sdc
|
||||||
|
|
||||||
|
read_spef -name reg1_ff reg1_asap7.spef
|
||||||
|
read_spef -name reg1_ss reg1_asap7_ss.spef
|
||||||
|
|
||||||
|
define_scene scene1 -mode mode1 -liberty asap7_small_ff -spef reg1_ff
|
||||||
|
define_scene scene2 -mode mode2 -liberty asap7_small_ss -spef reg1_ss
|
||||||
|
|
||||||
|
report_checks -scenes scene1
|
||||||
|
report_checks -scenes scene2
|
||||||
|
report_checks -group_path_count 4
|
||||||
|
|
@ -1,15 +1,20 @@
|
||||||
# 3 corners with +/- 10% derating example
|
# 3 liberty corners with +/- 10% derating example
|
||||||
define_corners ss tt ff
|
read_liberty nangate45_slow.lib.gz
|
||||||
read_liberty -corner ss nangate45_slow.lib.gz
|
read_liberty nangate45_typ.lib.gz
|
||||||
read_liberty -corner tt nangate45_typ.lib.gz
|
read_liberty nangate45_fast.lib.gz
|
||||||
read_liberty -corner ff nangate45_fast.lib.gz
|
|
||||||
read_verilog example1.v
|
read_verilog example1.v
|
||||||
link_design top
|
link_design top
|
||||||
set_timing_derate -early 0.9
|
set_timing_derate -early 0.9
|
||||||
set_timing_derate -late 1.1
|
set_timing_derate -late 1.1
|
||||||
create_clock -name clk -period 10 {clk1 clk2 clk3}
|
create_clock -name clk -period 10 {clk1 clk2 clk3}
|
||||||
set_input_delay -clock clk 0 {in1 in2}
|
set_input_delay -clock clk 0 {in1 in2}
|
||||||
# report all corners
|
|
||||||
|
define_scene ss -liberty nangate45_slow
|
||||||
|
define_scene tt -liberty nangate45_typ
|
||||||
|
define_scene ff -liberty nangate45_fast
|
||||||
|
|
||||||
|
# report all scenes
|
||||||
report_checks -path_delay min_max
|
report_checks -path_delay min_max
|
||||||
# report typical corner
|
# report typical scene
|
||||||
report_checks -corner tt
|
report_checks -scene tt
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
*SPEF "IEEE 1481-1998"
|
||||||
|
*DESIGN "reg1"
|
||||||
|
*DATE "Fri Nov 20 13:23:00 2002"
|
||||||
|
*VENDOR "Parallax Software, Inc"
|
||||||
|
*PROGRAM "Handjob"
|
||||||
|
*VERSION "1.0.1c"
|
||||||
|
*DESIGN_FLOW "MISSING_NETS"
|
||||||
|
*DIVIDER /
|
||||||
|
*DELIMITER :
|
||||||
|
*BUS_DELIMITER [ ]
|
||||||
|
*T_UNIT 1.0 PS
|
||||||
|
*C_UNIT 1.0 FF
|
||||||
|
*R_UNIT 1.0 KOHM
|
||||||
|
*L_UNIT 1.0 UH
|
||||||
|
|
||||||
|
*POWER_NETS VDD
|
||||||
|
*GROUND_NETS VSS
|
||||||
|
|
||||||
|
*PORTS
|
||||||
|
in1 I
|
||||||
|
in2 I
|
||||||
|
clk1 I
|
||||||
|
clk2 I
|
||||||
|
clk3 I
|
||||||
|
out O
|
||||||
|
|
||||||
|
*D_NET in1 13.4
|
||||||
|
*CONN
|
||||||
|
*P in1 I
|
||||||
|
*I r1:D I *L .0036
|
||||||
|
*CAP
|
||||||
|
1 in1 6.7
|
||||||
|
2 r1:D 6.7
|
||||||
|
*RES
|
||||||
|
3 in1 r1:D 2.42
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET in2 13.4
|
||||||
|
*CONN
|
||||||
|
*P in2 I
|
||||||
|
*I r2:D I *L .0036
|
||||||
|
*CAP
|
||||||
|
1 in2 6.7
|
||||||
|
2 r2:D 6.7
|
||||||
|
*RES
|
||||||
|
3 in2 r2:D 2.42
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET clk1 13.4
|
||||||
|
*CONN
|
||||||
|
*P clk1 I
|
||||||
|
*I r1:CLK I *L .0036
|
||||||
|
*CAP
|
||||||
|
1 clk1 6.7
|
||||||
|
2 r1:CLK 6.7
|
||||||
|
*RES
|
||||||
|
3 clk1 r1:CLK 2.42
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET clk2 13.4
|
||||||
|
*CONN
|
||||||
|
*P clk2 I
|
||||||
|
*I r2:CLK I *L .0036
|
||||||
|
*CAP
|
||||||
|
1 clk2 6.7
|
||||||
|
2 r2:CLK 6.7
|
||||||
|
*RES
|
||||||
|
3 clk2 r2:CLK 2.42
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET clk3 13.4
|
||||||
|
*CONN
|
||||||
|
*P clk3 I
|
||||||
|
*I r3:CLK I *L .0036
|
||||||
|
*CAP
|
||||||
|
1 clk3 6.7
|
||||||
|
2 r3:CLK 6.7
|
||||||
|
*RES
|
||||||
|
3 clk3 r3:CLK 2.42
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET r1q 13.4
|
||||||
|
*CONN
|
||||||
|
*I r1:Q O
|
||||||
|
*I u2:A I *L .0086
|
||||||
|
*CAP
|
||||||
|
1 r1:Q 6.7
|
||||||
|
2 u2:A 6.7
|
||||||
|
*RES
|
||||||
|
3 r1:Q u2:A 2.42
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET r2q 13.4
|
||||||
|
*CONN
|
||||||
|
*I r2:Q O
|
||||||
|
*I u1:A I *L .0086
|
||||||
|
*CAP
|
||||||
|
1 r2:Q 6.7
|
||||||
|
2 u1:A 6.7
|
||||||
|
*RES
|
||||||
|
3 r2:Q u1:A 2.42
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET u1z 13.4
|
||||||
|
*CONN
|
||||||
|
*I u1:Y O
|
||||||
|
*I u2:B I *L .0086
|
||||||
|
*CAP
|
||||||
|
1 u1:Y 6.7
|
||||||
|
2 u2:B 6.7
|
||||||
|
*RES
|
||||||
|
3 u1:Y u2:B 2.42
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET u2z 13.4
|
||||||
|
*CONN
|
||||||
|
*I u2:Y O
|
||||||
|
*I r3:D I *L .0086
|
||||||
|
*CAP
|
||||||
|
1 u2:Y 6.7
|
||||||
|
2 r3:D 6.7
|
||||||
|
*RES
|
||||||
|
3 u2:Y r3:D 2.42
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET out 13.4
|
||||||
|
*CONN
|
||||||
|
*I r3:Q O
|
||||||
|
*P out O
|
||||||
|
*CAP
|
||||||
|
1 r3:Q 6.7
|
||||||
|
2 out 6.7
|
||||||
|
*RES
|
||||||
|
3 r3:Q out 2.42
|
||||||
|
*END
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
module top (in1, in2, clk1, clk2, clk3, out);
|
||||||
|
input in1, in2, clk1, clk2, clk3;
|
||||||
|
output out;
|
||||||
|
wire r1q, r2q, u1z, u2z;
|
||||||
|
|
||||||
|
DFFHQx4_ASAP7_75t_R r1 (.D(in1), .CLK(clk1), .Q(r1q));
|
||||||
|
DFFHQx4_ASAP7_75t_R r2 (.D(in2), .CLK(clk2), .Q(r2q));
|
||||||
|
BUFx2_ASAP7_75t_R u1 (.A(r2q), .Y(u1z));
|
||||||
|
AND2x2_ASAP7_75t_R u2 (.A(r1q), .B(u1z), .Y(u2z));
|
||||||
|
DFFHQx4_ASAP7_75t_R r3 (.D(u2z), .CLK(clk3), .Q(out));
|
||||||
|
endmodule // top
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
*SPEF "IEEE 1481-1998"
|
||||||
|
*DESIGN "reg1"
|
||||||
|
*DATE "Fri Nov 20 13:23:00 2002"
|
||||||
|
*VENDOR "Parallax Software, Inc"
|
||||||
|
*PROGRAM "Handjob"
|
||||||
|
*VERSION "1.0.1c"
|
||||||
|
*DESIGN_FLOW "MISSING_NETS"
|
||||||
|
*DIVIDER /
|
||||||
|
*DELIMITER :
|
||||||
|
*BUS_DELIMITER [ ]
|
||||||
|
*T_UNIT 1.0 PS
|
||||||
|
*C_UNIT 1.0 FF
|
||||||
|
*R_UNIT 1.0 KOHM
|
||||||
|
*L_UNIT 1.0 UH
|
||||||
|
|
||||||
|
*POWER_NETS VDD
|
||||||
|
*GROUND_NETS VSS
|
||||||
|
|
||||||
|
*PORTS
|
||||||
|
in1 I
|
||||||
|
in2 I
|
||||||
|
clk1 I
|
||||||
|
clk2 I
|
||||||
|
clk3 I
|
||||||
|
out O
|
||||||
|
|
||||||
|
*D_NET in1 13.4
|
||||||
|
*CONN
|
||||||
|
*P in1 I
|
||||||
|
*I r1:D I *L .0036
|
||||||
|
*CAP
|
||||||
|
1 in1 8.1
|
||||||
|
2 r1:D 8.1
|
||||||
|
*RES
|
||||||
|
3 in1 r1:D 2.7
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET in2 13.4
|
||||||
|
*CONN
|
||||||
|
*P in2 I
|
||||||
|
*I r2:D I *L .0036
|
||||||
|
*CAP
|
||||||
|
1 in2 8.1
|
||||||
|
2 r2:D 8.1
|
||||||
|
*RES
|
||||||
|
3 in2 r2:D 2.7
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET clk1 13.4
|
||||||
|
*CONN
|
||||||
|
*P clk1 I
|
||||||
|
*I r1:CLK I *L .0036
|
||||||
|
*CAP
|
||||||
|
1 clk1 8.1
|
||||||
|
2 r1:CLK 8.1
|
||||||
|
*RES
|
||||||
|
3 clk1 r1:CLK 2.7
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET clk2 13.4
|
||||||
|
*CONN
|
||||||
|
*P clk2 I
|
||||||
|
*I r2:CLK I *L .0036
|
||||||
|
*CAP
|
||||||
|
1 clk2 8.1
|
||||||
|
2 r2:CLK 8.1
|
||||||
|
*RES
|
||||||
|
3 clk2 r2:CLK 2.7
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET clk3 13.4
|
||||||
|
*CONN
|
||||||
|
*P clk3 I
|
||||||
|
*I r3:CLK I *L .0036
|
||||||
|
*CAP
|
||||||
|
1 clk3 8.1
|
||||||
|
2 r3:CLK 8.1
|
||||||
|
*RES
|
||||||
|
3 clk3 r3:CLK 2.7
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET r1q 13.4
|
||||||
|
*CONN
|
||||||
|
*I r1:Q O
|
||||||
|
*I u2:A I *L .0086
|
||||||
|
*CAP
|
||||||
|
1 r1:Q 8.1
|
||||||
|
2 u2:A 8.1
|
||||||
|
*RES
|
||||||
|
3 r1:Q u2:A 2.7
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET r2q 13.4
|
||||||
|
*CONN
|
||||||
|
*I r2:Q O
|
||||||
|
*I u1:A I *L .0086
|
||||||
|
*CAP
|
||||||
|
1 r2:Q 8.1
|
||||||
|
2 u1:A 8.1
|
||||||
|
*RES
|
||||||
|
3 r2:Q u1:A 2.7
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET u1z 13.4
|
||||||
|
*CONN
|
||||||
|
*I u1:Y O
|
||||||
|
*I u2:B I *L .0086
|
||||||
|
*CAP
|
||||||
|
1 u1:Y 8.1
|
||||||
|
2 u2:B 8.1
|
||||||
|
*RES
|
||||||
|
3 u1:Y u2:B 2.7
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET u2z 13.4
|
||||||
|
*CONN
|
||||||
|
*I u2:Y O
|
||||||
|
*I r3:D I *L .0086
|
||||||
|
*CAP
|
||||||
|
1 u2:Y 8.1
|
||||||
|
2 r3:D 8.1
|
||||||
|
*RES
|
||||||
|
3 u2:Y r3:D 2.7
|
||||||
|
*END
|
||||||
|
|
||||||
|
*D_NET out 13.4
|
||||||
|
*CONN
|
||||||
|
*I r3:Q O
|
||||||
|
*P out O
|
||||||
|
*CAP
|
||||||
|
1 r3:Q 8.1
|
||||||
|
2 out 8.1
|
||||||
|
*RES
|
||||||
|
3 r3:Q out 2.7
|
||||||
|
*END
|
||||||
204
graph/Graph.cc
204
graph/Graph.cc
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "Graph.hh"
|
#include "Graph.hh"
|
||||||
|
|
||||||
|
#include "ContainerHelpers.hh"
|
||||||
#include "Debug.hh"
|
#include "Debug.hh"
|
||||||
#include "Stats.hh"
|
#include "Stats.hh"
|
||||||
#include "MinMax.hh"
|
#include "MinMax.hh"
|
||||||
|
|
@ -34,7 +35,6 @@
|
||||||
#include "Liberty.hh"
|
#include "Liberty.hh"
|
||||||
#include "PortDirection.hh"
|
#include "PortDirection.hh"
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "DcalcAnalysisPt.hh"
|
|
||||||
#include "FuncExpr.hh"
|
#include "FuncExpr.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -56,7 +56,7 @@ Graph::Graph(StaState *sta,
|
||||||
slew_rf_count_(slew_rf_count),
|
slew_rf_count_(slew_rf_count),
|
||||||
ap_count_(ap_count),
|
ap_count_(ap_count),
|
||||||
period_check_annotations_(nullptr),
|
period_check_annotations_(nullptr),
|
||||||
reg_clk_vertices_(new VertexSet(graph_))
|
reg_clk_vertices_(makeVertexSet(this))
|
||||||
{
|
{
|
||||||
// For the benifit of reg_clk_vertices_ that references graph_.
|
// For the benifit of reg_clk_vertices_ that references graph_.
|
||||||
graph_ = this;
|
graph_ = this;
|
||||||
|
|
@ -68,7 +68,6 @@ Graph::~Graph()
|
||||||
delete edges_;
|
delete edges_;
|
||||||
vertices_->clear();
|
vertices_->clear();
|
||||||
delete vertices_;
|
delete vertices_;
|
||||||
delete reg_clk_vertices_;
|
|
||||||
removePeriodCheckAnnotations();
|
removePeriodCheckAnnotations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,7 +253,7 @@ Graph::makeInstDrvrWireEdges(const Instance *inst,
|
||||||
while (pin_iter->hasNext()) {
|
while (pin_iter->hasNext()) {
|
||||||
Pin *pin = pin_iter->next();
|
Pin *pin = pin_iter->next();
|
||||||
if (network_->isDriver(pin)
|
if (network_->isDriver(pin)
|
||||||
&& !visited_drvrs.hasKey(pin))
|
&& !visited_drvrs.contains(pin))
|
||||||
makeWireEdgesFromPin(pin, visited_drvrs);
|
makeWireEdgesFromPin(pin, visited_drvrs);
|
||||||
}
|
}
|
||||||
delete pin_iter;
|
delete pin_iter;
|
||||||
|
|
@ -391,6 +390,13 @@ Graph::makeWireEdge(const Pin *from_pin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Graph::makeSceneAfter()
|
||||||
|
{
|
||||||
|
ap_count_ = dcalcAnalysisPtCount();
|
||||||
|
initSlews();
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Vertex *
|
Vertex *
|
||||||
|
|
@ -440,7 +446,7 @@ Graph::makeVertex(Pin *pin,
|
||||||
vertex->init(pin, is_bidirect_drvr, is_reg_clk);
|
vertex->init(pin, is_bidirect_drvr, is_reg_clk);
|
||||||
initSlews(vertex);
|
initSlews(vertex);
|
||||||
if (is_reg_clk)
|
if (is_reg_clk)
|
||||||
reg_clk_vertices_->insert(vertex);
|
reg_clk_vertices_.insert(vertex);
|
||||||
return vertex;
|
return vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -452,7 +458,7 @@ Graph::pinVertices(const Pin *pin,
|
||||||
{
|
{
|
||||||
vertex = Graph::vertex(network_->vertexId(pin));
|
vertex = Graph::vertex(network_->vertexId(pin));
|
||||||
if (network_->direction(pin)->isBidirect())
|
if (network_->direction(pin)->isBidirect())
|
||||||
bidirect_drvr_vertex = pin_bidirect_drvr_vertex_map_.findKey(pin);
|
bidirect_drvr_vertex = findKey(pin_bidirect_drvr_vertex_map_, pin);
|
||||||
else
|
else
|
||||||
bidirect_drvr_vertex = nullptr;
|
bidirect_drvr_vertex = nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -461,7 +467,7 @@ Vertex *
|
||||||
Graph::pinDrvrVertex(const Pin *pin) const
|
Graph::pinDrvrVertex(const Pin *pin) const
|
||||||
{
|
{
|
||||||
if (network_->direction(pin)->isBidirect())
|
if (network_->direction(pin)->isBidirect())
|
||||||
return pin_bidirect_drvr_vertex_map_.findKey(pin);
|
return findKey(pin_bidirect_drvr_vertex_map_, pin);
|
||||||
else
|
else
|
||||||
return Graph::vertex(network_->vertexId(pin));
|
return Graph::vertex(network_->vertexId(pin));
|
||||||
}
|
}
|
||||||
|
|
@ -476,7 +482,7 @@ void
|
||||||
Graph::deleteVertex(Vertex *vertex)
|
Graph::deleteVertex(Vertex *vertex)
|
||||||
{
|
{
|
||||||
if (vertex->isRegClk())
|
if (vertex->isRegClk())
|
||||||
reg_clk_vertices_->erase(vertex);
|
reg_clk_vertices_.erase(vertex);
|
||||||
Pin *pin = vertex->pin_;
|
Pin *pin = vertex->pin_;
|
||||||
if (vertex->isBidirectDriver())
|
if (vertex->isBidirectDriver())
|
||||||
pin_bidirect_drvr_vertex_map_.erase(pin_bidirect_drvr_vertex_map_
|
pin_bidirect_drvr_vertex_map_.erase(pin_bidirect_drvr_vertex_map_
|
||||||
|
|
@ -574,30 +580,6 @@ Graph::gateEdgeArc(const Pin *in_pin,
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Path *
|
|
||||||
Graph::makePaths(Vertex *vertex,
|
|
||||||
uint32_t count)
|
|
||||||
{
|
|
||||||
Path *paths = new Path[count];
|
|
||||||
vertex->setPaths(paths);
|
|
||||||
return paths;
|
|
||||||
}
|
|
||||||
|
|
||||||
Path *
|
|
||||||
Graph::paths(const Vertex *vertex) const
|
|
||||||
{
|
|
||||||
return vertex->paths();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Graph::deletePaths(Vertex *vertex)
|
|
||||||
{
|
|
||||||
vertex->setPaths(nullptr);
|
|
||||||
vertex->tag_group_index_ = tag_group_index_max;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
const Slew &
|
const Slew &
|
||||||
Graph::slew(const Vertex *vertex,
|
Graph::slew(const Vertex *vertex,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
|
|
@ -831,19 +813,6 @@ Graph::initArcDelays(Edge *edge)
|
||||||
arc_delays[i] = 0.0;
|
arc_delays[i] = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
Graph::delayAnnotated(Edge *edge)
|
|
||||||
{
|
|
||||||
TimingArcSet *arc_set = edge->timingArcSet();
|
|
||||||
for (TimingArc *arc : arc_set->arcs()) {
|
|
||||||
for (DcalcAPIndex ap_index = 0; ap_index < ap_count_; ap_index++) {
|
|
||||||
if (!arcDelayAnnotated(edge, arc, ap_index))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -906,7 +875,7 @@ Graph::periodCheckAnnotation(const Pin *pin,
|
||||||
{
|
{
|
||||||
exists = false;
|
exists = false;
|
||||||
if (period_check_annotations_) {
|
if (period_check_annotations_) {
|
||||||
float *periods = period_check_annotations_->findKey(pin);
|
float *periods = findKey(period_check_annotations_, pin);
|
||||||
if (periods) {
|
if (periods) {
|
||||||
period = periods[ap_index];
|
period = periods[ap_index];
|
||||||
if (period >= 0.0)
|
if (period >= 0.0)
|
||||||
|
|
@ -922,7 +891,7 @@ Graph::setPeriodCheckAnnotation(const Pin *pin,
|
||||||
{
|
{
|
||||||
if (period_check_annotations_ == nullptr)
|
if (period_check_annotations_ == nullptr)
|
||||||
period_check_annotations_ = new PeriodCheckAnnotations(network_);
|
period_check_annotations_ = new PeriodCheckAnnotations(network_);
|
||||||
float *periods = period_check_annotations_->findKey(pin);
|
float *periods = findKey(period_check_annotations_, pin);
|
||||||
if (periods == nullptr) {
|
if (periods == nullptr) {
|
||||||
periods = new float[ap_count_];
|
periods = new float[ap_count_];
|
||||||
// Use negative (illegal) period values to indicate unannotated checks.
|
// Use negative (illegal) period values to indicate unannotated checks.
|
||||||
|
|
@ -986,16 +955,13 @@ Vertex::init(Pin *pin,
|
||||||
paths_ = nullptr;
|
paths_ = nullptr;
|
||||||
tag_group_index_ = tag_group_index_max;
|
tag_group_index_ = tag_group_index_max;
|
||||||
slew_annotated_ = false;
|
slew_annotated_ = false;
|
||||||
sim_value_ = unsigned(LogicValue::unknown);
|
|
||||||
is_disabled_constraint_ = false;
|
|
||||||
is_gated_clk_enable_ = false;
|
|
||||||
has_checks_ = false;
|
has_checks_ = false;
|
||||||
is_check_clk_ = false;
|
is_check_clk_ = false;
|
||||||
is_constrained_ = false;
|
|
||||||
has_downstream_clk_pin_ = false;
|
has_downstream_clk_pin_ = false;
|
||||||
level_ = 0;
|
level_ = 0;
|
||||||
visited1_ = false;
|
visited1_ = false;
|
||||||
visited2_ = false;
|
visited2_ = false;
|
||||||
|
has_sim_value_ = false;
|
||||||
bfs_in_queue_ = 0;
|
bfs_in_queue_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1082,11 +1048,17 @@ Vertex::setSlews(Slew *slews)
|
||||||
slews_ = slews;
|
slews_ = slews;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vertex::setHasSimValue(bool has_sim)
|
||||||
|
{
|
||||||
|
has_sim_value_ = has_sim;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Vertex::slewAnnotated(const RiseFall *rf,
|
Vertex::slewAnnotated(const RiseFall *rf,
|
||||||
const MinMax *min_max) const
|
const MinMax *min_max) const
|
||||||
{
|
{
|
||||||
int index = min_max->index() * transitionCount() + rf->index();
|
int index = min_max->index() * RiseFall::index_count+ rf->index();
|
||||||
return ((1 << index) & slew_annotated_) != 0;
|
return ((1 << index) & slew_annotated_) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1105,7 +1077,7 @@ Vertex::setSlewAnnotated(bool annotated,
|
||||||
// only rise/fall.
|
// only rise/fall.
|
||||||
if (ap_index > 1)
|
if (ap_index > 1)
|
||||||
ap_index = 0;
|
ap_index = 0;
|
||||||
int index = ap_index * transitionCount() + rf->index();
|
int index = ap_index * RiseFall::index_count + rf->index();
|
||||||
if (annotated)
|
if (annotated)
|
||||||
slew_annotated_ |= (1 << index);
|
slew_annotated_ |= (1 << index);
|
||||||
else
|
else
|
||||||
|
|
@ -1130,6 +1102,15 @@ Vertex::setTagGroupIndex(TagGroupIndex tag_index)
|
||||||
tag_group_index_ = tag_index;
|
tag_group_index_ = tag_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Path *
|
||||||
|
Vertex::makePaths(uint32_t count)
|
||||||
|
{
|
||||||
|
delete [] paths_;
|
||||||
|
Path *paths = new Path[count];
|
||||||
|
paths_ = paths;
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Vertex::setPaths(Path *paths)
|
Vertex::setPaths(Path *paths)
|
||||||
{
|
{
|
||||||
|
|
@ -1137,30 +1118,12 @@ Vertex::setPaths(Path *paths)
|
||||||
paths_ = paths;
|
paths_ = paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogicValue
|
|
||||||
Vertex::simValue() const
|
|
||||||
{
|
|
||||||
return static_cast<LogicValue>(sim_value_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Vertex::setSimValue(LogicValue value)
|
Vertex::deletePaths()
|
||||||
{
|
{
|
||||||
sim_value_ = unsigned(value);
|
delete [] paths_;
|
||||||
}
|
paths_ = nullptr;
|
||||||
|
tag_group_index_ = tag_group_index_max;
|
||||||
bool
|
|
||||||
Vertex::isConstant() const
|
|
||||||
{
|
|
||||||
LogicValue value = static_cast<LogicValue>(sim_value_);
|
|
||||||
return value == LogicValue::zero
|
|
||||||
|| value == LogicValue::one;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Vertex::setIsDisabledConstraint(bool disabled)
|
|
||||||
{
|
|
||||||
is_disabled_constraint_ = disabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -1187,18 +1150,6 @@ Vertex::setIsCheckClk(bool is_check_clk)
|
||||||
is_check_clk_ = is_check_clk;
|
is_check_clk_ = is_check_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Vertex::setIsGatedClkEnable(bool enable)
|
|
||||||
{
|
|
||||||
is_gated_clk_enable_ = enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Vertex::setIsConstrained(bool constrained)
|
|
||||||
{
|
|
||||||
is_constrained_ = constrained;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Vertex::setHasDownstreamClkPin(bool has_clk_pin)
|
Vertex::setHasDownstreamClkPin(bool has_clk_pin)
|
||||||
{
|
{
|
||||||
|
|
@ -1251,10 +1202,9 @@ Edge::init(VertexId from,
|
||||||
arc_delay_annotated_is_bits_ = true;
|
arc_delay_annotated_is_bits_ = true;
|
||||||
arc_delay_annotated_.bits_ = 0;
|
arc_delay_annotated_.bits_ = 0;
|
||||||
delay_annotation_is_incremental_ = false;
|
delay_annotation_is_incremental_ = false;
|
||||||
sim_timing_sense_ = unsigned(TimingSense::unknown);
|
|
||||||
is_disabled_constraint_ = false;
|
|
||||||
is_disabled_cond_ = false;
|
|
||||||
is_disabled_loop_ = false;
|
is_disabled_loop_ = false;
|
||||||
|
has_sim_sense_ = false;
|
||||||
|
has_disabled_cond_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Edge::~Edge()
|
Edge::~Edge()
|
||||||
|
|
@ -1384,48 +1334,6 @@ Edge::sense() const
|
||||||
return arc_set_->sense();
|
return arc_set_->sense();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TimingSense
|
|
||||||
Edge::simTimingSense() const
|
|
||||||
{
|
|
||||||
return static_cast<TimingSense>(sim_timing_sense_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Edge::setSimTimingSense(TimingSense sense)
|
|
||||||
{
|
|
||||||
sim_timing_sense_ = unsigned(sense);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Edge::isDisabledConstraint() const
|
|
||||||
{
|
|
||||||
const TimingRole *role = arc_set_->role();
|
|
||||||
bool is_wire = role->isWire();
|
|
||||||
return is_disabled_constraint_
|
|
||||||
|| arc_set_->isDisabledConstraint()
|
|
||||||
// set_disable_timing cell does not disable timing checks.
|
|
||||||
|| (!(role->isTimingCheck() || is_wire)
|
|
||||||
&& arc_set_->libertyCell()->isDisabledConstraint())
|
|
||||||
|| (!is_wire
|
|
||||||
&& arc_set_->from()->isDisabledConstraint())
|
|
||||||
|| (!is_wire
|
|
||||||
&& arc_set_->to()->isDisabledConstraint());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Edge::setIsDisabledConstraint(bool disabled)
|
|
||||||
{
|
|
||||||
is_disabled_constraint_ = disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Edge::setIsDisabledCond(bool disabled)
|
|
||||||
{
|
|
||||||
is_disabled_cond_ = disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Edge::setIsDisabledLoop(bool disabled)
|
Edge::setIsDisabledLoop(bool disabled)
|
||||||
{
|
{
|
||||||
|
|
@ -1444,6 +1352,18 @@ Edge::setIsBidirectNetPath(bool is_bidir)
|
||||||
is_bidirect_net_path_ = is_bidir;
|
is_bidirect_net_path_ = is_bidir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Edge::setHasSimSense(bool has_sense)
|
||||||
|
{
|
||||||
|
has_sim_sense_ = has_sense;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Edge::setHasDisabledCond(bool has_disabled)
|
||||||
|
{
|
||||||
|
has_disabled_cond_ = has_disabled;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
VertexIterator::VertexIterator(Graph *graph) :
|
VertexIterator::VertexIterator(Graph *graph) :
|
||||||
|
|
@ -1483,7 +1403,7 @@ VertexIterator::findNextPin()
|
||||||
Pin *pin = pin_iter_->next();
|
Pin *pin = pin_iter_->next();
|
||||||
vertex_ = graph_->vertex(network_->vertexId(pin));
|
vertex_ = graph_->vertex(network_->vertexId(pin));
|
||||||
bidir_vertex_ = network_->direction(pin)->isBidirect()
|
bidir_vertex_ = network_->direction(pin)->isBidirect()
|
||||||
? graph_->pin_bidirect_drvr_vertex_map_.findKey(pin)
|
? findKey(graph_->pin_bidirect_drvr_vertex_map_, pin)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
if (vertex_ || bidir_vertex_)
|
if (vertex_ || bidir_vertex_)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1600,7 +1520,19 @@ EdgesThruHierPinIterator::EdgesThruHierPinIterator(const Pin *hpin,
|
||||||
{
|
{
|
||||||
FindEdgesThruHierPinVisitor visitor(edges_, graph);
|
FindEdgesThruHierPinVisitor visitor(edges_, graph);
|
||||||
visitDrvrLoadsThruHierPin(hpin, network, &visitor);
|
visitDrvrLoadsThruHierPin(hpin, network, &visitor);
|
||||||
edge_iter_.init(edges_);
|
edge_iter_ = edges_.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
EdgesThruHierPinIterator::hasNext()
|
||||||
|
{
|
||||||
|
return edge_iter_ != edges_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
Edge *
|
||||||
|
EdgesThruHierPinIterator::next()
|
||||||
|
{
|
||||||
|
return *edge_iter_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -1617,9 +1549,5 @@ VertexIdLess::operator()(const Vertex *vertex1,
|
||||||
return graph_->id(vertex1) < graph_->id(vertex2);
|
return graph_->id(vertex1) < graph_->id(vertex2);
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexSet::VertexSet(Graph *&graph) :
|
|
||||||
Set<Vertex*, VertexIdLess>(VertexIdLess(graph))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
229
graph/Graph.i
229
graph/Graph.i
|
|
@ -31,8 +31,9 @@
|
||||||
#include "Liberty.hh"
|
#include "Liberty.hh"
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "Clock.hh"
|
#include "Clock.hh"
|
||||||
#include "Corner.hh"
|
#include "Scene.hh"
|
||||||
#include "Search.hh"
|
#include "Search.hh"
|
||||||
|
#include "Sdc.hh"
|
||||||
#include "Sta.hh"
|
#include "Sta.hh"
|
||||||
|
|
||||||
using namespace sta;
|
using namespace sta;
|
||||||
|
|
@ -93,21 +94,21 @@ vertex_iterator()
|
||||||
void
|
void
|
||||||
set_arc_delay(Edge *edge,
|
set_arc_delay(Edge *edge,
|
||||||
TimingArc *arc,
|
TimingArc *arc,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
float delay)
|
float delay)
|
||||||
{
|
{
|
||||||
Sta::sta()->setArcDelay(edge, arc, corner, min_max, delay);
|
Sta::sta()->setArcDelay(edge, arc, scene, min_max, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_annotated_slew(Vertex *vertex,
|
set_annotated_slew(Vertex *vertex,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
const RiseFallBoth *rf,
|
const RiseFallBoth *rf,
|
||||||
float slew)
|
float slew)
|
||||||
{
|
{
|
||||||
Sta::sta()->setAnnotatedSlew(vertex, corner, min_max, rf, slew);
|
Sta::sta()->setAnnotatedSlew(vertex, scene, min_max, rf, slew);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all delay and slew annotations.
|
// Remove all delay and slew annotations.
|
||||||
|
|
@ -132,20 +133,20 @@ int level() { return Sta::sta()->vertexLevel(self); }
|
||||||
int tag_group_index() { return self->tagGroupIndex(); }
|
int tag_group_index() { return self->tagGroupIndex(); }
|
||||||
|
|
||||||
Slew
|
Slew
|
||||||
slew(const RiseFall *rf,
|
slew(const RiseFallBoth *rf,
|
||||||
const MinMax *min_max)
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
Sta *sta = Sta::sta();
|
Sta *sta = Sta::sta();
|
||||||
return sta->vertexSlew(self, rf, min_max);
|
return sta->slew(self, rf, sta->scenes(), min_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
Slew
|
Slew
|
||||||
slew_corner(const RiseFall *rf,
|
slew_scenes(const RiseFallBoth *rf,
|
||||||
const Corner *corner,
|
const SceneSeq scenes,
|
||||||
const MinMax *min_max)
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
Sta *sta = Sta::sta();
|
Sta *sta = Sta::sta();
|
||||||
return sta->vertexSlew(self, rf, corner, min_max);
|
return sta->slew(self, rf, scenes, min_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexOutEdgeIterator *
|
VertexOutEdgeIterator *
|
||||||
|
|
@ -160,162 +161,13 @@ in_edge_iterator()
|
||||||
return new VertexInEdgeIterator(self, Sta::sta()->graph());
|
return new VertexInEdgeIterator(self, Sta::sta()->graph());
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatSeq
|
|
||||||
arrivals_clk(const RiseFall *rf,
|
|
||||||
Clock *clk,
|
|
||||||
const RiseFall *clk_rf)
|
|
||||||
{
|
|
||||||
Sta *sta = Sta::sta();
|
|
||||||
FloatSeq arrivals;
|
|
||||||
const ClockEdge *clk_edge = nullptr;
|
|
||||||
if (clk)
|
|
||||||
clk_edge = clk->edge(clk_rf);
|
|
||||||
for (auto path_ap : sta->corners()->pathAnalysisPts()) {
|
|
||||||
arrivals.push_back(delayAsFloat(sta->vertexArrival(self, rf, clk_edge,
|
|
||||||
path_ap, nullptr)));
|
|
||||||
}
|
|
||||||
return arrivals;
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
|
||||||
arrival(const MinMax *min_max)
|
|
||||||
{
|
|
||||||
Sta *sta = Sta::sta();
|
|
||||||
return delayAsFloat(sta->vertexArrival(self, min_max));
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSeq
|
|
||||||
arrivals_clk_delays(const RiseFall *rf,
|
|
||||||
Clock *clk,
|
|
||||||
const RiseFall *clk_rf,
|
|
||||||
int digits)
|
|
||||||
{
|
|
||||||
Sta *sta = Sta::sta();
|
|
||||||
StringSeq arrivals;
|
|
||||||
const ClockEdge *clk_edge = nullptr;
|
|
||||||
if (clk)
|
|
||||||
clk_edge = clk->edge(clk_rf);
|
|
||||||
for (auto path_ap : sta->corners()->pathAnalysisPts()) {
|
|
||||||
arrivals.push_back(delayAsString(sta->vertexArrival(self, rf, clk_edge,
|
|
||||||
path_ap, nullptr),
|
|
||||||
sta, digits));
|
|
||||||
}
|
|
||||||
return arrivals;
|
|
||||||
}
|
|
||||||
|
|
||||||
FloatSeq
|
|
||||||
requireds_clk(const RiseFall *rf,
|
|
||||||
Clock *clk,
|
|
||||||
const RiseFall *clk_rf)
|
|
||||||
{
|
|
||||||
Sta *sta = Sta::sta();
|
|
||||||
FloatSeq reqs;
|
|
||||||
const ClockEdge *clk_edge = nullptr;
|
|
||||||
if (clk)
|
|
||||||
clk_edge = clk->edge(clk_rf);
|
|
||||||
for (auto path_ap : sta->corners()->pathAnalysisPts()) {
|
|
||||||
reqs.push_back(delayAsFloat(sta->vertexRequired(self, rf, clk_edge,
|
|
||||||
path_ap)));
|
|
||||||
}
|
|
||||||
return reqs;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSeq
|
|
||||||
requireds_clk_delays(const RiseFall *rf,
|
|
||||||
Clock *clk,
|
|
||||||
const RiseFall *clk_rf,
|
|
||||||
int digits)
|
|
||||||
{
|
|
||||||
Sta *sta = Sta::sta();
|
|
||||||
StringSeq reqs;
|
|
||||||
const ClockEdge *clk_edge = nullptr;
|
|
||||||
if (clk)
|
|
||||||
clk_edge = clk->edge(clk_rf);
|
|
||||||
for (auto path_ap : sta->corners()->pathAnalysisPts()) {
|
|
||||||
reqs.push_back(delayAsString(sta->vertexRequired(self, rf, clk_edge, path_ap),
|
|
||||||
sta, digits));
|
|
||||||
}
|
|
||||||
return reqs;
|
|
||||||
}
|
|
||||||
|
|
||||||
Slack
|
|
||||||
slack(MinMax *min_max)
|
|
||||||
{
|
|
||||||
Sta *sta = Sta::sta();
|
|
||||||
return sta->vertexSlack(self, min_max);
|
|
||||||
}
|
|
||||||
|
|
||||||
FloatSeq
|
|
||||||
slacks(RiseFall *rf)
|
|
||||||
{
|
|
||||||
Sta *sta = Sta::sta();
|
|
||||||
FloatSeq slacks;
|
|
||||||
for (auto path_ap : sta->corners()->pathAnalysisPts()) {
|
|
||||||
slacks.push_back(delayAsFloat(sta->vertexSlack(self, rf, path_ap)));
|
|
||||||
}
|
|
||||||
return slacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Slack with respect to a clock rise/fall edge.
|
|
||||||
FloatSeq
|
|
||||||
slacks_clk(const RiseFall *rf,
|
|
||||||
Clock *clk,
|
|
||||||
const RiseFall *clk_rf)
|
|
||||||
{
|
|
||||||
Sta *sta = Sta::sta();
|
|
||||||
FloatSeq slacks;
|
|
||||||
const ClockEdge *clk_edge = nullptr;
|
|
||||||
if (clk)
|
|
||||||
clk_edge = clk->edge(clk_rf);
|
|
||||||
for (auto path_ap : sta->corners()->pathAnalysisPts()) {
|
|
||||||
slacks.push_back(delayAsFloat(sta->vertexSlack(self, rf, clk_edge,
|
|
||||||
path_ap)));
|
|
||||||
}
|
|
||||||
return slacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringSeq
|
|
||||||
slacks_clk_delays(const RiseFall *rf,
|
|
||||||
Clock *clk,
|
|
||||||
const RiseFall *clk_rf,
|
|
||||||
int digits)
|
|
||||||
{
|
|
||||||
Sta *sta = Sta::sta();
|
|
||||||
StringSeq slacks;
|
|
||||||
const ClockEdge *clk_edge = nullptr;
|
|
||||||
if (clk)
|
|
||||||
clk_edge = clk->edge(clk_rf);
|
|
||||||
for (auto path_ap : sta->corners()->pathAnalysisPts()) {
|
|
||||||
slacks.push_back(delayAsString(sta->vertexSlack(self, rf, clk_edge,
|
|
||||||
path_ap),
|
|
||||||
sta, digits));
|
|
||||||
}
|
|
||||||
return slacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
VertexPathIterator *
|
VertexPathIterator *
|
||||||
path_iterator(const RiseFall *rf,
|
path_iterator(const RiseFall *rf,
|
||||||
const MinMax *min_max)
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
return Sta::sta()->vertexPathIterator(self, rf, min_max);
|
return new VertexPathIterator(self, rf, min_max, Sta::sta());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
has_downstream_clk_pin()
|
|
||||||
{
|
|
||||||
return self->hasDownstreamClkPin();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
is_clock()
|
|
||||||
{
|
|
||||||
Sta *sta = Sta::sta();
|
|
||||||
Search *search = sta->search();
|
|
||||||
return search->isClock(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_disabled_constraint() { return self->isDisabledConstraint(); }
|
|
||||||
|
|
||||||
} // Vertex methods
|
} // Vertex methods
|
||||||
|
|
||||||
%extend Edge {
|
%extend Edge {
|
||||||
|
|
@ -328,28 +180,51 @@ const char *sense() { return to_string(self->sense()); }
|
||||||
TimingArcSeq &
|
TimingArcSeq &
|
||||||
timing_arcs() { return self->timingArcSet()->arcs(); }
|
timing_arcs() { return self->timingArcSet()->arcs(); }
|
||||||
bool is_disabled_loop() { return Sta::sta()->isDisabledLoop(self); }
|
bool is_disabled_loop() { return Sta::sta()->isDisabledLoop(self); }
|
||||||
bool is_disabled_constraint() { return Sta::sta()->isDisabledConstraint(self);}
|
|
||||||
bool is_disabled_constant() { return Sta::sta()->isDisabledConstant(self); }
|
bool is_disabled_constraint()
|
||||||
|
{
|
||||||
|
Sta *sta = Sta::sta();
|
||||||
|
const Sdc *sdc = sta->cmdSdc();
|
||||||
|
return sta->isDisabledConstraint(self, sdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_disabled_constant()
|
||||||
|
{
|
||||||
|
Sta *sta = Sta::sta();
|
||||||
|
const Mode *mode = sta->cmdMode();
|
||||||
|
return sta->isDisabledConstant(self, mode);
|
||||||
|
}
|
||||||
|
|
||||||
bool is_disabled_cond_default()
|
bool is_disabled_cond_default()
|
||||||
{ return Sta::sta()->isDisabledCondDefault(self); }
|
{ return Sta::sta()->isDisabledCondDefault(self); }
|
||||||
|
|
||||||
PinSet
|
PinSet
|
||||||
disabled_constant_pins() { return Sta::sta()->disabledConstantPins(self); }
|
disabled_constant_pins()
|
||||||
|
{
|
||||||
|
Sta *sta = Sta::sta();
|
||||||
|
const Mode *mode = sta->cmdMode();
|
||||||
|
return sta->disabledConstantPins(self, mode);
|
||||||
|
}
|
||||||
|
|
||||||
bool is_disabled_bidirect_inst_path()
|
bool is_disabled_bidirect_inst_path()
|
||||||
{ return Sta::sta()->isDisabledBidirectInstPath(self); }
|
{ return Sta::sta()->isDisabledBidirectInstPath(self); }
|
||||||
bool is_disabled_bidirect_net_path()
|
|
||||||
{ return Sta::sta()->isDisabledBidirectNetPath(self); }
|
|
||||||
bool is_disabled_preset_clear()
|
bool is_disabled_preset_clear()
|
||||||
{ return Sta::sta()->isDisabledPresetClr(self); }
|
{ return Sta::sta()->isDisabledPresetClr(self); }
|
||||||
const char *
|
const char *
|
||||||
sim_timing_sense(){return to_string(Sta::sta()->simTimingSense(self));}
|
sim_timing_sense(){
|
||||||
|
Sta *sta = Sta::sta();
|
||||||
|
const Mode *mode = sta->cmdMode();
|
||||||
|
return to_string(sta->simTimingSense(self, mode));
|
||||||
|
}
|
||||||
|
|
||||||
FloatSeq
|
FloatSeq
|
||||||
arc_delays(TimingArc *arc)
|
arc_delays(TimingArc *arc)
|
||||||
{
|
{
|
||||||
Sta *sta = Sta::sta();
|
Sta *sta = Sta::sta();
|
||||||
FloatSeq delays;
|
FloatSeq delays;
|
||||||
for (auto dcalc_ap : sta->corners()->dcalcAnalysisPts())
|
DcalcAPIndex ap_count = sta->dcalcAnalysisPtCount();
|
||||||
delays.push_back(delayAsFloat(sta->arcDelay(self, arc, dcalc_ap)));
|
for (DcalcAPIndex ap_index = 0; ap_index < ap_count; ap_index++)
|
||||||
|
delays.push_back(delayAsFloat(sta->arcDelay(self, arc, ap_index)));
|
||||||
return delays;
|
return delays;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -359,31 +234,31 @@ arc_delay_strings(TimingArc *arc,
|
||||||
{
|
{
|
||||||
Sta *sta = Sta::sta();
|
Sta *sta = Sta::sta();
|
||||||
StringSeq delays;
|
StringSeq delays;
|
||||||
for (auto dcalc_ap : sta->corners()->dcalcAnalysisPts())
|
DcalcAPIndex ap_count = sta->dcalcAnalysisPtCount();
|
||||||
delays.push_back(delayAsString(sta->arcDelay(self, arc, dcalc_ap),
|
for (DcalcAPIndex ap_index = 0; ap_index < ap_count; ap_index++)
|
||||||
|
delays.push_back(delayAsString(sta->arcDelay(self, arc, ap_index),
|
||||||
sta, digits));
|
sta, digits));
|
||||||
return delays;
|
return delays;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
delay_annotated(TimingArc *arc,
|
delay_annotated(TimingArc *arc,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *min_max)
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
return Sta::sta()->arcDelayAnnotated(self, arc, scene, min_max);
|
||||||
return Sta::sta()->arcDelayAnnotated(self, arc, dcalc_ap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
arc_delay(TimingArc *arc,
|
arc_delay(TimingArc *arc,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *min_max)
|
const MinMax *min_max)
|
||||||
{
|
{
|
||||||
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max);
|
||||||
return delayAsFloat(Sta::sta()->arcDelay(self, arc, dcalc_ap));
|
return delayAsFloat(Sta::sta()->arcDelay(self, arc, ap_index));
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
std::string
|
||||||
cond()
|
cond()
|
||||||
{
|
{
|
||||||
FuncExpr *cond = self->timingArcSet()->cond();
|
FuncExpr *cond = self->timingArcSet()->cond();
|
||||||
|
|
|
||||||
|
|
@ -180,10 +180,6 @@ proc edge_disable_reason { edge } {
|
||||||
if { $disables != "" } { append disables ", " }
|
if { $disables != "" } { append disables ", " }
|
||||||
append disables "bidirect instance path"
|
append disables "bidirect instance path"
|
||||||
}
|
}
|
||||||
if [$edge is_disabled_bidirect_net_path] {
|
|
||||||
if { $disables != "" } { append disables ", " }
|
|
||||||
append disables "bidirect net path"
|
|
||||||
}
|
|
||||||
if { [$edge is_disabled_preset_clear] } {
|
if { [$edge is_disabled_preset_clear] } {
|
||||||
if { $disables != "" } { append disables ", " }
|
if { $disables != "" } { append disables ", " }
|
||||||
append disables "sta_preset_clear_arcs_enabled"
|
append disables "sta_preset_clear_arcs_enabled"
|
||||||
|
|
@ -295,28 +291,6 @@ proc edge_disable_reason_verbose { edge } {
|
||||||
return $disables
|
return $disables
|
||||||
}
|
}
|
||||||
|
|
||||||
################################################################
|
|
||||||
|
|
||||||
define_cmd_args "report_slews" {[-corner corner] pin}
|
|
||||||
|
|
||||||
proc report_slews { args } {
|
|
||||||
global sta_report_default_digits
|
|
||||||
|
|
||||||
parse_key_args "report_slews" args keys {-corner} flags {}
|
|
||||||
check_argc_eq1 "report_slews" $args
|
|
||||||
|
|
||||||
set corner [parse_corner_or_all keys]
|
|
||||||
set pin [get_port_pin_error "pin" [lindex $args 0]]
|
|
||||||
set digits $sta_report_default_digits
|
|
||||||
foreach vertex [$pin vertices] {
|
|
||||||
if { $corner == "NULL" } {
|
|
||||||
report_line "[vertex_path_name $vertex] [rise_short_name] [format_time [$vertex slew rise min] $digits]:[format_time [$vertex slew rise max] $digits] [fall_short_name] [format_time [$vertex slew fall min] $digits]:[format_time [$vertex slew fall max] $digits]"
|
|
||||||
} else {
|
|
||||||
report_line "[vertex_path_name $vertex] [rise_short_name] [format_time [$vertex slew_corner rise $corner min] $digits]:[format_time [$vertex slew_corner rise $corner max] $digits] [fall_short_name] [format_time [$vertex slew_corner fall $corner min] $digits]:[format_time [$vertex slew_corner fall $corner max] $digits]"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proc vertex_path_name { vertex } {
|
proc vertex_path_name { vertex } {
|
||||||
set pin [$vertex pin]
|
set pin [$vertex pin]
|
||||||
set pin_name [get_full_name $pin]
|
set pin_name [get_full_name $pin]
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
//
|
//
|
||||||
// This notice may not be removed or altered from any source distribution.
|
// This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
#include "ContainerHelpers.hh"
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "NetworkCmp.hh"
|
#include "NetworkCmp.hh"
|
||||||
|
|
|
||||||
|
|
@ -40,17 +40,16 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
class Corner;
|
class Scene;
|
||||||
class Parasitic;
|
class Parasitic;
|
||||||
class DcalcAnalysisPt;
|
|
||||||
class MultiDrvrNet;
|
class MultiDrvrNet;
|
||||||
class ArcDcalcArg;
|
class ArcDcalcArg;
|
||||||
|
|
||||||
typedef std::vector<ArcDcalcArg*> ArcDcalcArgPtrSeq;
|
using ArcDcalcArgPtrSeq = std::vector<ArcDcalcArg*>;
|
||||||
typedef std::vector<ArcDcalcArg> ArcDcalcArgSeq;
|
using ArcDcalcArgSeq = std::vector<ArcDcalcArg>;
|
||||||
|
|
||||||
// Driver load pin -> index in driver loads.
|
// Driver load pin -> index in driver loads.
|
||||||
typedef std::map<const Pin *, size_t, PinIdLess> LoadPinIndexMap;
|
using LoadPinIndexMap = std::map<const Pin *, size_t, PinIdLess>;
|
||||||
|
|
||||||
// Arguments for gate delay calculation delay/slew at one driver pin
|
// Arguments for gate delay calculation delay/slew at one driver pin
|
||||||
// through one timing arc at one delay calc analysis point.
|
// through one timing arc at one delay calc analysis point.
|
||||||
|
|
@ -81,7 +80,7 @@ public:
|
||||||
const Net *drvrNet(const Network *network) const;
|
const Net *drvrNet(const Network *network) const;
|
||||||
Edge *edge() const { return edge_; }
|
Edge *edge() const { return edge_; }
|
||||||
const TimingArc *arc() const { return arc_; }
|
const TimingArc *arc() const { return arc_; }
|
||||||
Slew inSlew() const { return in_slew_; }
|
const Slew &inSlew() const { return in_slew_; }
|
||||||
float inSlewFlt() const;
|
float inSlewFlt() const;
|
||||||
void setInSlew(Slew in_slew);
|
void setInSlew(Slew in_slew);
|
||||||
const Parasitic *parasitic() const { return parasitic_; }
|
const Parasitic *parasitic() const { return parasitic_; }
|
||||||
|
|
@ -138,8 +137,7 @@ protected:
|
||||||
std::vector<Slew> load_slews_;
|
std::vector<Slew> load_slews_;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<ArcDcalcArg> ArcDcalcArgSeq;
|
using ArcDcalcResultSeq = std::vector<ArcDcalcResult>;
|
||||||
typedef std::vector<ArcDcalcResult> ArcDcalcResultSeq;
|
|
||||||
|
|
||||||
// Delay calculator class hierarchy.
|
// Delay calculator class hierarchy.
|
||||||
// ArcDelayCalc
|
// ArcDelayCalc
|
||||||
|
|
@ -160,7 +158,7 @@ typedef std::vector<ArcDcalcResult> ArcDcalcResultSeq;
|
||||||
class ArcDelayCalc : public StaState
|
class ArcDelayCalc : public StaState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ArcDelayCalc(StaState *sta);
|
ArcDelayCalc(StaState *sta);
|
||||||
virtual ~ArcDelayCalc() {}
|
virtual ~ArcDelayCalc() {}
|
||||||
virtual ArcDelayCalc *copy() = 0;
|
virtual ArcDelayCalc *copy() = 0;
|
||||||
virtual const char *name() const = 0;
|
virtual const char *name() const = 0;
|
||||||
|
|
@ -169,25 +167,29 @@ public:
|
||||||
// calculator by probing parasitics_.
|
// calculator by probing parasitics_.
|
||||||
virtual Parasitic *findParasitic(const Pin *drvr_pin,
|
virtual Parasitic *findParasitic(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) = 0;
|
||||||
virtual bool reduceSupported() const = 0;
|
virtual bool reduceSupported() const = 0;
|
||||||
// Reduce parasitic_network to a representation acceptable to the delay calculator.
|
// Reduce parasitic_network to a representation acceptable to the delay calculator.
|
||||||
virtual Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
virtual Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) = 0;
|
||||||
// Reduce parasitic_network to a representation acceptable to the delay calculator
|
// Reduce parasitic_network to a representation acceptable to the delay calculator
|
||||||
// for one or more corners and min/max rise/fall.
|
// for one or more scenes and min/max rise/fall.
|
||||||
// Null corner means reduce all corners.
|
// Null scene means reduce all scenes.
|
||||||
virtual void reduceParasitic(const Parasitic *parasitic_network,
|
virtual void reduceParasitic(const Parasitic *parasitic_network,
|
||||||
const Net *net,
|
const Net *net,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMaxAll *min_max) = 0;
|
const MinMaxAll *min_max) = 0;
|
||||||
// Set the in_slew, load_cap, parasitic for gates.
|
// Set the in_slew, load_cap, parasitic for gates.
|
||||||
virtual void setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
virtual void setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
||||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) = 0;
|
||||||
virtual void setDcalcArgParasiticSlew(ArcDcalcArgSeq &gates,
|
virtual void setDcalcArgParasiticSlew(ArcDcalcArgSeq &gates,
|
||||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) = 0;
|
||||||
// Find the wire delays and slews for an input port without a driving cell.
|
// Find the wire delays and slews for an input port without a driving cell.
|
||||||
// This call primarily initializes the load delay/slew iterator.
|
// This call primarily initializes the load delay/slew iterator.
|
||||||
virtual ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
virtual ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||||
|
|
@ -195,7 +197,8 @@ public:
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) = 0;
|
||||||
|
|
||||||
// Find the delay and slew for arc driving drvr_pin.
|
// Find the delay and slew for arc driving drvr_pin.
|
||||||
virtual ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
virtual ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
||||||
|
|
@ -205,7 +208,8 @@ public:
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) = 0;
|
||||||
// deprecated 2024-02-27
|
// deprecated 2024-02-27
|
||||||
virtual void gateDelay(const TimingArc *arc,
|
virtual void gateDelay(const TimingArc *arc,
|
||||||
const Slew &in_slew,
|
const Slew &in_slew,
|
||||||
|
|
@ -213,7 +217,8 @@ public:
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
float related_out_cap,
|
float related_out_cap,
|
||||||
const Pvt *pvt,
|
const Pvt *pvt,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
// Return values.
|
// Return values.
|
||||||
ArcDelay &gate_delay,
|
ArcDelay &gate_delay,
|
||||||
Slew &drvr_slew) __attribute__ ((deprecated));
|
Slew &drvr_slew) __attribute__ ((deprecated));
|
||||||
|
|
@ -221,7 +226,8 @@ public:
|
||||||
// Find gate delays and slews for parallel gates.
|
// Find gate delays and slews for parallel gates.
|
||||||
virtual ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &args,
|
virtual ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &args,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) = 0;
|
||||||
|
|
||||||
// Find the delay for a timing check arc given the arc's
|
// Find the delay for a timing check arc given the arc's
|
||||||
// from/clock, to/data slews and related output pin parasitic.
|
// from/clock, to/data slews and related output pin parasitic.
|
||||||
|
|
@ -230,7 +236,8 @@ public:
|
||||||
const Slew &from_slew,
|
const Slew &from_slew,
|
||||||
const Slew &to_slew,
|
const Slew &to_slew,
|
||||||
float related_out_cap,
|
float related_out_cap,
|
||||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) = 0;
|
||||||
// Report delay and slew calculation.
|
// Report delay and slew calculation.
|
||||||
virtual std::string reportGateDelay(const Pin *drvr_pin,
|
virtual std::string reportGateDelay(const Pin *drvr_pin,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
|
|
@ -238,7 +245,8 @@ public:
|
||||||
float load_cap,
|
float load_cap,
|
||||||
const Parasitic *parasitic,
|
const Parasitic *parasitic,
|
||||||
const LoadPinIndexMap &load_pin_index_map,
|
const LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits) = 0;
|
int digits) = 0;
|
||||||
// Report timing check delay calculation.
|
// Report timing check delay calculation.
|
||||||
virtual std::string reportCheckDelay(const Pin *check_pin,
|
virtual std::string reportCheckDelay(const Pin *check_pin,
|
||||||
|
|
@ -247,7 +255,8 @@ public:
|
||||||
const char *from_slew_annotation,
|
const char *from_slew_annotation,
|
||||||
const Slew &to_slew,
|
const Slew &to_slew,
|
||||||
float related_out_cap,
|
float related_out_cap,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
int digits) = 0;
|
int digits) = 0;
|
||||||
virtual void finishDrvrPin() = 0;
|
virtual void finishDrvrPin() = 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ struct DdManager;
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef std::map<const LibertyPort*, DdNode*, LibertyPortLess> BddPortVarMap;
|
using BddPortVarMap = std::map<const LibertyPort*, DdNode*, LibertyPortLess>;
|
||||||
typedef std::map<unsigned, const LibertyPort*> BddVarIdxPortMap;
|
using BddVarIdxPortMap = std::map<unsigned, const LibertyPort*>;
|
||||||
|
|
||||||
class Bdd : public StaState
|
class Bdd : public StaState
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Iterator.hh"
|
#include "Iterator.hh"
|
||||||
#include "Set.hh"
|
|
||||||
#include "GraphClass.hh"
|
#include "GraphClass.hh"
|
||||||
#include "VertexVisitor.hh"
|
#include "VertexVisitor.hh"
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
|
|
@ -39,7 +39,7 @@ class BfsFwdIterator;
|
||||||
class BfsBkwdIterator;
|
class BfsBkwdIterator;
|
||||||
|
|
||||||
// LevelQueue is a vector of vertex vectors indexed by logic level.
|
// LevelQueue is a vector of vertex vectors indexed by logic level.
|
||||||
typedef Vector<VertexSeq> LevelQueue;
|
using LevelQueue = std::vector<VertexSeq>;
|
||||||
|
|
||||||
// Abstract base class for forward and backward breadth first search iterators.
|
// Abstract base class for forward and backward breadth first search iterators.
|
||||||
// Visit all of the vertices at a level before moving to the next.
|
// Visit all of the vertices at a level before moving to the next.
|
||||||
|
|
@ -58,19 +58,19 @@ public:
|
||||||
void ensureSize();
|
void ensureSize();
|
||||||
// Reset to virgin state.
|
// Reset to virgin state.
|
||||||
void clear();
|
void clear();
|
||||||
bool empty() const;
|
[[nodiscard]] bool empty() const;
|
||||||
// Enqueue a vertex to search from.
|
// Enqueue a vertex to search from.
|
||||||
void enqueue(Vertex *vertex);
|
void enqueue(Vertex *vertex);
|
||||||
// Enqueue vertices adjacent to a vertex.
|
// Enqueue vertices adjacent to a vertex.
|
||||||
void enqueueAdjacentVertices(Vertex *vertex);
|
void enqueueAdjacentVertices(Vertex *vertex);
|
||||||
void enqueueAdjacentVertices(Vertex *vertex,
|
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||||
SearchPred *search_pred);
|
const Mode *mode);
|
||||||
void enqueueAdjacentVertices(Vertex *vertex,
|
|
||||||
Level to_level);
|
|
||||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||||
SearchPred *search_pred,
|
SearchPred *search_pred,
|
||||||
Level to_level) = 0;
|
const Mode *mode) = 0;
|
||||||
bool inQueue(Vertex *vertex);
|
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||||
|
SearchPred *search_pred) = 0;
|
||||||
|
[[nodiscard]] bool inQueue(Vertex *vertex);
|
||||||
void checkInQueue(Vertex *vertex);
|
void checkInQueue(Vertex *vertex);
|
||||||
// Notify iterator that vertex will be deleted.
|
// Notify iterator that vertex will be deleted.
|
||||||
void deleteVertexBefore(Vertex *vertex);
|
void deleteVertexBefore(Vertex *vertex);
|
||||||
|
|
@ -131,9 +131,11 @@ public:
|
||||||
SearchPred *search_pred,
|
SearchPred *search_pred,
|
||||||
StaState *sta);
|
StaState *sta);
|
||||||
virtual ~BfsFwdIterator();
|
virtual ~BfsFwdIterator();
|
||||||
|
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||||
|
SearchPred *search_pred);
|
||||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||||
SearchPred *search_pred,
|
SearchPred *search_pred,
|
||||||
Level to_level);
|
const Mode *mode);
|
||||||
using BfsIterator::enqueueAdjacentVertices;
|
using BfsIterator::enqueueAdjacentVertices;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -151,9 +153,11 @@ public:
|
||||||
SearchPred *search_pred,
|
SearchPred *search_pred,
|
||||||
StaState *sta);
|
StaState *sta);
|
||||||
virtual ~BfsBkwdIterator();
|
virtual ~BfsBkwdIterator();
|
||||||
|
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||||
|
SearchPred *search_pred);
|
||||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||||
SearchPred *search_pred,
|
SearchPred *search_pred,
|
||||||
Level to_level);
|
const Mode *mode);
|
||||||
using BfsIterator::enqueueAdjacentVertices;
|
using BfsIterator::enqueueAdjacentVertices;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,256 @@
|
||||||
|
// 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 <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
// BoundedHeap: A container that maintains the top N elements using a min-heap.
|
||||||
|
// This provides O(log n) insertion when the heap is full, O(1) when not full,
|
||||||
|
// and O(n log n) extraction of all elements. Useful for maintaining top K
|
||||||
|
// elements without storing all elements.
|
||||||
|
//
|
||||||
|
// The heap maintains the "worst" (minimum according to Compare) element at
|
||||||
|
// the root, so new elements that are better than the worst can replace it.
|
||||||
|
// For example, with Compare = std::greater<int>, this maintains the N largest
|
||||||
|
// values (greater values are "better").
|
||||||
|
//
|
||||||
|
// Template parameters:
|
||||||
|
// T: The element type
|
||||||
|
// Compare: Comparison function object type (default: std::less<T>)
|
||||||
|
// For top N largest, use std::greater<T>
|
||||||
|
// For top N smallest, use std::less<T>
|
||||||
|
template <typename T, typename Compare = std::less<T>>
|
||||||
|
class BoundedHeap {
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using size_type = size_t;
|
||||||
|
using const_reference = const T&;
|
||||||
|
using compare_type = Compare;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
explicit BoundedHeap(size_type max_size,
|
||||||
|
const Compare& comp = Compare()) :
|
||||||
|
max_size_(max_size),
|
||||||
|
comp_(comp),
|
||||||
|
min_heap_comp_(comp)
|
||||||
|
{
|
||||||
|
heap_.reserve(max_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy constructor
|
||||||
|
BoundedHeap(const BoundedHeap& other) :
|
||||||
|
heap_(other.heap_),
|
||||||
|
max_size_(other.max_size_),
|
||||||
|
comp_(other.comp_),
|
||||||
|
min_heap_comp_(other.comp_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Assignment operator
|
||||||
|
BoundedHeap& operator=(const BoundedHeap& other)
|
||||||
|
{
|
||||||
|
if (this != &other) {
|
||||||
|
heap_ = other.heap_;
|
||||||
|
max_size_ = other.max_size_;
|
||||||
|
comp_ = other.comp_;
|
||||||
|
min_heap_comp_ = MinHeapCompare(other.comp_);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move constructor
|
||||||
|
BoundedHeap(BoundedHeap&& other) noexcept :
|
||||||
|
heap_(std::move(other.heap_)),
|
||||||
|
max_size_(other.max_size_),
|
||||||
|
comp_(std::move(other.comp_)),
|
||||||
|
min_heap_comp_(comp_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Move assignment operator
|
||||||
|
BoundedHeap& operator=(BoundedHeap&& other) noexcept
|
||||||
|
{
|
||||||
|
if (this != &other) {
|
||||||
|
heap_ = std::move(other.heap_);
|
||||||
|
max_size_ = other.max_size_;
|
||||||
|
comp_ = std::move(other.comp_);
|
||||||
|
min_heap_comp_ = MinHeapCompare(comp_);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setMaxSize(size_t max_size)
|
||||||
|
{
|
||||||
|
max_size_ = max_size;
|
||||||
|
heap_.reserve(max_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert an element into the heap.
|
||||||
|
// If the heap is not full, the element is added.
|
||||||
|
// If the heap is full and the new element is better than the worst element,
|
||||||
|
// the worst element is replaced. Otherwise, the element is ignored.
|
||||||
|
// Returns true if the element was inserted, false if it was ignored.
|
||||||
|
bool
|
||||||
|
insert(const T& value) {
|
||||||
|
if (heap_.size() < max_size_) {
|
||||||
|
heap_.push_back(value);
|
||||||
|
std::push_heap(heap_.begin(), heap_.end(), min_heap_comp_);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (!heap_.empty()) {
|
||||||
|
// When keeping N worst (smallest) values: if new value is smaller than worst,
|
||||||
|
// we should keep it and remove the largest element to make room.
|
||||||
|
// If new value is larger than worst, we reject it (already have worse values).
|
||||||
|
// comp_(value, worst) is true when value < worst (value is smaller/worse)
|
||||||
|
if (comp_(value, heap_.front())) {
|
||||||
|
// New value is smaller than worst - find and replace the largest element
|
||||||
|
auto max_it = std::max_element(heap_.begin(), heap_.end(), comp_);
|
||||||
|
*max_it = value;
|
||||||
|
// Rebuild heap since we modified an internal element
|
||||||
|
std::make_heap(heap_.begin(), heap_.end(), min_heap_comp_);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Otherwise, new value is >= worst, so we already have worse values - reject it
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert an element using move semantics
|
||||||
|
bool insert(T&& value)
|
||||||
|
{
|
||||||
|
if (heap_.size() < max_size_) {
|
||||||
|
heap_.push_back(std::move(value));
|
||||||
|
std::push_heap(heap_.begin(), heap_.end(), min_heap_comp_);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (!heap_.empty()) {
|
||||||
|
// When keeping N worst (smallest) values: if new value is smaller than worst,
|
||||||
|
// we should keep it and remove the largest element to make room.
|
||||||
|
// If new value is larger than worst, we reject it (already have worse values).
|
||||||
|
// comp_(value, worst) is true when value < worst (value is smaller/worse)
|
||||||
|
if (comp_(value, heap_.front())) {
|
||||||
|
// New value is smaller than worst - find and replace the largest element
|
||||||
|
auto max_it = std::max_element(heap_.begin(), heap_.end(), comp_);
|
||||||
|
*max_it = std::move(value);
|
||||||
|
// Rebuild heap since we modified an internal element
|
||||||
|
std::make_heap(heap_.begin(), heap_.end(), min_heap_comp_);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Otherwise, new value is >= worst, so we already have worse values - reject it
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract all elements sorted from best to worst.
|
||||||
|
// This destroys the heap structure but preserves the elements.
|
||||||
|
std::vector<T> extract()
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the worst element (the one that would be replaced next).
|
||||||
|
// Requires !empty()
|
||||||
|
const_reference worst() const
|
||||||
|
{
|
||||||
|
return heap_.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the heap is empty
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return heap_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current number of elements in the heap
|
||||||
|
size_type size() const
|
||||||
|
{
|
||||||
|
return heap_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the maximum size of the heap
|
||||||
|
size_type max_size() const
|
||||||
|
{
|
||||||
|
return max_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the heap is full
|
||||||
|
bool full() const
|
||||||
|
{
|
||||||
|
return heap_.size() >= max_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all elements from the heap
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
heap_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the comparison function
|
||||||
|
Compare compare() const
|
||||||
|
{
|
||||||
|
return comp_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<T> heap_;
|
||||||
|
size_type max_size_;
|
||||||
|
Compare comp_;
|
||||||
|
|
||||||
|
// Helper comparator for min-heap: we want the worst element at root
|
||||||
|
// so we can easily remove it when adding better elements.
|
||||||
|
// This is the inverse of the user's comparison.
|
||||||
|
struct MinHeapCompare
|
||||||
|
{
|
||||||
|
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
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MinHeapCompare min_heap_comp_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sta
|
||||||
|
|
||||||
|
|
@ -24,8 +24,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Map.hh"
|
#include <map>
|
||||||
#include "Set.hh"
|
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
#include "GraphClass.hh"
|
#include "GraphClass.hh"
|
||||||
|
|
@ -33,31 +33,34 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef Map<const Pin*, ClockSet> PinClksMap;
|
using PinClksMap = std::map<const Pin*, ClockSet>;
|
||||||
typedef Map<const Clock *, PinSet*> ClkPinsMap;
|
using ClkPinsMap = std::map<const Clock *, PinSet*>;
|
||||||
|
|
||||||
class Sta;
|
class Sta;
|
||||||
|
|
||||||
// Find clock network pins.
|
// Find clock network pins.
|
||||||
// This is not as reliable as Search::isClock but is much cheaper.
|
|
||||||
class ClkNetwork : public StaState
|
class ClkNetwork : public StaState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClkNetwork(StaState *sta);
|
ClkNetwork(Mode *mode,
|
||||||
|
StaState *sta);
|
||||||
~ClkNetwork();
|
~ClkNetwork();
|
||||||
void ensureClkNetwork();
|
void ensureClkNetwork();
|
||||||
void clear();
|
void clear();
|
||||||
bool isClock(const Pin *pin) const;
|
bool isClock(const Pin *pin) const;
|
||||||
|
bool isClock(const Vertex *vertex) const;
|
||||||
bool isClock(const Net *net) const;
|
bool isClock(const Net *net) const;
|
||||||
bool isIdealClock(const Pin *pin) const;
|
bool isIdealClock(const Pin *pin) const;
|
||||||
|
bool isIdealClock(const Vertex *vertex) const;
|
||||||
bool isPropagatedClock(const Pin *pin) const;
|
bool isPropagatedClock(const Pin *pin) const;
|
||||||
const ClockSet *clocks(const Pin *pin);
|
const ClockSet *clocks(const Pin *pin) const;
|
||||||
const ClockSet *idealClocks(const Pin *pin);
|
const ClockSet *clocks(const Vertex *vertex) const;
|
||||||
|
const ClockSet *idealClocks(const Pin *pin) const;
|
||||||
const PinSet *pins(const Clock *clk);
|
const PinSet *pins(const Clock *clk);
|
||||||
void clkPinsInvalid();
|
void clkPinsInvalid();
|
||||||
float idealClkSlew(const Pin *pin,
|
float idealClkSlew(const Pin *pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void deletePinBefore(const Pin *pin);
|
void deletePinBefore(const Pin *pin);
|
||||||
|
|
@ -66,6 +69,8 @@ protected:
|
||||||
friend class Sta;
|
friend class Sta;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Mode *mode_;
|
||||||
|
|
||||||
void findClkPins();
|
void findClkPins();
|
||||||
void findClkPins(bool ideal_only,
|
void findClkPins(bool ideal_only,
|
||||||
PinClksMap &clk_pin_map);
|
PinClksMap &clk_pin_map);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "MinMax.hh"
|
#include "MinMax.hh"
|
||||||
#include "RiseFallMinMax.hh"
|
#include "RiseFallMinMax.hh"
|
||||||
#include "SdcClass.hh"
|
#include "SdcClass.hh"
|
||||||
|
|
@ -32,7 +34,7 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef Map<Pin*, PinSet*> ClkHpinEdgeMap;
|
using ClkHpinEdgeMap = std::map<Pin*, PinSet*>;
|
||||||
|
|
||||||
class Clock : public SdcCmdComment
|
class Clock : public SdcCmdComment
|
||||||
{
|
{
|
||||||
|
|
@ -264,7 +266,7 @@ public:
|
||||||
const RiseFallBoth *tgt_rf,
|
const RiseFallBoth *tgt_rf,
|
||||||
const SetupHoldAll *setup_hold);
|
const SetupHoldAll *setup_hold);
|
||||||
const RiseFallMinMax *uncertainties(const RiseFall *src_rf) const;
|
const RiseFallMinMax *uncertainties(const RiseFall *src_rf) const;
|
||||||
bool empty() const;
|
[[nodiscard]] bool empty() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Clock *src_;
|
const Clock *src_;
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "Vector.hh"
|
|
||||||
#include "Map.hh"
|
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
|
|
||||||
|
|
@ -45,17 +45,17 @@ class PatternMatch;
|
||||||
class LibertyCell;
|
class LibertyCell;
|
||||||
class LibertyPort;
|
class LibertyPort;
|
||||||
|
|
||||||
typedef Map<std::string, ConcreteCell*> ConcreteCellMap;
|
using ConcreteCellMap = std::map<std::string, ConcreteCell*>;
|
||||||
typedef Vector<ConcretePort*> ConcretePortSeq;
|
using ConcretePortSeq = std::vector<ConcretePort*>;
|
||||||
typedef Map<std::string, ConcretePort*> ConcretePortMap;
|
using ConcretePortMap = std::map<std::string, ConcretePort*>;
|
||||||
typedef ConcreteCellMap::ConstIterator ConcreteLibraryCellIterator;
|
using ConcreteLibraryCellIterator = MapIterator<ConcreteCellMap, ConcreteCell*>;
|
||||||
typedef ConcretePortSeq::ConstIterator ConcreteCellPortIterator;
|
using ConcreteCellPortIterator = VectorIterator<ConcretePortSeq, ConcretePort*>;
|
||||||
typedef ConcretePortSeq::ConstIterator ConcretePortMemberIterator;
|
using ConcretePortMemberIterator = VectorIterator<ConcretePortSeq, ConcretePort*>;
|
||||||
|
|
||||||
class ConcreteLibrary
|
class ConcreteLibrary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ConcreteLibrary(const char *name,
|
ConcreteLibrary(const char *name,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
bool is_liberty);
|
bool is_liberty);
|
||||||
virtual ~ConcreteLibrary();
|
virtual ~ConcreteLibrary();
|
||||||
|
|
@ -263,14 +263,15 @@ private:
|
||||||
class ConcreteCellPortBitIterator : public Iterator<ConcretePort*>
|
class ConcreteCellPortBitIterator : public Iterator<ConcretePort*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ConcreteCellPortBitIterator(const ConcreteCell *cell);
|
ConcreteCellPortBitIterator(const ConcreteCell *cell);
|
||||||
virtual bool hasNext();
|
virtual bool hasNext();
|
||||||
virtual ConcretePort *next();
|
virtual ConcretePort *next();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void findNext();
|
void findNext();
|
||||||
|
|
||||||
ConcretePortSeq::ConstIterator port_iter_;
|
const ConcretePortSeq &ports_;
|
||||||
|
ConcretePortSeq::const_iterator port_iter_;
|
||||||
ConcretePortMemberIterator *member_iter_;
|
ConcretePortMemberIterator *member_iter_;
|
||||||
ConcretePort *next_;
|
ConcretePort *next_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "Map.hh"
|
|
||||||
#include "Set.hh"
|
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "LibertyClass.hh"
|
#include "LibertyClass.hh"
|
||||||
|
|
@ -45,16 +46,14 @@ class ConcretePort;
|
||||||
class ConcreteBindingTbl;
|
class ConcreteBindingTbl;
|
||||||
class ConcreteLibertyLibraryIterator;
|
class ConcreteLibertyLibraryIterator;
|
||||||
|
|
||||||
typedef Vector<ConcreteLibrary*> ConcreteLibrarySeq;
|
using ConcreteLibrarySeq = std::vector<ConcreteLibrary*>;
|
||||||
typedef Map<const char*, ConcreteLibrary*, CharPtrLess> ConcreteLibraryMap;
|
using ConcreteLibraryMap = std::map<const char*, ConcreteLibrary*, CharPtrLess>;
|
||||||
typedef ConcreteLibrarySeq::ConstIterator ConcreteLibraryIterator;
|
using ConcreteInstanceChildMap = std::map<const char *, ConcreteInstance*, CharPtrLess>;
|
||||||
typedef Map<const char *, ConcreteInstance*,
|
using ConcreteInstanceNetMap = std::map<const char *, ConcreteNet*, CharPtrLess>;
|
||||||
CharPtrLess> ConcreteInstanceChildMap;
|
using ConcreteNetSeq = std::vector<ConcreteNet*>;
|
||||||
typedef Map<const char *, ConcreteNet*, CharPtrLess> ConcreteInstanceNetMap;
|
using ConcretePinSeq = std::vector<ConcretePin*>;
|
||||||
typedef Vector<ConcreteNet*> ConcreteNetSeq;
|
using CellNetworkViewMap = std::map<Cell*, Instance*>;
|
||||||
typedef Vector<ConcretePin*> ConcretePinSeq;
|
using ConcreteNetSet = std::set<const ConcreteNet*>;
|
||||||
typedef Map<Cell*, Instance*> CellNetworkViewMap;
|
|
||||||
typedef Set<const ConcreteNet*> ConcreteNetSet;
|
|
||||||
|
|
||||||
// This adapter implements the network api for the concrete network.
|
// This adapter implements the network api for the concrete network.
|
||||||
// A superset of the Network api methods are implemented in the interface.
|
// A superset of the Network api methods are implemented in the interface.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,381 @@
|
||||||
|
// 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 <type_traits>
|
||||||
|
#include <utility> // for std::declval
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <ranges>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
// C++ kung foo courtesy of chat gtp.
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// 1. Sequence containers (vector<T*>, list<T*>, deque<T*>, …)
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
template <typename Container>
|
||||||
|
std::enable_if_t<std::is_pointer_v<typename Container::value_type>>
|
||||||
|
deleteContents(Container& c)
|
||||||
|
{
|
||||||
|
for (auto ptr : c)
|
||||||
|
delete ptr;
|
||||||
|
c.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
std::enable_if_t<std::is_pointer_v<typename Container::value_type>>
|
||||||
|
deleteContents(Container *c)
|
||||||
|
{
|
||||||
|
for (auto ptr : *c)
|
||||||
|
delete ptr;
|
||||||
|
c->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// 2. Maps (map<K, T*>, unordered_map<K, T*>)
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
template <typename Map>
|
||||||
|
std::enable_if_t<std::is_pointer_v<typename Map::mapped_type>
|
||||||
|
>
|
||||||
|
deleteContents(Map& m)
|
||||||
|
{
|
||||||
|
for (auto& kv : m)
|
||||||
|
delete kv.second;
|
||||||
|
m.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Map>
|
||||||
|
std::enable_if_t<std::is_pointer_v<typename Map::mapped_type>
|
||||||
|
>
|
||||||
|
deleteContents(Map *m)
|
||||||
|
{
|
||||||
|
for (auto& kv : *m)
|
||||||
|
delete kv.second;
|
||||||
|
m->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// 3. Sets (set<T*>, unordered_set<T*>)
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
template <typename Set>
|
||||||
|
std::enable_if_t<
|
||||||
|
std::is_pointer_v<typename Set::value_type> &&
|
||||||
|
!std::is_same_v<typename Set::value_type, typename Set::mapped_type>
|
||||||
|
>
|
||||||
|
deleteContents(Set& s)
|
||||||
|
{
|
||||||
|
for (auto ptr : s)
|
||||||
|
delete ptr;
|
||||||
|
s.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// detect whether container has mapped_type
|
||||||
|
template<typename, typename = void>
|
||||||
|
struct has_mapped_type : std::false_type {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct has_mapped_type<T, std::void_t<typename T::mapped_type>>
|
||||||
|
: std::true_type {};
|
||||||
|
|
||||||
|
// handle pointer types
|
||||||
|
template<typename T>
|
||||||
|
struct has_mapped_type<T*, void> : has_mapped_type<T> {};
|
||||||
|
|
||||||
|
// return-type chooser: use struct, NOT alias template
|
||||||
|
template<typename C, bool = has_mapped_type<C>::value>
|
||||||
|
struct find_return;
|
||||||
|
|
||||||
|
// pointer to map
|
||||||
|
template<typename C>
|
||||||
|
struct find_return<C*, true>
|
||||||
|
{
|
||||||
|
using type = typename C::mapped_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// pointer to set
|
||||||
|
template<typename C>
|
||||||
|
struct find_return<C*, false>
|
||||||
|
{
|
||||||
|
using type = typename C::key_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// map ref
|
||||||
|
template<typename C>
|
||||||
|
struct find_return<C, true>
|
||||||
|
{
|
||||||
|
using type = typename C::mapped_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// set ref
|
||||||
|
template<typename C>
|
||||||
|
struct find_return<C, false>
|
||||||
|
{
|
||||||
|
using type = typename C::key_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Find an value in a contaiiner of pointers.
|
||||||
|
// return nullptr if not found.
|
||||||
|
template<typename AssocContainer>
|
||||||
|
auto
|
||||||
|
findKey(const AssocContainer& c,
|
||||||
|
typename AssocContainer::key_type key)
|
||||||
|
-> typename find_return<AssocContainer>::type
|
||||||
|
{
|
||||||
|
using ReturnType = typename find_return<AssocContainer>::type;
|
||||||
|
|
||||||
|
static_assert(std::is_pointer_v<ReturnType>,
|
||||||
|
"findKey requires pointer types");
|
||||||
|
|
||||||
|
auto it = c.find(key);
|
||||||
|
if (it == c.end())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if constexpr (has_mapped_type<AssocContainer>::value)
|
||||||
|
return it->second; // map
|
||||||
|
else
|
||||||
|
return *it; // set
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find an value in a contaiiner of pointers.
|
||||||
|
// return nullptr if not found.
|
||||||
|
template<typename AssocContainer>
|
||||||
|
auto
|
||||||
|
findKey(const AssocContainer* c,
|
||||||
|
typename AssocContainer::key_type key)
|
||||||
|
-> typename find_return<AssocContainer>::type
|
||||||
|
{
|
||||||
|
using ReturnType = typename find_return<AssocContainer>::type;
|
||||||
|
|
||||||
|
static_assert(std::is_pointer_v<ReturnType>,
|
||||||
|
"findKey requires pointer types");
|
||||||
|
|
||||||
|
auto it = c->find(key);
|
||||||
|
if (it == c->end())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if constexpr (has_mapped_type<AssocContainer>::value)
|
||||||
|
// map
|
||||||
|
return it->second;
|
||||||
|
else
|
||||||
|
// set
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AssocContainer>
|
||||||
|
void
|
||||||
|
findKeyValue(const AssocContainer& c,
|
||||||
|
typename AssocContainer::key_type key,
|
||||||
|
typename find_return<AssocContainer>::type &value,
|
||||||
|
bool &exists)
|
||||||
|
{
|
||||||
|
auto it = c.find(key);
|
||||||
|
if (it == c.end()) {
|
||||||
|
exists = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (has_mapped_type<AssocContainer>::value) {
|
||||||
|
// map
|
||||||
|
value = it->second;
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// set
|
||||||
|
value = *it;
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AssocContainer>
|
||||||
|
void
|
||||||
|
findKeyValue(const AssocContainer *c,
|
||||||
|
typename AssocContainer::key_type key,
|
||||||
|
typename find_return<AssocContainer>::type &value,
|
||||||
|
bool &exists)
|
||||||
|
{
|
||||||
|
auto it = c->find(key);
|
||||||
|
if (it == c->end()) {
|
||||||
|
exists = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (has_mapped_type<AssocContainer>::value) {
|
||||||
|
// map
|
||||||
|
value = it->second;
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// set
|
||||||
|
value = *it;
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AssocContainer>
|
||||||
|
auto
|
||||||
|
findKeyValuePtr(AssocContainer& c,
|
||||||
|
typename AssocContainer::key_type key)
|
||||||
|
-> typename find_return<AssocContainer>::type*
|
||||||
|
{
|
||||||
|
auto it = c.find(key);
|
||||||
|
if (it == c.end())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if constexpr (has_mapped_type<AssocContainer>::value)
|
||||||
|
// map
|
||||||
|
return &it->second;
|
||||||
|
else
|
||||||
|
// set
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Determine if two std::set's intersect.
|
||||||
|
// Returns true if there is at least one common element.
|
||||||
|
template <typename Set>
|
||||||
|
bool
|
||||||
|
intersects(const Set &set1,
|
||||||
|
const Set &set2,
|
||||||
|
typename Set::key_compare key_less)
|
||||||
|
{
|
||||||
|
auto iter1 = set1.begin();
|
||||||
|
auto end1 = set1.end();
|
||||||
|
auto iter2 = set2.begin();
|
||||||
|
auto end2 = set2.end();
|
||||||
|
|
||||||
|
while (iter1 != end1 && iter2 != end2) {
|
||||||
|
if (key_less(*iter1, *iter2))
|
||||||
|
iter1++;
|
||||||
|
else if (key_less(*iter2, *iter1))
|
||||||
|
iter2++;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine if two std::set's intersect (pointer version).
|
||||||
|
// Returns true if there is at least one common element.
|
||||||
|
template <typename Set>
|
||||||
|
bool
|
||||||
|
intersects(const Set *set1,
|
||||||
|
const Set *set2,
|
||||||
|
typename Set::key_compare key_less)
|
||||||
|
{
|
||||||
|
if (set1 && set2) {
|
||||||
|
auto iter1 = set1->begin();
|
||||||
|
auto end1 = set1->end();
|
||||||
|
auto iter2 = set2->begin();
|
||||||
|
auto end2 = set2->end();
|
||||||
|
|
||||||
|
while (iter1 != end1 && iter2 != end2) {
|
||||||
|
if (key_less(*iter1, *iter2))
|
||||||
|
iter1++;
|
||||||
|
else if (key_less(*iter2, *iter1))
|
||||||
|
iter2++;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Compare set contents.
|
||||||
|
template <typename Set>
|
||||||
|
int
|
||||||
|
compare(const Set *set1,
|
||||||
|
const Set *set2,
|
||||||
|
typename Set::key_compare key_less)
|
||||||
|
{
|
||||||
|
size_t size1 = set1 ? set1->size() : 0;
|
||||||
|
size_t size2 = set2 ? set2->size() : 0;
|
||||||
|
if (size1 == size2) {
|
||||||
|
if (set1 == nullptr || set2 == nullptr) {
|
||||||
|
// Both are null or empty, so they're equal
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto iter1 = set1->begin();
|
||||||
|
auto iter2 = set2->begin();
|
||||||
|
auto end1 = set1->end();
|
||||||
|
auto end2 = set2->end();
|
||||||
|
while (iter1 != end1 && iter2 != end2) {
|
||||||
|
if (key_less(*iter1, *iter2))
|
||||||
|
return -1;
|
||||||
|
else if (key_less(*iter2, *iter1))
|
||||||
|
return 1;
|
||||||
|
++iter1;
|
||||||
|
++iter2;
|
||||||
|
}
|
||||||
|
// Sets are equal.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (size1 > size2) ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Sort functions that do not require begin()/end() range.
|
||||||
|
|
||||||
|
// reference arg
|
||||||
|
template<std::ranges::random_access_range Range,
|
||||||
|
typename Comp = std::less<>>
|
||||||
|
requires std::predicate<Comp&,
|
||||||
|
std::ranges::range_reference_t<Range>,
|
||||||
|
std::ranges::range_reference_t<Range>>
|
||||||
|
void
|
||||||
|
sort(Range& r,
|
||||||
|
Comp comp = Comp{})
|
||||||
|
{
|
||||||
|
std::sort(std::ranges::begin(r), std::ranges::end(r), comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// pointer arg
|
||||||
|
template<typename Range,
|
||||||
|
typename Comp = std::less<>>
|
||||||
|
requires std::ranges::random_access_range<Range> &&
|
||||||
|
std::predicate<Comp&,
|
||||||
|
std::ranges::range_reference_t<Range>,
|
||||||
|
std::ranges::range_reference_t<Range>>
|
||||||
|
void
|
||||||
|
sort(Range* r,
|
||||||
|
Comp comp = Comp{})
|
||||||
|
{
|
||||||
|
std::sort(std::ranges::begin(*r), std::ranges::end(*r), comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -1,139 +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 "MinMax.hh"
|
|
||||||
#include "Vector.hh"
|
|
||||||
#include "StringSet.hh"
|
|
||||||
#include "GraphClass.hh"
|
|
||||||
#include "SearchClass.hh"
|
|
||||||
#include "StaState.hh"
|
|
||||||
|
|
||||||
namespace sta {
|
|
||||||
|
|
||||||
class ParasiticAnalysisPt;
|
|
||||||
class DcalcAnalysisPt;
|
|
||||||
class PathAnalysisPt;
|
|
||||||
class Corner;
|
|
||||||
class Corners;
|
|
||||||
class LibertyLibrary;
|
|
||||||
|
|
||||||
typedef Vector<Corner*> CornerSeq;
|
|
||||||
typedef Map<const char *, Corner*, CharPtrLess> CornerMap;
|
|
||||||
typedef Vector<ParasiticAnalysisPt*> ParasiticAnalysisPtSeq;
|
|
||||||
typedef Vector<DcalcAnalysisPt*> DcalcAnalysisPtSeq;
|
|
||||||
typedef Vector<PathAnalysisPt*> PathAnalysisPtSeq;
|
|
||||||
typedef Vector<LibertyLibrary*> LibertySeq;
|
|
||||||
|
|
||||||
class Corners : public StaState
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Corners(StaState *sta);
|
|
||||||
~Corners();
|
|
||||||
void clear();
|
|
||||||
int count() const;
|
|
||||||
void copy(Corners *corners);
|
|
||||||
bool multiCorner() const;
|
|
||||||
Corner *findCorner(const char *corner);
|
|
||||||
Corner *findCorner(int corner_index);
|
|
||||||
void makeCorners(StringSet *corner_names);
|
|
||||||
void analysisTypeChanged();
|
|
||||||
void operatingConditionsChanged();
|
|
||||||
|
|
||||||
// Make one parasitic analysis points.
|
|
||||||
void makeParasiticAnalysisPts(bool per_corner);
|
|
||||||
int parasiticAnalysisPtCount() const;
|
|
||||||
ParasiticAnalysisPtSeq ¶siticAnalysisPts();
|
|
||||||
|
|
||||||
DcalcAPIndex dcalcAnalysisPtCount() const;
|
|
||||||
DcalcAnalysisPtSeq &dcalcAnalysisPts();
|
|
||||||
const DcalcAnalysisPtSeq &dcalcAnalysisPts() const;
|
|
||||||
|
|
||||||
PathAPIndex pathAnalysisPtCount() const;
|
|
||||||
PathAnalysisPt *findPathAnalysisPt(PathAPIndex path_index) const;
|
|
||||||
PathAnalysisPtSeq &pathAnalysisPts();
|
|
||||||
const PathAnalysisPtSeq &pathAnalysisPts() const;
|
|
||||||
CornerSeq &corners() { return corners_; }
|
|
||||||
// Iterators for range iteration.
|
|
||||||
// for (auto corner : *sta->corners()) {}
|
|
||||||
CornerSeq::iterator begin() { return corners_.begin(); }
|
|
||||||
CornerSeq::iterator end() { return corners_.end(); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void makeAnalysisPts();
|
|
||||||
void makeDcalcAnalysisPts(Corner *corner);
|
|
||||||
DcalcAnalysisPt *makeDcalcAnalysisPt(Corner *corner,
|
|
||||||
const MinMax *min_max,
|
|
||||||
const MinMax *check_clk_slew_min_max);
|
|
||||||
void makePathAnalysisPts(Corner *corner);
|
|
||||||
void makePathAnalysisPts(Corner *corner,
|
|
||||||
bool swap_clk_min_max,
|
|
||||||
DcalcAnalysisPt *dcalc_ap_min,
|
|
||||||
DcalcAnalysisPt *dcalc_ap_max);
|
|
||||||
|
|
||||||
private:
|
|
||||||
CornerMap corner_map_;
|
|
||||||
CornerSeq corners_;
|
|
||||||
ParasiticAnalysisPtSeq parasitic_analysis_pts_;
|
|
||||||
DcalcAnalysisPtSeq dcalc_analysis_pts_;
|
|
||||||
PathAnalysisPtSeq path_analysis_pts_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Corner
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Corner(const char *name,
|
|
||||||
int index);
|
|
||||||
const char *name() const { return name_.c_str(); }
|
|
||||||
int index() const { return index_; }
|
|
||||||
ParasiticAnalysisPt *findParasiticAnalysisPt(const MinMax *min_max) const;
|
|
||||||
int parasiticAnalysisPtcount();
|
|
||||||
DcalcAnalysisPt *findDcalcAnalysisPt(const MinMax *min_max) const;
|
|
||||||
PathAnalysisPt *findPathAnalysisPt(const MinMax *min_max) const;
|
|
||||||
void addLiberty(LibertyLibrary *lib,
|
|
||||||
const MinMax *min_max);
|
|
||||||
const LibertySeq &libertyLibraries(const MinMax *min_max) const;
|
|
||||||
int libertyIndex(const MinMax *min_max) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void setParasiticAnalysisPtcount(int ap_count);
|
|
||||||
void setParasiticAP(ParasiticAnalysisPt *path_ap,
|
|
||||||
int mm_index);
|
|
||||||
void setDcalcAnalysisPtcount(DcalcAPIndex ap_count);
|
|
||||||
void addDcalcAP(DcalcAnalysisPt *dcalc_ap);
|
|
||||||
void addPathAP(PathAnalysisPt *path_ap);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string name_;
|
|
||||||
int index_;
|
|
||||||
ParasiticAnalysisPtSeq parasitic_analysis_pts_;
|
|
||||||
DcalcAnalysisPtSeq dcalc_analysis_pts_;
|
|
||||||
PathAnalysisPtSeq path_analysis_pts_;
|
|
||||||
LibertySeq liberty_[MinMax::index_count];
|
|
||||||
|
|
||||||
friend class Corners;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
@ -24,7 +24,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "UnorderedSet.hh"
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "MinMax.hh"
|
#include "MinMax.hh"
|
||||||
#include "TimingRole.hh"
|
#include "TimingRole.hh"
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
|
|
@ -52,7 +53,9 @@ public:
|
||||||
const CycleAccting *acct2) const;
|
const CycleAccting *acct2) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef UnorderedSet<CycleAccting*, CycleAcctingHash, CycleAcctingEqual> CycleAcctingSet;
|
using CycleAcctingSet = std::unordered_set<CycleAccting*,
|
||||||
|
CycleAcctingHash,
|
||||||
|
CycleAcctingEqual>;
|
||||||
|
|
||||||
class CycleAcctings
|
class CycleAcctings
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ public:
|
||||||
void removeMargin(const RiseFallBoth *from_rf,
|
void removeMargin(const RiseFallBoth *from_rf,
|
||||||
const RiseFallBoth *to_rf,
|
const RiseFallBoth *to_rf,
|
||||||
const SetupHoldAll *setup_hold);
|
const SetupHoldAll *setup_hold);
|
||||||
bool empty() const;
|
[[nodiscard]] bool empty() const;
|
||||||
void marginIsOneValue(const SetupHold *setup_hold,
|
void marginIsOneValue(const SetupHold *setup_hold,
|
||||||
// Return values.
|
// Return values.
|
||||||
float &value,
|
float &value,
|
||||||
|
|
|
||||||
|
|
@ -1,81 +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 "Iterator.hh"
|
|
||||||
#include "MinMax.hh"
|
|
||||||
#include "LibertyClass.hh"
|
|
||||||
#include "SdcClass.hh"
|
|
||||||
#include "ParasiticsClass.hh"
|
|
||||||
#include "GraphClass.hh"
|
|
||||||
#include "StaState.hh"
|
|
||||||
|
|
||||||
namespace sta {
|
|
||||||
|
|
||||||
class Corner;
|
|
||||||
|
|
||||||
// Delay calculation analysis point.
|
|
||||||
// This collects all of the parameters used to find one set of
|
|
||||||
// delay calculation results.
|
|
||||||
class DcalcAnalysisPt
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DcalcAnalysisPt(Corner *corner,
|
|
||||||
DcalcAPIndex index,
|
|
||||||
const OperatingConditions *op_cond,
|
|
||||||
const MinMax *min_max,
|
|
||||||
const MinMax *check_clk_slew_min_max);
|
|
||||||
Corner *corner() const { return corner_; }
|
|
||||||
// Which of the delay_count results this analysis point corresponds to.
|
|
||||||
DcalcAPIndex index() const { return index_; }
|
|
||||||
// Slew index of timing check data.
|
|
||||||
DcalcAPIndex checkDataSlewIndex() const { return index_; }
|
|
||||||
// Slew index of timing check clock.
|
|
||||||
DcalcAPIndex checkClkSlewIndex() const { return check_clk_slew_index_; }
|
|
||||||
// Slew min/max of timing check clock.
|
|
||||||
const MinMax *checkClkSlewMinMax() const { return check_clk_slew_min_max_; }
|
|
||||||
// Constraint min/max values to use.
|
|
||||||
const MinMax *constraintMinMax() const { return min_max_; }
|
|
||||||
// Constraints::operatingCondition(cnst_min_max_)
|
|
||||||
const OperatingConditions *operatingConditions() const { return op_cond_; }
|
|
||||||
void setOperatingConditions(const OperatingConditions *op_cond);
|
|
||||||
// Delay merging min/max operator (for wires).
|
|
||||||
const MinMax *delayMinMax() const { return min_max_; }
|
|
||||||
// Merge min/max slews across timing arcs.
|
|
||||||
const MinMax *slewMinMax() const { return min_max_; }
|
|
||||||
ParasiticAnalysisPt *parasiticAnalysisPt() const;
|
|
||||||
void setCheckClkSlewIndex(DcalcAPIndex index);
|
|
||||||
int libertyIndex() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Corner *corner_;
|
|
||||||
DcalcAPIndex index_;
|
|
||||||
DcalcAPIndex check_clk_slew_index_;
|
|
||||||
const OperatingConditions *op_cond_;
|
|
||||||
const MinMax *min_max_;
|
|
||||||
const MinMax *check_clk_slew_min_max_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
@ -24,10 +24,11 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "Map.hh"
|
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -35,13 +36,12 @@ namespace sta {
|
||||||
class Report;
|
class Report;
|
||||||
class Pin;
|
class Pin;
|
||||||
|
|
||||||
typedef Map<const char *, int, CharPtrLess> DebugMap;
|
using DebugMap = std::map<std::string, int>;
|
||||||
|
|
||||||
class Debug
|
class Debug
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Debug(Report *report);
|
Debug(Report *report);
|
||||||
~Debug();
|
|
||||||
int level(const char *what);
|
int level(const char *what);
|
||||||
void setLevel(const char *what,
|
void setLevel(const char *what,
|
||||||
int level);
|
int level);
|
||||||
|
|
@ -57,18 +57,15 @@ protected:
|
||||||
Report *report_;
|
Report *report_;
|
||||||
std::mutex buffer_lock_;
|
std::mutex buffer_lock_;
|
||||||
bool debug_on_;
|
bool debug_on_;
|
||||||
DebugMap *debug_map_;
|
DebugMap debug_map_;
|
||||||
int stats_level_;
|
int stats_level_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inlining a varargs function would eval the args, which can
|
// Inlining a varargs function would eval the args, which can
|
||||||
// be expensive, so use a macro.
|
// be expensive, so use a macro.
|
||||||
// Note that "##__VA_ARGS__" is a gcc extension to support zero arguments (no comma).
|
|
||||||
// clang -Wno-gnu-zero-variadic-macro-arguments suppresses the warning.
|
|
||||||
// c++20 has "__VA_OPT__" to deal with the zero arg case so this is temporary.
|
|
||||||
#define debugPrint(debug, what, level, ...) \
|
#define debugPrint(debug, what, level, ...) \
|
||||||
if (debug->check(what, level)) { \
|
if (debug->check(what, level)) { \
|
||||||
debug->reportLine(what, ##__VA_ARGS__); \
|
debug->reportLine(what __VA_OPT__(,) __VA_ARGS__); \
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,10 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef Delay ArcDelay;
|
using ArcDelay = Delay;
|
||||||
typedef Delay Slew;
|
using Slew = Delay;
|
||||||
typedef Delay Arrival;
|
using Arrival = Delay;
|
||||||
typedef Delay Required;
|
using Required = Delay;
|
||||||
typedef Delay Slack;
|
using Slack = Delay;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace sta {
|
||||||
class ArcDelayCalc;
|
class ArcDelayCalc;
|
||||||
class StaState;
|
class StaState;
|
||||||
|
|
||||||
typedef ArcDelayCalc *(*MakeArcDelayCalc)(StaState *sta);
|
using MakeArcDelayCalc = ArcDelayCalc *(*)(StaState *sta);
|
||||||
|
|
||||||
// Register builtin delay calculators.
|
// Register builtin delay calculators.
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,9 @@ namespace sta {
|
||||||
|
|
||||||
class StaState;
|
class StaState;
|
||||||
|
|
||||||
typedef float Delay;
|
using Delay = float;
|
||||||
// Delay double for accumulating Delays.
|
// Delay double for accumulating Delays.
|
||||||
typedef double DelayDbl;
|
using DelayDbl = double;
|
||||||
|
|
||||||
const Delay delay_zero = 0.0;
|
const Delay delay_zero = 0.0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Map.hh"
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
#include "LibertyClass.hh"
|
#include "LibertyClass.hh"
|
||||||
#include "SdcClass.hh"
|
#include "SdcClass.hh"
|
||||||
|
|
@ -35,10 +37,10 @@ class TimingRole;
|
||||||
class DisabledCellPorts;
|
class DisabledCellPorts;
|
||||||
class DisabledInstancePorts;
|
class DisabledInstancePorts;
|
||||||
|
|
||||||
typedef Vector<DisabledInstancePorts*> DisabledInstancePortsSeq;
|
using DisabledInstancePortsSeq = std::vector<DisabledInstancePorts*>;
|
||||||
typedef Vector<DisabledCellPorts*> DisabledCellPortsSeq;
|
using DisabledCellPortsSeq = std::vector<DisabledCellPorts*>;
|
||||||
typedef Vector<LibertyPortPair> LibertyPortPairSeq;
|
using LibertyPortPairSeq = std::vector<LibertyPortPair>;
|
||||||
typedef Set<TimingArcSet*> TimingArcSetSet;
|
using TimingArcSetSet = std::set<TimingArcSet*, TimingArcSetLess>;
|
||||||
|
|
||||||
// Base class for disabled cell and instance ports.
|
// Base class for disabled cell and instance ports.
|
||||||
class DisabledPorts
|
class DisabledPorts
|
||||||
|
|
@ -56,13 +58,13 @@ public:
|
||||||
LibertyPort *to);
|
LibertyPort *to);
|
||||||
void removeDisabledFromTo(LibertyPort *from,
|
void removeDisabledFromTo(LibertyPort *from,
|
||||||
LibertyPort *to);
|
LibertyPort *to);
|
||||||
bool isDisabled(LibertyPort *from,
|
[[nodiscard]] bool isDisabled(LibertyPort *from,
|
||||||
LibertyPort *to,
|
LibertyPort *to,
|
||||||
const TimingRole *role);
|
const TimingRole *role);
|
||||||
LibertyPortPairSet *fromTo() const { return from_to_; }
|
LibertyPortPairSet *fromTo() const { return from_to_; }
|
||||||
LibertyPortSet *from() const { return from_; }
|
LibertyPortSet *from() const { return from_; }
|
||||||
LibertyPortSet *to() const { return to_; }
|
LibertyPortSet *to() const { return to_; }
|
||||||
bool all() const { return all_; }
|
[[nodiscard]] bool all() const { return all_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool all_;
|
bool all_;
|
||||||
|
|
@ -80,7 +82,7 @@ public:
|
||||||
LibertyCell *cell() const { return cell_; }
|
LibertyCell *cell() const { return cell_; }
|
||||||
void setDisabled(TimingArcSet *arc_set);
|
void setDisabled(TimingArcSet *arc_set);
|
||||||
void removeDisabled(TimingArcSet *arc_set);
|
void removeDisabled(TimingArcSet *arc_set);
|
||||||
bool isDisabled(TimingArcSet *arc_set) const;
|
[[nodiscard]] bool isDisabled(TimingArcSet *arc_set) const;
|
||||||
TimingArcSetSet *timingArcSets() const { return arc_sets_; }
|
TimingArcSetSet *timingArcSets() const { return arc_sets_; }
|
||||||
|
|
||||||
using DisabledPorts::isDisabled;
|
using DisabledPorts::isDisabled;
|
||||||
|
|
@ -102,7 +104,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
DisabledCellPortsSeq
|
DisabledCellPortsSeq
|
||||||
sortByName(DisabledCellPortsMap *cell_map);
|
sortByName(const DisabledCellPortsMap *cell_map);
|
||||||
DisabledInstancePortsSeq
|
DisabledInstancePortsSeq
|
||||||
sortByPathName(const DisabledInstancePortsMap *inst_map,
|
sortByPathName(const DisabledInstancePortsMap *inst_map,
|
||||||
const Network *network);
|
const Network *network);
|
||||||
|
|
|
||||||
|
|
@ -24,15 +24,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Vector.hh"
|
#include <map>
|
||||||
#include "Map.hh"
|
#include <unordered_map>
|
||||||
#include "UnorderedMap.hh"
|
|
||||||
#include "LibertyClass.hh"
|
#include "LibertyClass.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef Map<LibertyCell*, LibertyCellSeq*> EquivCellMap;
|
using EquivCellMap = std::map<LibertyCell*, LibertyCellSeq*>;
|
||||||
typedef UnorderedMap<unsigned, LibertyCellSeq*> LibertyCellHashMap;
|
using LibertyCellHashMap = std::unordered_map<unsigned, LibertyCellSeq*>;
|
||||||
|
|
||||||
class EquivCells
|
class EquivCells
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ protected:
|
||||||
class FileNotReadable : public Exception
|
class FileNotReadable : public Exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit FileNotReadable(const char *filename);
|
FileNotReadable(const char *filename);
|
||||||
virtual const char *what() const noexcept;
|
virtual const char *what() const noexcept;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -78,7 +78,7 @@ protected:
|
||||||
class FileNotWritable : public Exception
|
class FileNotWritable : public Exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit FileNotWritable(const char *filename);
|
FileNotWritable(const char *filename);
|
||||||
virtual const char *what() const noexcept;
|
virtual const char *what() const noexcept;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Error.hh"
|
#include "Error.hh"
|
||||||
#include "Set.hh"
|
|
||||||
#include "SdcCmdComment.hh"
|
#include "SdcCmdComment.hh"
|
||||||
#include "SdcClass.hh"
|
#include "SdcClass.hh"
|
||||||
|
|
||||||
|
|
@ -44,7 +45,7 @@ class ExceptionThru;
|
||||||
class ExceptionTo;
|
class ExceptionTo;
|
||||||
class ExceptionState;
|
class ExceptionState;
|
||||||
|
|
||||||
typedef Vector<ExceptionPath*> ExceptionPathSeq;
|
using ExceptionPathSeq = std::vector<ExceptionPath*>;
|
||||||
|
|
||||||
class ExceptionPath : public SdcCmdComment
|
class ExceptionPath : public SdcCmdComment
|
||||||
{
|
{
|
||||||
|
|
@ -593,14 +594,14 @@ exceptionThrusClone(ExceptionThruSeq *thrus,
|
||||||
class ExceptionPtIterator
|
class ExceptionPtIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ExceptionPtIterator(const ExceptionPath *exception);
|
ExceptionPtIterator(const ExceptionPath *exception);
|
||||||
bool hasNext();
|
bool hasNext();
|
||||||
ExceptionPt *next();
|
ExceptionPt *next();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ExceptionPath *exception_;
|
const ExceptionPath *exception_;
|
||||||
bool from_done_;
|
bool from_done_;
|
||||||
ExceptionThruSeq::Iterator thru_iter_;
|
ExceptionThruSeq::iterator thru_iter_;
|
||||||
bool to_done_;
|
bool to_done_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -667,8 +668,8 @@ private:
|
||||||
int index_;
|
int index_;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
int
|
||||||
exceptionStateLess(const ExceptionState *state1,
|
exceptionStateCmp(const ExceptionState *state1,
|
||||||
const ExceptionState *state2);
|
const ExceptionState *state2);
|
||||||
|
|
||||||
// Exception thrown by check.
|
// Exception thrown by check.
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Set.hh"
|
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
#include "LibertyClass.hh"
|
#include "LibertyClass.hh"
|
||||||
|
|
||||||
|
|
@ -35,16 +34,16 @@ namespace sta {
|
||||||
class FuncExpr
|
class FuncExpr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Operator {op_port,
|
enum class Op {port,
|
||||||
op_not,
|
not_,
|
||||||
op_or,
|
or_,
|
||||||
op_and,
|
and_,
|
||||||
op_xor,
|
xor_,
|
||||||
op_one,
|
one,
|
||||||
op_zero};
|
zero};
|
||||||
|
|
||||||
// Constructors.
|
// Constructors.
|
||||||
FuncExpr(Operator op,
|
FuncExpr(Op op,
|
||||||
FuncExpr *left,
|
FuncExpr *left,
|
||||||
FuncExpr *right,
|
FuncExpr *right,
|
||||||
LibertyPort *port);
|
LibertyPort *port);
|
||||||
|
|
@ -67,14 +66,15 @@ public:
|
||||||
FuncExpr *copy();
|
FuncExpr *copy();
|
||||||
// Delete expression and all of its subexpressions.
|
// Delete expression and all of its subexpressions.
|
||||||
void deleteSubexprs();
|
void deleteSubexprs();
|
||||||
// op == op_port
|
// op == port
|
||||||
LibertyPort *port() const;
|
LibertyPort *port() const;
|
||||||
Operator op() const { return op_; }
|
Op op() const { return op_; }
|
||||||
// When operator is NOT left is the only operand.
|
// When operator is NOT left is the only operand.
|
||||||
FuncExpr *left() const { return left_; }
|
FuncExpr *left() const { return left_; }
|
||||||
// nullptr when op == op_not
|
// nullptr when op == not_
|
||||||
FuncExpr *right() const { return right_; }
|
FuncExpr *right() const { return right_; }
|
||||||
TimingSense portTimingSense(const LibertyPort *port) const;
|
TimingSense portTimingSense(const LibertyPort *port) const;
|
||||||
|
LibertyPortSet ports() const;
|
||||||
// Return true if expression has port as an input.
|
// Return true if expression has port as an input.
|
||||||
bool hasPort(const LibertyPort *port) const;
|
bool hasPort(const LibertyPort *port) const;
|
||||||
std::string to_string() const;
|
std::string to_string() const;
|
||||||
|
|
@ -86,11 +86,14 @@ public:
|
||||||
bool checkSize(LibertyPort *port);
|
bool checkSize(LibertyPort *port);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void findPorts(const FuncExpr *expr,
|
||||||
|
LibertyPortSet &ports) const;
|
||||||
|
|
||||||
std::string to_string(bool with_parens) const;
|
std::string to_string(bool with_parens) const;
|
||||||
std::string to_string(bool with_parens,
|
std::string to_string(bool with_parens,
|
||||||
char op) const;
|
char op) const;
|
||||||
|
|
||||||
Operator op_;
|
Op op_;
|
||||||
FuncExpr *left_;
|
FuncExpr *left_;
|
||||||
FuncExpr *right_;
|
FuncExpr *right_;
|
||||||
LibertyPort *port_;
|
LibertyPort *port_;
|
||||||
|
|
@ -100,18 +103,4 @@ private:
|
||||||
FuncExpr *
|
FuncExpr *
|
||||||
funcExprNot(FuncExpr *expr);
|
funcExprNot(FuncExpr *expr);
|
||||||
|
|
||||||
class FuncExprPortIterator : public Iterator<LibertyPort*>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit FuncExprPortIterator(const FuncExpr *expr);
|
|
||||||
virtual bool hasNext() { return iter_.hasNext(); }
|
|
||||||
virtual LibertyPort *next() { return iter_.next(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void findPorts(const FuncExpr *expr);
|
|
||||||
|
|
||||||
LibertyPortSet ports_;
|
|
||||||
LibertyPortSet::ConstIterator iter_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,9 @@
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "Iterator.hh"
|
#include "Iterator.hh"
|
||||||
#include "Map.hh"
|
|
||||||
#include "Vector.hh"
|
|
||||||
#include "ObjectTable.hh"
|
#include "ObjectTable.hh"
|
||||||
#include "LibertyClass.hh"
|
#include "LibertyClass.hh"
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
|
|
@ -44,12 +43,12 @@ namespace sta {
|
||||||
class MinMax;
|
class MinMax;
|
||||||
class Sdc;
|
class Sdc;
|
||||||
|
|
||||||
typedef ObjectTable<Vertex> VertexTable;
|
using VertexTable = ObjectTable<Vertex>;
|
||||||
typedef ObjectTable<Edge> EdgeTable;
|
using EdgeTable = ObjectTable<Edge>;
|
||||||
typedef Map<const Pin*, Vertex*> PinVertexMap;
|
using PinVertexMap = std::map<const Pin*, Vertex*>;
|
||||||
typedef Iterator<Edge*> VertexEdgeIterator;
|
using VertexEdgeIterator = Iterator<Edge*>;
|
||||||
typedef Map<const Pin*, float*, PinIdLess> PeriodCheckAnnotations;
|
using PeriodCheckAnnotations = std::map<const Pin*, float*, PinIdLess>;
|
||||||
typedef ObjectId EdgeId;
|
using EdgeId = ObjectId;
|
||||||
|
|
||||||
static constexpr EdgeId edge_id_null = object_id_null;
|
static constexpr EdgeId edge_id_null = object_id_null;
|
||||||
static constexpr ObjectIdx edge_idx_null = object_id_null;
|
static constexpr ObjectIdx edge_idx_null = object_id_null;
|
||||||
|
|
@ -94,10 +93,6 @@ public:
|
||||||
void deleteVertex(Vertex *vertex);
|
void deleteVertex(Vertex *vertex);
|
||||||
bool hasFaninOne(Vertex *vertex) const;
|
bool hasFaninOne(Vertex *vertex) const;
|
||||||
VertexId vertexCount() { return vertices_->size(); }
|
VertexId vertexCount() { return vertices_->size(); }
|
||||||
Path *makePaths(Vertex *vertex,
|
|
||||||
uint32_t count);
|
|
||||||
Path *paths(const Vertex *vertex) const;
|
|
||||||
void deletePaths(Vertex *vertex);
|
|
||||||
|
|
||||||
// Reported slew are the same as those in the liberty tables.
|
// Reported slew are the same as those in the liberty tables.
|
||||||
// reported_slews = measured_slews / slew_derate_from_library
|
// reported_slews = measured_slews / slew_derate_from_library
|
||||||
|
|
@ -163,8 +158,6 @@ public:
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
DcalcAPIndex ap_index,
|
DcalcAPIndex ap_index,
|
||||||
bool annotated);
|
bool annotated);
|
||||||
// True if any edge arc is annotated.
|
|
||||||
bool delayAnnotated(Edge *edge);
|
|
||||||
|
|
||||||
void minPulseWidthArc(Vertex *vertex,
|
void minPulseWidthArc(Vertex *vertex,
|
||||||
const RiseFall *hi_low,
|
const RiseFall *hi_low,
|
||||||
|
|
@ -188,7 +181,8 @@ public:
|
||||||
|
|
||||||
// Remove all delay and slew annotations.
|
// Remove all delay and slew annotations.
|
||||||
void removeDelaySlewAnnotations();
|
void removeDelaySlewAnnotations();
|
||||||
VertexSet *regClkVertices() { return reg_clk_vertices_; }
|
VertexSet ®ClkVertices() { return reg_clk_vertices_; }
|
||||||
|
void makeSceneAfter();
|
||||||
|
|
||||||
static constexpr int vertex_level_bits = 24;
|
static constexpr int vertex_level_bits = 24;
|
||||||
static constexpr int vertex_level_max = (1<<vertex_level_bits)-1;
|
static constexpr int vertex_level_max = (1<<vertex_level_bits)-1;
|
||||||
|
|
@ -233,7 +227,7 @@ protected:
|
||||||
// Sdf period check annotations.
|
// Sdf period check annotations.
|
||||||
PeriodCheckAnnotations *period_check_annotations_;
|
PeriodCheckAnnotations *period_check_annotations_;
|
||||||
// Register/latch clock vertices to search from.
|
// Register/latch clock vertices to search from.
|
||||||
VertexSet *reg_clk_vertices_;
|
VertexSet reg_clk_vertices_;
|
||||||
|
|
||||||
friend class Vertex;
|
friend class Vertex;
|
||||||
friend class VertexIterator;
|
friend class VertexIterator;
|
||||||
|
|
@ -253,21 +247,23 @@ public:
|
||||||
std::string to_string(const StaState *sta) const;
|
std::string to_string(const StaState *sta) const;
|
||||||
// compatibility
|
// compatibility
|
||||||
const char *name(const Network *network) const;
|
const char *name(const Network *network) const;
|
||||||
bool isBidirectDriver() const { return is_bidirect_drvr_; }
|
[[nodiscard]] bool isBidirectDriver() const { return is_bidirect_drvr_; }
|
||||||
bool isDriver(const Network *network) const;
|
[[nodiscard]] bool isDriver(const Network *network) const;
|
||||||
Level level() const { return level_; }
|
Level level() const { return level_; }
|
||||||
void setLevel(Level level);
|
void setLevel(Level level);
|
||||||
bool visited() const { return visited1_; }
|
[[nodiscard]] bool visited() const { return visited1_; }
|
||||||
void setVisited(bool visited);
|
void setVisited(bool visited);
|
||||||
bool visited2() const { return visited2_; }
|
[[nodiscard]] bool visited2() const { return visited2_; }
|
||||||
void setVisited2(bool visited);
|
void setVisited2(bool visited);
|
||||||
bool isRoot() const{ return level_ == 0; }
|
[[nodiscard]] bool isRoot() const{ return level_ == 0; }
|
||||||
bool hasFanin() const;
|
[[nodiscard]] bool hasFanin() const;
|
||||||
bool hasFanout() const;
|
[[nodiscard]] bool hasFanout() const;
|
||||||
Slew *slews() { return slews_; }
|
Slew *slews() { return slews_; }
|
||||||
const Slew *slews() const { return slews_; }
|
const Slew *slews() const { return slews_; }
|
||||||
Path *paths() const { return paths_; }
|
Path *paths() const { return paths_; }
|
||||||
|
Path *makePaths(uint32_t count);
|
||||||
void setPaths(Path *paths);
|
void setPaths(Path *paths);
|
||||||
|
void deletePaths();
|
||||||
TagGroupIndex tagGroupIndex() const;
|
TagGroupIndex tagGroupIndex() const;
|
||||||
void setTagGroupIndex(TagGroupIndex tag_index);
|
void setTagGroupIndex(TagGroupIndex tag_index);
|
||||||
// Slew is annotated by sdc set_annotated_transition cmd.
|
// Slew is annotated by sdc set_annotated_transition cmd.
|
||||||
|
|
@ -279,38 +275,24 @@ public:
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
DcalcAPIndex ap_index);
|
DcalcAPIndex ap_index);
|
||||||
void removeSlewAnnotated();
|
void removeSlewAnnotated();
|
||||||
// Constant zero/one from simulation.
|
|
||||||
bool isConstant() const;
|
|
||||||
LogicValue simValue() const;
|
|
||||||
void setSimValue(LogicValue value);
|
|
||||||
bool isDisabledConstraint() const { return is_disabled_constraint_; }
|
|
||||||
void setIsDisabledConstraint(bool disabled);
|
|
||||||
// True when vertex has timing check edges that constrain it.
|
// True when vertex has timing check edges that constrain it.
|
||||||
bool hasChecks() const { return has_checks_; }
|
[[nodiscard]] bool hasChecks() const { return has_checks_; }
|
||||||
void setHasChecks(bool has_checks);
|
void setHasChecks(bool has_checks);
|
||||||
bool isCheckClk() const { return is_check_clk_; }
|
[[nodiscard]] bool isCheckClk() const { return is_check_clk_; }
|
||||||
void setIsCheckClk(bool is_check_clk);
|
void setIsCheckClk(bool is_check_clk);
|
||||||
bool isGatedClkEnable() const { return is_gated_clk_enable_; }
|
[[nodiscard]] bool hasDownstreamClkPin() const { return has_downstream_clk_pin_; }
|
||||||
void setIsGatedClkEnable(bool enable);
|
|
||||||
bool hasDownstreamClkPin() const { return has_downstream_clk_pin_; }
|
|
||||||
void setHasDownstreamClkPin(bool has_clk_pin);
|
void setHasDownstreamClkPin(bool has_clk_pin);
|
||||||
// Vertices are constrained if they have one or more of the
|
[[nodiscard]] bool bfsInQueue(BfsIndex index) const;
|
||||||
// following timing constraints:
|
|
||||||
// output delay constraints
|
|
||||||
// data check constraints
|
|
||||||
// path delay constraints
|
|
||||||
bool isConstrained() const { return is_constrained_; }
|
|
||||||
void setIsConstrained(bool constrained);
|
|
||||||
bool bfsInQueue(BfsIndex index) const;
|
|
||||||
void setBfsInQueue(BfsIndex index, bool value);
|
void setBfsInQueue(BfsIndex index, bool value);
|
||||||
bool isRegClk() const { return is_reg_clk_; }
|
[[nodiscard]] bool isRegClk() const { return is_reg_clk_; }
|
||||||
|
// Has sim value in some mode.
|
||||||
|
[[nodiscard]] bool hasSimValue() const { return has_sim_value_; }
|
||||||
|
void setHasSimValue(bool has_sim);
|
||||||
|
|
||||||
// ObjectTable interface.
|
// ObjectTable interface.
|
||||||
ObjectIdx objectIdx() const { return object_idx_; }
|
[[nodiscard]] ObjectIdx objectIdx() const { return object_idx_; }
|
||||||
void setObjectIdx(ObjectIdx idx);
|
void setObjectIdx(ObjectIdx idx);
|
||||||
|
|
||||||
static int transitionCount() { return 2; } // rise/fall
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void init(Pin *pin,
|
void init(Pin *pin,
|
||||||
bool is_bidirect_drvr,
|
bool is_bidirect_drvr,
|
||||||
|
|
@ -336,23 +318,19 @@ protected:
|
||||||
|
|
||||||
int level_:Graph::vertex_level_bits; // 24
|
int level_:Graph::vertex_level_bits; // 24
|
||||||
unsigned int slew_annotated_:slew_annotated_bits; // 4
|
unsigned int slew_annotated_:slew_annotated_bits; // 4
|
||||||
// LogicValue gcc barfs if this is dcl'd.
|
|
||||||
unsigned sim_value_:3;
|
|
||||||
// Bidirect pins have two vertices.
|
// Bidirect pins have two vertices.
|
||||||
// This flag distinguishes the driver and load vertices.
|
// This flag distinguishes the driver and load vertices.
|
||||||
bool is_bidirect_drvr_:1;
|
bool is_bidirect_drvr_:1;
|
||||||
|
|
||||||
bool is_reg_clk_:1;
|
bool is_reg_clk_:1;
|
||||||
bool is_disabled_constraint_:1;
|
|
||||||
bool is_gated_clk_enable_:1;
|
|
||||||
// Constrained by timing check edge.
|
// Constrained by timing check edge.
|
||||||
bool has_checks_:1;
|
bool has_checks_:1;
|
||||||
// Is the clock for a timing check.
|
// Is the clock for a timing check.
|
||||||
bool is_check_clk_:1;
|
bool is_check_clk_:1;
|
||||||
bool is_constrained_:1;
|
|
||||||
bool has_downstream_clk_pin_:1;
|
bool has_downstream_clk_pin_:1;
|
||||||
bool visited1_:1;
|
bool visited1_:1;
|
||||||
bool visited2_:1;
|
bool visited2_:1;
|
||||||
|
bool has_sim_value_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Graph;
|
friend class Graph;
|
||||||
|
|
@ -382,18 +360,8 @@ public:
|
||||||
void setArcDelays(ArcDelay *arc_delays);
|
void setArcDelays(ArcDelay *arc_delays);
|
||||||
bool delay_Annotation_Is_Incremental() const {return delay_annotation_is_incremental_;};
|
bool delay_Annotation_Is_Incremental() const {return delay_annotation_is_incremental_;};
|
||||||
void setDelayAnnotationIsIncremental(bool is_incr);
|
void setDelayAnnotationIsIncremental(bool is_incr);
|
||||||
// Edge is disabled by set_disable_timing constraint.
|
|
||||||
bool isDisabledConstraint() const;
|
|
||||||
void setIsDisabledConstraint(bool disabled);
|
|
||||||
// Timing sense for the to_pin function after simplifying the
|
|
||||||
// function based constants on the instance pins.
|
|
||||||
TimingSense simTimingSense() const;
|
|
||||||
void setSimTimingSense(TimingSense sense);
|
|
||||||
// Edge is disabled by constants in condition (when) function.
|
|
||||||
bool isDisabledCond() const { return is_disabled_cond_; }
|
|
||||||
void setIsDisabledCond(bool disabled);
|
|
||||||
// Edge is disabled to break combinational loops.
|
// Edge is disabled to break combinational loops.
|
||||||
bool isDisabledLoop() const { return is_disabled_loop_; }
|
[[nodiscard]] bool isDisabledLoop() const { return is_disabled_loop_; }
|
||||||
void setIsDisabledLoop(bool disabled);
|
void setIsDisabledLoop(bool disabled);
|
||||||
// Edge is disabled to prevent converging clocks from merging (Xilinx).
|
// Edge is disabled to prevent converging clocks from merging (Xilinx).
|
||||||
bool isBidirectInstPath() const { return is_bidirect_inst_path_; }
|
bool isBidirectInstPath() const { return is_bidirect_inst_path_; }
|
||||||
|
|
@ -401,6 +369,10 @@ public:
|
||||||
bool isBidirectNetPath() const { return is_bidirect_net_path_; }
|
bool isBidirectNetPath() const { return is_bidirect_net_path_; }
|
||||||
void setIsBidirectNetPath(bool is_bidir);
|
void setIsBidirectNetPath(bool is_bidir);
|
||||||
void removeDelayAnnotated();
|
void removeDelayAnnotated();
|
||||||
|
[[nodiscard]] bool hasSimSense() const { return has_sim_sense_; }
|
||||||
|
void setHasSimSense(bool has_sense);
|
||||||
|
[[nodiscard]] bool hasDisabledCond() const { return has_disabled_cond_; }
|
||||||
|
void setHasDisabledCond(bool has_disabled);
|
||||||
|
|
||||||
// ObjectTable interface.
|
// ObjectTable interface.
|
||||||
ObjectIdx objectIdx() const { return object_idx_; }
|
ObjectIdx objectIdx() const { return object_idx_; }
|
||||||
|
|
@ -435,11 +407,9 @@ protected:
|
||||||
bool delay_annotation_is_incremental_:1;
|
bool delay_annotation_is_incremental_:1;
|
||||||
bool is_bidirect_inst_path_:1;
|
bool is_bidirect_inst_path_:1;
|
||||||
bool is_bidirect_net_path_:1;
|
bool is_bidirect_net_path_:1;
|
||||||
// Timing sense from function and constants on edge instance.
|
|
||||||
unsigned sim_timing_sense_:timing_sense_bit_count;
|
|
||||||
bool is_disabled_constraint_:1;
|
|
||||||
bool is_disabled_cond_:1;
|
|
||||||
bool is_disabled_loop_:1;
|
bool is_disabled_loop_:1;
|
||||||
|
bool has_sim_sense_:1;
|
||||||
|
bool has_disabled_cond_:1;
|
||||||
unsigned object_idx_:VertexTable::idx_bits;
|
unsigned object_idx_:VertexTable::idx_bits;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -456,7 +426,7 @@ private:
|
||||||
class VertexIterator : public Iterator<Vertex*>
|
class VertexIterator : public Iterator<Vertex*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit VertexIterator(Graph *graph);
|
VertexIterator(Graph *graph);
|
||||||
virtual bool hasNext() { return vertex_ || bidir_vertex_; }
|
virtual bool hasNext() { return vertex_ || bidir_vertex_; }
|
||||||
virtual Vertex *next();
|
virtual Vertex *next();
|
||||||
|
|
||||||
|
|
@ -508,29 +478,19 @@ public:
|
||||||
EdgesThruHierPinIterator(const Pin *hpin,
|
EdgesThruHierPinIterator(const Pin *hpin,
|
||||||
Network *network,
|
Network *network,
|
||||||
Graph *graph);
|
Graph *graph);
|
||||||
virtual bool hasNext() { return edge_iter_.hasNext(); }
|
virtual bool hasNext();
|
||||||
virtual Edge *next() { return edge_iter_.next(); }
|
virtual Edge *next();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EdgeSet edges_;
|
EdgeSet edges_;
|
||||||
EdgeSet::Iterator edge_iter_;
|
EdgeSet::iterator edge_iter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VertexIdLess
|
// Helper function to create a VertexSet with the comparator initialized
|
||||||
|
inline VertexSet
|
||||||
|
makeVertexSet(StaState *sta)
|
||||||
{
|
{
|
||||||
public:
|
return VertexSet(VertexIdLess(sta->graphRef()));
|
||||||
VertexIdLess(Graph *&graph);
|
}
|
||||||
bool operator()(const Vertex *vertex1,
|
|
||||||
const Vertex *vertex2) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Graph *&graph_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class VertexSet : public Set<Vertex*, VertexIdLess>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VertexSet(Graph *&graph);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "ObjectId.hh"
|
#include "ObjectId.hh"
|
||||||
#include "Set.hh"
|
|
||||||
#include "Vector.hh"
|
|
||||||
#include "MinMax.hh"
|
#include "MinMax.hh"
|
||||||
#include "Transition.hh"
|
#include "Transition.hh"
|
||||||
#include "Delay.hh"
|
#include "Delay.hh"
|
||||||
|
|
@ -42,19 +42,29 @@ class Edge;
|
||||||
class VertexIterator;
|
class VertexIterator;
|
||||||
class VertexInEdgeIterator;
|
class VertexInEdgeIterator;
|
||||||
class VertexOutEdgeIterator;
|
class VertexOutEdgeIterator;
|
||||||
class GraphLoop;
|
|
||||||
class VertexSet;
|
|
||||||
|
|
||||||
typedef ObjectId VertexId;
|
class VertexIdLess
|
||||||
typedef ObjectId EdgeId;
|
{
|
||||||
typedef Vector<Vertex*> VertexSeq;
|
public:
|
||||||
typedef Vector<Edge*> EdgeSeq;
|
VertexIdLess() = delete;
|
||||||
typedef Set<Edge*> EdgeSet;
|
VertexIdLess(Graph *&graph);
|
||||||
typedef int Level;
|
bool operator()(const Vertex *vertex1,
|
||||||
typedef int DcalcAPIndex;
|
const Vertex *vertex2) const;
|
||||||
typedef int TagGroupIndex;
|
|
||||||
typedef Vector<GraphLoop*> GraphLoopSeq;
|
private:
|
||||||
typedef std::vector<Slew> SlewSeq;
|
Graph *&graph_;
|
||||||
|
};
|
||||||
|
|
||||||
|
using VertexId = ObjectId;
|
||||||
|
using EdgeId = ObjectId;
|
||||||
|
using VertexSeq = std::vector<Vertex*>;
|
||||||
|
using VertexSet = std::set<Vertex*, VertexIdLess>;
|
||||||
|
using EdgeSeq = std::vector<Edge*>;
|
||||||
|
using EdgeSet = std::set<Edge*>;
|
||||||
|
using Level = int;
|
||||||
|
using DcalcAPIndex = int;
|
||||||
|
using TagGroupIndex = int;
|
||||||
|
using SlewSeq = std::vector<Slew>;
|
||||||
|
|
||||||
static constexpr int level_max = std::numeric_limits<Level>::max();
|
static constexpr int level_max = std::numeric_limits<Level>::max();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace sta {
|
||||||
class VertexNameLess
|
class VertexNameLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit VertexNameLess(Network *network);
|
VertexNameLess(Network *network);
|
||||||
bool operator()(const Vertex *vertex1,
|
bool operator()(const Vertex *vertex1,
|
||||||
const Vertex *vertex2);
|
const Vertex *vertex2);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,15 +24,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <mutex>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include "Map.hh"
|
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
#include "GraphClass.hh"
|
#include "GraphClass.hh"
|
||||||
#include "SearchClass.hh"
|
#include "SearchClass.hh"
|
||||||
#include "DcalcAnalysisPt.hh"
|
#include "SdcClass.hh"
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
#include "ArcDelayCalc.hh"
|
#include "ArcDelayCalc.hh"
|
||||||
|
|
||||||
|
|
@ -42,9 +42,10 @@ class DelayCalcObserver;
|
||||||
class MultiDrvrNet;
|
class MultiDrvrNet;
|
||||||
class FindVertexDelays;
|
class FindVertexDelays;
|
||||||
class NetCaps;
|
class NetCaps;
|
||||||
|
class SearchPred;
|
||||||
|
|
||||||
typedef Map<const Vertex*, MultiDrvrNet*> MultiDrvrNetMap;
|
using MultiDrvrNetMap = std::map<const Vertex*, MultiDrvrNet*>;
|
||||||
typedef std::vector<SlewSeq> DrvrLoadSlews;
|
using DrvrLoadSlews = std::vector<SlewSeq>;
|
||||||
|
|
||||||
// This class traverses the graph calling the arc delay calculator and
|
// This class traverses the graph calling the arc delay calculator and
|
||||||
// annotating delays on graph edges.
|
// annotating delays on graph edges.
|
||||||
|
|
@ -73,7 +74,7 @@ public:
|
||||||
// Returned string is owned by the caller.
|
// Returned string is owned by the caller.
|
||||||
virtual std::string reportDelayCalc(const Edge *edge,
|
virtual std::string reportDelayCalc(const Edge *edge,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
int digits);
|
int digits);
|
||||||
// Percentage (0.0:1.0) change in delay that causes downstream
|
// Percentage (0.0:1.0) change in delay that causes downstream
|
||||||
|
|
@ -82,19 +83,23 @@ public:
|
||||||
virtual void setIncrementalDelayTolerance(float tol);
|
virtual void setIncrementalDelayTolerance(float tol);
|
||||||
|
|
||||||
float loadCap(const Pin *drvr_pin,
|
float loadCap(const Pin *drvr_pin,
|
||||||
const DcalcAnalysisPt *dcalc_ap) const;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) const;
|
||||||
float loadCap(const Pin *drvr_pin,
|
float loadCap(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap) const;
|
const Scene *scene,
|
||||||
|
const MinMax *min_max) const;
|
||||||
void loadCap(const Pin *drvr_pin,
|
void loadCap(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
// Return values.
|
// Return values.
|
||||||
float &pin_cap,
|
float &pin_cap,
|
||||||
float &wire_cap) const;
|
float &wire_cap) const;
|
||||||
void netCaps(const Pin *drvr_pin,
|
void netCaps(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
// Return values.
|
// Return values.
|
||||||
float &pin_cap,
|
float &pin_cap,
|
||||||
float &wire_cap,
|
float &wire_cap,
|
||||||
|
|
@ -102,7 +107,8 @@ public:
|
||||||
bool &has_set_load) const;
|
bool &has_set_load) const;
|
||||||
void parasiticLoad(const Pin *drvr_pin,
|
void parasiticLoad(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
const MultiDrvrNet *multi_drvr,
|
const MultiDrvrNet *multi_drvr,
|
||||||
ArcDelayCalc *arc_delay_calc,
|
ArcDelayCalc *arc_delay_calc,
|
||||||
// Return values.
|
// Return values.
|
||||||
|
|
@ -112,14 +118,15 @@ public:
|
||||||
void findDriverArcDelays(Vertex *drvr_vertex,
|
void findDriverArcDelays(Vertex *drvr_vertex,
|
||||||
Edge *edge,
|
Edge *edge,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
ArcDelayCalc *arc_delay_calc);
|
ArcDelayCalc *arc_delay_calc);
|
||||||
// Precedence:
|
// Precedence:
|
||||||
// SDF annotation
|
// SDF annotation
|
||||||
// Liberty port timing group timing_type minimum_period.
|
// Liberty port timing group timing_type minimum_period.
|
||||||
// Liberty port min_period attribute.
|
// Liberty port min_period attribute.
|
||||||
void minPeriod(const Pin *pin,
|
void minPeriod(const Pin *pin,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
// Return values.
|
// Return values.
|
||||||
float &min_period,
|
float &min_period,
|
||||||
bool &exists);
|
bool &exists);
|
||||||
|
|
@ -127,11 +134,13 @@ public:
|
||||||
Slew edgeFromSlew(const Vertex *from_vertex,
|
Slew edgeFromSlew(const Vertex *from_vertex,
|
||||||
const RiseFall *from_rf,
|
const RiseFall *from_rf,
|
||||||
const Edge *edge,
|
const Edge *edge,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const Scene *scene,
|
||||||
|
const MinMax *min_max);
|
||||||
Slew edgeFromSlew(const Vertex *from_vertex,
|
Slew edgeFromSlew(const Vertex *from_vertex,
|
||||||
const RiseFall *from_rf,
|
const RiseFall *from_rf,
|
||||||
const TimingRole *role,
|
const TimingRole *role,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const Scene *scene,
|
||||||
|
const MinMax *min_max);
|
||||||
bool bidirectDrvrSlewFromLoad(const Pin *pin) const;
|
bool bidirectDrvrSlewFromLoad(const Pin *pin) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -145,13 +154,15 @@ protected:
|
||||||
void seedNoDrvrSlew(Vertex *drvr_vertex,
|
void seedNoDrvrSlew(Vertex *drvr_vertex,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
ArcDelayCalc *arc_delay_calc);
|
ArcDelayCalc *arc_delay_calc);
|
||||||
void seedNoDrvrCellSlew(Vertex *drvr_vertex,
|
void seedNoDrvrCellSlew(Vertex *drvr_vertex,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const InputDrive *drive,
|
const InputDrive *drive,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
ArcDelayCalc *arc_delay_calc);
|
ArcDelayCalc *arc_delay_calc);
|
||||||
void seedLoadSlew(Vertex *vertex);
|
void seedLoadSlew(Vertex *vertex);
|
||||||
void setInputPortWireDelays(Vertex *vertex);
|
void setInputPortWireDelays(Vertex *vertex);
|
||||||
|
|
@ -162,7 +173,8 @@ protected:
|
||||||
const LibertyPort *from_port,
|
const LibertyPort *from_port,
|
||||||
float *from_slews,
|
float *from_slews,
|
||||||
const LibertyPort *to_port,
|
const LibertyPort *to_port,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const Scene *scene,
|
||||||
|
const MinMax *min_max);
|
||||||
LibertyPort *driveCellDefaultFromPort(const LibertyCell *cell,
|
LibertyPort *driveCellDefaultFromPort(const LibertyCell *cell,
|
||||||
const LibertyPort *to_port);
|
const LibertyPort *to_port);
|
||||||
int findPortIndex(const LibertyCell *cell,
|
int findPortIndex(const LibertyCell *cell,
|
||||||
|
|
@ -171,7 +183,8 @@ protected:
|
||||||
Vertex *drvr_vertex,
|
Vertex *drvr_vertex,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
float from_slew,
|
float from_slew,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const Scene *scene,
|
||||||
|
const MinMax *min_max);
|
||||||
void findDriverDelays(Vertex *drvr_vertex,
|
void findDriverDelays(Vertex *drvr_vertex,
|
||||||
ArcDelayCalc *arc_delay_calc,
|
ArcDelayCalc *arc_delay_calc,
|
||||||
LoadPinIndexMap &load_pin_index_map);
|
LoadPinIndexMap &load_pin_index_map);
|
||||||
|
|
@ -196,14 +209,16 @@ protected:
|
||||||
const MultiDrvrNet *multi_drvr,
|
const MultiDrvrNet *multi_drvr,
|
||||||
Edge *edge,
|
Edge *edge,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
ArcDelayCalc *arc_delay_calc,
|
ArcDelayCalc *arc_delay_calc,
|
||||||
LoadPinIndexMap &load_pin_index_map);
|
LoadPinIndexMap &load_pin_index_map);
|
||||||
ArcDcalcArgSeq makeArcDcalcArgs(Vertex *drvr_vertex,
|
ArcDcalcArgSeq makeArcDcalcArgs(Vertex *drvr_vertex,
|
||||||
const MultiDrvrNet *multi_drvr,
|
const MultiDrvrNet *multi_drvr,
|
||||||
Edge *edge,
|
Edge *edge,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
ArcDelayCalc *arc_delay_calc);
|
ArcDelayCalc *arc_delay_calc);
|
||||||
void findParallelEdge(Vertex *vertex,
|
void findParallelEdge(Vertex *vertex,
|
||||||
const TimingArc *drvr_arc,
|
const TimingArc *drvr_arc,
|
||||||
|
|
@ -225,34 +240,40 @@ protected:
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
ArcDcalcResult &dcalc_result,
|
ArcDcalcResult &dcalc_result,
|
||||||
LoadPinIndexMap &load_pin_index_map,
|
LoadPinIndexMap &load_pin_index_map,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const Scene *scene,
|
||||||
|
const MinMax *min_max);
|
||||||
|
|
||||||
bool annotateDelaySlew(Edge *edge,
|
bool annotateDelaySlew(Edge *edge,
|
||||||
const TimingArc *arc,
|
const TimingArc *arc,
|
||||||
ArcDelay &gate_delay,
|
ArcDelay &gate_delay,
|
||||||
Slew &gate_slew,
|
Slew &gate_slew,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const Scene *scene,
|
||||||
|
const MinMax *min_max);
|
||||||
bool annotateLoadDelays(Vertex *drvr_vertex,
|
bool annotateLoadDelays(Vertex *drvr_vertex,
|
||||||
const RiseFall *drvr_rf,
|
const RiseFall *drvr_rf,
|
||||||
ArcDcalcResult &dcalc_result,
|
ArcDcalcResult &dcalc_result,
|
||||||
LoadPinIndexMap &load_pin_index_map,
|
LoadPinIndexMap &load_pin_index_map,
|
||||||
const ArcDelay &extra_delay,
|
const ArcDelay &extra_delay,
|
||||||
bool merge,
|
bool merge,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const Scene *scene,
|
||||||
|
const MinMax *min_max);
|
||||||
void findLatchEdgeDelays(Edge *edge);
|
void findLatchEdgeDelays(Edge *edge);
|
||||||
void findCheckEdgeDelays(Edge *edge,
|
void findCheckEdgeDelays(Edge *edge,
|
||||||
ArcDelayCalc *arc_delay_calc);
|
ArcDelayCalc *arc_delay_calc);
|
||||||
void deleteMultiDrvrNets();
|
void deleteMultiDrvrNets();
|
||||||
Slew checkEdgeClkSlew(const Vertex *from_vertex,
|
Slew checkEdgeClkSlew(const Vertex *from_vertex,
|
||||||
const RiseFall *from_rf,
|
const RiseFall *from_rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap);
|
const Scene *scene,
|
||||||
|
const MinMax *min_max);
|
||||||
float loadCap(const Pin *drvr_pin,
|
float loadCap(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
ArcDelayCalc *arc_delay_calc) const;
|
ArcDelayCalc *arc_delay_calc) const;
|
||||||
void parasiticLoad(const Pin *drvr_pin,
|
void parasiticLoad(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
const MultiDrvrNet *multi_drvr,
|
const MultiDrvrNet *multi_drvr,
|
||||||
ArcDelayCalc *arc_delay_calc,
|
ArcDelayCalc *arc_delay_calc,
|
||||||
// Return values.
|
// Return values.
|
||||||
|
|
@ -261,7 +282,8 @@ protected:
|
||||||
const Parasitic *¶sitic) const;
|
const Parasitic *¶sitic) const;
|
||||||
void netCaps(const Pin *drvr_pin,
|
void netCaps(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
const MultiDrvrNet *multi_drvr,
|
const MultiDrvrNet *multi_drvr,
|
||||||
// Return values.
|
// Return values.
|
||||||
float &pin_cap,
|
float &pin_cap,
|
||||||
|
|
@ -275,7 +297,7 @@ protected:
|
||||||
bool incremental_;
|
bool incremental_;
|
||||||
bool delays_exist_;
|
bool delays_exist_;
|
||||||
// Vertices with invalid -to delays.
|
// Vertices with invalid -to delays.
|
||||||
VertexSet *invalid_delays_;
|
VertexSet invalid_delays_;
|
||||||
// Timing check edges with invalid delays.
|
// Timing check edges with invalid delays.
|
||||||
EdgeSet invalid_check_edges_;
|
EdgeSet invalid_check_edges_;
|
||||||
// Latch D->Q edges with invalid delays.
|
// Latch D->Q edges with invalid delays.
|
||||||
|
|
@ -284,7 +306,6 @@ protected:
|
||||||
std::mutex invalid_edge_lock_;
|
std::mutex invalid_edge_lock_;
|
||||||
SearchPred *search_pred_;
|
SearchPred *search_pred_;
|
||||||
SearchPred *search_non_latch_pred_;
|
SearchPred *search_non_latch_pred_;
|
||||||
SearchPred *clk_pred_;
|
|
||||||
BfsFwdIterator *iter_;
|
BfsFwdIterator *iter_;
|
||||||
MultiDrvrNetMap multi_drvr_net_map_;
|
MultiDrvrNetMap multi_drvr_net_map_;
|
||||||
std::mutex multi_drvr_lock_;
|
std::mutex multi_drvr_lock_;
|
||||||
|
|
@ -319,13 +340,14 @@ public:
|
||||||
Vertex *dcalcDrvr() const { return dcalc_drvr_; }
|
Vertex *dcalcDrvr() const { return dcalc_drvr_; }
|
||||||
void setDcalcDrvr(Vertex *drvr);
|
void setDcalcDrvr(Vertex *drvr);
|
||||||
void netCaps(const RiseFall *rf,
|
void netCaps(const RiseFall *rf,
|
||||||
const DcalcAnalysisPt *dcalc_ap,
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
// Return values.
|
// Return values.
|
||||||
float &pin_cap,
|
float &pin_cap,
|
||||||
float &wire_cap,
|
float &wire_cap,
|
||||||
float &fanout,
|
float &fanout,
|
||||||
bool &has_net_load) const;
|
bool &has_net_load) const;
|
||||||
void findCaps(const Sdc *sdc);
|
void findCaps(const StaState *sta);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Driver that triggers delay calculation for all the drivers on the net.
|
// Driver that triggers delay calculation for all the drivers on the net.
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Set.hh"
|
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class InputDriveCell;
|
||||||
class InputDrive
|
class InputDrive
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit InputDrive();
|
InputDrive();
|
||||||
~InputDrive();
|
~InputDrive();
|
||||||
void setSlew(const RiseFallBoth *rf,
|
void setSlew(const RiseFallBoth *rf,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ protected:
|
||||||
class InternalPowerModel
|
class InternalPowerModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit InternalPowerModel(TableModel *model);
|
InternalPowerModel(TableModel *model);
|
||||||
~InternalPowerModel();
|
~InternalPowerModel();
|
||||||
float power(const LibertyCell *cell,
|
float power(const LibertyCell *cell,
|
||||||
const Pvt *pvt,
|
const Pvt *pvt,
|
||||||
|
|
|
||||||
|
|
@ -40,4 +40,80 @@ public:
|
||||||
virtual OBJ next() = 0;
|
virtual OBJ next() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename VECTOR_TYPE, typename OBJ_TYPE>
|
||||||
|
class VectorIterator : public Iterator<OBJ_TYPE>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VectorIterator(const VECTOR_TYPE *seq) :
|
||||||
|
seq_(seq)
|
||||||
|
{
|
||||||
|
if (seq_)
|
||||||
|
itr_ = seq_->begin();
|
||||||
|
}
|
||||||
|
VectorIterator(const VECTOR_TYPE &seq) :
|
||||||
|
seq_(&seq),
|
||||||
|
itr_(seq.begin())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasNext() { return seq_ && itr_ != seq_->end(); }
|
||||||
|
OBJ_TYPE next() { return *itr_++; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const VECTOR_TYPE *seq_;
|
||||||
|
VECTOR_TYPE::const_iterator itr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename MAP_TYPE, typename OBJ_TYPE>
|
||||||
|
class MapIterator : public Iterator<OBJ_TYPE>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MapIterator(const MAP_TYPE *map) :
|
||||||
|
map_(map)
|
||||||
|
{
|
||||||
|
if (map)
|
||||||
|
itr_ = map->begin();
|
||||||
|
}
|
||||||
|
MapIterator(const MAP_TYPE &map) :
|
||||||
|
map_(&map),
|
||||||
|
itr_(map.begin())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasNext() { return map_ && itr_ != map_->end(); }
|
||||||
|
OBJ_TYPE next() {
|
||||||
|
OBJ_TYPE next = itr_->second;
|
||||||
|
itr_++;
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const MAP_TYPE *map_;
|
||||||
|
MAP_TYPE::const_iterator itr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename SET_TYPE, typename OBJ_TYPE>
|
||||||
|
class SetIterator : public Iterator<OBJ_TYPE>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SetIterator(const SET_TYPE *set) :
|
||||||
|
set_(set)
|
||||||
|
{
|
||||||
|
if (set)
|
||||||
|
itr_ = set->begin();
|
||||||
|
}
|
||||||
|
SetIterator(const SET_TYPE &set) :
|
||||||
|
set_(&set),
|
||||||
|
itr_(set.begin())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasNext() { return set_ && itr_ != set_->end(); }
|
||||||
|
OBJ_TYPE next() { return *itr_++; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const SET_TYPE *set_;
|
||||||
|
SET_TYPE::const_iterator itr_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,11 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "ContainerHelpers.hh"
|
||||||
#include "MinMax.hh"
|
#include "MinMax.hh"
|
||||||
#include "RiseFallMinMax.hh"
|
#include "RiseFallMinMax.hh"
|
||||||
#include "ConcreteLibrary.hh"
|
#include "ConcreteLibrary.hh"
|
||||||
|
|
@ -56,40 +60,37 @@ class OcvDerate;
|
||||||
class TimingArcAttrs;
|
class TimingArcAttrs;
|
||||||
class InternalPowerAttrs;
|
class InternalPowerAttrs;
|
||||||
class StaState;
|
class StaState;
|
||||||
class Corner;
|
class Scene;
|
||||||
class Corners;
|
|
||||||
class DcalcAnalysisPt;
|
|
||||||
class DriverWaveform;
|
class DriverWaveform;
|
||||||
|
|
||||||
typedef Map<const char*, TableTemplate*, CharPtrLess> TableTemplateMap;
|
using TableTemplateMap = std::map<const char*, TableTemplate*, CharPtrLess>;
|
||||||
typedef Vector<TableTemplate*> TableTemplateSeq;
|
using TableTemplateSeq = std::vector<TableTemplate*>;
|
||||||
typedef Map<const char*, BusDcl *, CharPtrLess> BusDclMap;
|
using BusDclMap = std::map<const char*, BusDcl *, CharPtrLess>;
|
||||||
typedef Vector<BusDcl *> BusDclSeq;
|
using BusDclSeq = std::vector<BusDcl *>;
|
||||||
typedef Map<const char*, ScaleFactors*, CharPtrLess> ScaleFactorsMap;
|
using ScaleFactorsMap = std::map<const char*, ScaleFactors*, CharPtrLess>;
|
||||||
typedef Map<const char*, Wireload*, CharPtrLess> WireloadMap;
|
using WireloadMap = std::map<const char*, Wireload*, CharPtrLess>;
|
||||||
typedef Map<const char*, WireloadSelection*, CharPtrLess> WireloadSelectionMap;
|
using WireloadSelectionMap = std::map<const char*, WireloadSelection*, CharPtrLess>;
|
||||||
typedef Map<const char*, OperatingConditions*,
|
using OperatingConditionsMap = std::map<const char*, OperatingConditions*, CharPtrLess>;
|
||||||
CharPtrLess> OperatingConditionsMap;
|
using PortToSequentialMap = std::map<LibertyPort*, Sequential*>;
|
||||||
typedef Map<LibertyPort*, Sequential*> PortToSequentialMap;
|
using TimingArcSetSeq = std::vector<TimingArcSet*>;
|
||||||
typedef Vector<TimingArcSet*> TimingArcSetSeq;
|
using TimingArcSetSet = std::set<TimingArcSet*, TimingArcSetLess>;
|
||||||
typedef Set<TimingArcSet*, TimingArcSetLess> TimingArcSetMap;
|
using LibertyPortPairTimingArcMap = std::map<LibertyPortPair, TimingArcSetSeq*,
|
||||||
typedef Map<LibertyPortPair, TimingArcSetSeq*,
|
LibertyPortPairLess>;
|
||||||
LibertyPortPairLess> LibertyPortPairTimingArcMap;
|
using InternalPowerSeq = std::vector<InternalPower*>;
|
||||||
typedef Vector<InternalPower*> InternalPowerSeq;
|
using PortInternalPowerMap = std::map<const LibertyPort *, InternalPowerSeq>;
|
||||||
typedef Map<const LibertyPort *, InternalPowerSeq> PortInternalPowerSeq;
|
using LeakagePowerSeq = std::vector<LeakagePower*>;
|
||||||
typedef Vector<LeakagePower*> LeakagePowerSeq;
|
using LibertyPortTimingArcMap = std::map<const LibertyPort*, TimingArcSetSeq*>;
|
||||||
typedef Map<const LibertyPort*, TimingArcSetSeq*> LibertyPortTimingArcMap;
|
using ScaledCellMap = std::map<const OperatingConditions*, LibertyCell*>;
|
||||||
typedef Map<const OperatingConditions*, LibertyCell*> ScaledCellMap;
|
using ScaledPortMap = std::map<const OperatingConditions*, LibertyPort*>;
|
||||||
typedef Map<const OperatingConditions*, LibertyPort*> ScaledPortMap;
|
using ModeDefMap = std::map<const char *, ModeDef*, CharPtrLess>;
|
||||||
typedef Map<const char *, ModeDef*, CharPtrLess> ModeDefMap;
|
using ModeValueMap = std::map<const char *, ModeValueDef*, CharPtrLess>;
|
||||||
typedef Map<const char *, ModeValueDef*, CharPtrLess> ModeValueMap;
|
using LatchEnableMap = std::map<const TimingArcSet*, LatchEnable*>;
|
||||||
typedef Map<const TimingArcSet*, LatchEnable*> LatchEnableMap;
|
using LatchEnableSeq = std::vector<LatchEnable*>;
|
||||||
typedef Vector<LatchEnable*> LatchEnableSeq;
|
using OcvDerateMap = std::map<const char *, OcvDerate*, CharPtrLess>;
|
||||||
typedef Map<const char *, OcvDerate*, CharPtrLess> OcvDerateMap;
|
using InternalPowerAttrsSeq = std::vector<InternalPowerAttrs*>;
|
||||||
typedef Vector<InternalPowerAttrs*> InternalPowerAttrsSeq;
|
using SupplyVoltageMap = std::map<std::string, float>;
|
||||||
typedef Map<std::string, float> SupplyVoltageMap;
|
using DriverWaveformMap = std::map<std::string, DriverWaveform*>;
|
||||||
typedef Map<std::string, DriverWaveform*> DriverWaveformMap;
|
using SceneSeq = std::vector<Scene*>;
|
||||||
typedef Vector<DcalcAnalysisPt*> DcalcAnalysisPtSeq;
|
|
||||||
|
|
||||||
enum class ClockGateType { none, latch_posedge, latch_negedge, other };
|
enum class ClockGateType { none, latch_posedge, latch_negedge, other };
|
||||||
|
|
||||||
|
|
@ -316,24 +317,24 @@ public:
|
||||||
const char *filename);
|
const char *filename);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
makeCornerMap(LibertyLibrary *lib,
|
makeSceneMap(LibertyLibrary *lib,
|
||||||
int ap_index,
|
int ap_index,
|
||||||
Network *network,
|
Network *network,
|
||||||
Report *report);
|
Report *report);
|
||||||
static void
|
static void
|
||||||
makeCornerMap(LibertyCell *link_cell,
|
makeSceneMap(LibertyCell *link_cell,
|
||||||
LibertyCell *map_cell,
|
LibertyCell *map_cell,
|
||||||
int ap_index,
|
int ap_index,
|
||||||
Report *report);
|
Report *report);
|
||||||
static void
|
static void
|
||||||
makeCornerMap(LibertyCell *cell1,
|
makeSceneMap(LibertyCell *cell1,
|
||||||
LibertyCell *cell2,
|
LibertyCell *cell2,
|
||||||
bool link,
|
bool link,
|
||||||
int ap_index,
|
int ap_index,
|
||||||
Report *report);
|
Report *report);
|
||||||
static void
|
static void
|
||||||
checkCorners(LibertyCell *cell,
|
checkScenes(LibertyCell *cell,
|
||||||
Corners *corners,
|
const SceneSeq &scenes,
|
||||||
Report *report);
|
Report *report);
|
||||||
|
|
||||||
DriverWaveform *findDriverWaveform(const char *name);
|
DriverWaveform *findDriverWaveform(const char *name);
|
||||||
|
|
@ -404,12 +405,12 @@ private:
|
||||||
class LibertyCellIterator : public Iterator<LibertyCell*>
|
class LibertyCellIterator : public Iterator<LibertyCell*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit LibertyCellIterator(const LibertyLibrary *library);
|
LibertyCellIterator(const LibertyLibrary *library);
|
||||||
bool hasNext();
|
bool hasNext();
|
||||||
LibertyCell *next();
|
LibertyCell *next();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcreteCellMap::ConstIterator iter_;
|
ConcreteLibraryCellIterator iter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -497,11 +498,9 @@ public:
|
||||||
const FuncExpr *&enable_func,
|
const FuncExpr *&enable_func,
|
||||||
const RiseFall *&enable_rf) const;
|
const RiseFall *&enable_rf) const;
|
||||||
const RiseFall *latchCheckEnableEdge(TimingArcSet *check_set);
|
const RiseFall *latchCheckEnableEdge(TimingArcSet *check_set);
|
||||||
bool isDisabledConstraint() const { return is_disabled_constraint_; }
|
LibertyCell *sceneCell(const Scene *scene,
|
||||||
LibertyCell *cornerCell(const Corner *corner,
|
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
LibertyCell *cornerCell(const DcalcAnalysisPt *dcalc_ap);
|
LibertyCell *sceneCell(int ap_index);
|
||||||
LibertyCell *cornerCell(int ap_index);
|
|
||||||
|
|
||||||
// AOCV
|
// AOCV
|
||||||
float ocvArcDepth() const;
|
float ocvArcDepth() const;
|
||||||
|
|
@ -536,8 +535,7 @@ public:
|
||||||
void addOcvDerate(OcvDerate *derate);
|
void addOcvDerate(OcvDerate *derate);
|
||||||
void setTestCell(TestCell *test);
|
void setTestCell(TestCell *test);
|
||||||
void setHasInferedRegTimingArcs(bool infered);
|
void setHasInferedRegTimingArcs(bool infered);
|
||||||
void setIsDisabledConstraint(bool is_disabled);
|
void setSceneCell(LibertyCell *scene_cell,
|
||||||
void setCornerCell(LibertyCell *corner_cell,
|
|
||||||
int ap_index);
|
int ap_index);
|
||||||
// Call after cell is finished being constructed.
|
// Call after cell is finished being constructed.
|
||||||
void finish(bool infer_latches,
|
void finish(bool infer_latches,
|
||||||
|
|
@ -550,9 +548,9 @@ public:
|
||||||
LibertyPort *&input,
|
LibertyPort *&input,
|
||||||
LibertyPort *&output) const;
|
LibertyPort *&output) const;
|
||||||
// Check all liberty cells to make sure they exist
|
// Check all liberty cells to make sure they exist
|
||||||
// for all the defined corners.
|
// for all the defined scenes.
|
||||||
static void checkLibertyCorners();
|
static void checkLibertyScenes();
|
||||||
void ensureVoltageWaveforms(const DcalcAnalysisPtSeq &dcalc_aps);
|
void ensureVoltageWaveforms(const SceneSeq &scenes);
|
||||||
const char *footprint() const;
|
const char *footprint() const;
|
||||||
void setFootprint(const char *footprint);
|
void setFootprint(const char *footprint);
|
||||||
const char *userFunctionClass() const;
|
const char *userFunctionClass() const;
|
||||||
|
|
@ -594,7 +592,7 @@ protected:
|
||||||
const LibertyPort *output) const;
|
const LibertyPort *output) const;
|
||||||
bool hasInverterFunc(const LibertyPort *input,
|
bool hasInverterFunc(const LibertyPort *input,
|
||||||
const LibertyPort *output) const;
|
const LibertyPort *output) const;
|
||||||
bool checkCornerCell(const Corner *corner,
|
bool checkSceneCell(const Scene *scene,
|
||||||
const MinMax *min_max) const;
|
const MinMax *min_max) const;
|
||||||
|
|
||||||
LibertyLibrary *liberty_library_;
|
LibertyLibrary *liberty_library_;
|
||||||
|
|
@ -612,13 +610,13 @@ protected:
|
||||||
bool interface_timing_;
|
bool interface_timing_;
|
||||||
ClockGateType clock_gate_type_;
|
ClockGateType clock_gate_type_;
|
||||||
TimingArcSetSeq timing_arc_sets_;
|
TimingArcSetSeq timing_arc_sets_;
|
||||||
TimingArcSetMap timing_arc_set_map_;
|
TimingArcSetSet timing_arc_set_set_;
|
||||||
LibertyPortPairTimingArcMap port_timing_arc_set_map_;
|
LibertyPortPairTimingArcMap port_timing_arc_set_map_;
|
||||||
LibertyPortTimingArcMap timing_arc_set_from_map_;
|
LibertyPortTimingArcMap timing_arc_set_from_map_;
|
||||||
LibertyPortTimingArcMap timing_arc_set_to_map_;
|
LibertyPortTimingArcMap timing_arc_set_to_map_;
|
||||||
bool has_infered_reg_timing_arcs_;
|
bool has_infered_reg_timing_arcs_;
|
||||||
InternalPowerSeq internal_powers_;
|
InternalPowerSeq internal_powers_;
|
||||||
PortInternalPowerSeq port_internal_powers_;
|
PortInternalPowerMap port_internal_powers_;
|
||||||
InternalPowerAttrsSeq internal_power_attrs_;
|
InternalPowerAttrsSeq internal_power_attrs_;
|
||||||
LeakagePowerSeq leakage_powers_;
|
LeakagePowerSeq leakage_powers_;
|
||||||
SequentialSeq sequentials_;
|
SequentialSeq sequentials_;
|
||||||
|
|
@ -639,8 +637,7 @@ protected:
|
||||||
float ocv_arc_depth_;
|
float ocv_arc_depth_;
|
||||||
OcvDerate *ocv_derate_;
|
OcvDerate *ocv_derate_;
|
||||||
OcvDerateMap ocv_derate_map_;
|
OcvDerateMap ocv_derate_map_;
|
||||||
bool is_disabled_constraint_;
|
std::vector<LibertyCell*> scene_cells_;
|
||||||
Vector<LibertyCell*> corner_cells_;
|
|
||||||
float leakage_power_;
|
float leakage_power_;
|
||||||
bool leakage_power_exists_;
|
bool leakage_power_exists_;
|
||||||
bool has_internal_ports_;
|
bool has_internal_ports_;
|
||||||
|
|
@ -659,18 +656,18 @@ private:
|
||||||
class LibertyCellPortIterator : public Iterator<LibertyPort*>
|
class LibertyCellPortIterator : public Iterator<LibertyPort*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit LibertyCellPortIterator(const LibertyCell *cell);
|
LibertyCellPortIterator(const LibertyCell *cell);
|
||||||
bool hasNext();
|
bool hasNext();
|
||||||
LibertyPort *next();
|
LibertyPort *next();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcretePortSeq::ConstIterator iter_;
|
ConcreteCellPortIterator iter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LibertyCellPortBitIterator : public Iterator<LibertyPort*>
|
class LibertyCellPortBitIterator : public Iterator<LibertyPort*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit LibertyCellPortBitIterator(const LibertyCell *cell);
|
LibertyCellPortBitIterator(const LibertyCell *cell);
|
||||||
virtual ~LibertyCellPortBitIterator();
|
virtual ~LibertyCellPortBitIterator();
|
||||||
bool hasNext();
|
bool hasNext();
|
||||||
LibertyPort *next();
|
LibertyPort *next();
|
||||||
|
|
@ -814,17 +811,12 @@ public:
|
||||||
const RiseFall *pulseClkSense() const { return pulse_clk_sense_; }
|
const RiseFall *pulseClkSense() const { return pulse_clk_sense_; }
|
||||||
void setPulseClk(const RiseFall *rfigger,
|
void setPulseClk(const RiseFall *rfigger,
|
||||||
const RiseFall *sense);
|
const RiseFall *sense);
|
||||||
bool isDisabledConstraint() const { return is_disabled_constraint_; }
|
LibertyPort *scenePort(const Scene *scene,
|
||||||
void setIsDisabledConstraint(bool is_disabled);
|
|
||||||
LibertyPort *cornerPort(const Corner *corner,
|
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
const LibertyPort *cornerPort(const Corner *corner,
|
const LibertyPort *scenePort(const Scene *scene,
|
||||||
const MinMax *min_max) const;
|
const MinMax *min_max) const;
|
||||||
LibertyPort *cornerPort(const DcalcAnalysisPt *dcalc_ap);
|
const LibertyPort *scenePort(int ap_index) const;
|
||||||
const LibertyPort *cornerPort(const DcalcAnalysisPt *dcalc_ap) const;
|
void setScenePort(LibertyPort *scene_port,
|
||||||
LibertyPort *cornerPort(int ap_index);
|
|
||||||
const LibertyPort *cornerPort(int ap_index) const;
|
|
||||||
void setCornerPort(LibertyPort *corner_port,
|
|
||||||
int ap_index);
|
int ap_index);
|
||||||
const char *relatedGroundPin() const;
|
const char *relatedGroundPin() const;
|
||||||
void setRelatedGroundPin(const char *related_ground_pin);
|
void setRelatedGroundPin(const char *related_ground_pin);
|
||||||
|
|
@ -881,6 +873,7 @@ protected:
|
||||||
float,
|
float,
|
||||||
const MinMax *)> &setter);
|
const MinMax *)> &setter);
|
||||||
|
|
||||||
|
LibertyPort *scenePort(int ap_index);
|
||||||
|
|
||||||
LibertyCell *liberty_cell_;
|
LibertyCell *liberty_cell_;
|
||||||
BusDcl *bus_dcl_;
|
BusDcl *bus_dcl_;
|
||||||
|
|
@ -902,7 +895,7 @@ protected:
|
||||||
const RiseFall *pulse_clk_sense_;
|
const RiseFall *pulse_clk_sense_;
|
||||||
std::string related_ground_pin_;
|
std::string related_ground_pin_;
|
||||||
std::string related_power_pin_;
|
std::string related_power_pin_;
|
||||||
Vector<LibertyPort*> corner_ports_;
|
std::vector<LibertyPort*> scene_ports_;
|
||||||
ReceiverModelPtr receiver_model_;
|
ReceiverModelPtr receiver_model_;
|
||||||
DriverWaveform *driver_waveform_[RiseFall::index_count];
|
DriverWaveform *driver_waveform_[RiseFall::index_count];
|
||||||
// Redundant with clock_tree_path_delay timing arcs but faster to access.
|
// Redundant with clock_tree_path_delay timing arcs but faster to access.
|
||||||
|
|
@ -923,7 +916,6 @@ protected:
|
||||||
bool isolation_cell_enable_:1;
|
bool isolation_cell_enable_:1;
|
||||||
bool level_shifter_data_:1;
|
bool level_shifter_data_:1;
|
||||||
bool is_switch_:1;
|
bool is_switch_:1;
|
||||||
bool is_disabled_constraint_:1;
|
|
||||||
bool is_pad_:1;
|
bool is_pad_:1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -939,7 +931,7 @@ sortByName(const LibertyPortSet *set);
|
||||||
class LibertyPortMemberIterator : public Iterator<LibertyPort*>
|
class LibertyPortMemberIterator : public Iterator<LibertyPort*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit LibertyPortMemberIterator(const LibertyPort *port);
|
LibertyPortMemberIterator(const LibertyPort *port);
|
||||||
virtual ~LibertyPortMemberIterator();
|
virtual ~LibertyPortMemberIterator();
|
||||||
virtual bool hasNext();
|
virtual bool hasNext();
|
||||||
virtual LibertyPort *next();
|
virtual LibertyPort *next();
|
||||||
|
|
@ -990,7 +982,7 @@ protected:
|
||||||
class ScaleFactors
|
class ScaleFactors
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ScaleFactors(const char *name);
|
ScaleFactors(const char *name);
|
||||||
const char *name() const { return name_.c_str(); }
|
const char *name() const { return name_.c_str(); }
|
||||||
float scale(ScaleFactorType type,
|
float scale(ScaleFactorType type,
|
||||||
ScaleFactorPvt pvt,
|
ScaleFactorPvt pvt,
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
#include "Vector.hh"
|
#include <map>
|
||||||
#include "Map.hh"
|
#include <set>
|
||||||
#include "Set.hh"
|
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
|
|
@ -67,19 +66,19 @@ class ReceiverModel;
|
||||||
class Statetable;
|
class Statetable;
|
||||||
class StatetableRow;
|
class StatetableRow;
|
||||||
|
|
||||||
typedef Vector<LibertyLibrary*> LibertyLibrarySeq;
|
using LibertyLibrarySeq = std::vector<LibertyLibrary*>;
|
||||||
typedef Vector<LibertyCell*> LibertyCellSeq;
|
using LibertyCellSeq = std::vector<LibertyCell*>;
|
||||||
typedef Vector<Sequential*> SequentialSeq;
|
using SequentialSeq = std::vector<Sequential*>;
|
||||||
typedef Map<LibertyCell*, LibertyCellSeq*> LibertyCellEquivMap;
|
using LibertyCellEquivMap = std::map<LibertyCell*, LibertyCellSeq*>;
|
||||||
typedef Vector<LibertyPort*> LibertyPortSeq;
|
using LibertyPortSeq = std::vector<LibertyPort*>;
|
||||||
typedef Set<LibertyPort*> LibertyPortSet;
|
using LibertyPortSet = std::set<LibertyPort*>;
|
||||||
typedef std::pair<const LibertyPort*,const LibertyPort*> LibertyPortPair;
|
using LibertyPortPair = std::pair<const LibertyPort*,const LibertyPort*>;
|
||||||
typedef Set<LibertyCell*> LibertyCellSet;
|
using LibertyCellSet = std::set<LibertyCell*>;
|
||||||
typedef std::shared_ptr<Table> TablePtr;
|
using TablePtr = std::shared_ptr<Table>;
|
||||||
typedef std::shared_ptr<TimingArcAttrs> TimingArcAttrsPtr;
|
using TimingArcAttrsPtr = std::shared_ptr<TimingArcAttrs>;
|
||||||
typedef std::shared_ptr<TableAxis> TableAxisPtr;
|
using TableAxisPtr = std::shared_ptr<TableAxis>;
|
||||||
typedef std::shared_ptr<ReceiverModel> ReceiverModelPtr;
|
using ReceiverModelPtr = std::shared_ptr<ReceiverModel>;
|
||||||
typedef std::vector<StatetableRow> StatetableRows;
|
using StatetableRows = std::vector<StatetableRow>;
|
||||||
|
|
||||||
enum class ScaleFactorType : unsigned {
|
enum class ScaleFactorType : unsigned {
|
||||||
pin_cap,
|
pin_cap,
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ protected:
|
||||||
class CheckLinearModel : public CheckTimingModel
|
class CheckLinearModel : public CheckTimingModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CheckLinearModel(LibertyCell *cell,
|
CheckLinearModel(LibertyCell *cell,
|
||||||
float intrinsic);
|
float intrinsic);
|
||||||
ArcDelay checkDelay(const Pvt *pvt,
|
ArcDelay checkDelay(const Pvt *pvt,
|
||||||
float from_slew,
|
float from_slew,
|
||||||
|
|
|
||||||
|
|
@ -1,191 +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 <map>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace sta {
|
|
||||||
|
|
||||||
// Add convenience functions around STL container.
|
|
||||||
template <class KEY, class VALUE, class CMP = std::less<KEY>>
|
|
||||||
class Map : public std::map<KEY, VALUE, CMP>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Map() :
|
|
||||||
std::map<KEY, VALUE, CMP>()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
explicit Map(const CMP &cmp) :
|
|
||||||
std::map<KEY, VALUE, CMP>(cmp)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find out if key is in the set.
|
|
||||||
bool
|
|
||||||
hasKey(const KEY key) const
|
|
||||||
{
|
|
||||||
return this->find(key) != this->end();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the value corresponding to key.
|
|
||||||
VALUE
|
|
||||||
findKey(const KEY key) const
|
|
||||||
{
|
|
||||||
auto find_iter = this->find(key);
|
|
||||||
if (find_iter != this->end())
|
|
||||||
return find_iter->second;
|
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
void
|
|
||||||
findKey(const KEY key,
|
|
||||||
// Return Values.
|
|
||||||
VALUE &value,
|
|
||||||
bool &exists) const
|
|
||||||
{
|
|
||||||
auto find_iter = this->find(key);
|
|
||||||
if (find_iter != this->end()) {
|
|
||||||
value = find_iter->second;
|
|
||||||
exists = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
exists = false;
|
|
||||||
}
|
|
||||||
void
|
|
||||||
findKey(const KEY &key,
|
|
||||||
// Return Values.
|
|
||||||
KEY &map_key,
|
|
||||||
VALUE &value,
|
|
||||||
bool &exists) const
|
|
||||||
{
|
|
||||||
auto find_iter = this->find(key);
|
|
||||||
if (find_iter != this->end()) {
|
|
||||||
map_key = find_iter->first;
|
|
||||||
value = find_iter->second;
|
|
||||||
exists = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
exists = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
insert(const KEY &key,
|
|
||||||
VALUE value)
|
|
||||||
{
|
|
||||||
this->operator[](key) = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
deleteContents()
|
|
||||||
{
|
|
||||||
Iterator iter(this);
|
|
||||||
while (iter.hasNext())
|
|
||||||
delete iter.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
deleteKeysContents()
|
|
||||||
{
|
|
||||||
for (const auto [key, value] : this) {
|
|
||||||
delete key;
|
|
||||||
delete value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
deleteArrayContents()
|
|
||||||
{
|
|
||||||
Iterator iter(this);
|
|
||||||
while (iter.hasNext())
|
|
||||||
delete [] iter.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
deleteContentsClear()
|
|
||||||
{
|
|
||||||
deleteContents();
|
|
||||||
std::map<KEY, VALUE, CMP>::clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Java style container itererator
|
|
||||||
// Map::Iterator<string *, Value, stringLess> iter(map);
|
|
||||||
// while (iter.hasNext()) {
|
|
||||||
// Value *v = iter.next();
|
|
||||||
// }
|
|
||||||
class Iterator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Iterator() : container_(nullptr) {}
|
|
||||||
explicit Iterator(std::map<KEY, VALUE, CMP> *container) :
|
|
||||||
container_(container)
|
|
||||||
{ if (container_ != nullptr) iter_ = container_->begin(); }
|
|
||||||
explicit Iterator(std::map<KEY, VALUE, CMP> &container) :
|
|
||||||
container_(&container)
|
|
||||||
{ if (container_ != nullptr) iter_ = container_->begin(); }
|
|
||||||
void init(std::map<KEY, VALUE, CMP> *container)
|
|
||||||
{ container_ = container; if (container_ != nullptr) iter_=container_->begin();}
|
|
||||||
void init(std::map<KEY, VALUE, CMP> &container)
|
|
||||||
{ container_ = &container; if (container_ != nullptr) iter_=container_->begin();}
|
|
||||||
bool hasNext() { return container_ != nullptr && iter_ != container_->end(); }
|
|
||||||
VALUE next() { return iter_++->second; }
|
|
||||||
void next(KEY &key,
|
|
||||||
VALUE &value)
|
|
||||||
{ key = iter_->first; value = iter_->second; iter_++; }
|
|
||||||
std::map<KEY, VALUE, CMP> *container() { return container_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::map<KEY, VALUE, CMP> *container_;
|
|
||||||
typename std::map<KEY, VALUE, CMP>::iterator iter_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ConstIterator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ConstIterator() : container_(nullptr) {}
|
|
||||||
explicit ConstIterator(const std::map<KEY, VALUE, CMP> *container) :
|
|
||||||
container_(container)
|
|
||||||
{ if (container_ != nullptr) iter_ = container_->begin(); }
|
|
||||||
explicit ConstIterator(const std::map<KEY, VALUE, CMP> &container) :
|
|
||||||
container_(&container)
|
|
||||||
{ if (container_ != nullptr) iter_ = container_->begin(); }
|
|
||||||
void init(const std::map<KEY, VALUE, CMP> *container)
|
|
||||||
{ container_ = container; if (container_ != nullptr) iter_=container_->begin();}
|
|
||||||
void init(const std::map<KEY, VALUE, CMP> &container)
|
|
||||||
{ container_ = &container; if (container_ != nullptr) iter_=container_->begin();}
|
|
||||||
bool hasNext() { return container_ != nullptr && iter_ != container_->end(); }
|
|
||||||
VALUE next() { return iter_++->second; }
|
|
||||||
void next(KEY &key,
|
|
||||||
VALUE &value)
|
|
||||||
{ key = iter_->first; value = iter_->second; iter_++; }
|
|
||||||
const std::map<KEY, VALUE, CMP> *container() { return container_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::map<KEY, VALUE, CMP> *container_;
|
|
||||||
typename std::map<KEY, VALUE, CMP>::const_iterator iter_;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
@ -36,8 +36,8 @@ class MinMax;
|
||||||
class MinMaxAll;
|
class MinMaxAll;
|
||||||
|
|
||||||
// Use typedefs to make early/late functional equivalents to min/max.
|
// Use typedefs to make early/late functional equivalents to min/max.
|
||||||
typedef MinMax EarlyLate;
|
using EarlyLate = MinMax;
|
||||||
typedef MinMaxAll EarlyLateAll;
|
using EarlyLateAll = MinMaxAll;
|
||||||
|
|
||||||
// Large value used for min/max initial values.
|
// Large value used for min/max initial values.
|
||||||
extern const float INF;
|
extern const float INF;
|
||||||
|
|
@ -112,6 +112,7 @@ public:
|
||||||
static const MinMaxAll *max() { return &max_; }
|
static const MinMaxAll *max() { return &max_; }
|
||||||
static const MinMaxAll *late() { return &max_; }
|
static const MinMaxAll *late() { return &max_; }
|
||||||
static const MinMaxAll *all() { return &all_; }
|
static const MinMaxAll *all() { return &all_; }
|
||||||
|
static const MinMaxAll *minMax() { return &all_; }
|
||||||
const std::string &to_string() const { return name_; }
|
const std::string &to_string() const { return name_; }
|
||||||
int index() const { return index_; }
|
int index() const { return index_; }
|
||||||
const MinMax *asMinMax() const;
|
const MinMax *asMinMax() const;
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ private:
|
||||||
bool exists_[MinMax::index_count];
|
bool exists_[MinMax::index_count];
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef MinMaxValues<float> MinMaxFloatValues;
|
using MinMaxFloatValues = MinMaxValues<float>;
|
||||||
typedef MinMaxValues<int> MinMaxIntValues;
|
using MinMaxIntValues = MinMaxValues<int>;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
// 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 <string>
|
||||||
|
|
||||||
|
#include "StaState.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
class Sdc;
|
||||||
|
class Sim;
|
||||||
|
class ClkNetwork;
|
||||||
|
class Genclks;
|
||||||
|
class PathGroups;
|
||||||
|
|
||||||
|
using PathGroupSeq = std::vector<PathGroup*>;
|
||||||
|
|
||||||
|
// Sdc and dependent state.
|
||||||
|
class Mode : public StaState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mode(const std::string &name,
|
||||||
|
size_t mode_index,
|
||||||
|
StaState *sta);
|
||||||
|
virtual ~Mode();
|
||||||
|
virtual void copyState(const StaState *sta);
|
||||||
|
void clear();
|
||||||
|
const std::string &name() const { return name_; }
|
||||||
|
size_t modeIndex() const { return mode_index_; }
|
||||||
|
const SceneSeq &scenes() const { return scenes_; }
|
||||||
|
const SceneSet sceneSet() const;
|
||||||
|
void addScene(Scene *scene);
|
||||||
|
void removeScene(Scene *scene);
|
||||||
|
Sdc *sdc() { return sdc_; }
|
||||||
|
Sdc *sdc() const { return sdc_; }
|
||||||
|
Sim *sim() { return sim_; }
|
||||||
|
Sim *sim() const { return sim_; }
|
||||||
|
ClkNetwork *clkNetwork() { return clk_network_; }
|
||||||
|
ClkNetwork *clkNetwork() const { return clk_network_; }
|
||||||
|
Genclks *genclks() { return genclks_; }
|
||||||
|
Genclks *genclks() const { return genclks_; }
|
||||||
|
PathGroups *pathGroups() { return path_groups_; }
|
||||||
|
PathGroups *pathGroups() const { return path_groups_; }
|
||||||
|
PathGroupSeq pathGroups(const PathEnd *path_end) const;
|
||||||
|
PathGroups *makePathGroups(int group_path_count,
|
||||||
|
int endpoint_path_count,
|
||||||
|
bool unique_pins,
|
||||||
|
bool unique_edges,
|
||||||
|
float min_slack,
|
||||||
|
float max_slack,
|
||||||
|
StdStringSeq &group_names,
|
||||||
|
bool setup,
|
||||||
|
bool hold,
|
||||||
|
bool recovery,
|
||||||
|
bool removal,
|
||||||
|
bool clk_gating_setup,
|
||||||
|
bool clk_gating_hold,
|
||||||
|
bool unconstrained_paths);
|
||||||
|
void deletePathGroups();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name_;
|
||||||
|
size_t mode_index_;
|
||||||
|
SceneSeq scenes_;
|
||||||
|
Sdc *sdc_;
|
||||||
|
Sim *sim_;
|
||||||
|
ClkNetwork *clk_network_;
|
||||||
|
Genclks *genclks_;
|
||||||
|
PathGroups *path_groups_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -29,6 +29,6 @@
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
// Hide a bit of the std verbosity.
|
// Hide a bit of the std verbosity.
|
||||||
typedef std::lock_guard<std::mutex> LockGuard;
|
using LockGuard = std::lock_guard<std::mutex>;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "Map.hh"
|
|
||||||
#include "StringUtil.hh"
|
#include "StringUtil.hh"
|
||||||
#include "LibertyClass.hh"
|
#include "LibertyClass.hh"
|
||||||
#include "VertexId.hh"
|
#include "VertexId.hh"
|
||||||
|
|
@ -39,12 +39,12 @@ class Report;
|
||||||
class PatternMatch;
|
class PatternMatch;
|
||||||
class PinVisitor;
|
class PinVisitor;
|
||||||
|
|
||||||
typedef Map<const char*, LibertyLibrary*, CharPtrLess> LibertyLibraryMap;
|
using LibertyLibraryMap = std::map<const char*, LibertyLibrary*, CharPtrLess>;
|
||||||
// Link network function returns top level instance.
|
// Link network function returns top level instance.
|
||||||
// Return nullptr if link fails.
|
// Return nullptr if link fails.
|
||||||
typedef std::function<Instance* (const char *top_cell_name,
|
using LinkNetworkFunc = std::function<Instance* (const char *top_cell_name,
|
||||||
bool make_black_boxes)> LinkNetworkFunc;
|
bool make_black_boxes)>;
|
||||||
typedef Map<const Net*, PinSet*> NetDrvrPinsMap;
|
using NetDrvrPinsMap = std::map<const Net*, PinSet*>;
|
||||||
|
|
||||||
// The Network class defines the network API used by sta.
|
// The Network class defines the network API used by sta.
|
||||||
// The interface to a network implementation is constructed by
|
// The interface to a network implementation is constructed by
|
||||||
|
|
@ -132,10 +132,10 @@ public:
|
||||||
virtual LibertyLibrary *defaultLibertyLibrary() const;
|
virtual LibertyLibrary *defaultLibertyLibrary() const;
|
||||||
void setDefaultLibertyLibrary(LibertyLibrary *library);
|
void setDefaultLibertyLibrary(LibertyLibrary *library);
|
||||||
// Check liberty cells used by the network to make sure they exist
|
// Check liberty cells used by the network to make sure they exist
|
||||||
// for all the defined corners.
|
// for all the defined scenes.
|
||||||
void checkNetworkLibertyCorners();
|
void checkNetworkLibertyScenes();
|
||||||
// Check liberty cells to make sure they exist for all the defined corners.
|
// Check liberty cells to make sure they exist for all the defined scenes.
|
||||||
void checkLibertyCorners();
|
void checkLibertyScenes();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
// Cell functions.
|
// Cell functions.
|
||||||
|
|
@ -303,8 +303,8 @@ public:
|
||||||
virtual Term *term(const Pin *pin) const = 0;
|
virtual Term *term(const Pin *pin) const = 0;
|
||||||
virtual PortDirection *direction(const Pin *pin) const = 0;
|
virtual PortDirection *direction(const Pin *pin) const = 0;
|
||||||
virtual bool isLeaf(const Pin *pin) const;
|
virtual bool isLeaf(const Pin *pin) const;
|
||||||
bool isHierarchical(const Pin *pin) const;
|
[[nodiscard]] bool isHierarchical(const Pin *pin) const;
|
||||||
bool isTopLevelPort(const Pin *pin) const;
|
[[nodiscard]] bool isTopLevelPort(const Pin *pin) const;
|
||||||
// Is pin inside the instance hier_pin is attached to?
|
// Is pin inside the instance hier_pin is attached to?
|
||||||
bool isInside(const Pin *pin,
|
bool isInside(const Pin *pin,
|
||||||
const Pin *hier_pin) const;
|
const Pin *hier_pin) const;
|
||||||
|
|
@ -620,7 +620,7 @@ public:
|
||||||
NetworkConstantPinIterator(const Network *network,
|
NetworkConstantPinIterator(const Network *network,
|
||||||
NetSet &zero_nets,
|
NetSet &zero_nets,
|
||||||
NetSet &one_nets);
|
NetSet &one_nets);
|
||||||
~NetworkConstantPinIterator();
|
virtual ~NetworkConstantPinIterator() {}
|
||||||
virtual bool hasNext();
|
virtual bool hasNext();
|
||||||
virtual void next(const Pin *&pin, LogicValue &value);
|
virtual void next(const Pin *&pin, LogicValue &value);
|
||||||
|
|
||||||
|
|
@ -631,7 +631,7 @@ private:
|
||||||
const Network *network_;
|
const Network *network_;
|
||||||
PinSet constant_pins_[2];
|
PinSet constant_pins_[2];
|
||||||
LogicValue value_;
|
LogicValue value_;
|
||||||
PinSet::Iterator *pin_iter_;
|
PinSet::iterator pin_iter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Abstract base class for visitDrvrLoadsThruHierPin visitor.
|
// Abstract base class for visitDrvrLoadsThruHierPin visitor.
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,11 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "Set.hh"
|
|
||||||
#include "Vector.hh"
|
|
||||||
#include "Iterator.hh"
|
#include "Iterator.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
@ -49,30 +50,31 @@ class ConstantPinIterator;
|
||||||
class ViewType;
|
class ViewType;
|
||||||
class LibertyLibrary;
|
class LibertyLibrary;
|
||||||
|
|
||||||
typedef Iterator<Library*> LibraryIterator;
|
using LibraryIterator = Iterator<Library*>;
|
||||||
typedef Iterator<LibertyLibrary*> LibertyLibraryIterator;
|
using LibertyLibraryIterator = Iterator<LibertyLibrary*>;
|
||||||
typedef Vector<Cell*> CellSeq;
|
using CellSeq = std::vector<Cell*>;
|
||||||
typedef Vector<const Port*> PortSeq;
|
using PortSeq = std::vector<const Port*>;
|
||||||
typedef Iterator<Port*> CellPortIterator;
|
using CellPortIterator = Iterator<Port*>;
|
||||||
typedef Iterator<Port*> CellPortBitIterator;
|
using CellPortBitIterator = Iterator<Port*>;
|
||||||
typedef Iterator<Port*> PortMemberIterator;
|
using PortMemberIterator = Iterator<Port*>;
|
||||||
|
|
||||||
typedef Vector<const Pin*> PinSeq;
|
using PinSeq = std::vector<const Pin*>;
|
||||||
typedef Vector<const Instance*> InstanceSeq;
|
using PinUnorderedSet = std::unordered_set<const Pin*>;
|
||||||
typedef Vector<const Net*> NetSeq;
|
using InstanceSeq = std::vector<const Instance*>;
|
||||||
typedef std::vector<const Net*> ConstNetSeq;
|
using NetSeq = std::vector<const Net*>;
|
||||||
typedef Iterator<Instance*> InstanceChildIterator;
|
using ConstNetSeq = std::vector<const Net*>;
|
||||||
typedef Iterator<Pin*> InstancePinIterator;
|
using InstanceChildIterator = Iterator<Instance*>;
|
||||||
typedef Iterator<Net*> InstanceNetIterator;
|
using InstancePinIterator = Iterator<Pin*>;
|
||||||
typedef Iterator<Instance*> LeafInstanceIterator;
|
using InstanceNetIterator = Iterator<Net*>;
|
||||||
typedef Iterator<Net*> NetIterator;
|
using LeafInstanceIterator = Iterator<Instance*>;
|
||||||
typedef Iterator<const Pin*> NetPinIterator;
|
using NetIterator = Iterator<Net*>;
|
||||||
typedef Iterator<Term*> NetTermIterator;
|
using NetPinIterator = Iterator<const Pin*>;
|
||||||
typedef Iterator<const Pin*> ConnectedPinIterator;
|
using NetTermIterator = Iterator<Term*>;
|
||||||
typedef ConnectedPinIterator NetConnectedPinIterator;
|
using ConnectedPinIterator = Iterator<const Pin*>;
|
||||||
typedef ConnectedPinIterator PinConnectedPinIterator;
|
using NetConnectedPinIterator = ConnectedPinIterator;
|
||||||
typedef uint32_t ObjectId;
|
using PinConnectedPinIterator = ConnectedPinIterator;
|
||||||
typedef std::map<std::string, std::string> AttributeMap;
|
using ObjectId = uint32_t;
|
||||||
|
using AttributeMap = std::map<std::string, std::string>;
|
||||||
|
|
||||||
enum class LogicValue : unsigned { zero, one, unknown, rise, fall };
|
enum class LogicValue : unsigned { zero, one, unknown, rise, fall };
|
||||||
|
|
||||||
|
|
@ -138,55 +140,37 @@ private:
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class CellSet : public Set<const Cell*, CellIdLess>
|
class CellSet : public std::set<const Cell*, CellIdLess>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CellSet(const Network *network);
|
CellSet(const Network *network);
|
||||||
};
|
};
|
||||||
|
|
||||||
class PortSet : public Set<const Port*, PortIdLess>
|
class PortSet : public std::set<const Port*, PortIdLess>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PortSet(const Network *network);
|
PortSet(const Network *network);
|
||||||
};
|
};
|
||||||
|
|
||||||
class InstanceSet : public Set<const Instance*, InstanceIdLess>
|
class InstanceSet : public std::set<const Instance*, InstanceIdLess>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InstanceSet();
|
InstanceSet();
|
||||||
InstanceSet(const Network *network);
|
InstanceSet(const Network *network);
|
||||||
static int compare(const InstanceSet *set1,
|
|
||||||
const InstanceSet *set2,
|
|
||||||
const Network *network);
|
|
||||||
static bool intersects(const InstanceSet *set1,
|
|
||||||
const InstanceSet *set2,
|
|
||||||
const Network *network);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PinSet : public Set<const Pin*, PinIdLess>
|
class PinSet : public std::set<const Pin*, PinIdLess>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PinSet();
|
PinSet();
|
||||||
PinSet(const Network *network);
|
PinSet(const Network *network);
|
||||||
static int compare(const PinSet *set1,
|
|
||||||
const PinSet *set2,
|
|
||||||
const Network *network);
|
|
||||||
static bool intersects(const PinSet *set1,
|
|
||||||
const PinSet *set2,
|
|
||||||
const Network *network);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NetSet : public Set<const Net*, NetIdLess>
|
class NetSet : public std::set<const Net*, NetIdLess>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NetSet();
|
NetSet();
|
||||||
NetSet(const Network *network);
|
NetSet(const Network *network);
|
||||||
static int compare(const NetSet *set1,
|
|
||||||
const NetSet *set2,
|
|
||||||
const Network *network);
|
|
||||||
static bool intersects(const NetSet *set1,
|
|
||||||
const NetSet *set2,
|
|
||||||
const Network *network);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ namespace sta {
|
||||||
class PortNameLess
|
class PortNameLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PortNameLess(const Network *network);
|
PortNameLess(const Network *network);
|
||||||
bool operator()(const Port *port1,
|
bool operator()(const Port *port1,
|
||||||
const Port *port2) const;
|
const Port *port2) const;
|
||||||
|
|
||||||
|
|
@ -45,7 +45,7 @@ private:
|
||||||
class PinPathNameLess
|
class PinPathNameLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PinPathNameLess(const Network *network);
|
PinPathNameLess(const Network *network);
|
||||||
bool operator()(const Pin *pin1,
|
bool operator()(const Pin *pin1,
|
||||||
const Pin *pin2) const;
|
const Pin *pin2) const;
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ private:
|
||||||
class InstancePathNameLess
|
class InstancePathNameLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit InstancePathNameLess(const Network *network);
|
InstancePathNameLess(const Network *network);
|
||||||
bool operator()(const Instance *inst1,
|
bool operator()(const Instance *inst1,
|
||||||
const Instance *inst2) const;
|
const Instance *inst2) const;
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ private:
|
||||||
class NetPathNameLess
|
class NetPathNameLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit NetPathNameLess(const Network *network);
|
NetPathNameLess(const Network *network);
|
||||||
bool operator()(const Net *net1,
|
bool operator()(const Net *net1,
|
||||||
const Net *net2) const;
|
const Net *net2) const;
|
||||||
|
|
||||||
|
|
@ -78,6 +78,9 @@ private:
|
||||||
PinSeq
|
PinSeq
|
||||||
sortByPathName(const PinSet *set,
|
sortByPathName(const PinSet *set,
|
||||||
const Network *network);
|
const Network *network);
|
||||||
|
PinSeq
|
||||||
|
sortByPathName(const PinUnorderedSet *set,
|
||||||
|
const Network *network);
|
||||||
PortSeq
|
PortSeq
|
||||||
sortByName(const PortSet *set,
|
sortByName(const PortSet *set,
|
||||||
const Network *network);
|
const Network *network);
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,11 @@
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
// ObjectId is block index and object index within the block.
|
// ObjectId is block index and object index within the block.
|
||||||
typedef uint32_t ObjectId;
|
using ObjectId = uint32_t;
|
||||||
// Block index.
|
// Block index.
|
||||||
typedef uint32_t BlockIdx;
|
using BlockIdx = uint32_t;
|
||||||
// Object index within a block.
|
// Object index within a block.
|
||||||
typedef uint32_t ObjectIdx;
|
using ObjectIdx = uint32_t;
|
||||||
|
|
||||||
static constexpr int object_id_bits = sizeof(ObjectId) * 8;
|
static constexpr int object_id_bits = sizeof(ObjectId) * 8;
|
||||||
static constexpr BlockIdx block_idx_null = 0;
|
static constexpr BlockIdx block_idx_null = 0;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Vector.hh"
|
#include <vector>
|
||||||
|
|
||||||
|
#include "ContainerHelpers.hh"
|
||||||
#include "Error.hh"
|
#include "Error.hh"
|
||||||
#include "ObjectId.hh"
|
#include "ObjectId.hh"
|
||||||
|
|
||||||
|
|
@ -71,7 +73,7 @@ private:
|
||||||
size_t size_;
|
size_t size_;
|
||||||
// Object ID of next free object.
|
// Object ID of next free object.
|
||||||
ObjectId free_;
|
ObjectId free_;
|
||||||
Vector<TableBlock<TYPE>*> blocks_;
|
std::vector<TableBlock<TYPE>*> blocks_;
|
||||||
static constexpr ObjectId idx_mask_ = block_object_count - 1;
|
static constexpr ObjectId idx_mask_ = block_object_count - 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -85,7 +87,7 @@ ObjectTable<TYPE>::ObjectTable() :
|
||||||
template <class TYPE>
|
template <class TYPE>
|
||||||
ObjectTable<TYPE>::~ObjectTable()
|
ObjectTable<TYPE>::~ObjectTable()
|
||||||
{
|
{
|
||||||
blocks_.deleteContents();
|
deleteContents(blocks_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class TYPE>
|
template <class TYPE>
|
||||||
|
|
@ -181,7 +183,7 @@ template <class TYPE>
|
||||||
void
|
void
|
||||||
ObjectTable<TYPE>::clear()
|
ObjectTable<TYPE>::clear()
|
||||||
{
|
{
|
||||||
blocks_.deleteContentsClear();
|
deleteContents(blocks_);;
|
||||||
size_ = 0;
|
size_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,40 +37,36 @@
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
class Wireload;
|
class Wireload;
|
||||||
class Corner;
|
class Scene;
|
||||||
|
|
||||||
typedef std::complex<float> ComplexFloat;
|
using ComplexFloat = std::complex<float>;
|
||||||
typedef Vector<ComplexFloat> ComplexFloatSeq;
|
using ComplexFloatSeq = std::vector<ComplexFloat>;
|
||||||
typedef std::vector<ParasiticNode*> ParasiticNodeSeq;
|
using ParasiticNodeSeq = std::vector<ParasiticNode*>;
|
||||||
typedef std::vector<ParasiticResistor*> ParasiticResistorSeq;
|
using ParasiticResistorSeq = std::vector<ParasiticResistor*>;
|
||||||
typedef std::vector<ParasiticCapacitor*> ParasiticCapacitorSeq;
|
using ParasiticCapacitorSeq = std::vector<ParasiticCapacitor*>;
|
||||||
typedef std::map<ParasiticNode *, ParasiticResistorSeq> ParasiticNodeResistorMap;
|
using ParasiticNodeResistorMap = std::map<ParasiticNode *, ParasiticResistorSeq>;
|
||||||
typedef std::map<ParasiticNode *, ParasiticCapacitorSeq> ParasiticNodeCapacitorMap;
|
using ParasiticNodeCapacitorMap = std::map<ParasiticNode *, ParasiticCapacitorSeq>;
|
||||||
|
|
||||||
// Parasitics API.
|
// Parasitics API.
|
||||||
// All parasitic parameters can have multiple values, each corresponding
|
|
||||||
// to an analysis point.
|
|
||||||
// Parasitic annotation for a pin or net may exist for one analysis point
|
|
||||||
// and not another.
|
|
||||||
class Parasitics : public StaState
|
class Parasitics : public StaState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Parasitics(StaState *sta);
|
Parasitics(StaState *sta);
|
||||||
virtual ~Parasitics() {}
|
virtual ~Parasitics() {}
|
||||||
|
virtual const std::string &name() const = 0;
|
||||||
|
virtual const std::string &filename() const = 0;
|
||||||
virtual bool haveParasitics() = 0;
|
virtual bool haveParasitics() = 0;
|
||||||
|
|
||||||
// Clear all state.
|
// Clear all state.
|
||||||
virtual void clear() = 0;
|
virtual void clear() = 0;
|
||||||
|
|
||||||
// Delete all parasitics.
|
// Delete all parasitics.
|
||||||
virtual void deleteParasitics() = 0;
|
virtual void deleteParasitics() = 0;
|
||||||
// Delete all parasitics on net at analysis point.
|
// Delete all parasitics on net at analysis point.
|
||||||
virtual void deleteParasitics(const Net *net,
|
virtual void deleteParasitics(const Net *net) = 0;
|
||||||
const ParasiticAnalysisPt *ap) = 0;
|
|
||||||
// Delete all parasitics on pin at analysis point.
|
// Delete all parasitics on pin at analysis point.
|
||||||
virtual void deleteParasitics(const Pin *pin,
|
virtual void deleteParasitics(const Pin *pin) = 0;
|
||||||
const ParasiticAnalysisPt *ap) = 0;
|
virtual void deleteReducedParasitics(const Net *net) = 0;
|
||||||
virtual void deleteReducedParasitics(const Net *net,
|
|
||||||
const ParasiticAnalysisPt *ap) = 0;
|
|
||||||
virtual void deleteDrvrReducedParasitics(const Pin *drvr_pin) = 0;
|
virtual void deleteDrvrReducedParasitics(const Pin *drvr_pin) = 0;
|
||||||
|
|
||||||
virtual bool isReducedParasiticNetwork(const Parasitic *parasitic) const = 0;
|
virtual bool isReducedParasiticNetwork(const Parasitic *parasitic) const = 0;
|
||||||
|
|
@ -88,10 +84,10 @@ public:
|
||||||
virtual bool isPiElmore(const Parasitic *parasitic) const = 0;
|
virtual bool isPiElmore(const Parasitic *parasitic) const = 0;
|
||||||
virtual Parasitic *findPiElmore(const Pin *drvr_pin,
|
virtual Parasitic *findPiElmore(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const ParasiticAnalysisPt *ap) const = 0;
|
const MinMax *min_max) const = 0;
|
||||||
virtual Parasitic *makePiElmore(const Pin *drvr_pin,
|
virtual Parasitic *makePiElmore(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const ParasiticAnalysisPt *ap,
|
const MinMax *min_max,
|
||||||
float c2,
|
float c2,
|
||||||
float rpi,
|
float rpi,
|
||||||
float c1) = 0;
|
float c1) = 0;
|
||||||
|
|
@ -126,10 +122,10 @@ public:
|
||||||
virtual bool isPiPoleResidue(const Parasitic* parasitic) const = 0;
|
virtual bool isPiPoleResidue(const Parasitic* parasitic) const = 0;
|
||||||
virtual Parasitic *findPiPoleResidue(const Pin *drvr_pin,
|
virtual Parasitic *findPiPoleResidue(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const ParasiticAnalysisPt *ap) const=0;
|
const MinMax *min_max) const = 0;
|
||||||
virtual Parasitic *makePiPoleResidue(const Pin *drvr_pin,
|
virtual Parasitic *makePiPoleResidue(const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const ParasiticAnalysisPt *ap,
|
const MinMax *min_max,
|
||||||
float c2,
|
float c2,
|
||||||
float rpi,
|
float rpi,
|
||||||
float c1) = 0;
|
float c1) = 0;
|
||||||
|
|
@ -154,22 +150,16 @@ public:
|
||||||
// This api assumes that parasitic networks are not rise/fall
|
// This api assumes that parasitic networks are not rise/fall
|
||||||
// dependent because they do not include pin capacitances.
|
// dependent because they do not include pin capacitances.
|
||||||
virtual bool isParasiticNetwork(const Parasitic *parasitic) const = 0;
|
virtual bool isParasiticNetwork(const Parasitic *parasitic) const = 0;
|
||||||
virtual Parasitic *findParasiticNetwork(const Net *net,
|
virtual Parasitic *findParasiticNetwork(const Net *net) = 0;
|
||||||
const ParasiticAnalysisPt *ap) const = 0;
|
virtual Parasitic *findParasiticNetwork(const Pin *pin) = 0;
|
||||||
virtual Parasitic *findParasiticNetwork(const Pin *pin,
|
|
||||||
const ParasiticAnalysisPt *ap) const = 0;
|
|
||||||
virtual Parasitic *makeParasiticNetwork(const Net *net,
|
virtual Parasitic *makeParasiticNetwork(const Net *net,
|
||||||
bool includes_pin_caps,
|
bool includes_pin_caps) = 0;
|
||||||
const ParasiticAnalysisPt *ap) = 0;
|
|
||||||
virtual ParasiticNodeSeq nodes(const Parasitic *parasitic) const = 0;
|
virtual ParasiticNodeSeq nodes(const Parasitic *parasitic) const = 0;
|
||||||
virtual void report(const Parasitic *parasitic) const;
|
virtual void report(const Parasitic *parasitic) const;
|
||||||
virtual const Net *net(const Parasitic *parasitic) const = 0;
|
virtual const Net *net(const Parasitic *parasitic) const = 0;
|
||||||
virtual ParasiticResistorSeq resistors(const Parasitic *parasitic) const = 0;
|
virtual ParasiticResistorSeq resistors(const Parasitic *parasitic) const = 0;
|
||||||
virtual ParasiticCapacitorSeq capacitors(const Parasitic *parasitic) const = 0;
|
virtual ParasiticCapacitorSeq capacitors(const Parasitic *parasitic) const = 0;
|
||||||
// Delete parasitic network if it exists.
|
virtual void deleteParasiticNetwork(const Net *net) = 0;
|
||||||
virtual void deleteParasiticNetwork(const Net *net,
|
|
||||||
const ParasiticAnalysisPt *ap) = 0;
|
|
||||||
virtual void deleteParasiticNetworks(const Net *net) = 0;
|
|
||||||
// True if the parasitic network caps include pin capacitances.
|
// True if the parasitic network caps include pin capacitances.
|
||||||
virtual bool includesPinCaps(const Parasitic *parasitic) const = 0;
|
virtual bool includesPinCaps(const Parasitic *parasitic) const = 0;
|
||||||
// Parasitic network component builders.
|
// Parasitic network component builders.
|
||||||
|
|
@ -248,17 +238,15 @@ public:
|
||||||
Parasitic *reduceToPiElmore(const Parasitic *parasitic,
|
Parasitic *reduceToPiElmore(const Parasitic *parasitic,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *cnst_min_max,
|
const MinMax *min_max);
|
||||||
const ParasiticAnalysisPt *ap);
|
|
||||||
// Reduce parasitic network to pi and 2nd order pole/residue models
|
// Reduce parasitic network to pi and 2nd order pole/residue models
|
||||||
// for drvr_pin.
|
// for drvr_pin.
|
||||||
Parasitic *reduceToPiPoleResidue2(const Parasitic *parasitic,
|
Parasitic *reduceToPiPoleResidue2(const Parasitic *parasitic,
|
||||||
const Pin *drvr_pin,
|
const Pin *drvr_pin,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *cnst_min_max,
|
const MinMax *min_max);
|
||||||
const ParasiticAnalysisPt *ap);
|
|
||||||
|
|
||||||
// Estimate parasitic as pi elmore using wireload model.
|
// Estimate parasitic as pi elmore using wireload model.
|
||||||
Parasitic *estimatePiElmore(const Pin *drvr_pin,
|
Parasitic *estimatePiElmore(const Pin *drvr_pin,
|
||||||
|
|
@ -266,18 +254,19 @@ public:
|
||||||
const Wireload *wireload,
|
const Wireload *wireload,
|
||||||
float fanout,
|
float fanout,
|
||||||
float net_pin_cap,
|
float net_pin_cap,
|
||||||
const Corner *corner,
|
const Scene *scene,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
Parasitic *makeWireloadNetwork(const Pin *drvr_pin,
|
Parasitic *makeWireloadNetwork(const Pin *drvr_pin,
|
||||||
const Wireload *wireload,
|
const Wireload *wireload,
|
||||||
float fanout,
|
float fanout,
|
||||||
const MinMax *min_max,
|
const Scene *scene,
|
||||||
const ParasiticAnalysisPt *ap);
|
const MinMax *min_max);
|
||||||
// Network edit before/after methods.
|
// Network edit before/after methods.
|
||||||
virtual void disconnectPinBefore(const Pin *pin,
|
virtual void disconnectPinBefore(const Pin *pin) = 0;
|
||||||
const Network *network) = 0;
|
|
||||||
virtual void deletePinBefore(const Pin *pin) = 0;
|
virtual void deletePinBefore(const Pin *pin) = 0;
|
||||||
virtual void loadPinCapacitanceChanged(const Pin *pin) = 0;
|
virtual void loadPinCapacitanceChanged(const Pin *pin) = 0;
|
||||||
|
float couplingCapFactor() const { return coupling_cap_factor_; }
|
||||||
|
void setCouplingCapFactor(float factor);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void makeWireloadNetworkWorst(Parasitic *parasitic,
|
void makeWireloadNetworkWorst(Parasitic *parasitic,
|
||||||
|
|
@ -298,35 +287,16 @@ protected:
|
||||||
float fanout);
|
float fanout);
|
||||||
|
|
||||||
const Net *findParasiticNet(const Pin *pin) const;
|
const Net *findParasiticNet(const Pin *pin) const;
|
||||||
};
|
|
||||||
|
|
||||||
// Managed by the Corner class.
|
|
||||||
class ParasiticAnalysisPt
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ParasiticAnalysisPt(const char *name,
|
|
||||||
int index,
|
|
||||||
int index_max);
|
|
||||||
const char *name() const { return name_.c_str(); }
|
|
||||||
int index() const { return index_; }
|
|
||||||
int indexMax() const { return index_max_; }
|
|
||||||
// Coupling capacitor factor used by all reduction functions.
|
|
||||||
float couplingCapFactor() const { return coupling_cap_factor_; }
|
|
||||||
void setCouplingCapFactor(float factor);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string name_;
|
|
||||||
int index_;
|
|
||||||
int index_max_;
|
|
||||||
float coupling_cap_factor_;
|
float coupling_cap_factor_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ParasiticNodeLess
|
class ParasiticNodeLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ParasiticNodeLess();
|
||||||
ParasiticNodeLess(const Parasitics *parasitics,
|
ParasiticNodeLess(const Parasitics *parasitics,
|
||||||
const Network *network);
|
const Network *network);
|
||||||
ParasiticNodeLess(const ParasiticNodeLess &less);
|
|
||||||
bool operator()(const ParasiticNode *node1,
|
bool operator()(const ParasiticNode *node1,
|
||||||
const ParasiticNode *node2) const;
|
const ParasiticNode *node2) const;
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ namespace sta {
|
||||||
class Parasitics;
|
class Parasitics;
|
||||||
class Parasitic;
|
class Parasitic;
|
||||||
class ParasiticNode;
|
class ParasiticNode;
|
||||||
class ParasiticAnalysisPt;
|
|
||||||
class ParasiticResistor;
|
class ParasiticResistor;
|
||||||
class ParasiticCapacitor;
|
class ParasiticCapacitor;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,6 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
class DcalcAnalysisPt;
|
|
||||||
|
|
||||||
class Path
|
class Path
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -60,7 +58,6 @@ public:
|
||||||
TimingArc *prev_arc,
|
TimingArc *prev_arc,
|
||||||
bool is_enum,
|
bool is_enum,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
~Path();
|
|
||||||
std::string to_string(const StaState *sta) const;
|
std::string to_string(const StaState *sta) const;
|
||||||
bool isNull() const;
|
bool isNull() const;
|
||||||
// prev_path null
|
// prev_path null
|
||||||
|
|
@ -86,6 +83,9 @@ public:
|
||||||
VertexId vertexId(const StaState *sta) const;
|
VertexId vertexId(const StaState *sta) const;
|
||||||
Pin *pin(const StaState *sta) const;
|
Pin *pin(const StaState *sta) const;
|
||||||
Tag *tag(const StaState *sta) const;
|
Tag *tag(const StaState *sta) const;
|
||||||
|
Scene *scene(const StaState *sta) const;
|
||||||
|
Mode *mode(const StaState *sta) const;
|
||||||
|
Sdc *sdc(const StaState *sta) const;
|
||||||
TagIndex tagIndex(const StaState *sta) const;
|
TagIndex tagIndex(const StaState *sta) const;
|
||||||
void setTag(Tag *tag);
|
void setTag(Tag *tag);
|
||||||
size_t pathIndex(const StaState *sta) const;
|
size_t pathIndex(const StaState *sta) const;
|
||||||
|
|
@ -96,9 +96,8 @@ public:
|
||||||
const RiseFall *transition(const StaState *sta) const;
|
const RiseFall *transition(const StaState *sta) const;
|
||||||
int rfIndex(const StaState *sta) const;
|
int rfIndex(const StaState *sta) const;
|
||||||
const MinMax *minMax(const StaState *sta) const;
|
const MinMax *minMax(const StaState *sta) const;
|
||||||
PathAnalysisPt *pathAnalysisPt(const StaState *sta) const;
|
|
||||||
PathAPIndex pathAnalysisPtIndex(const StaState *sta) const;
|
PathAPIndex pathAnalysisPtIndex(const StaState *sta) const;
|
||||||
DcalcAnalysisPt *dcalcAnalysisPt(const StaState *sta) const;
|
DcalcAPIndex dcalcAnalysisPtIndex(const StaState *sta) const;
|
||||||
Arrival &arrival() { return arrival_; }
|
Arrival &arrival() { return arrival_; }
|
||||||
const Arrival &arrival() const { return arrival_; }
|
const Arrival &arrival() const { return arrival_; }
|
||||||
void setArrival(Arrival arrival);
|
void setArrival(Arrival arrival);
|
||||||
|
|
@ -121,6 +120,8 @@ public:
|
||||||
void setIsEnum(bool is_enum);
|
void setIsEnum(bool is_enum);
|
||||||
void checkPrevPath(const StaState *sta) const;
|
void checkPrevPath(const StaState *sta) const;
|
||||||
|
|
||||||
|
const MinMax *tgtClkMinMax(const StaState *sta) const;
|
||||||
|
|
||||||
static Path *vertexPath(const Path *path,
|
static Path *vertexPath(const Path *path,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
static Path *vertexPath(const Path &path,
|
static Path *vertexPath(const Path &path,
|
||||||
|
|
@ -176,7 +177,7 @@ protected:
|
||||||
class PathLess
|
class PathLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PathLess(const StaState *sta);
|
PathLess(const StaState *sta);
|
||||||
bool operator()(const Path *path1,
|
bool operator()(const Path *path1,
|
||||||
const Path *path2) const;
|
const Path *path2) const;
|
||||||
|
|
||||||
|
|
@ -191,11 +192,10 @@ public:
|
||||||
// Iterate over all vertex paths.
|
// Iterate over all vertex paths.
|
||||||
VertexPathIterator(Vertex *vertex,
|
VertexPathIterator(Vertex *vertex,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
// Iterate over vertex paths with the same transition and
|
|
||||||
// analysis pt but different tags.
|
|
||||||
VertexPathIterator(Vertex *vertex,
|
VertexPathIterator(Vertex *vertex,
|
||||||
|
const Scene *scene,
|
||||||
|
const MinMax *min_max,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const PathAnalysisPt *path_ap,
|
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
// Iterate over vertex paths with the same transition and
|
// Iterate over vertex paths with the same transition and
|
||||||
// analysis pt min/max but different tags.
|
// analysis pt min/max but different tags.
|
||||||
|
|
@ -203,11 +203,6 @@ public:
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
VertexPathIterator(Vertex *vertex,
|
|
||||||
const RiseFall *rf,
|
|
||||||
const PathAnalysisPt *path_ap,
|
|
||||||
const MinMax *min_max,
|
|
||||||
const StaState *sta);
|
|
||||||
virtual ~VertexPathIterator();
|
virtual ~VertexPathIterator();
|
||||||
virtual bool hasNext();
|
virtual bool hasNext();
|
||||||
virtual Path *next();
|
virtual Path *next();
|
||||||
|
|
@ -216,10 +211,10 @@ private:
|
||||||
void findNext();
|
void findNext();
|
||||||
|
|
||||||
const Search *search_;
|
const Search *search_;
|
||||||
bool filtered_;
|
const Scene *scene_;
|
||||||
const RiseFall *rf_;
|
|
||||||
const PathAnalysisPt *path_ap_;
|
|
||||||
const MinMax *min_max_;
|
const MinMax *min_max_;
|
||||||
|
const RiseFall *rf_;
|
||||||
|
bool filtered_;
|
||||||
Path *paths_;
|
Path *paths_;
|
||||||
size_t path_count_;
|
size_t path_count_;
|
||||||
size_t path_index_;
|
size_t path_index_;
|
||||||
|
|
|
||||||
|
|
@ -1,69 +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 <string>
|
|
||||||
|
|
||||||
#include "Iterator.hh"
|
|
||||||
#include "MinMax.hh"
|
|
||||||
#include "SdcClass.hh"
|
|
||||||
#include "SearchClass.hh"
|
|
||||||
|
|
||||||
namespace sta {
|
|
||||||
|
|
||||||
class MinMax;
|
|
||||||
class DcalcAnalysisPt;
|
|
||||||
class Corner;
|
|
||||||
|
|
||||||
class PathAnalysisPt
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PathAnalysisPt(Corner *corner,
|
|
||||||
PathAPIndex index,
|
|
||||||
const MinMax *path_min_max,
|
|
||||||
DcalcAnalysisPt *dcalc_ap);
|
|
||||||
std::string to_string() const;
|
|
||||||
Corner *corner() const { return corner_; }
|
|
||||||
PathAPIndex index() const { return index_; }
|
|
||||||
const MinMax *pathMinMax() const { return path_min_max_; }
|
|
||||||
// Converging path arrival merging.
|
|
||||||
const MinMax *mergeMinMax() const { return path_min_max_; }
|
|
||||||
// Path analysis point for timing check target clock arrivals.
|
|
||||||
PathAnalysisPt *tgtClkAnalysisPt() const { return tgt_clk_ap_; }
|
|
||||||
void setTgtClkAnalysisPt(PathAnalysisPt *path_ap);
|
|
||||||
DcalcAnalysisPt *dcalcAnalysisPt() const { return dcalc_ap_; }
|
|
||||||
PathAnalysisPt *insertionAnalysisPt(const EarlyLate *early_late) const;
|
|
||||||
void setInsertionAnalysisPt(const EarlyLate *early_late, PathAnalysisPt *ap);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Corner *corner_;
|
|
||||||
PathAPIndex index_;
|
|
||||||
const MinMax *path_min_max_;
|
|
||||||
PathAnalysisPt *tgt_clk_ap_;
|
|
||||||
PathAnalysisPt *insertion_aps_[EarlyLate::index_count];
|
|
||||||
DcalcAnalysisPt *dcalc_ap_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
@ -59,7 +59,7 @@ class ReportPath;
|
||||||
class PathEnd
|
class PathEnd
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Type { unconstrained,
|
enum class Type { unconstrained,
|
||||||
check,
|
check,
|
||||||
data_check,
|
data_check,
|
||||||
latch_check,
|
latch_check,
|
||||||
|
|
@ -80,8 +80,6 @@ public:
|
||||||
const EarlyLate *pathEarlyLate(const StaState *sta) const;
|
const EarlyLate *pathEarlyLate(const StaState *sta) const;
|
||||||
virtual const EarlyLate *clkEarlyLate(const StaState *sta) const;
|
virtual const EarlyLate *clkEarlyLate(const StaState *sta) const;
|
||||||
const RiseFall *transition(const StaState *sta) const;
|
const RiseFall *transition(const StaState *sta) const;
|
||||||
PathAnalysisPt *pathAnalysisPt(const StaState *sta) const;
|
|
||||||
PathAPIndex pathIndex(const StaState *sta) const;
|
|
||||||
virtual void reportShort(const ReportPath *report) const = 0;
|
virtual void reportShort(const ReportPath *report) const = 0;
|
||||||
virtual void reportFull(const ReportPath *report) const = 0;
|
virtual void reportFull(const ReportPath *report) const = 0;
|
||||||
PathGroup *pathGroup() const { return path_group_; }
|
PathGroup *pathGroup() const { return path_group_; }
|
||||||
|
|
@ -89,13 +87,13 @@ public:
|
||||||
|
|
||||||
// Predicates for PathEnd type.
|
// Predicates for PathEnd type.
|
||||||
// Default methods overridden by respective types.
|
// Default methods overridden by respective types.
|
||||||
virtual bool isUnconstrained() const { return false; }
|
[[nodiscard]] virtual bool isUnconstrained() const { return false; }
|
||||||
virtual bool isCheck() const { return false; }
|
[[nodiscard]] virtual bool isCheck() const { return false; }
|
||||||
virtual bool isDataCheck() const { return false; }
|
[[nodiscard]] virtual bool isDataCheck() const { return false; }
|
||||||
virtual bool isLatchCheck() const { return false; }
|
[[nodiscard]] virtual bool isLatchCheck() const { return false; }
|
||||||
virtual bool isOutputDelay() const { return false; }
|
[[nodiscard]] virtual bool isOutputDelay() const { return false; }
|
||||||
virtual bool isGatedClock() const { return false; }
|
[[nodiscard]] virtual bool isGatedClock() const { return false; }
|
||||||
virtual bool isPathDelay() const { return false; }
|
[[nodiscard]] virtual bool isPathDelay() const { return false; }
|
||||||
virtual Type type() const = 0;
|
virtual Type type() const = 0;
|
||||||
virtual const char *typeName() const = 0;
|
virtual const char *typeName() const = 0;
|
||||||
virtual int exceptPathCmp(const PathEnd *path_end,
|
virtual int exceptPathCmp(const PathEnd *path_end,
|
||||||
|
|
@ -187,7 +185,7 @@ public:
|
||||||
const ClockEdge *tgt_clk_edge,
|
const ClockEdge *tgt_clk_edge,
|
||||||
const Path *tgt_clk_path,
|
const Path *tgt_clk_path,
|
||||||
const TimingRole *check_role,
|
const TimingRole *check_role,
|
||||||
const StaState *sta);
|
const Sdc *sdc);
|
||||||
// Non inter-clock uncertainty.
|
// Non inter-clock uncertainty.
|
||||||
static float checkTgtClkUncertainty(const Path *tgt_clk_path,
|
static float checkTgtClkUncertainty(const Path *tgt_clk_path,
|
||||||
const ClockEdge *tgt_clk_edge,
|
const ClockEdge *tgt_clk_edge,
|
||||||
|
|
@ -204,7 +202,7 @@ protected:
|
||||||
static void checkInterClkUncertainty(const ClockEdge *src_clk_edge,
|
static void checkInterClkUncertainty(const ClockEdge *src_clk_edge,
|
||||||
const ClockEdge *tgt_clk_edge,
|
const ClockEdge *tgt_clk_edge,
|
||||||
const TimingRole *check_role,
|
const TimingRole *check_role,
|
||||||
const StaState *sta,
|
const Sdc *sdc,
|
||||||
float &uncertainty,
|
float &uncertainty,
|
||||||
bool &exists);
|
bool &exists);
|
||||||
static float outputDelayMargin(OutputDelay *output_delay,
|
static float outputDelayMargin(OutputDelay *output_delay,
|
||||||
|
|
@ -224,7 +222,7 @@ protected:
|
||||||
class PathEndUnconstrained : public PathEnd
|
class PathEndUnconstrained : public PathEnd
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PathEndUnconstrained(Path *path);
|
PathEndUnconstrained(Path *path);
|
||||||
virtual Type type() const;
|
virtual Type type() const;
|
||||||
virtual const char *typeName() const;
|
virtual const char *typeName() const;
|
||||||
virtual PathEnd *copy() const;
|
virtual PathEnd *copy() const;
|
||||||
|
|
@ -582,7 +580,7 @@ public:
|
||||||
virtual Required requiredTime(const StaState *sta) const;
|
virtual Required requiredTime(const StaState *sta) const;
|
||||||
virtual int exceptPathCmp(const PathEnd *path_end,
|
virtual int exceptPathCmp(const PathEnd *path_end,
|
||||||
const StaState *sta) const;
|
const StaState *sta) const;
|
||||||
bool hasOutputDelay() const { return output_delay_ != nullptr; }
|
[[nodiscard]] bool hasOutputDelay() const { return output_delay_ != nullptr; }
|
||||||
virtual bool ignoreClkLatency(const StaState *sta) const;
|
virtual bool ignoreClkLatency(const StaState *sta) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -613,7 +611,7 @@ protected:
|
||||||
class PathEndLess
|
class PathEndLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PathEndLess(const StaState *sta);
|
PathEndLess(const StaState *sta);
|
||||||
bool operator()(const PathEnd *path_end1,
|
bool operator()(const PathEnd *path_end1,
|
||||||
const PathEnd *path_end2) const;
|
const PathEnd *path_end2) const;
|
||||||
|
|
||||||
|
|
@ -625,7 +623,7 @@ protected:
|
||||||
class PathEndSlackLess
|
class PathEndSlackLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PathEndSlackLess(const StaState *sta);
|
PathEndSlackLess(const StaState *sta);
|
||||||
bool operator()(const PathEnd *path_end1,
|
bool operator()(const PathEnd *path_end1,
|
||||||
const PathEnd *path_end2) const;
|
const PathEnd *path_end2) const;
|
||||||
|
|
||||||
|
|
@ -636,7 +634,7 @@ protected:
|
||||||
class PathEndNoCrprLess
|
class PathEndNoCrprLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PathEndNoCrprLess(const StaState *sta);
|
PathEndNoCrprLess(const StaState *sta);
|
||||||
bool operator()(const PathEnd *path_end1,
|
bool operator()(const PathEnd *path_end1,
|
||||||
const PathEnd *path_end2) const;
|
const PathEnd *path_end2) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,11 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "Map.hh"
|
|
||||||
#include "Vector.hh"
|
|
||||||
#include "SdcClass.hh"
|
#include "SdcClass.hh"
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
#include "SearchClass.hh"
|
#include "SearchClass.hh"
|
||||||
|
|
@ -37,11 +38,11 @@ namespace sta {
|
||||||
class MinMax;
|
class MinMax;
|
||||||
class PathEndVisitor;
|
class PathEndVisitor;
|
||||||
|
|
||||||
typedef PathEndSeq::Iterator PathGroupIterator;
|
using PathGroupIterator = PathEndSeq::iterator;
|
||||||
typedef Map<const Clock*, PathGroup*> PathGroupClkMap;
|
using PathGroupClkMap = std::map<const Clock*, PathGroup*>;
|
||||||
typedef Map<const char*, PathGroup*, CharPtrLess> PathGroupNamedMap;
|
using PathGroupNamedMap = std::map<const char*, PathGroup*, CharPtrLess>;
|
||||||
typedef std::vector<PathGroup*> PathGroupSeq;
|
using PathGroupSeq = std::vector<PathGroup*>;
|
||||||
typedef std::vector<std::string> StdStringSeq;
|
using StdStringSeq = std::vector<std::string>;
|
||||||
|
|
||||||
// A collection of PathEnds grouped and sorted for reporting.
|
// A collection of PathEnds grouped and sorted for reporting.
|
||||||
class PathGroup
|
class PathGroup
|
||||||
|
|
@ -65,7 +66,7 @@ public:
|
||||||
float min_slack,
|
float min_slack,
|
||||||
float max_slack,
|
float max_slack,
|
||||||
const StaState *sta);
|
const StaState *sta);
|
||||||
const char *name() const { return name_; }
|
const char *name() const { return name_.c_str(); }
|
||||||
const MinMax *minMax() const { return min_max_;}
|
const MinMax *minMax() const { return min_max_;}
|
||||||
const PathEndSeq &pathEnds() const { return path_ends_; }
|
const PathEndSeq &pathEnds() const { return path_ends_; }
|
||||||
void insert(PathEnd *path_end);
|
void insert(PathEnd *path_end);
|
||||||
|
|
@ -75,7 +76,7 @@ public:
|
||||||
bool saveable(PathEnd *path_end);
|
bool saveable(PathEnd *path_end);
|
||||||
bool enumMinSlackUnderMin(PathEnd *path_end);
|
bool enumMinSlackUnderMin(PathEnd *path_end);
|
||||||
int maxPaths() const { return group_path_count_; }
|
int maxPaths() const { return group_path_count_; }
|
||||||
PathGroupIterator *iterator();
|
PathEndSeq &pathEnds() { return path_ends_; }
|
||||||
// This does NOT delete the path ends.
|
// This does NOT delete the path ends.
|
||||||
void clear();
|
void clear();
|
||||||
static size_t group_path_count_max;
|
static size_t group_path_count_max;
|
||||||
|
|
@ -95,7 +96,7 @@ protected:
|
||||||
void prune();
|
void prune();
|
||||||
void sort();
|
void sort();
|
||||||
|
|
||||||
const char *name_;
|
std::string name_;
|
||||||
size_t group_path_count_;
|
size_t group_path_count_;
|
||||||
size_t endpoint_path_count_;
|
size_t endpoint_path_count_;
|
||||||
bool unique_pins_;
|
bool unique_pins_;
|
||||||
|
|
@ -119,7 +120,7 @@ public:
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
float slack_min,
|
float slack_min,
|
||||||
float slack_max,
|
float slack_max,
|
||||||
PathGroupNameSet *group_names,
|
StdStringSeq &group_names,
|
||||||
bool setup,
|
bool setup,
|
||||||
bool hold,
|
bool hold,
|
||||||
bool recovery,
|
bool recovery,
|
||||||
|
|
@ -127,15 +128,17 @@ public:
|
||||||
bool clk_gating_setup,
|
bool clk_gating_setup,
|
||||||
bool clk_gating_hold,
|
bool clk_gating_hold,
|
||||||
bool unconstrained,
|
bool unconstrained,
|
||||||
const StaState *sta);
|
const Mode *mode);
|
||||||
~PathGroups();
|
~PathGroups();
|
||||||
// Use corner nullptr to make PathEnds for all corners.
|
// Use scene nullptr to make PathEnds for all scenes.
|
||||||
// The PathEnds in the vector are owned by the PathGroups.
|
// The PathEnds in the vector are owned by the PathGroups.
|
||||||
PathEndSeq makePathEnds(ExceptionTo *to,
|
void makePathEnds(ExceptionTo *to,
|
||||||
bool unconstrained_paths,
|
const SceneSeq &scenes,
|
||||||
const Corner *corner,
|
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
bool sort_by_slack);
|
bool sort_by_slack,
|
||||||
|
bool unconstrained_paths,
|
||||||
|
// Return value.
|
||||||
|
PathEndSeq &path_ends);
|
||||||
PathGroup *findPathGroup(const char *name,
|
PathGroup *findPathGroup(const char *name,
|
||||||
const MinMax *min_max) const;
|
const MinMax *min_max) const;
|
||||||
PathGroup *findPathGroup(const Clock *clock,
|
PathGroup *findPathGroup(const Clock *clock,
|
||||||
|
|
@ -154,14 +157,14 @@ protected:
|
||||||
int endpoint_path_count,
|
int endpoint_path_count,
|
||||||
bool unique_pins,
|
bool unique_pins,
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
const Corner *corner,
|
const SceneSeq &scenes,
|
||||||
const MinMaxAll *min_max);
|
const MinMaxAll *min_max);
|
||||||
void makeGroupPathEnds(ExceptionTo *to,
|
void makeGroupPathEnds(ExceptionTo *to,
|
||||||
const Corner *corner,
|
const SceneSeq &scenes,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
PathEndVisitor *visitor);
|
PathEndVisitor *visitor);
|
||||||
void makeGroupPathEnds(VertexSet *endpoints,
|
void makeGroupPathEnds(VertexSet &endpoints,
|
||||||
const Corner *corner,
|
const SceneSeq &scenes,
|
||||||
const MinMaxAll *min_max,
|
const MinMaxAll *min_max,
|
||||||
PathEndVisitor *visitor);
|
PathEndVisitor *visitor);
|
||||||
void enumPathEnds(PathGroup *group,
|
void enumPathEnds(PathGroup *group,
|
||||||
|
|
@ -171,7 +174,7 @@ protected:
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
bool cmp_slack);
|
bool cmp_slack);
|
||||||
|
|
||||||
void pushGroupPathEnds(PathEndSeq &path_ends);
|
void pushEnds(PathEndSeq &path_ends);
|
||||||
void pushUnconstrainedPathEnds(PathEndSeq &path_ends,
|
void pushUnconstrainedPathEnds(PathEndSeq &path_ends,
|
||||||
const MinMaxAll *min_max);
|
const MinMaxAll *min_max);
|
||||||
|
|
||||||
|
|
@ -181,15 +184,19 @@ protected:
|
||||||
bool unique_edges,
|
bool unique_edges,
|
||||||
float slack_min,
|
float slack_min,
|
||||||
float slack_max,
|
float slack_max,
|
||||||
PathGroupNameSet *group_names,
|
StdStringSet &group_names,
|
||||||
bool setup_hold,
|
bool setup_hold,
|
||||||
bool async,
|
bool async,
|
||||||
bool gated_clk,
|
bool gated_clk,
|
||||||
bool unconstrained,
|
bool unconstrained,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
bool reportGroup(const char *group_name,
|
bool reportGroup(const char *group_name,
|
||||||
PathGroupNameSet *group_names) const;
|
StdStringSet &group_names) const;
|
||||||
|
static GroupPath *groupPathTo(const PathEnd *path_end,
|
||||||
|
const StaState *sta);
|
||||||
|
StdStringSeq pathGroupNames();
|
||||||
|
|
||||||
|
const Mode *mode_;
|
||||||
int group_path_count_;
|
int group_path_count_;
|
||||||
int endpoint_path_count_;
|
int endpoint_path_count_;
|
||||||
bool unique_pins_;
|
bool unique_pins_;
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@
|
||||||
#include "Error.hh"
|
#include "Error.hh"
|
||||||
|
|
||||||
// Don't require all of tcl.h.
|
// Don't require all of tcl.h.
|
||||||
typedef struct Tcl_RegExp_ *Tcl_RegExp;
|
using Tcl_RegExp = struct Tcl_RegExp_ *;
|
||||||
typedef struct Tcl_Interp Tcl_Interp;
|
using Tcl_Interp = struct Tcl_Interp;
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
|
|
@ -78,7 +78,7 @@ private:
|
||||||
class RegexpCompileError : public Exception
|
class RegexpCompileError : public Exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit RegexpCompileError(const char *pattern);
|
RegexpCompileError(const char *pattern);
|
||||||
virtual ~RegexpCompileError() noexcept {}
|
virtual ~RegexpCompileError() noexcept {}
|
||||||
virtual const char *what() const noexcept;
|
virtual const char *what() const noexcept;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "Hash.hh"
|
#include "Hash.hh"
|
||||||
#include "Set.hh"
|
|
||||||
#include "NetworkClass.hh"
|
#include "NetworkClass.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef std::pair<const Pin*, const Pin*> PinPair;
|
using PinPair = std::pair<const Pin*, const Pin*>;
|
||||||
|
|
||||||
class PinPairLess
|
class PinPairLess
|
||||||
{
|
{
|
||||||
|
|
@ -44,7 +45,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PinPairSet : public Set<PinPair, PinPairLess>
|
class PinPairSet : public std::set<PinPair, PinPairLess>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PinPairSet(const Network *network);
|
PinPairSet(const Network *network);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "RiseFallMinMax.hh"
|
#include "RiseFallMinMax.hh"
|
||||||
#include "SdcClass.hh"
|
#include "SdcClass.hh"
|
||||||
|
|
||||||
|
|
@ -31,7 +33,7 @@ namespace sta {
|
||||||
|
|
||||||
class PortDelay;
|
class PortDelay;
|
||||||
|
|
||||||
typedef Vector<PortDelay*> PortDelaySeq;
|
using PortDelaySeq = std::vector<PortDelay*>;
|
||||||
|
|
||||||
// set_input_delay arrival, set_output_delay departure
|
// set_input_delay arrival, set_output_delay departure
|
||||||
class PortDelay
|
class PortDelay
|
||||||
|
|
@ -98,7 +100,7 @@ private:
|
||||||
class PortDelayLess
|
class PortDelayLess
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PortDelayLess(const Network *network);
|
PortDelayLess(const Network *network);
|
||||||
bool operator()(const PortDelay *delay1,
|
bool operator()(const PortDelay *delay1,
|
||||||
const PortDelay *delay2) const;
|
const PortDelay *delay2) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,39 +32,42 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
typedef MinMaxIntValues FanoutValues;
|
using FanoutValues = MinMaxIntValues;
|
||||||
|
|
||||||
// Port external pin and wire capacitance (set_load -pin_load -wire_load).
|
// Port external pin and wire capacitance (set_load -pin_load -wire_load).
|
||||||
class PortExtCap
|
class PortExtCap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PortExtCap(const Port *port);
|
PortExtCap();
|
||||||
const Port *port() { return port_; }
|
const Port *port() { return port_; }
|
||||||
void pinCap(const RiseFall *rf,
|
void pinCap(const RiseFall *rf,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
// Return values.
|
// Return values.
|
||||||
float &cap,
|
float &cap,
|
||||||
bool &exists);
|
bool &exists) const;
|
||||||
RiseFallMinMax *pinCap() { return &pin_cap_; }
|
const RiseFallMinMax *pinCap() const { return &pin_cap_; }
|
||||||
void setPinCap(float cap,
|
void setPinCap(const Port *port,
|
||||||
|
float cap,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
void wireCap(const RiseFall *rf,
|
void wireCap(const RiseFall *rf,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
// Return values.
|
// Return values.
|
||||||
float &cap,
|
float &cap,
|
||||||
bool &exists);
|
bool &exists) const;
|
||||||
RiseFallMinMax *wireCap() { return &wire_cap_; }
|
const RiseFallMinMax *wireCap() const { return &wire_cap_; }
|
||||||
void setWireCap(float cap,
|
void setWireCap(const Port *port,
|
||||||
|
float cap,
|
||||||
const RiseFall *rf,
|
const RiseFall *rf,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
void setFanout(int fanout,
|
void setFanout(const Port *port,
|
||||||
|
int fanout,
|
||||||
const MinMax *min_max);
|
const MinMax *min_max);
|
||||||
void fanout(const MinMax *min_max,
|
void fanout(const MinMax *min_max,
|
||||||
// Return values.
|
// Return values.
|
||||||
int &fanout,
|
int &fanout,
|
||||||
bool &exists);
|
bool &exists) const;
|
||||||
FanoutValues *fanout() { return &fanout_; }
|
const FanoutValues *fanout() const { return &fanout_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Port *port_;
|
const Port *port_;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue