From 5a8b29d3ee2ab779194535ee975d12ae25678c85 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 25 Jun 2022 11:59:07 -0700 Subject: [PATCH] TimingArcAttrs Signed-off-by: James Cherry --- include/sta/LibertyClass.hh | 4 ++ include/sta/TimingArc.hh | 11 ++-- liberty/LibertyBuilder.cc | 18 +++--- liberty/LibertyBuilder.hh | 18 +++--- liberty/LibertyReader.cc | 109 ++++++++++++++++++------------------ liberty/LibertyReaderPvt.hh | 4 +- liberty/TimingArc.cc | 11 ++-- search/MakeTimingModel.cc | 12 ++-- 8 files changed, 99 insertions(+), 88 deletions(-) diff --git a/include/sta/LibertyClass.hh b/include/sta/LibertyClass.hh index ee508752..6c868592 100644 --- a/include/sta/LibertyClass.hh +++ b/include/sta/LibertyClass.hh @@ -16,6 +16,8 @@ #pragma once +#include + #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 LibertyPortPair; typedef Set LibertyCellSet; typedef Vector FloatSeq; typedef Vector FloatTable; +typedef std::shared_ptr TimingArcAttrsPtr; enum class ScaleFactorType : unsigned { pin_cap, diff --git a/include/sta/TimingArc.hh b/include/sta/TimingArc.hh index f22b32bb..e0a8ed0f 100644 --- a/include/sta/TimingArc.hh +++ b/include/sta/TimingArc.hh @@ -16,6 +16,8 @@ #pragma once +#include + #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_; }; diff --git a/liberty/LibertyBuilder.cc b/liberty/LibertyBuilder.cc index 91ede02e..706f8792 100644 --- a/liberty/LibertyBuilder.cc +++ b/liberty/LibertyBuilder.cc @@ -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); } diff --git a/liberty/LibertyBuilder.hh b/liberty/LibertyBuilder.hh index d068dfc5..b07fe061 100644 --- a/liberty/LibertyBuilder.hh +++ b/liberty/LibertyBuilder.hh @@ -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 diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 7aad95ae..049cb3ef 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -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()), related_output_port_name_(nullptr) { for (auto rf_index : RiseFall::rangeIndex()) { diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index eb1e13f3..bec628f0 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -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]; diff --git a/liberty/TimingArc.cc b/liberty/TimingArc.cc index 43789d9b..81dcdfc3 100644 --- a/liberty/TimingArc.cc +++ b/liberty/TimingArc.cc @@ -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(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); diff --git a/search/MakeTimingModel.cc b/search/MakeTimingModel.cc index d6505a90..fab5e44d 100644 --- a/search/MakeTimingModel.cc +++ b/search/MakeTimingModel.cc @@ -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(); 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(); 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(); attrs->setModel(output_rf, gate_model); } if (attrs) {