make timing model header

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2023-04-06 07:42:50 -07:00
parent d17a232575
commit eb4839e145
4 changed files with 189 additions and 143 deletions

View File

@ -15,6 +15,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "MakeTimingModel.hh"
#include "MakeTimingModelPvt.hh"
#include <algorithm>
#include <map>
@ -45,16 +46,33 @@ namespace sta {
using std::max;
using std::make_shared;
MakeTimingModel::MakeTimingModel(const Corner *corner,
LibertyLibrary *
makeTimingModel(const char *lib_name,
const char *cell_name,
const char *filename,
const Corner *corner,
Sta *sta)
{
MakeTimingModel maker(lib_name, cell_name, filename, corner, sta);
return maker.makeTimingModel();
}
MakeTimingModel::MakeTimingModel(const char *lib_name,
const char *cell_name,
const char *filename,
const Corner *corner,
Sta *sta) :
StaState(sta),
sta_(sta),
cell_(nullptr),
lib_name_(lib_name),
cell_name_(cell_name),
filename_(filename),
corner_(corner),
cell_(nullptr),
min_max_(MinMax::max()),
lib_builder_(new LibertyBuilder),
tbl_template_index_(1),
sdc_backup_(nullptr)
sdc_backup_(nullptr),
sta_(sta)
{
}
@ -64,15 +82,13 @@ MakeTimingModel::~MakeTimingModel()
}
LibertyLibrary *
MakeTimingModel::makeTimingModel(const char *lib_name,
const char *cell_name,
const char *filename)
MakeTimingModel::makeTimingModel()
{
saveSdc();
tbl_template_index_ = 1;
makeLibrary(lib_name, filename);
makeCell(cell_name, filename);
makeLibrary();
makeCell();
makePorts();
sta_->searchPreamble();
@ -87,7 +103,7 @@ MakeTimingModel::makeTimingModel(const char *lib_name,
return library_;
}
// Move set_input_delay/set_output_delay/set_load's to the side.
// Move sdc commands used by makeTimingModel to the side.
void
MakeTimingModel::saveSdc()
{
@ -109,10 +125,9 @@ MakeTimingModel::restoreSdc()
}
void
MakeTimingModel::makeLibrary(const char *lib_name,
const char *filename)
MakeTimingModel::makeLibrary()
{
library_ = network_->makeLibertyLibrary(lib_name, filename);
library_ = network_->makeLibertyLibrary(lib_name_, filename_);
LibertyLibrary *default_lib = network_->defaultLibertyLibrary();
*library_->units()->timeUnit() = *default_lib->units()->timeUnit();
*library_->units()->capacitanceUnit() = *default_lib->units()->capacitanceUnit();
@ -136,10 +151,9 @@ MakeTimingModel::makeLibrary(const char *lib_name,
}
void
MakeTimingModel::makeCell(const char *cell_name,
const char *filename)
MakeTimingModel::makeCell()
{
cell_ = lib_builder_->makeCell(library_, cell_name, filename);
cell_ = lib_builder_->makeCell(library_, cell_name_, filename_);
}
void
@ -202,21 +216,18 @@ public:
virtual ~MakeEndTimingArcs() {}
virtual PathEndVisitor *copy() const;
virtual void visit(PathEnd *path_end);
void setInputPin(const Pin *input_pin);
void setInputRf(const RiseFall *input_rf);
const ClockEdgeDelays &margins() const { return margins_; }
private:
Sta *sta_;
const Pin *input_pin_;
const RiseFall *input_rf_;
ClockEdgeDelays margins_;
Sta *sta_;
};
MakeEndTimingArcs::MakeEndTimingArcs(Sta *sta) :
sta_(sta),
input_pin_(nullptr),
input_rf_(nullptr)
input_rf_(nullptr),
sta_(sta)
{
}
@ -226,13 +237,6 @@ MakeEndTimingArcs::copy() const
return new MakeEndTimingArcs(*this);
}
void
MakeEndTimingArcs::setInputPin(const Pin *input_pin)
{
input_pin_ = input_pin;
margins_.clear();
}
void
MakeEndTimingArcs::setInputRf(const RiseFall *input_rf)
{
@ -257,8 +261,7 @@ MakeEndTimingArcs::visit(PathEnd *path_end)
? data_delay - clk_latency + check_margin
: clk_latency - data_delay + check_margin;
float delay1 = delayAsFloat(margin, MinMax::max(), sta_);
debugPrint(debug, "make_timing_model", 2, "%s %s -> %s clock %s %s %s %s",
network->pathName(input_pin_),
debugPrint(debug, "make_timing_model", 2, "%s -> %s clock %s %s %s %s",
input_rf_->shortName(),
network->pathName(src_path->pin(sta_)),
tgt_clk_edge->name(),
@ -285,44 +288,53 @@ MakeEndTimingArcs::visit(PathEnd *path_end)
void
MakeTimingModel::findTimingFromInputs()
{
VisitPathEnds visit_ends(sta_);
MakeEndTimingArcs end_visitor(sta_);
InstancePinIterator *input_iter = network_->pinIterator(network_->topInstance());
while (input_iter->hasNext()) {
Pin *input_pin = input_iter->next();
if (network_->direction(input_pin)->isInput()
&& !sta_->isClockSrc(input_pin)) {
end_visitor.setInputPin(input_pin);
OutputPinDelays output_delays;
for (RiseFall *input_rf : RiseFall::range()) {
RiseFallBoth *input_rf1 = input_rf->asRiseFallBoth();
sta_->setInputDelay(input_pin, input_rf1,
sdc_->defaultArrivalClock(),
sdc_->defaultArrivalClockEdge()->transition(),
nullptr, false, false, MinMaxAll::all(), true, 0.0);
PinSet *from_pins = new PinSet(network_);
from_pins->insert(input_pin);
ExceptionFrom *from = sta_->makeExceptionFrom(from_pins, nullptr, nullptr,
input_rf1);
search_->deleteFilteredArrivals();
search_->findFilteredArrivals(from, nullptr, nullptr, false);
end_visitor.setInputRf(input_rf);
for (Vertex *end : *search_->endpoints())
visit_ends.visitPathEnds(end, corner_, MinMaxAll::all(), true, &end_visitor);
findOutputDelays(input_rf, output_delays);
sta_->removeInputDelay(input_pin, input_rf1,
sdc_->defaultArrivalClock(),
sdc_->defaultArrivalClockEdge()->transition(),
MinMaxAll::all());
}
makeSetupHoldTimingArcs(input_pin, end_visitor.margins());
makeInputOutputTimingArcs(input_pin, output_delays);
}
Instance *top_inst = network_->topInstance();
Cell *top_cell = network_->cell(top_inst);
CellPortBitIterator *port_iter = network_->portBitIterator(top_cell);
while (port_iter->hasNext()) {
Port *input_port = port_iter->next();
if (network_->direction(input_port)->isInput())
findTimingFromInput(input_port);
}
delete port_iter;
}
void
MakeTimingModel::findTimingFromInput(Port *input_port)
{
Instance *top_inst = network_->topInstance();
Pin *input_pin = network_->findPin(top_inst, input_port);
if (!sta_->isClockSrc(input_pin)) {
MakeEndTimingArcs end_visitor(sta_);
OutputPinDelays output_delays;
for (RiseFall *input_rf : RiseFall::range()) {
RiseFallBoth *input_rf1 = input_rf->asRiseFallBoth();
sta_->setInputDelay(input_pin, input_rf1,
sdc_->defaultArrivalClock(),
sdc_->defaultArrivalClockEdge()->transition(),
nullptr, false, false, MinMaxAll::all(), true, 0.0);
PinSet *from_pins = new PinSet(network_);
from_pins->insert(input_pin);
ExceptionFrom *from = sta_->makeExceptionFrom(from_pins, nullptr, nullptr,
input_rf1);
search_->deleteFilteredArrivals();
search_->findFilteredArrivals(from, nullptr, nullptr, false);
end_visitor.setInputRf(input_rf);
VisitPathEnds visit_ends(sta_);
for (Vertex *end : *search_->endpoints())
visit_ends.visitPathEnds(end, corner_, MinMaxAll::all(), true, &end_visitor);
findOutputDelays(input_rf, output_delays);
sta_->removeInputDelay(input_pin, input_rf1,
sdc_->defaultArrivalClock(),
sdc_->defaultArrivalClockEdge()->transition(),
MinMaxAll::all());
}
makeSetupHoldTimingArcs(input_pin, end_visitor.margins());
makeInputOutputTimingArcs(input_pin, output_delays);
}
delete input_iter;
}
void

View File

@ -16,81 +16,17 @@
#pragma once
#include <map>
#include "LibertyClass.hh"
#include "SdcClass.hh"
#include "SearchClass.hh"
#include "StaState.hh"
#include "RiseFallMinMax.hh"
namespace sta {
class LibertyLibrary;
class Corner;
class Sta;
class LibertyBuilder;
class OutputDelays
{
public:
OutputDelays();
TimingSense timingSense() const;
RiseFallMinMax delays;
// input edge -> output edge path exists for unateness
bool rf_path_exists[RiseFall::index_count][RiseFall::index_count];
};
typedef std::map<const ClockEdge*, RiseFallMinMax> ClockEdgeDelays;
typedef std::map<const Pin *, OutputDelays> OutputPinDelays;
class MakeTimingModel : public StaState
{
public:
MakeTimingModel(const Corner *corner,
Sta *sta);
~MakeTimingModel();
LibertyLibrary *makeTimingModel(const char *lib_name,
const char *cell_name,
const char *filename);
private:
void makeLibrary(const char *lib_name,
const char *filename);
void makeCell(const char *cell_name,
const char *filename);
void makePorts();
void checkClock(Clock *clk);
void findTimingFromInputs();
void findClkedOutputPaths();
void findOutputDelays(const RiseFall *input_rf,
OutputPinDelays &output_pin_delays);
void makeSetupHoldTimingArcs(const Pin *input_pin,
const ClockEdgeDelays &clk_margins);
void makeInputOutputTimingArcs(const Pin *input_pin,
OutputPinDelays &output_pin_delays);
TimingModel *makeScalarCheckModel(float value,
ScaleFactorType scale_factor_type,
RiseFall *rf);
TimingModel *makeGateModelScalar(Delay delay,
Slew slew,
RiseFall *rf);
TimingModel *makeGateModelTable(const Pin *output_pin,
Delay delay,
RiseFall *rf);
TableAxisPtr loadCapacitanceAxis(const TableModel *table);
LibertyPort *modelPort(const Pin *pin);
void saveSdc();
void restoreSdc();
Sta *sta_;
LibertyLibrary *library_;
LibertyCell *cell_;
const Corner *corner_;
MinMax *min_max_;
LibertyBuilder *lib_builder_;
int tbl_template_index_;
Sdc *sdc_backup_;
};
LibertyLibrary *
makeTimingModel(const char *lib_name,
const char *cell_name,
const char *filename,
const Corner *corner,
Sta *sta);
} // namespace

View File

@ -0,0 +1,99 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2023, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <map>
#include "LibertyClass.hh"
#include "SdcClass.hh"
#include "SearchClass.hh"
#include "StaState.hh"
#include "RiseFallMinMax.hh"
namespace sta {
class Sta;
class LibertyBuilder;
class OutputDelays
{
public:
OutputDelays();
TimingSense timingSense() const;
RiseFallMinMax delays;
// input edge -> output edge path exists for unateness
bool rf_path_exists[RiseFall::index_count][RiseFall::index_count];
};
typedef std::map<const ClockEdge*, RiseFallMinMax> ClockEdgeDelays;
typedef std::map<const Pin *, OutputDelays> OutputPinDelays;
class MakeTimingModel : public StaState
{
public:
MakeTimingModel(const char *lib_name,
const char *cell_name,
const char *filename,
const Corner *corner,
Sta *sta);
~MakeTimingModel();
LibertyLibrary *makeTimingModel();
private:
void makeLibrary();
void makeCell();
void makePorts();
void checkClock(Clock *clk);
void findTimingFromInputs();
void findTimingFromInput(Port *input_port);
void findClkedOutputPaths();
void findOutputDelays(const RiseFall *input_rf,
OutputPinDelays &output_pin_delays);
void makeSetupHoldTimingArcs(const Pin *input_pin,
const ClockEdgeDelays &clk_margins);
void makeInputOutputTimingArcs(const Pin *input_pin,
OutputPinDelays &output_pin_delays);
TimingModel *makeScalarCheckModel(float value,
ScaleFactorType scale_factor_type,
RiseFall *rf);
TimingModel *makeGateModelScalar(Delay delay,
Slew slew,
RiseFall *rf);
TimingModel *makeGateModelTable(const Pin *output_pin,
Delay delay,
RiseFall *rf);
TableAxisPtr loadCapacitanceAxis(const TableModel *table);
LibertyPort *modelPort(const Pin *pin);
void saveSdc();
void restoreSdc();
const char *lib_name_;
const char *cell_name_;
const char *filename_;
const Corner *corner_;
LibertyLibrary *library_;
LibertyCell *cell_;
MinMax *min_max_;
LibertyBuilder *lib_builder_;
int tbl_template_index_;
Sdc *sdc_backup_;
Sta *sta_;
};
} // namespace

View File

@ -5619,9 +5619,8 @@ Sta::writeTimingModel(const char *lib_name,
const char *filename,
const Corner *corner)
{
MakeTimingModel maker(corner, this);
LibertyLibrary *library = maker.makeTimingModel(lib_name, cell_name,
filename);
LibertyLibrary *library = makeTimingModel(lib_name, cell_name, filename,
corner, this);
writeLiberty(library, filename, this);
}