write verilog match liberty bus bit order
This commit is contained in:
parent
c759feaff6
commit
eb9fdd1be0
|
|
@ -170,7 +170,7 @@ public:
|
|||
Cell *cell() const;
|
||||
ConcreteLibrary *library() const { return cell_->library(); }
|
||||
PortDirection *direction() const { return direction_; }
|
||||
LibertyPort *libertyPort() { return liberty_port_; }
|
||||
LibertyPort *libertyPort() const { return liberty_port_; }
|
||||
void setLibertyPort(LibertyPort *port);
|
||||
void setDirection(PortDirection *dir);
|
||||
// Bundles are groups of related ports that do not use
|
||||
|
|
|
|||
|
|
@ -755,9 +755,9 @@ ConcreteNetwork::cell(const Port *port) const
|
|||
}
|
||||
|
||||
LibertyPort *
|
||||
ConcreteNetwork::libertyPort(Port *port) const
|
||||
ConcreteNetwork::libertyPort(const Port *port) const
|
||||
{
|
||||
ConcretePort *cport = reinterpret_cast<ConcretePort*>(port);
|
||||
const ConcretePort *cport = reinterpret_cast<const ConcretePort*>(port);
|
||||
return cport->libertyPort();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ public:
|
|||
|
||||
virtual const char *name(const Port *port) const;
|
||||
virtual Cell *cell(const Port *port) const;
|
||||
virtual LibertyPort *libertyPort(Port *port) const;
|
||||
virtual LibertyPort *libertyPort(const Port *port) const;
|
||||
virtual PortDirection *direction(const Port *port) const;
|
||||
virtual bool isBundle(const Port *port) const;
|
||||
virtual bool hasMembers(const Port *port) const;
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ public:
|
|||
// Port functions
|
||||
virtual const char *name(const Port *port) const = 0;
|
||||
virtual Cell *cell(const Port *port) const = 0;
|
||||
virtual LibertyPort *libertyPort(Port *port) const = 0;
|
||||
virtual LibertyPort *libertyPort(const Port *port) const = 0;
|
||||
virtual PortDirection *direction(const Port *port) const = 0;
|
||||
// Bus port functions.
|
||||
virtual bool isBus(const Port *port) const = 0;
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ NetworkNameAdapter::cell(const Port *port) const
|
|||
}
|
||||
|
||||
LibertyPort *
|
||||
NetworkNameAdapter::libertyPort(Port *port) const
|
||||
NetworkNameAdapter::libertyPort(const Port *port) const
|
||||
{
|
||||
return network_->libertyPort(port);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ public:
|
|||
|
||||
virtual const char *name(const Port *port) const;
|
||||
virtual Cell *cell(const Port *port) const;
|
||||
virtual LibertyPort *libertyPort(Port *port) const;
|
||||
virtual LibertyPort *libertyPort(const Port *port) const;
|
||||
virtual PortDirection *direction(const Port *port) const;
|
||||
virtual bool isBundle(const Port *port) const;
|
||||
virtual bool isBus(const Port *port) const;
|
||||
|
|
|
|||
|
|
@ -678,6 +678,8 @@ Power::inferedWhen(FuncExpr *expr,
|
|||
case FuncExpr::op_zero:
|
||||
return nullptr;
|
||||
}
|
||||
// gcc not too smaht
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -138,6 +138,12 @@ PropertyValue::PropertyValue(LibertyCell *value) :
|
|||
{
|
||||
}
|
||||
|
||||
PropertyValue::PropertyValue(LibertyPort *value) :
|
||||
type_(type_liberty_port),
|
||||
liberty_port_(value)
|
||||
{
|
||||
}
|
||||
|
||||
PropertyValue::PropertyValue(Library *value) :
|
||||
type_(type_library),
|
||||
library_(value)
|
||||
|
|
@ -150,6 +156,12 @@ PropertyValue::PropertyValue(Cell *value) :
|
|||
{
|
||||
}
|
||||
|
||||
PropertyValue::PropertyValue(Port *value) :
|
||||
type_(type_port),
|
||||
port_(value)
|
||||
{
|
||||
}
|
||||
|
||||
PropertyValue::PropertyValue(Instance *value) :
|
||||
type_(type_instance),
|
||||
inst_(value)
|
||||
|
|
@ -241,12 +253,18 @@ PropertyValue::PropertyValue(const PropertyValue &value) :
|
|||
case Type::type_liberty_cell:
|
||||
liberty_cell_ = value.liberty_cell_;
|
||||
break;
|
||||
case Type::type_cell:
|
||||
cell_ = value.cell_;
|
||||
case Type::type_liberty_port:
|
||||
liberty_port_ = value.liberty_port_;
|
||||
break;
|
||||
case Type::type_library:
|
||||
library_ = value.library_;
|
||||
break;
|
||||
case Type::type_cell:
|
||||
cell_ = value.cell_;
|
||||
break;
|
||||
case Type::type_port:
|
||||
port_ = value.port_;
|
||||
break;
|
||||
case Type::type_instance:
|
||||
inst_ = value.inst_;
|
||||
break;
|
||||
|
|
@ -290,17 +308,23 @@ PropertyValue::PropertyValue(PropertyValue &&value) :
|
|||
case Type::type_bool:
|
||||
bool_ = value.bool_;
|
||||
break;
|
||||
case Type::type_library:
|
||||
library_ = value.library_;
|
||||
break;
|
||||
case Type::type_cell:
|
||||
cell_ = value.cell_;
|
||||
break;
|
||||
case Type::type_port:
|
||||
port_ = value.port_;
|
||||
break;
|
||||
case Type::type_liberty_library:
|
||||
liberty_library_ = value.liberty_library_;
|
||||
break;
|
||||
case Type::type_liberty_cell:
|
||||
liberty_cell_ = value.liberty_cell_;
|
||||
break;
|
||||
case Type::type_cell:
|
||||
cell_ = value.cell_;
|
||||
break;
|
||||
case Type::type_library:
|
||||
library_ = value.library_;
|
||||
case Type::type_liberty_port:
|
||||
liberty_port_ = value.liberty_port_;
|
||||
break;
|
||||
case Type::type_instance:
|
||||
inst_ = value.inst_;
|
||||
|
|
@ -370,17 +394,23 @@ PropertyValue::operator=(const PropertyValue &value)
|
|||
case Type::type_bool:
|
||||
bool_ = value.bool_;
|
||||
break;
|
||||
case Type::type_library:
|
||||
library_ = value.library_;
|
||||
break;
|
||||
case Type::type_cell:
|
||||
cell_ = value.cell_;
|
||||
break;
|
||||
case Type::type_port:
|
||||
port_ = value.port_;
|
||||
break;
|
||||
case Type::type_liberty_library:
|
||||
liberty_library_ = value.liberty_library_;
|
||||
break;
|
||||
case Type::type_liberty_cell:
|
||||
liberty_cell_ = value.liberty_cell_;
|
||||
break;
|
||||
case Type::type_cell:
|
||||
cell_ = value.cell_;
|
||||
break;
|
||||
case Type::type_library:
|
||||
library_ = value.library_;
|
||||
case Type::type_liberty_port:
|
||||
liberty_port_ = value.liberty_port_;
|
||||
break;
|
||||
case Type::type_instance:
|
||||
inst_ = value.inst_;
|
||||
|
|
@ -427,17 +457,23 @@ PropertyValue::operator=(PropertyValue &&value)
|
|||
case Type::type_bool:
|
||||
bool_ = value.bool_;
|
||||
break;
|
||||
case Type::type_library:
|
||||
library_ = value.library_;
|
||||
break;
|
||||
case Type::type_cell:
|
||||
cell_ = value.cell_;
|
||||
break;
|
||||
case Type::type_port:
|
||||
port_ = value.port_;
|
||||
break;
|
||||
case Type::type_liberty_library:
|
||||
liberty_library_ = value.liberty_library_;
|
||||
break;
|
||||
case Type::type_liberty_cell:
|
||||
liberty_cell_ = value.liberty_cell_;
|
||||
break;
|
||||
case Type::type_cell:
|
||||
cell_ = value.cell_;
|
||||
break;
|
||||
case Type::type_library:
|
||||
library_ = value.library_;
|
||||
case Type::type_liberty_port:
|
||||
liberty_port_ = value.liberty_port_;
|
||||
break;
|
||||
case Type::type_instance:
|
||||
inst_ = value.inst_;
|
||||
|
|
@ -576,6 +612,9 @@ getProperty(const Port *port,
|
|||
return PropertyValue(network->name(port));
|
||||
else if (stringEqual(property, "direction"))
|
||||
return PropertyValue(network->direction(port)->name());
|
||||
else if (stringEqual(property, "liberty_port"))
|
||||
return PropertyValue(network->libertyPort(port));
|
||||
|
||||
else if (stringEqual(property, "activity")) {
|
||||
const Instance *top_inst = network->topInstance();
|
||||
const Pin *pin = network->findPin(top_inst, port);
|
||||
|
|
|
|||
|
|
@ -30,12 +30,22 @@ using std::string;
|
|||
class Sta;
|
||||
class PwrActivity;
|
||||
|
||||
// Adding a new property type
|
||||
// value union
|
||||
// enum Type
|
||||
// constructor
|
||||
// copy constructor switch clause
|
||||
// move constructor switch clause
|
||||
// operator= & switch clause
|
||||
// operator= && switch clause
|
||||
// StaTcl.i swig %typemap(out) PropertyValue switch clause
|
||||
|
||||
class PropertyValue
|
||||
{
|
||||
public:
|
||||
enum Type { type_none, type_string, type_float, type_bool,
|
||||
type_liberty_library, type_liberty_cell,
|
||||
type_library, type_cell,
|
||||
type_library, type_cell, type_port,
|
||||
type_liberty_library, type_liberty_cell, type_liberty_port,
|
||||
type_instance, type_pin, type_pins, type_net,
|
||||
type_clk, type_clks, type_path_refs, type_pwr_activity };
|
||||
PropertyValue();
|
||||
|
|
@ -43,10 +53,12 @@ public:
|
|||
PropertyValue(string &value);
|
||||
PropertyValue(float value);
|
||||
PropertyValue(bool value);
|
||||
PropertyValue(Library *value);
|
||||
PropertyValue(Cell *value);
|
||||
PropertyValue(Port *value);
|
||||
PropertyValue(LibertyLibrary *value);
|
||||
PropertyValue(LibertyCell *value);
|
||||
PropertyValue(Cell *value);
|
||||
PropertyValue(Library *value);
|
||||
PropertyValue(LibertyPort *value);
|
||||
PropertyValue(Instance *value);
|
||||
PropertyValue(Pin *value);
|
||||
PropertyValue(PinSeq *value);
|
||||
|
|
@ -68,8 +80,10 @@ public:
|
|||
bool boolValue() const { return bool_; }
|
||||
LibertyLibrary *libertyLibrary() const { return liberty_library_; }
|
||||
LibertyCell *libertyCell() const { return liberty_cell_; }
|
||||
LibertyPort *libertyPort() const { return liberty_port_; }
|
||||
Library *library() const { return library_; }
|
||||
Cell *cell() const { return cell_; }
|
||||
Port *port() const { return port_; }
|
||||
Instance *instance() const { return inst_; }
|
||||
Pin *pin() const { return pin_; }
|
||||
PinSeq *pins() const { return pins_; }
|
||||
|
|
@ -89,10 +103,12 @@ private:
|
|||
const char *string_;
|
||||
float float_;
|
||||
bool bool_;
|
||||
LibertyLibrary *liberty_library_;
|
||||
LibertyCell *liberty_cell_;
|
||||
Library *library_;
|
||||
Cell *cell_;
|
||||
Port *port_;
|
||||
LibertyLibrary *liberty_library_;
|
||||
LibertyCell *liberty_cell_;
|
||||
LibertyPort *liberty_port_;
|
||||
Instance *inst_;
|
||||
Pin *pin_;
|
||||
PinSeq *pins_;
|
||||
|
|
|
|||
13
tcl/Sdc.tcl
13
tcl/Sdc.tcl
|
|
@ -1759,18 +1759,13 @@ proc parse_disable_inst_ports { inst port_name } {
|
|||
if { $port_name == "" } {
|
||||
set ports "NULL"
|
||||
} else {
|
||||
set cell [instance_property $inst liberty_cell]
|
||||
set port [$cell find_liberty_port $port_name]
|
||||
set cell [instance_property $inst cell]
|
||||
set port [$cell find_port $port_name]
|
||||
if { $port == "NULL" } {
|
||||
sta_error "pin '[get_full_name $inst]${hierarchy_separator}${port_name}' not found."
|
||||
} else {
|
||||
set ports [port_members $port]
|
||||
foreach port $ports {
|
||||
set member_name [get_full_name $port]
|
||||
if { [$inst find_pin $member_name] == "NULL" } {
|
||||
sta_error "pin '[get_full_name $inst]]${hierarchy_separator}${member_name}' not found."
|
||||
}
|
||||
}
|
||||
set lib_port [get_property $port liberty_port]
|
||||
set ports [port_members $lib_port]
|
||||
}
|
||||
}
|
||||
return $ports
|
||||
|
|
|
|||
60
tcl/StaTcl.i
60
tcl/StaTcl.i
|
|
@ -1401,6 +1401,42 @@ using namespace sta;
|
|||
Tcl_SetResult(interp, const_cast<char*>(bool_string), TCL_STATIC);
|
||||
}
|
||||
break;
|
||||
case PropertyValue::Type::type_library: {
|
||||
Tcl_Obj *obj = SWIG_NewInstanceObj(value.library(),
|
||||
SWIGTYPE_p_Library, false);
|
||||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
break;
|
||||
case PropertyValue::Type::type_cell: {
|
||||
Tcl_Obj *obj = SWIG_NewInstanceObj(value.cell(),
|
||||
SWIGTYPE_p_Cell, false);
|
||||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
break;
|
||||
case PropertyValue::Type::type_port: {
|
||||
Tcl_Obj *obj = SWIG_NewInstanceObj(value.port(),
|
||||
SWIGTYPE_p_Port, false);
|
||||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
break;
|
||||
case PropertyValue::Type::type_liberty_library: {
|
||||
Tcl_Obj *obj = SWIG_NewInstanceObj(value.libertyLibrary(),
|
||||
SWIGTYPE_p_LibertyLibrary, false);
|
||||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
break;
|
||||
case PropertyValue::Type::type_liberty_cell: {
|
||||
Tcl_Obj *obj = SWIG_NewInstanceObj(value.libertyCell(),
|
||||
SWIGTYPE_p_LibertyCell, false);
|
||||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
break;
|
||||
case PropertyValue::Type::type_liberty_port: {
|
||||
Tcl_Obj *obj = SWIG_NewInstanceObj(value.libertyPort(),
|
||||
SWIGTYPE_p_LibertyPort, false);
|
||||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
break;
|
||||
case PropertyValue::Type::type_instance: {
|
||||
Tcl_Obj *obj = SWIG_NewInstanceObj(value.instance(),
|
||||
SWIGTYPE_p_Instance, false);
|
||||
|
|
@ -1430,30 +1466,6 @@ using namespace sta;
|
|||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
break;
|
||||
case PropertyValue::Type::type_liberty_cell: {
|
||||
Tcl_Obj *obj = SWIG_NewInstanceObj(value.libertyCell(),
|
||||
SWIGTYPE_p_LibertyCell, false);
|
||||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
break;
|
||||
case PropertyValue::Type::type_liberty_library: {
|
||||
Tcl_Obj *obj = SWIG_NewInstanceObj(value.libertyLibrary(),
|
||||
SWIGTYPE_p_LibertyLibrary, false);
|
||||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
break;
|
||||
case PropertyValue::Type::type_library: {
|
||||
Tcl_Obj *obj = SWIG_NewInstanceObj(value.library(),
|
||||
SWIGTYPE_p_Library, false);
|
||||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
break;
|
||||
case PropertyValue::Type::type_cell: {
|
||||
Tcl_Obj *obj = SWIG_NewInstanceObj(value.cell(),
|
||||
SWIGTYPE_p_Cell, false);
|
||||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
break;
|
||||
case PropertyValue::Type::type_clk: {
|
||||
Tcl_Obj *obj = SWIG_NewInstanceObj(value.clock(),
|
||||
SWIGTYPE_p_Clock, false);
|
||||
|
|
|
|||
|
|
@ -1755,8 +1755,7 @@ VerilogReader::linkNetwork(const char *top_cell_name,
|
|||
return top_instance;
|
||||
}
|
||||
else {
|
||||
report->error("%s is not a verilog module.\n",
|
||||
network_->name(top_cell));
|
||||
report->error("%s is not a verilog module.\n", top_cell_name);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "Machine.hh"
|
||||
#include "Error.hh"
|
||||
#include "PortDirection.hh"
|
||||
#include "Liberty.hh"
|
||||
#include "Network.hh"
|
||||
#include "NetworkCmp.hh"
|
||||
#include "VerilogNamespace.hh"
|
||||
|
|
@ -40,6 +41,15 @@ protected:
|
|||
const char *verilogPortDir(PortDirection *dir);
|
||||
void writeChildren(Instance *inst);
|
||||
void writeChild(Instance *child);
|
||||
void writeInstPin(Instance *inst,
|
||||
Port *port,
|
||||
bool &first_port);
|
||||
void writeInstBusPin(Instance *inst,
|
||||
Port *port,
|
||||
bool &first_port);
|
||||
void writeInstBusPinBit(Instance *inst,
|
||||
Port *port,
|
||||
bool &first_member);
|
||||
|
||||
const char *filename_;
|
||||
bool sort_;
|
||||
|
|
@ -194,54 +204,96 @@ VerilogWriter::writeChild(Instance *child)
|
|||
CellPortIterator *port_iter = network_->portIterator(child_cell);
|
||||
while (port_iter->hasNext()) {
|
||||
Port *port = port_iter->next();
|
||||
const char *port_name = network_->name(port);
|
||||
if (network_->hasMembers(port)) {
|
||||
if (!first_port)
|
||||
fprintf(stream_, ",\n ");
|
||||
fprintf(stream_, ".%s({", port_name);
|
||||
first_port = false;
|
||||
bool first_member = true;
|
||||
PortMemberIterator *member_iter = network_->memberIterator(port);
|
||||
while (member_iter->hasNext()) {
|
||||
Port *member = member_iter->next();
|
||||
Pin *pin = network_->findPin(child, member);
|
||||
const char *net_name = nullptr;
|
||||
if (pin) {
|
||||
Net *net = network_->net(pin);
|
||||
if (net)
|
||||
net_name = network_->name(net);
|
||||
}
|
||||
if (net_name == nullptr)
|
||||
// There is no verilog syntax to "skip" a bit in the concatentation.
|
||||
net_name = stringPrintTmp("_NC%d", unconnected_net_index_++);
|
||||
const char *net_vname = netVerilogName(net_name, network_->pathEscape());
|
||||
if (!first_member)
|
||||
fprintf(stream_, ",\n ");
|
||||
fprintf(stream_, "%s", net_vname);
|
||||
first_member = false;
|
||||
}
|
||||
delete member_iter;
|
||||
fprintf(stream_, "})");
|
||||
}
|
||||
else {
|
||||
Pin *pin = network_->findPin(child, port);
|
||||
if (pin) {
|
||||
Net *net = network_->net(pin);
|
||||
if (net) {
|
||||
const char *net_name = network_->name(net);
|
||||
const char *net_vname = netVerilogName(net_name, network_->pathEscape());
|
||||
if (!first_port)
|
||||
fprintf(stream_, ",\n ");
|
||||
fprintf(stream_, ".%s(%s)",
|
||||
port_name,
|
||||
net_vname);
|
||||
first_port = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (network_->hasMembers(port))
|
||||
writeInstBusPin(child, port, first_port);
|
||||
else
|
||||
writeInstPin(child, port, first_port);
|
||||
}
|
||||
delete port_iter;
|
||||
fprintf(stream_, ");\n");
|
||||
}
|
||||
|
||||
void
|
||||
VerilogWriter::writeInstPin(Instance *inst,
|
||||
Port *port,
|
||||
bool &first_port)
|
||||
{
|
||||
Pin *pin = network_->findPin(inst, port);
|
||||
if (pin) {
|
||||
Net *net = network_->net(pin);
|
||||
if (net) {
|
||||
const char *net_name = network_->name(net);
|
||||
const char *net_vname = netVerilogName(net_name, network_->pathEscape());
|
||||
if (!first_port)
|
||||
fprintf(stream_, ",\n ");
|
||||
const char *port_name = network_->name(port);
|
||||
fprintf(stream_, ".%s(%s)",
|
||||
port_name,
|
||||
net_vname);
|
||||
first_port = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VerilogWriter::writeInstBusPin(Instance *inst,
|
||||
Port *port,
|
||||
bool &first_port)
|
||||
{
|
||||
if (!first_port)
|
||||
fprintf(stream_, ",\n ");
|
||||
|
||||
const char *port_name = network_->name(port);
|
||||
fprintf(stream_, ".%s({", port_name);
|
||||
first_port = false;
|
||||
bool first_member = true;
|
||||
PortSeq members;
|
||||
PortMemberIterator *member_iter = network_->memberIterator(port);
|
||||
while (member_iter->hasNext()) {
|
||||
Port *member = member_iter->next();
|
||||
members.push_back(member);
|
||||
}
|
||||
delete member_iter;
|
||||
|
||||
// Match the bit_from/bit_to order of the liberty cell if it exists.
|
||||
LibertyPort *lib_port = network_->libertyPort(port);
|
||||
if (lib_port
|
||||
&& (network_->fromIndex(port) > network_->toIndex(port))
|
||||
!= (lib_port->fromIndex() > lib_port->toIndex())) {
|
||||
for (int i = members.size() - 1; i >= 0; i--) {
|
||||
Port *member = members[i];
|
||||
writeInstBusPinBit(inst, member, first_member);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < members.size(); i++) {
|
||||
Port *member = members[i];
|
||||
writeInstBusPinBit(inst, member, first_member);
|
||||
}
|
||||
}
|
||||
fprintf(stream_, "})");
|
||||
}
|
||||
|
||||
void
|
||||
VerilogWriter::writeInstBusPinBit(Instance *inst,
|
||||
Port *port,
|
||||
bool &first_member)
|
||||
{
|
||||
Pin *pin = network_->findPin(inst, port);
|
||||
const char *net_name = nullptr;
|
||||
if (pin) {
|
||||
Net *net = network_->net(pin);
|
||||
if (net)
|
||||
net_name = network_->name(net);
|
||||
}
|
||||
if (net_name == nullptr)
|
||||
// There is no verilog syntax to "skip" a bit in the concatentation.
|
||||
net_name = stringPrintTmp("_NC%d", unconnected_net_index_++);
|
||||
const char *net_vname = netVerilogName(net_name, network_->pathEscape());
|
||||
if (!first_member)
|
||||
fprintf(stream_, ",\n ");
|
||||
fprintf(stream_, "%s", net_vname);
|
||||
first_member = false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
Loading…
Reference in New Issue