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)
|
||||
endif()
|
||||
|
||||
project(STA VERSION 2.7.0
|
||||
project(STA VERSION 3.0.0
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
||||
|
|
@ -77,7 +77,6 @@ set(STA_SOURCE
|
|||
dcalc/ArnoldiDelayCalc.cc
|
||||
dcalc/ArnoldiReduce.cc
|
||||
dcalc/CcsCeffDelayCalc.cc
|
||||
dcalc/DcalcAnalysisPt.cc
|
||||
dcalc/DelayCalc.cc
|
||||
dcalc/DelayCalcBase.cc
|
||||
dcalc/DmpCeff.cc
|
||||
|
|
@ -135,6 +134,7 @@ set(STA_SOURCE
|
|||
parasitics/SpefReaderPvt.hh
|
||||
|
||||
power/Power.cc
|
||||
power/ReportPower.cc
|
||||
power/VcdReader.cc
|
||||
power/SaifReader.cc
|
||||
power/VcdParse.cc
|
||||
|
|
@ -154,7 +154,6 @@ set(STA_SOURCE
|
|||
sdc/PortDelay.cc
|
||||
sdc/PortExtCap.cc
|
||||
sdc/Sdc.cc
|
||||
sdc/SdcGraph.cc
|
||||
sdc/SdcCmdComment.cc
|
||||
sdc/Variables.cc
|
||||
sdc/WriteSdc.cc
|
||||
|
|
@ -168,15 +167,14 @@ set(STA_SOURCE
|
|||
search/CheckMaxSkews.cc
|
||||
search/CheckMinPeriods.cc
|
||||
search/CheckMinPulseWidths.cc
|
||||
search/CheckCapacitanceLimits.cc
|
||||
search/CheckFanoutLimits.cc
|
||||
search/CheckSlewLimits.cc
|
||||
search/CheckCapacitances.cc
|
||||
search/CheckFanouts.cc
|
||||
search/CheckSlews.cc
|
||||
search/CheckTiming.cc
|
||||
search/ClkInfo.cc
|
||||
search/ClkLatency.cc
|
||||
search/ClkNetwork.cc
|
||||
search/ClkSkew.cc
|
||||
search/Corner.cc
|
||||
search/Crpr.cc
|
||||
search/FindRegister.cc
|
||||
search/GatedClk.cc
|
||||
|
|
@ -184,8 +182,8 @@ set(STA_SOURCE
|
|||
search/Latches.cc
|
||||
search/Levelize.cc
|
||||
search/MakeTimingModel.cc
|
||||
search/Mode.cc
|
||||
search/Path.cc
|
||||
search/PathAnalysisPt.cc
|
||||
search/Path.cc
|
||||
search/PathEnd.cc
|
||||
search/PathEnum.cc
|
||||
|
|
@ -195,6 +193,7 @@ set(STA_SOURCE
|
|||
search/ReportPath.cc
|
||||
search/Search.cc
|
||||
search/SearchPred.cc
|
||||
search/Scene.cc
|
||||
search/Sim.cc
|
||||
search/Sta.cc
|
||||
search/StaState.cc
|
||||
|
|
@ -222,6 +221,7 @@ set(STA_SOURCE
|
|||
util/ReportStd.cc
|
||||
util/ReportTcl.cc
|
||||
util/RiseFallMinMax.cc
|
||||
util/RiseFallMinMaxDelay.cc
|
||||
util/RiseFallValues.cc
|
||||
util/Stats.cc
|
||||
util/StringSeq.cc
|
||||
|
|
@ -549,14 +549,14 @@ endif()
|
|||
|
||||
target_compile_options(OpenSTA
|
||||
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:AppleClang>:${CXX_FLAGS} -Wno-gnu-zero-variadic-macro-arguments>
|
||||
)
|
||||
|
||||
# Disable compiler specific extensions like gnu++11.
|
||||
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")
|
||||
|
||||
|
|
|
|||
17
app/Main.cc
17
app/Main.cc
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <cstdlib> // exit
|
||||
#include <filesystem>
|
||||
#include <tcl.h>
|
||||
#if TCL_READLINE
|
||||
#include <tclreadline.h>
|
||||
|
|
@ -47,7 +48,6 @@ using sta::evalTclInit;
|
|||
using sta::sourceTclFile;
|
||||
using sta::parseThreadsArg;
|
||||
using sta::tcl_inits;
|
||||
using sta::is_regular_file;
|
||||
|
||||
// Swig uses C linkage for init functions.
|
||||
extern "C" {
|
||||
|
|
@ -87,20 +87,11 @@ main(int argc,
|
|||
}
|
||||
else {
|
||||
// Set argc to 1 so Tcl_Main doesn't source any files.
|
||||
// Tcl_Main never returns.
|
||||
#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.
|
||||
// Store argc and argv in static variables for tclAppInit.
|
||||
cmd_argc = argc;
|
||||
cmd_argv = argv;
|
||||
// Tcl_Main never returns.
|
||||
Tcl_Main(1, argv, tclAppInit);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -141,7 +132,7 @@ staTclAppInit(int argc,
|
|||
string init_path = home;
|
||||
init_path += "/";
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include "Machine.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "Vector.hh"
|
||||
#include "Sta.hh"
|
||||
|
||||
namespace sta {
|
||||
|
|
@ -148,12 +147,4 @@ unencode(const char *inits[])
|
|||
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
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include "Network.hh"
|
||||
#include "Graph.hh"
|
||||
#include "ArcDelayCalc.hh"
|
||||
#include "DcalcAnalysisPt.hh"
|
||||
#include "GraphDelayCalc.hh"
|
||||
|
||||
namespace sta {
|
||||
|
|
@ -40,7 +39,8 @@ using std::make_shared;
|
|||
|
||||
Waveform
|
||||
ArcDcalcWaveforms::inputWaveform(ArcDcalcArg &dcalc_arg,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta)
|
||||
{
|
||||
const Network *network = sta->network();
|
||||
|
|
@ -55,7 +55,8 @@ ArcDcalcWaveforms::inputWaveform(ArcDcalcArg &dcalc_arg,
|
|||
const Vertex *in_vertex = graph->pinLoadVertex(in_pin);
|
||||
GraphDelayCalc *graph_dcalc = sta->graphDelayCalc();
|
||||
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();
|
||||
float vdd;
|
||||
bool vdd_exists;
|
||||
|
|
@ -67,7 +68,8 @@ ArcDcalcWaveforms::inputWaveform(ArcDcalcArg &dcalc_arg,
|
|||
FloatSeq *time_values = new FloatSeq;
|
||||
for (float time : *in_waveform.axis1()->values())
|
||||
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.
|
||||
FloatSeq *scaled_values = new FloatSeq;
|
||||
for (float value : *in_waveform.values()) {
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@
|
|||
namespace sta {
|
||||
|
||||
class StaState;
|
||||
class Corner;
|
||||
class DcalcAnalysisPt;
|
||||
class Scene;
|
||||
class ArcDcalcArg;
|
||||
|
||||
// Abstract class for delay calculation waveforms for ploting.
|
||||
|
|
@ -47,7 +46,8 @@ public:
|
|||
|
||||
protected:
|
||||
Waveform inputWaveform(ArcDcalcArg &dcalc_arg,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -46,14 +46,15 @@ ArcDelayCalc::gateDelay(const TimingArc *arc,
|
|||
const Parasitic *parasitic,
|
||||
float,
|
||||
const Pvt *,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew)
|
||||
{
|
||||
LoadPinIndexMap load_pin_index_map(network_);
|
||||
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();
|
||||
drvr_slew = dcalc_result.drvrSlew();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
#include "Graph.hh"
|
||||
#include "Parasitics.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "DcalcAnalysisPt.hh"
|
||||
#include "DelayCalc.hh"
|
||||
#include "ArcDelayCalc.hh"
|
||||
#include "LumpedCapDelayCalc.hh"
|
||||
|
|
@ -129,17 +128,20 @@ public:
|
|||
const char *name() const override { return "arnoldi"; }
|
||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
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,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
|
|
@ -147,14 +149,16 @@ public:
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
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,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits) override;
|
||||
void finishDrvrPin() override;
|
||||
void delay_work_set_thresholds(delay_work *D,
|
||||
|
|
@ -273,35 +277,34 @@ ArnoldiDelayCalc::~ArnoldiDelayCalc()
|
|||
Parasitic *
|
||||
ArnoldiDelayCalc::findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *drvr_rf,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
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.
|
||||
if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|
||||
|| network_->direction(drvr_pin)->isInternal())
|
||||
return nullptr;
|
||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
Parasitic *parasitic_network =
|
||||
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
|
||||
const MinMax *min_max = dcalc_ap->constraintMinMax();
|
||||
parasitics->findParasiticNetwork(drvr_pin);
|
||||
if (parasitic_network == nullptr) {
|
||||
Wireload *wireload = sdc_->wireload(min_max);
|
||||
Wireload *wireload = sdc->wireload(min_max);
|
||||
if (wireload) {
|
||||
float pin_cap, wire_cap, fanout;
|
||||
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);
|
||||
parasitic_network = parasitics_->makeWireloadNetwork(drvr_pin, wireload,
|
||||
fanout, min_max,
|
||||
parasitic_ap);
|
||||
parasitic_network = parasitics->makeWireloadNetwork(drvr_pin, wireload,
|
||||
fanout, scene, min_max);
|
||||
}
|
||||
}
|
||||
|
||||
if (parasitic_network) {
|
||||
rcmodel *rcmodel = reduce_->reduceToArnoldi(parasitic_network, drvr_pin,
|
||||
parasitic_ap->couplingCapFactor(),
|
||||
drvr_rf, corner, min_max, parasitic_ap);
|
||||
parasitics->couplingCapFactor(),
|
||||
drvr_rf, scene, min_max);
|
||||
// Arnoldi parasitics are their own class that are not saved in the parasitic db.
|
||||
unsaved_parasitics_.push_back(rcmodel);
|
||||
parasitic = rcmodel;
|
||||
|
|
@ -313,7 +316,8 @@ Parasitic *
|
|||
ArnoldiDelayCalc::reduceParasitic(const Parasitic *,
|
||||
const Pin *,
|
||||
const RiseFall *,
|
||||
const DcalcAnalysisPt *)
|
||||
const Scene *,
|
||||
const MinMax *)
|
||||
{
|
||||
// Decline because reduced arnoldi parasitics are not stored in the parasitics db.
|
||||
return nullptr;
|
||||
|
|
@ -333,7 +337,8 @@ ArnoldiDelayCalc::inputPortDelay(const Pin *,
|
|||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *)
|
||||
const Scene *,
|
||||
const MinMax *)
|
||||
{
|
||||
rcmodel_ = nullptr;
|
||||
_delayV[0] = 0.0;
|
||||
|
|
@ -389,21 +394,22 @@ ArnoldiDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
const LibertyCell *drvr_cell = arc->from()->libertyCell();
|
||||
ConcreteParasitic *cparasitic =
|
||||
reinterpret_cast<ConcreteParasitic*>(const_cast<Parasitic*>(parasitic));
|
||||
rcmodel_ = dynamic_cast<rcmodel*>(cparasitic);
|
||||
pocv_enabled_ = variables_->pocvEnabled();
|
||||
GateTableModel *table_model = arc->gateTableModel(dcalc_ap);
|
||||
GateTableModel *table_model = arc->gateTableModel(scene, min_max);
|
||||
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);
|
||||
}
|
||||
else
|
||||
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
|
||||
|
|
@ -470,12 +476,13 @@ ArnoldiDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits)
|
||||
{
|
||||
return LumpedCapDelayCalc::reportGateDelay(drvr_pin, arc, in_slew, load_cap,
|
||||
parasitic, load_pin_index_map,
|
||||
dcalc_ap, digits);
|
||||
scene, min_max, digits);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -154,17 +154,17 @@ ArnoldiReduce::reduceToArnoldi(Parasitic *parasitic,
|
|||
const Pin *drvr_pin,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
parasitic_network_ = reinterpret_cast<ConcreteParasiticNetwork*>(parasitic);
|
||||
drvr_pin_ = drvr_pin;
|
||||
coupling_cap_factor_ = coupling_cap_factor;
|
||||
rf_ = rf;
|
||||
corner_ = corner;
|
||||
scene_ = scene;
|
||||
min_max_ = min_max;
|
||||
ap_ = ap;
|
||||
parasitics_ = scene->parasitics(min_max);
|
||||
parasitic_network_ = reinterpret_cast<ConcreteParasiticNetwork*>(parasitic);
|
||||
|
||||
loadWork();
|
||||
return makeRcmodelDrv();
|
||||
}
|
||||
|
|
@ -444,7 +444,7 @@ ArnoldiReduce::getRC()
|
|||
}
|
||||
}
|
||||
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);
|
||||
if (!parasitics_->isExternal(node1)) {
|
||||
ts_point *pt = findPt(node1);
|
||||
|
|
@ -466,10 +466,11 @@ ArnoldiReduce::pinCapacitance(ParasiticNode *node)
|
|||
if (pin) {
|
||||
Port *port = network_->port(pin);
|
||||
LibertyPort *lib_port = network_->libertyPort(port);
|
||||
const Sdc *sdc = scene_->sdc();
|
||||
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))
|
||||
pin_cap = sdc_->portExtCap(port, rf_, corner_, min_max_);
|
||||
pin_cap = sdc->portExtCap(port, rf_, min_max_);
|
||||
}
|
||||
return pin_cap;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Map.hh"
|
||||
#include <map>
|
||||
|
||||
#include "Transition.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "ParasiticsClass.hh"
|
||||
|
|
@ -39,13 +40,13 @@ namespace sta {
|
|||
|
||||
class ConcreteParasiticNetwork;
|
||||
class ConcreteParasiticNode;
|
||||
class Corner;
|
||||
class Scene;
|
||||
|
||||
class rcmodel;
|
||||
struct ts_edge;
|
||||
struct ts_point;
|
||||
|
||||
typedef Map<ParasiticNode*, int> ArnolidPtMap;
|
||||
using ArnolidPtMap = std::map<ParasiticNode*, int>;
|
||||
|
||||
class ArnoldiReduce : public StaState
|
||||
{
|
||||
|
|
@ -56,9 +57,8 @@ public:
|
|||
const Pin *drvr_pin,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
|
||||
protected:
|
||||
void loadWork();
|
||||
|
|
@ -73,13 +73,13 @@ protected:
|
|||
void makeRcmodelFromTs();
|
||||
rcmodel *makeRcmodelFromW();
|
||||
|
||||
Parasitics *parasitics_;
|
||||
ConcreteParasiticNetwork *parasitic_network_;
|
||||
const Pin *drvr_pin_;
|
||||
float coupling_cap_factor_;
|
||||
const RiseFall *rf_;
|
||||
const Corner *corner_;
|
||||
const Scene *scene_;
|
||||
const MinMax *min_max_;
|
||||
const ParasiticAnalysisPt *ap_;
|
||||
// ParasiticNode -> ts_point index.
|
||||
ArnolidPtMap pt_map_;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@
|
|||
#include "TimingArc.hh"
|
||||
#include "Network.hh"
|
||||
#include "Graph.hh"
|
||||
#include "Corner.hh"
|
||||
#include "DcalcAnalysisPt.hh"
|
||||
#include "Scene.hh"
|
||||
#include "Parasitics.hh"
|
||||
#include "GraphDelayCalc.hh"
|
||||
#include "DmpDelayCalc.hh"
|
||||
|
|
@ -86,17 +85,20 @@ CcsCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
in_slew_ = delayAsFloat(in_slew);
|
||||
load_cap_ = load_cap;
|
||||
parasitics_ = scene->parasitics(min_max);
|
||||
parasitic_ = parasitic;
|
||||
output_waveforms_ = nullptr;
|
||||
|
||||
GateTableModel *table_model = arc->gateTableModel(dcalc_ap);
|
||||
GateTableModel *table_model = arc->gateTableModel(scene, min_max);
|
||||
if (table_model && parasitic) {
|
||||
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
|
||||
&& rpi_ > 0.0 && c1_ > 0.0
|
||||
// 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_;
|
||||
vh_ = drvr_library->slewUpperThreshold(drvr_rf_) * vdd_;
|
||||
|
||||
const DcalcAnalysisPtSeq &dcalc_aps = corners_->dcalcAnalysisPts();
|
||||
drvr_cell->ensureVoltageWaveforms(dcalc_aps);
|
||||
drvr_cell->ensureVoltageWaveforms(scenes_);
|
||||
in_slew_ = delayAsFloat(in_slew);
|
||||
output_waveforms_ = output_waveforms;
|
||||
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,
|
||||
load_pin_index_map, dcalc_ap);
|
||||
load_pin_index_map, scene, min_max);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -574,7 +575,7 @@ CcsCeffDelayCalc::drvrRampWaveform(const Pin *in_pin,
|
|||
const Pin *drvr_pin,
|
||||
const RiseFall *drvr_rf,
|
||||
const Pin *load_pin,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
bool elmore_exists = false;
|
||||
|
|
@ -582,7 +583,7 @@ CcsCeffDelayCalc::drvrRampWaveform(const Pin *in_pin,
|
|||
if (parasitic_) {
|
||||
parasitics_->findElmore(parasitic_, load_pin, elmore, elmore_exists);
|
||||
bool dcalc_success = makeWaveformPreamble(in_pin, in_rf, drvr_pin,
|
||||
drvr_rf, corner, min_max);
|
||||
drvr_rf, scene, min_max);
|
||||
if (dcalc_success
|
||||
&& elmore_exists) {
|
||||
FloatSeq *load_times = new FloatSeq;
|
||||
|
|
@ -617,7 +618,7 @@ CcsCeffDelayCalc::makeWaveformPreamble(const Pin *in_pin,
|
|||
const RiseFall *in_rf,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *drvr_rf,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
Vertex *in_vertex = graph_->pinLoadVertex(in_pin);
|
||||
|
|
@ -641,15 +642,15 @@ CcsCeffDelayCalc::makeWaveformPreamble(const Pin *in_pin,
|
|||
}
|
||||
}
|
||||
if (arc) {
|
||||
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
||||
const Slew &in_slew = graph_->slew(in_vertex, in_rf, dcalc_ap->index());
|
||||
parasitic_ = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf, dcalc_ap);
|
||||
DcalcAPIndex slew_index = scene->dcalcAnalysisPtIndex(min_max);
|
||||
const Slew &in_slew = graph_->slew(in_vertex, in_rf, slew_index);
|
||||
parasitic_ = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf, scene, min_max);
|
||||
if (parasitic_) {
|
||||
parasitics_->piModel(parasitic_, c2_, rpi_, c1_);
|
||||
LoadPinIndexMap load_pin_index_map =
|
||||
graph_delay_calc_->makeLoadPinIndexMap(drvr_vertex);
|
||||
gateDelay(drvr_pin, arc, in_slew, load_cap_, parasitic_,
|
||||
load_pin_index_map, dcalc_ap);
|
||||
load_pin_index_map, scene, min_max);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -666,20 +667,19 @@ CcsCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits)
|
||||
{
|
||||
Parasitic *pi_elmore = nullptr;
|
||||
const RiseFall *rf = arc->toEdge()->asRiseFall();
|
||||
if (parasitic && !parasitics_->isPiElmore(parasitic)) {
|
||||
const ParasiticAnalysisPt *ap = dcalc_ap->parasiticAnalysisPt();
|
||||
pi_elmore = parasitics_->reduceToPiElmore(parasitic, drvr_pin_, rf,
|
||||
dcalc_ap->corner(),
|
||||
dcalc_ap->constraintMinMax(), ap);
|
||||
scene, min_max);
|
||||
}
|
||||
string report = table_dcalc_->reportGateDelay(drvr_pin, arc, in_slew, load_cap,
|
||||
pi_elmore, load_pin_index_map,
|
||||
dcalc_ap, digits);
|
||||
scene, min_max, digits);
|
||||
parasitics_->deleteDrvrReducedParasitics(drvr_pin);
|
||||
return report;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
typedef std::map<const Pin*, FloatSeq, PinIdLess> WatchPinValuesMap;
|
||||
using WatchPinValuesMap = std::map<const Pin*, FloatSeq, PinIdLess>;
|
||||
|
||||
ArcDelayCalc *
|
||||
makeCcsCeffDelayCalc(StaState *sta);
|
||||
|
|
@ -49,14 +49,16 @@ public:
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
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,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits) override;
|
||||
|
||||
// Record waveform for drvr/load pin.
|
||||
|
|
@ -100,7 +102,7 @@ protected:
|
|||
const RiseFall *in_rf,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *drvr_rf,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
Waveform drvrWaveform();
|
||||
Waveform loadWaveform(const Pin *load_pin);
|
||||
|
|
@ -109,7 +111,7 @@ protected:
|
|||
const Pin *drvr_pin,
|
||||
const RiseFall *drvr_rf,
|
||||
const Pin *load_pin,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
void vl(double t,
|
||||
double elmore,
|
||||
|
|
@ -124,6 +126,7 @@ protected:
|
|||
const RiseFall *drvr_rf_;
|
||||
double in_slew_;
|
||||
double load_cap_;
|
||||
Parasitics *parasitics_;
|
||||
const Parasitic *parasitic_;
|
||||
|
||||
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 "Map.hh"
|
||||
#include <map>
|
||||
|
||||
#include "ContainerHelpers.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "UnitDelayCalc.hh"
|
||||
#include "LumpedCapDelayCalc.hh"
|
||||
|
|
@ -35,7 +37,7 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
typedef Map<const char*, MakeArcDelayCalc, CharPtrLess> DelayCalcMap;
|
||||
typedef std::map<const char*, MakeArcDelayCalc, CharPtrLess> DelayCalcMap;
|
||||
|
||||
static DelayCalcMap *delay_calcs = nullptr;
|
||||
|
||||
|
|
@ -71,7 +73,7 @@ ArcDelayCalc *
|
|||
makeDelayCalc(const char *name,
|
||||
StaState *sta)
|
||||
{
|
||||
MakeArcDelayCalc maker = delay_calcs->findKey(name);
|
||||
MakeArcDelayCalc maker = findKey(delay_calcs, name);
|
||||
if (maker)
|
||||
return maker(sta);
|
||||
else
|
||||
|
|
@ -81,7 +83,7 @@ makeDelayCalc(const char *name,
|
|||
bool
|
||||
isDelayCalcName(const char *name)
|
||||
{
|
||||
return delay_calcs->hasKey(name);
|
||||
return delay_calcs->contains(name);
|
||||
}
|
||||
|
||||
StringSeq
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@
|
|||
#include "dcalc/PrimaDelayCalc.hh"
|
||||
#include "Sta.hh"
|
||||
|
||||
using std::string;
|
||||
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
|
|
@ -62,15 +60,15 @@ set_delay_calc_incremental_tolerance(float tol)
|
|||
Sta::sta()->setIncrementalDelayTolerance(tol);
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
report_delay_calc_cmd(Edge *edge,
|
||||
TimingArc *arc,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits)
|
||||
{
|
||||
Sta *sta = Sta::sta();
|
||||
return sta->reportDelayCalc(edge, arc, corner, min_max, digits);
|
||||
return sta->reportDelayCalc(edge, arc, scene, min_max, digits);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
namespace eval sta {
|
||||
|
||||
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 {
|
||||
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
|
||||
|
||||
parse_key_args $cmd cmd_args \
|
||||
keys "$digits_key -from -to -corner" \
|
||||
keys "$digits_key -from -to -scene -corner" \
|
||||
flags {-min -max}
|
||||
set corner [parse_corner keys]
|
||||
set scene [parse_scene keys]
|
||||
set min_max [parse_min_max_flags flags]
|
||||
check_argc_eq0 $cmd $cmd_args
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ proc report_dcalc_cmd { cmd cmd_args digits_key } {
|
|||
while {[$iter has_next]} {
|
||||
set edge [$iter next]
|
||||
if { [$edge to] == $to_vertex } {
|
||||
report_edge_dcalc $edge $corner $min_max $digits
|
||||
report_edge_dcalc $edge $scene $min_max $digits
|
||||
}
|
||||
}
|
||||
$iter finish
|
||||
|
|
@ -68,7 +68,7 @@ proc report_dcalc_cmd { cmd cmd_args digits_key } {
|
|||
set iter [$from_vertex out_edge_iterator]
|
||||
while {[$iter has_next]} {
|
||||
set edge [$iter next]
|
||||
report_edge_dcalc $edge $corner $min_max $digits
|
||||
report_edge_dcalc $edge $scene $min_max $digits
|
||||
}
|
||||
$iter finish
|
||||
}
|
||||
|
|
@ -78,14 +78,14 @@ proc report_dcalc_cmd { cmd cmd_args digits_key } {
|
|||
set iter [$to_vertex in_edge_iterator]
|
||||
while {[$iter has_next]} {
|
||||
set edge [$iter next]
|
||||
report_edge_dcalc $edge $corner $min_max $digits
|
||||
report_edge_dcalc $edge $scene $min_max $digits
|
||||
}
|
||||
$iter finish
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc report_edge_dcalc { edge corner min_max digits } {
|
||||
proc report_edge_dcalc { edge scene min_max digits } {
|
||||
set role [$edge role]
|
||||
if { $role != "wire" } {
|
||||
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_rf [$arc to_edge]
|
||||
report_line "$from $from_rf -> $to $to_rf"
|
||||
report_line [report_delay_calc_cmd $edge $arc $corner $min_max $digits]
|
||||
if { [$edge delay_annotated $arc $corner $min_max] } {
|
||||
set delay [$edge arc_delay $arc $corner $min_max]
|
||||
report_line [report_delay_calc_cmd $edge $arc $scene $min_max $digits]
|
||||
if { [$edge delay_annotated $arc $scene $min_max] } {
|
||||
set delay [$edge arc_delay $arc $scene $min_max]
|
||||
report_line "Annotated value = [format_time $delay $digits]"
|
||||
}
|
||||
report_line "............................................."
|
||||
|
|
@ -140,16 +140,16 @@ define_cmd_args "set_pocv_sigma_factor" { factor }
|
|||
################################################################
|
||||
|
||||
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}
|
||||
|
||||
# Change the delay for timing arcs between from_pins and to_pins matching
|
||||
# on cell (instance) or net.
|
||||
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}
|
||||
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 to_rf [parse_rise_fall_flags flags]
|
||||
|
||||
|
|
@ -192,28 +192,28 @@ proc set_assigned_delay { args } {
|
|||
foreach from_pin $from_pins {
|
||||
set from_vertices [$from_pin vertices]
|
||||
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 } {
|
||||
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 {
|
||||
set to_vertices [$to_pin vertices]
|
||||
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 } {
|
||||
# Bidirect driver.
|
||||
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 edge_iter [$from_vertex out_edge_iterator]
|
||||
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] {
|
||||
if { $to_rf == "rise_fall" \
|
||||
|| $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
|
||||
}
|
||||
}
|
||||
|
|
@ -239,13 +239,13 @@ proc set_assigned_delay2 {from_vertex to_vertex to_rf corner min_max delay} {
|
|||
|
||||
define_cmd_args "set_assigned_check" \
|
||||
{-setup|-hold|-recovery|-removal [-rise] [-fall]\
|
||||
[-corner corner] [-min] [-max]\
|
||||
[-scene scene] [-min] [-max]\
|
||||
[-from from_pins] [-to to_pins] [-clock rise|fall]\
|
||||
[-cond sdf_cond] check_value}
|
||||
|
||||
proc 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}
|
||||
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."
|
||||
}
|
||||
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]
|
||||
|
||||
if { [info exists flags(-setup)] } {
|
||||
|
|
@ -298,31 +298,31 @@ proc set_assigned_check { args } {
|
|||
foreach from_pin $from_pins {
|
||||
set from_vertices [$from_pin vertices]
|
||||
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 } {
|
||||
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 \
|
||||
role corner min_max cond check_value } {
|
||||
role scene min_max cond check_value } {
|
||||
foreach to_pin $to_pins {
|
||||
set to_vertices [$to_pin vertices]
|
||||
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 } {
|
||||
# Bidirect driver.
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 matched 0
|
||||
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]) \
|
||||
&& [$arc role] eq $role \
|
||||
&& ($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
|
||||
}
|
||||
}
|
||||
|
|
@ -350,14 +350,14 @@ proc set_assigned_check2 { from_vertex from_rf to_vertex to_rf \
|
|||
################################################################a
|
||||
|
||||
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.
|
||||
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}
|
||||
|
||||
set corner [parse_corner keys]
|
||||
set scene [parse_scene keys]
|
||||
set min_max [parse_min_max_all_check_flags flags]
|
||||
set tr [parse_rise_fall_flags flags]
|
||||
check_argc_eq2 "set_assigned_transition" $args
|
||||
|
|
@ -371,7 +371,7 @@ proc set_assigned_transition { args } {
|
|||
foreach pin $pins {
|
||||
set vertices [$pin vertices]
|
||||
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 } {
|
||||
# Bidirect driver.
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@
|
|||
#include "Parasitics.hh"
|
||||
#include "Graph.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "Corner.hh"
|
||||
#include "DcalcAnalysisPt.hh"
|
||||
#include "Scene.hh"
|
||||
#include "GraphDelayCalc.hh"
|
||||
#include "Variables.hh"
|
||||
|
||||
|
|
@ -50,7 +49,7 @@ DelayCalcBase::DelayCalcBase(StaState *sta) :
|
|||
void
|
||||
DelayCalcBase::reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Net *net,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMaxAll *min_max)
|
||||
{
|
||||
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
|
||||
|
|
@ -59,16 +58,12 @@ DelayCalcBase::reduceParasitic(const Parasitic *parasitic_network,
|
|||
if (network_->isDriver(pin)) {
|
||||
for (const RiseFall *rf : RiseFall::range()) {
|
||||
for (const MinMax *min_max : min_max->range()) {
|
||||
if (corner == nullptr) {
|
||||
for (const Corner *corner1 : *corners_) {
|
||||
DcalcAnalysisPt *dcalc_ap = corner1->findDcalcAnalysisPt(min_max);
|
||||
reduceParasitic(parasitic_network, pin, rf, dcalc_ap);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
||||
reduceParasitic(parasitic_network, pin, rf, dcalc_ap);
|
||||
if (scene == nullptr) {
|
||||
for (const Scene *scene1 : scenes_)
|
||||
reduceParasitic(parasitic_network, pin, rf, scene1, min_max);
|
||||
}
|
||||
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 &to_slew,
|
||||
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) {
|
||||
float from_slew1 = delayAsFloat(from_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,
|
||||
variables_->pocvEnabled());
|
||||
}
|
||||
|
|
@ -183,40 +180,46 @@ DelayCalcBase::reportCheckDelay(const Pin *check_pin,
|
|||
const char *from_slew_annotation,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits)
|
||||
{
|
||||
CheckTimingModel *model = arc->checkModel(dcalc_ap);
|
||||
CheckTimingModel *model = arc->checkModel(scene, min_max);
|
||||
if (model) {
|
||||
float from_slew1 = delayAsFloat(from_slew);
|
||||
float to_slew1 = delayAsFloat(to_slew);
|
||||
return model->reportCheckDelay(pinPvt(check_pin, dcalc_ap), from_slew1,
|
||||
from_slew_annotation, to_slew1,
|
||||
related_out_cap, false, digits);
|
||||
return model->reportCheckDelay(pinPvt(check_pin, scene, min_max),
|
||||
from_slew1, from_slew_annotation,
|
||||
to_slew1, related_out_cap, false,
|
||||
digits);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const Pvt *
|
||||
DelayCalcBase::pinPvt(const Pin *pin,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
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)
|
||||
pvt = dcalc_ap->operatingConditions();
|
||||
pvt = sdc->operatingConditions(min_max);
|
||||
return pvt;
|
||||
}
|
||||
|
||||
void
|
||||
DelayCalcBase::setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
const Pin *drvr_pin = gate.drvrPin();
|
||||
if (drvr_pin) {
|
||||
const Parasitic *parasitic;
|
||||
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,
|
||||
parasitic);
|
||||
gate.setLoadCap(load_cap);
|
||||
|
|
@ -224,17 +227,19 @@ DelayCalcBase::setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
|||
const Pin *in_pin = gate.inPin();
|
||||
const Vertex *in_vertex = graph_->pinLoadVertex(in_pin);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DelayCalcBase::setDcalcArgParasiticSlew(ArcDcalcArgSeq &gates,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
for (ArcDcalcArg &gate : gates)
|
||||
setDcalcArgParasiticSlew(gate, dcalc_ap);
|
||||
setDcalcArgParasiticSlew(gate, scene, min_max);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -34,23 +34,26 @@ class GateTableModel;
|
|||
class DelayCalcBase : public ArcDelayCalc
|
||||
{
|
||||
public:
|
||||
explicit DelayCalcBase(StaState *sta);
|
||||
DelayCalcBase(StaState *sta);
|
||||
void finishDrvrPin() override;
|
||||
|
||||
void reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Net *net,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMaxAll *min_max) override;
|
||||
void setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
void setDcalcArgParasiticSlew(ArcDcalcArgSeq &gates,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
ArcDelay checkDelay(const Pin *check_pin,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
|
||||
std::string reportCheckDelay(const Pin *check_pin,
|
||||
const TimingArc *arc,
|
||||
|
|
@ -58,7 +61,8 @@ public:
|
|||
const char *from_slew_annotation,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits) override;
|
||||
|
||||
protected:
|
||||
|
|
@ -79,7 +83,8 @@ protected:
|
|||
ArcDelay &wire_delay,
|
||||
Slew &load_slew);
|
||||
const Pvt *pinPvt(const Pin *pin,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
|
||||
using ArcDelayCalc::reduceParasitic;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@
|
|||
#include "Network.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "Parasitics.hh"
|
||||
#include "DcalcAnalysisPt.hh"
|
||||
#include "ArcDelayCalc.hh"
|
||||
#include "FindRoot.hh"
|
||||
#include "Variables.hh"
|
||||
|
|
@ -1495,20 +1494,22 @@ DmpCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
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 LibertyCell *drvr_cell = arc->from()->libertyCell();
|
||||
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) {
|
||||
float in_slew1 = delayAsFloat(in_slew);
|
||||
float c2, rpi, c1;
|
||||
parasitics_->piModel(parasitic, c2, rpi, c1);
|
||||
if (isnan(c2) || isnan(c1) || isnan(rpi))
|
||||
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);
|
||||
double gate_delay, drvr_slew;
|
||||
gateDelaySlew(gate_delay, drvr_slew);
|
||||
|
|
@ -1529,7 +1530,7 @@ DmpCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
else {
|
||||
ArcDcalcResult dcalc_result =
|
||||
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
|
||||
&& !unsuppored_model_warned_) {
|
||||
unsuppored_model_warned_ = true;
|
||||
|
|
@ -1589,12 +1590,13 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits)
|
||||
{
|
||||
ArcDcalcResult dcalc_result = gateDelay(drvr_pin, arc, in_slew, load_cap,
|
||||
parasitic, load_pin_index_map, dcalc_ap);
|
||||
GateTableModel *model = arc->gateTableModel(dcalc_ap);
|
||||
parasitic, load_pin_index_map, scene, min_max);
|
||||
GateTableModel *model = arc->gateTableModel(scene, min_max);
|
||||
float c_eff = 0.0;
|
||||
string result;
|
||||
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 *res_unit = units->resistanceUnit();
|
||||
if (parasitic && dmp_alg_) {
|
||||
Parasitics *parasitics = scene->parasitics(min_max);
|
||||
|
||||
c_eff = dmp_alg_->ceff();
|
||||
float c2, rpi, c1;
|
||||
parasitics_->piModel(parasitic, c2, rpi, c1);
|
||||
parasitics->piModel(parasitic, c2, rpi, c1);
|
||||
result += "Pi model C2=";
|
||||
result += cap_unit->asString(c2, digits);
|
||||
result += " Rpi=";
|
||||
|
|
@ -1621,7 +1625,8 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
|||
if (model) {
|
||||
const Unit *time_unit = units->timeUnit();
|
||||
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);
|
||||
result += "Driver waveform slew = ";
|
||||
float drvr_slew = delayAsFloat(dcalc_result.drvrSlew());
|
||||
|
|
|
|||
|
|
@ -49,14 +49,16 @@ public:
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
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,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits) override;
|
||||
void copyState(const StaState *sta) override;
|
||||
|
||||
|
|
@ -87,6 +89,7 @@ protected:
|
|||
double rpi,
|
||||
double c1);
|
||||
|
||||
const Parasitics *parasitics_;
|
||||
static bool unsuppored_model_warned_;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include "Network.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "Parasitics.hh"
|
||||
#include "DcalcAnalysisPt.hh"
|
||||
#include "GraphDelayCalc.hh"
|
||||
#include "DmpCeff.hh"
|
||||
|
||||
|
|
@ -50,7 +49,8 @@ public:
|
|||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
|
||||
protected:
|
||||
void loadDelaySlew(const Pin *load_pin,
|
||||
|
|
@ -86,8 +86,10 @@ DmpCeffElmoreDelayCalc::inputPortDelay(const Pin *,
|
|||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
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());
|
||||
LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
|
||||
for (auto [load_pin, load_idx] : load_pin_index_map) {
|
||||
|
|
@ -96,7 +98,7 @@ DmpCeffElmoreDelayCalc::inputPortDelay(const Pin *,
|
|||
bool elmore_exists = false;
|
||||
float elmore = 0.0;
|
||||
if (parasitic)
|
||||
parasitics_->findElmore(parasitic, load_pin, elmore, elmore_exists);
|
||||
parasitics->findElmore(parasitic, load_pin, elmore, elmore_exists);
|
||||
if (elmore_exists)
|
||||
// Input port with no external driver.
|
||||
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"; }
|
||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
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,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
|
||||
private:
|
||||
void loadDelaySlew(const Pin *load_pin,
|
||||
|
|
@ -213,42 +218,40 @@ DmpCeffTwoPoleDelayCalc::copy()
|
|||
Parasitic *
|
||||
DmpCeffTwoPoleDelayCalc::findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
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.
|
||||
if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|
||||
|| network_->direction(drvr_pin)->isInternal())
|
||||
return nullptr;
|
||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
// Prefer PiPoleResidue.
|
||||
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap);
|
||||
parasitic = parasitics->findPiPoleResidue(drvr_pin, rf, min_max);
|
||||
if (parasitic)
|
||||
return parasitic;
|
||||
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
|
||||
parasitic = parasitics->findPiElmore(drvr_pin, rf, min_max);
|
||||
if (parasitic)
|
||||
return parasitic;
|
||||
Parasitic *parasitic_network =
|
||||
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
|
||||
parasitics->findParasiticNetwork(drvr_pin);
|
||||
if (parasitic_network) {
|
||||
parasitic = parasitics_->reduceToPiPoleResidue2(parasitic_network, drvr_pin, rf,
|
||||
corner,
|
||||
dcalc_ap->constraintMinMax(),
|
||||
parasitic_ap);
|
||||
parasitic = parasitics->reduceToPiPoleResidue2(parasitic_network, drvr_pin, rf,
|
||||
scene, min_max);
|
||||
if (parasitic)
|
||||
return parasitic;
|
||||
}
|
||||
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
|
||||
Wireload *wireload = sdc_->wireload(cnst_min_max);
|
||||
Wireload *wireload = sdc->wireload(min_max);
|
||||
if (wireload) {
|
||||
float pin_cap, wire_cap, fanout;
|
||||
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);
|
||||
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload,
|
||||
fanout, pin_cap, corner,
|
||||
cnst_min_max);
|
||||
parasitic = parasitics->estimatePiElmore(drvr_pin, rf, wireload,
|
||||
fanout, pin_cap,
|
||||
scene, min_max);
|
||||
}
|
||||
return parasitic;
|
||||
}
|
||||
|
|
@ -259,21 +262,23 @@ DmpCeffTwoPoleDelayCalc::inputPortDelay(const Pin *,
|
|||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
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());
|
||||
ArcDelay wire_delay = 0.0;
|
||||
Slew load_slew = in_slew;
|
||||
LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
|
||||
for (const auto [load_pin, load_idx] : load_pin_index_map) {
|
||||
if (parasitics_->isPiPoleResidue(parasitic)) {
|
||||
const Parasitic *pole_residue = parasitics_->findPoleResidue(parasitic, load_pin);
|
||||
if (parasitics->isPiPoleResidue(parasitic)) {
|
||||
const Parasitic *pole_residue = parasitics->findPoleResidue(parasitic, load_pin);
|
||||
if (pole_residue) {
|
||||
size_t pole_count = parasitics_->poleResidueCount(pole_residue);
|
||||
size_t pole_count = parasitics->poleResidueCount(pole_residue);
|
||||
if (pole_count >= 1) {
|
||||
ComplexFloat pole1, residue1;
|
||||
// Find the 1st (elmore) pole.
|
||||
parasitics_->poleResidue(pole_residue, 0, pole1, residue1);
|
||||
parasitics->poleResidue(pole_residue, 0, pole1, residue1);
|
||||
if (pole1.imag() == 0.0
|
||||
&& residue1.imag() == 0.0) {
|
||||
float p1 = pole1.real();
|
||||
|
|
@ -297,8 +302,10 @@ DmpCeffTwoPoleDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
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 RiseFall *rf = arc->toEdge()->asRiseFall();
|
||||
vth_ = drvr_library->outputThreshold(rf);
|
||||
|
|
@ -306,7 +313,7 @@ DmpCeffTwoPoleDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
vh_ = drvr_library->slewUpperThreshold(rf);
|
||||
slew_derate_ = drvr_library->slewDerateFromLibrary();
|
||||
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
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
typedef const std::function<void (double x,
|
||||
using FindRootFunc = const std::function<void (double x,
|
||||
// Return values.
|
||||
double &y,
|
||||
double &dy)> FindRootFunc;
|
||||
double &dy)>;
|
||||
|
||||
double
|
||||
findRoot(FindRootFunc func,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -35,7 +35,6 @@
|
|||
#include "Network.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "Parasitics.hh"
|
||||
#include "DcalcAnalysisPt.hh"
|
||||
#include "GraphDelayCalc.hh"
|
||||
#include "Variables.hh"
|
||||
|
||||
|
|
@ -64,35 +63,37 @@ LumpedCapDelayCalc::copy()
|
|||
Parasitic *
|
||||
LumpedCapDelayCalc::findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
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.
|
||||
if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|
||||
|| sdc->drvrPinHasWireCap(drvr_pin)
|
||||
|| network_->direction(drvr_pin)->isInternal())
|
||||
return nullptr;
|
||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
|
||||
// Prefer PiElmore.
|
||||
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
|
||||
parasitic = parasitics->findPiElmore(drvr_pin, rf, min_max);
|
||||
if (parasitic)
|
||||
return parasitic;
|
||||
Parasitic *parasitic_network = parasitics_->findParasiticNetwork(drvr_pin,
|
||||
parasitic_ap);
|
||||
Parasitic *parasitic_network = parasitics->findParasiticNetwork(drvr_pin);
|
||||
if (parasitic_network) {
|
||||
parasitic = reduceParasitic(parasitic_network, drvr_pin, rf, dcalc_ap);
|
||||
parasitic = reduceParasitic(parasitic_network, drvr_pin, rf, scene, min_max);
|
||||
if (parasitic)
|
||||
return parasitic;
|
||||
}
|
||||
const MinMax *min_max = dcalc_ap->constraintMinMax();
|
||||
Wireload *wireload = sdc_->wireload(min_max);
|
||||
|
||||
Wireload *wireload = sdc->wireload(min_max);
|
||||
if (wireload) {
|
||||
float pin_cap, wire_cap, fanout;
|
||||
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);
|
||||
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload, fanout,
|
||||
pin_cap, corner, min_max);
|
||||
parasitic = parasitics->estimatePiElmore(drvr_pin, rf, wireload, fanout,
|
||||
pin_cap, scene, min_max);
|
||||
}
|
||||
return parasitic;
|
||||
}
|
||||
|
|
@ -101,14 +102,13 @@ Parasitic *
|
|||
LumpedCapDelayCalc::reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
|
||||
{
|
||||
const Corner *corner = dcalc_ap->corner();
|
||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
return parasitics_->reduceToPiElmore(parasitic_network, drvr_pin, rf,
|
||||
corner, dcalc_ap->constraintMinMax(),
|
||||
parasitic_ap);
|
||||
Parasitics *parasitics = scene->parasitics(min_max);
|
||||
return parasitics->reduceToPiElmore(parasitic_network, drvr_pin, rf,
|
||||
scene, min_max);
|
||||
}
|
||||
|
||||
ArcDcalcResult
|
||||
|
|
@ -117,7 +117,8 @@ LumpedCapDelayCalc::inputPortDelay(const Pin *,
|
|||
const RiseFall *rf,
|
||||
const Parasitic *,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *)
|
||||
const Scene *,
|
||||
const MinMax *)
|
||||
{
|
||||
const LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
|
||||
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,
|
||||
const Parasitic *,
|
||||
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,
|
||||
" in_slew = %s load_cap = %s lumped",
|
||||
delayAsString(in_slew, this),
|
||||
|
|
@ -146,7 +148,7 @@ LumpedCapDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
// NaNs cause seg faults during table lookup.
|
||||
if (isnan(load_cap) || isnan(delayAsFloat(in_slew)))
|
||||
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(),
|
||||
gate_delay, drvr_slew);
|
||||
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,
|
||||
const Parasitic *,
|
||||
const LoadPinIndexMap &,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits)
|
||||
{
|
||||
GateTimingModel *model = arc->gateModel(dcalc_ap);
|
||||
GateTimingModel *model = arc->gateModel(scene, min_max);
|
||||
if (model) {
|
||||
float in_slew1 = delayAsFloat(in_slew);
|
||||
return model->reportGateDelay(pinPvt(check_pin, dcalc_ap), in_slew1, load_cap,
|
||||
false, digits);
|
||||
return model->reportGateDelay(pinPvt(check_pin, scene, min_max),
|
||||
in_slew1, load_cap, false, digits);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,32 +38,37 @@ public:
|
|||
const char *name() const override { return "lumped_cap"; }
|
||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
bool reduceSupported() const override { return true; }
|
||||
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
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,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
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,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits) override;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#include "ParallelDelayCalc.hh"
|
||||
|
||||
#include "TimingArc.hh"
|
||||
#include "Corner.hh"
|
||||
#include "Scene.hh"
|
||||
#include "Network.hh"
|
||||
#include "Graph.hh"
|
||||
#include "Sdc.hh"
|
||||
|
|
@ -44,25 +44,28 @@ ParallelDelayCalc::ParallelDelayCalc(StaState *sta):
|
|||
ArcDcalcResultSeq
|
||||
ParallelDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
if (dcalc_args.size() == 1) {
|
||||
ArcDcalcArg &dcalc_arg = dcalc_args[0];
|
||||
ArcDcalcResult dcalc_result = gateDelay(dcalc_arg.drvrPin(), dcalc_arg.arc(),
|
||||
dcalc_arg.inSlew(), dcalc_arg.loadCap(),
|
||||
dcalc_arg.parasitic(),
|
||||
load_pin_index_map, dcalc_ap);
|
||||
load_pin_index_map,
|
||||
scene, min_max);
|
||||
ArcDcalcResultSeq dcalc_results;
|
||||
dcalc_results.push_back(dcalc_result);
|
||||
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
|
||||
ParallelDelayCalc::gateDelaysParallel(ArcDcalcArgSeq &dcalc_args,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
size_t drvr_count = dcalc_args.size();
|
||||
ArcDcalcResultSeq dcalc_results(drvr_count);
|
||||
|
|
@ -75,16 +78,16 @@ ParallelDelayCalc::gateDelaysParallel(ArcDcalcArgSeq &dcalc_args,
|
|||
ArcDcalcResult &dcalc_result = dcalc_results[drvr_idx];
|
||||
const Pin *drvr_pin = dcalc_arg.drvrPin();
|
||||
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,
|
||||
load_pin_index_map, dcalc_ap);
|
||||
load_pin_index_map, scene, min_max);
|
||||
ArcDelay intrinsic_delay = intrinsic_result.gateDelay();
|
||||
intrinsic_delays[drvr_idx] = intrinsic_result.gateDelay();
|
||||
|
||||
ArcDcalcResult gate_result = gateDelay(drvr_pin, arc, in_slew, dcalc_arg.loadCap(),
|
||||
dcalc_arg.parasitic(),
|
||||
load_pin_index_map, dcalc_ap);
|
||||
load_pin_index_map, scene, min_max);
|
||||
ArcDelay gate_delay = gate_result.gateDelay();
|
||||
Slew drvr_slew = gate_result.drvrSlew();
|
||||
ArcDelay load_delay = gate_delay - intrinsic_delay;
|
||||
|
|
|
|||
|
|
@ -38,11 +38,13 @@ public:
|
|||
ParallelDelayCalc(StaState *sta);
|
||||
ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &dcalc_args,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
protected:
|
||||
ArcDcalcResultSeq gateDelaysParallel(ArcDcalcArgSeq &dcalc_args,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -33,8 +33,7 @@
|
|||
#include "PortDirection.hh"
|
||||
#include "Network.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "DcalcAnalysisPt.hh"
|
||||
#include "Corner.hh"
|
||||
#include "Scene.hh"
|
||||
#include "Graph.hh"
|
||||
#include "Parasitics.hh"
|
||||
#include "GraphDelayCalc.hh"
|
||||
|
|
@ -64,9 +63,12 @@ makePrimaDelayCalc(StaState *sta)
|
|||
PrimaDelayCalc::PrimaDelayCalc(StaState *sta) :
|
||||
DelayCalcBase(sta),
|
||||
dcalc_args_(nullptr),
|
||||
scene_(nullptr),
|
||||
min_max_(nullptr),
|
||||
parasitics_(nullptr),
|
||||
parasitic_network_(nullptr),
|
||||
load_pin_index_map_(nullptr),
|
||||
pin_node_map_(network_),
|
||||
node_index_map_(ParasiticNodeLess(parasitics_, network_)),
|
||||
prima_order_(3),
|
||||
make_waveforms_(false),
|
||||
waveform_drvr_pin_(nullptr),
|
||||
|
|
@ -81,7 +83,7 @@ PrimaDelayCalc::PrimaDelayCalc(const PrimaDelayCalc &dcalc) :
|
|||
dcalc_args_(nullptr),
|
||||
load_pin_index_map_(nullptr),
|
||||
pin_node_map_(network_),
|
||||
node_index_map_(ParasiticNodeLess(parasitics_, network_)),
|
||||
node_index_map_(dcalc.node_index_map_),
|
||||
prima_order_(dcalc.prima_order_),
|
||||
make_waveforms_(false),
|
||||
waveform_drvr_pin_(nullptr),
|
||||
|
|
@ -113,27 +115,26 @@ PrimaDelayCalc::copyState(const StaState *sta)
|
|||
Parasitic *
|
||||
PrimaDelayCalc::findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
const Corner *corner = dcalc_ap->corner();
|
||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
// set_load net has precidence over parasitics.
|
||||
if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|
||||
const Sdc *sdc = scene->sdc();
|
||||
Parasitics *parasitics = scene->parasitics(min_max);
|
||||
if (parasitics == nullptr
|
||||
// set_load net has precedence over parasitics.
|
||||
|| network_->direction(drvr_pin)->isInternal())
|
||||
return nullptr;
|
||||
Parasitic *parasitic = parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
|
||||
Parasitic *parasitic = parasitics->findParasiticNetwork(drvr_pin);
|
||||
if (parasitic)
|
||||
return parasitic;
|
||||
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
|
||||
Wireload *wireload = sdc_->wireload(cnst_min_max);
|
||||
Wireload *wireload = sdc->wireload(min_max);
|
||||
if (wireload) {
|
||||
float pin_cap, wire_cap, fanout;
|
||||
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);
|
||||
parasitic = parasitics_->makeWireloadNetwork(drvr_pin, wireload,
|
||||
fanout, cnst_min_max,
|
||||
parasitic_ap);
|
||||
parasitic = parasitics->makeWireloadNetwork(drvr_pin, wireload,
|
||||
fanout, scene, min_max);
|
||||
}
|
||||
return parasitic;
|
||||
}
|
||||
|
|
@ -142,7 +143,8 @@ Parasitic *
|
|||
PrimaDelayCalc::reduceParasitic(const Parasitic *,
|
||||
const Pin *,
|
||||
const RiseFall *,
|
||||
const DcalcAnalysisPt *)
|
||||
const Scene *,
|
||||
const MinMax *)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -153,18 +155,16 @@ PrimaDelayCalc::inputPortDelay(const Pin *drvr_pin,
|
|||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
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());
|
||||
LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
|
||||
|
||||
const Parasitic *pi_elmore = nullptr;
|
||||
if (parasitic && parasitics_->isParasiticNetwork(parasitic)) {
|
||||
const ParasiticAnalysisPt *ap = dcalc_ap->parasiticAnalysisPt();
|
||||
pi_elmore = parasitics_->reduceToPiElmore(parasitic, drvr_pin, rf,
|
||||
dcalc_ap->corner(),
|
||||
dcalc_ap->constraintMinMax(), ap);
|
||||
}
|
||||
if (parasitic && parasitics->isParasiticNetwork(parasitic))
|
||||
pi_elmore = parasitics->reduceToPiElmore(parasitic, drvr_pin, rf,
|
||||
scene, min_max);
|
||||
|
||||
for (auto load_pin_index : load_pin_index_map) {
|
||||
const Pin *load_pin = load_pin_index.first;
|
||||
|
|
@ -174,7 +174,7 @@ PrimaDelayCalc::inputPortDelay(const Pin *drvr_pin,
|
|||
bool elmore_exists = false;
|
||||
float elmore = 0.0;
|
||||
if (pi_elmore)
|
||||
parasitics_->findElmore(pi_elmore, load_pin, elmore, elmore_exists);
|
||||
parasitics->findElmore(pi_elmore, load_pin, elmore, elmore_exists);
|
||||
if (elmore_exists)
|
||||
// Input port with no external driver.
|
||||
dspfWireDelaySlew(load_pin, rf, in_slew, elmore, wire_delay, load_slew);
|
||||
|
|
@ -192,33 +192,37 @@ PrimaDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
ArcDcalcArgSeq dcalc_args;
|
||||
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];
|
||||
}
|
||||
|
||||
ArcDcalcResultSeq
|
||||
PrimaDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
dcalc_args_ = &dcalc_args;
|
||||
load_pin_index_map_ = &load_pin_index_map;
|
||||
drvr_count_ = dcalc_args.size();
|
||||
dcalc_ap_ = dcalc_ap;
|
||||
scene_ = scene;
|
||||
min_max_ = min_max;
|
||||
drvr_rf_ = dcalc_args[0].arc()->toEdge()->asRiseFall();
|
||||
parasitic_network_ = dcalc_args[0].parasitic();
|
||||
load_cap_ = dcalc_args[0].loadCap();
|
||||
parasitics_ = scene->parasitics(min_max);
|
||||
node_index_map_ = NodeIndexMap(ParasiticNodeLess(parasitics_, network_));
|
||||
|
||||
bool failed = false;
|
||||
output_waveforms_.resize(drvr_count_);
|
||||
const DcalcAnalysisPtSeq &dcalc_aps = corners_->dcalcAnalysisPts();
|
||||
for (size_t drvr_idx = 0; drvr_idx < drvr_count_; 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()) {
|
||||
OutputWaveforms *output_waveforms = table_model->outputWaveforms();
|
||||
float in_slew = dcalc_arg.inSlewFlt();
|
||||
|
|
@ -236,7 +240,7 @@ PrimaDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
|||
drvr_library->supplyVoltage("VDD", vdd_, vdd_exists);
|
||||
if (!vdd_exists)
|
||||
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) {
|
||||
vth_ = drvr_library->outputThreshold(drvr_rf_) * vdd_;
|
||||
vl_ = drvr_library->slewLowerThreshold(drvr_rf_) * vdd_;
|
||||
|
|
@ -266,11 +270,13 @@ PrimaDelayCalc::tableDcalcResults()
|
|||
const Pin *drvr_pin = dcalc_arg.drvrPin();
|
||||
if (drvr_pin) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
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
|
||||
|
|
@ -388,8 +394,7 @@ PrimaDelayCalc::driverResistance()
|
|||
{
|
||||
const Pin *drvr_pin = (*dcalc_args_)[0].drvrPin();
|
||||
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
|
||||
|
|
@ -458,17 +463,16 @@ PrimaDelayCalc::pinCapacitance(ParasiticNode *node)
|
|||
{
|
||||
const Pin *pin = parasitics_->pin(node);
|
||||
float pin_cap = 0.0;
|
||||
const Sdc *sdc = scene_->sdc();
|
||||
if (pin) {
|
||||
Port *port = network_->port(pin);
|
||||
LibertyPort *lib_port = network_->libertyPort(port);
|
||||
const Corner *corner = dcalc_ap_->corner();
|
||||
const MinMax *cnst_min_max = dcalc_ap_->constraintMinMax();
|
||||
if (lib_port) {
|
||||
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))
|
||||
pin_cap = sdc_->portExtCap(port, drvr_rf_, corner, cnst_min_max);
|
||||
pin_cap = sdc->portExtCap(port, drvr_rf_, min_max_);
|
||||
}
|
||||
return pin_cap;
|
||||
}
|
||||
|
|
@ -910,14 +914,15 @@ PrimaDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
|||
float load_cap,
|
||||
const Parasitic *,
|
||||
const LoadPinIndexMap &,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits)
|
||||
{
|
||||
GateTimingModel *model = arc->gateModel(dcalc_ap);
|
||||
GateTimingModel *model = arc->gateModel(scene, min_max);
|
||||
if (model) {
|
||||
float in_slew1 = delayAsFloat(in_slew);
|
||||
return model->reportGateDelay(pinPvt(drvr_pin, dcalc_ap), in_slew1, load_cap,
|
||||
false, digits);
|
||||
return model->reportGateDelay(pinPvt(drvr_pin, scene, min_max),
|
||||
in_slew1, load_cap, false, digits);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
#include <Eigen/SparseCore>
|
||||
#include <Eigen/SparseLU>
|
||||
|
||||
#include "Map.hh"
|
||||
#include "LumpedCapDelayCalc.hh"
|
||||
#include "ArcDcalcWaveforms.hh"
|
||||
#include "Parasitics.hh"
|
||||
|
|
@ -38,16 +37,16 @@ namespace sta {
|
|||
|
||||
class ArcDelayCalc;
|
||||
class StaState;
|
||||
class Corner;
|
||||
class Scene;
|
||||
|
||||
typedef Map<const Pin*, size_t, PinIdLess> PinNodeMap;
|
||||
typedef std::map<const ParasiticNode*, size_t, ParasiticNodeLess> NodeIndexMap;
|
||||
typedef Map<const Pin*, size_t> PortIndexMap;
|
||||
typedef Eigen::SparseMatrix<double> MatrixSd;
|
||||
typedef Map<const Pin*, Eigen::VectorXd, PinIdLess> PinLMap;
|
||||
typedef std::map<const Pin*, FloatSeq, PinIdLess> WatchPinValuesMap;
|
||||
using PinNodeMap = std::map<const Pin*, size_t, PinIdLess>;
|
||||
using NodeIndexMap = std::map<const ParasiticNode*, size_t, ParasiticNodeLess>;
|
||||
using PortIndexMap = std::map<const Pin*, size_t>;
|
||||
using MatrixSd = Eigen::SparseMatrix<double>;
|
||||
using PinLMap = std::map<const Pin*, Eigen::VectorXd, PinIdLess>;
|
||||
using WatchPinValuesMap = std::map<const Pin*, FloatSeq, PinIdLess>;
|
||||
|
||||
typedef Table1 Waveform;
|
||||
using Waveform = Table1;
|
||||
|
||||
ArcDelayCalc *
|
||||
makePrimaDelayCalc(StaState *sta);
|
||||
|
|
@ -65,35 +64,41 @@ public:
|
|||
void setPrimaReduceOrder(size_t order);
|
||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
bool reduceSupported() const override { return false; }
|
||||
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
ArcDcalcResult inputPortDelay(const Pin *drvr_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
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,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &dcalc_args,
|
||||
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,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits) override;
|
||||
|
||||
// Record waveform for drvr/load pin.
|
||||
|
|
@ -147,7 +152,7 @@ protected:
|
|||
const Pin *drvr_pin,
|
||||
const RiseFall *drvr_rf,
|
||||
const Pin *load_pin,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
void primaReduce();
|
||||
void primaReduce2();
|
||||
|
|
@ -168,7 +173,9 @@ protected:
|
|||
ArcDcalcArgSeq *dcalc_args_;
|
||||
size_t drvr_count_;
|
||||
float load_cap_;
|
||||
const DcalcAnalysisPt *dcalc_ap_;
|
||||
const Scene *scene_;
|
||||
const MinMax *min_max_;
|
||||
Parasitics *parasitics_;
|
||||
const Parasitic *parasitic_network_;
|
||||
const RiseFall *drvr_rf_;
|
||||
const LoadPinIndexMap *load_pin_index_map_;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ UnitDelayCalc::copy()
|
|||
Parasitic *
|
||||
UnitDelayCalc::findParasitic(const Pin *,
|
||||
const RiseFall *,
|
||||
const DcalcAnalysisPt *)
|
||||
const Scene *,
|
||||
const MinMax *)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -59,7 +60,8 @@ Parasitic *
|
|||
UnitDelayCalc::reduceParasitic(const Parasitic *,
|
||||
const Pin *,
|
||||
const RiseFall *,
|
||||
const DcalcAnalysisPt *)
|
||||
const Scene *,
|
||||
const MinMax *)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -67,20 +69,22 @@ UnitDelayCalc::reduceParasitic(const Parasitic *,
|
|||
void
|
||||
UnitDelayCalc::reduceParasitic(const Parasitic *,
|
||||
const Net *,
|
||||
const Corner *,
|
||||
const Scene *,
|
||||
const MinMaxAll *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
UnitDelayCalc::setDcalcArgParasiticSlew(ArcDcalcArg &,
|
||||
const DcalcAnalysisPt *)
|
||||
const Scene *,
|
||||
const MinMax *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
UnitDelayCalc::setDcalcArgParasiticSlew(ArcDcalcArgSeq &,
|
||||
const DcalcAnalysisPt *)
|
||||
const Scene *,
|
||||
const MinMax *)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +94,8 @@ UnitDelayCalc::inputPortDelay(const Pin *,
|
|||
const RiseFall *,
|
||||
const Parasitic *,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *)
|
||||
const Scene *,
|
||||
const MinMax *)
|
||||
{
|
||||
return unitDelayResult(load_pin_index_map);
|
||||
}
|
||||
|
|
@ -102,7 +107,8 @@ UnitDelayCalc::gateDelay(const Pin *,
|
|||
float,
|
||||
const Parasitic *,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *)
|
||||
const Scene *,
|
||||
const MinMax *)
|
||||
{
|
||||
return unitDelayResult(load_pin_index_map);
|
||||
}
|
||||
|
|
@ -110,7 +116,8 @@ UnitDelayCalc::gateDelay(const Pin *,
|
|||
ArcDcalcResultSeq
|
||||
UnitDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *)
|
||||
const Scene *,
|
||||
const MinMax *)
|
||||
{
|
||||
size_t drvr_count = dcalc_args.size();
|
||||
ArcDcalcResultSeq dcalc_results(drvr_count);
|
||||
|
|
@ -142,7 +149,8 @@ UnitDelayCalc::reportGateDelay(const Pin *,
|
|||
float,
|
||||
const Parasitic *,
|
||||
const LoadPinIndexMap &,
|
||||
const DcalcAnalysisPt *,
|
||||
const Scene *,
|
||||
const MinMax *,
|
||||
int)
|
||||
{
|
||||
string result("Delay = 1.0\n");
|
||||
|
|
@ -156,7 +164,8 @@ UnitDelayCalc::checkDelay(const Pin *,
|
|||
const Slew &,
|
||||
const Slew &,
|
||||
float,
|
||||
const DcalcAnalysisPt *)
|
||||
const Scene *,
|
||||
const MinMax *)
|
||||
{
|
||||
return units_->timeUnit()->scale();
|
||||
}
|
||||
|
|
@ -168,7 +177,8 @@ UnitDelayCalc::reportCheckDelay(const Pin *,
|
|||
const char *,
|
||||
const Slew &,
|
||||
float,
|
||||
const DcalcAnalysisPt *,
|
||||
const Scene *,
|
||||
const MinMax *,
|
||||
int)
|
||||
{
|
||||
return "Check = 1.0\n";
|
||||
|
|
|
|||
|
|
@ -37,26 +37,31 @@ public:
|
|||
const char *name() const override { return "unit"; }
|
||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
bool reduceSupported() const override { return false; }
|
||||
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
void reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Net *net,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMaxAll *min_max) override;
|
||||
void setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
void setDcalcArgParasiticSlew(ArcDcalcArgSeq &gates,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
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,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
|
|
@ -64,23 +69,27 @@ public:
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &args,
|
||||
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,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) override;
|
||||
std::string reportGateDelay(const Pin *drvr_pin,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits) override;
|
||||
std::string reportCheckDelay(const Pin *check_pin,
|
||||
const TimingArc *arc,
|
||||
|
|
@ -88,7 +97,8 @@ public:
|
|||
const char *from_slew_annotation,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits) override;
|
||||
void finishDrvrPin() override;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,45 @@
|
|||
|
||||
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
|
||||
------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,180 @@ OpenSTA Timing Analyzer Release Notes
|
|||
|
||||
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
|
||||
-------------------------
|
||||
|
||||
|
|
@ -19,6 +193,9 @@ to remove paths through identical pins and rise/fall edges.
|
|||
|
||||
Instances now have pins for verilog netlist power/ground connections,
|
||||
|
||||
Sta::findPathEnds group_paths arg has been changed from PathGroupNameSet*
|
||||
to StdStringSeq&.
|
||||
|
||||
Release 2.6.1 2025/03/30
|
||||
-------------------------
|
||||
|
||||
|
|
@ -93,6 +270,8 @@ timing groups.
|
|||
report_clock_skew -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
|
||||
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
|
||||
define_corners ss tt ff
|
||||
read_liberty -corner ss nangate45_slow.lib.gz
|
||||
read_liberty -corner tt nangate45_typ.lib.gz
|
||||
read_liberty -corner ff nangate45_fast.lib.gz
|
||||
# 3 liberty corners with +/- 10% derating example
|
||||
read_liberty nangate45_slow.lib.gz
|
||||
read_liberty nangate45_typ.lib.gz
|
||||
read_liberty nangate45_fast.lib.gz
|
||||
read_verilog example1.v
|
||||
link_design top
|
||||
set_timing_derate -early 0.9
|
||||
set_timing_derate -late 1.1
|
||||
create_clock -name clk -period 10 {clk1 clk2 clk3}
|
||||
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 typical corner
|
||||
report_checks -corner tt
|
||||
# report typical scene
|
||||
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 "ContainerHelpers.hh"
|
||||
#include "Debug.hh"
|
||||
#include "Stats.hh"
|
||||
#include "MinMax.hh"
|
||||
|
|
@ -34,7 +35,6 @@
|
|||
#include "Liberty.hh"
|
||||
#include "PortDirection.hh"
|
||||
#include "Network.hh"
|
||||
#include "DcalcAnalysisPt.hh"
|
||||
#include "FuncExpr.hh"
|
||||
|
||||
namespace sta {
|
||||
|
|
@ -56,7 +56,7 @@ Graph::Graph(StaState *sta,
|
|||
slew_rf_count_(slew_rf_count),
|
||||
ap_count_(ap_count),
|
||||
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_.
|
||||
graph_ = this;
|
||||
|
|
@ -68,7 +68,6 @@ Graph::~Graph()
|
|||
delete edges_;
|
||||
vertices_->clear();
|
||||
delete vertices_;
|
||||
delete reg_clk_vertices_;
|
||||
removePeriodCheckAnnotations();
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +253,7 @@ Graph::makeInstDrvrWireEdges(const Instance *inst,
|
|||
while (pin_iter->hasNext()) {
|
||||
Pin *pin = pin_iter->next();
|
||||
if (network_->isDriver(pin)
|
||||
&& !visited_drvrs.hasKey(pin))
|
||||
&& !visited_drvrs.contains(pin))
|
||||
makeWireEdgesFromPin(pin, visited_drvrs);
|
||||
}
|
||||
delete pin_iter;
|
||||
|
|
@ -391,6 +390,13 @@ Graph::makeWireEdge(const Pin *from_pin,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Graph::makeSceneAfter()
|
||||
{
|
||||
ap_count_ = dcalcAnalysisPtCount();
|
||||
initSlews();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
Vertex *
|
||||
|
|
@ -440,7 +446,7 @@ Graph::makeVertex(Pin *pin,
|
|||
vertex->init(pin, is_bidirect_drvr, is_reg_clk);
|
||||
initSlews(vertex);
|
||||
if (is_reg_clk)
|
||||
reg_clk_vertices_->insert(vertex);
|
||||
reg_clk_vertices_.insert(vertex);
|
||||
return vertex;
|
||||
}
|
||||
|
||||
|
|
@ -452,7 +458,7 @@ Graph::pinVertices(const Pin *pin,
|
|||
{
|
||||
vertex = Graph::vertex(network_->vertexId(pin));
|
||||
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
|
||||
bidirect_drvr_vertex = nullptr;
|
||||
}
|
||||
|
|
@ -461,7 +467,7 @@ Vertex *
|
|||
Graph::pinDrvrVertex(const Pin *pin) const
|
||||
{
|
||||
if (network_->direction(pin)->isBidirect())
|
||||
return pin_bidirect_drvr_vertex_map_.findKey(pin);
|
||||
return findKey(pin_bidirect_drvr_vertex_map_, pin);
|
||||
else
|
||||
return Graph::vertex(network_->vertexId(pin));
|
||||
}
|
||||
|
|
@ -476,7 +482,7 @@ void
|
|||
Graph::deleteVertex(Vertex *vertex)
|
||||
{
|
||||
if (vertex->isRegClk())
|
||||
reg_clk_vertices_->erase(vertex);
|
||||
reg_clk_vertices_.erase(vertex);
|
||||
Pin *pin = vertex->pin_;
|
||||
if (vertex->isBidirectDriver())
|
||||
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 &
|
||||
Graph::slew(const Vertex *vertex,
|
||||
const RiseFall *rf,
|
||||
|
|
@ -831,19 +813,6 @@ Graph::initArcDelays(Edge *edge)
|
|||
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
|
||||
|
|
@ -906,7 +875,7 @@ Graph::periodCheckAnnotation(const Pin *pin,
|
|||
{
|
||||
exists = false;
|
||||
if (period_check_annotations_) {
|
||||
float *periods = period_check_annotations_->findKey(pin);
|
||||
float *periods = findKey(period_check_annotations_, pin);
|
||||
if (periods) {
|
||||
period = periods[ap_index];
|
||||
if (period >= 0.0)
|
||||
|
|
@ -922,7 +891,7 @@ Graph::setPeriodCheckAnnotation(const Pin *pin,
|
|||
{
|
||||
if (period_check_annotations_ == nullptr)
|
||||
period_check_annotations_ = new PeriodCheckAnnotations(network_);
|
||||
float *periods = period_check_annotations_->findKey(pin);
|
||||
float *periods = findKey(period_check_annotations_, pin);
|
||||
if (periods == nullptr) {
|
||||
periods = new float[ap_count_];
|
||||
// Use negative (illegal) period values to indicate unannotated checks.
|
||||
|
|
@ -986,16 +955,13 @@ Vertex::init(Pin *pin,
|
|||
paths_ = nullptr;
|
||||
tag_group_index_ = tag_group_index_max;
|
||||
slew_annotated_ = false;
|
||||
sim_value_ = unsigned(LogicValue::unknown);
|
||||
is_disabled_constraint_ = false;
|
||||
is_gated_clk_enable_ = false;
|
||||
has_checks_ = false;
|
||||
is_check_clk_ = false;
|
||||
is_constrained_ = false;
|
||||
has_downstream_clk_pin_ = false;
|
||||
level_ = 0;
|
||||
visited1_ = false;
|
||||
visited2_ = false;
|
||||
has_sim_value_ = false;
|
||||
bfs_in_queue_ = 0;
|
||||
}
|
||||
|
||||
|
|
@ -1082,11 +1048,17 @@ Vertex::setSlews(Slew *slews)
|
|||
slews_ = slews;
|
||||
}
|
||||
|
||||
void
|
||||
Vertex::setHasSimValue(bool has_sim)
|
||||
{
|
||||
has_sim_value_ = has_sim;
|
||||
}
|
||||
|
||||
bool
|
||||
Vertex::slewAnnotated(const RiseFall *rf,
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -1105,7 +1077,7 @@ Vertex::setSlewAnnotated(bool annotated,
|
|||
// only rise/fall.
|
||||
if (ap_index > 1)
|
||||
ap_index = 0;
|
||||
int index = ap_index * transitionCount() + rf->index();
|
||||
int index = ap_index * RiseFall::index_count + rf->index();
|
||||
if (annotated)
|
||||
slew_annotated_ |= (1 << index);
|
||||
else
|
||||
|
|
@ -1130,6 +1102,15 @@ Vertex::setTagGroupIndex(TagGroupIndex 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
|
||||
Vertex::setPaths(Path *paths)
|
||||
{
|
||||
|
|
@ -1137,30 +1118,12 @@ Vertex::setPaths(Path *paths)
|
|||
paths_ = paths;
|
||||
}
|
||||
|
||||
LogicValue
|
||||
Vertex::simValue() const
|
||||
{
|
||||
return static_cast<LogicValue>(sim_value_);
|
||||
}
|
||||
|
||||
void
|
||||
Vertex::setSimValue(LogicValue value)
|
||||
Vertex::deletePaths()
|
||||
{
|
||||
sim_value_ = unsigned(value);
|
||||
}
|
||||
|
||||
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;
|
||||
delete [] paths_;
|
||||
paths_ = nullptr;
|
||||
tag_group_index_ = tag_group_index_max;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -1187,18 +1150,6 @@ Vertex::setIsCheckClk(bool 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
|
||||
Vertex::setHasDownstreamClkPin(bool has_clk_pin)
|
||||
{
|
||||
|
|
@ -1251,10 +1202,9 @@ Edge::init(VertexId from,
|
|||
arc_delay_annotated_is_bits_ = true;
|
||||
arc_delay_annotated_.bits_ = 0;
|
||||
delay_annotation_is_incremental_ = false;
|
||||
sim_timing_sense_ = unsigned(TimingSense::unknown);
|
||||
is_disabled_constraint_ = false;
|
||||
is_disabled_cond_ = false;
|
||||
is_disabled_loop_ = false;
|
||||
has_sim_sense_ = false;
|
||||
has_disabled_cond_ = false;
|
||||
}
|
||||
|
||||
Edge::~Edge()
|
||||
|
|
@ -1384,48 +1334,6 @@ Edge::sense() const
|
|||
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
|
||||
Edge::setIsDisabledLoop(bool disabled)
|
||||
{
|
||||
|
|
@ -1444,6 +1352,18 @@ Edge::setIsBidirectNetPath(bool 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) :
|
||||
|
|
@ -1483,7 +1403,7 @@ VertexIterator::findNextPin()
|
|||
Pin *pin = pin_iter_->next();
|
||||
vertex_ = graph_->vertex(network_->vertexId(pin));
|
||||
bidir_vertex_ = network_->direction(pin)->isBidirect()
|
||||
? graph_->pin_bidirect_drvr_vertex_map_.findKey(pin)
|
||||
? findKey(graph_->pin_bidirect_drvr_vertex_map_, pin)
|
||||
: nullptr;
|
||||
if (vertex_ || bidir_vertex_)
|
||||
return true;
|
||||
|
|
@ -1600,7 +1520,19 @@ EdgesThruHierPinIterator::EdgesThruHierPinIterator(const Pin *hpin,
|
|||
{
|
||||
FindEdgesThruHierPinVisitor visitor(edges_, graph);
|
||||
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);
|
||||
}
|
||||
|
||||
VertexSet::VertexSet(Graph *&graph) :
|
||||
Set<Vertex*, VertexIdLess>(VertexIdLess(graph))
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
229
graph/Graph.i
229
graph/Graph.i
|
|
@ -31,8 +31,9 @@
|
|||
#include "Liberty.hh"
|
||||
#include "Network.hh"
|
||||
#include "Clock.hh"
|
||||
#include "Corner.hh"
|
||||
#include "Scene.hh"
|
||||
#include "Search.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "Sta.hh"
|
||||
|
||||
using namespace sta;
|
||||
|
|
@ -93,21 +94,21 @@ vertex_iterator()
|
|||
void
|
||||
set_arc_delay(Edge *edge,
|
||||
TimingArc *arc,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMaxAll *min_max,
|
||||
float delay)
|
||||
{
|
||||
Sta::sta()->setArcDelay(edge, arc, corner, min_max, delay);
|
||||
Sta::sta()->setArcDelay(edge, arc, scene, min_max, delay);
|
||||
}
|
||||
|
||||
void
|
||||
set_annotated_slew(Vertex *vertex,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMaxAll *min_max,
|
||||
const RiseFallBoth *rf,
|
||||
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.
|
||||
|
|
@ -132,20 +133,20 @@ int level() { return Sta::sta()->vertexLevel(self); }
|
|||
int tag_group_index() { return self->tagGroupIndex(); }
|
||||
|
||||
Slew
|
||||
slew(const RiseFall *rf,
|
||||
slew(const RiseFallBoth *rf,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
Sta *sta = Sta::sta();
|
||||
return sta->vertexSlew(self, rf, min_max);
|
||||
return sta->slew(self, rf, sta->scenes(), min_max);
|
||||
}
|
||||
|
||||
Slew
|
||||
slew_corner(const RiseFall *rf,
|
||||
const Corner *corner,
|
||||
slew_scenes(const RiseFallBoth *rf,
|
||||
const SceneSeq scenes,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
Sta *sta = Sta::sta();
|
||||
return sta->vertexSlew(self, rf, corner, min_max);
|
||||
return sta->slew(self, rf, scenes, min_max);
|
||||
}
|
||||
|
||||
VertexOutEdgeIterator *
|
||||
|
|
@ -160,162 +161,13 @@ in_edge_iterator()
|
|||
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 *
|
||||
path_iterator(const RiseFall *rf,
|
||||
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
|
||||
|
||||
%extend Edge {
|
||||
|
|
@ -328,28 +180,51 @@ const char *sense() { return to_string(self->sense()); }
|
|||
TimingArcSeq &
|
||||
timing_arcs() { return self->timingArcSet()->arcs(); }
|
||||
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()
|
||||
{ return Sta::sta()->isDisabledCondDefault(self); }
|
||||
|
||||
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()
|
||||
{ return Sta::sta()->isDisabledBidirectInstPath(self); }
|
||||
bool is_disabled_bidirect_net_path()
|
||||
{ return Sta::sta()->isDisabledBidirectNetPath(self); }
|
||||
bool is_disabled_preset_clear()
|
||||
{ return Sta::sta()->isDisabledPresetClr(self); }
|
||||
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
|
||||
arc_delays(TimingArc *arc)
|
||||
{
|
||||
Sta *sta = Sta::sta();
|
||||
FloatSeq delays;
|
||||
for (auto dcalc_ap : sta->corners()->dcalcAnalysisPts())
|
||||
delays.push_back(delayAsFloat(sta->arcDelay(self, arc, dcalc_ap)));
|
||||
DcalcAPIndex ap_count = sta->dcalcAnalysisPtCount();
|
||||
for (DcalcAPIndex ap_index = 0; ap_index < ap_count; ap_index++)
|
||||
delays.push_back(delayAsFloat(sta->arcDelay(self, arc, ap_index)));
|
||||
return delays;
|
||||
}
|
||||
|
||||
|
|
@ -359,31 +234,31 @@ arc_delay_strings(TimingArc *arc,
|
|||
{
|
||||
Sta *sta = Sta::sta();
|
||||
StringSeq delays;
|
||||
for (auto dcalc_ap : sta->corners()->dcalcAnalysisPts())
|
||||
delays.push_back(delayAsString(sta->arcDelay(self, arc, dcalc_ap),
|
||||
DcalcAPIndex ap_count = sta->dcalcAnalysisPtCount();
|
||||
for (DcalcAPIndex ap_index = 0; ap_index < ap_count; ap_index++)
|
||||
delays.push_back(delayAsString(sta->arcDelay(self, arc, ap_index),
|
||||
sta, digits));
|
||||
return delays;
|
||||
}
|
||||
|
||||
bool
|
||||
delay_annotated(TimingArc *arc,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
||||
return Sta::sta()->arcDelayAnnotated(self, arc, dcalc_ap);
|
||||
return Sta::sta()->arcDelayAnnotated(self, arc, scene, min_max);
|
||||
}
|
||||
|
||||
float
|
||||
arc_delay(TimingArc *arc,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
||||
return delayAsFloat(Sta::sta()->arcDelay(self, arc, dcalc_ap));
|
||||
DcalcAPIndex ap_index = scene->dcalcAnalysisPtIndex(min_max);
|
||||
return delayAsFloat(Sta::sta()->arcDelay(self, arc, ap_index));
|
||||
}
|
||||
|
||||
string
|
||||
std::string
|
||||
cond()
|
||||
{
|
||||
FuncExpr *cond = self->timingArcSet()->cond();
|
||||
|
|
|
|||
|
|
@ -180,10 +180,6 @@ proc edge_disable_reason { edge } {
|
|||
if { $disables != "" } { append disables ", " }
|
||||
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 { $disables != "" } { append disables ", " }
|
||||
append disables "sta_preset_clear_arcs_enabled"
|
||||
|
|
@ -295,28 +291,6 @@ proc edge_disable_reason_verbose { edge } {
|
|||
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 } {
|
||||
set pin [$vertex pin]
|
||||
set pin_name [get_full_name $pin]
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
//
|
||||
// This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include "ContainerHelpers.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "Network.hh"
|
||||
#include "NetworkCmp.hh"
|
||||
|
|
|
|||
|
|
@ -40,17 +40,16 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
class Corner;
|
||||
class Scene;
|
||||
class Parasitic;
|
||||
class DcalcAnalysisPt;
|
||||
class MultiDrvrNet;
|
||||
class ArcDcalcArg;
|
||||
|
||||
typedef std::vector<ArcDcalcArg*> ArcDcalcArgPtrSeq;
|
||||
typedef std::vector<ArcDcalcArg> ArcDcalcArgSeq;
|
||||
using ArcDcalcArgPtrSeq = std::vector<ArcDcalcArg*>;
|
||||
using ArcDcalcArgSeq = std::vector<ArcDcalcArg>;
|
||||
|
||||
// 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
|
||||
// through one timing arc at one delay calc analysis point.
|
||||
|
|
@ -81,7 +80,7 @@ public:
|
|||
const Net *drvrNet(const Network *network) const;
|
||||
Edge *edge() const { return edge_; }
|
||||
const TimingArc *arc() const { return arc_; }
|
||||
Slew inSlew() const { return in_slew_; }
|
||||
const Slew &inSlew() const { return in_slew_; }
|
||||
float inSlewFlt() const;
|
||||
void setInSlew(Slew in_slew);
|
||||
const Parasitic *parasitic() const { return parasitic_; }
|
||||
|
|
@ -138,8 +137,7 @@ protected:
|
|||
std::vector<Slew> load_slews_;
|
||||
};
|
||||
|
||||
typedef std::vector<ArcDcalcArg> ArcDcalcArgSeq;
|
||||
typedef std::vector<ArcDcalcResult> ArcDcalcResultSeq;
|
||||
using ArcDcalcResultSeq = std::vector<ArcDcalcResult>;
|
||||
|
||||
// Delay calculator class hierarchy.
|
||||
// ArcDelayCalc
|
||||
|
|
@ -160,7 +158,7 @@ typedef std::vector<ArcDcalcResult> ArcDcalcResultSeq;
|
|||
class ArcDelayCalc : public StaState
|
||||
{
|
||||
public:
|
||||
explicit ArcDelayCalc(StaState *sta);
|
||||
ArcDelayCalc(StaState *sta);
|
||||
virtual ~ArcDelayCalc() {}
|
||||
virtual ArcDelayCalc *copy() = 0;
|
||||
virtual const char *name() const = 0;
|
||||
|
|
@ -169,25 +167,29 @@ public:
|
|||
// calculator by probing parasitics_.
|
||||
virtual Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) = 0;
|
||||
virtual bool reduceSupported() const = 0;
|
||||
// Reduce parasitic_network to a representation acceptable to the delay calculator.
|
||||
virtual Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
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
|
||||
// for one or more corners and min/max rise/fall.
|
||||
// Null corner means reduce all corners.
|
||||
// for one or more scenes and min/max rise/fall.
|
||||
// Null scene means reduce all scenes.
|
||||
virtual void reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Net *net,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMaxAll *min_max) = 0;
|
||||
// Set the in_slew, load_cap, parasitic for gates.
|
||||
virtual void setDcalcArgParasiticSlew(ArcDcalcArg &gate,
|
||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) = 0;
|
||||
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.
|
||||
// This call primarily initializes the load delay/slew iterator.
|
||||
virtual ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||
|
|
@ -195,7 +197,8 @@ public:
|
|||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
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.
|
||||
virtual ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
||||
|
|
@ -205,7 +208,8 @@ public:
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) = 0;
|
||||
// deprecated 2024-02-27
|
||||
virtual void gateDelay(const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
|
|
@ -213,7 +217,8 @@ public:
|
|||
const Parasitic *parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) __attribute__ ((deprecated));
|
||||
|
|
@ -221,7 +226,8 @@ public:
|
|||
// Find gate delays and slews for parallel gates.
|
||||
virtual ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &args,
|
||||
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
|
||||
// from/clock, to/data slews and related output pin parasitic.
|
||||
|
|
@ -230,7 +236,8 @@ public:
|
|||
const Slew &from_slew,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) = 0;
|
||||
// Report delay and slew calculation.
|
||||
virtual std::string reportGateDelay(const Pin *drvr_pin,
|
||||
const TimingArc *arc,
|
||||
|
|
@ -238,7 +245,8 @@ public:
|
|||
float load_cap,
|
||||
const Parasitic *parasitic,
|
||||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits) = 0;
|
||||
// Report timing check delay calculation.
|
||||
virtual std::string reportCheckDelay(const Pin *check_pin,
|
||||
|
|
@ -247,7 +255,8 @@ public:
|
|||
const char *from_slew_annotation,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits) = 0;
|
||||
virtual void finishDrvrPin() = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ struct DdManager;
|
|||
|
||||
namespace sta {
|
||||
|
||||
typedef std::map<const LibertyPort*, DdNode*, LibertyPortLess> BddPortVarMap;
|
||||
typedef std::map<unsigned, const LibertyPort*> BddVarIdxPortMap;
|
||||
using BddPortVarMap = std::map<const LibertyPort*, DdNode*, LibertyPortLess>;
|
||||
using BddVarIdxPortMap = std::map<unsigned, const LibertyPort*>;
|
||||
|
||||
class Bdd : public StaState
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "Iterator.hh"
|
||||
#include "Set.hh"
|
||||
#include "GraphClass.hh"
|
||||
#include "VertexVisitor.hh"
|
||||
#include "StaState.hh"
|
||||
|
|
@ -39,7 +39,7 @@ class BfsFwdIterator;
|
|||
class BfsBkwdIterator;
|
||||
|
||||
// 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.
|
||||
// Visit all of the vertices at a level before moving to the next.
|
||||
|
|
@ -58,19 +58,19 @@ public:
|
|||
void ensureSize();
|
||||
// Reset to virgin state.
|
||||
void clear();
|
||||
bool empty() const;
|
||||
[[nodiscard]] bool empty() const;
|
||||
// Enqueue a vertex to search from.
|
||||
void enqueue(Vertex *vertex);
|
||||
// Enqueue vertices adjacent to a vertex.
|
||||
void enqueueAdjacentVertices(Vertex *vertex);
|
||||
void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred);
|
||||
void enqueueAdjacentVertices(Vertex *vertex,
|
||||
Level to_level);
|
||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||
const Mode *mode);
|
||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred,
|
||||
Level to_level) = 0;
|
||||
bool inQueue(Vertex *vertex);
|
||||
const Mode *mode) = 0;
|
||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred) = 0;
|
||||
[[nodiscard]] bool inQueue(Vertex *vertex);
|
||||
void checkInQueue(Vertex *vertex);
|
||||
// Notify iterator that vertex will be deleted.
|
||||
void deleteVertexBefore(Vertex *vertex);
|
||||
|
|
@ -131,9 +131,11 @@ public:
|
|||
SearchPred *search_pred,
|
||||
StaState *sta);
|
||||
virtual ~BfsFwdIterator();
|
||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred);
|
||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred,
|
||||
Level to_level);
|
||||
const Mode *mode);
|
||||
using BfsIterator::enqueueAdjacentVertices;
|
||||
|
||||
protected:
|
||||
|
|
@ -151,9 +153,11 @@ public:
|
|||
SearchPred *search_pred,
|
||||
StaState *sta);
|
||||
virtual ~BfsBkwdIterator();
|
||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred);
|
||||
virtual void enqueueAdjacentVertices(Vertex *vertex,
|
||||
SearchPred *search_pred,
|
||||
Level to_level);
|
||||
const Mode *mode);
|
||||
using BfsIterator::enqueueAdjacentVertices;
|
||||
|
||||
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
|
||||
|
||||
#include "Map.hh"
|
||||
#include "Set.hh"
|
||||
#include <map>
|
||||
|
||||
#include "StaState.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "GraphClass.hh"
|
||||
|
|
@ -33,31 +33,34 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
typedef Map<const Pin*, ClockSet> PinClksMap;
|
||||
typedef Map<const Clock *, PinSet*> ClkPinsMap;
|
||||
using PinClksMap = std::map<const Pin*, ClockSet>;
|
||||
using ClkPinsMap = std::map<const Clock *, PinSet*>;
|
||||
|
||||
class Sta;
|
||||
|
||||
// Find clock network pins.
|
||||
// This is not as reliable as Search::isClock but is much cheaper.
|
||||
class ClkNetwork : public StaState
|
||||
{
|
||||
public:
|
||||
ClkNetwork(StaState *sta);
|
||||
ClkNetwork(Mode *mode,
|
||||
StaState *sta);
|
||||
~ClkNetwork();
|
||||
void ensureClkNetwork();
|
||||
void clear();
|
||||
bool isClock(const Pin *pin) const;
|
||||
bool isClock(const Vertex *vertex) const;
|
||||
bool isClock(const Net *net) const;
|
||||
bool isIdealClock(const Pin *pin) const;
|
||||
bool isIdealClock(const Vertex *vertex) const;
|
||||
bool isPropagatedClock(const Pin *pin) const;
|
||||
const ClockSet *clocks(const Pin *pin);
|
||||
const ClockSet *idealClocks(const Pin *pin);
|
||||
const ClockSet *clocks(const Pin *pin) const;
|
||||
const ClockSet *clocks(const Vertex *vertex) const;
|
||||
const ClockSet *idealClocks(const Pin *pin) const;
|
||||
const PinSet *pins(const Clock *clk);
|
||||
void clkPinsInvalid();
|
||||
float idealClkSlew(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const MinMax *min_max);
|
||||
const MinMax *min_max) const;
|
||||
|
||||
protected:
|
||||
void deletePinBefore(const Pin *pin);
|
||||
|
|
@ -66,6 +69,8 @@ protected:
|
|||
friend class Sta;
|
||||
|
||||
private:
|
||||
Mode *mode_;
|
||||
|
||||
void findClkPins();
|
||||
void findClkPins(bool ideal_only,
|
||||
PinClksMap &clk_pin_map);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "MinMax.hh"
|
||||
#include "RiseFallMinMax.hh"
|
||||
#include "SdcClass.hh"
|
||||
|
|
@ -32,7 +34,7 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
typedef Map<Pin*, PinSet*> ClkHpinEdgeMap;
|
||||
using ClkHpinEdgeMap = std::map<Pin*, PinSet*>;
|
||||
|
||||
class Clock : public SdcCmdComment
|
||||
{
|
||||
|
|
@ -264,7 +266,7 @@ public:
|
|||
const RiseFallBoth *tgt_rf,
|
||||
const SetupHoldAll *setup_hold);
|
||||
const RiseFallMinMax *uncertainties(const RiseFall *src_rf) const;
|
||||
bool empty() const;
|
||||
[[nodiscard]] bool empty() const;
|
||||
|
||||
private:
|
||||
const Clock *src_;
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "Vector.hh"
|
||||
#include "Map.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "NetworkClass.hh"
|
||||
|
||||
|
|
@ -45,17 +45,17 @@ class PatternMatch;
|
|||
class LibertyCell;
|
||||
class LibertyPort;
|
||||
|
||||
typedef Map<std::string, ConcreteCell*> ConcreteCellMap;
|
||||
typedef Vector<ConcretePort*> ConcretePortSeq;
|
||||
typedef Map<std::string, ConcretePort*> ConcretePortMap;
|
||||
typedef ConcreteCellMap::ConstIterator ConcreteLibraryCellIterator;
|
||||
typedef ConcretePortSeq::ConstIterator ConcreteCellPortIterator;
|
||||
typedef ConcretePortSeq::ConstIterator ConcretePortMemberIterator;
|
||||
using ConcreteCellMap = std::map<std::string, ConcreteCell*>;
|
||||
using ConcretePortSeq = std::vector<ConcretePort*>;
|
||||
using ConcretePortMap = std::map<std::string, ConcretePort*>;
|
||||
using ConcreteLibraryCellIterator = MapIterator<ConcreteCellMap, ConcreteCell*>;
|
||||
using ConcreteCellPortIterator = VectorIterator<ConcretePortSeq, ConcretePort*>;
|
||||
using ConcretePortMemberIterator = VectorIterator<ConcretePortSeq, ConcretePort*>;
|
||||
|
||||
class ConcreteLibrary
|
||||
{
|
||||
public:
|
||||
explicit ConcreteLibrary(const char *name,
|
||||
ConcreteLibrary(const char *name,
|
||||
const char *filename,
|
||||
bool is_liberty);
|
||||
virtual ~ConcreteLibrary();
|
||||
|
|
@ -263,14 +263,15 @@ private:
|
|||
class ConcreteCellPortBitIterator : public Iterator<ConcretePort*>
|
||||
{
|
||||
public:
|
||||
explicit ConcreteCellPortBitIterator(const ConcreteCell *cell);
|
||||
ConcreteCellPortBitIterator(const ConcreteCell *cell);
|
||||
virtual bool hasNext();
|
||||
virtual ConcretePort *next();
|
||||
|
||||
private:
|
||||
void findNext();
|
||||
|
||||
ConcretePortSeq::ConstIterator port_iter_;
|
||||
const ConcretePortSeq &ports_;
|
||||
ConcretePortSeq::const_iterator port_iter_;
|
||||
ConcretePortMemberIterator *member_iter_;
|
||||
ConcretePort *next_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,9 +25,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "Map.hh"
|
||||
#include "Set.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "Network.hh"
|
||||
#include "LibertyClass.hh"
|
||||
|
|
@ -45,16 +46,14 @@ class ConcretePort;
|
|||
class ConcreteBindingTbl;
|
||||
class ConcreteLibertyLibraryIterator;
|
||||
|
||||
typedef Vector<ConcreteLibrary*> ConcreteLibrarySeq;
|
||||
typedef Map<const char*, ConcreteLibrary*, CharPtrLess> ConcreteLibraryMap;
|
||||
typedef ConcreteLibrarySeq::ConstIterator ConcreteLibraryIterator;
|
||||
typedef Map<const char *, ConcreteInstance*,
|
||||
CharPtrLess> ConcreteInstanceChildMap;
|
||||
typedef Map<const char *, ConcreteNet*, CharPtrLess> ConcreteInstanceNetMap;
|
||||
typedef Vector<ConcreteNet*> ConcreteNetSeq;
|
||||
typedef Vector<ConcretePin*> ConcretePinSeq;
|
||||
typedef Map<Cell*, Instance*> CellNetworkViewMap;
|
||||
typedef Set<const ConcreteNet*> ConcreteNetSet;
|
||||
using ConcreteLibrarySeq = std::vector<ConcreteLibrary*>;
|
||||
using ConcreteLibraryMap = std::map<const char*, ConcreteLibrary*, CharPtrLess>;
|
||||
using ConcreteInstanceChildMap = std::map<const char *, ConcreteInstance*, CharPtrLess>;
|
||||
using ConcreteInstanceNetMap = std::map<const char *, ConcreteNet*, CharPtrLess>;
|
||||
using ConcreteNetSeq = std::vector<ConcreteNet*>;
|
||||
using ConcretePinSeq = std::vector<ConcretePin*>;
|
||||
using CellNetworkViewMap = std::map<Cell*, Instance*>;
|
||||
using ConcreteNetSet = std::set<const ConcreteNet*>;
|
||||
|
||||
// This adapter implements the network api for the concrete network.
|
||||
// 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
|
||||
|
||||
#include "UnorderedSet.hh"
|
||||
#include <unordered_set>
|
||||
|
||||
#include "MinMax.hh"
|
||||
#include "TimingRole.hh"
|
||||
#include "StaState.hh"
|
||||
|
|
@ -52,7 +53,9 @@ public:
|
|||
const CycleAccting *acct2) const;
|
||||
};
|
||||
|
||||
typedef UnorderedSet<CycleAccting*, CycleAcctingHash, CycleAcctingEqual> CycleAcctingSet;
|
||||
using CycleAcctingSet = std::unordered_set<CycleAccting*,
|
||||
CycleAcctingHash,
|
||||
CycleAcctingEqual>;
|
||||
|
||||
class CycleAcctings
|
||||
{
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public:
|
|||
void removeMargin(const RiseFallBoth *from_rf,
|
||||
const RiseFallBoth *to_rf,
|
||||
const SetupHoldAll *setup_hold);
|
||||
bool empty() const;
|
||||
[[nodiscard]] bool empty() const;
|
||||
void marginIsOneValue(const SetupHold *setup_hold,
|
||||
// Return values.
|
||||
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
|
||||
|
||||
#include <string>
|
||||
#include <cstdarg>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
#include "Map.hh"
|
||||
#include "StringUtil.hh"
|
||||
|
||||
namespace sta {
|
||||
|
|
@ -35,13 +36,12 @@ namespace sta {
|
|||
class Report;
|
||||
class Pin;
|
||||
|
||||
typedef Map<const char *, int, CharPtrLess> DebugMap;
|
||||
using DebugMap = std::map<std::string, int>;
|
||||
|
||||
class Debug
|
||||
{
|
||||
public:
|
||||
explicit Debug(Report *report);
|
||||
~Debug();
|
||||
Debug(Report *report);
|
||||
int level(const char *what);
|
||||
void setLevel(const char *what,
|
||||
int level);
|
||||
|
|
@ -57,18 +57,15 @@ protected:
|
|||
Report *report_;
|
||||
std::mutex buffer_lock_;
|
||||
bool debug_on_;
|
||||
DebugMap *debug_map_;
|
||||
DebugMap debug_map_;
|
||||
int stats_level_;
|
||||
};
|
||||
|
||||
// Inlining a varargs function would eval the args, which can
|
||||
// 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, ...) \
|
||||
if (debug->check(what, level)) { \
|
||||
debug->reportLine(what, ##__VA_ARGS__); \
|
||||
debug->reportLine(what __VA_OPT__(,) __VA_ARGS__); \
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -41,10 +41,10 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
typedef Delay ArcDelay;
|
||||
typedef Delay Slew;
|
||||
typedef Delay Arrival;
|
||||
typedef Delay Required;
|
||||
typedef Delay Slack;
|
||||
using ArcDelay = Delay;
|
||||
using Slew = Delay;
|
||||
using Arrival = Delay;
|
||||
using Required = Delay;
|
||||
using Slack = Delay;
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace sta {
|
|||
class ArcDelayCalc;
|
||||
class StaState;
|
||||
|
||||
typedef ArcDelayCalc *(*MakeArcDelayCalc)(StaState *sta);
|
||||
using MakeArcDelayCalc = ArcDelayCalc *(*)(StaState *sta);
|
||||
|
||||
// Register builtin delay calculators.
|
||||
void
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ namespace sta {
|
|||
|
||||
class StaState;
|
||||
|
||||
typedef float Delay;
|
||||
using Delay = float;
|
||||
// Delay double for accumulating Delays.
|
||||
typedef double DelayDbl;
|
||||
using DelayDbl = double;
|
||||
|
||||
const Delay delay_zero = 0.0;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Map.hh"
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "NetworkClass.hh"
|
||||
#include "LibertyClass.hh"
|
||||
#include "SdcClass.hh"
|
||||
|
|
@ -35,10 +37,10 @@ class TimingRole;
|
|||
class DisabledCellPorts;
|
||||
class DisabledInstancePorts;
|
||||
|
||||
typedef Vector<DisabledInstancePorts*> DisabledInstancePortsSeq;
|
||||
typedef Vector<DisabledCellPorts*> DisabledCellPortsSeq;
|
||||
typedef Vector<LibertyPortPair> LibertyPortPairSeq;
|
||||
typedef Set<TimingArcSet*> TimingArcSetSet;
|
||||
using DisabledInstancePortsSeq = std::vector<DisabledInstancePorts*>;
|
||||
using DisabledCellPortsSeq = std::vector<DisabledCellPorts*>;
|
||||
using LibertyPortPairSeq = std::vector<LibertyPortPair>;
|
||||
using TimingArcSetSet = std::set<TimingArcSet*, TimingArcSetLess>;
|
||||
|
||||
// Base class for disabled cell and instance ports.
|
||||
class DisabledPorts
|
||||
|
|
@ -56,13 +58,13 @@ public:
|
|||
LibertyPort *to);
|
||||
void removeDisabledFromTo(LibertyPort *from,
|
||||
LibertyPort *to);
|
||||
bool isDisabled(LibertyPort *from,
|
||||
[[nodiscard]] bool isDisabled(LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
const TimingRole *role);
|
||||
LibertyPortPairSet *fromTo() const { return from_to_; }
|
||||
LibertyPortSet *from() const { return from_; }
|
||||
LibertyPortSet *to() const { return to_; }
|
||||
bool all() const { return all_; }
|
||||
[[nodiscard]] bool all() const { return all_; }
|
||||
|
||||
private:
|
||||
bool all_;
|
||||
|
|
@ -80,7 +82,7 @@ public:
|
|||
LibertyCell *cell() const { return cell_; }
|
||||
void setDisabled(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_; }
|
||||
|
||||
using DisabledPorts::isDisabled;
|
||||
|
|
@ -102,7 +104,7 @@ private:
|
|||
};
|
||||
|
||||
DisabledCellPortsSeq
|
||||
sortByName(DisabledCellPortsMap *cell_map);
|
||||
sortByName(const DisabledCellPortsMap *cell_map);
|
||||
DisabledInstancePortsSeq
|
||||
sortByPathName(const DisabledInstancePortsMap *inst_map,
|
||||
const Network *network);
|
||||
|
|
|
|||
|
|
@ -24,15 +24,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Vector.hh"
|
||||
#include "Map.hh"
|
||||
#include "UnorderedMap.hh"
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "LibertyClass.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
typedef Map<LibertyCell*, LibertyCellSeq*> EquivCellMap;
|
||||
typedef UnorderedMap<unsigned, LibertyCellSeq*> LibertyCellHashMap;
|
||||
using EquivCellMap = std::map<LibertyCell*, LibertyCellSeq*>;
|
||||
using LibertyCellHashMap = std::unordered_map<unsigned, LibertyCellSeq*>;
|
||||
|
||||
class EquivCells
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ protected:
|
|||
class FileNotReadable : public Exception
|
||||
{
|
||||
public:
|
||||
explicit FileNotReadable(const char *filename);
|
||||
FileNotReadable(const char *filename);
|
||||
virtual const char *what() const noexcept;
|
||||
|
||||
protected:
|
||||
|
|
@ -78,7 +78,7 @@ protected:
|
|||
class FileNotWritable : public Exception
|
||||
{
|
||||
public:
|
||||
explicit FileNotWritable(const char *filename);
|
||||
FileNotWritable(const char *filename);
|
||||
virtual const char *what() const noexcept;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -24,8 +24,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Error.hh"
|
||||
#include "Set.hh"
|
||||
#include "SdcCmdComment.hh"
|
||||
#include "SdcClass.hh"
|
||||
|
||||
|
|
@ -44,7 +45,7 @@ class ExceptionThru;
|
|||
class ExceptionTo;
|
||||
class ExceptionState;
|
||||
|
||||
typedef Vector<ExceptionPath*> ExceptionPathSeq;
|
||||
using ExceptionPathSeq = std::vector<ExceptionPath*>;
|
||||
|
||||
class ExceptionPath : public SdcCmdComment
|
||||
{
|
||||
|
|
@ -593,14 +594,14 @@ exceptionThrusClone(ExceptionThruSeq *thrus,
|
|||
class ExceptionPtIterator
|
||||
{
|
||||
public:
|
||||
explicit ExceptionPtIterator(const ExceptionPath *exception);
|
||||
ExceptionPtIterator(const ExceptionPath *exception);
|
||||
bool hasNext();
|
||||
ExceptionPt *next();
|
||||
|
||||
private:
|
||||
const ExceptionPath *exception_;
|
||||
bool from_done_;
|
||||
ExceptionThruSeq::Iterator thru_iter_;
|
||||
ExceptionThruSeq::iterator thru_iter_;
|
||||
bool to_done_;
|
||||
};
|
||||
|
||||
|
|
@ -667,8 +668,8 @@ private:
|
|||
int index_;
|
||||
};
|
||||
|
||||
bool
|
||||
exceptionStateLess(const ExceptionState *state1,
|
||||
int
|
||||
exceptionStateCmp(const ExceptionState *state1,
|
||||
const ExceptionState *state2);
|
||||
|
||||
// Exception thrown by check.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "Set.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "LibertyClass.hh"
|
||||
|
||||
|
|
@ -35,16 +34,16 @@ namespace sta {
|
|||
class FuncExpr
|
||||
{
|
||||
public:
|
||||
enum Operator {op_port,
|
||||
op_not,
|
||||
op_or,
|
||||
op_and,
|
||||
op_xor,
|
||||
op_one,
|
||||
op_zero};
|
||||
enum class Op {port,
|
||||
not_,
|
||||
or_,
|
||||
and_,
|
||||
xor_,
|
||||
one,
|
||||
zero};
|
||||
|
||||
// Constructors.
|
||||
FuncExpr(Operator op,
|
||||
FuncExpr(Op op,
|
||||
FuncExpr *left,
|
||||
FuncExpr *right,
|
||||
LibertyPort *port);
|
||||
|
|
@ -67,14 +66,15 @@ public:
|
|||
FuncExpr *copy();
|
||||
// Delete expression and all of its subexpressions.
|
||||
void deleteSubexprs();
|
||||
// op == op_port
|
||||
// op == port
|
||||
LibertyPort *port() const;
|
||||
Operator op() const { return op_; }
|
||||
Op op() const { return op_; }
|
||||
// When operator is NOT left is the only operand.
|
||||
FuncExpr *left() const { return left_; }
|
||||
// nullptr when op == op_not
|
||||
// nullptr when op == not_
|
||||
FuncExpr *right() const { return right_; }
|
||||
TimingSense portTimingSense(const LibertyPort *port) const;
|
||||
LibertyPortSet ports() const;
|
||||
// Return true if expression has port as an input.
|
||||
bool hasPort(const LibertyPort *port) const;
|
||||
std::string to_string() const;
|
||||
|
|
@ -86,11 +86,14 @@ public:
|
|||
bool checkSize(LibertyPort *port);
|
||||
|
||||
private:
|
||||
void findPorts(const FuncExpr *expr,
|
||||
LibertyPortSet &ports) const;
|
||||
|
||||
std::string to_string(bool with_parens) const;
|
||||
std::string to_string(bool with_parens,
|
||||
char op) const;
|
||||
|
||||
Operator op_;
|
||||
Op op_;
|
||||
FuncExpr *left_;
|
||||
FuncExpr *right_;
|
||||
LibertyPort *port_;
|
||||
|
|
@ -100,18 +103,4 @@ private:
|
|||
FuncExpr *
|
||||
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
|
||||
|
|
|
|||
|
|
@ -26,10 +26,9 @@
|
|||
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
|
||||
#include "Iterator.hh"
|
||||
#include "Map.hh"
|
||||
#include "Vector.hh"
|
||||
#include "ObjectTable.hh"
|
||||
#include "LibertyClass.hh"
|
||||
#include "NetworkClass.hh"
|
||||
|
|
@ -44,12 +43,12 @@ namespace sta {
|
|||
class MinMax;
|
||||
class Sdc;
|
||||
|
||||
typedef ObjectTable<Vertex> VertexTable;
|
||||
typedef ObjectTable<Edge> EdgeTable;
|
||||
typedef Map<const Pin*, Vertex*> PinVertexMap;
|
||||
typedef Iterator<Edge*> VertexEdgeIterator;
|
||||
typedef Map<const Pin*, float*, PinIdLess> PeriodCheckAnnotations;
|
||||
typedef ObjectId EdgeId;
|
||||
using VertexTable = ObjectTable<Vertex>;
|
||||
using EdgeTable = ObjectTable<Edge>;
|
||||
using PinVertexMap = std::map<const Pin*, Vertex*>;
|
||||
using VertexEdgeIterator = Iterator<Edge*>;
|
||||
using PeriodCheckAnnotations = std::map<const Pin*, float*, PinIdLess>;
|
||||
using EdgeId = ObjectId;
|
||||
|
||||
static constexpr EdgeId edge_id_null = object_id_null;
|
||||
static constexpr ObjectIdx edge_idx_null = object_id_null;
|
||||
|
|
@ -94,10 +93,6 @@ public:
|
|||
void deleteVertex(Vertex *vertex);
|
||||
bool hasFaninOne(Vertex *vertex) const;
|
||||
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_slews = measured_slews / slew_derate_from_library
|
||||
|
|
@ -163,8 +158,6 @@ public:
|
|||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index,
|
||||
bool annotated);
|
||||
// True if any edge arc is annotated.
|
||||
bool delayAnnotated(Edge *edge);
|
||||
|
||||
void minPulseWidthArc(Vertex *vertex,
|
||||
const RiseFall *hi_low,
|
||||
|
|
@ -188,7 +181,8 @@ public:
|
|||
|
||||
// Remove all delay and slew annotations.
|
||||
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_max = (1<<vertex_level_bits)-1;
|
||||
|
|
@ -233,7 +227,7 @@ protected:
|
|||
// Sdf period check annotations.
|
||||
PeriodCheckAnnotations *period_check_annotations_;
|
||||
// Register/latch clock vertices to search from.
|
||||
VertexSet *reg_clk_vertices_;
|
||||
VertexSet reg_clk_vertices_;
|
||||
|
||||
friend class Vertex;
|
||||
friend class VertexIterator;
|
||||
|
|
@ -253,21 +247,23 @@ public:
|
|||
std::string to_string(const StaState *sta) const;
|
||||
// compatibility
|
||||
const char *name(const Network *network) const;
|
||||
bool isBidirectDriver() const { return is_bidirect_drvr_; }
|
||||
bool isDriver(const Network *network) const;
|
||||
[[nodiscard]] bool isBidirectDriver() const { return is_bidirect_drvr_; }
|
||||
[[nodiscard]] bool isDriver(const Network *network) const;
|
||||
Level level() const { return level_; }
|
||||
void setLevel(Level level);
|
||||
bool visited() const { return visited1_; }
|
||||
[[nodiscard]] bool visited() const { return visited1_; }
|
||||
void setVisited(bool visited);
|
||||
bool visited2() const { return visited2_; }
|
||||
[[nodiscard]] bool visited2() const { return visited2_; }
|
||||
void setVisited2(bool visited);
|
||||
bool isRoot() const{ return level_ == 0; }
|
||||
bool hasFanin() const;
|
||||
bool hasFanout() const;
|
||||
[[nodiscard]] bool isRoot() const{ return level_ == 0; }
|
||||
[[nodiscard]] bool hasFanin() const;
|
||||
[[nodiscard]] bool hasFanout() const;
|
||||
Slew *slews() { return slews_; }
|
||||
const Slew *slews() const { return slews_; }
|
||||
Path *paths() const { return paths_; }
|
||||
Path *makePaths(uint32_t count);
|
||||
void setPaths(Path *paths);
|
||||
void deletePaths();
|
||||
TagGroupIndex tagGroupIndex() const;
|
||||
void setTagGroupIndex(TagGroupIndex tag_index);
|
||||
// Slew is annotated by sdc set_annotated_transition cmd.
|
||||
|
|
@ -279,38 +275,24 @@ public:
|
|||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index);
|
||||
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.
|
||||
bool hasChecks() const { return has_checks_; }
|
||||
[[nodiscard]] bool hasChecks() const { return 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);
|
||||
bool isGatedClkEnable() const { return is_gated_clk_enable_; }
|
||||
void setIsGatedClkEnable(bool enable);
|
||||
bool hasDownstreamClkPin() const { return has_downstream_clk_pin_; }
|
||||
[[nodiscard]] bool hasDownstreamClkPin() const { return has_downstream_clk_pin_; }
|
||||
void setHasDownstreamClkPin(bool has_clk_pin);
|
||||
// Vertices are constrained if they have one or more of the
|
||||
// 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;
|
||||
[[nodiscard]] bool bfsInQueue(BfsIndex index) const;
|
||||
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.
|
||||
ObjectIdx objectIdx() const { return object_idx_; }
|
||||
[[nodiscard]] ObjectIdx objectIdx() const { return object_idx_; }
|
||||
void setObjectIdx(ObjectIdx idx);
|
||||
|
||||
static int transitionCount() { return 2; } // rise/fall
|
||||
|
||||
protected:
|
||||
void init(Pin *pin,
|
||||
bool is_bidirect_drvr,
|
||||
|
|
@ -336,23 +318,19 @@ protected:
|
|||
|
||||
int level_:Graph::vertex_level_bits; // 24
|
||||
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.
|
||||
// This flag distinguishes the driver and load vertices.
|
||||
bool is_bidirect_drvr_:1;
|
||||
|
||||
bool is_reg_clk_:1;
|
||||
bool is_disabled_constraint_:1;
|
||||
bool is_gated_clk_enable_:1;
|
||||
// Constrained by timing check edge.
|
||||
bool has_checks_:1;
|
||||
// Is the clock for a timing check.
|
||||
bool is_check_clk_:1;
|
||||
bool is_constrained_:1;
|
||||
bool has_downstream_clk_pin_:1;
|
||||
bool visited1_:1;
|
||||
bool visited2_:1;
|
||||
bool has_sim_value_;
|
||||
|
||||
private:
|
||||
friend class Graph;
|
||||
|
|
@ -382,18 +360,8 @@ public:
|
|||
void setArcDelays(ArcDelay *arc_delays);
|
||||
bool delay_Annotation_Is_Incremental() const {return delay_annotation_is_incremental_;};
|
||||
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.
|
||||
bool isDisabledLoop() const { return is_disabled_loop_; }
|
||||
[[nodiscard]] bool isDisabledLoop() const { return is_disabled_loop_; }
|
||||
void setIsDisabledLoop(bool disabled);
|
||||
// Edge is disabled to prevent converging clocks from merging (Xilinx).
|
||||
bool isBidirectInstPath() const { return is_bidirect_inst_path_; }
|
||||
|
|
@ -401,6 +369,10 @@ public:
|
|||
bool isBidirectNetPath() const { return is_bidirect_net_path_; }
|
||||
void setIsBidirectNetPath(bool is_bidir);
|
||||
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.
|
||||
ObjectIdx objectIdx() const { return object_idx_; }
|
||||
|
|
@ -435,11 +407,9 @@ protected:
|
|||
bool delay_annotation_is_incremental_:1;
|
||||
bool is_bidirect_inst_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 has_sim_sense_:1;
|
||||
bool has_disabled_cond_:1;
|
||||
unsigned object_idx_:VertexTable::idx_bits;
|
||||
|
||||
private:
|
||||
|
|
@ -456,7 +426,7 @@ private:
|
|||
class VertexIterator : public Iterator<Vertex*>
|
||||
{
|
||||
public:
|
||||
explicit VertexIterator(Graph *graph);
|
||||
VertexIterator(Graph *graph);
|
||||
virtual bool hasNext() { return vertex_ || bidir_vertex_; }
|
||||
virtual Vertex *next();
|
||||
|
||||
|
|
@ -508,29 +478,19 @@ public:
|
|||
EdgesThruHierPinIterator(const Pin *hpin,
|
||||
Network *network,
|
||||
Graph *graph);
|
||||
virtual bool hasNext() { return edge_iter_.hasNext(); }
|
||||
virtual Edge *next() { return edge_iter_.next(); }
|
||||
virtual bool hasNext();
|
||||
virtual Edge *next();
|
||||
|
||||
private:
|
||||
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:
|
||||
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);
|
||||
};
|
||||
return VertexSet(VertexIdLess(sta->graphRef()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include "ObjectId.hh"
|
||||
#include "Set.hh"
|
||||
#include "Vector.hh"
|
||||
#include "MinMax.hh"
|
||||
#include "Transition.hh"
|
||||
#include "Delay.hh"
|
||||
|
|
@ -42,19 +42,29 @@ class Edge;
|
|||
class VertexIterator;
|
||||
class VertexInEdgeIterator;
|
||||
class VertexOutEdgeIterator;
|
||||
class GraphLoop;
|
||||
class VertexSet;
|
||||
|
||||
typedef ObjectId VertexId;
|
||||
typedef ObjectId EdgeId;
|
||||
typedef Vector<Vertex*> VertexSeq;
|
||||
typedef Vector<Edge*> EdgeSeq;
|
||||
typedef Set<Edge*> EdgeSet;
|
||||
typedef int Level;
|
||||
typedef int DcalcAPIndex;
|
||||
typedef int TagGroupIndex;
|
||||
typedef Vector<GraphLoop*> GraphLoopSeq;
|
||||
typedef std::vector<Slew> SlewSeq;
|
||||
class VertexIdLess
|
||||
{
|
||||
public:
|
||||
VertexIdLess() = delete;
|
||||
VertexIdLess(Graph *&graph);
|
||||
bool operator()(const Vertex *vertex1,
|
||||
const Vertex *vertex2) const;
|
||||
|
||||
private:
|
||||
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();
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace sta {
|
|||
class VertexNameLess
|
||||
{
|
||||
public:
|
||||
explicit VertexNameLess(Network *network);
|
||||
VertexNameLess(Network *network);
|
||||
bool operator()(const Vertex *vertex1,
|
||||
const Vertex *vertex2);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,15 +24,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
#include "Map.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "GraphClass.hh"
|
||||
#include "SearchClass.hh"
|
||||
#include "DcalcAnalysisPt.hh"
|
||||
#include "SdcClass.hh"
|
||||
#include "StaState.hh"
|
||||
#include "ArcDelayCalc.hh"
|
||||
|
||||
|
|
@ -42,9 +42,10 @@ class DelayCalcObserver;
|
|||
class MultiDrvrNet;
|
||||
class FindVertexDelays;
|
||||
class NetCaps;
|
||||
class SearchPred;
|
||||
|
||||
typedef Map<const Vertex*, MultiDrvrNet*> MultiDrvrNetMap;
|
||||
typedef std::vector<SlewSeq> DrvrLoadSlews;
|
||||
using MultiDrvrNetMap = std::map<const Vertex*, MultiDrvrNet*>;
|
||||
using DrvrLoadSlews = std::vector<SlewSeq>;
|
||||
|
||||
// This class traverses the graph calling the arc delay calculator and
|
||||
// annotating delays on graph edges.
|
||||
|
|
@ -73,7 +74,7 @@ public:
|
|||
// Returned string is owned by the caller.
|
||||
virtual std::string reportDelayCalc(const Edge *edge,
|
||||
const TimingArc *arc,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
int digits);
|
||||
// Percentage (0.0:1.0) change in delay that causes downstream
|
||||
|
|
@ -82,19 +83,23 @@ public:
|
|||
virtual void setIncrementalDelayTolerance(float tol);
|
||||
|
||||
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,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) const;
|
||||
const Scene *scene,
|
||||
const MinMax *min_max) const;
|
||||
void loadCap(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap) const;
|
||||
void netCaps(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap,
|
||||
|
|
@ -102,7 +107,8 @@ public:
|
|||
bool &has_set_load) const;
|
||||
void parasiticLoad(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
const MultiDrvrNet *multi_drvr,
|
||||
ArcDelayCalc *arc_delay_calc,
|
||||
// Return values.
|
||||
|
|
@ -112,14 +118,15 @@ public:
|
|||
void findDriverArcDelays(Vertex *drvr_vertex,
|
||||
Edge *edge,
|
||||
const TimingArc *arc,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
ArcDelayCalc *arc_delay_calc);
|
||||
// Precedence:
|
||||
// SDF annotation
|
||||
// Liberty port timing group timing_type minimum_period.
|
||||
// Liberty port min_period attribute.
|
||||
void minPeriod(const Pin *pin,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
// Return values.
|
||||
float &min_period,
|
||||
bool &exists);
|
||||
|
|
@ -127,11 +134,13 @@ public:
|
|||
Slew edgeFromSlew(const Vertex *from_vertex,
|
||||
const RiseFall *from_rf,
|
||||
const Edge *edge,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
Slew edgeFromSlew(const Vertex *from_vertex,
|
||||
const RiseFall *from_rf,
|
||||
const TimingRole *role,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
bool bidirectDrvrSlewFromLoad(const Pin *pin) const;
|
||||
|
||||
protected:
|
||||
|
|
@ -145,13 +154,15 @@ protected:
|
|||
void seedNoDrvrSlew(Vertex *drvr_vertex,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
ArcDelayCalc *arc_delay_calc);
|
||||
void seedNoDrvrCellSlew(Vertex *drvr_vertex,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const InputDrive *drive,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
ArcDelayCalc *arc_delay_calc);
|
||||
void seedLoadSlew(Vertex *vertex);
|
||||
void setInputPortWireDelays(Vertex *vertex);
|
||||
|
|
@ -162,7 +173,8 @@ protected:
|
|||
const LibertyPort *from_port,
|
||||
float *from_slews,
|
||||
const LibertyPort *to_port,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
LibertyPort *driveCellDefaultFromPort(const LibertyCell *cell,
|
||||
const LibertyPort *to_port);
|
||||
int findPortIndex(const LibertyCell *cell,
|
||||
|
|
@ -171,7 +183,8 @@ protected:
|
|||
Vertex *drvr_vertex,
|
||||
const TimingArc *arc,
|
||||
float from_slew,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
void findDriverDelays(Vertex *drvr_vertex,
|
||||
ArcDelayCalc *arc_delay_calc,
|
||||
LoadPinIndexMap &load_pin_index_map);
|
||||
|
|
@ -196,14 +209,16 @@ protected:
|
|||
const MultiDrvrNet *multi_drvr,
|
||||
Edge *edge,
|
||||
const TimingArc *arc,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
ArcDelayCalc *arc_delay_calc,
|
||||
LoadPinIndexMap &load_pin_index_map);
|
||||
ArcDcalcArgSeq makeArcDcalcArgs(Vertex *drvr_vertex,
|
||||
const MultiDrvrNet *multi_drvr,
|
||||
Edge *edge,
|
||||
const TimingArc *arc,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
ArcDelayCalc *arc_delay_calc);
|
||||
void findParallelEdge(Vertex *vertex,
|
||||
const TimingArc *drvr_arc,
|
||||
|
|
@ -225,34 +240,40 @@ protected:
|
|||
const TimingArc *arc,
|
||||
ArcDcalcResult &dcalc_result,
|
||||
LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
|
||||
bool annotateDelaySlew(Edge *edge,
|
||||
const TimingArc *arc,
|
||||
ArcDelay &gate_delay,
|
||||
Slew &gate_slew,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
bool annotateLoadDelays(Vertex *drvr_vertex,
|
||||
const RiseFall *drvr_rf,
|
||||
ArcDcalcResult &dcalc_result,
|
||||
LoadPinIndexMap &load_pin_index_map,
|
||||
const ArcDelay &extra_delay,
|
||||
bool merge,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
void findLatchEdgeDelays(Edge *edge);
|
||||
void findCheckEdgeDelays(Edge *edge,
|
||||
ArcDelayCalc *arc_delay_calc);
|
||||
void deleteMultiDrvrNets();
|
||||
Slew checkEdgeClkSlew(const Vertex *from_vertex,
|
||||
const RiseFall *from_rf,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
float loadCap(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
ArcDelayCalc *arc_delay_calc) const;
|
||||
void parasiticLoad(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
const MultiDrvrNet *multi_drvr,
|
||||
ArcDelayCalc *arc_delay_calc,
|
||||
// Return values.
|
||||
|
|
@ -261,7 +282,8 @@ protected:
|
|||
const Parasitic *¶sitic) const;
|
||||
void netCaps(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
const MultiDrvrNet *multi_drvr,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
|
|
@ -275,7 +297,7 @@ protected:
|
|||
bool incremental_;
|
||||
bool delays_exist_;
|
||||
// Vertices with invalid -to delays.
|
||||
VertexSet *invalid_delays_;
|
||||
VertexSet invalid_delays_;
|
||||
// Timing check edges with invalid delays.
|
||||
EdgeSet invalid_check_edges_;
|
||||
// Latch D->Q edges with invalid delays.
|
||||
|
|
@ -284,7 +306,6 @@ protected:
|
|||
std::mutex invalid_edge_lock_;
|
||||
SearchPred *search_pred_;
|
||||
SearchPred *search_non_latch_pred_;
|
||||
SearchPred *clk_pred_;
|
||||
BfsFwdIterator *iter_;
|
||||
MultiDrvrNetMap multi_drvr_net_map_;
|
||||
std::mutex multi_drvr_lock_;
|
||||
|
|
@ -319,13 +340,14 @@ public:
|
|||
Vertex *dcalcDrvr() const { return dcalc_drvr_; }
|
||||
void setDcalcDrvr(Vertex *drvr);
|
||||
void netCaps(const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap,
|
||||
float &fanout,
|
||||
bool &has_net_load) const;
|
||||
void findCaps(const Sdc *sdc);
|
||||
void findCaps(const StaState *sta);
|
||||
|
||||
private:
|
||||
// Driver that triggers delay calculation for all the drivers on the net.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Set.hh"
|
||||
#include "NetworkClass.hh"
|
||||
|
||||
namespace sta {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class InputDriveCell;
|
|||
class InputDrive
|
||||
{
|
||||
public:
|
||||
explicit InputDrive();
|
||||
InputDrive();
|
||||
~InputDrive();
|
||||
void setSlew(const RiseFallBoth *rf,
|
||||
const MinMaxAll *min_max,
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ protected:
|
|||
class InternalPowerModel
|
||||
{
|
||||
public:
|
||||
explicit InternalPowerModel(TableModel *model);
|
||||
InternalPowerModel(TableModel *model);
|
||||
~InternalPowerModel();
|
||||
float power(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
|
|
|
|||
|
|
@ -40,4 +40,80 @@ public:
|
|||
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
|
||||
|
|
|
|||
|
|
@ -27,7 +27,11 @@
|
|||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "ContainerHelpers.hh"
|
||||
#include "MinMax.hh"
|
||||
#include "RiseFallMinMax.hh"
|
||||
#include "ConcreteLibrary.hh"
|
||||
|
|
@ -56,40 +60,37 @@ class OcvDerate;
|
|||
class TimingArcAttrs;
|
||||
class InternalPowerAttrs;
|
||||
class StaState;
|
||||
class Corner;
|
||||
class Corners;
|
||||
class DcalcAnalysisPt;
|
||||
class Scene;
|
||||
class DriverWaveform;
|
||||
|
||||
typedef Map<const char*, TableTemplate*, CharPtrLess> TableTemplateMap;
|
||||
typedef Vector<TableTemplate*> TableTemplateSeq;
|
||||
typedef Map<const char*, BusDcl *, CharPtrLess> BusDclMap;
|
||||
typedef Vector<BusDcl *> BusDclSeq;
|
||||
typedef Map<const char*, ScaleFactors*, CharPtrLess> ScaleFactorsMap;
|
||||
typedef Map<const char*, Wireload*, CharPtrLess> WireloadMap;
|
||||
typedef Map<const char*, WireloadSelection*, CharPtrLess> WireloadSelectionMap;
|
||||
typedef Map<const char*, OperatingConditions*,
|
||||
CharPtrLess> OperatingConditionsMap;
|
||||
typedef Map<LibertyPort*, Sequential*> PortToSequentialMap;
|
||||
typedef Vector<TimingArcSet*> TimingArcSetSeq;
|
||||
typedef Set<TimingArcSet*, TimingArcSetLess> TimingArcSetMap;
|
||||
typedef Map<LibertyPortPair, TimingArcSetSeq*,
|
||||
LibertyPortPairLess> LibertyPortPairTimingArcMap;
|
||||
typedef Vector<InternalPower*> InternalPowerSeq;
|
||||
typedef Map<const LibertyPort *, InternalPowerSeq> PortInternalPowerSeq;
|
||||
typedef Vector<LeakagePower*> LeakagePowerSeq;
|
||||
typedef Map<const LibertyPort*, TimingArcSetSeq*> LibertyPortTimingArcMap;
|
||||
typedef Map<const OperatingConditions*, LibertyCell*> ScaledCellMap;
|
||||
typedef Map<const OperatingConditions*, LibertyPort*> ScaledPortMap;
|
||||
typedef Map<const char *, ModeDef*, CharPtrLess> ModeDefMap;
|
||||
typedef Map<const char *, ModeValueDef*, CharPtrLess> ModeValueMap;
|
||||
typedef Map<const TimingArcSet*, LatchEnable*> LatchEnableMap;
|
||||
typedef Vector<LatchEnable*> LatchEnableSeq;
|
||||
typedef Map<const char *, OcvDerate*, CharPtrLess> OcvDerateMap;
|
||||
typedef Vector<InternalPowerAttrs*> InternalPowerAttrsSeq;
|
||||
typedef Map<std::string, float> SupplyVoltageMap;
|
||||
typedef Map<std::string, DriverWaveform*> DriverWaveformMap;
|
||||
typedef Vector<DcalcAnalysisPt*> DcalcAnalysisPtSeq;
|
||||
using TableTemplateMap = std::map<const char*, TableTemplate*, CharPtrLess>;
|
||||
using TableTemplateSeq = std::vector<TableTemplate*>;
|
||||
using BusDclMap = std::map<const char*, BusDcl *, CharPtrLess>;
|
||||
using BusDclSeq = std::vector<BusDcl *>;
|
||||
using ScaleFactorsMap = std::map<const char*, ScaleFactors*, CharPtrLess>;
|
||||
using WireloadMap = std::map<const char*, Wireload*, CharPtrLess>;
|
||||
using WireloadSelectionMap = std::map<const char*, WireloadSelection*, CharPtrLess>;
|
||||
using OperatingConditionsMap = std::map<const char*, OperatingConditions*, CharPtrLess>;
|
||||
using PortToSequentialMap = std::map<LibertyPort*, Sequential*>;
|
||||
using TimingArcSetSeq = std::vector<TimingArcSet*>;
|
||||
using TimingArcSetSet = std::set<TimingArcSet*, TimingArcSetLess>;
|
||||
using LibertyPortPairTimingArcMap = std::map<LibertyPortPair, TimingArcSetSeq*,
|
||||
LibertyPortPairLess>;
|
||||
using InternalPowerSeq = std::vector<InternalPower*>;
|
||||
using PortInternalPowerMap = std::map<const LibertyPort *, InternalPowerSeq>;
|
||||
using LeakagePowerSeq = std::vector<LeakagePower*>;
|
||||
using LibertyPortTimingArcMap = std::map<const LibertyPort*, TimingArcSetSeq*>;
|
||||
using ScaledCellMap = std::map<const OperatingConditions*, LibertyCell*>;
|
||||
using ScaledPortMap = std::map<const OperatingConditions*, LibertyPort*>;
|
||||
using ModeDefMap = std::map<const char *, ModeDef*, CharPtrLess>;
|
||||
using ModeValueMap = std::map<const char *, ModeValueDef*, CharPtrLess>;
|
||||
using LatchEnableMap = std::map<const TimingArcSet*, LatchEnable*>;
|
||||
using LatchEnableSeq = std::vector<LatchEnable*>;
|
||||
using OcvDerateMap = std::map<const char *, OcvDerate*, CharPtrLess>;
|
||||
using InternalPowerAttrsSeq = std::vector<InternalPowerAttrs*>;
|
||||
using SupplyVoltageMap = std::map<std::string, float>;
|
||||
using DriverWaveformMap = std::map<std::string, DriverWaveform*>;
|
||||
using SceneSeq = std::vector<Scene*>;
|
||||
|
||||
enum class ClockGateType { none, latch_posedge, latch_negedge, other };
|
||||
|
||||
|
|
@ -316,24 +317,24 @@ public:
|
|||
const char *filename);
|
||||
|
||||
static void
|
||||
makeCornerMap(LibertyLibrary *lib,
|
||||
makeSceneMap(LibertyLibrary *lib,
|
||||
int ap_index,
|
||||
Network *network,
|
||||
Report *report);
|
||||
static void
|
||||
makeCornerMap(LibertyCell *link_cell,
|
||||
makeSceneMap(LibertyCell *link_cell,
|
||||
LibertyCell *map_cell,
|
||||
int ap_index,
|
||||
Report *report);
|
||||
static void
|
||||
makeCornerMap(LibertyCell *cell1,
|
||||
makeSceneMap(LibertyCell *cell1,
|
||||
LibertyCell *cell2,
|
||||
bool link,
|
||||
int ap_index,
|
||||
Report *report);
|
||||
static void
|
||||
checkCorners(LibertyCell *cell,
|
||||
Corners *corners,
|
||||
checkScenes(LibertyCell *cell,
|
||||
const SceneSeq &scenes,
|
||||
Report *report);
|
||||
|
||||
DriverWaveform *findDriverWaveform(const char *name);
|
||||
|
|
@ -404,12 +405,12 @@ private:
|
|||
class LibertyCellIterator : public Iterator<LibertyCell*>
|
||||
{
|
||||
public:
|
||||
explicit LibertyCellIterator(const LibertyLibrary *library);
|
||||
LibertyCellIterator(const LibertyLibrary *library);
|
||||
bool hasNext();
|
||||
LibertyCell *next();
|
||||
|
||||
private:
|
||||
ConcreteCellMap::ConstIterator iter_;
|
||||
ConcreteLibraryCellIterator iter_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -497,11 +498,9 @@ public:
|
|||
const FuncExpr *&enable_func,
|
||||
const RiseFall *&enable_rf) const;
|
||||
const RiseFall *latchCheckEnableEdge(TimingArcSet *check_set);
|
||||
bool isDisabledConstraint() const { return is_disabled_constraint_; }
|
||||
LibertyCell *cornerCell(const Corner *corner,
|
||||
LibertyCell *sceneCell(const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
LibertyCell *cornerCell(const DcalcAnalysisPt *dcalc_ap);
|
||||
LibertyCell *cornerCell(int ap_index);
|
||||
LibertyCell *sceneCell(int ap_index);
|
||||
|
||||
// AOCV
|
||||
float ocvArcDepth() const;
|
||||
|
|
@ -536,8 +535,7 @@ public:
|
|||
void addOcvDerate(OcvDerate *derate);
|
||||
void setTestCell(TestCell *test);
|
||||
void setHasInferedRegTimingArcs(bool infered);
|
||||
void setIsDisabledConstraint(bool is_disabled);
|
||||
void setCornerCell(LibertyCell *corner_cell,
|
||||
void setSceneCell(LibertyCell *scene_cell,
|
||||
int ap_index);
|
||||
// Call after cell is finished being constructed.
|
||||
void finish(bool infer_latches,
|
||||
|
|
@ -550,9 +548,9 @@ public:
|
|||
LibertyPort *&input,
|
||||
LibertyPort *&output) const;
|
||||
// Check all liberty cells to make sure they exist
|
||||
// for all the defined corners.
|
||||
static void checkLibertyCorners();
|
||||
void ensureVoltageWaveforms(const DcalcAnalysisPtSeq &dcalc_aps);
|
||||
// for all the defined scenes.
|
||||
static void checkLibertyScenes();
|
||||
void ensureVoltageWaveforms(const SceneSeq &scenes);
|
||||
const char *footprint() const;
|
||||
void setFootprint(const char *footprint);
|
||||
const char *userFunctionClass() const;
|
||||
|
|
@ -594,7 +592,7 @@ protected:
|
|||
const LibertyPort *output) const;
|
||||
bool hasInverterFunc(const LibertyPort *input,
|
||||
const LibertyPort *output) const;
|
||||
bool checkCornerCell(const Corner *corner,
|
||||
bool checkSceneCell(const Scene *scene,
|
||||
const MinMax *min_max) const;
|
||||
|
||||
LibertyLibrary *liberty_library_;
|
||||
|
|
@ -612,13 +610,13 @@ protected:
|
|||
bool interface_timing_;
|
||||
ClockGateType clock_gate_type_;
|
||||
TimingArcSetSeq timing_arc_sets_;
|
||||
TimingArcSetMap timing_arc_set_map_;
|
||||
TimingArcSetSet timing_arc_set_set_;
|
||||
LibertyPortPairTimingArcMap port_timing_arc_set_map_;
|
||||
LibertyPortTimingArcMap timing_arc_set_from_map_;
|
||||
LibertyPortTimingArcMap timing_arc_set_to_map_;
|
||||
bool has_infered_reg_timing_arcs_;
|
||||
InternalPowerSeq internal_powers_;
|
||||
PortInternalPowerSeq port_internal_powers_;
|
||||
PortInternalPowerMap port_internal_powers_;
|
||||
InternalPowerAttrsSeq internal_power_attrs_;
|
||||
LeakagePowerSeq leakage_powers_;
|
||||
SequentialSeq sequentials_;
|
||||
|
|
@ -639,8 +637,7 @@ protected:
|
|||
float ocv_arc_depth_;
|
||||
OcvDerate *ocv_derate_;
|
||||
OcvDerateMap ocv_derate_map_;
|
||||
bool is_disabled_constraint_;
|
||||
Vector<LibertyCell*> corner_cells_;
|
||||
std::vector<LibertyCell*> scene_cells_;
|
||||
float leakage_power_;
|
||||
bool leakage_power_exists_;
|
||||
bool has_internal_ports_;
|
||||
|
|
@ -659,18 +656,18 @@ private:
|
|||
class LibertyCellPortIterator : public Iterator<LibertyPort*>
|
||||
{
|
||||
public:
|
||||
explicit LibertyCellPortIterator(const LibertyCell *cell);
|
||||
LibertyCellPortIterator(const LibertyCell *cell);
|
||||
bool hasNext();
|
||||
LibertyPort *next();
|
||||
|
||||
private:
|
||||
ConcretePortSeq::ConstIterator iter_;
|
||||
ConcreteCellPortIterator iter_;
|
||||
};
|
||||
|
||||
class LibertyCellPortBitIterator : public Iterator<LibertyPort*>
|
||||
{
|
||||
public:
|
||||
explicit LibertyCellPortBitIterator(const LibertyCell *cell);
|
||||
LibertyCellPortBitIterator(const LibertyCell *cell);
|
||||
virtual ~LibertyCellPortBitIterator();
|
||||
bool hasNext();
|
||||
LibertyPort *next();
|
||||
|
|
@ -814,17 +811,12 @@ public:
|
|||
const RiseFall *pulseClkSense() const { return pulse_clk_sense_; }
|
||||
void setPulseClk(const RiseFall *rfigger,
|
||||
const RiseFall *sense);
|
||||
bool isDisabledConstraint() const { return is_disabled_constraint_; }
|
||||
void setIsDisabledConstraint(bool is_disabled);
|
||||
LibertyPort *cornerPort(const Corner *corner,
|
||||
LibertyPort *scenePort(const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
const LibertyPort *cornerPort(const Corner *corner,
|
||||
const LibertyPort *scenePort(const Scene *scene,
|
||||
const MinMax *min_max) const;
|
||||
LibertyPort *cornerPort(const DcalcAnalysisPt *dcalc_ap);
|
||||
const LibertyPort *cornerPort(const DcalcAnalysisPt *dcalc_ap) const;
|
||||
LibertyPort *cornerPort(int ap_index);
|
||||
const LibertyPort *cornerPort(int ap_index) const;
|
||||
void setCornerPort(LibertyPort *corner_port,
|
||||
const LibertyPort *scenePort(int ap_index) const;
|
||||
void setScenePort(LibertyPort *scene_port,
|
||||
int ap_index);
|
||||
const char *relatedGroundPin() const;
|
||||
void setRelatedGroundPin(const char *related_ground_pin);
|
||||
|
|
@ -881,6 +873,7 @@ protected:
|
|||
float,
|
||||
const MinMax *)> &setter);
|
||||
|
||||
LibertyPort *scenePort(int ap_index);
|
||||
|
||||
LibertyCell *liberty_cell_;
|
||||
BusDcl *bus_dcl_;
|
||||
|
|
@ -902,7 +895,7 @@ protected:
|
|||
const RiseFall *pulse_clk_sense_;
|
||||
std::string related_ground_pin_;
|
||||
std::string related_power_pin_;
|
||||
Vector<LibertyPort*> corner_ports_;
|
||||
std::vector<LibertyPort*> scene_ports_;
|
||||
ReceiverModelPtr receiver_model_;
|
||||
DriverWaveform *driver_waveform_[RiseFall::index_count];
|
||||
// Redundant with clock_tree_path_delay timing arcs but faster to access.
|
||||
|
|
@ -923,7 +916,6 @@ protected:
|
|||
bool isolation_cell_enable_:1;
|
||||
bool level_shifter_data_:1;
|
||||
bool is_switch_:1;
|
||||
bool is_disabled_constraint_:1;
|
||||
bool is_pad_:1;
|
||||
|
||||
private:
|
||||
|
|
@ -939,7 +931,7 @@ sortByName(const LibertyPortSet *set);
|
|||
class LibertyPortMemberIterator : public Iterator<LibertyPort*>
|
||||
{
|
||||
public:
|
||||
explicit LibertyPortMemberIterator(const LibertyPort *port);
|
||||
LibertyPortMemberIterator(const LibertyPort *port);
|
||||
virtual ~LibertyPortMemberIterator();
|
||||
virtual bool hasNext();
|
||||
virtual LibertyPort *next();
|
||||
|
|
@ -990,7 +982,7 @@ protected:
|
|||
class ScaleFactors
|
||||
{
|
||||
public:
|
||||
explicit ScaleFactors(const char *name);
|
||||
ScaleFactors(const char *name);
|
||||
const char *name() const { return name_.c_str(); }
|
||||
float scale(ScaleFactorType type,
|
||||
ScaleFactorPvt pvt,
|
||||
|
|
|
|||
|
|
@ -25,10 +25,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Vector.hh"
|
||||
#include "Map.hh"
|
||||
#include "Set.hh"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -67,19 +66,19 @@ class ReceiverModel;
|
|||
class Statetable;
|
||||
class StatetableRow;
|
||||
|
||||
typedef Vector<LibertyLibrary*> LibertyLibrarySeq;
|
||||
typedef Vector<LibertyCell*> LibertyCellSeq;
|
||||
typedef Vector<Sequential*> SequentialSeq;
|
||||
typedef Map<LibertyCell*, LibertyCellSeq*> LibertyCellEquivMap;
|
||||
typedef Vector<LibertyPort*> LibertyPortSeq;
|
||||
typedef Set<LibertyPort*> LibertyPortSet;
|
||||
typedef std::pair<const LibertyPort*,const LibertyPort*> LibertyPortPair;
|
||||
typedef Set<LibertyCell*> LibertyCellSet;
|
||||
typedef std::shared_ptr<Table> TablePtr;
|
||||
typedef std::shared_ptr<TimingArcAttrs> TimingArcAttrsPtr;
|
||||
typedef std::shared_ptr<TableAxis> TableAxisPtr;
|
||||
typedef std::shared_ptr<ReceiverModel> ReceiverModelPtr;
|
||||
typedef std::vector<StatetableRow> StatetableRows;
|
||||
using LibertyLibrarySeq = std::vector<LibertyLibrary*>;
|
||||
using LibertyCellSeq = std::vector<LibertyCell*>;
|
||||
using SequentialSeq = std::vector<Sequential*>;
|
||||
using LibertyCellEquivMap = std::map<LibertyCell*, LibertyCellSeq*>;
|
||||
using LibertyPortSeq = std::vector<LibertyPort*>;
|
||||
using LibertyPortSet = std::set<LibertyPort*>;
|
||||
using LibertyPortPair = std::pair<const LibertyPort*,const LibertyPort*>;
|
||||
using LibertyCellSet = std::set<LibertyCell*>;
|
||||
using TablePtr = std::shared_ptr<Table>;
|
||||
using TimingArcAttrsPtr = std::shared_ptr<TimingArcAttrs>;
|
||||
using TableAxisPtr = std::shared_ptr<TableAxis>;
|
||||
using ReceiverModelPtr = std::shared_ptr<ReceiverModel>;
|
||||
using StatetableRows = std::vector<StatetableRow>;
|
||||
|
||||
enum class ScaleFactorType : unsigned {
|
||||
pin_cap,
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ protected:
|
|||
class CheckLinearModel : public CheckTimingModel
|
||||
{
|
||||
public:
|
||||
explicit CheckLinearModel(LibertyCell *cell,
|
||||
CheckLinearModel(LibertyCell *cell,
|
||||
float intrinsic);
|
||||
ArcDelay checkDelay(const Pvt *pvt,
|
||||
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;
|
||||
|
||||
// Use typedefs to make early/late functional equivalents to min/max.
|
||||
typedef MinMax EarlyLate;
|
||||
typedef MinMaxAll EarlyLateAll;
|
||||
using EarlyLate = MinMax;
|
||||
using EarlyLateAll = MinMaxAll;
|
||||
|
||||
// Large value used for min/max initial values.
|
||||
extern const float INF;
|
||||
|
|
@ -112,6 +112,7 @@ public:
|
|||
static const MinMaxAll *max() { return &max_; }
|
||||
static const MinMaxAll *late() { return &max_; }
|
||||
static const MinMaxAll *all() { return &all_; }
|
||||
static const MinMaxAll *minMax() { return &all_; }
|
||||
const std::string &to_string() const { return name_; }
|
||||
int index() const { return index_; }
|
||||
const MinMax *asMinMax() const;
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ private:
|
|||
bool exists_[MinMax::index_count];
|
||||
};
|
||||
|
||||
typedef MinMaxValues<float> MinMaxFloatValues;
|
||||
typedef MinMaxValues<int> MinMaxIntValues;
|
||||
using MinMaxFloatValues = MinMaxValues<float>;
|
||||
using MinMaxIntValues = MinMaxValues<int>;
|
||||
|
||||
} // 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 {
|
||||
|
||||
// Hide a bit of the std verbosity.
|
||||
typedef std::lock_guard<std::mutex> LockGuard;
|
||||
using LockGuard = std::lock_guard<std::mutex>;
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
#include "Map.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "LibertyClass.hh"
|
||||
#include "VertexId.hh"
|
||||
|
|
@ -39,12 +39,12 @@ class Report;
|
|||
class PatternMatch;
|
||||
class PinVisitor;
|
||||
|
||||
typedef Map<const char*, LibertyLibrary*, CharPtrLess> LibertyLibraryMap;
|
||||
using LibertyLibraryMap = std::map<const char*, LibertyLibrary*, CharPtrLess>;
|
||||
// Link network function returns top level instance.
|
||||
// Return nullptr if link fails.
|
||||
typedef std::function<Instance* (const char *top_cell_name,
|
||||
bool make_black_boxes)> LinkNetworkFunc;
|
||||
typedef Map<const Net*, PinSet*> NetDrvrPinsMap;
|
||||
using LinkNetworkFunc = std::function<Instance* (const char *top_cell_name,
|
||||
bool make_black_boxes)>;
|
||||
using NetDrvrPinsMap = std::map<const Net*, PinSet*>;
|
||||
|
||||
// The Network class defines the network API used by sta.
|
||||
// The interface to a network implementation is constructed by
|
||||
|
|
@ -132,10 +132,10 @@ public:
|
|||
virtual LibertyLibrary *defaultLibertyLibrary() const;
|
||||
void setDefaultLibertyLibrary(LibertyLibrary *library);
|
||||
// Check liberty cells used by the network to make sure they exist
|
||||
// for all the defined corners.
|
||||
void checkNetworkLibertyCorners();
|
||||
// Check liberty cells to make sure they exist for all the defined corners.
|
||||
void checkLibertyCorners();
|
||||
// for all the defined scenes.
|
||||
void checkNetworkLibertyScenes();
|
||||
// Check liberty cells to make sure they exist for all the defined scenes.
|
||||
void checkLibertyScenes();
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Cell functions.
|
||||
|
|
@ -303,8 +303,8 @@ public:
|
|||
virtual Term *term(const Pin *pin) const = 0;
|
||||
virtual PortDirection *direction(const Pin *pin) const = 0;
|
||||
virtual bool isLeaf(const Pin *pin) const;
|
||||
bool isHierarchical(const Pin *pin) const;
|
||||
bool isTopLevelPort(const Pin *pin) const;
|
||||
[[nodiscard]] bool isHierarchical(const Pin *pin) const;
|
||||
[[nodiscard]] bool isTopLevelPort(const Pin *pin) const;
|
||||
// Is pin inside the instance hier_pin is attached to?
|
||||
bool isInside(const Pin *pin,
|
||||
const Pin *hier_pin) const;
|
||||
|
|
@ -620,7 +620,7 @@ public:
|
|||
NetworkConstantPinIterator(const Network *network,
|
||||
NetSet &zero_nets,
|
||||
NetSet &one_nets);
|
||||
~NetworkConstantPinIterator();
|
||||
virtual ~NetworkConstantPinIterator() {}
|
||||
virtual bool hasNext();
|
||||
virtual void next(const Pin *&pin, LogicValue &value);
|
||||
|
||||
|
|
@ -631,7 +631,7 @@ private:
|
|||
const Network *network_;
|
||||
PinSet constant_pins_[2];
|
||||
LogicValue value_;
|
||||
PinSet::Iterator *pin_iter_;
|
||||
PinSet::iterator pin_iter_;
|
||||
};
|
||||
|
||||
// Abstract base class for visitDrvrLoadsThruHierPin visitor.
|
||||
|
|
|
|||
|
|
@ -26,10 +26,11 @@
|
|||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "Set.hh"
|
||||
#include "Vector.hh"
|
||||
#include "Iterator.hh"
|
||||
|
||||
namespace sta {
|
||||
|
|
@ -49,30 +50,31 @@ class ConstantPinIterator;
|
|||
class ViewType;
|
||||
class LibertyLibrary;
|
||||
|
||||
typedef Iterator<Library*> LibraryIterator;
|
||||
typedef Iterator<LibertyLibrary*> LibertyLibraryIterator;
|
||||
typedef Vector<Cell*> CellSeq;
|
||||
typedef Vector<const Port*> PortSeq;
|
||||
typedef Iterator<Port*> CellPortIterator;
|
||||
typedef Iterator<Port*> CellPortBitIterator;
|
||||
typedef Iterator<Port*> PortMemberIterator;
|
||||
using LibraryIterator = Iterator<Library*>;
|
||||
using LibertyLibraryIterator = Iterator<LibertyLibrary*>;
|
||||
using CellSeq = std::vector<Cell*>;
|
||||
using PortSeq = std::vector<const Port*>;
|
||||
using CellPortIterator = Iterator<Port*>;
|
||||
using CellPortBitIterator = Iterator<Port*>;
|
||||
using PortMemberIterator = Iterator<Port*>;
|
||||
|
||||
typedef Vector<const Pin*> PinSeq;
|
||||
typedef Vector<const Instance*> InstanceSeq;
|
||||
typedef Vector<const Net*> NetSeq;
|
||||
typedef std::vector<const Net*> ConstNetSeq;
|
||||
typedef Iterator<Instance*> InstanceChildIterator;
|
||||
typedef Iterator<Pin*> InstancePinIterator;
|
||||
typedef Iterator<Net*> InstanceNetIterator;
|
||||
typedef Iterator<Instance*> LeafInstanceIterator;
|
||||
typedef Iterator<Net*> NetIterator;
|
||||
typedef Iterator<const Pin*> NetPinIterator;
|
||||
typedef Iterator<Term*> NetTermIterator;
|
||||
typedef Iterator<const Pin*> ConnectedPinIterator;
|
||||
typedef ConnectedPinIterator NetConnectedPinIterator;
|
||||
typedef ConnectedPinIterator PinConnectedPinIterator;
|
||||
typedef uint32_t ObjectId;
|
||||
typedef std::map<std::string, std::string> AttributeMap;
|
||||
using PinSeq = std::vector<const Pin*>;
|
||||
using PinUnorderedSet = std::unordered_set<const Pin*>;
|
||||
using InstanceSeq = std::vector<const Instance*>;
|
||||
using NetSeq = std::vector<const Net*>;
|
||||
using ConstNetSeq = std::vector<const Net*>;
|
||||
using InstanceChildIterator = Iterator<Instance*>;
|
||||
using InstancePinIterator = Iterator<Pin*>;
|
||||
using InstanceNetIterator = Iterator<Net*>;
|
||||
using LeafInstanceIterator = Iterator<Instance*>;
|
||||
using NetIterator = Iterator<Net*>;
|
||||
using NetPinIterator = Iterator<const Pin*>;
|
||||
using NetTermIterator = Iterator<Term*>;
|
||||
using ConnectedPinIterator = Iterator<const Pin*>;
|
||||
using NetConnectedPinIterator = ConnectedPinIterator;
|
||||
using PinConnectedPinIterator = ConnectedPinIterator;
|
||||
using ObjectId = uint32_t;
|
||||
using AttributeMap = std::map<std::string, std::string>;
|
||||
|
||||
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:
|
||||
CellSet(const Network *network);
|
||||
};
|
||||
|
||||
class PortSet : public Set<const Port*, PortIdLess>
|
||||
class PortSet : public std::set<const Port*, PortIdLess>
|
||||
{
|
||||
public:
|
||||
PortSet(const Network *network);
|
||||
};
|
||||
|
||||
class InstanceSet : public Set<const Instance*, InstanceIdLess>
|
||||
class InstanceSet : public std::set<const Instance*, InstanceIdLess>
|
||||
{
|
||||
public:
|
||||
InstanceSet();
|
||||
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:
|
||||
PinSet();
|
||||
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:
|
||||
NetSet();
|
||||
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
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace sta {
|
|||
class PortNameLess
|
||||
{
|
||||
public:
|
||||
explicit PortNameLess(const Network *network);
|
||||
PortNameLess(const Network *network);
|
||||
bool operator()(const Port *port1,
|
||||
const Port *port2) const;
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ private:
|
|||
class PinPathNameLess
|
||||
{
|
||||
public:
|
||||
explicit PinPathNameLess(const Network *network);
|
||||
PinPathNameLess(const Network *network);
|
||||
bool operator()(const Pin *pin1,
|
||||
const Pin *pin2) const;
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ private:
|
|||
class InstancePathNameLess
|
||||
{
|
||||
public:
|
||||
explicit InstancePathNameLess(const Network *network);
|
||||
InstancePathNameLess(const Network *network);
|
||||
bool operator()(const Instance *inst1,
|
||||
const Instance *inst2) const;
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ private:
|
|||
class NetPathNameLess
|
||||
{
|
||||
public:
|
||||
explicit NetPathNameLess(const Network *network);
|
||||
NetPathNameLess(const Network *network);
|
||||
bool operator()(const Net *net1,
|
||||
const Net *net2) const;
|
||||
|
||||
|
|
@ -78,6 +78,9 @@ private:
|
|||
PinSeq
|
||||
sortByPathName(const PinSet *set,
|
||||
const Network *network);
|
||||
PinSeq
|
||||
sortByPathName(const PinUnorderedSet *set,
|
||||
const Network *network);
|
||||
PortSeq
|
||||
sortByName(const PortSet *set,
|
||||
const Network *network);
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@
|
|||
namespace sta {
|
||||
|
||||
// ObjectId is block index and object index within the block.
|
||||
typedef uint32_t ObjectId;
|
||||
using ObjectId = uint32_t;
|
||||
// Block index.
|
||||
typedef uint32_t BlockIdx;
|
||||
using BlockIdx = uint32_t;
|
||||
// Object index within a block.
|
||||
typedef uint32_t ObjectIdx;
|
||||
using ObjectIdx = uint32_t;
|
||||
|
||||
static constexpr int object_id_bits = sizeof(ObjectId) * 8;
|
||||
static constexpr BlockIdx block_idx_null = 0;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Vector.hh"
|
||||
#include <vector>
|
||||
|
||||
#include "ContainerHelpers.hh"
|
||||
#include "Error.hh"
|
||||
#include "ObjectId.hh"
|
||||
|
||||
|
|
@ -71,7 +73,7 @@ private:
|
|||
size_t size_;
|
||||
// Object ID of next free object.
|
||||
ObjectId free_;
|
||||
Vector<TableBlock<TYPE>*> blocks_;
|
||||
std::vector<TableBlock<TYPE>*> blocks_;
|
||||
static constexpr ObjectId idx_mask_ = block_object_count - 1;
|
||||
};
|
||||
|
||||
|
|
@ -85,7 +87,7 @@ ObjectTable<TYPE>::ObjectTable() :
|
|||
template <class TYPE>
|
||||
ObjectTable<TYPE>::~ObjectTable()
|
||||
{
|
||||
blocks_.deleteContents();
|
||||
deleteContents(blocks_);
|
||||
}
|
||||
|
||||
template <class TYPE>
|
||||
|
|
@ -181,7 +183,7 @@ template <class TYPE>
|
|||
void
|
||||
ObjectTable<TYPE>::clear()
|
||||
{
|
||||
blocks_.deleteContentsClear();
|
||||
deleteContents(blocks_);;
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,40 +37,36 @@
|
|||
namespace sta {
|
||||
|
||||
class Wireload;
|
||||
class Corner;
|
||||
class Scene;
|
||||
|
||||
typedef std::complex<float> ComplexFloat;
|
||||
typedef Vector<ComplexFloat> ComplexFloatSeq;
|
||||
typedef std::vector<ParasiticNode*> ParasiticNodeSeq;
|
||||
typedef std::vector<ParasiticResistor*> ParasiticResistorSeq;
|
||||
typedef std::vector<ParasiticCapacitor*> ParasiticCapacitorSeq;
|
||||
typedef std::map<ParasiticNode *, ParasiticResistorSeq> ParasiticNodeResistorMap;
|
||||
typedef std::map<ParasiticNode *, ParasiticCapacitorSeq> ParasiticNodeCapacitorMap;
|
||||
using ComplexFloat = std::complex<float>;
|
||||
using ComplexFloatSeq = std::vector<ComplexFloat>;
|
||||
using ParasiticNodeSeq = std::vector<ParasiticNode*>;
|
||||
using ParasiticResistorSeq = std::vector<ParasiticResistor*>;
|
||||
using ParasiticCapacitorSeq = std::vector<ParasiticCapacitor*>;
|
||||
using ParasiticNodeResistorMap = std::map<ParasiticNode *, ParasiticResistorSeq>;
|
||||
using ParasiticNodeCapacitorMap = std::map<ParasiticNode *, ParasiticCapacitorSeq>;
|
||||
|
||||
// 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
|
||||
{
|
||||
public:
|
||||
Parasitics(StaState *sta);
|
||||
virtual ~Parasitics() {}
|
||||
virtual const std::string &name() const = 0;
|
||||
virtual const std::string &filename() const = 0;
|
||||
virtual bool haveParasitics() = 0;
|
||||
|
||||
// Clear all state.
|
||||
virtual void clear() = 0;
|
||||
|
||||
// Delete all parasitics.
|
||||
virtual void deleteParasitics() = 0;
|
||||
// Delete all parasitics on net at analysis point.
|
||||
virtual void deleteParasitics(const Net *net,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
virtual void deleteParasitics(const Net *net) = 0;
|
||||
// Delete all parasitics on pin at analysis point.
|
||||
virtual void deleteParasitics(const Pin *pin,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
virtual void deleteReducedParasitics(const Net *net,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
virtual void deleteParasitics(const Pin *pin) = 0;
|
||||
virtual void deleteReducedParasitics(const Net *net) = 0;
|
||||
virtual void deleteDrvrReducedParasitics(const Pin *drvr_pin) = 0;
|
||||
|
||||
virtual bool isReducedParasiticNetwork(const Parasitic *parasitic) const = 0;
|
||||
|
|
@ -88,10 +84,10 @@ public:
|
|||
virtual bool isPiElmore(const Parasitic *parasitic) const = 0;
|
||||
virtual Parasitic *findPiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap) const = 0;
|
||||
const MinMax *min_max) const = 0;
|
||||
virtual Parasitic *makePiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
const MinMax *min_max,
|
||||
float c2,
|
||||
float rpi,
|
||||
float c1) = 0;
|
||||
|
|
@ -126,10 +122,10 @@ public:
|
|||
virtual bool isPiPoleResidue(const Parasitic* parasitic) const = 0;
|
||||
virtual Parasitic *findPiPoleResidue(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap) const=0;
|
||||
const MinMax *min_max) const = 0;
|
||||
virtual Parasitic *makePiPoleResidue(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
const MinMax *min_max,
|
||||
float c2,
|
||||
float rpi,
|
||||
float c1) = 0;
|
||||
|
|
@ -154,22 +150,16 @@ public:
|
|||
// This api assumes that parasitic networks are not rise/fall
|
||||
// dependent because they do not include pin capacitances.
|
||||
virtual bool isParasiticNetwork(const Parasitic *parasitic) const = 0;
|
||||
virtual Parasitic *findParasiticNetwork(const Net *net,
|
||||
const ParasiticAnalysisPt *ap) const = 0;
|
||||
virtual Parasitic *findParasiticNetwork(const Pin *pin,
|
||||
const ParasiticAnalysisPt *ap) const = 0;
|
||||
virtual Parasitic *findParasiticNetwork(const Net *net) = 0;
|
||||
virtual Parasitic *findParasiticNetwork(const Pin *pin) = 0;
|
||||
virtual Parasitic *makeParasiticNetwork(const Net *net,
|
||||
bool includes_pin_caps,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
bool includes_pin_caps) = 0;
|
||||
virtual ParasiticNodeSeq nodes(const Parasitic *parasitic) const = 0;
|
||||
virtual void report(const Parasitic *parasitic) const;
|
||||
virtual const Net *net(const Parasitic *parasitic) const = 0;
|
||||
virtual ParasiticResistorSeq resistors(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,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
virtual void deleteParasiticNetworks(const Net *net) = 0;
|
||||
virtual void deleteParasiticNetwork(const Net *net) = 0;
|
||||
// True if the parasitic network caps include pin capacitances.
|
||||
virtual bool includesPinCaps(const Parasitic *parasitic) const = 0;
|
||||
// Parasitic network component builders.
|
||||
|
|
@ -248,17 +238,15 @@ public:
|
|||
Parasitic *reduceToPiElmore(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
// Reduce parasitic network to pi and 2nd order pole/residue models
|
||||
// for drvr_pin.
|
||||
Parasitic *reduceToPiPoleResidue2(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
|
||||
// Estimate parasitic as pi elmore using wireload model.
|
||||
Parasitic *estimatePiElmore(const Pin *drvr_pin,
|
||||
|
|
@ -266,18 +254,19 @@ public:
|
|||
const Wireload *wireload,
|
||||
float fanout,
|
||||
float net_pin_cap,
|
||||
const Corner *corner,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
Parasitic *makeWireloadNetwork(const Pin *drvr_pin,
|
||||
const Wireload *wireload,
|
||||
float fanout,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
const Scene *scene,
|
||||
const MinMax *min_max);
|
||||
// Network edit before/after methods.
|
||||
virtual void disconnectPinBefore(const Pin *pin,
|
||||
const Network *network) = 0;
|
||||
virtual void disconnectPinBefore(const Pin *pin) = 0;
|
||||
virtual void deletePinBefore(const Pin *pin) = 0;
|
||||
virtual void loadPinCapacitanceChanged(const Pin *pin) = 0;
|
||||
float couplingCapFactor() const { return coupling_cap_factor_; }
|
||||
void setCouplingCapFactor(float factor);
|
||||
|
||||
protected:
|
||||
void makeWireloadNetworkWorst(Parasitic *parasitic,
|
||||
|
|
@ -298,35 +287,16 @@ protected:
|
|||
float fanout);
|
||||
|
||||
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_;
|
||||
};
|
||||
|
||||
class ParasiticNodeLess
|
||||
{
|
||||
public:
|
||||
ParasiticNodeLess();
|
||||
ParasiticNodeLess(const Parasitics *parasitics,
|
||||
const Network *network);
|
||||
ParasiticNodeLess(const ParasiticNodeLess &less);
|
||||
bool operator()(const ParasiticNode *node1,
|
||||
const ParasiticNode *node2) const;
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ namespace sta {
|
|||
class Parasitics;
|
||||
class Parasitic;
|
||||
class ParasiticNode;
|
||||
class ParasiticAnalysisPt;
|
||||
class ParasiticResistor;
|
||||
class ParasiticCapacitor;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
class DcalcAnalysisPt;
|
||||
|
||||
class Path
|
||||
{
|
||||
public:
|
||||
|
|
@ -60,7 +58,6 @@ public:
|
|||
TimingArc *prev_arc,
|
||||
bool is_enum,
|
||||
const StaState *sta);
|
||||
~Path();
|
||||
std::string to_string(const StaState *sta) const;
|
||||
bool isNull() const;
|
||||
// prev_path null
|
||||
|
|
@ -86,6 +83,9 @@ public:
|
|||
VertexId vertexId(const StaState *sta) const;
|
||||
Pin *pin(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;
|
||||
void setTag(Tag *tag);
|
||||
size_t pathIndex(const StaState *sta) const;
|
||||
|
|
@ -96,9 +96,8 @@ public:
|
|||
const RiseFall *transition(const StaState *sta) const;
|
||||
int rfIndex(const StaState *sta) const;
|
||||
const MinMax *minMax(const StaState *sta) const;
|
||||
PathAnalysisPt *pathAnalysisPt(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_; }
|
||||
const Arrival &arrival() const { return arrival_; }
|
||||
void setArrival(Arrival arrival);
|
||||
|
|
@ -121,6 +120,8 @@ public:
|
|||
void setIsEnum(bool is_enum);
|
||||
void checkPrevPath(const StaState *sta) const;
|
||||
|
||||
const MinMax *tgtClkMinMax(const StaState *sta) const;
|
||||
|
||||
static Path *vertexPath(const Path *path,
|
||||
const StaState *sta);
|
||||
static Path *vertexPath(const Path &path,
|
||||
|
|
@ -176,7 +177,7 @@ protected:
|
|||
class PathLess
|
||||
{
|
||||
public:
|
||||
explicit PathLess(const StaState *sta);
|
||||
PathLess(const StaState *sta);
|
||||
bool operator()(const Path *path1,
|
||||
const Path *path2) const;
|
||||
|
||||
|
|
@ -191,11 +192,10 @@ public:
|
|||
// Iterate over all vertex paths.
|
||||
VertexPathIterator(Vertex *vertex,
|
||||
const StaState *sta);
|
||||
// Iterate over vertex paths with the same transition and
|
||||
// analysis pt but different tags.
|
||||
VertexPathIterator(Vertex *vertex,
|
||||
const Scene *scene,
|
||||
const MinMax *min_max,
|
||||
const RiseFall *rf,
|
||||
const PathAnalysisPt *path_ap,
|
||||
const StaState *sta);
|
||||
// Iterate over vertex paths with the same transition and
|
||||
// analysis pt min/max but different tags.
|
||||
|
|
@ -203,11 +203,6 @@ public:
|
|||
const RiseFall *rf,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta);
|
||||
VertexPathIterator(Vertex *vertex,
|
||||
const RiseFall *rf,
|
||||
const PathAnalysisPt *path_ap,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta);
|
||||
virtual ~VertexPathIterator();
|
||||
virtual bool hasNext();
|
||||
virtual Path *next();
|
||||
|
|
@ -216,10 +211,10 @@ private:
|
|||
void findNext();
|
||||
|
||||
const Search *search_;
|
||||
bool filtered_;
|
||||
const RiseFall *rf_;
|
||||
const PathAnalysisPt *path_ap_;
|
||||
const Scene *scene_;
|
||||
const MinMax *min_max_;
|
||||
const RiseFall *rf_;
|
||||
bool filtered_;
|
||||
Path *paths_;
|
||||
size_t path_count_;
|
||||
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
|
||||
{
|
||||
public:
|
||||
enum Type { unconstrained,
|
||||
enum class Type { unconstrained,
|
||||
check,
|
||||
data_check,
|
||||
latch_check,
|
||||
|
|
@ -80,8 +80,6 @@ public:
|
|||
const EarlyLate *pathEarlyLate(const StaState *sta) const;
|
||||
virtual const EarlyLate *clkEarlyLate(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 reportFull(const ReportPath *report) const = 0;
|
||||
PathGroup *pathGroup() const { return path_group_; }
|
||||
|
|
@ -89,13 +87,13 @@ public:
|
|||
|
||||
// Predicates for PathEnd type.
|
||||
// Default methods overridden by respective types.
|
||||
virtual bool isUnconstrained() const { return false; }
|
||||
virtual bool isCheck() const { return false; }
|
||||
virtual bool isDataCheck() const { return false; }
|
||||
virtual bool isLatchCheck() const { return false; }
|
||||
virtual bool isOutputDelay() const { return false; }
|
||||
virtual bool isGatedClock() const { return false; }
|
||||
virtual bool isPathDelay() const { return false; }
|
||||
[[nodiscard]] virtual bool isUnconstrained() const { return false; }
|
||||
[[nodiscard]] virtual bool isCheck() const { return false; }
|
||||
[[nodiscard]] virtual bool isDataCheck() const { return false; }
|
||||
[[nodiscard]] virtual bool isLatchCheck() const { return false; }
|
||||
[[nodiscard]] virtual bool isOutputDelay() const { return false; }
|
||||
[[nodiscard]] virtual bool isGatedClock() const { return false; }
|
||||
[[nodiscard]] virtual bool isPathDelay() const { return false; }
|
||||
virtual Type type() const = 0;
|
||||
virtual const char *typeName() const = 0;
|
||||
virtual int exceptPathCmp(const PathEnd *path_end,
|
||||
|
|
@ -187,7 +185,7 @@ public:
|
|||
const ClockEdge *tgt_clk_edge,
|
||||
const Path *tgt_clk_path,
|
||||
const TimingRole *check_role,
|
||||
const StaState *sta);
|
||||
const Sdc *sdc);
|
||||
// Non inter-clock uncertainty.
|
||||
static float checkTgtClkUncertainty(const Path *tgt_clk_path,
|
||||
const ClockEdge *tgt_clk_edge,
|
||||
|
|
@ -204,7 +202,7 @@ protected:
|
|||
static void checkInterClkUncertainty(const ClockEdge *src_clk_edge,
|
||||
const ClockEdge *tgt_clk_edge,
|
||||
const TimingRole *check_role,
|
||||
const StaState *sta,
|
||||
const Sdc *sdc,
|
||||
float &uncertainty,
|
||||
bool &exists);
|
||||
static float outputDelayMargin(OutputDelay *output_delay,
|
||||
|
|
@ -224,7 +222,7 @@ protected:
|
|||
class PathEndUnconstrained : public PathEnd
|
||||
{
|
||||
public:
|
||||
explicit PathEndUnconstrained(Path *path);
|
||||
PathEndUnconstrained(Path *path);
|
||||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual PathEnd *copy() const;
|
||||
|
|
@ -582,7 +580,7 @@ public:
|
|||
virtual Required requiredTime(const StaState *sta) const;
|
||||
virtual int exceptPathCmp(const PathEnd *path_end,
|
||||
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;
|
||||
|
||||
protected:
|
||||
|
|
@ -613,7 +611,7 @@ protected:
|
|||
class PathEndLess
|
||||
{
|
||||
public:
|
||||
explicit PathEndLess(const StaState *sta);
|
||||
PathEndLess(const StaState *sta);
|
||||
bool operator()(const PathEnd *path_end1,
|
||||
const PathEnd *path_end2) const;
|
||||
|
||||
|
|
@ -625,7 +623,7 @@ protected:
|
|||
class PathEndSlackLess
|
||||
{
|
||||
public:
|
||||
explicit PathEndSlackLess(const StaState *sta);
|
||||
PathEndSlackLess(const StaState *sta);
|
||||
bool operator()(const PathEnd *path_end1,
|
||||
const PathEnd *path_end2) const;
|
||||
|
||||
|
|
@ -636,7 +634,7 @@ protected:
|
|||
class PathEndNoCrprLess
|
||||
{
|
||||
public:
|
||||
explicit PathEndNoCrprLess(const StaState *sta);
|
||||
PathEndNoCrprLess(const StaState *sta);
|
||||
bool operator()(const PathEnd *path_end1,
|
||||
const PathEnd *path_end2) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,10 +24,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
#include "Map.hh"
|
||||
#include "Vector.hh"
|
||||
#include "SdcClass.hh"
|
||||
#include "StaState.hh"
|
||||
#include "SearchClass.hh"
|
||||
|
|
@ -37,11 +38,11 @@ namespace sta {
|
|||
class MinMax;
|
||||
class PathEndVisitor;
|
||||
|
||||
typedef PathEndSeq::Iterator PathGroupIterator;
|
||||
typedef Map<const Clock*, PathGroup*> PathGroupClkMap;
|
||||
typedef Map<const char*, PathGroup*, CharPtrLess> PathGroupNamedMap;
|
||||
typedef std::vector<PathGroup*> PathGroupSeq;
|
||||
typedef std::vector<std::string> StdStringSeq;
|
||||
using PathGroupIterator = PathEndSeq::iterator;
|
||||
using PathGroupClkMap = std::map<const Clock*, PathGroup*>;
|
||||
using PathGroupNamedMap = std::map<const char*, PathGroup*, CharPtrLess>;
|
||||
using PathGroupSeq = std::vector<PathGroup*>;
|
||||
using StdStringSeq = std::vector<std::string>;
|
||||
|
||||
// A collection of PathEnds grouped and sorted for reporting.
|
||||
class PathGroup
|
||||
|
|
@ -65,7 +66,7 @@ public:
|
|||
float min_slack,
|
||||
float max_slack,
|
||||
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 PathEndSeq &pathEnds() const { return path_ends_; }
|
||||
void insert(PathEnd *path_end);
|
||||
|
|
@ -75,7 +76,7 @@ public:
|
|||
bool saveable(PathEnd *path_end);
|
||||
bool enumMinSlackUnderMin(PathEnd *path_end);
|
||||
int maxPaths() const { return group_path_count_; }
|
||||
PathGroupIterator *iterator();
|
||||
PathEndSeq &pathEnds() { return path_ends_; }
|
||||
// This does NOT delete the path ends.
|
||||
void clear();
|
||||
static size_t group_path_count_max;
|
||||
|
|
@ -95,7 +96,7 @@ protected:
|
|||
void prune();
|
||||
void sort();
|
||||
|
||||
const char *name_;
|
||||
std::string name_;
|
||||
size_t group_path_count_;
|
||||
size_t endpoint_path_count_;
|
||||
bool unique_pins_;
|
||||
|
|
@ -119,7 +120,7 @@ public:
|
|||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
PathGroupNameSet *group_names,
|
||||
StdStringSeq &group_names,
|
||||
bool setup,
|
||||
bool hold,
|
||||
bool recovery,
|
||||
|
|
@ -127,15 +128,17 @@ public:
|
|||
bool clk_gating_setup,
|
||||
bool clk_gating_hold,
|
||||
bool unconstrained,
|
||||
const StaState *sta);
|
||||
const Mode *mode);
|
||||
~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.
|
||||
PathEndSeq makePathEnds(ExceptionTo *to,
|
||||
bool unconstrained_paths,
|
||||
const Corner *corner,
|
||||
void makePathEnds(ExceptionTo *to,
|
||||
const SceneSeq &scenes,
|
||||
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,
|
||||
const MinMax *min_max) const;
|
||||
PathGroup *findPathGroup(const Clock *clock,
|
||||
|
|
@ -154,14 +157,14 @@ protected:
|
|||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
const Corner *corner,
|
||||
const SceneSeq &scenes,
|
||||
const MinMaxAll *min_max);
|
||||
void makeGroupPathEnds(ExceptionTo *to,
|
||||
const Corner *corner,
|
||||
const SceneSeq &scenes,
|
||||
const MinMaxAll *min_max,
|
||||
PathEndVisitor *visitor);
|
||||
void makeGroupPathEnds(VertexSet *endpoints,
|
||||
const Corner *corner,
|
||||
void makeGroupPathEnds(VertexSet &endpoints,
|
||||
const SceneSeq &scenes,
|
||||
const MinMaxAll *min_max,
|
||||
PathEndVisitor *visitor);
|
||||
void enumPathEnds(PathGroup *group,
|
||||
|
|
@ -171,7 +174,7 @@ protected:
|
|||
bool unique_edges,
|
||||
bool cmp_slack);
|
||||
|
||||
void pushGroupPathEnds(PathEndSeq &path_ends);
|
||||
void pushEnds(PathEndSeq &path_ends);
|
||||
void pushUnconstrainedPathEnds(PathEndSeq &path_ends,
|
||||
const MinMaxAll *min_max);
|
||||
|
||||
|
|
@ -181,15 +184,19 @@ protected:
|
|||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
PathGroupNameSet *group_names,
|
||||
StdStringSet &group_names,
|
||||
bool setup_hold,
|
||||
bool async,
|
||||
bool gated_clk,
|
||||
bool unconstrained,
|
||||
const MinMax *min_max);
|
||||
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 endpoint_path_count_;
|
||||
bool unique_pins_;
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@
|
|||
#include "Error.hh"
|
||||
|
||||
// Don't require all of tcl.h.
|
||||
typedef struct Tcl_RegExp_ *Tcl_RegExp;
|
||||
typedef struct Tcl_Interp Tcl_Interp;
|
||||
using Tcl_RegExp = struct Tcl_RegExp_ *;
|
||||
using Tcl_Interp = struct Tcl_Interp;
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ private:
|
|||
class RegexpCompileError : public Exception
|
||||
{
|
||||
public:
|
||||
explicit RegexpCompileError(const char *pattern);
|
||||
RegexpCompileError(const char *pattern);
|
||||
virtual ~RegexpCompileError() noexcept {}
|
||||
virtual const char *what() const noexcept;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,13 +24,14 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "Hash.hh"
|
||||
#include "Set.hh"
|
||||
#include "NetworkClass.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
typedef std::pair<const Pin*, const Pin*> PinPair;
|
||||
using PinPair = std::pair<const Pin*, const Pin*>;
|
||||
|
||||
class PinPairLess
|
||||
{
|
||||
|
|
@ -44,7 +45,7 @@ private:
|
|||
};
|
||||
|
||||
|
||||
class PinPairSet : public Set<PinPair, PinPairLess>
|
||||
class PinPairSet : public std::set<PinPair, PinPairLess>
|
||||
{
|
||||
public:
|
||||
PinPairSet(const Network *network);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "RiseFallMinMax.hh"
|
||||
#include "SdcClass.hh"
|
||||
|
||||
|
|
@ -31,7 +33,7 @@ namespace sta {
|
|||
|
||||
class PortDelay;
|
||||
|
||||
typedef Vector<PortDelay*> PortDelaySeq;
|
||||
using PortDelaySeq = std::vector<PortDelay*>;
|
||||
|
||||
// set_input_delay arrival, set_output_delay departure
|
||||
class PortDelay
|
||||
|
|
@ -98,7 +100,7 @@ private:
|
|||
class PortDelayLess
|
||||
{
|
||||
public:
|
||||
explicit PortDelayLess(const Network *network);
|
||||
PortDelayLess(const Network *network);
|
||||
bool operator()(const PortDelay *delay1,
|
||||
const PortDelay *delay2) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,39 +32,42 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
typedef MinMaxIntValues FanoutValues;
|
||||
using FanoutValues = MinMaxIntValues;
|
||||
|
||||
// Port external pin and wire capacitance (set_load -pin_load -wire_load).
|
||||
class PortExtCap
|
||||
{
|
||||
public:
|
||||
PortExtCap(const Port *port);
|
||||
PortExtCap();
|
||||
const Port *port() { return port_; }
|
||||
void pinCap(const RiseFall *rf,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
float &cap,
|
||||
bool &exists);
|
||||
RiseFallMinMax *pinCap() { return &pin_cap_; }
|
||||
void setPinCap(float cap,
|
||||
bool &exists) const;
|
||||
const RiseFallMinMax *pinCap() const { return &pin_cap_; }
|
||||
void setPinCap(const Port *port,
|
||||
float cap,
|
||||
const RiseFall *rf,
|
||||
const MinMax *min_max);
|
||||
void wireCap(const RiseFall *rf,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
float &cap,
|
||||
bool &exists);
|
||||
RiseFallMinMax *wireCap() { return &wire_cap_; }
|
||||
void setWireCap(float cap,
|
||||
bool &exists) const;
|
||||
const RiseFallMinMax *wireCap() const { return &wire_cap_; }
|
||||
void setWireCap(const Port *port,
|
||||
float cap,
|
||||
const RiseFall *rf,
|
||||
const MinMax *min_max);
|
||||
void setFanout(int fanout,
|
||||
void setFanout(const Port *port,
|
||||
int fanout,
|
||||
const MinMax *min_max);
|
||||
void fanout(const MinMax *min_max,
|
||||
// Return values.
|
||||
int &fanout,
|
||||
bool &exists);
|
||||
FanoutValues *fanout() { return &fanout_; }
|
||||
bool &exists) const;
|
||||
const FanoutValues *fanout() const { return &fanout_; }
|
||||
|
||||
private:
|
||||
const Port *port_;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue