make timing model header
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
d17a232575
commit
eb4839e145
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue