diff --git a/include/sta/ConcreteLibrary.hh b/include/sta/ConcreteLibrary.hh index 5b5ed813..d4eb6ff8 100644 --- a/include/sta/ConcreteLibrary.hh +++ b/include/sta/ConcreteLibrary.hh @@ -196,6 +196,9 @@ public: // Bundles are groups of related ports that do not use // bus notation. bool isBundle() const { return is_bundle_; } + ConcretePort *bundlePort() const { return bundle_port_; } + bool isBundleMember() const { return bundle_port_ != nullptr; } + void setBundlePort(ConcretePort *port); bool isBus() const { return is_bus_; } // Index of cell bit ports. // Bus/bundle ports do not have an pin index. @@ -251,6 +254,7 @@ protected: // Expanded bus bit ports (ordered by from_index_ to to_index_) // or bundle member ports. ConcretePortSeq *member_ports_; + ConcretePort *bundle_port_; private: friend class ConcreteCell; diff --git a/include/sta/InternalPower.hh b/include/sta/InternalPower.hh index 1ca4bf2e..0c30a38d 100644 --- a/include/sta/InternalPower.hh +++ b/include/sta/InternalPower.hh @@ -39,7 +39,7 @@ public: virtual ~InternalPowerAttrs(); void deleteContents(); FuncExpr *when() const { return when_; } - FuncExpr *&whenRef() { return when_; } + void setWhen(FuncExpr *when); void setModel(const RiseFall *rf, InternalPowerModel *model); InternalPowerModel *model(const RiseFall *rf) const; diff --git a/include/sta/LeakagePower.hh b/include/sta/LeakagePower.hh index 6670a356..a0dbd86d 100644 --- a/include/sta/LeakagePower.hh +++ b/include/sta/LeakagePower.hh @@ -35,7 +35,7 @@ class LeakagePowerAttrs public: LeakagePowerAttrs(); FuncExpr *when() const { return when_; } - FuncExpr *&whenRef() { return when_; } + void setWhen(FuncExpr *when); float power() { return power_; } void setPower(float power); diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index fec901fa..4794c30e 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -701,6 +701,7 @@ public: LibertyLibrary *libertyLibrary() const { return liberty_cell_->libertyLibrary(); } LibertyPort *findLibertyMember(int index) const; LibertyPort *findLibertyBusBit(int index) const; + LibertyPort *bundlePort() const; BusDcl *busDcl() const { return bus_dcl_; } void setDirection(PortDirection *dir); ScanSignalType scanSignalType() const { return scan_signal_type_; } @@ -740,11 +741,9 @@ public: const StaState *sta) const; FuncExpr *function() const { return function_; } void setFunction(FuncExpr *func); - FuncExpr *&functionRef() { return function_; } // Tristate enable function. FuncExpr *tristateEnable() const { return tristate_enable_; } void setTristateEnable(FuncExpr *enable); - FuncExpr *&tristateEnableRef() { return tristate_enable_; } void slewLimit(const MinMax *min_max, // Return values. float &limit, @@ -1046,7 +1045,7 @@ public: ~ModeValueDef(); const char *value() const { return value_.c_str(); } FuncExpr *cond() const { return cond_; } - FuncExpr *&condRef() { return cond_; } + void setCond(FuncExpr *cond); const char *sdfCond() const { return sdf_cond_.c_str(); } void setSdfCond(const char *sdf_cond); diff --git a/include/sta/TimingArc.hh b/include/sta/TimingArc.hh index 21e56c95..3884cbd3 100644 --- a/include/sta/TimingArc.hh +++ b/include/sta/TimingArc.hh @@ -104,7 +104,7 @@ public: TimingSense timingSense() const { return timing_sense_; } void setTimingSense(TimingSense sense); FuncExpr *cond() const { return cond_; } - FuncExpr *&condRef() { return cond_; } + void setCond(FuncExpr *cond); const char *sdfCond() const { return sdf_cond_; } void setSdfCond(const char *cond); const char *sdfCondStart() const { return sdf_cond_start_; } diff --git a/liberty/InternalPower.cc b/liberty/InternalPower.cc index a4a90740..a68dd196 100644 --- a/liberty/InternalPower.cc +++ b/liberty/InternalPower.cc @@ -63,6 +63,12 @@ InternalPowerAttrs::model(const RiseFall *rf) const return models_[rf->index()]; } +void +InternalPowerAttrs::setWhen(FuncExpr *when) +{ + when_ = when; +} + void InternalPowerAttrs::setModel(const RiseFall *rf, InternalPowerModel *model) diff --git a/liberty/LeakagePower.cc b/liberty/LeakagePower.cc index 5b53604b..73e4a618 100644 --- a/liberty/LeakagePower.cc +++ b/liberty/LeakagePower.cc @@ -36,6 +36,12 @@ LeakagePowerAttrs::LeakagePowerAttrs() : { } +void +LeakagePowerAttrs::setWhen(FuncExpr *when) +{ + when_ = when; +} + void LeakagePowerAttrs::setPower(float power) { diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index f8cab012..ba38c6ce 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -2179,6 +2179,12 @@ LibertyPort::findLibertyBusBit(int index) const return static_cast(findBusBit(index)); } +LibertyPort * +LibertyPort::bundlePort() const +{ + return static_cast(bundle_port_); +} + void LibertyPort::setCapacitance(float cap) { @@ -2923,6 +2929,12 @@ ModeValueDef::~ModeValueDef() cond_->deleteSubexprs(); } +void +ModeValueDef::setCond(FuncExpr *cond) +{ + cond_ = cond; +} + void ModeValueDef::setSdfCond(const char *sdf_cond) { diff --git a/liberty/Liberty.i b/liberty/Liberty.i index afa00e87..4dd5d7a8 100644 --- a/liberty/Liberty.i +++ b/liberty/Liberty.i @@ -310,8 +310,13 @@ LibertyCell *test_cell() { return self->testCell(); } const char *bus_name() { return self->busName(); } Cell *cell() { return self->cell(); } bool is_bus() { return self->isBus(); } +bool is_bus_bit() { return self->isBusBit(); } +bool is_bundle() { return self->isBundle(); } +bool is_bundle_member() { return self->isBundleMember(); } +bool has_members() { return self->hasMembers(); } LibertyPortMemberIterator * member_iterator() { return new LibertyPortMemberIterator(self); } +LibertyPort *bundle_port() { return self->bundlePort(); } string function() diff --git a/liberty/Liberty.tcl b/liberty/Liberty.tcl index 4297683b..0103d3f5 100644 --- a/liberty/Liberty.tcl +++ b/liberty/Liberty.tcl @@ -50,5 +50,68 @@ proc write_liberty { args } { write_liberty_cmd $library $filename } +################################################################ + +define_cmd_args "report_lib_cell" {cell_name [> filename] [>> filename]} + +proc_redirect report_lib_cell { + check_argc_eq1 "report_lib_cell" $args + set arg [lindex $args 0] + set cell [get_lib_cell_warn "lib_cell" $arg] + set corner [cmd_corner] + if { $cell != "NULL" } { + report_lib_cell_ $cell $corner + } +} + +proc report_lib_cell_ { cell corner } { + set lib [$cell liberty_library] + report_line "Cell [get_name $cell]" + report_line "Library [get_name $lib]" + set filename [liberty_cell_property $cell "filename"] + if { $filename != "" } { + report_line "File $filename" + } + set iter [$cell liberty_port_iterator] + while {[$iter has_next]} { + set port [$iter next] + if { [$port is_bus] || [$port is_bundle] } { + report_lib_port $port $corner + set member_iter [$port member_iterator] + while { [$member_iter has_next] } { + set port [$member_iter next] + report_lib_port $port $corner + } + $member_iter finish + } elseif { ![$port is_bundle_member] && ![$port is_bus_bit] } { + report_lib_port $port $corner + } + } + $iter finish +} + +proc report_lib_port { port corner } { + global sta_report_default_digits + + if { [$port is_bus] } { + set port_name [$port bus_name] + } else { + set port_name [get_name $port] + } + set indent "" + if { [$port is_bundle_member] || [$port is_bus_bit] } { + set indent " " + } + set enable [$port tristate_enable] + if { $enable != "" } { + set enable " enable=$enable" + } + set func [$port function] + if { $func != "" } { + set func " function=$func" + } + report_line " ${indent}$port_name [liberty_port_direction $port]$enable$func[port_capacitance_str $port $corner $sta_report_default_digits]" +} + # sta namespace end } diff --git a/liberty/LibertyBuilder.cc b/liberty/LibertyBuilder.cc index 2d4b4a70..e5184345 100644 --- a/liberty/LibertyBuilder.cc +++ b/liberty/LibertyBuilder.cc @@ -135,6 +135,8 @@ LibertyBuilder::makeBundlePort(LibertyCell *cell, { LibertyPort *port = new LibertyPort(cell, name, false, nullptr, -1, -1, true, members); cell->addPort(port); + for (ConcretePort *member : *members) + member->setBundlePort(port); return port; } diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 5e86b347..672fb1c9 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -2224,13 +2224,13 @@ LibertyReader::makeLeakagePowers() // the cell definition when all of the ports are defined. void LibertyReader::makeLibertyFunc(const char *expr, - FuncExpr *&func_ref, + LibertySetFunc set_func, bool invert, const char *attr_name, LibertyStmt *stmt) { - LibertyFunc *func = new LibertyFunc(expr, func_ref, invert, attr_name, - stmt->line()); + LibertyFunc *func = new LibertyFunc(expr, set_func, + invert, attr_name, stmt->line()); cell_funcs_.push_back(func); } @@ -2248,12 +2248,8 @@ LibertyReader::parseCellFuncs() else expr = FuncExpr::makeNot(expr); } - if (expr) { - FuncExpr *prev_func = func->funcRef(); - if (prev_func) - prev_func->deleteSubexprs(); - func->funcRef() = expr; - } + if (expr) + func->setFunc()(expr); delete func; } cell_funcs_.clear(); @@ -3457,7 +3453,9 @@ LibertyReader::visitFunction(LibertyAttr *attr) const char *func = getAttrString(attr); if (func) { for (LibertyPort *port : *ports_) - makeLibertyFunc(func, port->functionRef(), false, "function", attr); + makeLibertyFunc(func, + [port] (FuncExpr *expr) { port->setFunction(expr); }, + false, "function", attr); } } } @@ -3469,8 +3467,9 @@ LibertyReader::visitThreeState(LibertyAttr *attr) const char *three_state = getAttrString(attr); if (three_state) { for (LibertyPort *port : *ports_) - makeLibertyFunc(three_state, port->tristateEnableRef(), true, - "three_state", attr); + makeLibertyFunc(three_state, + [port] (FuncExpr *expr) { port->setTristateEnable(expr); }, + true, "three_state", attr); } } } @@ -4914,23 +4913,39 @@ LibertyReader::visitWhen(LibertyAttr *attr) libWarn(1265, attr, "when attribute inside table model."); if (mode_value_) { const char *func = getAttrString(attr); - if (func) - makeLibertyFunc(func, mode_value_->condRef(), false, "when", attr); + if (func) { + ModeValueDef *mode_value = mode_value_; + makeLibertyFunc(func, + [mode_value] (FuncExpr *expr) {mode_value->setCond(expr);}, + false, "when", attr); + } } if (timing_) { const char *func = getAttrString(attr); - if (func) - makeLibertyFunc(func, timing_->attrs()->condRef(), false, "when", attr); + if (func) { + TimingArcAttrs *attrs = timing_->attrs().get(); + makeLibertyFunc(func, + [attrs] (FuncExpr *expr) { attrs->setCond(expr);}, + false, "when", attr); + } } if (internal_power_) { const char *func = getAttrString(attr); - if (func) - makeLibertyFunc(func, internal_power_->whenRef(), false, "when", attr); + if (func) { + InternalPowerGroup *internal_pwr = internal_power_; + makeLibertyFunc(func, + [internal_pwr] (FuncExpr *expr) { internal_pwr->setWhen(expr);}, + false, "when", attr); + } } if (leakage_power_) { const char *func = getAttrString(attr); - if (func) - makeLibertyFunc(func, leakage_power_->whenRef(), false, "when", attr); + if (func) { + LeakagePowerGroup *leakage_pwr = leakage_power_; + makeLibertyFunc(func, + [leakage_pwr] (FuncExpr *expr) { leakage_pwr->setWhen(expr);}, + false, "when", attr); + } } } @@ -5719,12 +5734,12 @@ LibertyReader::endEcsmWaveform(LibertyGroup *) //////////////////////////////////////////////////////////////// LibertyFunc::LibertyFunc(const char *expr, - FuncExpr *&func_ref, + LibertySetFunc set_func, bool invert, const char *attr_name, int line) : expr_(stringCopy(expr)), - func_ref_(func_ref), + set_func_(set_func), invert_(invert), attr_name_(stringCopy(attr_name)), line_(line) diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index 56109653..8a4e34f7 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -73,6 +73,7 @@ typedef Vector LeakagePowerGroupSeq; typedef void (LibertyPort::*LibertyPortBoolSetter)(bool value); typedef Vector OutputWaveformSeq; typedef std::vector StdStringSeq; +typedef std::function LibertySetFunc; class LibertyReader : public LibertyGroupVisitor { @@ -187,7 +188,7 @@ public: virtual void makeLeakagePowers(); virtual void parseCellFuncs(); virtual void makeLibertyFunc(const char *expr, - FuncExpr *&func_ref, + LibertySetFunc set_func, bool invert, const char *attr_name, LibertyStmt *stmt); @@ -697,20 +698,20 @@ class LibertyFunc { public: LibertyFunc(const char *expr, - FuncExpr *&func_ref, + LibertySetFunc set_func, bool invert, const char *attr_name, int line); ~LibertyFunc(); const char *expr() const { return expr_; } - FuncExpr *&funcRef() const { return func_ref_; } + LibertySetFunc setFunc() const { return set_func_; } bool invert() const { return invert_; } const char *attrName() const { return attr_name_; } int line() const { return line_; } protected: const char *expr_; - FuncExpr *&func_ref_; + LibertySetFunc set_func_; bool invert_; const char *attr_name_; int line_; diff --git a/liberty/TimingArc.cc b/liberty/TimingArc.cc index 537f0085..b03b5cc6 100644 --- a/liberty/TimingArc.cc +++ b/liberty/TimingArc.cc @@ -101,6 +101,12 @@ TimingArcAttrs::setTimingSense(TimingSense sense) timing_sense_ = sense; } +void +TimingArcAttrs::setCond(FuncExpr *cond) +{ + cond_ = cond; +} + void TimingArcAttrs::setSdfCond(const char *cond) { diff --git a/network/ConcreteLibrary.cc b/network/ConcreteLibrary.cc index ec897b1e..2dedc9f4 100644 --- a/network/ConcreteLibrary.cc +++ b/network/ConcreteLibrary.cc @@ -179,6 +179,8 @@ ConcreteCell::makeBundlePort(const char *name, { ConcretePort *port = new ConcretePort(name, false, -1, -1, true, members, this); addPort(port); + for (ConcretePort *member : *members) + member->setBundlePort(port); return port; } @@ -427,7 +429,8 @@ ConcretePort::ConcretePort(const char *name, is_bus_(is_bus), from_index_(from_index), to_index_(to_index), - member_ports_(member_ports) + member_ports_(member_ports), + bundle_port_(nullptr) { } @@ -452,6 +455,12 @@ ConcretePort::setLibertyPort(LibertyPort *port) liberty_port_ = port; } +void +ConcretePort::setBundlePort(ConcretePort *port) +{ + bundle_port_ = port; +} + void ConcretePort::setExtPort(void *port) { diff --git a/network/Network.tcl b/network/Network.tcl index 7a05760e..b9d958a6 100644 --- a/network/Network.tcl +++ b/network/Network.tcl @@ -140,51 +140,6 @@ proc instance_sorted_children { instance } { ################################################################ -define_cmd_args "report_lib_cell" {cell_name [> filename] [>> filename]} - -proc_redirect report_lib_cell { - check_argc_eq1 "report_lib_cell" $args - set arg [lindex $args 0] - set cell [get_lib_cell_warn "lib_cell" $arg] - set corner [cmd_corner] - if { $cell != "NULL" } { - report_lib_cell_ $cell $corner - } -} - -proc report_lib_cell_ { cell corner } { - global sta_report_default_digits - - set lib [$cell liberty_library] - report_line "Cell [get_name $cell]" - report_line "Library [get_name $lib]" - set filename [liberty_cell_property $cell "filename"] - if { $filename != "" } { - report_line "File $filename" - } - set iter [$cell liberty_port_iterator] - while {[$iter has_next]} { - set port [$iter next] - if { [$port is_bus] } { - set port_name [$port bus_name] - } else { - set port_name [get_name $port] - } - set enable [$port tristate_enable] - if { $enable != "" } { - set enable " enable=$enable" - } - set func [$port function] - if { $func != "" } { - set func " function=$func" - } - report_line " $port_name [liberty_port_direction $port]$enable$func[port_capacitance_str $port $corner $sta_report_default_digits]" - } - $iter finish -} - -################################################################ - define_cmd_args "report_net" {[-corner corner] [-digits digits]\ net_path [> filename] [>> filename]}