make timing model table models

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2022-06-11 16:25:21 -07:00
parent 1eb6da19e9
commit cf9e720582
2 changed files with 124 additions and 10 deletions

View File

@ -38,6 +38,7 @@
#include "Search.hh"
#include "Sta.hh"
#include "VisitPathEnds.hh"
#include "ArcDelayCalc.hh"
namespace sta {
@ -49,7 +50,8 @@ MakeTimingModel::MakeTimingModel(const Corner *corner,
sta_(sta),
corner_(corner),
min_max_(MinMax::max()),
lib_builder_(new LibertyBuilder)
lib_builder_(new LibertyBuilder),
tbl_template_index_(1)
{
}
@ -62,6 +64,7 @@ LibertyLibrary *
MakeTimingModel::makeTimingModel(const char *cell_name,
const char *filename)
{
tbl_template_index_ = 1;
makeLibrary(cell_name, filename);
makeCell(cell_name, filename);
makePorts();
@ -348,10 +351,8 @@ void
MakeTimingModel::makeInputOutputTimingArcs(const Pin *input_pin,
OutputPinDelays &output_pin_delays)
{
const DcalcAnalysisPt *dcalc_ap = corner_->findDcalcAnalysisPt(min_max_);
for (auto out_pin_delay : output_pin_delays) {
const Pin *output_pin = out_pin_delay.first;
Vertex *output_vertex = graph_->pinLoadVertex(output_pin);
OutputDelays &output_delays = out_pin_delay.second;
TimingArcAttrs *attrs = nullptr;
for (RiseFall *output_rf : RiseFall::range()) {
@ -365,8 +366,7 @@ MakeTimingModel::makeInputOutputTimingArcs(const Pin *input_pin,
network_->pathName(output_pin),
output_rf->shortName(),
delayAsString(delay, sta_));
Slew slew = graph_->slew(output_vertex, output_rf, dcalc_ap->index());
TimingModel *gate_model = makeScalarGateModel(delay, slew, output_rf);
TimingModel *gate_model = makeGateModelTable(output_pin, delay, output_rf);
if (attrs == nullptr)
attrs = new TimingArcAttrs();
attrs->setModel(output_rf, gate_model);
@ -389,7 +389,6 @@ MakeTimingModel::makeInputOutputTimingArcs(const Pin *input_pin,
void
MakeTimingModel::findClkedOutputPaths()
{
const DcalcAnalysisPt *dcalc_ap = corner_->findDcalcAnalysisPt(min_max_);
InstancePinIterator *output_iter = network_->pinIterator(network_->topInstance());
while (output_iter->hasNext()) {
Pin *output_pin = output_iter->next();
@ -419,8 +418,7 @@ MakeTimingModel::findClkedOutputPaths()
TimingArcAttrs *attrs = nullptr;
for (RiseFall *output_rf : RiseFall::range()) {
float delay = delays.value(output_rf, min_max_);
Slew slew = graph_->slew(output_vertex, output_rf, dcalc_ap->index());
TimingModel *gate_model = makeScalarGateModel(delay, slew, output_rf);
TimingModel *gate_model = makeGateModelTable(output_pin, delay, output_rf);
if (attrs == nullptr)
attrs = new TimingArcAttrs();
attrs->setModel(output_rf, gate_model);
@ -457,7 +455,7 @@ MakeTimingModel::makeScalarCheckModel(float value,
}
TimingModel *
MakeTimingModel::makeScalarGateModel(Delay delay,
MakeTimingModel::makeGateModelScalar(Delay delay,
Slew slew,
RiseFall *rf)
{
@ -474,6 +472,117 @@ MakeTimingModel::makeScalarGateModel(Delay delay,
return gate_model;
}
// Eval the driver pin model along its load capacitance
// axis and add the input to output 'delay' to the table values.
TimingModel *
MakeTimingModel::makeGateModelTable(const Pin *output_pin,
Delay delay,
RiseFall *rf)
{
const char *output_port_name = network_->name(network_->port(output_pin));
const DcalcAnalysisPt *dcalc_ap = corner_->findDcalcAnalysisPt(min_max_);
const Pvt *pvt = dcalc_ap->operatingConditions();
const OperatingConditions *op_cond = dcalc_ap->operatingConditions();
int lib_index = dcalc_ap->libertyIndex();
PinSet *drvrs = network_->drivers(network_->net(network_->term(output_pin)));
const Pin *drvr_pin = *drvrs->begin();
const LibertyPort *drvr_port = network_->libertyPort(drvr_pin);
if (drvr_port) {
const LibertyCell *drvr_cell = drvr_port->libertyCell();
LibertyCellTimingArcSetIterator set_iter(drvr_cell, nullptr, drvr_port);
while (set_iter.hasNext()) {
TimingArcSet *arc_set = set_iter.next();
TimingArcSetArcIterator arc_iter(arc_set);
while (arc_iter.hasNext()) {
TimingArc *drvr_arc = arc_iter.next();
// Use the first timing arc to simplify life.
if (drvr_arc->toEdge()->asRiseFall() == rf) {
const LibertyPort *gate_in_port = drvr_arc->from();
const Instance *drvr_inst = network_->instance(drvr_pin);
const Pin *gate_in_pin = network_->findPin(drvr_inst, gate_in_port);
if (gate_in_pin) {
Vertex *gate_in_vertex = graph_->pinLoadVertex(gate_in_pin);
Slew in_slew = graph_->slew(gate_in_vertex,
drvr_arc->fromEdge()->asRiseFall(),
dcalc_ap->index());
TimingModel *drvr_model = drvr_arc->cornerArc(lib_index)->model(op_cond);
GateTableModel *drvr_gate_model = dynamic_cast<GateTableModel*>(drvr_model);
if (drvr_gate_model) {
float output_load_cap = graph_delay_calc_->loadCap(output_pin, dcalc_ap);
ArcDelay drvr_self_delay;
Slew drvr_self_slew;
drvr_gate_model->gateDelay(drvr_cell, pvt, in_slew,
output_load_cap, 0.0, false,
drvr_self_delay, drvr_self_slew);
const TableModel *drvr_table = drvr_gate_model->delayModel();
const TableAxis *drvr_load_axis = loadCapacitanceAxis(drvr_table);
const FloatSeq *drvr_axis_values = drvr_load_axis->values();
FloatSeq *load_values = new FloatSeq;
FloatSeq *slew_values = new FloatSeq;
for (size_t i = 0; i < drvr_axis_values->size(); i++) {
float load_cap = (*drvr_axis_values)[i];
// get slew from driver input pin
ArcDelay gate_delay;
Slew gate_slew;
drvr_gate_model->gateDelay(drvr_cell, pvt, in_slew,
load_cap, 0.0, false,
gate_delay, gate_slew);
// Remove the self delay driving the output pin net load cap.
load_values->push_back(delay + gate_delay - drvr_self_delay);
slew_values->push_back(gate_slew);
}
FloatSeq *axis_values = new FloatSeq(*drvr_axis_values);
TableAxis *load_axis =
new TableAxis(TableAxisVariable::total_output_net_capacitance,
axis_values);
Table *delay_table = new Table1(load_values, load_axis, true);
Table *slew_table = new Table1(slew_values, load_axis, true);
string template_name;
template_name += output_port_name;
template_name += "_";;
template_name += std::to_string(tbl_template_index_++);
TableTemplate *tbl_template = new TableTemplate(template_name.c_str());
tbl_template->setAxis1(load_axis);
library_->addTableTemplate(tbl_template, TableTemplateType::delay);
TableModel *delay_model = new TableModel(delay_table, tbl_template,
ScaleFactorType::cell, rf);
TableModel *slew_model = new TableModel(slew_table, tbl_template,
ScaleFactorType::cell, rf);
GateTableModel *gate_model = new GateTableModel(delay_model, nullptr,
slew_model, nullptr);
return gate_model;
}
}
}
}
}
}
Vertex *output_vertex = graph_->pinLoadVertex(output_pin);
Slew slew = graph_->slew(output_vertex, rf, dcalc_ap->index());
return makeGateModelScalar(delay, slew, rf);
}
TableAxis *
MakeTimingModel::loadCapacitanceAxis(const TableModel *table)
{
if (table->axis1()->variable() == TableAxisVariable::total_output_net_capacitance)
return table->axis1();
else if (table->axis2()->variable() == TableAxisVariable::total_output_net_capacitance)
return table->axis2();
else if (table->axis3()->variable() == TableAxisVariable::total_output_net_capacitance)
return table->axis3();
else
return nullptr;
}
OutputDelays::OutputDelays()
{
rf_path_exists[RiseFall::riseIndex()][RiseFall::riseIndex()] = false;

View File

@ -69,9 +69,13 @@ private:
TimingModel *makeScalarCheckModel(float value,
ScaleFactorType scale_factor_type,
RiseFall *rf);
TimingModel *makeScalarGateModel(Delay delay,
TimingModel *makeGateModelScalar(Delay delay,
Slew slew,
RiseFall *rf);
TimingModel *makeGateModelTable(const Pin *output_pin,
Delay delay,
RiseFall *rf);
TableAxis *loadCapacitanceAxis(const TableModel *table);
LibertyPort *modelPort(const Pin *pin);
Sta *sta_;
@ -80,6 +84,7 @@ private:
const Corner *corner_;
MinMax *min_max_;
LibertyBuilder *lib_builder_;
int tbl_template_index_;
};
} // namespace