From 96e7abad48c942452f247267f219d38be902f804 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 16 Oct 2013 16:16:06 +0200 Subject: [PATCH] Added iopadmap pass --- README | 7 +- passes/opt/opt_clean.cc | 2 +- passes/techmap/Makefile.inc | 1 + passes/techmap/iopadmap.cc | 159 ++++++++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 passes/techmap/iopadmap.cc diff --git a/README b/README index df504ad24..cf5fbdb13 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 96c4c7a18..2ea60c03c 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 022603564..abe2ac5e6 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 000000000..03d0d181c --- /dev/null +++ b/passes/techmap/iopadmap.cc @@ -0,0 +1,159 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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 \n"); + log(" Map module input ports to the given cell type with\n"); + log(" the given port name.\n"); + log("\n"); + log(" -outpad \n"); + log(" -inoutpad \n"); + log(" Similar to -inpad, but for output and inout ports.\n"); + log("\n"); + log(" -widthparam \n"); + log(" Use the specified parameter name to set the port width.\n"); + log("\n"); + log(" -nameparam \n"); + log(" Use the specified parameter to set the port name.\n"); + log("\n"); + } + virtual void execute(std::vector 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; + -- 2.30.2