Merge pull request #347 from The-OpenROAD-Project-staging/sta_latest_upstream_primacrashfix_0413

Sta latest upstream primacrashfix 0413
This commit is contained in:
Matt Liberty 2026-04-16 15:52:49 +00:00 committed by GitHub
commit f668dba758
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 463 additions and 316 deletions

View File

@ -36,6 +36,9 @@ option(ENABLE_ASAN "Compile with address santizer enabled" OFF)
# Turn on to debug compiler args.
set(CMAKE_VERBOSE_MAKEFILE OFF)
# Write compile_commands.json to the build directory for clang-tidy.
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(STA_HOME ${PROJECT_SOURCE_DIR})
message(STATUS "STA version: ${PROJECT_VERSION}")
@ -598,13 +601,13 @@ set(CXX_FLAGS -Wall -Wextra -pedantic -Wcast-qual -Wredundant-decls
if(ENABLE_TSAN)
message(STATUS "Thread sanitizer: ${ENABLE_TSAN}")
set(CXX_FLAGS "${CXX_FLAGS};-fsanitize=thread")
set(CMAKE_EXE_LINKER_FLAGS "-fsanitize=thread")
string(APPEND CMAKE_EXE_LINKER_FLAGS " -fsanitize=thread")
endif()
if(ENABLE_ASAN)
message(STATUS "Address sanitizer: ${ENABLE_ASAN}")
set(CXX_FLAGS "${CXX_FLAGS};-fsanitize=address")
set(CMAKE_EXE_LINKER_FLAGS "-fsanitize=address")
string(APPEND CMAKE_EXE_LINKER_FLAGS " -fsanitize=address")
endif()
target_compile_options(OpenSTA
@ -630,6 +633,7 @@ message(STATUS "STA library: ${CMAKE_BINARY_DIR}/libOpenSTA.a")
add_executable(sta app/Main.cc)
target_link_libraries(sta
PRIVATE
sta_swig
OpenSTA
)

View File

@ -216,43 +216,8 @@ PrimaDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
parasitics_ = scene->parasitics(min_max);
node_index_map_ = NodeIndexMap(ParasiticNodeLess(parasitics_, network_));
bool failed = false;
output_waveforms_.resize(drvr_count_);
for (size_t drvr_idx = 0; drvr_idx < drvr_count_; drvr_idx++) {
ArcDcalcArg &dcalc_arg = dcalc_args[drvr_idx];
GateTableModel *table_model = dcalc_arg.arc()->gateTableModel(scene, min_max);
if (table_model && dcalc_arg.parasitic()) {
OutputWaveforms *output_waveforms = table_model->outputWaveforms();
float in_slew = dcalc_arg.inSlewFlt();
if (output_waveforms
// Bounds check because extrapolating waveforms does not work for shit.
&& output_waveforms->slewAxis()->inBounds(in_slew)
&& output_waveforms->capAxis()->inBounds(dcalc_arg.loadCap())) {
output_waveforms_[drvr_idx] = output_waveforms;
debugPrint(debug_, "ccs_dcalc", 1, "{} {}", dcalc_arg.drvrCell()->name(),
drvr_rf_->shortName());
LibertyCell *drvr_cell = dcalc_arg.drvrCell();
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
bool vdd_exists;
drvr_library->supplyVoltage("VDD", vdd_, vdd_exists);
if (!vdd_exists)
report_->error(1720, "VDD not defined in library {}",
drvr_library->name());
drvr_cell->ensureVoltageWaveforms(scenes_);
if (drvr_idx == 0) {
vth_ = drvr_library->outputThreshold(drvr_rf_) * vdd_;
vl_ = drvr_library->slewLowerThreshold(drvr_rf_) * vdd_;
vh_ = drvr_library->slewUpperThreshold(drvr_rf_) * vdd_;
}
}
else
failed = true;
}
else
failed = true;
}
if (failed)
bool arg_fail = checkArgs(dcalc_args, scene, min_max);
if (arg_fail)
return tableDcalcResults();
else {
simulate();
@ -260,6 +225,100 @@ PrimaDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
}
}
// Return true on failure.
// Use falureReason() to get failure string.
bool
PrimaDelayCalc::checkArgs(ArcDcalcArgSeq &dcalc_args,
const Scene *scene,
const MinMax *min_max)
{
drvr_count_ = dcalc_args.size();
output_waveforms_.resize(drvr_count_);
failure_reason_ = nullptr;
failure_arg_ = nullptr;
for (size_t drvr_idx = 0; drvr_idx < drvr_count_; drvr_idx++) {
ArcDcalcArg &dcalc_arg = dcalc_args[drvr_idx];
GateTableModel *table_model = dcalc_arg.arc()->gateTableModel(scene, min_max);
if (table_model) {
if (dcalc_arg.parasitic()) {
OutputWaveforms *output_waveforms = table_model->outputWaveforms();
float in_slew = dcalc_arg.inSlewFlt();
if (output_waveforms) {
const LibertyLibrary *drvr_library = dcalc_arg.drvrLibrary();
float vdd;
bool vdd_exists;
drvr_library->supplyVoltage("VDD", vdd, vdd_exists);
if (vdd_exists) {
if (drvr_idx == 0) {
// Assume drivers are in the same library.
const RiseFall *drvr_rf = dcalc_arg.drvrEdge();
vdd_ = vdd;
vth_ = drvr_library->outputThreshold(drvr_rf) * vdd_;
vl_ = drvr_library->slewLowerThreshold(drvr_rf) * vdd_;
vh_ = drvr_library->slewUpperThreshold(drvr_rf) * vdd_;
}
}
else {
failure_reason_ = "vdd not defined";
failure_arg_ = &dcalc_arg;
}
// Bounds check because extrapolating waveforms does not work for shit.
if (output_waveforms->slewAxis()->inBounds(in_slew)) {
if (output_waveforms->capAxis()->inBounds(dcalc_arg.loadCap())) {
output_waveforms_[drvr_idx] = output_waveforms;
debugPrint(debug_, "prima", 1, "{} {}",
dcalc_arg.drvrCell()->name(),
dcalc_arg.drvrEdge()->to_string().c_str());
LibertyCell *drvr_cell = dcalc_arg.drvrCell();
drvr_cell->ensureVoltageWaveforms(scenes_);
}
else {
failure_reason_ = "load cap out of bounds";
failure_arg_ = &dcalc_arg;
}
}
else {
failure_reason_ = "input slew out of bounds";
failure_arg_ = &dcalc_arg;
}
}
else {
failure_reason_ = "no output waveforms";
failure_arg_ = &dcalc_arg;
}
}
else {
failure_reason_ = "no parasitic";
failure_arg_ = &dcalc_arg;
}
}
else {
failure_reason_ = "no table model";
failure_arg_ = &dcalc_arg;
}
}
if (failure_reason_) {
std::string reason = failureReason();
debugPrint(debug_,"prima", 1, "arg check failed {}.", reason.c_str());
}
return failure_reason_ != nullptr;
}
std::string
PrimaDelayCalc::failureReason()
{
const Pin *drvr_pin = failure_arg_->drvrPin();
const Instance *inst = network_->instance(drvr_pin);
LibertyPort *from = failure_arg_->arc()->from();
LibertyPort *to = failure_arg_->arc()->to();
return sta::format("{} {} -> {} {}",
sdc_network_->pathName(inst),
from->name(),
to->name(),
failure_reason_);
}
ArcDcalcResultSeq
PrimaDelayCalc::tableDcalcResults()
{
@ -938,18 +997,29 @@ PrimaDelayCalc::reportGateDelay(const Pin *drvr_pin,
const MinMax *min_max,
int digits)
{
GateTimingModel *model = arc->gateModel(scene, min_max);
if (model) {
ArcDcalcArgSeq dcalc_args;
dcalc_args.emplace_back(nullptr, drvr_pin, nullptr, arc, in_slew,
load_cap, parasitic);
bool arg_fail = checkArgs(dcalc_args, scene, min_max);
if (arg_fail) {
const RiseFall *rf = arc->toEdge()->asRiseFall();
const Parasitic *reduced =
table_dcalc_->findParasitic(drvr_pin, rf, scene, min_max);
return table_dcalc_->reportGateDelay(drvr_pin, arc, in_slew, load_cap,
reduced, load_pin_index_map, scene,
min_max, digits);
}
else {
GateTimingModel *model = arc->gateModel(scene, min_max);
// Delay calc to find ceff.
gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic,
load_pin_index_map, scene, min_max);
float in_slew1 = delayAsFloat(in_slew);
float ceff = ceff_vth_.empty() ? load_cap : ceff_vth_[0];
float ceff = ceff_vth_[0];
return model->reportGateDelay(pinPvt(drvr_pin, scene, min_max),
in_slew1, ceff, min_max,
PocvMode::scalar, digits);
}
return "";
}
////////////////////////////////////////////////////////////////

View File

@ -100,6 +100,10 @@ public:
const Scene *scene,
const MinMax *min_max,
int digits) override;
bool checkArgs(ArcDcalcArgSeq &dcalc_args,
const Scene *scene,
const MinMax *min_max);
std::string failureReason();
// Record waveform for drvr/load pin.
void watchPin(const Pin *pin) override;
@ -253,6 +257,9 @@ protected:
// Delay calculator to use when ccs waveforms are missing from liberty.
ArcDelayCalc *table_dcalc_;
const char *failure_reason_;
ArcDcalcArg *failure_arg_;
using ArcDelayCalc::reduceParasitic;
};

