03d0d181c0bfe999fc9773d5817c94395e05806e
[yosys.git] / passes / techmap / iopadmap.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "kernel/register.h"
21 #include "kernel/rtlil.h"
22 #include "kernel/log.h"
23
24 struct IopadmapPass : public Pass {
25 IopadmapPass() : Pass("iopadmap", "technology mapping of flip-flops") { }
26 virtual void help()
27 {
28 log("\n");
29 log(" iopadmap [options] [selection]\n");
30 log("\n");
31 log("Map module inputs/outputs to PAD cells from a library. This pass\n");
32 log("can only map to very simple PAD cells. Use 'techmap' to further map\n");
33 log("the resulting cells to more sophisticated PAD cells.\n");
34 log("\n");
35 log(" -inpad <celltype> <portname>\n");
36 log(" Map module input ports to the given cell type with\n");
37 log(" the given port name.\n");
38 log("\n");
39 log(" -outpad <celltype> <portname>\n");
40 log(" -inoutpad <celltype> <portname>\n");
41 log(" Similar to -inpad, but for output and inout ports.\n");
42 log("\n");
43 log(" -widthparam <param_name>\n");
44 log(" Use the specified parameter name to set the port width.\n");
45 log("\n");
46 log(" -nameparam <param_name>\n");
47 log(" Use the specified parameter to set the port name.\n");
48 log("\n");
49 }
50 virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
51 {
52 log_header("Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n");
53
54 std::string inpad_celltype, inpad_portname;
55 std::string outpad_celltype, outpad_portname;
56 std::string inoutpad_celltype, inoutpad_portname;
57 std::string widthparam, nameparam;
58
59 size_t argidx;
60 for (argidx = 1; argidx < args.size(); argidx++)
61 {
62 std::string arg = args[argidx];
63 if (arg == "-inpad" && argidx+2 < args.size()) {
64 inpad_celltype = args[++argidx];
65 inpad_portname = args[++argidx];
66 continue;
67 }
68 if (arg == "-outpad" && argidx+2 < args.size()) {
69 outpad_celltype = args[++argidx];
70 outpad_portname = args[++argidx];
71 continue;
72 }
73 if (arg == "-inoutpad" && argidx+2 < args.size()) {
74 inoutpad_celltype = args[++argidx];
75 inoutpad_portname = args[++argidx];
76 continue;
77 }
78 if (arg == "-widthparam" && argidx+1 < args.size()) {
79 widthparam = args[++argidx];
80 continue;
81 }
82 if (arg == "-nameparam" && argidx+1 < args.size()) {
83 nameparam = args[++argidx];
84 continue;
85 }
86 break;
87 }
88 extra_args(args, argidx, design);
89
90 for (auto &it : design->modules)
91 {
92 RTLIL::Module *module = it.second;
93
94 if (!design->selected(module))
95 continue;
96
97 for (auto &it2 : module->wires)
98 {
99 RTLIL::Wire *wire = it2.second;
100
101 if (!wire->port_id || !design->selected(module, wire))
102 continue;
103
104 std::string celltype, portname;
105
106 if (wire->port_input && !wire->port_output) {
107 if (inpad_celltype.empty()) {
108 log("Don't map input port %s.%s: Missing option -inpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
109 continue;
110 }
111 celltype = inpad_celltype;
112 portname = inpad_portname;
113 } else
114 if (!wire->port_input && wire->port_output) {
115 if (outpad_celltype.empty()) {
116 log("Don't map output port %s.%s: Missing option -outpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
117 continue;
118 }
119 celltype = outpad_celltype;
120 portname = outpad_portname;
121 } else
122 if (wire->port_input && wire->port_output) {
123 if (inoutpad_celltype.empty()) {
124 log("Don't map inout port %s.%s: Missing option -inoutpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
125 continue;
126 }
127 celltype = inoutpad_celltype;
128 portname = inoutpad_portname;
129 } else
130 log_abort();
131
132 if (wire->width != 1 && widthparam.empty()) {
133 log("Don't map multi-bit port %s.%s: Missing option -widthparam.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
134 continue;
135 }
136
137 log("Mapping port %s.%s.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
138
139 RTLIL::Cell *cell = new RTLIL::Cell;
140 cell->name = NEW_ID;
141 cell->type = RTLIL::escape_id(celltype);
142 cell->connections[RTLIL::escape_id(portname)] = RTLIL::SigSpec(wire);
143 if (!widthparam.empty())
144 cell->parameters[RTLIL::escape_id(widthparam)] = RTLIL::Const(wire->width);
145 if (!nameparam.empty())
146 cell->parameters[RTLIL::escape_id(nameparam)] = RTLIL::Const(RTLIL::id2cstr(wire->name));
147 cell->attributes["\\keep"] = RTLIL::Const();
148 module->add(cell);
149
150 wire->port_id = 0;
151 wire->port_input = false;
152 wire->port_output = false;
153 }
154
155 module->fixup_ports();
156 }
157 }
158 } IopadmapPass;
159