TimingArcAttrs

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2022-06-25 11:59:07 -07:00
parent 74bc7af476
commit 5a8b29d3ee
8 changed files with 99 additions and 88 deletions

View File

@ -16,6 +16,8 @@
#pragma once
#include <memory>
#include "Vector.hh"
#include "Map.hh"
#include "Set.hh"
@ -45,6 +47,7 @@ class Wireload;
class WireloadSelection;
class TimingArcSet;
class TimingArc;
class TimingArcAttrs;
class InternalPower;
class LeakagePower;
class Sequential;
@ -65,6 +68,7 @@ typedef std::pair<const LibertyPort*,const LibertyPort*> LibertyPortPair;
typedef Set<LibertyCell*> LibertyCellSet;
typedef Vector<float> FloatSeq;
typedef Vector<FloatSeq*> FloatTable;
typedef std::shared_ptr<TimingArcAttrs> TimingArcAttrsPtr;
enum class ScaleFactorType : unsigned {
pin_cap,

View File

@ -16,6 +16,8 @@
#pragma once
#include <memory>
#include "Vector.hh"
#include "Transition.hh"
#include "Delay.hh"
@ -135,7 +137,7 @@ public:
LibertyPort *to,
LibertyPort *related_out,
TimingRole *role,
TimingArcAttrs *attrs);
TimingArcAttrsPtr attrs);
virtual ~TimingArcSet();
LibertyCell *libertyCell() const;
LibertyPort *from() const { return from_; }
@ -195,13 +197,14 @@ public:
protected:
void init(LibertyCell *cell);
TimingArcSet(TimingRole *role,
TimingArcAttrs *attrs);
TimingArcAttrsPtr attrs);
LibertyPort *from_;
LibertyPort *to_;
LibertyPort *related_out_;
TimingRole *role_;
TimingArcAttrs *attrs_;
// TimingArcAttrs are shared by TimingArcSets in a bus with timing groups.
TimingArcAttrsPtr attrs_;
TimingArcSeq arcs_;
bool is_cond_default_;
unsigned index_;
@ -210,7 +213,7 @@ protected:
TimingArc *from_arc2_[RiseFall::index_count];
TimingArc *to_arc_[RiseFall::index_count];
static TimingArcAttrs *wire_timing_arc_attrs_;
static TimingArcAttrsPtr wire_timing_arc_attrs_;
static TimingArcSet *wire_timing_arc_set_;
};

View File

@ -123,7 +123,7 @@ LibertyBuilder::makeTimingArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
TimingArcAttrs *attrs)
TimingArcAttrsPtr attrs)
{
FuncExpr *to_func;
Sequential *seq = nullptr;
@ -254,7 +254,7 @@ LibertyBuilder::makeCombinationalArcs(LibertyCell *cell,
LibertyPort *related_out,
bool to_rise,
bool to_fall,
TimingArcAttrs *attrs)
TimingArcAttrsPtr attrs)
{
FuncExpr *func = to_port->function();
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port, related_out,
@ -334,7 +334,7 @@ LibertyBuilder::makeLatchDtoQArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
TimingArcAttrs *attrs)
TimingArcAttrsPtr attrs)
{
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
related_out,
@ -364,7 +364,7 @@ LibertyBuilder::makeRegLatchArcs(LibertyCell *cell,
LibertyPort *to_port,
LibertyPort *related_out,
RiseFall *from_rf,
TimingArcAttrs *attrs)
TimingArcAttrsPtr attrs)
{
FuncExpr *to_func = to_port->function();
FuncExprPortIterator port_iter(to_func);
@ -402,7 +402,7 @@ LibertyBuilder::makeFromTransitionArcs(LibertyCell *cell,
LibertyPort *related_out,
RiseFall *from_rf,
TimingRole *role,
TimingArcAttrs *attrs)
TimingArcAttrsPtr attrs)
{
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
related_out, role, attrs);
@ -425,7 +425,7 @@ LibertyBuilder::makePresetClrArcs(LibertyCell *cell,
LibertyPort *to_port,
LibertyPort *related_out,
RiseFall *to_rf,
TimingArcAttrs *attrs)
TimingArcAttrsPtr attrs)
{
TimingArcSet *arc_set = nullptr;
TimingModel *model = attrs->model(to_rf);
@ -462,7 +462,7 @@ LibertyBuilder::makeTristateEnableArcs(LibertyCell *cell,
LibertyPort *related_out,
bool to_rise,
bool to_fall,
TimingArcAttrs *attrs)
TimingArcAttrsPtr attrs)
{
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port, related_out,
TimingRole::tristateEnable(), attrs);
@ -533,7 +533,7 @@ LibertyBuilder::makeTristateDisableArcs(LibertyCell *cell,
LibertyPort *related_out,
bool to_rise,
bool to_fall,
TimingArcAttrs *attrs)
TimingArcAttrsPtr attrs)
{
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
related_out,
@ -605,7 +605,7 @@ LibertyBuilder::makeTimingArcSet(LibertyCell *cell,
LibertyPort *to,
LibertyPort *related_out,
TimingRole *role,
TimingArcAttrs *attrs)
TimingArcAttrsPtr attrs)
{
return new TimingArcSet(cell, from, to, related_out, role, attrs);
}