View File

@ -42,50 +42,54 @@ Cell: BUFx2_ASAP7_75t_R
Arc sense: positive_unate
Arc type: combinational
A ^ -> Y ^
Pi model C2=6.70 Rpi=2.42 C1=7.27, Ceff=10.50
P = 1.00 V = 0.77 T = 0.00
------- input_net_transition = 50.73
| total_output_net_capacitance = 13.97
| 11.52 23.04
| total_output_net_capacitance = 10.50
| 5.76 11.52
v --------------------
40.00 | 35.12 50.39
80.00 | 40.08 55.44
Table value = 39.70
40.00 | 27.29 35.12
80.00 | 32.30 40.08
Table value = 35.06
PVT scale factor = 1.00
Delay = 39.70
Delay = 35.06
------- input_net_transition = 50.73
| total_output_net_capacitance = 13.97
| 11.52 23.04
| total_output_net_capacitance = 10.50
| 5.76 11.52
v --------------------
40.00 | 37.28 71.28
80.00 | 38.13 71.69
Table value = 44.70
40.00 | 20.70 37.28
80.00 | 21.40 38.13
Table value = 34.55
PVT scale factor = 1.00
Slew = 44.70
Slew = 34.55
Driver waveform slew = 47.36
.............................................
A v -> Y v
Pi model C2=6.70 Rpi=2.42 C1=7.27, Ceff=10.09
P = 1.00 V = 0.77 T = 0.00
------- input_net_transition = 48.72
| total_output_net_capacitance = 13.97
| 11.52 23.04
| total_output_net_capacitance = 10.09
| 5.76 11.52
v --------------------
40.00 | 36.17 49.65
80.00 | 43.28 56.72
Table value = 40.58
40.00 | 29.18 36.17
80.00 | 36.09 43.28
Table value = 35.97
PVT scale factor = 1.00
Delay = 40.58
Delay = 35.97
------- input_net_transition = 48.72
| total_output_net_capacitance = 13.97
| 11.52 23.04
| total_output_net_capacitance = 10.09
| 5.76 11.52
v --------------------
40.00 | 31.72 59.66
80.00 | 32.63 60.23
Table value = 37.84
40.00 | 18.15 31.72
80.00 | 19.36 32.63
Table value = 28.57
PVT scale factor = 1.00
Slew = 37.84
Slew = 28.57
Driver waveform slew = 40.66
.............................................

View File

@ -12,5 +12,23 @@ create_clock -name clk -period 500 -waveform {0 250} {clk1 clk2 clk3}
set_delay_calculator prima
read_spef -name spef ../../test/reg1_asap7.spef
# read_spef -name <spef> only parks the parasitics under <spef> in the
# parasitics_name_map_; it does NOT bind them to any Scene (this is the
# deferred-binding flow for MCMM -- see examples/mcmm3.tcl and Sta::readSpef
# in search/Sta.cc). Without an explicit Scene binding, report_dcalc /
# report_checks would see only pin capacitance (~0.57 fF here) and produce
# incorrect table lookups, instead of the wire-cap-annotated ~13.97 fF we
# expect for this design. define_scene with -spef spef creates a Scene
# bound to the -name'd Parasitics via Scene::setParasitics and makes it the
# current Scene, so Prima receives the full RC network.
define_scene scene1 \
-liberty {asap7sc7p5t_SEQ_RVT_FF_nldm_220123 \
asap7sc7p5t_INVBUF_RVT_FF_nldm_211120 \
asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120 \
asap7sc7p5t_OA_RVT_FF_nldm_211120 \
asap7sc7p5t_AO_RVT_FF_nldm_211120} \
-spef spef
report_checks
report_dcalc -from u1/A -to u1/Y

View File

@ -28,6 +28,7 @@
#include <string_view>
#include <vector>
#include "NetworkClass.hh"
#include "SdcClass.hh"
#include "SearchClass.hh"
#include "StringUtil.hh"

View File

@ -25,25 +25,26 @@
#pragma once
#include <string>
#include <string_view>
namespace sta {
std::string
cellVerilogName(std::string sta_name);
cellVerilogName(std::string_view sta_name);
std::string
instanceVerilogName(std::string sta_name);
instanceVerilogName(std::string_view sta_name);
std::string
netVerilogName(std::string sta_name);
netVerilogName(std::string_view sta_name);
std::string
portVerilogName(std::string sta_name);
portVerilogName(std::string_view sta_name);
std::string
moduleVerilogToSta(std::string sta_name);
moduleVerilogToSta(std::string_view sta_name);
std::string
instanceVerilogToSta(std::string sta_name);
instanceVerilogToSta(std::string_view sta_name);
std::string
netVerilogToSta(std::string sta_name);
netVerilogToSta(std::string_view sta_name);
std::string
portVerilogToSta(std::string sta_name);
portVerilogToSta(std::string_view sta_name);
} // namespace

View File

@ -1489,8 +1489,7 @@ LibertyCell::outputPortSequential(LibertyPort *port)
bool
LibertyCell::hasSequentials() const
{
return !sequentials_.empty()
|| statetable_ != nullptr;
return !sequentials_.empty() || statetable_ != nullptr;
}
void
@ -2478,16 +2477,10 @@ bool
LibertyPort::less(const LibertyPort *port1,
const LibertyPort *port2)
{
if (port1 == nullptr || port2 == nullptr)
if (port1 && port2)
return port1->pinIndex() < port2->pinIndex();
else
return port1 == nullptr && port2 != nullptr;
const std::string &name1 = port1->name();
const std::string &name2 = port2->name();
if (name1 == name2) {
PortDirection *dir1 = port1->direction();
PortDirection *dir2 = port2->direction();
return dir1->index() < dir2->index();
}
return name1 < name2;
}
void

View File

@ -34,26 +34,26 @@ namespace sta {
constexpr char verilog_escape = '\\';
static std::string
staToVerilog(std::string sta_name);
staToVerilog(std::string_view sta_name);
static std::string
staToVerilog2(std::string sta_name);
staToVerilog2(std::string_view sta_name);
static std::string
verilogToSta(const std::string verilog_name);
verilogToSta(const std::string_view verilog_name);
std::string
cellVerilogName(std::string sta_name)
cellVerilogName(std::string_view sta_name)
{
return staToVerilog(sta_name);
}
std::string
instanceVerilogName(std::string sta_name)
instanceVerilogName(std::string_view sta_name)
{
return staToVerilog(sta_name);
}
std::string
netVerilogName(std::string sta_name)
netVerilogName(std::string_view sta_name)
{
bool is_bus;
std::string bus_name;
@ -69,13 +69,20 @@ netVerilogName(std::string sta_name)
}
std::string
portVerilogName(std::string sta_name)
portVerilogName(std::string_view sta_name)
{
return staToVerilog2(sta_name);
}
// <cctype> functions expect a value representable as unsigned char or EOF.
static bool
isAlnumUnderscore(char ch)
{
return std::isalnum(static_cast<unsigned char>(ch)) != 0 || ch == '_';
}
static std::string
staToVerilog(std::string sta_name)
staToVerilog(std::string_view sta_name)
{
// Leave room for leading escape and trailing space if the name
// needs to be escaped.
@ -87,14 +94,18 @@ staToVerilog(std::string sta_name)
char ch = sta_name[i];
if (ch == verilog_escape) {
escaped = true;
char next_ch = sta_name[i + 1];
if (next_ch == verilog_escape) {
escaped_name += next_ch;
i++;
if (i + 1 < sta_length) {
char next_ch = sta_name[i + 1];
if (next_ch == verilog_escape) {
escaped_name += next_ch;
i++;
}
}
else
escaped_name += ch;
}
else {
if ((!(isalnum(ch) || ch == '_')))
if (!isAlnumUnderscore(ch))
escaped = true;
escaped_name += ch;
}
@ -105,11 +116,11 @@ staToVerilog(std::string sta_name)
return escaped_name;
}
else
return sta_name;
return std::string(sta_name);
}
static std::string
staToVerilog2(std::string sta_name)
staToVerilog2(std::string_view sta_name)
{
constexpr char bus_brkt_left = '[';
constexpr char bus_brkt_right = ']';
@ -123,16 +134,19 @@ staToVerilog2(std::string sta_name)
char ch = sta_name[i];
if (ch == verilog_escape) {
escaped = true;
char next_ch = sta_name[i + 1];
if (next_ch == verilog_escape) {
escaped_name += next_ch;
i++;
if (i + 1 < sta_length) {
char next_ch = sta_name[i + 1];
if (next_ch == verilog_escape) {
escaped_name += next_ch;
i++;
}
}
else
escaped_name += ch;
}
else {
bool is_brkt = (ch == bus_brkt_left || ch == bus_brkt_right);
if ((!(isalnum(ch) || ch == '_') && !is_brkt)
|| is_brkt)
if ((!isAlnumUnderscore(ch) && !is_brkt) || is_brkt)
escaped = true;
escaped_name += ch;
}
@ -143,45 +157,49 @@ staToVerilog2(std::string sta_name)
return escaped_name;
}
else
return sta_name;
return std::string(sta_name);
}
////////////////////////////////////////////////////////////////
std::string
moduleVerilogToSta(std::string module_name)
moduleVerilogToSta(std::string_view module_name)
{
return verilogToSta(module_name);
}
std::string
instanceVerilogToSta(std::string inst_name)
instanceVerilogToSta(std::string_view inst_name)
{
return verilogToSta(inst_name);
}
std::string
netVerilogToSta(std::string net_name)
netVerilogToSta(std::string_view net_name)
{
return verilogToSta(net_name);
}
std::string
portVerilogToSta(std::string port_name)
portVerilogToSta(std::string_view port_name)
{
return verilogToSta(port_name);
}
static std::string
verilogToSta(std::string verilog_name)
verilogToSta(std::string_view verilog_name)
{
if (verilog_name.empty())
return std::string(verilog_name);
if (verilog_name.front() == '\\') {
constexpr char divider = '/';
constexpr char bus_brkt_left = '[';
constexpr char bus_brkt_right = ']';
size_t verilog_name_length = verilog_name.size();
if (isspace(verilog_name.back()))
if (verilog_name_length > 1
&& std::isspace(static_cast<unsigned char>(verilog_name.back())) != 0)
verilog_name_length--;
std::string sta_name;
// Ignore leading '\'.
@ -198,7 +216,7 @@ verilogToSta(std::string verilog_name)
return sta_name;
}
else
return verilog_name;
return std::string(verilog_name);
}
} // namespace

View File

@ -459,50 +459,54 @@ Cell: BUFx2_ASAP7_75t_R
Arc sense: positive_unate
Arc type: combinational
A ^ -> Y ^
Pi model C2=6.70 Rpi=2.42 C1=7.27, Ceff=10.50
P = 1.00 V = 0.77 T = 0.00
------- input_net_transition = 50.73
| total_output_net_capacitance = 13.97
| 11.52 23.04
| total_output_net_capacitance = 10.50
| 5.76 11.52
v --------------------
40.00 | 35.12 50.39
80.00 | 40.08 55.44
Table value = 39.70
40.00 | 27.29 35.12
80.00 | 32.30 40.08
Table value = 35.06
PVT scale factor = 1.00
Delay = 39.70
Delay = 35.06
------- input_net_transition = 50.73
| total_output_net_capacitance = 13.97
| 11.52 23.04
| total_output_net_capacitance = 10.50
| 5.76 11.52
v --------------------
40.00 | 37.28 71.28
80.00 | 38.13 71.69
Table value = 44.70
40.00 | 20.70 37.28
80.00 | 21.40 38.13
Table value = 34.55
PVT scale factor = 1.00
Slew = 44.70
Slew = 34.55
Driver waveform slew = 47.36
.............................................
A v -> Y v
Pi model C2=6.70 Rpi=2.42 C1=7.27, Ceff=10.09
P = 1.00 V = 0.77 T = 0.00
------- input_net_transition = 48.75
| total_output_net_capacitance = 13.97
| 11.52 23.04
| total_output_net_capacitance = 10.09
| 5.76 11.52
v --------------------
40.00 | 36.17 49.65
80.00 | 43.28 56.72
Table value = 40.59
40.00 | 29.18 36.17
80.00 | 36.09 43.28
Table value = 35.98
PVT scale factor = 1.00
Delay = 40.59
Delay = 35.98
------- input_net_transition = 48.75
| total_output_net_capacitance = 13.97
| 11.52 23.04
| total_output_net_capacitance = 10.09
| 5.76 11.52
v --------------------
40.00 | 31.72 59.66
80.00 | 32.63 60.23
Table value = 37.84
40.00 | 18.15 31.72
80.00 | 19.36 32.63
Table value = 28.57
PVT scale factor = 1.00
Slew = 37.84
Slew = 28.57
Driver waveform slew = 40.66
.............................................
@ -512,50 +516,54 @@ Cell: AND2x2_ASAP7_75t_R
Arc sense: positive_unate
Arc type: combinational
A ^ -> Y ^
Pi model C2=6.70 Rpi=2.42 C1=7.32, Ceff=10.90
P = 1.00 V = 0.70 T = 25.00
------- input_net_transition = 50.41
| total_output_net_capacitance = 14.02
| 11.52 23.04
| total_output_net_capacitance = 10.90
| 5.76 11.52
v --------------------
40.00 | 40.48 58.12
80.00 | 45.47 63.31
Table value = 45.62
40.00 | 31.28 40.48
80.00 | 36.30 45.47
Table value = 40.79
PVT scale factor = 1.00
Delay = 45.62
Delay = 40.79
------- input_net_transition = 50.41
| total_output_net_capacitance = 14.02
| 11.52 23.04
| total_output_net_capacitance = 10.90
| 5.76 11.52
v --------------------
40.00 | 43.68 82.62
80.00 | 44.42 82.97
Table value = 52.30
40.00 | 24.52 43.68
80.00 | 25.29 44.42
Table value = 41.80
PVT scale factor = 1.00
Slew = 52.30
Slew = 41.80
Driver waveform slew = 55.90
.............................................
A v -> Y v
Pi model C2=6.70 Rpi=2.42 C1=7.32, Ceff=10.35
P = 1.00 V = 0.70 T = 25.00
------- input_net_transition = 48.36
| total_output_net_capacitance = 14.02
| 11.52 23.04
| total_output_net_capacitance = 10.35
| 5.76 11.52
v --------------------
40.00 | 43.09 58.01
80.00 | 52.65 67.66
Table value = 48.33
40.00 | 35.35 43.09
80.00 | 44.73 52.65
Table value = 43.51
PVT scale factor = 1.00
Delay = 48.33
Delay = 43.51
------- input_net_transition = 48.36
| total_output_net_capacitance = 14.02
| 11.52 23.04
| total_output_net_capacitance = 10.35
| 5.76 11.52
v --------------------
40.00 | 35.08 65.82
80.00 | 36.06 66.39
Table value = 41.94
40.00 | 20.09 35.08
80.00 | 21.45 36.06
Table value = 32.26
PVT scale factor = 1.00
Slew = 41.94
Slew = 32.26
Driver waveform slew = 45.57
.............................................
@ -565,50 +573,54 @@ Cell: DFFHQx4_ASAP7_75t_R
Arc sense: non_unate
Arc type: Reg Clk to Q
CLK ^ -> Q ^
Pi model C2=6.70 Rpi=2.42 C1=7.22, Ceff=9.22
P = 1.00 V = 0.77 T = 0.00
------- input_net_transition = 48.38
| total_output_net_capacitance = 13.92
| 11.52 23.04
| total_output_net_capacitance = 9.22
| 5.76 11.52
v --------------------
40.00 | 64.09 71.91
80.00 | 69.26 77.08
Table value = 66.81
40.00 | 59.92 64.09
80.00 | 65.10 69.26
Table value = 63.51
PVT scale factor = 1.00
Delay = 66.81
Delay = 63.51
------- input_net_transition = 48.38
| total_output_net_capacitance = 13.92
| 11.52 23.04
| total_output_net_capacitance = 9.22
| 5.76 11.52
v --------------------
40.00 | 21.04 37.91
80.00 | 21.05 37.92
Table value = 24.56
40.00 | 13.01 21.04
80.00 | 13.01 21.05
Table value = 17.83
PVT scale factor = 1.00
Slew = 24.56
Slew = 17.83
Driver waveform slew = 22.83
.............................................
CLK ^ -> Q v
Pi model C2=6.70 Rpi=2.42 C1=7.21, Ceff=8.89
P = 1.00 V = 0.77 T = 0.00
------- input_net_transition = 48.38
| total_output_net_capacitance = 13.91
| 11.52 23.04
| total_output_net_capacitance = 8.89
| 5.76 11.52
v --------------------
40.00 | 61.63 68.60
80.00 | 66.47 73.44
Table value = 64.09
40.00 | 57.80 61.63
80.00 | 62.64 66.47
Table value = 60.90
PVT scale factor = 1.00
Delay = 64.09
Delay = 60.90
------- input_net_transition = 48.38
| total_output_net_capacitance = 13.91
| 11.52 23.04
| total_output_net_capacitance = 8.89
| 5.76 11.52
v --------------------
40.00 | 17.99 31.89
80.00 | 17.98 31.88
Table value = 20.87
40.00 | 11.30 17.99
80.00 | 11.31 17.98
Table value = 14.94
PVT scale factor = 1.00
Slew = 20.87
Slew = 14.94
Driver waveform slew = 19.18
.............................................

View File

