From eb9fdd1be0bb50d00ed1487918b85758657c6d79 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 2 Jul 2019 07:07:34 -0700 Subject: [PATCH] write verilog match liberty bus bit order --- network/ConcreteLibrary.hh | 2 +- network/ConcreteNetwork.cc | 4 +- network/ConcreteNetwork.hh | 2 +- network/Network.hh | 2 +- network/SdcNetwork.cc | 2 +- network/SdcNetwork.hh | 2 +- search/Power.cc | 2 + search/Property.cc | 73 ++++++++++++++----- search/Property.hh | 28 ++++++-- tcl/Sdc.tcl | 13 ++-- tcl/StaTcl.i | 60 +++++++++------- verilog/VerilogReader.cc | 3 +- verilog/VerilogWriter.cc | 142 +++++++++++++++++++++++++------------ 13 files changed, 225 insertions(+), 110 deletions(-) diff --git a/network/ConcreteLibrary.hh b/network/ConcreteLibrary.hh index 83941d0a..906b135c 100644 --- a/network/ConcreteLibrary.hh +++ b/network/ConcreteLibrary.hh @@ -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 diff --git a/network/ConcreteNetwork.cc b/network/ConcreteNetwork.cc index 4e872ae3..ecc6b360 100644 --- a/network/ConcreteNetwork.cc +++ b/network/ConcreteNetwork.cc @@ -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(port); + const ConcretePort *cport = reinterpret_cast(port); return cport->libertyPort(); } diff --git a/network/ConcreteNetwork.hh b/network/ConcreteNetwork.hh index a4c5266f..87f68f9c 100644 --- a/network/ConcreteNetwork.hh +++ b/network/ConcreteNetwork.hh @@ -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; diff --git a/network/Network.hh b/network/Network.hh index 3696a36c..5fcf0dd4 100644 --- a/network/Network.hh +++ b/network/Network.hh @@ -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; diff --git a/network/SdcNetwork.cc b/network/SdcNetwork.cc index 90cc8d5a..204dcc38 100644 --- a/network/SdcNetwork.cc +++ b/network/SdcNetwork.cc @@ -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); } diff --git a/network/SdcNetwork.hh b/network/SdcNetwork.hh index f933fc52..b23f0e1a 100644 --- a/network/SdcNetwork.hh +++ b/network/SdcNetwork.hh @@ -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; diff --git a/search/Power.cc b/search/Power.cc index 62e6f5ac..99fd61cc 100644 --- a/search/Power.cc +++ b/search/Power.cc @@ -678,6 +678,8 @@ Power::inferedWhen(FuncExpr *expr, case FuncExpr::op_zero: return nullptr; } + // gcc not too smaht + return nullptr; } //////////////////////////////////////////////////////////////// diff --git a/search/Property.cc b/search/Property.cc index 422ab29a..7635af04 100644 --- a/search/Property.cc +++ b/search/Property.cc @@ -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); diff --git a/search/Property.hh b/search/Property.hh index 8f4693d7..c90ec0e4 100644 --- a/search/Property.hh +++ b/search/Property.hh @@ -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_; diff --git a/tcl/Sdc.tcl b/tcl/Sdc.tcl index 777e4daa..8bfa9893 100644 --- a/tcl/Sdc.tcl +++ b/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 diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index 88758b82..6fa9b6ce 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -1401,6 +1401,42 @@ using namespace sta; Tcl_SetResult(interp, const_cast(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); diff --git a/verilog/VerilogReader.cc b/verilog/VerilogReader.cc index 4dbf89f6..bc5e884b 100644 --- a/verilog/VerilogReader.cc +++ b/verilog/VerilogReader.cc @@ -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; } } diff --git a/verilog/VerilogWriter.cc b/verilog/VerilogWriter.cc index 9a82987f..18289125 100644 --- a/verilog/VerilogWriter.cc +++ b/verilog/VerilogWriter.cc @@ -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