Merge remote-tracking branch 'upstream/master' into update

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
Matt Liberty 2024-02-12 22:48:05 -08:00
commit d61313d8ad
386 changed files with 7288 additions and 8818 deletions

View File

@ -1,5 +1,5 @@
# OpenSTA, Static Timing Analyzer # OpenSTA, Static Timing Analyzer
# Copyright (c) 2023, Parallax Software, Inc. # Copyright (c) 2024, Parallax Software, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -24,14 +24,14 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.14)
cmake_policy(SET CMP0086 NEW) cmake_policy(SET CMP0086 NEW)
endif() endif()
project(STA VERSION 2.4.0 project(STA VERSION 2.5.0
LANGUAGES CXX LANGUAGES CXX
) )
option(USE_CUDD "Use CUDD BDD package") option(USE_CUDD "Use CUDD BDD package")
option(CUDD_DIR "CUDD BDD package directory") option(CUDD_DIR "CUDD BDD package directory")
set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_VERBOSE_MAKEFILE OFF)
set(STA_HOME ${PROJECT_SOURCE_DIR}) set(STA_HOME ${PROJECT_SOURCE_DIR})
message(STATUS "STA version: ${PROJECT_VERSION}") message(STATUS "STA version: ${PROJECT_VERSION}")
@ -62,6 +62,7 @@ set(STA_SOURCE
app/StaMain.cc app/StaMain.cc
dcalc/ArcDelayCalc.cc dcalc/ArcDelayCalc.cc
dcalc/ArcDcalcWaveforms.cc
dcalc/ArnoldiDelayCalc.cc dcalc/ArnoldiDelayCalc.cc
dcalc/ArnoldiReduce.cc dcalc/ArnoldiReduce.cc
dcalc/DcalcAnalysisPt.cc dcalc/DcalcAnalysisPt.cc
@ -69,11 +70,11 @@ set(STA_SOURCE
dcalc/DelayCalcBase.cc dcalc/DelayCalcBase.cc
dcalc/DmpCeff.cc dcalc/DmpCeff.cc
dcalc/DmpDelayCalc.cc dcalc/DmpDelayCalc.cc
dcalc/FindRoot.cc
dcalc/GraphDelayCalc.cc dcalc/GraphDelayCalc.cc
dcalc/LumpedCapDelayCalc.cc dcalc/LumpedCapDelayCalc.cc
dcalc/NetCaps.cc dcalc/NetCaps.cc
dcalc/ParallelDelayCalc.cc dcalc/ParallelDelayCalc.cc
dcalc/SlewDegradeDelayCalc.cc
dcalc/UnitDelayCalc.cc dcalc/UnitDelayCalc.cc
graph/DelayFloat.cc graph/DelayFloat.cc
@ -114,7 +115,6 @@ set(STA_SOURCE
parasitics/ConcreteParasitics.cc parasitics/ConcreteParasitics.cc
parasitics/EstimateParasitics.cc parasitics/EstimateParasitics.cc
parasitics/NullParasitics.cc
parasitics/Parasitics.cc parasitics/Parasitics.cc
parasitics/ReduceParasitics.cc parasitics/ReduceParasitics.cc
parasitics/ReportParasiticAnnotation.cc parasitics/ReportParasiticAnnotation.cc
@ -325,16 +325,20 @@ set_property(SOURCE ${STA_SWIG_FILE}
-I${STA_HOME}/verilog -I${STA_HOME}/verilog
) )
set_property(SOURCE ${STA_SWIG_FILE} set(SWIG_FILES
PROPERTY DEPENDS
${STA_HOME}/dcalc/DelayCalc.i ${STA_HOME}/dcalc/DelayCalc.i
${STA_HOME}/parasitics/Parasitics.i ${STA_HOME}/parasitics/Parasitics.i
${STA_HOME}/power/Power.i ${STA_HOME}/power/Power.i
${STA_HOME}/sdf/Sdf.i ${STA_HOME}/sdf/Sdf.i
${STA_HOME}/tcl/Exception.i ${STA_HOME}/tcl/Exception.i
${STA_HOME}/tcl/StaTcl.i ${STA_HOME}/tcl/StaTcl.i
${STA_HOME}/tcl/StaTclTypes.i
${STA_HOME}/tcl/NetworkEdit.i ${STA_HOME}/tcl/NetworkEdit.i
${STA_HOME}/verilog/Verilog.i ${STA_HOME}/verilog/Verilog.i
)
set_property(SOURCE ${STA_SWIG_FILE}
PROPERTY DEPENDS ${SWIG_FILES}
) )
swig_add_library(sta_swig swig_add_library(sta_swig
@ -343,16 +347,14 @@ swig_add_library(sta_swig
SOURCES ${STA_SWIG_FILE} SOURCES ${STA_SWIG_FILE}
) )
get_target_property(SWIG_FILES sta_swig SOURCES) get_target_property(STA_SWIG_CXX_FILE sta_swig SOURCES)
foreach(SWIG_FILE ${SWIG_FILES}) set_source_files_properties(${STA_SWIG_CXX_FILE}
set_source_files_properties(${SWIG_FILE}
PROPERTIES PROPERTIES
# No simple way to modify the swig template that emits code full of warnings # No simple way to modify the swig template that emits code full of warnings
# so suppress them. # so suppress them.
COMPILE_OPTIONS "-Wno-cast-qual;-Wno-missing-braces;-Wno-deprecated-declarations" COMPILE_OPTIONS "-Wno-cast-qual;-Wno-missing-braces;-Wno-deprecated-declarations"
) )
endforeach()
target_link_libraries(sta_swig target_link_libraries(sta_swig
PUBLIC PUBLIC
@ -578,6 +580,7 @@ add_custom_target(sta_tags etags -o TAGS
${STA_SOURCE} ${STA_SOURCE}
*/*.hh */*.hh
include/sta/*.hh include/sta/*.hh
${SWIG_FILES}
${STA_TCL_FILES} ${STA_TCL_FILES}
${SWIG_TCL_FILES} ${SWIG_TCL_FILES}
WORKING_DIRECTORY ${STA_HOME} WORKING_DIRECTORY ${STA_HOME}

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
%module sta %module sta
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -17,6 +17,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
%include "Exception.i" %include "Exception.i"
%include "StaTclTypes.i"
%include "StaTcl.i" %include "StaTcl.i"
%include "Verilog.i" %include "Verilog.i"
%include "NetworkEdit.i" %include "NetworkEdit.i"

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -63,7 +63,7 @@ get_filename_component(TCL_LIB_PARENT2 "${TCL_LIB_PARENT1}" PATH)
if (NOT TCL_HEADER) if (NOT TCL_HEADER)
find_file(TCL_HEADER tcl.h find_file(TCL_HEADER tcl.h
PATHS ${TCL_LIB_PARENT1} ${TCL_LIB_PARENT2} PATHS ${TCL_LIB_PARENT1} ${TCL_LIB_PARENT2}
PATH_SUFFIXES include include/tcl PATH_SUFFIXES include include/tcl include/tcl-tk
NO_DEFAULT_PATH NO_DEFAULT_PATH
) )
endif() endif()

View File

@ -0,0 +1,43 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2024, 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/>.
#include "ArcDcalcWaveforms.hh"
namespace sta {
Table1
ArcDcalcWaveforms::inputWaveform(const Pin *,
const RiseFall *,
const Corner *,
const MinMax *)
{
return Table1();
}
Table1
ArcDcalcWaveforms::drvrRampWaveform(const Pin *,
const RiseFall *,
const Pin *,
const RiseFall *,
const Pin *,
const Corner *,
const MinMax *)
{
return Table1();
}
} // namespace

View File

@ -0,0 +1,59 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2024, 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/>.
#pragma once
#include "MinMax.hh"
#include "TableModel.hh"
#include "NetworkClass.hh"
namespace sta {
class Corner;
class DcalcAnalysisPt;
// Abstract class for the graph delay calculator traversal to interface
class ArcDcalcWaveforms
{
public:
virtual Table1 inputWaveform(const Pin *in_pin,
const RiseFall *in_rf,
const Corner *corner,
const MinMax *min_max);
virtual Table1 drvrWaveform(const Pin *in_pin,
const RiseFall *in_rf,
const Pin *drvr_pin,
const RiseFall *drvr_rf,
const Corner *corner,
const MinMax *min_max) = 0;
virtual Table1 loadWaveform(const Pin *in_pin,
const RiseFall *in_rf,
const Pin *drvr_pin,
const RiseFall *drvr_rf,
const Pin *load_pin,
const Corner *corner,
const MinMax *min_max) = 0;
virtual Table1 drvrRampWaveform(const Pin *in_pin,
const RiseFall *in_rf,
const Pin *drvr_pin,
const RiseFall *drvr_rf,
const Pin *load_pin,
const Corner *corner,
const MinMax *min_max);
};
} // namespace

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -16,10 +16,6 @@
#include "ArcDelayCalc.hh" #include "ArcDelayCalc.hh"
#include "TimingModel.hh"
#include "TimingArc.hh"
#include "GraphDelayCalc.hh"
namespace sta { namespace sta {
ArcDelayCalc::ArcDelayCalc(StaState *sta): ArcDelayCalc::ArcDelayCalc(StaState *sta):
@ -27,27 +23,114 @@ ArcDelayCalc::ArcDelayCalc(StaState *sta):
{ {
} }
TimingModel * void
ArcDelayCalc::model(const TimingArc *arc, ArcDelayCalc::gateDelay(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const const Slew &in_slew,
float load_cap,
const Parasitic *parasitic,
float,
const Pvt *,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &drvr_slew)
{ {
const OperatingConditions *op_cond = dcalc_ap->operatingConditions(); LoadPinIndexMap load_pin_index_map(network_);
const TimingArc *corner_arc = arc->cornerArc(dcalc_ap->libertyIndex()); ArcDcalcResult dcalc_result = gateDelay(nullptr, arc, in_slew, load_cap, parasitic,
return corner_arc->model(op_cond); load_pin_index_map, dcalc_ap);
gate_delay = dcalc_result.gateDelay();
drvr_slew = dcalc_result.drvrSlew();
} }
GateTimingModel * ////////////////////////////////////////////////////////////////
ArcDelayCalc::gateModel(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const ArcDcalcArg::ArcDcalcArg() :
drvr_pin_(nullptr),
edge_(nullptr),
arc_(nullptr),
in_slew_(0.0),
parasitic_(nullptr)
{ {
return dynamic_cast<GateTimingModel*>(model(arc, dcalc_ap));
} }
CheckTimingModel * ArcDcalcArg::ArcDcalcArg(const Pin *drvr_pin,
ArcDelayCalc::checkModel(const TimingArc *arc, Edge *edge,
const DcalcAnalysisPt *dcalc_ap) const const TimingArc *arc,
const Slew in_slew,
const Parasitic *parasitic) :
drvr_pin_(drvr_pin),
edge_(edge),
arc_(arc),
in_slew_(in_slew),
parasitic_(parasitic)
{ {
return dynamic_cast<CheckTimingModel*>(model(arc, dcalc_ap)); }
void
ArcDcalcArg::setParasitic(const Parasitic *parasitic)
{
parasitic_ = parasitic;
}
////////////////////////////////////////////////////////////////
ArcDcalcResult::ArcDcalcResult() :
gate_delay_(0.0),
drvr_slew_(0.0)
{
}
ArcDcalcResult::ArcDcalcResult(size_t load_count) :
gate_delay_(0.0),
drvr_slew_(0.0)
{
wire_delays_.resize(load_count);
load_slews_.resize(load_count);
}
void
ArcDcalcResult::setGateDelay(ArcDelay gate_delay)
{
gate_delay_ = gate_delay;
}
void
ArcDcalcResult::setDrvrSlew(Slew drvr_slew)
{
drvr_slew_ = drvr_slew;
}
ArcDelay
ArcDcalcResult::wireDelay(size_t load_idx) const
{
return wire_delays_[load_idx];
}
void
ArcDcalcResult::setWireDelay(size_t load_idx,
ArcDelay wire_delay)
{
wire_delays_[load_idx] = wire_delay;
}
void
ArcDcalcResult::setLoadCount(size_t load_count)
{
wire_delays_.resize(load_count);
load_slews_.resize(load_count);
}
Slew
ArcDcalcResult::loadSlew(size_t load_idx) const
{
return load_slews_[load_idx];
}
void
ArcDcalcResult::setLoadSlew(size_t load_idx,
Slew load_slew)
{
load_slews_[load_idx] = load_slew;
} }
} // namespace } // namespace

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -64,6 +64,8 @@ public:
rcmodel(); rcmodel();
virtual ~rcmodel(); virtual ~rcmodel();
virtual float capacitance() const; virtual float capacitance() const;
virtual PinSet unannotatedLoads(const Pin *drvr_pin,
const Parasitics *parasitics) const;
const Pin **pinV; // [n] const Pin **pinV; // [n]
}; };
@ -74,7 +76,6 @@ struct timing_table
const LibertyCell *cell; const LibertyCell *cell;
const Pvt *pvt; const Pvt *pvt;
float in_slew; float in_slew;
float relcap;
}; };
} // namespace } // namespace

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -30,6 +30,7 @@
#include "TimingModel.hh" #include "TimingModel.hh"
#include "TimingArc.hh" #include "TimingArc.hh"
#include "TableModel.hh" #include "TableModel.hh"
#include "PortDirection.hh"
#include "Network.hh" #include "Network.hh"
#include "Graph.hh" #include "Graph.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
@ -117,34 +118,33 @@ public:
Parasitic *findParasitic(const Pin *drvr_pin, Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override; const DcalcAnalysisPt *dcalc_ap) override;
ReducedParasiticType reducedParasiticType() const override; Parasitic *reduceParasitic(const Parasitic *parasitic_network,
void inputPortDelay(const Pin *port_pin, const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override;
ArcDcalcResult inputPortDelay(const Pin *port_pin,
float in_slew, float in_slew,
const RiseFall *rf, const RiseFall *rf,
const Parasitic *parasitic, const Parasitic *parasitic,
const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap) override; const DcalcAnalysisPt *dcalc_ap) override;
void gateDelay(const TimingArc *arc, ArcDcalcResult gateDelay(const Pin *drvr_pin,
const TimingArc *arc,
const Slew &in_slew,
// Pass in load_cap or parasitic.
float load_cap,
const Parasitic *parasitic,
const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap) override;
string reportGateDelay(const Pin *drvr_pin,
const TimingArc *arc,
const Slew &in_slew, const Slew &in_slew,
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const Parasitic *parasitic,
float related_out_cap, const LoadPinIndexMap &load_pin_index_map,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &drvr_slew) override;
void loadDelay(const Pin *load_pin,
// Return values.
ArcDelay &wire_delay,
Slew &load_slew) override;
string reportGateDelay(const TimingArc *arc,
const Slew &in_slew,
float load_cap,
const Parasitic *drvr_parasitic,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
int digits) override; int digits) override;
void finishDrvrPin() override;
void delay_work_set_thresholds(delay_work *D, void delay_work_set_thresholds(delay_work *D,
double lo, double lo,
double hi, double hi,
@ -152,14 +152,12 @@ public:
double derate); double derate);
private: private:
void gateDelaySlew(const LibertyCell *drvr_cell, ArcDcalcResult gateDelaySlew(const LibertyCell *drvr_cell,
const TimingArc *arc,
const GateTableModel *table_model, const GateTableModel *table_model,
const Slew &in_slew, const Slew &in_slew,
float related_out_cap, const LoadPinIndexMap &load_pin_index_map,
const Pvt *pvt, const Pvt *pvt);
// Return values.
ArcDelay &gate_delay,
Slew &drvr_slew);
void ar1_ceff_delay(delay_work *D, void ar1_ceff_delay(delay_work *D,
timing_table *tab, timing_table *tab,
arnoldi1 *mod, arnoldi1 *mod,
@ -224,9 +222,9 @@ private:
double *_delayV; double *_delayV;
double *_slewV; double *_slewV;
int pin_n_; int pin_n_;
bool input_port_;
ArnoldiReduce *reduce_; ArnoldiReduce *reduce_;
delay_work *delay_work_; delay_work *delay_work_;
vector<rcmodel*> unsaved_parasitics_;
}; };
ArcDelayCalc * ArcDelayCalc *
@ -266,65 +264,70 @@ ArnoldiDelayCalc::findParasitic(const Pin *drvr_pin,
{ {
Parasitic *parasitic = nullptr; Parasitic *parasitic = nullptr;
const Corner *corner = dcalc_ap->corner(); const Corner *corner = dcalc_ap->corner();
// set_load net has precidence over parasitics. // set_load net has precedence over parasitics.
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) { if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|| network_->direction(drvr_pin)->isInternal())
return nullptr;
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt(); const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
Parasitic *parasitic_network = Parasitic *parasitic_network =
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap); parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
bool delete_parasitic_network = false; const MinMax *min_max = dcalc_ap->constraintMinMax();
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
const OperatingConditions *op_cond = dcalc_ap->operatingConditions();
if (parasitic_network == nullptr) { if (parasitic_network == nullptr) {
Wireload *wireload = sdc_->wireload(cnst_min_max); Wireload *wireload = sdc_->wireload(min_max);
if (wireload) { if (wireload) {
float pin_cap, wire_cap, fanout; float pin_cap, wire_cap, fanout;
bool has_wire_cap; bool has_wire_cap;
graph_delay_calc_->netCaps(drvr_pin, drvr_rf, dcalc_ap, graph_delay_calc_->netCaps(drvr_pin, drvr_rf, dcalc_ap,
pin_cap, wire_cap, fanout, has_wire_cap); pin_cap, wire_cap, fanout, has_wire_cap);
parasitic_network = parasitics_->makeWireloadNetwork(drvr_pin, wireload, parasitic_network = parasitics_->makeWireloadNetwork(drvr_pin, wireload,
fanout, op_cond, fanout, min_max,
parasitic_ap); parasitic_ap);
delete_parasitic_network = true;
} }
} }
if (parasitic_network) { if (parasitic_network) {
parasitic = reduce_->reduceToArnoldi(parasitic_network, rcmodel *rcmodel = reduce_->reduceToArnoldi(parasitic_network, drvr_pin,
drvr_pin,
parasitic_ap->couplingCapFactor(), parasitic_ap->couplingCapFactor(),
drvr_rf, op_cond, corner, drvr_rf, corner, min_max, parasitic_ap);
cnst_min_max, parasitic_ap);
if (delete_parasitic_network) {
Net *net = network_->net(drvr_pin);
parasitics_->deleteParasiticNetwork(net, parasitic_ap);
}
// Arnoldi parasitics are their own class that are not saved in the parasitic db. // Arnoldi parasitics are their own class that are not saved in the parasitic db.
unsaved_parasitics_.push_back(parasitic); unsaved_parasitics_.push_back(rcmodel);
} parasitic = rcmodel;
} }
return parasitic; return parasitic;
} }
ReducedParasiticType Parasitic *
ArnoldiDelayCalc::reducedParasiticType() const ArnoldiDelayCalc::reduceParasitic(const Parasitic *,
const Pin *,
const RiseFall *,
const DcalcAnalysisPt *)
{ {
return ReducedParasiticType::arnoldi; // Decline because reduced arnoldi parasitics are not stored in the parasitics db.
return nullptr;
} }
void void
ArnoldiDelayCalc::inputPortDelay(const Pin *drvr_pin, ArnoldiDelayCalc::finishDrvrPin()
{
for (auto parasitic : unsaved_parasitics_)
delete parasitic;
unsaved_parasitics_.clear();
}
ArcDcalcResult
ArnoldiDelayCalc::inputPortDelay(const Pin *,
float in_slew, float in_slew,
const RiseFall *rf, const RiseFall *rf,
const Parasitic *parasitic, const Parasitic *parasitic,
const DcalcAnalysisPt *dcalc_ap) const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *)
{ {
LumpedCapDelayCalc::inputPortDelay(drvr_pin, in_slew, rf, parasitic, dcalc_ap);
rcmodel_ = nullptr; rcmodel_ = nullptr;
_delayV[0] = 0.0; _delayV[0] = 0.0;
_slewV[0] = in_slew; _slewV[0] = in_slew;
int j; LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
ArcDcalcResult dcalc_result(load_pin_index_map.size());
if (parasitic) { if (parasitic) {
rcmodel_ = reinterpret_cast<rcmodel*>(const_cast<Parasitic*>(parasitic)); rcmodel_ = reinterpret_cast<rcmodel*>(const_cast<Parasitic*>(parasitic));
pin_n_ = rcmodel_->n; pin_n_ = rcmodel_->n;
@ -335,69 +338,67 @@ ArnoldiDelayCalc::inputPortDelay(const Pin *drvr_pin,
_delayV = (double*)realloc(_delayV,_pinNmax * sizeof(double)); _delayV = (double*)realloc(_delayV,_pinNmax * sizeof(double));
_slewV = (double*)realloc(_slewV,_pinNmax * sizeof(double)); _slewV = (double*)realloc(_slewV,_pinNmax * sizeof(double));
} }
pin_n_ = 1;
pin_n_ = rcmodel_->n; pin_n_ = rcmodel_->n;
double slew_derate = drvr_library_->slewDerateFromLibrary(); double slew_derate = drvr_library->slewDerateFromLibrary();
double lo_thresh = drvr_library_->slewLowerThreshold(drvr_rf_); double lo_thresh = drvr_library->slewLowerThreshold(rf);
double hi_thresh = drvr_library_->slewUpperThreshold(drvr_rf_); double hi_thresh = drvr_library->slewUpperThreshold(rf);
bool rising = (drvr_rf_ == RiseFall::rise()); bool rising = (rf == RiseFall::rise());
delay_work_set_thresholds(delay_work_, lo_thresh, hi_thresh, rising, delay_work_set_thresholds(delay_work_, lo_thresh, hi_thresh, rising, slew_derate);
slew_derate);
delay_c *c = delay_work_->c; delay_c *c = delay_work_->c;
double c_log = c->vlg; double c_log = c->vlg;
for (j=1;j<pin_n_;j++) { for (int j=1;j<pin_n_;j++) {
double elmore = rcmodel_->elmore(j); double elmore = rcmodel_->elmore(j);
_delayV[j] = 0.6931472*elmore; double wire_delay = 0.6931472*elmore;
_slewV[j] = in_slew + c_log*elmore/slew_derate; double load_slew = in_slew + c_log*elmore/slew_derate;
_delayV[j] = wire_delay;
_slewV[j] = load_slew;
const Pin *load_pin = rcmodel_->pinV[j];
auto load_idx_itr = load_pin_index_map.find(load_pin);
if (load_idx_itr != load_pin_index_map.end()) {
size_t load_idx = load_idx_itr->second;
dcalc_result.setWireDelay(load_idx, wire_delay);
dcalc_result.setLoadSlew(load_idx, load_slew);
} }
} }
}
else
dcalc_result = makeResult(drvr_library, rf, 0.0, in_slew, load_pin_index_map);
return dcalc_result;
} }
void ArcDcalcResult
ArnoldiDelayCalc::gateDelay(const TimingArc *arc, ArnoldiDelayCalc::gateDelay(const Pin *drvr_pin,
const TimingArc *arc,
const Slew &in_slew, const Slew &in_slew,
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const Parasitic *parasitic,
float related_out_cap, const LoadPinIndexMap &load_pin_index_map,
const Pvt *pvt, const DcalcAnalysisPt *dcalc_ap)
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &drvr_slew)
{ {
input_port_ = false;
drvr_rf_ = arc->toEdge()->asRiseFall();
const LibertyCell *drvr_cell = arc->from()->libertyCell(); const LibertyCell *drvr_cell = arc->from()->libertyCell();
drvr_library_ = drvr_cell->libertyLibrary(); ConcreteParasitic *cparasitic =
drvr_parasitic_ = drvr_parasitic; reinterpret_cast<ConcreteParasitic*>(const_cast<Parasitic*>(parasitic));
ConcreteParasitic *drvr_cparasitic = rcmodel_ = dynamic_cast<rcmodel*>(cparasitic);
reinterpret_cast<ConcreteParasitic*>(const_cast<Parasitic*>(drvr_parasitic)); GateTableModel *table_model = gateTableModel(arc, dcalc_ap);
rcmodel_ = dynamic_cast<rcmodel*>(drvr_cparasitic); if (table_model && rcmodel_) {
GateTimingModel *model = gateModel(arc, dcalc_ap); const Pvt *pvt = pinPvt(drvr_pin, dcalc_ap);
GateTableModel *table_model = dynamic_cast<GateTableModel*>(model); return gateDelaySlew(drvr_cell, arc, table_model, in_slew, load_pin_index_map, pvt);
if (table_model && rcmodel_) }
gateDelaySlew(drvr_cell, table_model, in_slew,
related_out_cap, pvt,
gate_delay, drvr_slew);
else else
LumpedCapDelayCalc::gateDelay(arc, in_slew, load_cap, drvr_parasitic, return LumpedCapDelayCalc::gateDelay(drvr_pin, arc, in_slew, load_cap,
related_out_cap, pvt, dcalc_ap, parasitic, load_pin_index_map, dcalc_ap);
gate_delay, drvr_slew);
drvr_slew_ = drvr_slew;
multi_drvr_slew_factor_ = 1.0F;
} }
void ArcDcalcResult
ArnoldiDelayCalc::gateDelaySlew(const LibertyCell *drvr_cell, ArnoldiDelayCalc::gateDelaySlew(const LibertyCell *drvr_cell,
const TimingArc *arc,
const GateTableModel *table_model, const GateTableModel *table_model,
const Slew &in_slew, const Slew &in_slew,
float related_out_cap, const LoadPinIndexMap &load_pin_index_map,
const Pvt *pvt, const Pvt *pvt)
// Return values.
ArcDelay &gate_delay,
Slew &drvr_slew)
{ {
pin_n_ = rcmodel_->n; pin_n_ = rcmodel_->n;
if (pin_n_ >= _pinNmax) { if (pin_n_ >= _pinNmax) {
@ -407,12 +408,15 @@ ArnoldiDelayCalc::gateDelaySlew(const LibertyCell *drvr_cell,
_slewV = (double*)realloc(_slewV,_pinNmax * sizeof(double)); _slewV = (double*)realloc(_slewV,_pinNmax * sizeof(double));
} }
ArcDcalcResult dcalc_result(load_pin_index_map.size());
pin_n_ = rcmodel_->n; pin_n_ = rcmodel_->n;
if (table_model) { const RiseFall *rf = arc->toEdge()->asRiseFall();
double slew_derate = drvr_library_->slewDerateFromLibrary(); if (table_model && rf) {
double lo_thresh = drvr_library_->slewLowerThreshold(drvr_rf_); const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
double hi_thresh = drvr_library_->slewUpperThreshold(drvr_rf_); double slew_derate = drvr_library->slewDerateFromLibrary();
bool rising = (drvr_rf_ == RiseFall::rise()); double lo_thresh = drvr_library->slewLowerThreshold(rf);
double hi_thresh = drvr_library->slewUpperThreshold(rf);
bool rising = (rf == RiseFall::rise());
delay_work_set_thresholds(delay_work_, lo_thresh, hi_thresh, rising, delay_work_set_thresholds(delay_work_, lo_thresh, hi_thresh, rising,
slew_derate); slew_derate);
if (rcmodel_->order > 0) { if (rcmodel_->order > 0) {
@ -421,48 +425,43 @@ ArnoldiDelayCalc::gateDelaySlew(const LibertyCell *drvr_cell,
tab.cell = drvr_cell; tab.cell = drvr_cell;
tab.pvt = pvt; tab.pvt = pvt;
tab.in_slew = delayAsFloat(in_slew); tab.in_slew = delayAsFloat(in_slew);
tab.relcap = related_out_cap;
ar1_ceff_delay(delay_work_, &tab, rcmodel_, ar1_ceff_delay(delay_work_, &tab, rcmodel_,
_delayV, _slewV); _delayV, _slewV);
} }
gate_delay = _delayV[0]; dcalc_result.setGateDelay(_delayV[0]);
drvr_slew = _slewV[0]; dcalc_result.setDrvrSlew(_slewV[0]);
}
}
void
ArnoldiDelayCalc::loadDelay(const Pin *load_pin,
// Return values.
ArcDelay &wire_delay,
Slew &load_slew)
{
// This does not appear to handle input port parasitics correctly.
wire_delay = 0.0;
load_slew = drvr_slew_ * multi_drvr_slew_factor_;
if (rcmodel_) { if (rcmodel_) {
// HACK
for (int i = 0; i < rcmodel_->n; i++) { for (int i = 0; i < rcmodel_->n; i++) {
if (rcmodel_->pinV[i] == load_pin) { const Pin *load_pin = rcmodel_->pinV[i];
wire_delay = _delayV[i] - _delayV[0]; auto load_idx_itr = load_pin_index_map.find(load_pin);
load_slew = _slewV[i] * multi_drvr_slew_factor_; if (load_idx_itr != load_pin_index_map.end()) {
break; size_t load_idx = load_idx_itr->second;
ArcDelay wire_delay = _delayV[i] - _delayV[0];
Slew load_slew = _slewV[i];
thresholdAdjust(load_pin, drvr_library, rf, wire_delay, load_slew);
dcalc_result.setWireDelay(load_idx, wire_delay);
dcalc_result.setLoadSlew(load_idx, load_slew);
} }
} }
} }
thresholdAdjust(load_pin, wire_delay, load_slew); }
return dcalc_result;
} }
string string
ArnoldiDelayCalc::reportGateDelay(const TimingArc *, ArnoldiDelayCalc::reportGateDelay(const Pin *drvr_pin,
const Slew &, const TimingArc *arc,
float, const Slew &in_slew,
const Parasitic *, float load_cap,
float, const Parasitic *parasitic,
const Pvt *, const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *, const DcalcAnalysisPt *dcalc_ap,
int) int digits)
{ {
return ""; return LumpedCapDelayCalc::reportGateDelay(drvr_pin, arc, in_slew, load_cap,
parasitic, load_pin_index_map,
dcalc_ap, digits);
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -1310,12 +1309,11 @@ ArnoldiDelayCalc::ra_get_r(delay_work *D,
c1 = ctot; c1 = ctot;
ArcDelay d1; ArcDelay d1;
Slew s1; Slew s1;
tab->table->gateDelay(tab->pvt, tab->in_slew, c1, tab->relcap, pocv_enabled_, d1, s1); tab->table->gateDelay(tab->pvt, tab->in_slew, c1, pocv_enabled_, d1, s1);
tlohi = slew_derate*delayAsFloat(s1); tlohi = slew_derate*delayAsFloat(s1);
r = tlohi/(c_log*c1); r = tlohi/(c_log*c1);
if (rdelay>0.0 && r > rdelay) if (rdelay>0.0 && r > rdelay)
r = rdelay; r = rdelay;
// else printf("from rdelay %g to r %g\n",rdelay,r);
return r; return r;
} }
@ -1332,7 +1330,7 @@ ArnoldiDelayCalc::ra_get_s(delay_work *D,
double tlohi,smin,s; double tlohi,smin,s;
ArcDelay d1; ArcDelay d1;
Slew s1; Slew s1;
tab->table->gateDelay(tab->pvt, tab->in_slew, c, tab->relcap, pocv_enabled_, d1, s1); tab->table->gateDelay(tab->pvt, tab->in_slew, c, pocv_enabled_, d1, s1);
tlohi = slew_derate*delayAsFloat(s1); tlohi = slew_derate*delayAsFloat(s1);
smin = r*c*c_smin; // c_smin = ra_hinv((1-vhi)/vhi-log(vhi)) + log(vhi); smin = r*c*c_smin; // c_smin = ra_hinv((1-vhi)/vhi-log(vhi)) + log(vhi);
if (c_log*r*c >= tlohi) { if (c_log*r*c >= tlohi) {
@ -1365,8 +1363,8 @@ ArnoldiDelayCalc::ra_rdelay_1(timing_table *tab,
return 0.0; return 0.0;
ArcDelay d1, d2; ArcDelay d1, d2;
Slew s1, s2; Slew s1, s2;
tab->table->gateDelay(tab->pvt, tab->in_slew, c1, tab->relcap, pocv_enabled_, d1, s1); tab->table->gateDelay(tab->pvt, tab->in_slew, c1, pocv_enabled_, d1, s1);
tab->table->gateDelay(tab->pvt, tab->in_slew, c2, tab->relcap, pocv_enabled_, d2, s2); tab->table->gateDelay(tab->pvt, tab->in_slew, c2, pocv_enabled_, d2, s2);
double dt50 = delayAsFloat(d1)-delayAsFloat(d2); double dt50 = delayAsFloat(d1)-delayAsFloat(d2);
if (dt50 <= 0.0) if (dt50 <= 0.0)
return 0.0; return 0.0;
@ -1418,8 +1416,7 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D,
units_->timeUnit()->asString(s)); units_->timeUnit()->asString(s));
thix = ra_solve_for_t(p,s,vhi); thix = ra_solve_for_t(p,s,vhi);
tlox = ra_solve_for_t(p,s,vlo); tlox = ra_solve_for_t(p,s,vlo);
tab->table->gateDelay(tab->pvt,tab->in_slew, ctot, tab->relcap, pocv_enabled_, tab->table->gateDelay(tab->pvt,tab->in_slew, ctot, pocv_enabled_, df, sf);
df, sf);
debugPrint(debug_, "arnoldi", 1, "table slew (in_slew %s ctot %s) = %s", debugPrint(debug_, "arnoldi", 1, "table slew (in_slew %s ctot %s) = %s",
units_->timeUnit()->asString(tab->in_slew), units_->timeUnit()->asString(tab->in_slew),
units_->capacitanceUnit()->asString(ctot), units_->capacitanceUnit()->asString(ctot),
@ -1430,7 +1427,7 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D,
units_->timeUnit()->asString(tlox-thix)); units_->timeUnit()->asString(tlox-thix));
} }
ceff = ctot; ceff = ctot;
tab->table->gateDelay(tab->pvt, tab->in_slew, ceff, tab->relcap, pocv_enabled_, tab->table->gateDelay(tab->pvt, tab->in_slew, ceff, pocv_enabled_,
df, sf); df, sf);
t50_sy = delayAsFloat(df); t50_sy = delayAsFloat(df);
t50_sr = ra_solve_for_t(1.0/(r*ceff),s,0.5); t50_sr = ra_solve_for_t(1.0/(r*ceff),s,0.5);
@ -1472,7 +1469,7 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D,
units_->timeUnit()->asString(ceff_time), units_->timeUnit()->asString(ceff_time),
units_->capacitanceUnit()->asString(ceff)); units_->capacitanceUnit()->asString(ceff));
tab->table->gateDelay(tab->pvt, tab->in_slew, ceff, tab->relcap, pocv_enabled_, df, sf); tab->table->gateDelay(tab->pvt, tab->in_slew, ceff, pocv_enabled_, df, sf);
t50_sy = delayAsFloat(df); t50_sy = delayAsFloat(df);
t50_sr = ra_solve_for_t(1.0/(r*ceff),s,0.5); t50_sr = ra_solve_for_t(1.0/(r*ceff),s,0.5);
for (j=0;j<mod->n;j++) { for (j=0;j<mod->n;j++) {

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -46,6 +46,14 @@ rcmodel::capacitance() const
return ctot; return ctot;
} }
PinSet
rcmodel::unannotatedLoads(const Pin *,
const Parasitics *) const
{
// This should never be called because the rcmodel is not saved in the Parasitics.
return PinSet();
}
struct ts_point struct ts_point
{ {
ParasiticNode *node_; ParasiticNode *node_;
@ -62,7 +70,7 @@ struct ts_point
struct ts_edge struct ts_edge
{ {
ConcreteParasiticResistor *resistor_; ParasiticResistor *resistor_;
ts_point *from; ts_point *from;
ts_point *to; ts_point *to;
}; };
@ -131,23 +139,21 @@ ArnoldiReduce::~ArnoldiReduce()
free(ts_pointV); free(ts_pointV);
} }
Parasitic * rcmodel *
ArnoldiReduce::reduceToArnoldi(Parasitic *parasitic, ArnoldiReduce::reduceToArnoldi(Parasitic *parasitic,
const Pin *drvr_pin, const Pin *drvr_pin,
float coupling_cap_factor, float coupling_cap_factor,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *min_max,
const ParasiticAnalysisPt *ap) const ParasiticAnalysisPt *ap)
{ {
parasitic_network_ = reinterpret_cast<ConcreteParasiticNetwork*>(parasitic); parasitic_network_ = reinterpret_cast<ConcreteParasiticNetwork*>(parasitic);
drvr_pin_ = drvr_pin; drvr_pin_ = drvr_pin;
coupling_cap_factor_ = coupling_cap_factor; coupling_cap_factor_ = coupling_cap_factor;
rf_ = rf; rf_ = rf;
op_cond_ = op_cond;
corner_ = corner; corner_ = corner;
cnst_min_max_ = cnst_min_max; min_max_ = min_max;
ap_ = ap; ap_ = ap;
loadWork(); loadWork();
return makeRcmodelDrv(); return makeRcmodelDrv();
@ -158,18 +164,21 @@ ArnoldiReduce::loadWork()
{ {
pt_map_.clear(); pt_map_.clear();
int resistor_count = 0; const ParasiticResistorSeq &resistors = parasitics_->resistors(parasitic_network_);
ConcreteParasiticDeviceSet devices; int resistor_count = resistors.size();
parasitic_network_->devices(&devices);
ConcreteParasiticDeviceSet::Iterator device_iter(devices);
while (device_iter.hasNext()) {
ParasiticDevice *device = device_iter.next();
if (parasitics_->isResistor(device))
resistor_count++;
}
termN = parasitic_network_->pinNodes()->size(); termN = 0;
int subnode_count = parasitic_network_->subNodes()->size(); int subnode_count = 0;
ParasiticNodeSeq nodes = parasitics_->nodes(parasitic_network_);
for (ParasiticNode *node : nodes) {
if (!parasitics_->isExternal(node)) {
const Pin *pin = parasitics_->pin(node);
if (pin)
termN++;
else
subnode_count++;
}
}
ts_pointN = subnode_count + 1 + termN; ts_pointN = subnode_count + 1 + termN;
ts_edgeN = resistor_count; ts_edgeN = resistor_count;
allocPoints(); allocPoints();
@ -191,22 +200,11 @@ ArnoldiReduce::loadWork()
pend = pterm0; pend = pterm0;
e = e0; e = e0;
int index = 0; int index = 0;
ConcreteParasiticSubNodeMap::Iterator
sub_node_iter(parasitic_network_->subNodes());
while (sub_node_iter.hasNext()) {
ConcreteParasiticSubNode *node = sub_node_iter.next();
pt_map_[node] = index;
p = p0 + index;
p->node_ = node;
p->eN = 0;
p->is_term = false;
index++;
}
ConcreteParasiticPinNodeMap::Iterator for (ParasiticNode *node : nodes) {
pin_node_iter(parasitic_network_->pinNodes()); if (!parasitics_->isExternal(node)) {
while (pin_node_iter.hasNext()) { const Pin *pin = parasitics_->pin(node);
ConcreteParasiticPinNode *node = pin_node_iter.next(); if (pin) {
p = pend++; p = pend++;
pt_map_[node] = p - p0; pt_map_[node] = p - p0;
p->node_ = node; p->node_ = node;
@ -214,19 +212,23 @@ ArnoldiReduce::loadWork()
p->is_term = true; p->is_term = true;
tindex = p - pterm0; tindex = p - pterm0;
p->tindex = tindex; p->tindex = tindex;
const Pin *pin = parasitics_->connectionPin(node);
pinV[tindex] = pin; pinV[tindex] = pin;
} }
else {
pt_map_[node] = index;
p = p0 + index;
p->node_ = node;
p->eN = 0;
p->is_term = false;
index++;
}
}
}
ts_edge **eV = ts_eV; ts_edge **eV = ts_eV;
ConcreteParasiticDeviceSet::Iterator device_iter2(devices); for (ParasiticResistor *resistor : resistors) {
while (device_iter2.hasNext()) { ts_point *pt1 = findPt(parasitics_->node1(resistor));
ParasiticDevice *device = device_iter2.next(); ts_point *pt2 = findPt(parasitics_->node2(resistor));
if (parasitics_->isResistor(device)) {
ConcreteParasiticResistor *resistor =
reinterpret_cast<ConcreteParasiticResistor*>(device);
ts_point *pt1 = findPt(resistor->node1());
ts_point *pt2 = findPt(resistor->node2());
e->from = pt1; e->from = pt1;
e->to = pt2; e->to = pt2;
e->resistor_ = resistor; e->resistor_ = resistor;
@ -235,7 +237,6 @@ ArnoldiReduce::loadWork()
pt2->eN++; pt2->eN++;
e++; e++;
} }
}
for (p=p0;p!=pend;p++) { for (p=p0;p!=pend;p++) {
if (p->node_) { if (p->node_) {
@ -313,8 +314,7 @@ ArnoldiReduce::findPt(ParasiticNode *node)
rcmodel * rcmodel *
ArnoldiReduce::makeRcmodelDrv() ArnoldiReduce::makeRcmodelDrv()
{ {
ParasiticNode *drv_node = parasitics_->findNode(parasitic_network_, ParasiticNode *drv_node = parasitics_->findNode(parasitic_network_, drvr_pin_);
drvr_pin_);
ts_point *pdrv = findPt(drv_node); ts_point *pdrv = findPt(drv_node);
makeRcmodelDfs(pdrv); makeRcmodelDfs(pdrv);
getRC(); getRC();
@ -322,8 +322,7 @@ ArnoldiReduce::makeRcmodelDrv()
return nullptr; return nullptr;
setTerms(pdrv); setTerms(pdrv);
makeRcmodelFromTs(); makeRcmodelFromTs();
rcmodel *mod = makeRcmodelFromW(); return makeRcmodelFromW();
return mod;
} }
#define ts_orient( pp, ee) \ #define ts_orient( pp, ee) \
@ -415,7 +414,7 @@ ArnoldiReduce::getRC()
p->r = 0.0; p->r = 0.0;
if (p->node_) { if (p->node_) {
ParasiticNode *node = p->node_; ParasiticNode *node = p->node_;
double cap = parasitics_->nodeGndCap(node, ap_) double cap = parasitics_->nodeGndCap(node)
+ pinCapacitance(node); + pinCapacitance(node);
if (cap > 0.0) { if (cap > 0.0) {
p->c = cap; p->c = cap;
@ -424,7 +423,7 @@ ArnoldiReduce::getRC()
else else
p->c = 0.0; p->c = 0.0;
if (p->in_edge && p->in_edge->resistor_) if (p->in_edge && p->in_edge->resistor_)
p->r = parasitics_->value(p->in_edge->resistor_, ap_); p->r = parasitics_->value(p->in_edge->resistor_);
if (!(p->r>=0.0 && p->r<100e+3)) { // 0 < r < 100kohm if (!(p->r>=0.0 && p->r<100e+3)) { // 0 < r < 100kohm
debugPrint(debug_, "arnoldi", 1, debugPrint(debug_, "arnoldi", 1,
"R value %g out of range, drvr pin %s", "R value %g out of range, drvr pin %s",
@ -433,20 +432,33 @@ ArnoldiReduce::getRC()
} }
} }
} }
for (ParasiticCapacitor *capacitor : parasitics_->capacitors(parasitic_network_)) {
float cap = parasitics_->value(capacitor) * ap_->couplingCapFactor();
ParasiticNode *node1 = parasitics_->node1(capacitor);
if (!parasitics_->isExternal(node1)) {
ts_point *pt = findPt(node1);
pt->c += cap;
}
ParasiticNode *node2 = parasitics_->node2(capacitor);
if (!parasitics_->isExternal(node2)) {
ts_point *pt = findPt(node2);
pt->c += cap;
}
}
} }
float float
ArnoldiReduce::pinCapacitance(ParasiticNode *node) ArnoldiReduce::pinCapacitance(ParasiticNode *node)
{ {
const Pin *pin = parasitics_->connectionPin(node); const Pin *pin = parasitics_->pin(node);
float pin_cap = 0.0; float pin_cap = 0.0;
if (pin) { if (pin) {
Port *port = network_->port(pin); Port *port = network_->port(pin);
LibertyPort *lib_port = network_->libertyPort(port); LibertyPort *lib_port = network_->libertyPort(port);
if (lib_port) if (lib_port)
pin_cap = sdc_->pinCapacitance(pin,rf_, op_cond_, corner_, cnst_min_max_); pin_cap = sdc_->pinCapacitance(pin,rf_, corner_, min_max_);
else if (network_->isTopLevelPort(pin)) else if (network_->isTopLevelPort(pin))
pin_cap = sdc_->portExtCap(port, rf_, corner_, cnst_min_max_); pin_cap = sdc_->portExtCap(port, rf_, corner_, min_max_);
} }
return pin_cap; return pin_cap;
} }

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -37,18 +37,17 @@ class rcmodel;
struct ts_edge; struct ts_edge;
struct ts_point; struct ts_point;
typedef Map<ConcreteParasiticNode*, int> ArnolidPtMap; typedef Map<ParasiticNode*, int> ArnolidPtMap;
class ArnoldiReduce : public StaState class ArnoldiReduce : public StaState
{ {
public: public:
ArnoldiReduce(StaState *sta); ArnoldiReduce(StaState *sta);
~ArnoldiReduce(); ~ArnoldiReduce();
Parasitic *reduceToArnoldi(Parasitic *parasitic, rcmodel *reduceToArnoldi(Parasitic *parasitic,
const Pin *drvr_pin, const Pin *drvr_pin,
float coupling_cap_factor, float coupling_cap_factor,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap); const ParasiticAnalysisPt *ap);
@ -70,9 +69,8 @@ protected:
const Pin *drvr_pin_; const Pin *drvr_pin_;
float coupling_cap_factor_; float coupling_cap_factor_;
const RiseFall *rf_; const RiseFall *rf_;
const OperatingConditions *op_cond_;
const Corner *corner_; const Corner *corner_;
const MinMax *cnst_min_max_; const MinMax *min_max_;
const ParasiticAnalysisPt *ap_; const ParasiticAnalysisPt *ap_;
// ParasiticNode -> ts_point index. // ParasiticNode -> ts_point index.
ArnolidPtMap pt_map_; ArnolidPtMap pt_map_;

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -20,7 +20,6 @@
#include "StringUtil.hh" #include "StringUtil.hh"
#include "UnitDelayCalc.hh" #include "UnitDelayCalc.hh"
#include "LumpedCapDelayCalc.hh" #include "LumpedCapDelayCalc.hh"
#include "SlewDegradeDelayCalc.hh"
#include "DmpDelayCalc.hh" #include "DmpDelayCalc.hh"
#include "ArnoldiDelayCalc.hh" #include "ArnoldiDelayCalc.hh"
@ -35,7 +34,6 @@ registerDelayCalcs()
{ {
registerDelayCalc("unit", makeUnitDelayCalc); registerDelayCalc("unit", makeUnitDelayCalc);
registerDelayCalc("lumped_cap", makeLumpedCapDelayCalc); registerDelayCalc("lumped_cap", makeLumpedCapDelayCalc);
registerDelayCalc("slew_degrade", makeSlewDegradeDelayCalc);
registerDelayCalc("dmp_ceff_elmore", makeDmpCeffElmoreDelayCalc); registerDelayCalc("dmp_ceff_elmore", makeDmpCeffElmoreDelayCalc);
registerDelayCalc("dmp_ceff_two_pole", makeDmpCeffTwoPoleDelayCalc); registerDelayCalc("dmp_ceff_two_pole", makeDmpCeffTwoPoleDelayCalc);
registerDelayCalc("arnoldi", makeArnoldiDelayCalc); registerDelayCalc("arnoldi", makeArnoldiDelayCalc);

View File

@ -3,7 +3,7 @@
%{ %{
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -19,6 +19,8 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "Sta.hh" #include "Sta.hh"
#include "ArcDelayCalc.hh"
#include "dcalc/ArcDcalcWaveforms.hh"
%} %}
@ -59,4 +61,76 @@ report_delay_calc_cmd(Edge *edge,
return Sta::sta()->reportDelayCalc(edge, arc, corner, min_max, digits); return Sta::sta()->reportDelayCalc(edge, arc, corner, min_max, digits);
} }
////////////////////////////////////////////////////////////////
Table1
ccs_input_waveform(const Pin *in_pin,
const RiseFall *in_rf,
const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
Sta *sta = Sta::sta();
ArcDcalcWaveforms *arc_dcalc = dynamic_cast<ArcDcalcWaveforms*>(sta->arcDelayCalc());
if (arc_dcalc)
return arc_dcalc->inputWaveform(in_pin, in_rf, corner, min_max);
else
return Table1();
}
Table1
ccs_driver_waveform(const Pin *in_pin,
const RiseFall *in_rf,
const Pin *drvr_pin,
const RiseFall *drvr_rf,
const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
Sta *sta = Sta::sta();
ArcDcalcWaveforms *arc_dcalc = dynamic_cast<ArcDcalcWaveforms*>(sta->arcDelayCalc());
if (arc_dcalc)
return arc_dcalc->drvrWaveform(in_pin, in_rf, drvr_pin, drvr_rf, corner, min_max);
else
return Table1();
}
Table1
ccs_driver_ramp_waveform(const Pin *in_pin,
const RiseFall *in_rf,
const Pin *drvr_pin,
const RiseFall *drvr_rf,
const Pin *load_pin,
const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
Sta *sta = Sta::sta();
ArcDcalcWaveforms *arc_dcalc = dynamic_cast<ArcDcalcWaveforms*>(sta->arcDelayCalc());
if (arc_dcalc)
return arc_dcalc->drvrRampWaveform(in_pin, in_rf, drvr_pin, drvr_rf,
load_pin, corner, min_max);
else
return Table1();
}
Table1
ccs_load_waveform(const Pin *in_pin,
const RiseFall *in_rf,
const Pin *drvr_pin,
const RiseFall *drvr_rf,
const Pin *load_pin,
const Corner *corner,
const MinMax *min_max)
{
cmdLinkedNetwork();
Sta *sta = Sta::sta();
ArcDcalcWaveforms *arc_dcalc = dynamic_cast<ArcDcalcWaveforms*>(sta->arcDelayCalc());
if (arc_dcalc)
return arc_dcalc->loadWaveform(in_pin, in_rf, drvr_pin, drvr_rf,
load_pin, corner, min_max);
else
return Table1();
}
%} // inline %} // inline

View File

@ -1,5 +1,5 @@
# OpenSTA, Static Timing Analyzer # OpenSTA, Static Timing Analyzer
# Copyright (c) 2023, Parallax Software, Inc. # Copyright (c) 2024, Parallax Software, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -116,7 +116,7 @@ proc set_delay_calculator { alg } {
if { [is_delay_calc_name $alg] } { if { [is_delay_calc_name $alg] } {
set_delay_calculator_cmd $alg set_delay_calculator_cmd $alg
} else { } else {
sta_error 435 "delay calculator $alg not found." sta_error 180 "delay calculator $alg not found."
} }
} }
@ -145,38 +145,38 @@ proc set_assigned_delay_cmd { cmd cmd_args } {
if [info exists keys(-from)] { if [info exists keys(-from)] {
set from_pins [get_port_pins_error "from_pins" $keys(-from)] set from_pins [get_port_pins_error "from_pins" $keys(-from)]
} else { } else {
sta_error 442 "$cmd missing -from argument." sta_error 181 "$cmd missing -from argument."
} }
if [info exists keys(-to)] { if [info exists keys(-to)] {
set to_pins [get_port_pins_error "to_pins" $keys(-to)] set to_pins [get_port_pins_error "to_pins" $keys(-to)]
} else { } else {
sta_error 443 "$cmd missing -to argument." sta_error 182 "$cmd missing -to argument."
} }
set delay [lindex $cmd_args 0] set delay [lindex $cmd_args 0]
if {![string is double $delay]} { if {![string is double $delay]} {
sta_error 444 "$cmd delay is not a float." sta_error 183 "$cmd delay is not a float."
} }
set delay [time_ui_sta $delay] set delay [time_ui_sta $delay]
if {[info exists flags(-cell)] && [info exists flags(-net)]} { if {[info exists flags(-cell)] && [info exists flags(-net)]} {
sta_error 445 "set_annotated_delay -cell and -net options are mutually excluive." sta_error 184 "set_annotated_delay -cell and -net options are mutually excluive."
} elseif {[info exists flags(-cell)]} { } elseif {[info exists flags(-cell)]} {
if { $from_pins != {} } { if { $from_pins != {} } {
set inst [[lindex $from_pins 0] instance] set inst [[lindex $from_pins 0] instance]
foreach pin $from_pins { foreach pin $from_pins {
if {[$pin instance] != $inst} { if {[$pin instance] != $inst} {
sta_error 446 "$cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]." sta_error 185 "$cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]."
} }
} }
foreach pin $to_pins { foreach pin $to_pins {
if {[$pin instance] != $inst} { if {[$pin instance] != $inst} {
sta_error 447 "$cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]" sta_error 186 "$cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]"
} }
} }
} }
} elseif {![info exists flags(-net)]} { } elseif {![info exists flags(-net)]} {
sta_error 448 "$cmd -cell or -net required." sta_error 187 "$cmd -cell or -net required."
} }
foreach from_pin $from_pins { foreach from_pin $from_pins {
set from_vertices [$from_pin vertices] set from_vertices [$from_pin vertices]
@ -240,7 +240,7 @@ proc set_assigned_check_cmd { cmd cmd_args } {
if { [info exists keys(-from)] } { if { [info exists keys(-from)] } {
set from_pins [get_port_pins_error "from_pins" $keys(-from)] set from_pins [get_port_pins_error "from_pins" $keys(-from)]
} else { } else {
sta_error 449 "$cmd missing -from argument." sta_error 188 "$cmd missing -from argument."
} }
set from_rf "rise_fall" set from_rf "rise_fall"
if { [info exists keys(-clock)] } { if { [info exists keys(-clock)] } {
@ -249,14 +249,14 @@ proc set_assigned_check_cmd { cmd cmd_args } {
|| $clk_arg eq "fall" } { || $clk_arg eq "fall" } {
set from_rf $clk_arg set from_rf $clk_arg
} else { } else {
sta_error 450 "$cmd -clock must be rise or fall." sta_error 189 "$cmd -clock must be rise or fall."
} }
} }
if { [info exists keys(-to)] } { if { [info exists keys(-to)] } {
set to_pins [get_port_pins_error "to_pins" $keys(-to)] set to_pins [get_port_pins_error "to_pins" $keys(-to)]
} else { } else {
sta_error 451 "$cmd missing -to argument." sta_error 190 "$cmd missing -to argument."
} }
set to_rf [parse_rise_fall_flags flags] set to_rf [parse_rise_fall_flags flags]
set corner [parse_corner keys] set corner [parse_corner keys]
@ -271,7 +271,7 @@ proc set_assigned_check_cmd { cmd cmd_args } {
} elseif { [info exists flags(-removal)] } { } elseif { [info exists flags(-removal)] } {
set role "removal" set role "removal"
} else { } else {
sta_error 452 "$cmd missing -setup|-hold|-recovery|-removal check type.." sta_error 191 "$cmd missing -setup|-hold|-recovery|-removal check type.."
} }
set cond "" set cond ""
if { [info exists key(-cond)] } { if { [info exists key(-cond)] } {
@ -279,7 +279,7 @@ proc set_assigned_check_cmd { cmd cmd_args } {
} }
set check_value [lindex $cmd_args 0] set check_value [lindex $cmd_args 0]
if { ![string is double $check_value] } { if { ![string is double $check_value] } {
sta_error 453 "$cmd check_value is not a float." sta_error 192 "$cmd check_value is not a float."
} }
set check_value [time_ui_sta $check_value] set check_value [time_ui_sta $check_value]
@ -347,7 +347,7 @@ proc set_assigned_transition { args } {
set slew [lindex $args 0] set slew [lindex $args 0]
if {![string is double $slew]} { if {![string is double $slew]} {
sta_error 428 "set_assigned_transition transition is not a float." sta_error 210 "set_assigned_transition transition is not a float."
} }
set slew [time_ui_sta $slew] set slew [time_ui_sta $slew]
set pins [get_port_pins_error "pins" [lindex $args 1]] set pins [get_port_pins_error "pins" [lindex $args 1]]

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -18,53 +18,85 @@
#include "Liberty.hh" #include "Liberty.hh"
#include "TimingArc.hh" #include "TimingArc.hh"
#include "TimingModel.hh"
#include "TableModel.hh"
#include "Network.hh" #include "Network.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
#include "Sdc.hh"
#include "Corner.hh"
#include "DcalcAnalysisPt.hh"
namespace sta { namespace sta {
using std::log;
DelayCalcBase::DelayCalcBase(StaState *sta) : DelayCalcBase::DelayCalcBase(StaState *sta) :
ArcDelayCalc(sta) ArcDelayCalc(sta)
{ {
} }
void
DelayCalcBase::reduceParasitic(const Parasitic *parasitic_network,
const Net *net,
const Corner *corner,
const MinMaxAll *min_max)
{
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
while (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next();
if (network_->isDriver(pin)) {
for (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);
}
}
}
}
}
delete pin_iter;
}
TimingModel *
DelayCalcBase::model(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const
{
const OperatingConditions *op_cond = dcalc_ap->operatingConditions();
const TimingArc *corner_arc = arc->cornerArc(dcalc_ap->libertyIndex());
return corner_arc->model(op_cond);
}
GateTimingModel *
DelayCalcBase::gateModel(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const
{
return dynamic_cast<GateTimingModel*>(model(arc, dcalc_ap));
}
GateTableModel *
DelayCalcBase::gateTableModel(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const
{
return dynamic_cast<GateTableModel*>(model(arc, dcalc_ap));
}
CheckTimingModel *
DelayCalcBase::checkModel(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const
{
return dynamic_cast<CheckTimingModel*>(model(arc, dcalc_ap));
}
void void
DelayCalcBase::finishDrvrPin() DelayCalcBase::finishDrvrPin()
{ {
for (auto parasitic : unsaved_parasitics_)
parasitics_->deleteUnsavedParasitic(parasitic);
unsaved_parasitics_.clear();
for (auto drvr_pin : reduced_parasitic_drvrs_)
parasitics_->deleteDrvrReducedParasitics(drvr_pin);
reduced_parasitic_drvrs_.clear();
}
void
DelayCalcBase::inputPortDelay(const Pin *,
float in_slew,
const RiseFall *rf,
const Parasitic *parasitic,
const DcalcAnalysisPt *)
{
drvr_cell_ = nullptr;
drvr_library_ = network_->defaultLibertyLibrary();
drvr_slew_ = in_slew;
drvr_rf_ = rf;
drvr_parasitic_ = parasitic;
input_port_ = true;
}
void
DelayCalcBase::gateDelayInit(const TimingArc *arc,
const Slew &in_slew,
const Parasitic *drvr_parasitic)
{
drvr_cell_ = arc->from()->libertyCell();
drvr_library_ = drvr_cell_->libertyLibrary();
drvr_rf_ = arc->toEdge()->asRiseFall();
drvr_slew_ = in_slew;
drvr_parasitic_ = drvr_parasitic;
input_port_ = false;
} }
// For DSPF on an input port the elmore delay is used as the time // For DSPF on an input port the elmore delay is used as the time
@ -73,40 +105,47 @@ DelayCalcBase::gateDelayInit(const TimingArc *arc,
// Note that this uses the driver thresholds and relies on // Note that this uses the driver thresholds and relies on
// thresholdAdjust to convert the delay and slew to the load's thresholds. // thresholdAdjust to convert the delay and slew to the load's thresholds.
void void
DelayCalcBase::dspfWireDelaySlew(const Pin *, DelayCalcBase::dspfWireDelaySlew(const Pin *load_pin,
const RiseFall *rf,
Slew drvr_slew,
float elmore, float elmore,
ArcDelay &wire_delay, ArcDelay &wire_delay,
Slew &load_slew) Slew &load_slew)
{ {
float vth = drvr_library_->inputThreshold(drvr_rf_);
float vl = drvr_library_->slewLowerThreshold(drvr_rf_); LibertyLibrary *load_library = thresholdLibrary(load_pin);
float vh = drvr_library_->slewUpperThreshold(drvr_rf_); float vth = load_library->inputThreshold(rf);
float slew_derate = drvr_library_->slewDerateFromLibrary(); float vl = load_library->slewLowerThreshold(rf);
float vh = load_library->slewUpperThreshold(rf);
float slew_derate = load_library->slewDerateFromLibrary();
wire_delay = -elmore * log(1.0 - vth); wire_delay = -elmore * log(1.0 - vth);
load_slew = drvr_slew_ + elmore * log((1.0 - vl) / (1.0 - vh)) / slew_derate; load_slew = drvr_slew + elmore * log((1.0 - vl) / (1.0 - vh)) / slew_derate;
load_slew = drvr_slew + elmore * log((1.0 - vl) / (1.0 - vh)) / slew_derate;
} }
void void
DelayCalcBase::thresholdAdjust(const Pin *load_pin, DelayCalcBase::thresholdAdjust(const Pin *load_pin,
const LibertyLibrary *drvr_library,
const RiseFall *rf,
ArcDelay &load_delay, ArcDelay &load_delay,
Slew &load_slew) Slew &load_slew)
{ {
LibertyLibrary *load_library = thresholdLibrary(load_pin); LibertyLibrary *load_library = thresholdLibrary(load_pin);
if (load_library if (load_library
&& drvr_library_ && drvr_library
&& load_library != drvr_library_) { && load_library != drvr_library) {
float drvr_vth = drvr_library_->outputThreshold(drvr_rf_); float drvr_vth = drvr_library->outputThreshold(rf);
float load_vth = load_library->inputThreshold(drvr_rf_); float load_vth = load_library->inputThreshold(rf);
float drvr_slew_delta = drvr_library_->slewUpperThreshold(drvr_rf_) float drvr_slew_delta = drvr_library->slewUpperThreshold(rf)
- drvr_library_->slewLowerThreshold(drvr_rf_); - drvr_library->slewLowerThreshold(rf);
float load_delay_delta = float load_delay_delta =
delayAsFloat(load_slew) * ((load_vth - drvr_vth) / drvr_slew_delta); delayAsFloat(load_slew) * ((load_vth - drvr_vth) / drvr_slew_delta);
load_delay += (drvr_rf_ == RiseFall::rise()) load_delay += (rf == RiseFall::rise())
? load_delay_delta ? load_delay_delta
: -load_delay_delta; : -load_delay_delta;
float load_slew_delta = load_library->slewUpperThreshold(drvr_rf_) float load_slew_delta = load_library->slewUpperThreshold(rf)
- load_library->slewLowerThreshold(drvr_rf_); - load_library->slewLowerThreshold(rf);
float drvr_slew_derate = drvr_library_->slewDerateFromLibrary(); float drvr_slew_derate = drvr_library->slewDerateFromLibrary();
float load_slew_derate = load_library->slewDerateFromLibrary(); float load_slew_derate = load_library->slewDerateFromLibrary();
load_slew = load_slew * ((load_slew_delta / load_slew_derate) load_slew = load_slew * ((load_slew_delta / load_slew_derate)
/ (drvr_slew_delta / drvr_slew_derate)); / (drvr_slew_delta / drvr_slew_derate));
@ -129,4 +168,55 @@ DelayCalcBase::thresholdLibrary(const Pin *load_pin)
} }
} }
ArcDelay
DelayCalcBase::checkDelay(const Pin *check_pin,
const TimingArc *arc,
const Slew &from_slew,
const Slew &to_slew,
float related_out_cap,
const DcalcAnalysisPt *dcalc_ap)
{
CheckTimingModel *model = checkModel(arc, dcalc_ap);
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,
related_out_cap, pocv_enabled_);
}
else
return delay_zero;
}
string
DelayCalcBase::reportCheckDelay(const Pin *check_pin,
const TimingArc *arc,
const Slew &from_slew,
const char *from_slew_annotation,
const Slew &to_slew,
float related_out_cap,
const DcalcAnalysisPt *dcalc_ap,
int digits)
{
CheckTimingModel *model = checkModel(arc, dcalc_ap);
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 "";
}
const Pvt *
DelayCalcBase::pinPvt(const Pin *pin,
const DcalcAnalysisPt *dcalc_ap)
{
const Instance *drvr_inst = network_->instance(pin);
const Pvt *pvt = sdc_->pvt(drvr_inst, dcalc_ap->constraintMinMax());
if (pvt == nullptr)
pvt = dcalc_ap->operatingConditions();
return pvt;
}
} // namespace } // namespace

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -20,44 +20,64 @@
namespace sta { namespace sta {
class GateTableModel;
class DelayCalcBase : public ArcDelayCalc class DelayCalcBase : public ArcDelayCalc
{ {
public: public:
explicit DelayCalcBase(StaState *sta); explicit DelayCalcBase(StaState *sta);
void inputPortDelay(const Pin *port_pin,
float in_slew,
const RiseFall *rf,
const Parasitic *parasitic,
const DcalcAnalysisPt *dcalc_ap) override;
void finishDrvrPin() override; void finishDrvrPin() override;
void reduceParasitic(const Parasitic *parasitic_network,
const Net *net,
const Corner *corner,
const MinMaxAll *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;
string reportCheckDelay(const Pin *check_pin,
const TimingArc *arc,
const Slew &from_slew,
const char *from_slew_annotation,
const Slew &to_slew,
float related_out_cap,
const DcalcAnalysisPt *dcalc_ap,
int digits) override;
protected: protected:
void gateDelayInit(const TimingArc *arc, GateTimingModel *gateModel(const TimingArc *arc,
const Slew &in_slew, const DcalcAnalysisPt *dcalc_ap) const;
const Parasitic *drvr_parasitic); GateTableModel *gateTableModel(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const;
CheckTimingModel *checkModel(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const;
TimingModel *model(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const;
// Find the liberty library to use for logic/slew thresholds. // Find the liberty library to use for logic/slew thresholds.
LibertyLibrary *thresholdLibrary(const Pin *load_pin); LibertyLibrary *thresholdLibrary(const Pin *load_pin);
// Adjust load_delay and load_slew from driver thresholds to load thresholds. // Adjust load_delay and load_slew from driver thresholds to load thresholds.
void thresholdAdjust(const Pin *load_pin, void thresholdAdjust(const Pin *load_pin,
const LibertyLibrary *drvr_library,
const RiseFall *rf,
ArcDelay &load_delay, ArcDelay &load_delay,
Slew &load_slew); Slew &load_slew);
// Helper function for input ports driving dspf parasitic. // Helper function for input ports driving dspf parasitic.
void dspfWireDelaySlew(const Pin *load_pin, void dspfWireDelaySlew(const Pin *load_pin,
const RiseFall *rf,
Slew drvr_slew,
float elmore, float elmore,
// Return values.
ArcDelay &wire_delay, ArcDelay &wire_delay,
Slew &load_slew); Slew &load_slew);
const Pvt *pinPvt(const Pin *pin,
const DcalcAnalysisPt *dcalc_ap);
Slew drvr_slew_; using ArcDelayCalc::reduceParasitic;
const LibertyCell *drvr_cell_;
const LibertyLibrary *drvr_library_;
const Parasitic *drvr_parasitic_;
bool input_port_;
const RiseFall *drvr_rf_;
// Parasitics returned by findParasitic that are reduced or estimated
// that can be deleted after delay calculation for the driver pin
// is finished.
Vector<Parasitic*> unsaved_parasitics_;
Vector<const Pin *> reduced_parasitic_drvrs_;
}; };
} // namespace } // namespace

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -34,42 +34,36 @@ class DmpCeffDelayCalc : public LumpedCapDelayCalc
public: public:
DmpCeffDelayCalc(StaState *sta); DmpCeffDelayCalc(StaState *sta);
virtual ~DmpCeffDelayCalc(); virtual ~DmpCeffDelayCalc();
virtual void inputPortDelay(const Pin *port_pin, ArcDcalcResult gateDelay(const Pin *drvr_pin,
float in_slew, const TimingArc *arc,
const RiseFall *rf, const Slew &in_slew,
float load_cap,
const Parasitic *parasitic, const Parasitic *parasitic,
const DcalcAnalysisPt *dcalc_ap); const LoadPinIndexMap &load_pin_index_map,
virtual void gateDelay(const TimingArc *arc, const DcalcAnalysisPt *dcalc_ap) override;
string reportGateDelay(const Pin *drvr_pin,
const TimingArc *arc,
const Slew &in_slew, const Slew &in_slew,
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const Parasitic *parasitic,
float related_out_cap, const LoadPinIndexMap &load_pin_index_map,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
// return values int digits) override;
ArcDelay &gate_delay, void copyState(const StaState *sta) override;
Slew &drvr_slew);
virtual float ceff(const TimingArc *arc,
const Slew &in_slew,
float load_cap,
const Parasitic *drvr_parasitic,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap);
virtual string reportGateDelay(const TimingArc *arc,
const Slew &in_slew,
float load_cap,
const Parasitic *drvr_parasitic,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
int digits);
virtual void copyState(const StaState *sta);
protected: protected:
void gateDelaySlew(double &delay, virtual void loadDelaySlew(const Pin *load_pin,
double drvr_slew,
const RiseFall *rf,
const LibertyLibrary *drvr_library,
const Parasitic *parasitic,
// Return values.
ArcDelay &wire_delay,
Slew &load_slew) = 0;
void gateDelaySlew(// Return values.
double &delay,
double &slew); double &slew);
void loadDelaySlew(const Pin *load_pin, void loadDelaySlewElmore(const Pin *load_pin,
double elmore, double elmore,
ArcDelay &delay, ArcDelay &delay,
Slew &slew); Slew &slew);
@ -80,7 +74,6 @@ protected:
const GateTableModel *gate_model, const GateTableModel *gate_model,
const RiseFall *rf, const RiseFall *rf,
double in_slew, double in_slew,
float related_out_cap,
double c2, double c2,
double rpi, double rpi,
double c1); double c1);

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -19,12 +19,13 @@
#include "TableModel.hh" #include "TableModel.hh"
#include "TimingArc.hh" #include "TimingArc.hh"
#include "Liberty.hh" #include "Liberty.hh"
#include "PortDirection.hh"
#include "Network.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
#include "DcalcAnalysisPt.hh" #include "DcalcAnalysisPt.hh"
#include "GraphDelayCalc.hh" #include "GraphDelayCalc.hh"
#include "DmpCeff.hh" #include "DmpCeff.hh"
#include "Network.hh"
namespace sta { namespace sta {
@ -35,7 +36,20 @@ class DmpCeffElmoreDelayCalc : public DmpCeffDelayCalc
public: public:
DmpCeffElmoreDelayCalc(StaState *sta); DmpCeffElmoreDelayCalc(StaState *sta);
ArcDelayCalc *copy() override; ArcDelayCalc *copy() override;
void loadDelay(const Pin *load_pin, 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;
protected:
void loadDelaySlew(const Pin *load_pin,
double drvr_slew,
const RiseFall *rf,
const LibertyLibrary *drvr_library,
const Parasitic *parasitic,
// Return values.
ArcDelay &wire_delay, ArcDelay &wire_delay,
Slew &load_slew) override; Slew &load_slew) override;
}; };
@ -57,26 +71,54 @@ DmpCeffElmoreDelayCalc::copy()
return new DmpCeffElmoreDelayCalc(this); return new DmpCeffElmoreDelayCalc(this);
} }
ArcDcalcResult
DmpCeffElmoreDelayCalc::inputPortDelay(const Pin *,
float in_slew,
const RiseFall *rf,
const Parasitic *parasitic,
const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *)
{
ArcDcalcResult dcalc_result(load_pin_index_map.size());
LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
for (auto load_pin_index : load_pin_index_map) {
const Pin *load_pin = load_pin_index.first;
size_t load_idx = load_pin_index.second;
ArcDelay wire_delay = 0.0;
Slew load_slew = in_slew;
bool elmore_exists = false;
float elmore = 0.0;
if (parasitic)
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);
thresholdAdjust(load_pin, drvr_library, rf, wire_delay, load_slew);
dcalc_result.setWireDelay(load_idx, wire_delay);
dcalc_result.setLoadSlew(load_idx, load_slew);
}
return dcalc_result;
}
void void
DmpCeffElmoreDelayCalc::loadDelay(const Pin *load_pin, DmpCeffElmoreDelayCalc::loadDelaySlew(const Pin *load_pin,
double drvr_slew,
const RiseFall *rf,
const LibertyLibrary *drvr_library,
const Parasitic *parasitic,
// Return values.
ArcDelay &wire_delay, ArcDelay &wire_delay,
Slew &load_slew) Slew &load_slew)
{ {
ArcDelay wire_delay1 = 0.0; wire_delay = 0.0;
Slew load_slew1 = drvr_slew_; load_slew = drvr_slew;
bool elmore_exists = false; bool elmore_exists = false;
float elmore = 0.0; float elmore = 0.0;
if (drvr_parasitic_) if (parasitic)
parasitics_->findElmore(drvr_parasitic_, load_pin, elmore, elmore_exists); parasitics_->findElmore(parasitic, load_pin, elmore, elmore_exists);
if (elmore_exists) { if (elmore_exists)
if (input_port_) loadDelaySlewElmore(load_pin, elmore, wire_delay, load_slew);
dspfWireDelaySlew(load_pin, elmore, wire_delay1, load_slew1); thresholdAdjust(load_pin, drvr_library, rf, wire_delay, load_slew);
else
loadDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
}
thresholdAdjust(load_pin, wire_delay1, load_slew1);
wire_delay = wire_delay1;
load_slew = load_slew1 * multi_drvr_slew_factor_;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -91,28 +133,31 @@ public:
Parasitic *findParasitic(const Pin *drvr_pin, Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override; const DcalcAnalysisPt *dcalc_ap) override;
ReducedParasiticType reducedParasiticType() const override; ArcDcalcResult inputPortDelay(const Pin *port_pin,
void inputPortDelay(const Pin *port_pin,
float in_slew, float in_slew,
const RiseFall *rf, const RiseFall *rf,
const Parasitic *parasitic, const Parasitic *parasitic,
const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap) override; const DcalcAnalysisPt *dcalc_ap) override;
void gateDelay(const TimingArc *arc, ArcDcalcResult gateDelay(const Pin *drvr_pin,
const TimingArc *arc,
const Slew &in_slew, const Slew &in_slew,
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const Parasitic *parasitic,
float related_out_cap, const LoadPinIndexMap &load_pin_index_map,
const Pvt *pvt, const DcalcAnalysisPt *dcalc_ap) override;
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &drvr_slew) override;
void loadDelay(const Pin *load_pin,
ArcDelay &wire_delay,
Slew &load_slew) override;
private: private:
void loadDelay(Parasitic *pole_residue, void loadDelaySlew(const Pin *load_pin,
double drvr_slew,
const RiseFall *rf,
const LibertyLibrary *drvr_library,
const Parasitic *parasitic,
// Return values.
ArcDelay &wire_delay,
Slew &load_slew) override;
void loadDelay(double drvr_slew,
Parasitic *pole_residue,
double p1, double p1,
double k1, double k1,
ArcDelay &wire_delay, ArcDelay &wire_delay,
@ -164,104 +209,117 @@ DmpCeffTwoPoleDelayCalc::findParasitic(const Pin *drvr_pin,
{ {
Parasitic *parasitic = nullptr; Parasitic *parasitic = nullptr;
const Corner *corner = dcalc_ap->corner(); const Corner *corner = dcalc_ap->corner();
// set_load net has precidence over parasitics. // set_load net has precedence over parasitics.
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) { if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|| network_->direction(drvr_pin)->isInternal())
return nullptr;
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt(); const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
if (parasitics_->haveParasitics()) {
// Prefer PiPoleResidue. // Prefer PiPoleResidue.
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap); parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap);
if (parasitic == nullptr) { if (parasitic)
return parasitic;
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap); parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
if (parasitic == nullptr) { if (parasitic)
return parasitic;
Parasitic *parasitic_network = Parasitic *parasitic_network =
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap); parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
if (parasitic_network) { if (parasitic_network) {
parasitics_->reduceToPiPoleResidue2(parasitic_network, drvr_pin, parasitic = parasitics_->reduceToPiPoleResidue2(parasitic_network, drvr_pin, rf,
dcalc_ap->operatingConditions(),
corner, corner,
dcalc_ap->constraintMinMax(), dcalc_ap->constraintMinMax(),
parasitic_ap); parasitic_ap);
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap); if (parasitic)
reduced_parasitic_drvrs_.push_back(drvr_pin); return parasitic;
} }
}
}
}
else {
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax(); const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
Wireload *wireload = sdc_->wireload(cnst_min_max); Wireload *wireload = sdc_->wireload(cnst_min_max);
if (wireload) { if (wireload) {
float pin_cap, wire_cap, fanout; float pin_cap, wire_cap, fanout;
bool has_wire_cap; bool has_wire_cap;
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap, graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap, pin_cap, wire_cap,
pin_cap, wire_cap, fanout, has_wire_cap); fanout, has_wire_cap);
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload, parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload,
fanout, pin_cap, fanout, pin_cap, corner,
dcalc_ap->operatingConditions(), cnst_min_max);
corner,
cnst_min_max,
parasitic_ap);
// Estimated parasitics are not recorded in the "database", so
// save it for deletion after the drvr pin delay calc is finished.
if (parasitic)
unsaved_parasitics_.push_back(parasitic);
}
}
} }
return parasitic; return parasitic;
} }
ReducedParasiticType ArcDcalcResult
DmpCeffTwoPoleDelayCalc::reducedParasiticType() const DmpCeffTwoPoleDelayCalc::inputPortDelay(const Pin *,
{
return ReducedParasiticType::pi_pole_residue2;
}
void
DmpCeffTwoPoleDelayCalc::inputPortDelay(const Pin *port_pin,
float in_slew, float in_slew,
const RiseFall *rf, const RiseFall *rf,
const Parasitic *parasitic, const Parasitic *parasitic,
const DcalcAnalysisPt *dcalc_ap) const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *)
{ {
parasitic_is_pole_residue_ = parasitics_->isPiPoleResidue(parasitic); ArcDcalcResult dcalc_result(load_pin_index_map.size());
DmpCeffDelayCalc::inputPortDelay(port_pin, in_slew, rf, parasitic, dcalc_ap); ArcDelay wire_delay = 0.0;
Slew load_slew = in_slew;
LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
for (auto load_pin_index : load_pin_index_map) {
const Pin *load_pin = load_pin_index.first;
size_t load_idx = load_pin_index.second;
if (parasitics_->isPiPoleResidue(parasitic)) {
const Parasitic *pole_residue = parasitics_->findPoleResidue(parasitic, load_pin);
if (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);
if (pole1.imag() == 0.0
&& residue1.imag() == 0.0) {
float p1 = pole1.real();
float elmore = 1.0F / p1;
dspfWireDelaySlew(load_pin, rf, in_slew, elmore, wire_delay, load_slew);
thresholdAdjust(load_pin, drvr_library, rf, wire_delay, load_slew);
}
}
}
}
dcalc_result.setWireDelay(load_idx, wire_delay);
dcalc_result.setLoadSlew(load_idx, load_slew);
}
return dcalc_result;
} }
void ArcDcalcResult
DmpCeffTwoPoleDelayCalc::gateDelay(const TimingArc *arc, DmpCeffTwoPoleDelayCalc::gateDelay(const Pin *drvr_pin,
const TimingArc *arc,
const Slew &in_slew, const Slew &in_slew,
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const Parasitic *parasitic,
float related_out_cap, const LoadPinIndexMap &load_pin_index_map,
const Pvt *pvt, const DcalcAnalysisPt *dcalc_ap)
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &drvr_slew)
{ {
gateDelayInit(arc, in_slew, drvr_parasitic); const LibertyLibrary *drvr_library = arc->to()->libertyLibrary();
parasitic_is_pole_residue_ = parasitics_->isPiPoleResidue(drvr_parasitic); const RiseFall *rf = arc->toEdge()->asRiseFall();
vth_ = drvr_library_->outputThreshold(drvr_rf_); vth_ = drvr_library->outputThreshold(rf);
vl_ = drvr_library_->slewLowerThreshold(drvr_rf_); vl_ = drvr_library->slewLowerThreshold(rf);
vh_ = drvr_library_->slewUpperThreshold(drvr_rf_); vh_ = drvr_library->slewUpperThreshold(rf);
slew_derate_ = drvr_library_->slewDerateFromLibrary(); slew_derate_ = drvr_library->slewDerateFromLibrary();
DmpCeffDelayCalc::gateDelay(arc, in_slew, load_cap, drvr_parasitic, return DmpCeffDelayCalc::gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic,
related_out_cap, pvt, dcalc_ap, load_pin_index_map, dcalc_ap) ;
gate_delay, drvr_slew);
} }
void void
DmpCeffTwoPoleDelayCalc::loadDelay(const Pin *load_pin, DmpCeffTwoPoleDelayCalc::loadDelaySlew(const Pin *load_pin,
double drvr_slew,
const RiseFall *rf,
const LibertyLibrary *drvr_library,
const Parasitic *parasitic,
// Return values.
ArcDelay &wire_delay, ArcDelay &wire_delay,
Slew &load_slew) Slew &load_slew)
{ {
parasitic_is_pole_residue_ = parasitics_->isPiPoleResidue(parasitic);
// Should handle PiElmore parasitic. // Should handle PiElmore parasitic.
ArcDelay wire_delay1 = 0.0; wire_delay = 0.0;
Slew load_slew1 = drvr_slew_; load_slew = drvr_slew;
Parasitic *pole_residue = 0; Parasitic *pole_residue = 0;
if (parasitic_is_pole_residue_) if (parasitic_is_pole_residue_)
pole_residue = parasitics_->findPoleResidue(drvr_parasitic_, load_pin); pole_residue = parasitics_->findPoleResidue(parasitic, load_pin);
if (pole_residue) { if (pole_residue) {
size_t pole_count = parasitics_->poleResidueCount(pole_residue); size_t pole_count = parasitics_->poleResidueCount(pole_residue);
if (pole_count >= 1) { if (pole_count >= 1) {
@ -272,37 +330,31 @@ DmpCeffTwoPoleDelayCalc::loadDelay(const Pin *load_pin,
&& residue1.imag() == 0.0) { && residue1.imag() == 0.0) {
float p1 = pole1.real(); float p1 = pole1.real();
float k1 = residue1.real(); float k1 = residue1.real();
if (input_port_) {
float elmore = 1.0F / p1;
// Input port with no external driver.
dspfWireDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
}
else {
if (pole_count >= 2) if (pole_count >= 2)
loadDelay(pole_residue, p1, k1, wire_delay1, load_slew1); loadDelay(drvr_slew, pole_residue, p1, k1, wire_delay, load_slew);
else { else {
float elmore = 1.0F / p1; float elmore = 1.0F / p1;
wire_delay1 = elmore; wire_delay = elmore;
load_slew1 = drvr_slew_; load_slew = drvr_slew;
} }
} }
} }
} }
} thresholdAdjust(load_pin, drvr_library, rf, wire_delay, load_slew);
thresholdAdjust(load_pin, wire_delay1, load_slew1);
wire_delay = wire_delay1;
load_slew = load_slew1 * multi_drvr_slew_factor_;
} }
void void
DmpCeffTwoPoleDelayCalc::loadDelay(Parasitic *pole_residue, DmpCeffTwoPoleDelayCalc::loadDelay(double drvr_slew,
double p1, double k1, Parasitic *pole_residue,
double p1,
double k1,
// Return values.
ArcDelay &wire_delay, ArcDelay &wire_delay,
Slew &load_slew) Slew &load_slew)
{ {
ComplexFloat pole2, residue2; ComplexFloat pole2, residue2;
parasitics_->poleResidue(pole_residue, 1, pole2, residue2); parasitics_->poleResidue(pole_residue, 1, pole2, residue2);
if (!delayZero(drvr_slew_) if (!delayZero(drvr_slew)
&& pole2.imag() == 0.0 && pole2.imag() == 0.0
&& residue2.imag() == 0.0) { && residue2.imag() == 0.0) {
double p2 = pole2.real(); double p2 = pole2.real();
@ -311,7 +363,7 @@ DmpCeffTwoPoleDelayCalc::loadDelay(Parasitic *pole_residue,
double k2_p2_2 = k2 / (p2 * p2); double k2_p2_2 = k2 / (p2 * p2);
double B = k1_p1_2 + k2_p2_2; double B = k1_p1_2 + k2_p2_2;
// Convert tt to 0:1 range. // Convert tt to 0:1 range.
float tt = delayAsFloat(drvr_slew_) * slew_derate_ / (vh_ - vl_); float tt = delayAsFloat(drvr_slew) * slew_derate_ / (vh_ - vl_);
double y_tt = (tt - B + k1_p1_2 * exp(-p1 * tt) double y_tt = (tt - B + k1_p1_2 * exp(-p1 * tt)
+ k2_p2_2 * exp(-p2 * tt)) / tt; + k2_p2_2 * exp(-p2 * tt)) / tt;
wire_delay = loadDelay(vth_, p1, p2, k1, k2, B, k1_p1_2, k2_p2_2, tt, y_tt) wire_delay = loadDelay(vth_, p1, p2, k1, k2, B, k1_p1_2, k2_p2_2, tt, y_tt)

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

106
dcalc/FindRoot.cc Normal file
View File

@ -0,0 +1,106 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, 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/>.
#include "FindRoot.hh"
#include <algorithm> // abs
namespace sta {
using std::abs;
double
findRoot(FindRootFunc func,
double x1,
double x2,
double x_tol,
int max_iter,
// Return value.
bool &fail)
{
double y1, y2, dy1;
func(x1, y1, dy1);
func(x2, y2, dy1);
return findRoot(func, x1, y1, x2, y2, x_tol, max_iter, fail);
}
double
findRoot(FindRootFunc func,
double x1,
double y1,
double x2,
double y2,
double x_tol,
int max_iter,
// Return value.
bool &fail)
{
if ((y1 > 0.0 && y2 > 0.0) || (y1 < 0.0 && y2 < 0.0)) {
// Initial bounds do not surround a root.
fail = true;
return 0.0;
}
if (y1 == 0.0) {
fail = false;
return x1;
}
if (y2 == 0.0) {
fail = false;
return x2;
}
if (y1 > 0.0)
// Swap x1/x2 so func(x1) < 0.
std::swap(x1, x2);
double root = (x1 + x2) * 0.5;
double dx_prev = abs(x2 - x1);
double dx = dx_prev;
double y, dy;
func(root, y, dy);
for (int iter = 0; iter < max_iter; iter++) {
// Newton/raphson out of range.
if ((((root - x2) * dy - y) * ((root - x1) * dy - y) > 0.0)
// Not decreasing fast enough.
|| (abs(2.0 * y) > abs(dx_prev * dy))) {
// Bisect x1/x2 interval.
dx_prev = dx;
dx = (x2 - x1) * 0.5;
root = x1 + dx;
}
else {
dx_prev = dx;
dx = y / dy;
root -= dx;
}
if (abs(dx) <= x_tol * abs(root)) {
// Converged.
fail = false;
return root;
}
func(root, y, dy);
if (y < 0.0)
x1 = root;
else
x2 = root;
}
fail = true;
return root;
}
} // namespace

View File

@ -16,12 +16,33 @@
#pragma once #pragma once
#include <functional>
namespace sta { namespace sta {
class ArcDelayCalc; typedef const std::function<void (double x,
class StaState; // Return values.
double &y,
double &dy)> FindRootFunc;
ArcDelayCalc * double
makeSlewDegradeDelayCalc(StaState *sta); findRoot(FindRootFunc func,
double x1,
double x2,
double x_tol,
int max_iter,
// Return value.
bool &fail);
double
findRoot(FindRootFunc func,
double x1,
double y1,
double x2,
double y2,
double x_tol,
int max_iter,
// Return value.
bool &fail);
} // namespace } // namespace

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -23,6 +23,7 @@
#include "TimingArc.hh" #include "TimingArc.hh"
#include "TimingModel.hh" #include "TimingModel.hh"
#include "Liberty.hh" #include "Liberty.hh"
#include "PortDirection.hh"
#include "Network.hh" #include "Network.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
@ -57,176 +58,131 @@ LumpedCapDelayCalc::findParasitic(const Pin *drvr_pin,
{ {
Parasitic *parasitic = nullptr; Parasitic *parasitic = nullptr;
const Corner *corner = dcalc_ap->corner(); const Corner *corner = dcalc_ap->corner();
// set_load net has precidence over parasitics. // set_load net has precedence over parasitics.
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) { if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|| network_->direction(drvr_pin)->isInternal())
return nullptr;
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt(); const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
if (parasitics_->haveParasitics()) {
// Prefer PiElmore. // Prefer PiElmore.
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap); parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
if (parasitic == nullptr) { if (parasitic)
Parasitic *parasitic_network = return parasitic;
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap); Parasitic *parasitic_network = parasitics_->findParasiticNetwork(drvr_pin,
if (parasitic_network) {
parasitics_->reduceToPiElmore(parasitic_network, drvr_pin,
dcalc_ap->operatingConditions(),
corner,
dcalc_ap->constraintMinMax(),
parasitic_ap); parasitic_ap);
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap); if (parasitic_network) {
reduced_parasitic_drvrs_.push_back(drvr_pin); parasitic = reduceParasitic(parasitic_network, drvr_pin, rf, dcalc_ap);
if (parasitic)
return parasitic;
} }
} const MinMax *min_max = dcalc_ap->constraintMinMax();
} Wireload *wireload = sdc_->wireload(min_max);
else {
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
Wireload *wireload = sdc_->wireload(cnst_min_max);
if (wireload) { if (wireload) {
float pin_cap, wire_cap, fanout; float pin_cap, wire_cap, fanout;
bool has_net_load; bool has_net_load;
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap, graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap,
pin_cap, wire_cap, fanout, has_net_load); pin_cap, wire_cap, fanout, has_net_load);
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload, parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload, fanout,
fanout, pin_cap, pin_cap, corner, min_max);
dcalc_ap->operatingConditions(),
corner,
cnst_min_max,
parasitic_ap);
// Estimated parasitics are not recorded in the "database", so save
// it for deletion after the drvr pin delay calc is finished.
if (parasitic)
unsaved_parasitics_.push_back(parasitic);
}
}
} }
return parasitic; return parasitic;
} }
ReducedParasiticType Parasitic *
LumpedCapDelayCalc::reducedParasiticType() const LumpedCapDelayCalc::reduceParasitic(const Parasitic *parasitic_network,
const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap)
{ {
return ReducedParasiticType::pi_elmore; 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);
} }
float ArcDcalcResult
LumpedCapDelayCalc::ceff(const TimingArc *, LumpedCapDelayCalc::inputPortDelay(const Pin *,
const Slew &, float in_slew,
float load_cap, const RiseFall *rf,
const Parasitic *, const Parasitic *,
float, const LoadPinIndexMap &load_pin_index_map,
const Pvt *,
const DcalcAnalysisPt *) const DcalcAnalysisPt *)
{ {
return load_cap; const LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
return makeResult(drvr_library,rf, 0.0, in_slew, load_pin_index_map);
} }
void ArcDcalcResult
LumpedCapDelayCalc::gateDelay(const TimingArc *arc, LumpedCapDelayCalc::gateDelay(const Pin *drvr_pin,
const TimingArc *arc,
const Slew &in_slew, const Slew &in_slew,
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const Parasitic *,
float related_out_cap, const LoadPinIndexMap &load_pin_index_map,
const Pvt *pvt, const DcalcAnalysisPt *dcalc_ap)
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &drvr_slew)
{ {
gateDelayInit(arc, in_slew, drvr_parasitic);
GateTimingModel *model = gateModel(arc, dcalc_ap); GateTimingModel *model = gateModel(arc, dcalc_ap);
debugPrint(debug_, "delay_calc", 3, debugPrint(debug_, "delay_calc", 3,
" in_slew = %s load_cap = %s related_load_cap = %s lumped", " in_slew = %s load_cap = %s lumped",
delayAsString(in_slew, this), delayAsString(in_slew, this),
units()->capacitanceUnit()->asString(load_cap), units()->capacitanceUnit()->asString(load_cap));
units()->capacitanceUnit()->asString(related_out_cap)); const RiseFall *rf = arc->toEdge()->asRiseFall();
const LibertyLibrary *drvr_library = arc->to()->libertyLibrary();
if (model) { if (model) {
ArcDelay gate_delay1; ArcDelay gate_delay;
Slew drvr_slew1; Slew drvr_slew;
float in_slew1 = delayAsFloat(in_slew); float in_slew1 = delayAsFloat(in_slew);
// NaNs cause seg faults during table lookup. // NaNs cause seg faults during table lookup.
if (isnan(load_cap) || isnan(related_out_cap) || isnan(delayAsFloat(in_slew))) if (isnan(load_cap) || isnan(delayAsFloat(in_slew)))
report_->error(710, "gate delay input variable is NaN"); report_->error(1350, "gate delay input variable is NaN");
model->gateDelay(pvt, in_slew1, load_cap, related_out_cap, model->gateDelay(pinPvt(drvr_pin, dcalc_ap), in_slew1, load_cap, pocv_enabled_,
pocv_enabled_, gate_delay1, drvr_slew1); gate_delay, drvr_slew);
gate_delay = gate_delay1; return makeResult(drvr_library, rf, gate_delay, drvr_slew, load_pin_index_map);
drvr_slew = drvr_slew1;
drvr_slew_ = drvr_slew1;
}
else {
gate_delay = delay_zero;
drvr_slew = delay_zero;
drvr_slew_ = 0.0;
} }
else
return makeResult(drvr_library, rf, delay_zero, delay_zero, load_pin_index_map);
} }
void ArcDcalcResult
LumpedCapDelayCalc::loadDelay(const Pin *load_pin, LumpedCapDelayCalc::makeResult(const LibertyLibrary *drvr_library,
ArcDelay &wire_delay, const RiseFall *rf,
Slew &load_slew) ArcDelay gate_delay,
Slew drvr_slew,
const LoadPinIndexMap &load_pin_index_map)
{ {
Delay wire_delay1 = 0.0; ArcDcalcResult dcalc_result(load_pin_index_map.size());
Slew load_slew1 = drvr_slew_ * multi_drvr_slew_factor_; dcalc_result.setGateDelay(gate_delay);
thresholdAdjust(load_pin, wire_delay1, load_slew1); dcalc_result.setDrvrSlew(drvr_slew);
wire_delay = wire_delay1;
load_slew = load_slew1; for (auto load_pin_index : load_pin_index_map) {
const Pin *load_pin = load_pin_index.first;
size_t load_idx = load_pin_index.second;
ArcDelay wire_delay = 0.0;
thresholdAdjust(load_pin, drvr_library, rf, wire_delay, drvr_slew);
dcalc_result.setWireDelay(load_idx, wire_delay);
dcalc_result.setLoadSlew(load_idx, drvr_slew);
}
return dcalc_result;
} }
string string
LumpedCapDelayCalc::reportGateDelay(const TimingArc *arc, LumpedCapDelayCalc::reportGateDelay(const Pin *check_pin,
const TimingArc *arc,
const Slew &in_slew, const Slew &in_slew,
float load_cap, float load_cap,
const Parasitic *, const Parasitic *,
float related_out_cap, const LoadPinIndexMap &,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
int digits) int digits)
{ {
GateTimingModel *model = gateModel(arc, dcalc_ap); GateTimingModel *model = gateModel(arc, dcalc_ap);
if (model) { if (model) {
float in_slew1 = delayAsFloat(in_slew); float in_slew1 = delayAsFloat(in_slew);
return model->reportGateDelay(pvt, in_slew1, load_cap, related_out_cap, return model->reportGateDelay(pinPvt(check_pin, dcalc_ap), in_slew1, load_cap,
false, digits); false, digits);
} }
return ""; return "";
} }
void
LumpedCapDelayCalc::checkDelay(const TimingArc *arc,
const Slew &from_slew,
const Slew &to_slew,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &margin)
{
CheckTimingModel *model = checkModel(arc, dcalc_ap);
if (model) {
float from_slew1 = delayAsFloat(from_slew);
float to_slew1 = delayAsFloat(to_slew);
model->checkDelay(pvt, from_slew1, to_slew1, related_out_cap, pocv_enabled_, margin);
}
else
margin = delay_zero;
}
string
LumpedCapDelayCalc::reportCheckDelay(const TimingArc *arc,
const Slew &from_slew,
const char *from_slew_annotation,
const Slew &to_slew,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
int digits)
{
CheckTimingModel *model = checkModel(arc, dcalc_ap);
if (model) {
float from_slew1 = delayAsFloat(from_slew);
float to_slew1 = delayAsFloat(to_slew);
return model->reportCheckDelay(pvt, from_slew1, from_slew_annotation,
to_slew1, related_out_cap, false, digits);
}
return "";
}
} // namespace } // namespace

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -30,54 +30,40 @@ public:
Parasitic *findParasitic(const Pin *drvr_pin, Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override; const DcalcAnalysisPt *dcalc_ap) override;
ReducedParasiticType reducedParasiticType() const override; Parasitic *reduceParasitic(const Parasitic *parasitic_network,
void gateDelay(const TimingArc *arc, const Pin *drvr_pin,
const Slew &in_slew, const RiseFall *rf,
float load_cap,
const Parasitic *drvr_parasitic,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &drvr_slew) override;
float ceff(const TimingArc *arc,
const Slew &in_slew,
float load_cap,
const Parasitic *drvr_parasitic,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap) override; const DcalcAnalysisPt *dcalc_ap) override;
void loadDelay(const Pin *load_pin, ArcDcalcResult inputPortDelay(const Pin *port_pin,
// Return values. float in_slew,
ArcDelay &wire_delay, const RiseFall *rf,
Slew &load_slew) override; const Parasitic *parasitic,
void checkDelay(const TimingArc *arc, const LoadPinIndexMap &load_pin_index_map,
const Slew &from_slew, const DcalcAnalysisPt *dcalc_ap) override;
const Slew &to_slew, ArcDcalcResult gateDelay(const Pin *drvr_pin,
float related_out_cap, const TimingArc *arc,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &margin) override;
string reportGateDelay(const TimingArc *arc,
const Slew &in_slew, const Slew &in_slew,
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const Parasitic *parasitic,
float related_out_cap, const LoadPinIndexMap &load_pin_index_map,
const Pvt *pvt, const DcalcAnalysisPt *dcalc_ap) override;
const DcalcAnalysisPt *dcalc_ap, string reportGateDelay(const Pin *drvr_pin,
int digits) override; const TimingArc *arc,
string reportCheckDelay(const TimingArc *arc, const Slew &in_slew,
const Slew &from_slew, float load_cap,
const char *from_slew_annotation, const Parasitic *parasitic,
const Slew &to_slew, const LoadPinIndexMap &load_pin_index_map,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
int digits) override; int digits) override;
protected: protected:
ArcDcalcResult makeResult(const LibertyLibrary *drvr_library,
const RiseFall *rf,
ArcDelay gate_delay,
Slew drvr_slew,
const LoadPinIndexMap &load_pin_index_map);
using ArcDelayCalc::reduceParasitic;
}; };
ArcDelayCalc * ArcDelayCalc *

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -31,141 +31,81 @@ ParallelDelayCalc::ParallelDelayCalc(StaState *sta):
{ {
} }
void ArcDcalcResultSeq
ParallelDelayCalc::inputPortDelay(const Pin *drvr_pin, ParallelDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
float in_slew, float load_cap,
const RiseFall *rf, const LoadPinIndexMap &load_pin_index_map,
const Parasitic *parasitic,
const DcalcAnalysisPt *dcalc_ap) const DcalcAnalysisPt *dcalc_ap)
{ {
DelayCalcBase::inputPortDelay(drvr_pin, in_slew, rf, parasitic, dcalc_ap); if (dcalc_args.size() == 1) {
multi_drvr_slew_factor_ = 1.0; ArcDcalcArg &dcalc_arg = dcalc_args[0];
ArcDcalcResult dcalc_result = gateDelay(dcalc_arg.drvrPin(), dcalc_arg.arc(),
dcalc_arg.inSlew(),
load_cap, dcalc_arg.parasitic(),
load_pin_index_map, dcalc_ap);
ArcDcalcResultSeq dcalc_results;
dcalc_results.push_back(dcalc_result);
return dcalc_results;
}
return gateDelaysParallel(dcalc_args, load_cap, load_pin_index_map, dcalc_ap);
} }
void ArcDcalcResultSeq
ParallelDelayCalc::gateDelayInit(const TimingArc *arc, ParallelDelayCalc::gateDelaysParallel(ArcDcalcArgSeq &dcalc_args,
const Slew &in_slew,
const Parasitic *drvr_parasitic)
{
DelayCalcBase::gateDelayInit(arc, in_slew, drvr_parasitic);
multi_drvr_slew_factor_ = 1.0F;
}
void
ParallelDelayCalc::findParallelGateDelays(const MultiDrvrNet *multi_drvr,
GraphDelayCalc *dcalc)
{
int count = RiseFall::index_count * corners_->dcalcAnalysisPtCount();
parallel_delays_.resize(count);
parallel_slews_.resize(count);
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
for (auto drvr_rf : RiseFall::range()) {
DcalcAPIndex ap_index = dcalc_ap->index();
int drvr_rf_index = drvr_rf->index();
int index = ap_index * RiseFall::index_count + drvr_rf_index;
findMultiDrvrGateDelay(multi_drvr, drvr_rf, dcalc_ap, dcalc,
parallel_delays_[index],
parallel_slews_[index]);
}
}
}
void
ParallelDelayCalc::findMultiDrvrGateDelay(const MultiDrvrNet *multi_drvr,
const RiseFall *drvr_rf,
const DcalcAnalysisPt *dcalc_ap,
GraphDelayCalc *dcalc,
// Return values.
ArcDelay &parallel_delay,
Slew &parallel_slew)
{
ArcDelay delay_sum = 0.0;
Slew slew_sum = 0.0;
for (Vertex *drvr_vertex : *multi_drvr->drvrs()) {
Pin *drvr_pin = drvr_vertex->pin();
Instance *drvr_inst = network_->instance(drvr_pin);
const Pvt *pvt = sdc_->pvt(drvr_inst, dcalc_ap->constraintMinMax());
if (pvt == nullptr)
pvt = dcalc_ap->operatingConditions();
VertexInEdgeIterator edge_iter(drvr_vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
TimingArcSet *arc_set = edge->timingArcSet();
const LibertyPort *related_out_port = arc_set->relatedOut();
for (TimingArc *arc : arc_set->arcs()) {
RiseFall *arc_rf = arc->toEdge()->asRiseFall();
if (arc_rf == drvr_rf) {
Vertex *from_vertex = edge->from(graph_);
RiseFall *from_rf = arc->fromEdge()->asRiseFall();
Slew from_slew = dcalc->edgeFromSlew(from_vertex, from_rf,
edge, dcalc_ap);
ArcDelay intrinsic_delay;
Slew intrinsic_slew;
gateDelay(arc, from_slew, 0.0, 0, 0.0, pvt, dcalc_ap,
intrinsic_delay, intrinsic_slew);
Parasitic *parasitic = findParasitic(drvr_pin, drvr_rf, dcalc_ap);
const Pin *related_out_pin = 0;
float related_out_cap = 0.0;
if (related_out_port) {
Instance *inst = network_->instance(drvr_pin);
related_out_pin = network_->findPin(inst, related_out_port);
if (related_out_pin) {
Parasitic *related_out_parasitic = findParasitic(related_out_pin,
drvr_rf,
dcalc_ap);
related_out_cap = dcalc->loadCap(related_out_pin,
related_out_parasitic,
drvr_rf, dcalc_ap);
}
}
float load_cap = dcalc->loadCap(drvr_pin, parasitic,
drvr_rf, dcalc_ap);
ArcDelay gate_delay;
Slew gate_slew;
gateDelay(arc, from_slew, load_cap, parasitic,
related_out_cap, pvt, dcalc_ap,
gate_delay, gate_slew);
delay_sum += 1.0F / (gate_delay - intrinsic_delay);
slew_sum += 1.0F / gate_slew;
}
}
}
}
parallel_delay = 1.0F / delay_sum;
parallel_slew = 1.0F / slew_sum;
}
void
ParallelDelayCalc::parallelGateDelay(const Pin *,
const TimingArc *arc,
const Slew &from_slew,
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const LoadPinIndexMap &load_pin_index_map,
float related_out_cap, const DcalcAnalysisPt *dcalc_ap)
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &gate_slew)
{ {
ArcDelay intrinsic_delay; size_t drvr_count = dcalc_args.size();
Slew intrinsic_slew; ArcDcalcResultSeq dcalc_results(drvr_count);
gateDelay(arc, from_slew, 0.0, 0, 0.0, pvt, dcalc_ap, Slew slew_sum = 0.0;
intrinsic_delay, intrinsic_slew); ArcDelay load_delay_sum = 0.0;
const RiseFall *drvr_rf = arc->toEdge()->asRiseFall(); vector<ArcDelay> intrinsic_delays(dcalc_args.size());
int index = dcalc_ap->index() * RiseFall::index_count + drvr_rf->index(); vector<ArcDelay> load_delays(dcalc_args.size());
ArcDelay parallel_delay = parallel_delays_[index]; for (size_t drvr_idx = 0; drvr_idx < drvr_count; drvr_idx++) {
Slew parallel_slew = parallel_slews_[index]; ArcDcalcArg &dcalc_arg = dcalc_args[drvr_idx];
gate_delay = parallel_delay + intrinsic_delay; ArcDcalcResult &dcalc_result = dcalc_results[drvr_idx];
gate_slew = parallel_slew; const Pin *drvr_pin = dcalc_arg.drvrPin();
const TimingArc *arc = dcalc_arg.arc();
Slew in_slew = dcalc_arg.inSlew();
Delay gate_delay1; ArcDcalcResult intrinsic_result = gateDelay(drvr_pin, arc, in_slew, 0.0, nullptr,
Slew gate_slew1; load_pin_index_map, dcalc_ap);
gateDelay(arc, from_slew, load_cap, drvr_parasitic, ArcDelay intrinsic_delay = intrinsic_result.gateDelay();
related_out_cap, pvt, dcalc_ap, intrinsic_delays[drvr_idx] = intrinsic_result.gateDelay();
gate_delay1, gate_slew1);
float factor = delayRatio(gate_slew, gate_slew1); ArcDcalcResult gate_result = gateDelay(drvr_pin, arc, in_slew, load_cap,
multi_drvr_slew_factor_ = factor; dcalc_arg.parasitic(),
load_pin_index_map, dcalc_ap);
ArcDelay gate_delay = gate_result.gateDelay();
Slew drvr_slew = gate_result.drvrSlew();
ArcDelay load_delay = gate_delay - intrinsic_delay;
load_delays[drvr_idx] = load_delay;
if (!delayZero(load_delay))
load_delay_sum += 1.0 / load_delay;
if (!delayZero(drvr_slew))
slew_sum += 1.0 / drvr_slew;
dcalc_result.setLoadCount(load_pin_index_map.size());
for (auto load_pin_index : load_pin_index_map) {
size_t load_idx = load_pin_index.second;
dcalc_result.setWireDelay(load_idx, gate_result.wireDelay(load_idx));
dcalc_result.setLoadSlew(load_idx, gate_result.loadSlew(load_idx));
}
}
ArcDelay gate_load_delay = delayZero(load_delay_sum)
? delay_zero
: 1.0 / load_delay_sum;
ArcDelay drvr_slew = delayZero(slew_sum) ? delay_zero : 1.0 / slew_sum;
for (size_t drvr_idx = 0; drvr_idx < drvr_count; drvr_idx++) {
ArcDcalcResult &dcalc_result = dcalc_results[drvr_idx];
dcalc_result.setGateDelay(intrinsic_delays[drvr_idx] + gate_load_delay);
dcalc_result.setDrvrSlew(drvr_slew);
}
return dcalc_results;
} }
} // namespace } // namespace

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -17,52 +17,26 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <map>
#include "DelayCalcBase.hh" #include "DelayCalcBase.hh"
namespace sta { namespace sta {
// Delay calculation for parallel gates based on using parallel drive resistance. // Delay calculation for parallel gates using parallel drive resistance.
class ParallelDelayCalc : public DelayCalcBase class ParallelDelayCalc : public DelayCalcBase
{ {
public: public:
explicit ParallelDelayCalc(StaState *sta); ParallelDelayCalc(StaState *sta);
void inputPortDelay(const Pin *port_pin, ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &dcalc_args,
float in_slew,
const RiseFall *rf,
const Parasitic *parasitic,
const DcalcAnalysisPt *dcalc_ap) override;
void gateDelayInit(const TimingArc *arc,
const Slew &in_slew,
const Parasitic *drvr_parasitic);
void findParallelGateDelays(const MultiDrvrNet *multi_drvr,
GraphDelayCalc *dcalc) override;
void parallelGateDelay(const Pin *drvr_pin,
const TimingArc *arc,
const Slew &from_slew,
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const LoadPinIndexMap &load_pin_index_map,
float related_out_cap, const DcalcAnalysisPt *dcalc_ap) override;
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &gate_slew) override;
protected: protected:
void findMultiDrvrGateDelay(const MultiDrvrNet *multi_drvr, ArcDcalcResultSeq gateDelaysParallel(ArcDcalcArgSeq &dcalc_args,
const RiseFall *drvr_rf, float load_cap,
const DcalcAnalysisPt *dcalc_ap, const LoadPinIndexMap &load_pin_index_map,
GraphDelayCalc *dcalc, const DcalcAnalysisPt *dcalc_ap);
// Return values.
ArcDelay &parallel_delay,
Slew &parallel_slew);
// [drvr_rf->index][dcalc_ap->index]
vector<ArcDelay> parallel_delays_;
// [drvr_rf->index][dcalc_ap->index]
vector<Slew> parallel_slews_;
float multi_drvr_slew_factor_;
}; };
} // namespace } // namespace

View File

@ -1,141 +0,0 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, 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/>.
#include "SlewDegradeDelayCalc.hh"
#include "TimingArc.hh"
#include "Liberty.hh"
#include "Network.hh"
#include "Sdc.hh"
#include "Parasitics.hh"
#include "DcalcAnalysisPt.hh"
#include "LumpedCapDelayCalc.hh"
namespace sta {
// Liberty table model lumped capacitance arc delay calculator.
// Effective capacitance is the pi model total capacitance (C1+C2).
// Wire delays are elmore delays.
// Driver slews are degraded to loads by rise/fall transition_degradation
// tables.
class SlewDegradeDelayCalc : public LumpedCapDelayCalc
{
public:
SlewDegradeDelayCalc(StaState *sta);
ArcDelayCalc *copy() override;
void inputPortDelay(const Pin *port_pin,
float in_slew,
const RiseFall *rf,
const Parasitic *parasitic,
const DcalcAnalysisPt *dcalc_ap) override;
void gateDelay(const TimingArc *arc,
const Slew &in_slew,
float load_cap,
const Parasitic *drvr_parasitic,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &drvr_slew) override;
void loadDelay(const Pin *load_pin,
ArcDelay &wire_delay,
Slew &load_slew) override;
using LumpedCapDelayCalc::gateDelay;
using LumpedCapDelayCalc::reportGateDelay;
private:
const Pvt *pvt_;
};
ArcDelayCalc *
makeSlewDegradeDelayCalc(StaState *sta)
{
return new SlewDegradeDelayCalc(sta);
}
SlewDegradeDelayCalc::SlewDegradeDelayCalc(StaState *sta) :
LumpedCapDelayCalc(sta)
{
}
ArcDelayCalc *
SlewDegradeDelayCalc::copy()
{
return new SlewDegradeDelayCalc(this);
}
void
SlewDegradeDelayCalc::inputPortDelay(const Pin *port_pin,
float in_slew,
const RiseFall *rf,
const Parasitic *parasitic,
const DcalcAnalysisPt *dcalc_ap)
{
pvt_ = dcalc_ap->operatingConditions();
LumpedCapDelayCalc::inputPortDelay(port_pin, in_slew, rf, parasitic, dcalc_ap);
}
void
SlewDegradeDelayCalc::gateDelay(const TimingArc *arc,
const Slew &in_slew,
float load_cap,
const Parasitic *drvr_parasitic,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &drvr_slew)
{
input_port_ = false;
drvr_parasitic_ = drvr_parasitic;
drvr_rf_ = arc->toEdge()->asRiseFall();
drvr_cell_ = arc->from()->libertyCell();
drvr_library_ = drvr_cell_->libertyLibrary();
pvt_ = pvt;
LumpedCapDelayCalc::gateDelay(arc, in_slew, load_cap, drvr_parasitic,
related_out_cap, pvt, dcalc_ap,
gate_delay, drvr_slew);
}
void
SlewDegradeDelayCalc::loadDelay(const Pin *load_pin,
ArcDelay &wire_delay,
Slew &load_slew)
{
ArcDelay wire_delay1 = 0.0;
Slew load_slew1 = drvr_slew_;
bool elmore_exists = false;
float elmore = 0.0;
if (drvr_parasitic_)
parasitics_->findElmore(drvr_parasitic_, load_pin, elmore, elmore_exists);
if (elmore_exists) {
if (drvr_library_ && drvr_library_->wireSlewDegradationTable(drvr_rf_)) {
wire_delay1 = elmore;
load_slew1 = drvr_library_->degradeWireSlew(drvr_rf_,
delayAsFloat(drvr_slew_),
delayAsFloat(wire_delay1));
}
dspfWireDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
}
thresholdAdjust(load_pin, wire_delay1, load_slew1);
wire_delay = wire_delay1;
load_slew = load_slew1 * multi_drvr_slew_factor_;
}
} // namespace

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -45,86 +45,82 @@ UnitDelayCalc::findParasitic(const Pin *,
return nullptr; return nullptr;
} }
ReducedParasiticType Parasitic *
UnitDelayCalc::reducedParasiticType() const UnitDelayCalc::reduceParasitic(const Parasitic *,
const Pin *,
const RiseFall *,
const DcalcAnalysisPt *)
{ {
return ReducedParasiticType::none; return nullptr;
} }
void void
UnitDelayCalc::reduceParasitic(const Parasitic *,
const Net *,
const Corner *,
const MinMaxAll *)
{
}
ArcDcalcResult
UnitDelayCalc::inputPortDelay(const Pin *, UnitDelayCalc::inputPortDelay(const Pin *,
float, float,
const RiseFall *, const RiseFall *,
const Parasitic *, const Parasitic *,
const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *) const DcalcAnalysisPt *)
{ {
return unitDelayResult(load_pin_index_map);
} }
void ArcDcalcResult
UnitDelayCalc::gateDelay(const TimingArc *, UnitDelayCalc::gateDelay(const Pin *,
const Slew &,
float,
const Parasitic *,
float,
const Pvt *, const DcalcAnalysisPt *,
// Return values.
ArcDelay &gate_delay, Slew &drvr_slew)
{
gate_delay = units_->timeUnit()->scale();
drvr_slew = 0.0;
}
void
UnitDelayCalc::findParallelGateDelays(const MultiDrvrNet *,
GraphDelayCalc *)
{
}
void
UnitDelayCalc::parallelGateDelay(const Pin *,
const TimingArc *, const TimingArc *,
const Slew &, const Slew &,
float, float,
const Parasitic *, const Parasitic *,
float, const LoadPinIndexMap &load_pin_index_map,
const Pvt *,
const DcalcAnalysisPt *,
// Return values.
ArcDelay &gate_delay,
Slew &gate_slew)
{
gate_delay = units_->timeUnit()->scale();
gate_slew = 0.0;
}
void
UnitDelayCalc::loadDelay(const Pin *,
ArcDelay &wire_delay,
Slew &load_slew)
{
wire_delay = 0.0;
load_slew = 0.0;
}
float
UnitDelayCalc::ceff(const TimingArc *,
const Slew &,
float,
const Parasitic *,
float,
const Pvt *,
const DcalcAnalysisPt *) const DcalcAnalysisPt *)
{ {
return 0.0; return unitDelayResult(load_pin_index_map);
}
ArcDcalcResultSeq
UnitDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
float,
const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *)
{
size_t drvr_count = dcalc_args.size();
ArcDcalcResultSeq dcalc_results(drvr_count);
for (size_t drvr_idx = 0; drvr_idx < drvr_count; drvr_idx++) {
ArcDcalcResult &dcalc_result = dcalc_results[drvr_idx];
dcalc_result = unitDelayResult(load_pin_index_map);
}
return dcalc_results;
}
ArcDcalcResult
UnitDelayCalc::unitDelayResult(const LoadPinIndexMap &load_pin_index_map)
{
size_t load_count = load_pin_index_map.size();
ArcDcalcResult dcalc_result(load_count);
dcalc_result.setGateDelay(units_->timeUnit()->scale());
dcalc_result.setDrvrSlew(0.0);
for (size_t load_idx = 0; load_idx < load_count; load_idx++) {
dcalc_result.setWireDelay(load_idx, 0.0);
dcalc_result.setLoadSlew(load_idx, 0.0);
}
return dcalc_result;
} }
string string
UnitDelayCalc::reportGateDelay(const TimingArc *, UnitDelayCalc::reportGateDelay(const Pin *,
const TimingArc *,
const Slew &, const Slew &,
float, float,
const Parasitic *, const Parasitic *,
float, const LoadPinIndexMap &,
const Pvt *,
const DcalcAnalysisPt *, const DcalcAnalysisPt *,
int) int)
{ {
@ -133,26 +129,24 @@ UnitDelayCalc::reportGateDelay(const TimingArc *,
return result; return result;
} }
void ArcDelay
UnitDelayCalc::checkDelay(const TimingArc *, UnitDelayCalc::checkDelay(const Pin *,
const TimingArc *,
const Slew &, const Slew &,
const Slew &, const Slew &,
float, float,
const Pvt *, const DcalcAnalysisPt *)
const DcalcAnalysisPt *,
// Return values.
ArcDelay &margin)
{ {
margin = units_->timeUnit()->scale(); return units_->timeUnit()->scale();
} }
string string
UnitDelayCalc::reportCheckDelay(const TimingArc *, UnitDelayCalc::reportCheckDelay(const Pin *,
const TimingArc *,
const Slew &, const Slew &,
const char *, const char *,
const Slew &, const Slew &,
float, float,
const Pvt *,
const DcalcAnalysisPt *, const DcalcAnalysisPt *,
int) int)
{ {

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -29,72 +29,58 @@ public:
Parasitic *findParasitic(const Pin *drvr_pin, Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override; const DcalcAnalysisPt *dcalc_ap) override;
ReducedParasiticType reducedParasiticType() const override; Parasitic *reduceParasitic(const Parasitic *parasitic_network,
void inputPortDelay(const Pin *port_pin, const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override;
void reduceParasitic(const Parasitic *parasitic_network,
const Net *net,
const Corner *corner,
const MinMaxAll *min_max) override;
ArcDcalcResult inputPortDelay(const Pin *port_pin,
float in_slew, float in_slew,
const RiseFall *rf, const RiseFall *rf,
const Parasitic *parasitic, const Parasitic *parasitic,
const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap) override; const DcalcAnalysisPt *dcalc_ap) override;
void gateDelay(const TimingArc *arc, ArcDcalcResult gateDelay(const Pin *drvr_pin,
const Slew &in_slew,
float load_cap,
const Parasitic *drvr_parasitic,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &drvr_slew) override;
void findParallelGateDelays(const MultiDrvrNet *multi_drvr,
GraphDelayCalc *dcalc) override;
// Retrieve the delay and slew for one parallel gate.
void parallelGateDelay(const Pin *drvr_pin,
const TimingArc *arc, const TimingArc *arc,
const Slew &from_slew,
float load_cap,
const Parasitic *drvr_parasitic,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &gate_slew) override;
void loadDelay(const Pin *load_pin,
// Return values.
ArcDelay &wire_delay,
Slew &load_slew) override;
float ceff(const TimingArc *arc,
const Slew &in_slew, const Slew &in_slew,
// Pass in load_cap or parasitic.
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const Parasitic *parasitic,
float related_out_cap, const LoadPinIndexMap &load_pin_index_map,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap) override; const DcalcAnalysisPt *dcalc_ap) override;
void checkDelay(const TimingArc *arc, ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &args,
float load_cap,
const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap) override;
ArcDelay checkDelay(const Pin *check_pin,
const TimingArc *arc,
const Slew &from_slew, const Slew &from_slew,
const Slew &to_slew, const Slew &to_slew,
float related_out_cap, float related_out_cap,
const Pvt *pvt, const DcalcAnalysisPt *dcalc_ap) override;
const DcalcAnalysisPt *dcalc_ap, string reportGateDelay(const Pin *drvr_pin,
// Return values. const TimingArc *arc,
ArcDelay &margin) override;
string reportGateDelay(const TimingArc *arc,
const Slew &in_slew, const Slew &in_slew,
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const Parasitic *parasitic,
float related_out_cap, const LoadPinIndexMap &load_pin_index_map,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
int digits) override; int digits) override;
string reportCheckDelay(const TimingArc *arc, string reportCheckDelay(const Pin *check_pin,
const TimingArc *arc,
const Slew &from_slew, const Slew &from_slew,
const char *from_slew_annotation, const char *from_slew_annotation,
const Slew &to_slew, const Slew &to_slew,
float related_out_cap, float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
int digits) override; int digits) override;
void finishDrvrPin() override; void finishDrvrPin() override;
protected:
ArcDcalcResult unitDelayResult(const LoadPinIndexMap &load_pin_index_map);
}; };
ArcDelayCalc * ArcDelayCalc *

View File

@ -1,5 +1,5 @@
# OpenSTA, Static Timing Analyzer # OpenSTA, Static Timing Analyzer
# Copyright (c) 2023, Parallax Software, Inc. # Copyright (c) 2024, Parallax Software, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

52
doc/CLA.txt Normal file
View File

@ -0,0 +1,52 @@
Parallax Software maintains a responsible open source policy and
promotes good practices in intellectual property management. Please
read this Agreement carefully. By submitting your Contributions (see
definition below) and clicking ["Sign in with GitHub to agree"], you
agree to all of the terms and conditions defined herein.
Parallax Software, Inc. appreciates your willingness to grant
permission to use your software code checked directly into a source
control system that is available by GitHub Inc ("Contributions") in
conjunction with OpenSTA. By clicking ["Sign in with GitHub to
agree"], you hereby grant to Parallax Software and to recipients of
software distributed with OpenSTA a perpetual, worldwide,
non-exclusive, no-charge, royalty-free, irrevocable license to use,
make, have made, offer to sell, sell, import, reproduce, prepare
derivative works of, publicly display, publicly perform, sublicense,
and distribute your present and future Contributions and such
derivative works as part of OpenSTA.
Nothing in this license shall constitute a copyright transfer or in
any other way infringe your rights to use your own Contributions for
any other purpose. This license is for your protection as a
Contributor as well as the protection of OpenSTA and its users.
1. You represent and warrant that you are the sole owner of the
Contributions and/or have sufficient rights in your Contribution to
grant all rights you grant hereunder.
2. You represent that the Contributions are your original works of
authorship, that you created the Contributions and did not copy them
from another source, and no other person claims, or has the right to
claim, any right in any invention or patent related to the
Contributions.
3. You represent that you are legally entitled to grant the above
license. If your employer has rights to intellectual property that you
create, you represent that you have received permission to make the
Contributions on behalf of that employer, or that your employer has
waived such rights for the Contributions.
4. Finally, it means that you have not entered into any agreements
that would prevent you from granting the rights provided in this
Agreement.
5. You understand that the decision to include the Contribution in any
product or source repository is entirely that of Parallax Software and
this Agreement does not guarantee that the Contributions will be
included in any product, technology or services.
If you become aware of any facts or circumstances related to the
representation above that would make these representations inaccurate
or untrue, you agree to notify Parallax Software promptly with any
details.

View File

@ -3,6 +3,19 @@ OpenSTA Timing Analyzer Release Notes
This file summarizes user visible changes for each release. This file summarizes user visible changes for each release.
Release 2.5.0 2024/01/17
-------------------------
The report_net -connections, -verbose and -hier_pins flags are deprecated.
The report_instance -connections and -verbose flags are deprecated.
The options are now enabled in all cases.
The read_spef parasitic reduction arguments have changed. The
-reduce_to and -delete_after_reduce arguments are deprecated and
replaced with the -reduce flag. With the -reduce flag, the current
delay calculator reduces the parastic network to the appropriate type
and deletes the parasitic network.
Release 2.4.0 2023/01/19 Release 2.4.0 2023/01/19
------------------------- -------------------------

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
# OpenSTA, Static Timing Analyzer # OpenSTA, Static Timing Analyzer
# Copyright (c) 2023, Parallax Software, Inc. # Copyright (c) 2024, Parallax Software, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
exec tclsh $0 ${1+"$@"} exec tclsh $0 ${1+"$@"}
# OpenSTA, Static Timing Analyzer # OpenSTA, Static Timing Analyzer
# Copyright (c) 2023, Parallax Software, Inc. # Copyright (c) 2024, Parallax Software, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -200,7 +200,7 @@ delayAsFloat(const Delay &delay,
else if (early_late == EarlyLate::late()) else if (early_late == EarlyLate::late())
return delay.mean() + delay.sigma() * sta->sigmaFactor(); return delay.mean() + delay.sigma() * sta->sigmaFactor();
else else
sta->report()->critical(594, "unknown early/late value."); sta->report()->critical(1020, "unknown early/late value.");
} }
return delay.mean(); return delay.mean();
} }

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -375,7 +375,7 @@ delayAsFloat(const Delay &delay,
else if (early_late == EarlyLate::late()) else if (early_late == EarlyLate::late())
return delay.mean() + delay.sigma(early_late) * sta->sigmaFactor(); return delay.mean() + delay.sigma(early_late) * sta->sigmaFactor();
else else
sta->report()->critical(595, "unknown early/late value."); sta->report()->critical(1030, "unknown early/late value.");
} }
return delay.mean(); return delay.mean();
} }

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -106,7 +106,7 @@ public:
int &bidirect_count, int &bidirect_count,
int &load_count, int &load_count,
const Network *network); const Network *network);
virtual void operator()(Pin *pin); virtual void operator()(const Pin *pin);
protected: protected:
Pin *drvr_pin_; Pin *drvr_pin_;
@ -133,7 +133,7 @@ FindNetDrvrLoadCounts::FindNetDrvrLoadCounts(Pin *drvr_pin,
} }
void void
FindNetDrvrLoadCounts::operator()(Pin *pin) FindNetDrvrLoadCounts::operator()(const Pin *pin)
{ {
if (network_->isDriver(pin)) { if (network_->isDriver(pin)) {
if (pin != drvr_pin_) if (pin != drvr_pin_)
@ -790,7 +790,7 @@ Graph::arcDelayAnnotated(const Edge *edge,
if (arc_delay_annotated_.size()) { if (arc_delay_annotated_.size()) {
size_t index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index; size_t index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index;
if (index >= arc_delay_annotated_.size()) if (index >= arc_delay_annotated_.size())
report_->critical(208, "arc_delay_annotated array bounds exceeded"); report_->critical(1080, "arc_delay_annotated array bounds exceeded");
return arc_delay_annotated_[index]; return arc_delay_annotated_[index];
} }
else else
@ -805,7 +805,7 @@ Graph::setArcDelayAnnotated(Edge *edge,
{ {
size_t index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index; size_t index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index;
if (index >= arc_delay_annotated_.size()) if (index >= arc_delay_annotated_.size())
report_->critical(209, "arc_delay_annotated array bounds exceeded"); report_->critical(1081, "arc_delay_annotated array bounds exceeded");
arc_delay_annotated_[index] = annotated; arc_delay_annotated_[index] = annotated;
} }
@ -817,7 +817,7 @@ Graph::wireDelayAnnotated(Edge *edge,
size_t index = (edge->arcDelays() + TimingArcSet::wireArcIndex(rf)) * ap_count_ size_t index = (edge->arcDelays() + TimingArcSet::wireArcIndex(rf)) * ap_count_
+ ap_index; + ap_index;
if (index >= arc_delay_annotated_.size()) if (index >= arc_delay_annotated_.size())
report_->critical(210, "arc_delay_annotated array bounds exceeded"); report_->critical(1082, "arc_delay_annotated array bounds exceeded");
return arc_delay_annotated_[index]; return arc_delay_annotated_[index];
} }
@ -830,7 +830,7 @@ Graph::setWireDelayAnnotated(Edge *edge,
size_t index = (edge->arcDelays() + TimingArcSet::wireArcIndex(rf)) * ap_count_ size_t index = (edge->arcDelays() + TimingArcSet::wireArcIndex(rf)) * ap_count_
+ ap_index; + ap_index;
if (index >= arc_delay_annotated_.size()) if (index >= arc_delay_annotated_.size())
report_->critical(228, "arc_delay_annotated array bounds exceeded"); report_->critical(1083, "arc_delay_annotated array bounds exceeded");
arc_delay_annotated_[index] = annotated; arc_delay_annotated_[index] = annotated;
} }

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -18,10 +18,14 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
#include "MinMax.hh" #include "MinMax.hh"
#include "LibertyClass.hh" #include "LibertyClass.hh"
#include "TimingArc.hh"
#include "TableModel.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
#include "GraphClass.hh"
#include "Delay.hh" #include "Delay.hh"
#include "ParasiticsClass.hh" #include "ParasiticsClass.hh"
#include "StaState.hh" #include "StaState.hh"
@ -30,18 +34,77 @@ namespace sta {
using std::string; using std::string;
using std::vector; using std::vector;
using std::map;
class Corner;
class Parasitic; class Parasitic;
class DcalcAnalysisPt; class DcalcAnalysisPt;
class MultiDrvrNet; class MultiDrvrNet;
// Driver load pin -> index in driver loads.
typedef map<const Pin *, size_t, PinIdLess> LoadPinIndexMap;
// Arguments for gate delay calculation delay/slew at one driver pin
// through one timing arc at one delay calc analysis point.
class ArcDcalcArg
{
public:
ArcDcalcArg();
ArcDcalcArg(const Pin *drvr_pin,
Edge *edge,
const TimingArc *arc,
const Slew in_slew,
const Parasitic *parasitic);
const Pin *drvrPin() const { return drvr_pin_; }
Edge *edge() const { return edge_; }
const TimingArc *arc() const { return arc_; }
Slew inSlew() const { return in_slew_; }
const Parasitic *parasitic() { return parasitic_; }
void setParasitic(const Parasitic *parasitic);
protected:
const Pin *drvr_pin_;
Edge *edge_;
const TimingArc *arc_;
Slew in_slew_;
const Parasitic *parasitic_;
};
// Arc delay calc result.
class ArcDcalcResult
{
public:
ArcDcalcResult();
ArcDcalcResult(size_t load_count);
void setLoadCount(size_t load_count);
ArcDelay &gateDelay() { return gate_delay_; }
void setGateDelay(ArcDelay gate_delay);
Slew &drvrSlew() { return drvr_slew_; }
void setDrvrSlew(Slew drvr_slew);
ArcDelay wireDelay(size_t load_idx) const;
void setWireDelay(size_t load_idx,
ArcDelay wire_delay);
Slew loadSlew(size_t load_idx) const;
void setLoadSlew(size_t load_idx,
Slew load_slew);
protected:
ArcDelay gate_delay_;
Slew drvr_slew_;
// Load wire delay and slews indexed by load pin index.
vector<ArcDelay> wire_delays_;
vector<Slew> load_slews_;
};
typedef vector<ArcDcalcArg> ArcDcalcArgSeq;
typedef vector<ArcDcalcResult> ArcDcalcResultSeq;
// Delay calculator class hierarchy. // Delay calculator class hierarchy.
// ArcDelayCalc // ArcDelayCalc
// UnitDelayCalc // UnitDelayCalc
// DelayCalcBase // DelayCalcBase
// ParallelDelayCalc // ParallelDelayCalc
// LumpedCapDelayCalc // LumpedCapDelayCalc
// SlewDegradeDelayCalc
// DmpCeffDelayCalc // DmpCeffDelayCalc
// DmpCeffElmoreDelayCalc // DmpCeffElmoreDelayCalc
// DmpCeffTwoPoleDelayCalc // DmpCeffTwoPoleDelayCalc
@ -61,95 +124,80 @@ public:
virtual Parasitic *findParasitic(const Pin *drvr_pin, virtual Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) = 0; const DcalcAnalysisPt *dcalc_ap) = 0;
virtual ReducedParasiticType reducedParasiticType() 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;
// 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.
virtual void reduceParasitic(const Parasitic *parasitic_network,
const Net *net,
const Corner *corner,
const MinMaxAll *min_max) = 0;
// Find the wire delays and slews for an input port without a driving cell. // Find the wire delays and slews for an input port without a driving cell.
// This call primarily initializes the load delay/slew iterator. // This call primarily initializes the load delay/slew iterator.
virtual void inputPortDelay(const Pin *port_pin, virtual ArcDcalcResult inputPortDelay(const Pin *port_pin,
float in_slew, float in_slew,
const RiseFall *rf, const RiseFall *rf,
const Parasitic *parasitic, const Parasitic *parasitic,
const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap) = 0; const DcalcAnalysisPt *dcalc_ap) = 0;
// Find the delay and slew for arc driving drvr_pin. // Find the delay and slew for arc driving drvr_pin.
virtual ArcDcalcResult gateDelay(const Pin *drvr_pin,
const TimingArc *arc,
const Slew &in_slew,
// Pass in load_cap or parasitic.
float load_cap,
const Parasitic *parasitic,
const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap) = 0;
virtual void gateDelay(const TimingArc *arc, virtual void gateDelay(const TimingArc *arc,
const Slew &in_slew, const Slew &in_slew,
// Pass in load_cap or drvr_parasitic.
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const Parasitic *parasitic,
float related_out_cap, float related_out_cap,
const Pvt *pvt, const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
// Return values. // Return values.
ArcDelay &gate_delay, ArcDelay &gate_delay,
Slew &drvr_slew) = 0; Slew &drvr_slew) __attribute__ ((deprecated));
// Find gate delays and slews for parallel gates. // Find gate delays and slews for parallel gates.
virtual void findParallelGateDelays(const MultiDrvrNet *multi_drvr, virtual ArcDcalcResultSeq gateDelays(ArcDcalcArgSeq &args,
GraphDelayCalc *dcalc) = 0;
// Retrieve the delay and slew for one parallel gate.
virtual void parallelGateDelay(const Pin *drvr_pin,
const TimingArc *arc,
const Slew &from_slew,
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const LoadPinIndexMap &load_pin_index_map,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &gate_delay,
Slew &gate_slew) = 0;
// Find the wire delay and load slew of a load pin.
// Called after inputPortDelay or gateDelay.
virtual void loadDelay(const Pin *load_pin,
// Return values.
ArcDelay &wire_delay,
Slew &load_slew) = 0;
// Ceff for parasitics with pi models.
virtual float ceff(const TimingArc *arc,
const Slew &in_slew,
float load_cap,
const Parasitic *drvr_parasitic,
float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap) = 0; const DcalcAnalysisPt *dcalc_ap) = 0;
// Find the delay for a timing check arc given the arc's // Find the delay for a timing check arc given the arc's
// from/clock, to/data slews and related output pin parasitic. // from/clock, to/data slews and related output pin parasitic.
virtual void checkDelay(const TimingArc *arc, virtual ArcDelay checkDelay(const Pin *check_pin,
const TimingArc *arc,
const Slew &from_slew, const Slew &from_slew,
const Slew &to_slew, const Slew &to_slew,
float related_out_cap, float related_out_cap,
const Pvt *pvt, const DcalcAnalysisPt *dcalc_ap) = 0;
const DcalcAnalysisPt *dcalc_ap,
// Return values.
ArcDelay &margin) = 0;
// Report delay and slew calculation. // Report delay and slew calculation.
virtual string reportGateDelay(const TimingArc *arc, virtual string reportGateDelay(const Pin *drvr_pin,
const TimingArc *arc,
const Slew &in_slew, const Slew &in_slew,
// Pass in load_cap or drvr_parasitic.
float load_cap, float load_cap,
const Parasitic *drvr_parasitic, const Parasitic *parasitic,
float related_out_cap, const LoadPinIndexMap &load_pin_index_map,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
int digits) = 0; int digits) = 0;
// Report timing check delay calculation. // Report timing check delay calculation.
virtual string reportCheckDelay(const TimingArc *arc, virtual string reportCheckDelay(const Pin *check_pin,
const TimingArc *arc,
const Slew &from_slew, const Slew &from_slew,
const char *from_slew_annotation, const char *from_slew_annotation,
const Slew &to_slew, const Slew &to_slew,
float related_out_cap, float related_out_cap,
const Pvt *pvt,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
int digits) = 0; int digits) = 0;
virtual void finishDrvrPin() = 0; virtual void finishDrvrPin() = 0;
protected:
GateTimingModel *gateModel(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const;
CheckTimingModel *checkModel(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const;
TimingModel *model(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const;
}; };
} // namespace } // namespace

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -55,8 +55,7 @@ public:
void operatingConditionsChanged(); void operatingConditionsChanged();
// Make one parasitic analysis points. // Make one parasitic analysis points.
void makeParasiticAnalysisPts(bool per_corner, void makeParasiticAnalysisPts(bool per_corner);
bool per_min_max);
int parasiticAnalysisPtCount() const; int parasiticAnalysisPtCount() const;
ParasiticAnalysisPtSeq &parasiticAnalysisPts(); ParasiticAnalysisPtSeq &parasiticAnalysisPts();
@ -114,7 +113,7 @@ public:
protected: protected:
void setParasiticAnalysisPtcount(int ap_count); void setParasiticAnalysisPtcount(int ap_count);
void setParasiticAP(ParasiticAnalysisPt *path_ap, void setParasiticAP(ParasiticAnalysisPt *path_ap,
int ap_index); int mm_index);
void setDcalcAnalysisPtcount(DcalcAPIndex ap_count); void setDcalcAnalysisPtcount(DcalcAPIndex ap_count);
void addDcalcAP(DcalcAnalysisPt *dcalc_ap); void addDcalcAP(DcalcAnalysisPt *dcalc_ap);
void addPathAP(PathAnalysisPt *path_ap); void addPathAP(PathAnalysisPt *path_ap);

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -17,6 +17,7 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <mutex>
#include "Map.hh" #include "Map.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
@ -25,10 +26,12 @@
#include "DcalcAnalysisPt.hh" #include "DcalcAnalysisPt.hh"
#include "StaState.hh" #include "StaState.hh"
#include "Delay.hh" #include "Delay.hh"
#include "ArcDelayCalc.hh"
namespace sta { namespace sta {
using std::vector; using std::vector;
using std::map;
class DelayCalcObserver; class DelayCalcObserver;
class MultiDrvrNet; class MultiDrvrNet;
@ -69,33 +72,19 @@ public:
// delays to be recomputed during incremental delay calculation. // delays to be recomputed during incremental delay calculation.
virtual float incrementalDelayTolerance(); virtual float incrementalDelayTolerance();
virtual void setIncrementalDelayTolerance(float tol); virtual void setIncrementalDelayTolerance(float tol);
// Load pin_cap + wire_cap.
virtual float loadCap(const Pin *drvr_pin, float loadCap(const Pin *drvr_pin,
const RiseFall *drvr_rf,
const DcalcAnalysisPt *dcalc_ap) const; const DcalcAnalysisPt *dcalc_ap) const;
// Load pin_cap + wire_cap including parasitic min/max for rise/fall. float loadCap(const Pin *drvr_pin,
virtual float loadCap(const Pin *drvr_pin, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) const; const DcalcAnalysisPt *dcalc_ap) const;
// pin_cap = net pin capacitances + port external pin capacitance, void loadCap(const Pin *drvr_pin,
// wire_cap = annotated net capacitance + port external wire capacitance.
virtual void loadCap(const Pin *drvr_pin,
const Parasitic *drvr_parasitic,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
// Return values. // Return values.
float &pin_cap, float &pin_cap,
float &wire_cap) const; float &wire_cap) const;
// Load pin_cap + wire_cap including parasitic. void netCaps(const Pin *drvr_pin,
virtual float loadCap(const Pin *drvr_pin,
const Parasitic *drvr_parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) const;
float loadCap(const Pin *drvr_pin,
const Parasitic *drvr_parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
const MultiDrvrNet *multi_drvr) const;
virtual void netCaps(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
// Return values. // Return values.
@ -103,9 +92,12 @@ public:
float &wire_cap, float &wire_cap,
float &fanout, float &fanout,
bool &has_set_load) const; bool &has_set_load) const;
float ceff(Edge *edge, LoadPinIndexMap makeLoadPinIndexMap(Vertex *drvr_vertex);
TimingArc *arc, void findDriverArcDelays(Vertex *drvr_vertex,
const DcalcAnalysisPt *dcalc_ap); Edge *edge,
const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap,
ArcDelayCalc *arc_delay_calc);
// Precedence: // Precedence:
// SDF annotation // SDF annotation
// Liberty library // Liberty library
@ -170,18 +162,38 @@ protected:
const DcalcAnalysisPt *dcalc_ap); const DcalcAnalysisPt *dcalc_ap);
bool findDriverDelays(Vertex *drvr_vertex, bool findDriverDelays(Vertex *drvr_vertex,
ArcDelayCalc *arc_delay_calc); ArcDelayCalc *arc_delay_calc);
MultiDrvrNet *multiDrvrNet(const Vertex *drvr_vertex) const;
MultiDrvrNet *findMultiDrvrNet(Vertex *drvr_pin); MultiDrvrNet *findMultiDrvrNet(Vertex *drvr_pin);
MultiDrvrNet *makeMultiDrvrNet(PinSet &drvr_pins); MultiDrvrNet *makeMultiDrvrNet(Vertex *drvr_vertex);
bool hasMultiDrvrs(Vertex *drvr_vertex);
Vertex *firstLoad(Vertex *drvr_vertex);
bool findDriverDelays1(Vertex *drvr_vertex, bool findDriverDelays1(Vertex *drvr_vertex,
MultiDrvrNet *multi_drvr, MultiDrvrNet *multi_drvr,
ArcDelayCalc *arc_delay_calc); ArcDelayCalc *arc_delay_calc);
void initLoadSlews(Vertex *drvr_vertex); void initLoadSlews(Vertex *drvr_vertex);
bool findDriverEdgeDelays(const Instance *drvr_inst, bool findDriverEdgeDelays(Vertex *drvr_vertex,
const Pin *drvr_pin,
Vertex *drvr_vertex,
const MultiDrvrNet *multi_drvr, const MultiDrvrNet *multi_drvr,
Edge *edge, Edge *edge,
ArcDelayCalc *arc_delay_calc); ArcDelayCalc *arc_delay_calc);
bool findDriverArcDelays(Vertex *drvr_vertex,
const MultiDrvrNet *multi_drvr,
Edge *edge,
const TimingArc *arc,
LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap,
ArcDelayCalc *arc_delay_calc);
ArcDcalcArgSeq makeArcDcalcArgs(Vertex *drvr_vertex,
const MultiDrvrNet *multi_drvr,
Edge *edge,
const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap,
ArcDelayCalc *arc_delay_calc);
void findParallelEdge(Vertex *vertex,
Edge *drvr_edge,
const TimingArc *drvr_arc,
// Return values.
Edge *&edge,
const TimingArc *&arc);
void initWireDelays(Vertex *drvr_vertex); void initWireDelays(Vertex *drvr_vertex);
void initRootSlews(Vertex *vertex); void initRootSlews(Vertex *vertex);
void zeroSlewAndWireDelays(Vertex *drvr_vertex); void zeroSlewAndWireDelays(Vertex *drvr_vertex);
@ -189,23 +201,24 @@ protected:
ArcDelayCalc *arc_delay_calc, ArcDelayCalc *arc_delay_calc,
bool propagate); bool propagate);
void enqueueTimingChecksEdges(Vertex *vertex); void enqueueTimingChecksEdges(Vertex *vertex);
bool findArcDelay(const Pin *drvr_pin, bool annotateDelaysSlews(Edge *edge,
Vertex *drvr_vertex,
const TimingArc *arc, const TimingArc *arc,
const Parasitic *drvr_parasitic, ArcDcalcResult &dcalc_result,
float related_out_cap, LoadPinIndexMap &load_pin_index_map,
Vertex *from_vertex, const DcalcAnalysisPt *dcalc_ap);
Edge *edge,
const Pvt *pvt, bool annotateDelaySlew(Edge *edge,
const DcalcAnalysisPt *dcalc_ap, const TimingArc *arc,
const MultiDrvrNet *multi_drvr, ArcDelay &gate_delay,
ArcDelayCalc *arc_delay_calc); Slew &gate_slew,
const DcalcAnalysisPt *dcalc_ap);
void annotateLoadDelays(Vertex *drvr_vertex, void annotateLoadDelays(Vertex *drvr_vertex,
const RiseFall *drvr_rf, const RiseFall *drvr_rf,
ArcDcalcResult &dcalc_result,
LoadPinIndexMap &load_pin_index_map,
const ArcDelay &extra_delay, const ArcDelay &extra_delay,
bool merge, bool merge,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap);
ArcDelayCalc *arc_delay_calc);
void findLatchEdgeDelays(Edge *edge); void findLatchEdgeDelays(Edge *edge);
void findCheckEdgeDelays(Edge *edge, void findCheckEdgeDelays(Edge *edge,
ArcDelayCalc *arc_delay_calc); ArcDelayCalc *arc_delay_calc);
@ -214,12 +227,36 @@ protected:
const RiseFall *from_rf, const RiseFall *from_rf,
const DcalcAnalysisPt *dcalc_ap); const DcalcAnalysisPt *dcalc_ap);
bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const; bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const;
MultiDrvrNet *multiDrvrNet(const Vertex *drvr_vertex) const; float loadCap(const Pin *drvr_pin,
void loadCap(const Parasitic *drvr_parasitic, const RiseFall *rf,
bool has_set_load, const DcalcAnalysisPt *dcalc_ap,
ArcDelayCalc *arc_delay_calc) const;
void parasiticLoad(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
const MultiDrvrNet *multi_drvr,
ArcDelayCalc *arc_delay_calc,
// Return values.
float &cap,
const Parasitic *&parasitic) const;
void parasiticLoad(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
const MultiDrvrNet *multi_drvr,
ArcDelayCalc *arc_delay_calc,
// Return values. // Return values.
float &pin_cap, float &pin_cap,
float &wire_cap) const; float &wire_cap,
const Parasitic *&parasitic) const;
void netCaps(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
const MultiDrvrNet *multi_drvr,
// Return values.
float &pin_cap,
float &wire_cap,
float &fanout,
bool &has_net_load) const;
// Observer for edge delay changes. // Observer for edge delay changes.
DelayCalcObserver *observer_; DelayCalcObserver *observer_;
@ -239,7 +276,7 @@ protected:
SearchPred *clk_pred_; SearchPred *clk_pred_;
BfsFwdIterator *iter_; BfsFwdIterator *iter_;
MultiDrvrNetMap multi_drvr_net_map_; MultiDrvrNetMap multi_drvr_net_map_;
bool multi_drvr_nets_found_; std::mutex multi_drvr_lock_;
// Percentage (0.0:1.0) change in delay that causes downstream // Percentage (0.0:1.0) change in delay that causes downstream
// delays to be recomputed during incremental delay calculation. // delays to be recomputed during incremental delay calculation.
float incremental_delay_tolerance_; float incremental_delay_tolerance_;
@ -264,10 +301,9 @@ public:
class MultiDrvrNet class MultiDrvrNet
{ {
public: public:
MultiDrvrNet(VertexSet *drvrs); MultiDrvrNet();
~MultiDrvrNet(); VertexSeq &drvrs() { return drvrs_; }
const VertexSet *drvrs() const { return drvrs_; } const VertexSeq &drvrs() const { return drvrs_; }
VertexSet *drvrs() { return drvrs_; }
bool parallelGates(const Network *network) const; bool parallelGates(const Network *network) const;
Vertex *dcalcDrvr() const { return dcalc_drvr_; } Vertex *dcalcDrvr() const { return dcalc_drvr_; }
void setDcalcDrvr(Vertex *drvr); void setDcalcDrvr(Vertex *drvr);
@ -283,7 +319,7 @@ public:
private: private:
// Driver that triggers delay calculation for all the drivers on the net. // Driver that triggers delay calculation for all the drivers on the net.
Vertex *dcalc_drvr_; Vertex *dcalc_drvr_;
VertexSet *drvrs_; VertexSeq drvrs_;
// [drvr_rf->index][dcalc_ap->index] // [drvr_rf->index][dcalc_ap->index]
vector<NetCaps> net_caps_; vector<NetCaps> net_caps_;
}; };

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -319,6 +319,7 @@ public:
DriverWaveform *findDriverWaveform(const char *name); DriverWaveform *findDriverWaveform(const char *name);
DriverWaveform *driverWaveformDefault() { return driver_waveform_default_; } DriverWaveform *driverWaveformDefault() { return driver_waveform_default_; }
void addDriverWaveform(DriverWaveform *driver_waveform); void addDriverWaveform(DriverWaveform *driver_waveform);
void ensureVoltageWaveforms();
protected: protected:
float degradeWireSlew(const TableModel *model, float degradeWireSlew(const TableModel *model,
@ -370,6 +371,7 @@ protected:
DriverWaveformMap driver_waveform_map_; DriverWaveformMap driver_waveform_map_;
// Unnamed driver waveform. // Unnamed driver waveform.
DriverWaveform *driver_waveform_default_; DriverWaveform *driver_waveform_default_;
bool have_voltage_waveforms_;
static constexpr float input_threshold_default_ = .5; static constexpr float input_threshold_default_ = .5;
static constexpr float output_threshold_default_ = .5; static constexpr float output_threshold_default_ = .5;

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -29,7 +29,6 @@ public:
void gateDelay(const Pvt *pvt, void gateDelay(const Pvt *pvt,
float in_slew, float in_slew,
float load_cap, float load_cap,
float related_out_cap,
bool pocv_enabled, bool pocv_enabled,
// Return values. // Return values.
ArcDelay &gate_delay, ArcDelay &gate_delay,
@ -37,7 +36,6 @@ public:
string reportGateDelay(const Pvt *pvt, string reportGateDelay(const Pvt *pvt,
float in_slew, float in_slew,
float load_cap, float load_cap,
float related_out_cap,
bool pocv_enabled, bool pocv_enabled,
int digits) const override; int digits) const override;
float driveResistance(const Pvt *pvt) const override; float driveResistance(const Pvt *pvt) const override;
@ -54,13 +52,11 @@ class CheckLinearModel : public CheckTimingModel
public: public:
explicit CheckLinearModel(LibertyCell *cell, explicit CheckLinearModel(LibertyCell *cell,
float intrinsic); float intrinsic);
void checkDelay(const Pvt *pvt, ArcDelay checkDelay(const Pvt *pvt,
float from_slew, float from_slew,
float to_slew, float to_slew,
float related_out_cap, float related_out_cap,
bool pocv_enabled, bool pocv_enabled) const override;
// Return values.
ArcDelay &margin) const override;
string reportCheckDelay(const Pvt *pvt, string reportCheckDelay(const Pvt *pvt,
float from_slew, float from_slew,
const char *from_slew_annotation, const char *from_slew_annotation,

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc. // Copyright (c) 2024, Parallax Software, Inc.
// //
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@ -238,6 +238,7 @@ public:
// the other primitives. // the other primitives.
LeafInstanceIterator *leafInstanceIterator() const; LeafInstanceIterator *leafInstanceIterator() const;
LeafInstanceIterator *leafInstanceIterator(const Instance *hier_inst) const; LeafInstanceIterator *leafInstanceIterator(const Instance *hier_inst) const;
InstanceSeq leafInstances();
// Iterate over the children of an instance. // Iterate over the children of an instance.
virtual InstanceChildIterator * virtual InstanceChildIterator *
childIterator(const Instance *instance) const = 0; childIterator(const Instance *instance) const = 0;

Some files were not shown because too many files have changed in this diff Show More