@ -1362,50 +1362,54 @@ Cell: BUFx2_ASAP7_75t_R
Arc sense: positive_unate
Arc type: combinational
A ^ -> Y ^
Pi model C2=6.70 Rpi=2.42 C1=7.27, Ceff=10.50
P = 1.00 V = 0.77 T = 0.00
------- input_net_transition = 50.73
| total_output_net_capacitance = 13.97
| 11.52 23.04
| total_output_net_capacitance = 10.50
| 5.76 11.52
v --------------------
40.00 | 35.12 50.39
80.00 | 40.08 55.44
Table value = 39.70
40.00 | 27.29 35.12
80.00 | 32.30 40.08
Table value = 35.06
PVT scale factor = 1.00
Delay = 39.70
Delay = 35.06
------- input_net_transition = 50.73
| total_output_net_capacitance = 13.97
| 11.52 23.04
| total_output_net_capacitance = 10.50
| 5.76 11.52
v --------------------
40.00 | 37.28 71.28
80.00 | 38.13 71.69
Table value = 44.70
40.00 | 20.70 37.28
80.00 | 21.40 38.13
Table value = 34.55
PVT scale factor = 1.00
Slew = 44.70
Slew = 34.55
Driver waveform slew = 47.36
.............................................
A v -> Y v
Pi model C2=6.70 Rpi=2.42 C1=7.27, Ceff=10.09
P = 1.00 V = 0.77 T = 0.00
------- input_net_transition = 48.75
| total_output_net_capacitance = 13.97
| 11.52 23.04
| total_output_net_capacitance = 10.09
| 5.76 11.52
v --------------------
40.00 | 36.17 49.65
80.00 | 43.28 56.72
Table value = 40.59
40.00 | 29.18 36.17
80.00 | 36.09 43.28
Table value = 35.98
PVT scale factor = 1.00
Delay = 40.59
Delay = 35.98
------- input_net_transition = 48.75
| total_output_net_capacitance = 13.97
| 11.52 23.04
| total_output_net_capacitance = 10.09
| 5.76 11.52
v --------------------
40.00 | 31.72 59.66
80.00 | 32.63 60.23
Table value = 37.84
40.00 | 18.15 31.72
80.00 | 19.36 32.63
Table value = 28.57
PVT scale factor = 1.00
Slew = 37.84
Slew = 28.57
Driver waveform slew = 40.66
.............................................
@ -1415,50 +1419,54 @@ Cell: AND2x2_ASAP7_75t_R
Arc sense: positive_unate
Arc type: combinational
A ^ -> Y ^
Pi model C2=6.70 Rpi=2.42 C1=7.32, Ceff=10.90
P = 1.00 V = 0.70 T = 25.00
------- input_net_transition = 50.41
| total_output_net_capacitance = 14.02
| 11.52 23.04
| total_output_net_capacitance = 10.90
| 5.76 11.52
v --------------------
40.00 | 40.48 58.12
80.00 | 45.47 63.31
Table value = 45.62
40.00 | 31.28 40.48
80.00 | 36.30 45.47
Table value = 40.79
PVT scale factor = 1.00
Delay = 45.62
Delay = 40.79
------- input_net_transition = 50.41
| total_output_net_capacitance = 14.02
| 11.52 23.04
| total_output_net_capacitance = 10.90
| 5.76 11.52
v --------------------
40.00 | 43.68 82.62
80.00 | 44.42 82.97
Table value = 52.30
40.00 | 24.52 43.68
80.00 | 25.29 44.42
Table value = 41.80
PVT scale factor = 1.00
Slew = 52.30
Slew = 41.80
Driver waveform slew = 55.90
.............................................
A v -> Y v
Pi model C2=6.70 Rpi=2.42 C1=7.32, Ceff=10.35
P = 1.00 V = 0.70 T = 25.00
------- input_net_transition = 48.36
| total_output_net_capacitance = 14.02
| 11.52 23.04
| total_output_net_capacitance = 10.35
| 5.76 11.52
v --------------------
40.00 | 43.09 58.01
80.00 | 52.65 67.66
Table value = 48.33
40.00 | 35.35 43.09
80.00 | 44.73 52.65
Table value = 43.51
PVT scale factor = 1.00
Delay = 48.33
Delay = 43.51
------- input_net_transition = 48.36
| total_output_net_capacitance = 14.02
| 11.52 23.04
| total_output_net_capacitance = 10.35
| 5.76 11.52
v --------------------
40.00 | 35.08 65.82
80.00 | 36.06 66.39
Table value = 41.94
40.00 | 20.09 35.08
80.00 | 21.45 36.06
Table value = 32.26
PVT scale factor = 1.00
Slew = 41.94
Slew = 32.26
Driver waveform slew = 45.57
.............................................
@ -1468,50 +1476,54 @@ Cell: DFFHQx4_ASAP7_75t_R
Arc sense: non_unate
Arc type: Reg Clk to Q
CLK ^ -> Q ^
Pi model C2=6.70 Rpi=2.42 C1=7.22, Ceff=9.22
P = 1.00 V = 0.77 T = 0.00
------- input_net_transition = 48.38
| total_output_net_capacitance = 13.92
| 11.52 23.04
| total_output_net_capacitance = 9.22
| 5.76 11.52
v --------------------
40.00 | 64.09 71.91
80.00 | 69.26 77.08
Table value = 66.81
40.00 | 59.92 64.09
80.00 | 65.10 69.26
Table value = 63.51
PVT scale factor = 1.00
Delay = 66.81
Delay = 63.51
------- input_net_transition = 48.38
| total_output_net_capacitance = 13.92
| 11.52 23.04
| total_output_net_capacitance = 9.22
| 5.76 11.52
v --------------------
40.00 | 21.04 37.91
80.00 | 21.05 37.92
Table value = 24.56
40.00 | 13.01 21.04
80.00 | 13.01 21.05
Table value = 17.83
PVT scale factor = 1.00
Slew = 24.56
Slew = 17.83
Driver waveform slew = 22.83
.............................................
CLK ^ -> Q v
Pi model C2=6.70 Rpi=2.42 C1=7.21, Ceff=8.89
P = 1.00 V = 0.77 T = 0.00
------- input_net_transition = 48.38
| total_output_net_capacitance = 13.91
| 11.52 23.04
| total_output_net_capacitance = 8.89
| 5.76 11.52
v --------------------
40.00 | 61.63 68.60
80.00 | 66.47 73.44
Table value = 64.09
40.00 | 57.80 61.63
80.00 | 62.64 66.47
Table value = 60.90
PVT scale factor = 1.00
Delay = 64.09
Delay = 60.90
------- input_net_transition = 48.38
| total_output_net_capacitance = 13.91
| 11.52 23.04
| total_output_net_capacitance = 8.89
| 5.76 11.52
v --------------------
40.00 | 17.99 31.89
80.00 | 17.98 31.88
Table value = 20.87
40.00 | 11.30 17.99
80.00 | 11.31 17.98
Table value = 14.94
PVT scale factor = 1.00
Slew = 20.87
Slew = 14.94
Driver waveform slew = 19.18
.............................................