View File

@ -52,7 +52,7 @@ public:
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
TimingArcAttrs *attrs);
TimingArcAttrsPtr attrs);
InternalPower *makeInternalPower(LibertyCell *cell,
LibertyPort *port,
LibertyPort *related_port,
@ -66,14 +66,14 @@ public:
LibertyPort *related_out,
RiseFall *from_rf,
TimingRole *role,
TimingArcAttrs *attrs);
TimingArcAttrsPtr attrs);
TimingArcSet *makeCombinationalArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
bool to_rise,
bool to_fall,
TimingArcAttrs *attrs);
TimingArcAttrsPtr attrs);
protected:
ConcretePort *makeBusPort(const char *name,
@ -100,7 +100,7 @@ protected:
LibertyPort *to,
LibertyPort *related_out,
TimingRole *role,
TimingArcAttrs *attrs);
TimingArcAttrsPtr attrs);
virtual TimingArc *makeTimingArc(TimingArcSet *set,
Transition *from_rf,
Transition *to_rf,
@ -113,33 +113,33 @@ protected:
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
TimingArcAttrs *attrs);
TimingArcAttrsPtr attrs);
TimingArcSet *makeRegLatchArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
RiseFall *from_rf,
TimingArcAttrs *attrs);
TimingArcAttrsPtr attrs);
TimingArcSet *makePresetClrArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
RiseFall *to_rf,
TimingArcAttrs *attrs);
TimingArcAttrsPtr attrs);
TimingArcSet *makeTristateEnableArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
bool to_rise,
bool to_fall,
TimingArcAttrs *attrs);
TimingArcAttrsPtr attrs);
TimingArcSet *makeTristateDisableArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
bool to_rise,
bool to_fall,
TimingArcAttrs *attrs);
TimingArcAttrsPtr attrs);
};
} // namespace

View File

@ -2154,8 +2154,8 @@ LibertyReader::makeTimingArcs(LibertyPort *to_port,
related_out_port = findPort(related_out_port_name);
int line = timing->line();
PortDirection *to_port_dir = to_port->direction();
// Should be more comprehensive (timing checks on inputs, etc).
TimingType type = timing->timingType();
// Checks should be more comprehensive (timing checks on inputs, etc).
TimingType type = timing->attrs()->timingType();
if (type == TimingType::combinational &&
to_port_dir->isInput())
libWarn(94, line, "combinational timing to an input port.");
@ -2194,65 +2194,66 @@ TimingGroup::makeTimingModels(LibertyLibrary *library,
void
TimingGroup::makeLinearModels(LibertyLibrary *library)
{
for (auto tr : RiseFall::range()) {
int tr_index = tr->index();
float intr = intrinsic_[tr_index];
bool intr_exists = intrinsic_exists_[tr_index];
for (auto rf : RiseFall::range()) {
int rf_index = rf->index();
float intr = intrinsic_[rf_index];
bool intr_exists = intrinsic_exists_[rf_index];
if (!intr_exists)
library->defaultIntrinsic(tr, intr, intr_exists);
library->defaultIntrinsic(rf, intr, intr_exists);
TimingModel *model = nullptr;
if (timingTypeIsCheck(timing_type_)) {
if (timingTypeIsCheck(attrs_->timingType())) {
if (intr_exists)
model = new CheckLinearModel(intr);
}
else {
float res = resistance_[tr_index];
bool res_exists = resistance_exists_[tr_index];
float res = resistance_[rf_index];
bool res_exists = resistance_exists_[rf_index];
if (!res_exists)
library->defaultPinResistance(tr, PortDirection::output(),
library->defaultPinResistance(rf, PortDirection::output(),
res, res_exists);
if (!res_exists)
res = 0.0F;
if (intr_exists)
model = new GateLinearModel(intr, res);
}
models_[tr_index] = model;
attrs_->setModel(rf, model);
}
}
void
TimingGroup::makeTableModels(LibertyReader *visitor)
{
for (auto tr : RiseFall::range()) {
int tr_index = tr->index();
TableModel *cell = cell_[tr_index];
TableModel *constraint = constraint_[tr_index];
TableModel *transition = transition_[tr_index];
for (auto rf : RiseFall::range()) {
int rf_index = rf->index();
TableModel *cell = cell_[rf_index];
TableModel *constraint = constraint_[rf_index];
TableModel *transition = transition_[rf_index];
if (cell || transition) {
models_[tr_index] = new GateTableModel(cell, delay_sigma_[tr_index],
transition, slew_sigma_[tr_index]);
if (timing_type_ == TimingType::clear
|| timing_type_ == TimingType::combinational
|| timing_type_ == TimingType::combinational_fall
|| timing_type_ == TimingType::combinational_rise
|| timing_type_ == TimingType::falling_edge
|| timing_type_ == TimingType::preset
|| timing_type_ == TimingType::rising_edge
|| timing_type_ == TimingType::three_state_disable
|| timing_type_ == TimingType::three_state_disable_rise
|| timing_type_ == TimingType::three_state_disable_fall
|| timing_type_ == TimingType::three_state_enable
|| timing_type_ == TimingType::three_state_enable_fall
|| timing_type_ == TimingType::three_state_enable_rise) {
attrs_->setModel(rf, new GateTableModel(cell, delay_sigma_[rf_index],
transition, slew_sigma_[rf_index]));
TimingType timing_type = attrs_->timingType();
if (timing_type == TimingType::clear
|| timing_type == TimingType::combinational
|| timing_type == TimingType::combinational_fall
|| timing_type == TimingType::combinational_rise
|| timing_type == TimingType::falling_edge
|| timing_type == TimingType::preset
|| timing_type == TimingType::rising_edge
|| timing_type == TimingType::three_state_disable
|| timing_type == TimingType::three_state_disable_rise
|| timing_type == TimingType::three_state_disable_fall
|| timing_type == TimingType::three_state_enable
|| timing_type == TimingType::three_state_enable_fall
|| timing_type == TimingType::three_state_enable_rise) {
if (transition == nullptr)
visitor->libWarn(95, line_, "missing %s_transition.", tr->name());
visitor->libWarn(95, line_, "missing %s_transition.", rf->name());
if (cell == nullptr)
visitor->libWarn(96, line_, "missing cell_%s.", tr->name());
visitor->libWarn(96, line_, "missing cell_%s.", rf->name());
}
}
if (constraint)
models_[tr_index] = new CheckTableModel(constraint,
constraint_sigma_[tr_index]);
attrs_->setModel(rf, new CheckTableModel(constraint,
constraint_sigma_[rf_index]));
}
}
@ -2268,7 +2269,7 @@ LibertyReader::makeTimingArcs(const char *from_port_name,
if (from_port_iter.hasNext()) {
LibertyPort *from_port = from_port_iter.next();
builder_->makeTimingArcs(cell_, from_port, to_port,
related_out_port, timing);
related_out_port, timing->attrs());
}
}
else if (from_port_iter.size() > 1 && !to_port->hasMembers()) {
@ -2276,7 +2277,7 @@ LibertyReader::makeTimingArcs(const char *from_port_name,
while (from_port_iter.hasNext()) {
LibertyPort *from_port = from_port_iter.next();
builder_->makeTimingArcs(cell_, from_port, to_port,
related_out_port, timing);
related_out_port, timing->attrs());
}
}
else if (from_port_iter.size() == 1 && to_port->hasMembers()) {
@ -2287,7 +2288,7 @@ LibertyReader::makeTimingArcs(const char *from_port_name,
while (bit_iter.hasNext()) {
LibertyPort *to_port_bit = bit_iter.next();
builder_->makeTimingArcs(cell_, from_port, to_port_bit,
related_out_port, timing);
related_out_port, timing->attrs());
}
}
}
@ -2300,7 +2301,7 @@ LibertyReader::makeTimingArcs(const char *from_port_name,
LibertyPort *from_port_bit = from_port_iter.next();
LibertyPort *to_port_bit = to_iter.next();
builder_->makeTimingArcs(cell_, from_port_bit, to_port_bit,
related_out_port, timing);
related_out_port, timing->attrs());
}
}
else
@ -2316,7 +2317,7 @@ LibertyReader::makeTimingArcs(const char *from_port_name,
while (to_iter.hasNext()) {
LibertyPort *to_port_bit = to_iter.next();
builder_->makeTimingArcs(cell_, from_port_bit, to_port_bit,
related_out_port, timing);
related_out_port, timing->attrs());
}
}
}
@ -3493,7 +3494,7 @@ LibertyReader::endTiming(LibertyGroup *)
for (auto tr : RiseFall::range()) {
TableModel *model = timing_->constraint(tr);
if (model) {
ScaleFactorType type=timingTypeScaleFactorType(timing_->timingType());
ScaleFactorType type=timingTypeScaleFactorType(timing_->attrs()->timingType());
model->setScaleFactorType(type);
}
}
@ -3578,7 +3579,7 @@ LibertyReader::visitTimingType(LibertyAttr *attr)
if (type == TimingType::unknown)
libWarn(111, attr, "unknown timing_type %s.", type_name);
else
timing_->setTimingType(type);
timing_->attrs()->setTimingType(type);
}
}
}
@ -3590,11 +3591,11 @@ LibertyReader::visitTimingSense(LibertyAttr *attr)
const char *sense_name = getAttrString(attr);
if (sense_name) {
if (stringEq(sense_name, "non_unate"))
timing_->setTimingSense(TimingSense::non_unate);
timing_->attrs()->setTimingSense(TimingSense::non_unate);
else if (stringEq(sense_name, "positive_unate"))
timing_->setTimingSense(TimingSense::positive_unate);
timing_->attrs()->setTimingSense(TimingSense::positive_unate);
else if (stringEq(sense_name, "negative_unate"))
timing_->setTimingSense(TimingSense::negative_unate);
timing_->attrs()->setTimingSense(TimingSense::negative_unate);
else
libWarn(112, attr, "unknown timing_sense %s.", sense_name);
}
@ -3607,7 +3608,7 @@ LibertyReader::visitSdfCondStart(LibertyAttr *attr)
if (timing_) {
const char *cond = getAttrString(attr);
if (cond)
timing_->setSdfCondStart(cond);
timing_->attrs()->setSdfCondStart(cond);
}
}
@ -3617,7 +3618,7 @@ LibertyReader::visitSdfCondEnd(LibertyAttr *attr)
if (timing_) {
const char *cond = getAttrString(attr);
if (cond)
timing_->setSdfCondEnd(cond);
timing_->attrs()->setSdfCondEnd(cond);
}
}
@ -3630,11 +3631,11 @@ LibertyReader::visitMode(LibertyAttr *attr)
if (value_iter.hasNext()) {
LibertyAttrValue *value = value_iter.next();
if (value->isString()) {
timing_->setModeName(value->stringValue());
timing_->attrs()->setModeName(value->stringValue());
if (value_iter.hasNext()) {
value = value_iter.next();
if (value->isString())
timing_->setModeValue(value->stringValue());
timing_->attrs()->setModeValue(value->stringValue());
else
libWarn(113, attr, "mode value is not a string.");
}
@ -4123,7 +4124,7 @@ LibertyReader::visitWhen(LibertyAttr *attr)
if (timing_) {
const char *func = getAttrString(attr);
if (func)
makeLibertyFunc(func, timing_->condRef(), false, "when", attr);
makeLibertyFunc(func, timing_->attrs()->condRef(), false, "when", attr);
}
if (internal_power_) {
const char *func = getAttrString(attr);
@ -4148,7 +4149,7 @@ LibertyReader::visitSdfCond(LibertyAttr *attr)
else if (timing_) {
const char *cond = getAttrString(attr);
if (cond)
timing_->setSdfCond(cond);
timing_->attrs()->setSdfCond(cond);
}
// sdf_cond can also appear inside minimum_period groups.
}
@ -4606,7 +4607,7 @@ LibertyReader::visitOcvArcDepth(LibertyAttr *attr)
getAttrFloat(attr, value, exists);
if (exists) {
if (timing_)
timing_->setOcvArcDepth(value);
timing_->attrs()->setOcvArcDepth(value);
else if (cell_)
cell_->setOcvArcDepth(value);
else
@ -5049,8 +5050,8 @@ RelatedPortGroup::setIsOneToOne(bool one)
////////////////////////////////////////////////////////////////
TimingGroup::TimingGroup(int line) :
TimingArcAttrs(),
RelatedPortGroup(line),
attrs_(std::make_shared<TimingArcAttrs>()),
related_output_port_name_(nullptr)
{
for (auto rf_index : RiseFall::rangeIndex()) {

View File

@ -698,11 +698,12 @@ protected:
int line_;
};
class TimingGroup : public TimingArcAttrs, public RelatedPortGroup
class TimingGroup : public RelatedPortGroup
{
public:
explicit TimingGroup(int line);
virtual ~TimingGroup();
TimingArcAttrsPtr attrs() { return attrs_; }
const char *relatedOutputPortName()const {return related_output_port_name_;}
void setRelatedOutputPortName(const char *name);
void intrinsic(RiseFall *rf,
@ -742,6 +743,7 @@ protected:
void makeLinearModels(LibertyLibrary *library);
void makeTableModels(LibertyReader *visitor);
TimingArcAttrsPtr attrs_;
const char *related_output_port_name_;
float intrinsic_[RiseFall::index_count];
bool intrinsic_exists_[RiseFall::index_count];

View File

@ -24,6 +24,8 @@
namespace sta {
using std::make_shared;
static bool
timingArcsEquiv(const TimingArcSet *set1,
const TimingArcSet *set2);
@ -171,7 +173,7 @@ TimingArc::intrinsicDelay() const
////////////////////////////////////////////////////////////////
TimingArcAttrs *TimingArcSet::wire_timing_arc_attrs_ = nullptr;
TimingArcAttrsPtr TimingArcSet::wire_timing_arc_attrs_ = nullptr;
TimingArcSet *TimingArcSet::wire_timing_arc_set_ = nullptr;
TimingArcSet::TimingArcSet(LibertyCell *cell,
@ -179,7 +181,7 @@ TimingArcSet::TimingArcSet(LibertyCell *cell,
LibertyPort *to,
LibertyPort *related_out,
TimingRole *role,
TimingArcAttrs *attrs) :
TimingArcAttrsPtr attrs) :
from_(from),
to_(to),
related_out_(related_out),
@ -193,7 +195,7 @@ TimingArcSet::TimingArcSet(LibertyCell *cell,
}
TimingArcSet::TimingArcSet(TimingRole *role,
TimingArcAttrs *attrs) :
TimingArcAttrsPtr attrs) :
from_(nullptr),
to_(nullptr),
related_out_(nullptr),
@ -222,7 +224,6 @@ TimingArcSet::init(LibertyCell *cell)
TimingArcSet::~TimingArcSet()
{
arcs_.deleteContents();
delete attrs_;
}
bool
@ -514,7 +515,7 @@ TimingArcSet::wireArcIndex(const RiseFall *rf)
void
TimingArcSet::init()
{
wire_timing_arc_attrs_ = new TimingArcAttrs(TimingSense::positive_unate);
wire_timing_arc_attrs_ = make_shared<TimingArcAttrs>(TimingSense::positive_unate);
wire_timing_arc_set_ = new TimingArcSet(TimingRole::wire(), wire_timing_arc_attrs_);
new TimingArc(wire_timing_arc_set_, Transition::rise(),
Transition::rise(), nullptr);

View File

@ -316,7 +316,7 @@ MakeTimingModel::makeSetupHoldTimingArcs(const Pin *input_pin,
RiseFallMinMax &margins = clk_edge_margins.second;
for (MinMax *min_max : MinMax::range()) {
bool setup = (min_max == MinMax::max());
TimingArcAttrs *attrs = nullptr;
TimingArcAttrsPtr attrs = nullptr;
for (RiseFall *input_rf : RiseFall::range()) {
float margin;
bool exists;
@ -333,7 +333,7 @@ MakeTimingModel::makeSetupHoldTimingArcs(const Pin *input_pin,
: ScaleFactorType::hold;
TimingModel *check_model = makeScalarCheckModel(margin, scale_type, input_rf);
if (attrs == nullptr)
attrs = new TimingArcAttrs();
attrs = std::make_shared<TimingArcAttrs>();
attrs->setModel(input_rf, check_model);
}
}
@ -359,7 +359,7 @@ MakeTimingModel::makeInputOutputTimingArcs(const Pin *input_pin,
for (auto out_pin_delay : output_pin_delays) {
const Pin *output_pin = out_pin_delay.first;
OutputDelays &output_delays = out_pin_delay.second;
TimingArcAttrs *attrs = nullptr;
TimingArcAttrsPtr attrs = nullptr;
for (RiseFall *output_rf : RiseFall::range()) {
MinMax *min_max = MinMax::max();
float delay;
@ -373,7 +373,7 @@ MakeTimingModel::makeInputOutputTimingArcs(const Pin *input_pin,
delayAsString(delay, sta_));
TimingModel *gate_model = makeGateModelTable(output_pin, delay, output_rf);
if (attrs == nullptr)
attrs = new TimingArcAttrs();
attrs = std::make_shared<TimingArcAttrs>();
attrs->setModel(output_rf, gate_model);
}
}
@ -420,12 +420,12 @@ MakeTimingModel::findClkedOutputPaths()
for (const Pin *clk_pin : clk_edge->clock()->pins()) {
LibertyPort *clk_port = modelPort(clk_pin);
RiseFall *clk_rf = clk_edge->transition();
TimingArcAttrs *attrs = nullptr;
TimingArcAttrsPtr attrs = nullptr;
for (RiseFall *output_rf : RiseFall::range()) {
float delay = delays.value(output_rf, min_max_) - clk_edge->time();
TimingModel *gate_model = makeGateModelTable(output_pin, delay, output_rf);
if (attrs == nullptr)
attrs = new TimingArcAttrs();
attrs = std::make_shared<TimingArcAttrs>();
attrs->setModel(output_rf, gate_model);
}
if (attrs) {