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);
|
||||
void writeTableModel(const TableModel *model);
|
||||
void writeTableModel0(const TableModel *model);
|
||||
void writeTableModel1(const TableModel *model);
|
||||
void writeTableModel2(const TableModel *model);
|
||||
void writeTableAxis(TableAxis *axis,
|
||||
int index);
|
||||
|
|
@ -373,6 +374,7 @@ LibertyWriter::writeTableModel(const TableModel *model)
|
|||
writeTableModel0(model);
|
||||
break;
|
||||
case 1:
|
||||
writeTableModel1(model);
|
||||
break;
|
||||
case 2:
|
||||
writeTableModel2(model);
|
||||
|
|
@ -391,6 +393,21 @@ LibertyWriter::writeTableModel0(const TableModel *model)
|
|||
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
|
||||
LibertyWriter::writeTableModel2(const TableModel *model)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ GateTableModel::GateTableModel(TableModel *delay_model,
|
|||
slew_model_(slew_model)
|
||||
{
|
||||
for (auto el_index : EarlyLate::rangeIndex()) {
|
||||
slew_sigma_models_[el_index] = slew_sigma_models[el_index];
|
||||
delay_sigma_models_[el_index] = delay_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 ? delay_sigma_models[el_index] : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#include "TimingArc.hh"
|
||||
#include "TableModel.hh"
|
||||
#include "liberty/LibertyBuilder.hh"
|
||||
#include "LibertyWriter.hh"
|
||||
#include "Network.hh"
|
||||
#include "PortDirection.hh"
|
||||
#include "Corner.hh"
|
||||
|
|
@ -36,16 +35,6 @@
|
|||
|
||||
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,
|
||||
Sta *sta) :
|
||||
StaState(sta),
|
||||
|
|
@ -61,21 +50,7 @@ MakeTimingModel::~MakeTimingModel()
|
|||
delete lib_builder_;
|
||||
}
|
||||
|
||||
void
|
||||
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
|
||||
LibertyLibrary *
|
||||
MakeTimingModel::makeTimingModel(const char *cell_name,
|
||||
const char *filename)
|
||||
{
|
||||
|
|
@ -86,13 +61,11 @@ MakeTimingModel::makeTimingModel(const char *cell_name,
|
|||
for (Clock *clk : *sdc_->clocks())
|
||||
sta_->setPropagatedClock(clk);
|
||||
|
||||
#if 0
|
||||
findInputToOutputPaths();
|
||||
findInputSetupHolds();
|
||||
findClkedOutputPaths();
|
||||
#endif
|
||||
findClkedOutputPaths();
|
||||
cell_->finish(false, report_, debug_);
|
||||
return library_;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -269,37 +242,52 @@ MakeTimingModel::findClkedOutputPaths()
|
|||
while (output_iter->hasNext()) {
|
||||
Pin *output_pin = output_iter->next();
|
||||
if (network_->direction(output_pin)->isOutput()) {
|
||||
LibertyPort *output_port = modelPort(output_pin);
|
||||
for (Clock *clk : *sdc_->clocks()) {
|
||||
for (RiseFall *clk_rf : RiseFall::range()) {
|
||||
for (RiseFall *output_rf : RiseFall::range()) {
|
||||
RiseFallBoth *output_rf1 = output_rf->asRiseFallBoth();
|
||||
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);
|
||||
for (const Pin *clk_pin : clk->pins()) {
|
||||
LibertyPort *clk_port = modelPort(clk_pin);
|
||||
for (RiseFall *clk_rf : RiseFall::range()) {
|
||||
TimingArcAttrs *attrs = nullptr;
|
||||
for (RiseFall *output_rf : RiseFall::range()) {
|
||||
RiseFallBoth *output_rf1 = output_rf->asRiseFallBoth();
|
||||
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;
|
||||
from_clks->insert(clk);
|
||||
ExceptionFrom *from = sta_->makeExceptionFrom(nullptr, from_clks, nullptr,
|
||||
clk_rf->asRiseFallBoth());
|
||||
PinSet *to_pins = new PinSet;
|
||||
to_pins->insert(output_pin);
|
||||
ExceptionTo *to = sta_->makeExceptionTo(to_pins, nullptr, nullptr,
|
||||
output_rf1, output_rf1);
|
||||
ClockSet *from_clks = new ClockSet;
|
||||
from_clks->insert(clk);
|
||||
ExceptionFrom *from = sta_->makeExceptionFrom(nullptr, from_clks, nullptr,
|
||||
clk_rf->asRiseFallBoth());
|
||||
PinSet *to_pins = new PinSet;
|
||||
to_pins->insert(output_pin);
|
||||
ExceptionTo *to = sta_->makeExceptionTo(to_pins, nullptr, nullptr,
|
||||
output_rf1, output_rf1);
|
||||
|
||||
PathEndSeq *ends = sta_->findPathEnds(from, nullptr, to, false, corner_, min_max1,
|
||||
1, 1, false, -INF, INF, false, nullptr,
|
||||
true, false, false, false, false, false);
|
||||
if (!ends->empty()) {
|
||||
debugPrint(debug_, "make_timing_model", 1, "clock %s -> output %s",
|
||||
clk->name(),
|
||||
network_->pathName(output_pin));
|
||||
PathEnd *end = (*ends)[0];
|
||||
if (debug_->check("make_timing_model", 2))
|
||||
sta_->reportPathEnd(end);
|
||||
PathEndSeq *ends = sta_->findPathEnds(from, nullptr, to, false, corner_, min_max1,
|
||||
1, 1, false, -INF, INF, false, nullptr,
|
||||
true, false, false, false, false, false);
|
||||
if (!ends->empty()) {
|
||||
debugPrint(debug_, "make_timing_model", 1, "clock %s -> output %s",
|
||||
clk->name(),
|
||||
network_->pathName(output_pin));
|
||||
PathEnd *end = (*ends)[0];
|
||||
if (debug_->check("make_timing_model", 2))
|
||||
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(),
|
||||
clk, clk_rf, MinMaxAll::max());
|
||||
if (attrs)
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -31,11 +31,8 @@ public:
|
|||
MakeTimingModel(const Corner *corner,
|
||||
Sta *sta);
|
||||
~MakeTimingModel();
|
||||
void writeTimingModel(const char *cell_name,
|
||||
const char *filename);
|
||||
void makeTimingModel(const char *cell_name,
|
||||
const char *filename);
|
||||
void writeLibertyFile(const char *filename);
|
||||
LibertyLibrary *makeTimingModel(const char *cell_name,
|
||||
const char *filename);
|
||||
|
||||
private:
|
||||
void makeLibrary(const char *cell_name,
|
||||
|
|
@ -51,6 +48,9 @@ private:
|
|||
TimingModel *makeScalarCheckModel(float value,
|
||||
ScaleFactorType scale_factor_type,
|
||||
RiseFall *rf);
|
||||
TimingModel *makeScalarGateModel(Delay delay,
|
||||
Slew slew,
|
||||
RiseFall *rf);
|
||||
|
||||
Sta *sta_;
|
||||
LibertyLibrary *library_;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "EquivCells.hh"
|
||||
#include "Liberty.hh"
|
||||
#include "liberty/LibertyReader.hh"
|
||||
#include "LibertyWriter.hh"
|
||||
#include "SdcNetwork.hh"
|
||||
#include "MakeConcreteNetwork.hh"
|
||||
#include "PortDirection.hh"
|
||||
|
|
@ -5572,7 +5573,9 @@ Sta::writeTimingModel(const char *cell_name,
|
|||
const char *filename,
|
||||
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