View File

@ -24,11 +24,17 @@
#include "FilterObjects.hh"
#include <regex>
#include <stack>
#include <functional>
#include <memory>
#include <regex>
#include <stack>
#include <cstddef>
#include <string>
#include <string_view>
#include "NetworkClass.hh"
#include "Network.hh"
#include "StringUtil.hh"
#include "Property.hh"
#include "PatternMatch.hh"
#include "Sta.hh"
@ -52,22 +58,27 @@ public:
undefined
};
Token(std::string text,
Token(std::string_view text,
Kind kind);
std::string text;
Kind kind;
const std::string &text() const { return text_; }
Kind kind() const { return kind_; }
std::string text_;
Kind kind_;
};
struct PredicateToken : public Token
{
PredicateToken(std::string property,
std::string op,
std::string arg);
PredicateToken(std::string_view property,
std::string_view op,
std::string_view arg);
const std::string &property() const { return property_; }
const std::string &op() const { return op_; }
const std::string &arg() const { return arg_; }
std::string property;
std::string op;
std::string arg;
std::string property_;
std::string op_;
std::string arg_;
};
FilterExpr(std::string_view expression,
@ -82,19 +93,21 @@ private:
Report *report_;
};
FilterExpr::Token::Token(std::string text,
FilterExpr::Token::Token(std::string_view text,
Token::Kind kind) :
text (text),
kind(kind)
text_(text),
kind_(kind)
{
}
FilterExpr::PredicateToken::PredicateToken(std::string property,
std::string op,
std::string arg) :
Token(property + " " + op + " " + arg,
FilterExpr::PredicateToken::PredicateToken(std::string_view property,
std::string_view op,
std::string_view arg) :
Token(sta::format("{} {} {}", property, op, arg),
Token::Kind::predicate),
property(property), op(op), arg(arg)
property_(property),
op_(op),
arg_(arg)
{
}
@ -140,7 +153,7 @@ FilterExpr::lex()
std::string property = token_match[1].str();
// The default operation on a predicate if an op and arg are
// omitted is 'prop == 1 || true'.
// omitted is 'prop == 1'.
std::string op = "==";
std::string arg = "1";
@ -175,7 +188,7 @@ FilterExpr::shuntingYard(std::vector<std::unique_ptr<Token>> &infix)
std::stack<std::unique_ptr<Token>> operator_stack;
for (auto &token : infix) {
switch (token->kind) {
switch (token->kind()) {
case Token::Kind::predicate:
output.push_back(std::move(token));
break;
@ -185,7 +198,7 @@ FilterExpr::shuntingYard(std::vector<std::unique_ptr<Token>> &infix)
// The operators' enum values are ascending by precedence:
// inv > and > or
while (operator_stack.size()
&& operator_stack.top()->kind > token->kind) {
&& operator_stack.top()->kind() > token->kind()) {
output.push_back(std::move(operator_stack.top()));
operator_stack.pop();
}
@ -208,7 +221,7 @@ FilterExpr::shuntingYard(std::vector<std::unique_ptr<Token>> &infix)
if (operator_stack.empty())
report_->error(2601, "-filter extraneous ).");
while (operator_stack.size()
&& operator_stack.top()->kind != Token::Kind::op_lparen) {
&& operator_stack.top()->kind() != Token::Kind::op_lparen) {
output.push_back(std::move(operator_stack.top()));
operator_stack.pop();
if (operator_stack.empty())
@ -224,7 +237,7 @@ FilterExpr::shuntingYard(std::vector<std::unique_ptr<Token>> &infix)
}
while (operator_stack.size()) {
if (operator_stack.top()->kind == Token::Kind::op_lparen)
if (operator_stack.top()->kind() == Token::Kind::op_lparen)
report_->error(2603, "-filter unmatched (.");
output.push_back(std::move(operator_stack.top()));
operator_stack.pop();
@ -235,20 +248,20 @@ FilterExpr::shuntingYard(std::vector<std::unique_ptr<Token>> &infix)
////////////////////////////////////////////////////////////////
template <typename T> std::set<T*>
filterObjects(const char *property,
const char *op,
const char *pattern,
template <typename T> static std::set<T*>
filterObjects(std::string_view property,
std::string_view op,
std::string_view pattern,
std::set<T*> &all,
Sta *sta)
{
Properties &properties = sta->properties();
Network *network = sta->network();
auto filtered_objects = std::set<T*>();
bool exact_match = stringEq(op, "==");
bool pattern_match = stringEq(op, "=~");
bool not_match = stringEq(op, "!=");
bool not_pattern_match = stringEq(op, "!~");
bool exact_match = (op == "==");
bool pattern_match = (op == "=~");
bool not_match = (op == "!=");
bool not_pattern_match = (op == "!~");
for (T *object : all) {
PropertyValue value = properties.getProperty(object, property);
std::string prop = value.to_string(network);
@ -259,8 +272,8 @@ filterObjects(const char *property,
else if (stringEqual(pattern, "false"))
pattern = "0";
}
if ((exact_match && stringEq(prop.c_str(), pattern))
|| (not_match && !stringEq(prop.c_str(), pattern))
if ((exact_match && prop == pattern)
|| (not_match && prop != pattern)
|| (pattern_match && patternMatch(pattern, prop))
|| (not_pattern_match && !patternMatch(pattern, prop)))
filtered_objects.insert(object);
@ -268,9 +281,9 @@ filterObjects(const char *property,
return filtered_objects;
}
template <typename T> std::vector<T*>
template <typename T> static std::vector<T*>
filterObjects(std::string_view filter_expression,
std::vector<T*> *objects,
const std::vector<T*> *objects,
Sta *sta)
{
Report *report = sta->report();
@ -286,7 +299,7 @@ filterObjects(std::string_view filter_expression,
auto postfix = filter.postfix();
std::stack<std::set<T*>> eval_stack;
for (auto &token : postfix) {
if (token->kind == FilterExpr::Token::Kind::op_or) {
if (token->kind() == FilterExpr::Token::Kind::op_or) {
if (eval_stack.size() < 2)
report->error(2604, "-filter logical OR requires at least two operands.");
auto arg0 = eval_stack.top();
@ -298,7 +311,7 @@ filterObjects(std::string_view filter_expression,
std::inserter(union_result, union_result.begin()));
eval_stack.push(union_result);
}
else if (token->kind == FilterExpr::Token::Kind::op_and) {
else if (token->kind() == FilterExpr::Token::Kind::op_and) {
if (eval_stack.size() < 2) {
report->error(2605, "-filter logical AND requires two operands.");
}
@ -313,7 +326,7 @@ filterObjects(std::string_view filter_expression,
intersection_result.begin()));
eval_stack.push(intersection_result);
}
else if (token->kind == FilterExpr::Token::Kind::op_inv) {
else if (token->kind() == FilterExpr::Token::Kind::op_inv) {
if (eval_stack.size() < 1) {
report->error(2606, "-filter NOT missing operand.");
}
@ -327,13 +340,13 @@ filterObjects(std::string_view filter_expression,
difference_result.begin()));
eval_stack.push(difference_result);
}
else if (token->kind == FilterExpr::Token::Kind::defined
|| token->kind == FilterExpr::Token::Kind::undefined) {
else if (token->kind() == FilterExpr::Token::Kind::defined
|| token->kind() == FilterExpr::Token::Kind::undefined) {
bool should_be_defined =
(token->kind == FilterExpr::Token::Kind::defined);
(token->kind() == FilterExpr::Token::Kind::defined);
auto result = std::set<T*>();
for (auto object : all) {
PropertyValue value = properties.getProperty(object, token->text);
PropertyValue value = properties.getProperty(object, token->text());
bool is_defined = false;
switch (value.type()) {
case PropertyValue::Type::float_:
@ -377,12 +390,12 @@ filterObjects(std::string_view filter_expression,
}
eval_stack.push(result);
}
else if (token->kind == FilterExpr::Token::Kind::predicate) {
else if (token->kind() == FilterExpr::Token::Kind::predicate) {
auto *predicate_token =
static_cast<FilterExpr::PredicateToken *>(token.get());
auto result = filterObjects<T>(predicate_token->property.c_str(),
predicate_token->op.c_str(),
predicate_token->arg.c_str(),
auto result = filterObjects<T>(predicate_token->property(),
predicate_token->op(),
predicate_token->arg(),
all, sta);
eval_stack.push(result);
}
@ -495,7 +508,7 @@ filterExprToPostfix(std::string_view expr,
auto postfix = filter.postfix();
StringSeq result;
for (auto &token : postfix)
result.push_back(token->text);
result.push_back(token->text());
return result;
}

View File

@ -144,8 +144,8 @@ set_false_path -from [get_ports in2] -fall_to [get_ports out2]
set_multicycle_path 2 -setup -from [get_clocks clk1] -to [get_clocks clk2]
set_max_delay 7.0 -from [get_ports in3] -rise_through [get_pins or1/ZN] -to [get_ports out2]
set sdc1 [make_result_file sdc_exc_override1.sdc]
set sdc1 [make_result_file sdc_exc_thru_override1.sdc]
write_sdc -no_timestamp $sdc1
set sdc2 [make_result_file sdc_exc_override2.sdc]
set sdc2 [make_result_file sdc_exc_thru_override2.sdc]
write_sdc -no_timestamp -compatible $sdc2

View File

@ -4169,12 +4169,6 @@ Sta::readSpef(std::string_view name,
parasitics = findParasitics(std::string(name));
if (parasitics == nullptr)
parasitics = makeConcreteParasitics(std::string(name), std::string(filename));
if (scene)
scene->setParasitics(parasitics, min_max);
else {
for (Scene *scn : scenes_)
scn->setParasitics(parasitics, min_max);
}
}
bool success = readSpefFile(filename, instance, pin_cap_included,