2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 #include "kernel/register.h"
21 #include "kernel/rtlil.h"
22 #include "kernel/log.h"
24 static void split_portname_pair(std::string
&port1
, std::string
&port2
)
26 size_t pos
= port1
.find_first_of(':');
27 if (pos
!= std::string::npos
) {
28 port2
= port1
.substr(pos
+1);
29 port1
= port1
.substr(0, pos
);
33 struct IopadmapPass
: public Pass
{
34 IopadmapPass() : Pass("iopadmap", "technology mapping of i/o pads (or buffers)") { }
38 log(" iopadmap [options] [selection]\n");
40 log("Map module inputs/outputs to PAD cells from a library. This pass\n");
41 log("can only map to very simple PAD cells. Use 'techmap' to further map\n");
42 log("the resulting cells to more sophisticated PAD cells.\n");
44 log(" -inpad <celltype> <portname>[:<portname>]\n");
45 log(" Map module input ports to the given cell type with\n");
46 log(" the given port name. if a 2nd portname is given, the\n");
47 log(" signal is passed through the pad call, using the 2nd\n");
48 log(" portname as output.\n");
50 log(" -outpad <celltype> <portname>[:<portname>]\n");
51 log(" -inoutpad <celltype> <portname>[:<portname>]\n");
52 log(" Similar to -inpad, but for output and inout ports.\n");
54 log(" -widthparam <param_name>\n");
55 log(" Use the specified parameter name to set the port width.\n");
57 log(" -nameparam <param_name>\n");
58 log(" Use the specified parameter to set the port name.\n");
61 log(" create individual bit-wide buffers even for ports that\n");
62 log(" are wider. (the default behavio is to create word-wide\n");
63 log(" buffers use -widthparam to set the word size on the cell.)\n");
66 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
68 log_header("Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n");
70 std::string inpad_celltype
, inpad_portname
, inpad_portname2
;
71 std::string outpad_celltype
, outpad_portname
, outpad_portname2
;
72 std::string inoutpad_celltype
, inoutpad_portname
, inoutpad_portname2
;
73 std::string widthparam
, nameparam
;
74 bool flag_bits
= false;
77 for (argidx
= 1; argidx
< args
.size(); argidx
++)
79 std::string arg
= args
[argidx
];
80 if (arg
== "-inpad" && argidx
+2 < args
.size()) {
81 inpad_celltype
= args
[++argidx
];
82 inpad_portname
= args
[++argidx
];
83 split_portname_pair(inpad_portname
, inpad_portname2
);
86 if (arg
== "-outpad" && argidx
+2 < args
.size()) {
87 outpad_celltype
= args
[++argidx
];
88 outpad_portname
= args
[++argidx
];
89 split_portname_pair(outpad_portname
, outpad_portname2
);
92 if (arg
== "-inoutpad" && argidx
+2 < args
.size()) {
93 inoutpad_celltype
= args
[++argidx
];
94 inoutpad_portname
= args
[++argidx
];
95 split_portname_pair(inoutpad_portname
, inoutpad_portname2
);
98 if (arg
== "-widthparam" && argidx
+1 < args
.size()) {
99 widthparam
= args
[++argidx
];
102 if (arg
== "-nameparam" && argidx
+1 < args
.size()) {
103 nameparam
= args
[++argidx
];
106 if (arg
== "-bits") {
112 extra_args(args
, argidx
, design
);
114 for (auto &it
: design
->modules_
)
116 RTLIL::Module
*module
= it
.second
;
118 if (!design
->selected(module
) || module
->get_bool_attribute("\\blackbox"))
121 for (auto &it2
: module
->wires_
)
123 RTLIL::Wire
*wire
= it2
.second
;
125 if (!wire
->port_id
|| !design
->selected(module
, wire
))
128 std::string celltype
, portname
, portname2
;
130 if (wire
->port_input
&& !wire
->port_output
) {
131 if (inpad_celltype
.empty()) {
132 log("Don't map input port %s.%s: Missing option -inpad.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
));
135 celltype
= inpad_celltype
;
136 portname
= inpad_portname
;
137 portname2
= inpad_portname2
;
139 if (!wire
->port_input
&& wire
->port_output
) {
140 if (outpad_celltype
.empty()) {
141 log("Don't map output port %s.%s: Missing option -outpad.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
));
144 celltype
= outpad_celltype
;
145 portname
= outpad_portname
;
146 portname2
= outpad_portname2
;
148 if (wire
->port_input
&& wire
->port_output
) {
149 if (inoutpad_celltype
.empty()) {
150 log("Don't map inout port %s.%s: Missing option -inoutpad.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
));
153 celltype
= inoutpad_celltype
;
154 portname
= inoutpad_portname
;
155 portname2
= inoutpad_portname2
;
159 if (!flag_bits
&& wire
->width
!= 1 && widthparam
.empty()) {
160 log("Don't map multi-bit port %s.%s: Missing option -widthparam or -bits.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
));
164 log("Mapping port %s.%s using %s.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
), celltype
.c_str());
166 RTLIL::Wire
*new_wire
= NULL
;
167 if (!portname2
.empty())
168 new_wire
= module
->addWire(NEW_ID
, wire
);
172 for (int i
= 0; i
< wire
->width
; i
++)
174 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, RTLIL::escape_id(celltype
));
175 cell
->setPort(RTLIL::escape_id(portname
), RTLIL::SigSpec(wire
, i
));
176 if (!portname2
.empty())
177 cell
->setPort(RTLIL::escape_id(portname2
), RTLIL::SigSpec(new_wire
, i
));
178 if (!widthparam
.empty())
179 cell
->parameters
[RTLIL::escape_id(widthparam
)] = RTLIL::Const(1);
180 if (!nameparam
.empty())
181 cell
->parameters
[RTLIL::escape_id(nameparam
)] = RTLIL::Const(stringf("%s[%d]", RTLIL::id2cstr(wire
->name
), i
));
182 cell
->attributes
["\\keep"] = RTLIL::Const(1);
187 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, RTLIL::escape_id(celltype
));
188 cell
->setPort(RTLIL::escape_id(portname
), RTLIL::SigSpec(wire
));
189 if (!portname2
.empty())
190 cell
->setPort(RTLIL::escape_id(portname2
), RTLIL::SigSpec(new_wire
));
191 if (!widthparam
.empty())
192 cell
->parameters
[RTLIL::escape_id(widthparam
)] = RTLIL::Const(wire
->width
);
193 if (!nameparam
.empty())
194 cell
->parameters
[RTLIL::escape_id(nameparam
)] = RTLIL::Const(RTLIL::id2cstr(wire
->name
));
195 cell
->attributes
["\\keep"] = RTLIL::Const(1);
199 wire
->port_input
= false;
200 wire
->port_output
= false;
203 module
->fixup_ports();