make timing model table models
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
1eb6da19e9
commit
cf9e720582
|
|
@ -38,6 +38,7 @@
|
||||||
#include "Search.hh"
|
#include "Search.hh"
|
||||||
#include "Sta.hh"
|
#include "Sta.hh"
|
||||||
#include "VisitPathEnds.hh"
|
#include "VisitPathEnds.hh"
|
||||||
|
#include "ArcDelayCalc.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
|
|
@ -49,7 +50,8 @@ MakeTimingModel::MakeTimingModel(const Corner *corner,
|
||||||
sta_(sta),
|
sta_(sta),
|
||||||
corner_(corner),
|
corner_(corner),
|
||||||
min_max_(MinMax::max()),
|
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,
|
MakeTimingModel::makeTimingModel(const char *cell_name,
|
||||||
const char *filename)
|
const char *filename)
|
||||||
{
|
{
|
||||||
|
tbl_template_index_ = 1;
|
||||||
makeLibrary(cell_name, filename);
|
makeLibrary(cell_name, filename);
|
||||||
makeCell(cell_name, filename);
|
makeCell(cell_name, filename);
|
||||||
makePorts();
|
makePorts();
|
||||||
|
|
@ -348,10 +351,8 @@ void
|
||||||
MakeTimingModel::makeInputOutputTimingArcs(const Pin *input_pin,
|
MakeTimingModel::makeInputOutputTimingArcs(const Pin *input_pin,
|
||||||
OutputPinDelays &output_pin_delays)
|
OutputPinDelays &output_pin_delays)
|
||||||
{
|
{
|
||||||
const DcalcAnalysisPt *dcalc_ap = corner_->findDcalcAnalysisPt(min_max_);
|
|
||||||
for (auto out_pin_delay : output_pin_delays) {
|
for (auto out_pin_delay : output_pin_delays) {
|
||||||
const Pin *output_pin = out_pin_delay.first;
|
const Pin *output_pin = out_pin_delay.first;
|
||||||
Vertex *output_vertex = graph_->pinLoadVertex(output_pin);
|
|
||||||
OutputDelays &output_delays = out_pin_delay.second;
|
OutputDelays &output_delays = out_pin_delay.second;
|
||||||
TimingArcAttrs *attrs = nullptr;
|
TimingArcAttrs *attrs = nullptr;
|
||||||
for (RiseFall *output_rf : RiseFall::range()) {
|
for (RiseFall *output_rf : RiseFall::range()) {
|
||||||
|
|
@ -365,8 +366,7 @@ MakeTimingModel::makeInputOutputTimingArcs(const Pin *input_pin,
|
||||||
network_->pathName(output_pin),
|
network_->pathName(output_pin),
|
||||||
output_rf->shortName(),
|
output_rf->shortName(),
|
||||||
delayAsString(delay, sta_));
|
delayAsString(delay, sta_));
|
||||||
Slew slew = graph_->slew(output_vertex, output_rf, dcalc_ap->index());
|
TimingModel *gate_model = makeGateModelTable(output_pin, delay, output_rf);
|
||||||
TimingModel *gate_model = makeScalarGateModel(delay, slew, output_rf);
|
|
||||||
if (attrs == nullptr)
|
if (attrs == nullptr)
|
||||||
attrs = new TimingArcAttrs();
|
attrs = new TimingArcAttrs();
|
||||||
attrs->setModel(output_rf, gate_model);
|
attrs->setModel(output_rf, gate_model);
|
||||||
|
|
@ -389,7 +389,6 @@ MakeTimingModel::makeInputOutputTimingArcs(const Pin *input_pin,
|
||||||
void
|
void
|
||||||
MakeTimingModel::findClkedOutputPaths()
|
MakeTimingModel::findClkedOutputPaths()
|
||||||
{
|
{
|
||||||
const DcalcAnalysisPt *dcalc_ap = corner_->findDcalcAnalysisPt(min_max_);
|
|
||||||
InstancePinIterator *output_iter = network_->pinIterator(network_->topInstance());
|
InstancePinIterator *output_iter = network_->pinIterator(network_->topInstance());
|
||||||
while (output_iter->hasNext()) {
|
while (output_iter->hasNext()) {
|
||||||
Pin *output_pin = output_iter->next();
|
Pin *output_pin = output_iter->next();
|
||||||
|
|
@ -419,8 +418,7 @@ MakeTimingModel::findClkedOutputPaths()
|
||||||
TimingArcAttrs *attrs = nullptr;
|
TimingArcAttrs *attrs = nullptr;
|
||||||
for (RiseFall *output_rf : RiseFall::range()) {
|
for (RiseFall *output_rf : RiseFall::range()) {
|
||||||
float delay = delays.value(output_rf, min_max_);
|
float delay = delays.value(output_rf, min_max_);
|
||||||
Slew slew = graph_->slew(output_vertex, output_rf, dcalc_ap->index());
|
TimingModel *gate_model = makeGateModelTable(output_pin, delay, output_rf);
|
||||||
TimingModel *gate_model = makeScalarGateModel(delay, slew, output_rf);
|
|
||||||
if (attrs == nullptr)
|
if (attrs == nullptr)
|
||||||
attrs = new TimingArcAttrs();
|
attrs = new TimingArcAttrs();
|
||||||
attrs->setModel(output_rf, gate_model);
|
attrs->setModel(output_rf, gate_model);
|
||||||
|
|
@ -457,7 +455,7 @@ MakeTimingModel::makeScalarCheckModel(float value,
|
||||||
}
|
}
|
||||||
|
|
||||||
TimingModel *
|
TimingModel *
|
||||||
MakeTimingModel::makeScalarGateModel(Delay delay,
|
MakeTimingModel::makeGateModelScalar(Delay delay,
|
||||||
Slew slew,
|
Slew slew,
|
||||||
RiseFall *rf)
|
RiseFall *rf)
|
||||||
{
|
{
|
||||||
|
|
@ -474,6 +472,117 @@ MakeTimingModel::makeScalarGateModel(Delay delay,
|
||||||
return gate_model;
|
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()
|
OutputDelays::OutputDelays()
|
||||||
{
|
{
|
||||||
rf_path_exists[RiseFall::riseIndex()][RiseFall::riseIndex()] = false;
|
rf_path_exists[RiseFall::riseIndex()][RiseFall::riseIndex()] = false;
|
||||||
|
|
|
||||||
|
|
@ -69,9 +69,13 @@ private:
|
||||||
TimingModel *makeScalarCheckModel(float value,
|
TimingModel *makeScalarCheckModel(float value,
|
||||||
ScaleFactorType scale_factor_type,
|
ScaleFactorType scale_factor_type,
|
||||||
RiseFall *rf);
|
RiseFall *rf);
|
||||||
TimingModel *makeScalarGateModel(Delay delay,
|
TimingModel *makeGateModelScalar(Delay delay,
|
||||||
Slew slew,
|
Slew slew,
|
||||||
RiseFall *rf);
|
RiseFall *rf);
|
||||||
|
TimingModel *makeGateModelTable(const Pin *output_pin,
|
||||||
|
Delay delay,
|
||||||
|
RiseFall *rf);
|
||||||
|
TableAxis *loadCapacitanceAxis(const TableModel *table);
|
||||||
LibertyPort *modelPort(const Pin *pin);
|
LibertyPort *modelPort(const Pin *pin);
|
||||||
|
|
||||||
Sta *sta_;
|
Sta *sta_;
|
||||||
|
|
@ -80,6 +84,7 @@ private:
|
||||||
const Corner *corner_;
|
const Corner *corner_;
|
||||||
MinMax *min_max_;
|
MinMax *min_max_;
|
||||||
LibertyBuilder *lib_builder_;
|
LibertyBuilder *lib_builder_;
|
||||||
|
int tbl_template_index_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue