From 0d7c89f5440b0a1a790df065a9df3e725f4d899e Mon Sep 17 00:00:00 2001 From: James Cherry Date: Mon, 21 Jul 2025 14:35:53 -0700 Subject: [PATCH] cp liberty bus properties to bit ports resolves #273 Signed-off-by: James Cherry --- include/sta/Liberty.hh | 11 ++++++ liberty/Liberty.cc | 79 +++++++++++++++++++++++++++++++++++++++++- search/Property.cc | 6 ++++ 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index f642f0f3..7fe410bb 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -26,6 +26,7 @@ #include #include +#include #include "MinMax.hh" #include "RiseFallMinMax.hh" @@ -873,6 +874,16 @@ protected: void addScaledPort(OperatingConditions *op_cond, LibertyPort *scaled_port); RiseFallMinMax clkTreeDelays1() const; + void setMemberFlag(bool value, + const std::function &setter); + void setMemberFloat(float value, + const std::function &setter); + void setMemberMinMaxFloat(float value, + const MinMax *min_max, + const std::function &setter); + LibertyCell *liberty_cell_; BusDcl *bus_dcl_; diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index 5a05c424..c87093fb 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -994,6 +994,14 @@ LibertyCell::findLibertyPortsMatching(PatternMatch *pattern) const LibertyPort *port = port_iter.next(); if (pattern->match(port->name())) matches.push_back(port); + if (port->hasMembers()) { + LibertyPortMemberIterator port_iter2(port); + while (port_iter2.hasNext()) { + LibertyPort *port2 = port_iter2.next(); + if (pattern->match(port2->name())) + matches.push_back(port2); + } + } } return matches; } @@ -2347,7 +2355,7 @@ void LibertyPort::setFunction(FuncExpr *func) { function_ = func; - if (is_bus_ || is_bundle_) { + if (hasMembers()) { LibertyPortMemberIterator member_iter(this); int bit_offset = 0; while (member_iter.hasNext()) { @@ -2388,6 +2396,7 @@ LibertyPort::setSlewLimit(float slew, const MinMax *min_max) { slew_limit_.setValue(min_max, slew); + setMemberMinMaxFloat(slew, min_max, &LibertyPort::setSlewLimit); } void @@ -2404,6 +2413,7 @@ LibertyPort::setCapacitanceLimit(float cap, const MinMax *min_max) { cap_limit_.setValue(min_max, cap); + setMemberMinMaxFloat(cap, min_max, &LibertyPort::setCapacitanceLimit); } void @@ -2420,6 +2430,7 @@ LibertyPort::setFanoutLoad(float fanout_load) { fanout_load_ = fanout_load; fanout_load_exists_ = true; + setMemberFloat(fanout_load, &LibertyPort::setFanoutLoad); } void @@ -2470,6 +2481,13 @@ LibertyPort::setMinPeriod(float min_period) { min_period_ = min_period; min_period_exists_ = true; + if (hasMembers()) { + LibertyPortMemberIterator member_iter(this); + while (member_iter.hasNext()) { + LibertyPort *port_bit = member_iter.next(); + port_bit->setMinPeriod(min_period); + } + } } void @@ -2489,6 +2507,13 @@ LibertyPort::setMinPulseWidth(const RiseFall *hi_low, int hi_low_index = hi_low->index(); min_pulse_width_[hi_low_index] = min_width; min_pulse_width_exists_ |= (1 << hi_low_index); + if (hasMembers()) { + LibertyPortMemberIterator member_iter(this); + while (member_iter.hasNext()) { + LibertyPort *port_bit = member_iter.next(); + port_bit->setMinPulseWidth(hi_low, min_width); + } + } } bool @@ -2538,24 +2563,28 @@ void LibertyPort::setIsClock(bool is_clk) { is_clk_ = is_clk; + setMemberFlag(is_clk, &LibertyPort::setIsClock); } void LibertyPort::setIsRegClk(bool is_clk) { is_reg_clk_ = is_clk; + setMemberFlag(is_clk, &LibertyPort::setIsRegClk); } void LibertyPort::setIsRegOutput(bool is_reg_out) { is_reg_output_ = is_reg_out; + setMemberFlag(is_reg_out, &LibertyPort::setIsRegOutput); } void LibertyPort::setIsLatchData(bool is_latch_data) { is_latch_data_ = is_latch_data; + setMemberFlag(is_latch_data, &LibertyPort::setIsLatchData); } void @@ -2592,24 +2621,28 @@ void LibertyPort::setIsolationCellData(bool isolation_cell_data) { isolation_cell_data_ = isolation_cell_data; + setMemberFlag(isolation_cell_data, &LibertyPort::setIsolationCellData); } void LibertyPort::setIsolationCellEnable(bool isolation_cell_enable) { isolation_cell_enable_ = isolation_cell_enable; + setMemberFlag(isolation_cell_enable, &LibertyPort::setIsolationCellEnable); } void LibertyPort::setLevelShifterData(bool level_shifter_data) { level_shifter_data_ = level_shifter_data; + setMemberFlag(level_shifter_data, &LibertyPort::setLevelShifterData); } void LibertyPort::setIsSwitch(bool is_switch) { is_switch_ = is_switch; + setMemberFlag(is_switch, &LibertyPort::setIsSwitch); } void @@ -2821,6 +2854,50 @@ LibertyPort::setClkTreeDelay(const TableModel *model, clk_tree_delay_[from_rf->index()][to_rf->index()][min_max->index()] = model; } +void +LibertyPort::setMemberFlag(bool value, + const std::function &setter) +{ + if (hasMembers()) { + LibertyPortMemberIterator member_iter(this); + while (member_iter.hasNext()) { + LibertyPort *port_bit = member_iter.next(); + setter(port_bit, value); + } + } +} + +void +LibertyPort::setMemberFloat(float value, + const std::function &setter) +{ + if (hasMembers()) { + LibertyPortMemberIterator member_iter(this); + while (member_iter.hasNext()) { + LibertyPort *port_bit = member_iter.next(); + setter(port_bit, value); + } + } +} + +void +LibertyPort::setMemberMinMaxFloat(float value, + const MinMax *min_max, + const std::function &setter) +{ + if (hasMembers()) { + LibertyPortMemberIterator member_iter(this); + while (member_iter.hasNext()) { + LibertyPort *port_bit = member_iter.next(); + setter(port_bit, value, min_max); + } + } +} + //////////////////////////////////////////////////////////////// LibertyPortSeq diff --git a/search/Property.cc b/search/Property.cc index 3e5f740c..67aa3aac 100644 --- a/search/Property.cc +++ b/search/Property.cc @@ -872,6 +872,8 @@ Properties::getProperty(const LibertyPort *port, float cap = port->capacitance(RiseFall::rise(), MinMax::max()); return capacitancePropertyValue(cap); } + else if (property == "is_clock") + return PropertyValue(port->isClock()); else if (property == "is_register_clock") return PropertyValue(port->isRegClk()); @@ -989,6 +991,10 @@ Properties::getProperty(const Pin *pin, return PropertyValue(network->isHierarchical(pin)); else if (property == "is_port") return PropertyValue(network->isTopLevelPort(pin)); + else if (property == "is_clock") { + const LibertyPort *port = network->libertyPort(pin); + return PropertyValue(port->isClock()); + } else if (property == "is_register_clock") { const LibertyPort *port = network->libertyPort(pin); return PropertyValue(port && port->isRegClk());