liberty bundle ports apply func's to members resolves #256

commit d7629119c261bbc1551f7a6b008475b194a9ff91
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Jun 10 13:59:36 2025 +0200

    issue256

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2025-06-16 16:45:21 +02:00
parent 343b93b633
commit c2a0c4db30
16 changed files with 161 additions and 78 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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_; }

View File

@ -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)

View File

@ -36,6 +36,12 @@ LeakagePowerAttrs::LeakagePowerAttrs() :
{
}
void
LeakagePowerAttrs::setWhen(FuncExpr *when)
{
when_ = when;
}
void
LeakagePowerAttrs::setPower(float power)
{

View File

@ -2179,6 +2179,12 @@ LibertyPort::findLibertyBusBit(int index) const
return static_cast<LibertyPort*>(findBusBit(index));
}
LibertyPort *
LibertyPort::bundlePort() const
{
return static_cast<LibertyPort*>(bundle_port_);
}
void
LibertyPort::setCapacitance(float cap)
{
@ -2916,6 +2922,12 @@ ModeValueDef::~ModeValueDef()
cond_->deleteSubexprs();
}
void
ModeValueDef::setCond(FuncExpr *cond)
{
cond_ = cond;
}
void
ModeValueDef::setSdfCond(const char *sdf_cond)
{

View File

@ -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()

View File

@ -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
}

View File

@ -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;
}

View File

@ -2222,13 +2222,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);
}
@ -2246,12 +2246,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();
@ -3446,7 +3442,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);
}
}
}
@ -3458,8 +3456,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);
}
}
}
@ -4898,23 +4897,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);
}
}
}
@ -5703,12 +5718,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)

View File

@ -73,6 +73,7 @@ typedef Vector<LeakagePowerGroup*> LeakagePowerGroupSeq;
typedef void (LibertyPort::*LibertyPortBoolSetter)(bool value);
typedef Vector<OutputWaveform*> OutputWaveformSeq;
typedef std::vector<std::string> StdStringSeq;
typedef std::function<void (FuncExpr *expr)> 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);
@ -695,20 +696,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_;

View File

@ -101,6 +101,12 @@ TimingArcAttrs::setTimingSense(TimingSense sense)
timing_sense_ = sense;
}
void
TimingArcAttrs::setCond(FuncExpr *cond)
{
cond_ = cond;
}
void
TimingArcAttrs::setSdfCond(const char *cond)
{

View File

@ -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)
{

View File

@ -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]}