PrimaDelayCalc::reportGateDelay resolves #418
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
c887b2e4b3
commit
b136ba309a
|
|
@ -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,8 +997,16 @@ 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)
|
||||
return table_dcalc_->reportGateDelay(drvr_pin, arc, in_slew, load_cap,
|
||||
parasitic, 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);
|
||||
|
|
@ -949,7 +1016,6 @@ PrimaDelayCalc::reportGateDelay(const Pin *drvr_pin,
|
|||
in_slew1, ceff, min_max,
|
||||
PocvMode::scalar, digits);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue