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:
parent
343b93b633
commit
c2a0c4db30
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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_; }
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,12 @@ LeakagePowerAttrs::LeakagePowerAttrs() :
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
LeakagePowerAttrs::setWhen(FuncExpr *when)
|
||||
{
|
||||
when_ = when;
|
||||
}
|
||||
|
||||
void
|
||||
LeakagePowerAttrs::setPower(float power)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -101,6 +101,12 @@ TimingArcAttrs::setTimingSense(TimingSense sense)
|
|||
timing_sense_ = sense;
|
||||
}
|
||||
|
||||
void
|
||||
TimingArcAttrs::setCond(FuncExpr *cond)
|
||||
{
|
||||
cond_ = cond;
|
||||
}
|
||||
|
||||
void
|
||||
TimingArcAttrs::setSdfCond(const char *cond)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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]}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue