Merge remote-tracking branch 'upstream/master' into update
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
commit
d61313d8ad
|
|
@ -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}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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++) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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]]
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
708
dcalc/DmpCeff.cc
708
dcalc/DmpCeff.cc
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 *
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ¶llel_delay,
|
|
||||||
Slew ¶llel_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
|
||||||
|
|
|
||||||
|
|
@ -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 ¶llel_delay,
|
|
||||||
Slew ¶llel_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
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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 *
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
|
|
||||||
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -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
|
||||||
|
|
|
||||||
1040
doc/messages.txt
1040
doc/messages.txt
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 ¶siticAnalysisPts();
|
ParasiticAnalysisPtSeq ¶siticAnalysisPts();
|
||||||
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 *¶sitic) 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 *¶sitic) 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_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
Loading…
Reference in New Issue