summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2013-10-16 16:16:06 +0200
committerClifford Wolf <clifford@clifford.at>2013-10-16 16:16:06 +0200
commit96e7abad48c942452f247267f219d38be902f804 (patch)
treecddc562437bc3c44376a34b2245d7bee12cc8816
parentb6db2d9b3382ac3725f81586198ad7d9c014e990 (diff)
Added iopadmap pass
-rw-r--r--README7
-rw-r--r--passes/opt/opt_clean.cc2
-rw-r--r--passes/techmap/Makefile.inc1
-rw-r--r--passes/techmap/iopadmap.cc159
4 files changed, 167 insertions, 2 deletions
diff --git a/README b/README
index df504ad2..cf5fbdb1 100644
--- 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
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index 96c4c7a1..2ea60c03 100644
--- a/passes/opt/opt_clean.cc
+++ b/passes/opt/opt_clean.cc
@@ -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);
}
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index 02260356..abe2ac5e 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -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
index 00000000..03d0d181
--- /dev/null
+++ b/passes/techmap/iopadmap.cc
@@ -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;
+