Added iopadmap pass
authorClifford Wolf <clifford@clifford.at>
Wed, 16 Oct 2013 14:16:06 +0000 (16:16 +0200)
committerClifford Wolf <clifford@clifford.at>
Wed, 16 Oct 2013 14:16:06 +0000 (16:16 +0200)
README
passes/opt/opt_clean.cc
passes/techmap/Makefile.inc
passes/techmap/iopadmap.cc [new file with mode: 0644]

diff --git a/README b/README
index df504ad24fd5702d709a323b6654ea869122dc6b..cf5fbdb137a0f74d16755ad17b5c67fff2485702 100644 (file)
--- a/README
+++ b/README
@@ -232,7 +232,8 @@ Verilog Attributes and non-standard features
 
 - The "nolatches" attribute on modules or always-blocks
   prohibits the generation of logic-loops for latches. Instead
-  all not explicitly assigned values default to x-bits.
+  all not explicitly assigned values default to x-bits. This does
+  not affect clocked storage elements such as flip-flops.
 
 - The "nosync" attribute on registers prohibits the generation of a
   storage element. The register itself will always have all bits set
@@ -246,6 +247,10 @@ Verilog Attributes and non-standard features
   passes to identify input and output ports of cells. The verilog backend
   also does not output placeholder modules on default.
 
+- The "keep" attribute on cells is used to mark cells that should never be
+  removed by the optimizer. This is used for example for cells that have
+  hidden connections that are not part of the netlist, such as IO pads.
+
 - In addition to the (* ... *) attribute syntax, yosys supports
   the non-standard {* ... *} attribute syntax to set default attributes
   for everything that comes after the {* ... *} statement. (Reset
index 96c4c7a1806b674c466ea561c3f37ca5e9233833..2ea60c03cad3902043a819638ae25800a3936823 100644 (file)
@@ -47,7 +47,7 @@ static void rmunused_module_cells(RTLIL::Module *module, bool verbose)
                                wire2driver.insert(sig, cell);
                        }
                }
-               if (cell->type == "$memwr")
+               if (cell->type == "$memwr" || cell->attributes.count("\\keep"))
                        queue.insert(cell);
                unused.insert(cell);
        }
index 02260356411fff51a6af286e34e4547e3c02a623..abe2ac5e62818f1a53c5e452415e2e129d8ac81d 100644 (file)
@@ -1,6 +1,7 @@
 
 OBJS += passes/techmap/techmap.o
 OBJS += passes/techmap/dfflibmap.o
+OBJS += passes/techmap/iopadmap.o
 OBJS += passes/techmap/libparse.o
 
 GENFILES += passes/techmap/stdcells.inc
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
new file mode 100644 (file)
index 0000000..03d0d18
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+ *  
+ *  Permission to use, copy, modify, and/or distribute this software for any
+ *  purpose with or without fee is hereby granted, provided that the above
+ *  copyright notice and this permission notice appear in all copies.
+ *  
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/register.h"
+#include "kernel/rtlil.h"
+#include "kernel/log.h"
+
+struct IopadmapPass : public Pass {
+       IopadmapPass() : Pass("iopadmap", "technology mapping of flip-flops") { }
+       virtual void help()
+       {
+               log("\n");
+               log("    iopadmap [options] [selection]\n");
+               log("\n");
+               log("Map module inputs/outputs to PAD cells from a library. This pass\n");
+               log("can only map to very simple PAD cells. Use 'techmap' to further map\n");
+               log("the resulting cells to more sophisticated PAD cells.\n");
+               log("\n");
+               log("    -inpad <celltype> <portname>\n");
+               log("        Map module input ports to the given cell type with\n");
+               log("        the given port name.\n");
+               log("\n");
+               log("    -outpad <celltype> <portname>\n");
+               log("    -inoutpad <celltype> <portname>\n");
+               log("        Similar to -inpad, but for output and inout ports.\n");
+               log("\n");
+               log("    -widthparam <param_name>\n");
+               log("        Use the specified parameter name to set the port width.\n");
+               log("\n");
+               log("    -nameparam <param_name>\n");
+               log("        Use the specified parameter to set the port name.\n");
+               log("\n");
+       }
+       virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+       {
+               log_header("Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n");
+
+               std::string inpad_celltype, inpad_portname;
+               std::string outpad_celltype, outpad_portname;
+               std::string inoutpad_celltype, inoutpad_portname;
+               std::string widthparam, nameparam;
+
+               size_t argidx;
+               for (argidx = 1; argidx < args.size(); argidx++)
+               {
+                       std::string arg = args[argidx];
+                       if (arg == "-inpad" && argidx+2 < args.size()) {
+                               inpad_celltype = args[++argidx];
+                               inpad_portname = args[++argidx];
+                               continue;
+                       }
+                       if (arg == "-outpad" && argidx+2 < args.size()) {
+                               outpad_celltype = args[++argidx];
+                               outpad_portname = args[++argidx];
+                               continue;
+                       }
+                       if (arg == "-inoutpad" && argidx+2 < args.size()) {
+                               inoutpad_celltype = args[++argidx];
+                               inoutpad_portname = args[++argidx];
+                               continue;
+                       }
+                       if (arg == "-widthparam" && argidx+1 < args.size()) {
+                               widthparam = args[++argidx];
+                               continue;
+                       }
+                       if (arg == "-nameparam" && argidx+1 < args.size()) {
+                               nameparam = args[++argidx];
+                               continue;
+                       }
+                       break;
+               }
+               extra_args(args, argidx, design);
+
+               for (auto &it : design->modules)
+               {
+                       RTLIL::Module *module = it.second;
+
+                       if (!design->selected(module))
+                               continue;
+
+                       for (auto &it2 : module->wires)
+                       {
+                               RTLIL::Wire *wire = it2.second;
+
+                               if (!wire->port_id || !design->selected(module, wire))
+                                       continue;
+
+                               std::string celltype, portname;
+
+                               if (wire->port_input && !wire->port_output) {
+                                       if (inpad_celltype.empty()) {
+                                               log("Don't map input port %s.%s: Missing option -inpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
+                                               continue;
+                                       }
+                                       celltype = inpad_celltype;
+                                       portname = inpad_portname;
+                               } else
+                               if (!wire->port_input && wire->port_output) {
+                                       if (outpad_celltype.empty()) {
+                                               log("Don't map output port %s.%s: Missing option -outpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
+                                               continue;
+                                       }
+                                       celltype = outpad_celltype;
+                                       portname = outpad_portname;
+                               } else
+                               if (wire->port_input && wire->port_output) {
+                                       if (inoutpad_celltype.empty()) {
+                                               log("Don't map inout port %s.%s: Missing option -inoutpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
+                                               continue;
+                                       }
+                                       celltype = inoutpad_celltype;
+                                       portname = inoutpad_portname;
+                               } else
+                                       log_abort();
+
+                               if (wire->width != 1 && widthparam.empty()) {
+                                       log("Don't map multi-bit port %s.%s: Missing option -widthparam.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
+                                       continue;
+                               }
+
+                               log("Mapping port %s.%s.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
+
+                               RTLIL::Cell *cell = new RTLIL::Cell;
+                               cell->name = NEW_ID;
+                               cell->type = RTLIL::escape_id(celltype);
+                               cell->connections[RTLIL::escape_id(portname)] = RTLIL::SigSpec(wire);
+                               if (!widthparam.empty())
+                                       cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(wire->width);
+                               if (!nameparam.empty())
+                                       cell->parameters[RTLIL::escape_id(nameparam)] = RTLIL::Const(RTLIL::id2cstr(wire->name));
+                               cell->attributes["\\keep"] = RTLIL::Const();
+                               module->add(cell);
+
+                               wire->port_id = 0;
+                               wire->port_input = false;
+                               wire->port_output = false;
+                       }
+
+                       module->fixup_ports();
+               }
+       }
+} IopadmapPass;