write_timing_model
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
548ad96708
commit
754ab9e220
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
|
|
@ -52,6 +52,7 @@ protected:
|
||||||
RiseFall *rf);
|
RiseFall *rf);
|
||||||
void writeTableModel(const TableModel *model);
|
void writeTableModel(const TableModel *model);
|
||||||
void writeTableModel0(const TableModel *model);
|
void writeTableModel0(const TableModel *model);
|
||||||
|
void writeTableModel1(const TableModel *model);
|
||||||
void writeTableModel2(const TableModel *model);
|
void writeTableModel2(const TableModel *model);
|
||||||
void writeTableAxis(TableAxis *axis,
|
void writeTableAxis(TableAxis *axis,
|
||||||
int index);
|
int index);
|
||||||
|
|
@ -373,6 +374,7 @@ LibertyWriter::writeTableModel(const TableModel *model)
|
||||||
writeTableModel0(model);
|
writeTableModel0(model);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
writeTableModel1(model);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
writeTableModel2(model);
|
writeTableModel2(model);
|
||||||
|
|
@ -391,6 +393,21 @@ LibertyWriter::writeTableModel0(const TableModel *model)
|
||||||
time_unit_->asString(value, 5));
|
time_unit_->asString(value, 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LibertyWriter::writeTableModel1(const TableModel *model)
|
||||||
|
{
|
||||||
|
fprintf(stream_, " values(\"");
|
||||||
|
bool first_col = true;
|
||||||
|
for (size_t index1 = 0; index1 < model->axis1()->size(); index1++) {
|
||||||
|
float value = model->value(index1, 0, 0);
|
||||||
|
if (!first_col)
|
||||||
|
fprintf(stream_, ",");
|
||||||
|
fprintf(stream_, "%s", time_unit_->asString(value, 5));
|
||||||
|
first_col = false;
|
||||||
|
}
|
||||||
|
fprintf(stream_, "\");\n");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LibertyWriter::writeTableModel2(const TableModel *model)
|
LibertyWriter::writeTableModel2(const TableModel *model)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ GateTableModel::GateTableModel(TableModel *delay_model,
|
||||||
slew_model_(slew_model)
|
slew_model_(slew_model)
|
||||||
{
|
{
|
||||||
for (auto el_index : EarlyLate::rangeIndex()) {
|
for (auto el_index : EarlyLate::rangeIndex()) {
|
||||||
slew_sigma_models_[el_index] = slew_sigma_models[el_index];
|
slew_sigma_models_[el_index] = slew_sigma_models ? slew_sigma_models[el_index] : nullptr;
|
||||||
delay_sigma_models_[el_index] = delay_sigma_models[el_index];
|
delay_sigma_models_[el_index] = delay_sigma_models ? delay_sigma_models[el_index] : nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
#include "TimingArc.hh"
|
#include "TimingArc.hh"
|
||||||
#include "TableModel.hh"
|
#include "TableModel.hh"
|
||||||
#include "liberty/LibertyBuilder.hh"
|
#include "liberty/LibertyBuilder.hh"
|
||||||
#include "LibertyWriter.hh"
|
|
||||||
#include "Network.hh"
|
#include "Network.hh"
|
||||||
#include "PortDirection.hh"
|
#include "PortDirection.hh"
|
||||||
#include "Corner.hh"
|
#include "Corner.hh"
|
||||||
|
|
@ -36,16 +35,6 @@
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
void
|
|
||||||
writeTimingModel(const char *cell_name,
|
|
||||||
const char *filename,
|
|
||||||
const Corner *corner,
|
|
||||||
Sta *sta)
|
|
||||||
{
|
|
||||||
MakeTimingModel writer(corner, sta);
|
|
||||||
writer.writeTimingModel(cell_name, filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
MakeTimingModel::MakeTimingModel(const Corner *corner,
|
MakeTimingModel::MakeTimingModel(const Corner *corner,
|
||||||
Sta *sta) :
|
Sta *sta) :
|
||||||
StaState(sta),
|
StaState(sta),
|
||||||
|
|
@ -61,21 +50,7 @@ MakeTimingModel::~MakeTimingModel()
|
||||||
delete lib_builder_;
|
delete lib_builder_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
LibertyLibrary *
|
||||||
MakeTimingModel::writeTimingModel(const char *cell_name,
|
|
||||||
const char *filename)
|
|
||||||
{
|
|
||||||
makeTimingModel(cell_name, filename);
|
|
||||||
writeLibertyFile(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MakeTimingModel::writeLibertyFile(const char *filename)
|
|
||||||
{
|
|
||||||
writeLiberty(library_, filename, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MakeTimingModel::makeTimingModel(const char *cell_name,
|
MakeTimingModel::makeTimingModel(const char *cell_name,
|
||||||
const char *filename)
|
const char *filename)
|
||||||
{
|
{
|
||||||
|
|
@ -86,13 +61,11 @@ MakeTimingModel::makeTimingModel(const char *cell_name,
|
||||||
for (Clock *clk : *sdc_->clocks())
|
for (Clock *clk : *sdc_->clocks())
|
||||||
sta_->setPropagatedClock(clk);
|
sta_->setPropagatedClock(clk);
|
||||||
|
|
||||||
#if 0
|
|
||||||
findInputToOutputPaths();
|
findInputToOutputPaths();
|
||||||
findInputSetupHolds();
|
findInputSetupHolds();
|
||||||
findClkedOutputPaths();
|
findClkedOutputPaths();
|
||||||
#endif
|
|
||||||
findClkedOutputPaths();
|
|
||||||
cell_->finish(false, report_, debug_);
|
cell_->finish(false, report_, debug_);
|
||||||
|
return library_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -269,37 +242,52 @@ MakeTimingModel::findClkedOutputPaths()
|
||||||
while (output_iter->hasNext()) {
|
while (output_iter->hasNext()) {
|
||||||
Pin *output_pin = output_iter->next();
|
Pin *output_pin = output_iter->next();
|
||||||
if (network_->direction(output_pin)->isOutput()) {
|
if (network_->direction(output_pin)->isOutput()) {
|
||||||
|
LibertyPort *output_port = modelPort(output_pin);
|
||||||
for (Clock *clk : *sdc_->clocks()) {
|
for (Clock *clk : *sdc_->clocks()) {
|
||||||
for (RiseFall *clk_rf : RiseFall::range()) {
|
for (const Pin *clk_pin : clk->pins()) {
|
||||||
for (RiseFall *output_rf : RiseFall::range()) {
|
LibertyPort *clk_port = modelPort(clk_pin);
|
||||||
RiseFallBoth *output_rf1 = output_rf->asRiseFallBoth();
|
for (RiseFall *clk_rf : RiseFall::range()) {
|
||||||
MinMax *min_max = MinMax::max();
|
TimingArcAttrs *attrs = nullptr;
|
||||||
MinMaxAll *min_max1 = min_max->asMinMaxAll();
|
for (RiseFall *output_rf : RiseFall::range()) {
|
||||||
sta_->setOutputDelay(output_pin, output_rf1, clk, clk_rf,
|
RiseFallBoth *output_rf1 = output_rf->asRiseFallBoth();
|
||||||
nullptr, false, false, min_max1, false, 0.0);
|
MinMax *min_max = MinMax::max();
|
||||||
|
MinMaxAll *min_max1 = min_max->asMinMaxAll();
|
||||||
|
sta_->setOutputDelay(output_pin, output_rf1, clk, clk_rf,
|
||||||
|
nullptr, false, false, min_max1, false, 0.0);
|
||||||
|
|
||||||
ClockSet *from_clks = new ClockSet;
|
ClockSet *from_clks = new ClockSet;
|
||||||
from_clks->insert(clk);
|
from_clks->insert(clk);
|
||||||
ExceptionFrom *from = sta_->makeExceptionFrom(nullptr, from_clks, nullptr,
|
ExceptionFrom *from = sta_->makeExceptionFrom(nullptr, from_clks, nullptr,
|
||||||
clk_rf->asRiseFallBoth());
|
clk_rf->asRiseFallBoth());
|
||||||
PinSet *to_pins = new PinSet;
|
PinSet *to_pins = new PinSet;
|
||||||
to_pins->insert(output_pin);
|
to_pins->insert(output_pin);
|
||||||
ExceptionTo *to = sta_->makeExceptionTo(to_pins, nullptr, nullptr,
|
ExceptionTo *to = sta_->makeExceptionTo(to_pins, nullptr, nullptr,
|
||||||
output_rf1, output_rf1);
|
output_rf1, output_rf1);
|
||||||
|
|
||||||
PathEndSeq *ends = sta_->findPathEnds(from, nullptr, to, false, corner_, min_max1,
|
PathEndSeq *ends = sta_->findPathEnds(from, nullptr, to, false, corner_, min_max1,
|
||||||
1, 1, false, -INF, INF, false, nullptr,
|
1, 1, false, -INF, INF, false, nullptr,
|
||||||
true, false, false, false, false, false);
|
true, false, false, false, false, false);
|
||||||
if (!ends->empty()) {
|
if (!ends->empty()) {
|
||||||
debugPrint(debug_, "make_timing_model", 1, "clock %s -> output %s",
|
debugPrint(debug_, "make_timing_model", 1, "clock %s -> output %s",
|
||||||
clk->name(),
|
clk->name(),
|
||||||
network_->pathName(output_pin));
|
network_->pathName(output_pin));
|
||||||
PathEnd *end = (*ends)[0];
|
PathEnd *end = (*ends)[0];
|
||||||
if (debug_->check("make_timing_model", 2))
|
if (debug_->check("make_timing_model", 2))
|
||||||
sta_->reportPathEnd(end);
|
sta_->reportPathEnd(end);
|
||||||
|
Arrival delay = end->path()->arrival(sta_);
|
||||||
|
Slew slew = end->path()->slew(sta_);
|
||||||
|
TimingModel *check_model = makeScalarGateModel(delay, slew, output_rf);
|
||||||
|
if (attrs == nullptr)
|
||||||
|
attrs = new TimingArcAttrs();
|
||||||
|
attrs->setModel(output_rf, check_model);
|
||||||
|
}
|
||||||
|
sta_->removeOutputDelay(output_pin, output_rf1, clk, clk_rf, MinMaxAll::max());
|
||||||
}
|
}
|
||||||
sta_->removeOutputDelay(output_pin, RiseFallBoth::riseFall(),
|
if (attrs)
|
||||||
clk, clk_rf, MinMaxAll::max());
|
lib_builder_->makeFromTransitionArcs(cell_, clk_port,
|
||||||
|
output_port, nullptr,
|
||||||
|
clk_rf, TimingRole::regClkToQ(),
|
||||||
|
attrs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -327,4 +315,22 @@ MakeTimingModel::makeScalarCheckModel(float value,
|
||||||
return check_model;
|
return check_model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimingModel *
|
||||||
|
MakeTimingModel::makeScalarGateModel(Delay delay,
|
||||||
|
Slew slew,
|
||||||
|
RiseFall *rf)
|
||||||
|
{
|
||||||
|
Table *delay_table = new Table0(delay);
|
||||||
|
Table *slew_table = new Table0(slew);
|
||||||
|
TableTemplate *tbl_template =
|
||||||
|
library_->findTableTemplate("scalar", 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;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,8 @@ public:
|
||||||
MakeTimingModel(const Corner *corner,
|
MakeTimingModel(const Corner *corner,
|
||||||
Sta *sta);
|
Sta *sta);
|
||||||
~MakeTimingModel();
|
~MakeTimingModel();
|
||||||
void writeTimingModel(const char *cell_name,
|
LibertyLibrary *makeTimingModel(const char *cell_name,
|
||||||
const char *filename);
|
const char *filename);
|
||||||
void makeTimingModel(const char *cell_name,
|
|
||||||
const char *filename);
|
|
||||||
void writeLibertyFile(const char *filename);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void makeLibrary(const char *cell_name,
|
void makeLibrary(const char *cell_name,
|
||||||
|
|
@ -51,6 +48,9 @@ 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,
|
||||||
|
Slew slew,
|
||||||
|
RiseFall *rf);
|
||||||
|
|
||||||
Sta *sta_;
|
Sta *sta_;
|
||||||
LibertyLibrary *library_;
|
LibertyLibrary *library_;
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include "EquivCells.hh"
|
#include "EquivCells.hh"
|
||||||
#include "Liberty.hh"
|
#include "Liberty.hh"
|
||||||
#include "liberty/LibertyReader.hh"
|
#include "liberty/LibertyReader.hh"
|
||||||
|
#include "LibertyWriter.hh"
|
||||||
#include "SdcNetwork.hh"
|
#include "SdcNetwork.hh"
|
||||||
#include "MakeConcreteNetwork.hh"
|
#include "MakeConcreteNetwork.hh"
|
||||||
#include "PortDirection.hh"
|
#include "PortDirection.hh"
|
||||||
|
|
@ -5572,7 +5573,9 @@ Sta::writeTimingModel(const char *cell_name,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
const Corner *corner)
|
const Corner *corner)
|
||||||
{
|
{
|
||||||
sta::writeTimingModel(cell_name, filename, corner, this);
|
MakeTimingModel maker(corner, this);
|
||||||
|
LibertyLibrary *library = maker.makeTimingModel(cell_name, filename);
|
||||||
|
writeLiberty(library, filename, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue