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"
25 PRIVATE_NAMESPACE_BEGIN
27 void split_portname_pair(std::string
&port1
, std::string
&port2
)
29 size_t pos
= port1
.find_first_of(':');
30 if (pos
!= std::string::npos
) {
31 port2
= port1
.substr(pos
+1);
32 port1
= port1
.substr(0, pos
);
36 struct IopadmapPass
: public Pass
{
37 IopadmapPass() : Pass("iopadmap", "technology mapping of i/o pads (or buffers)") { }
41 log(" iopadmap [options] [selection]\n");
43 log("Map module inputs/outputs to PAD cells from a library. This pass\n");
44 log("can only map to very simple PAD cells. Use 'techmap' to further map\n");
45 log("the resulting cells to more sophisticated PAD cells.\n");
47 log(" -inpad <celltype> <portname>[:<portname>]\n");
48 log(" Map module input ports to the given cell type with the\n");
49 log(" given output port name. if a 2nd portname is given, the\n");
50 log(" signal is passed through the pad call, using the 2nd\n");
51 log(" portname as input.\n");
53 log(" -outpad <celltype> <portname>[:<portname>]\n");
54 log(" -inoutpad <celltype> <portname>[:<portname>]\n");
55 log(" Similar to -inpad, but for output and inout ports.\n");
57 log(" -widthparam <param_name>\n");
58 log(" Use the specified parameter name to set the port width.\n");
60 log(" -nameparam <param_name>\n");
61 log(" Use the specified parameter to set the port name.\n");
64 log(" create individual bit-wide buffers even for ports that\n");
65 log(" are wider. (the default behavior is to create word-wide\n");
66 log(" buffers using -widthparam to set the word size on the cell.)\n");
69 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
71 log_header("Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n");
73 std::string inpad_celltype
, inpad_portname
, inpad_portname2
;
74 std::string outpad_celltype
, outpad_portname
, outpad_portname2
;
75 std::string inoutpad_celltype
, inoutpad_portname
, inoutpad_portname2
;
76 std::string widthparam
, nameparam
;
77 bool flag_bits
= false;
80 for (argidx
= 1; argidx
< args
.size(); argidx
++)
82 std::string arg
= args
[argidx
];
83 if (arg
== "-inpad" && argidx
+2 < args
.size()) {
84 inpad_celltype
= args
[++argidx
];
85 inpad_portname
= args
[++argidx
];
86 split_portname_pair(inpad_portname
, inpad_portname2
);
89 if (arg
== "-outpad" && argidx
+2 < args
.size()) {
90 outpad_celltype
= args
[++argidx
];
91 outpad_portname
= args
[++argidx
];
92 split_portname_pair(outpad_portname
, outpad_portname2
);
95 if (arg
== "-inoutpad" && argidx
+2 < args
.size()) {
96 inoutpad_celltype
= args
[++argidx
];
97 inoutpad_portname
= args
[++argidx
];
98 split_portname_pair(inoutpad_portname
, inoutpad_portname2
);
101 if (arg
== "-widthparam" && argidx
+1 < args
.size()) {
102 widthparam
= args
[++argidx
];
105 if (arg
== "-nameparam" && argidx
+1 < args
.size()) {
106 nameparam
= args
[++argidx
];
109 if (arg
== "-bits") {
115 extra_args(args
, argidx
, design
);
117 for (auto module
: design
->selected_modules())
119 for (auto wire
: module
->selected_wires())
124 std::string celltype
, portname
, portname2
;
126 if (wire
->port_input
&& !wire
->port_output
) {
127 if (inpad_celltype
.empty()) {
128 log("Don't map input port %s.%s: Missing option -inpad.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
));
131 celltype
= inpad_celltype
;
132 portname
= inpad_portname
;
133 portname2
= inpad_portname2
;
135 if (!wire
->port_input
&& wire
->port_output
) {
136 if (outpad_celltype
.empty()) {
137 log("Don't map output port %s.%s: Missing option -outpad.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
));
140 celltype
= outpad_celltype
;
141 portname
= outpad_portname
;
142 portname2
= outpad_portname2
;
144 if (wire
->port_input
&& wire
->port_output
) {
145 if (inoutpad_celltype
.empty()) {
146 log("Don't map inout port %s.%s: Missing option -inoutpad.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
));
149 celltype
= inoutpad_celltype
;
150 portname
= inoutpad_portname
;
151 portname2
= inoutpad_portname2
;
155 if (!flag_bits
&& wire
->width
!= 1 && widthparam
.empty()) {
156 log("Don't map multi-bit port %s.%s: Missing option -widthparam or -bits.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
));
160 log("Mapping port %s.%s using %s.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
), celltype
.c_str());
162 RTLIL::Wire
*new_wire
= NULL
;
163 if (!portname2
.empty()) {
164 new_wire
= module
->addWire(NEW_ID
, wire
);
165 module
->swap_names(new_wire
, wire
);
170 for (int i
= 0; i
< wire
->width
; i
++)
172 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, RTLIL::escape_id(celltype
));
173 cell
->setPort(RTLIL::escape_id(portname
), RTLIL::SigSpec(wire
, i
));
174 if (!portname2
.empty())
175 cell
->setPort(RTLIL::escape_id(portname2
), RTLIL::SigSpec(new_wire
, i
));
176 if (!widthparam
.empty())
177 cell
->parameters
[RTLIL::escape_id(widthparam
)] = RTLIL::Const(1);
178 if (!nameparam
.empty())
179 cell
->parameters
[RTLIL::escape_id(nameparam
)] = RTLIL::Const(stringf("%s[%d]", RTLIL::id2cstr(wire
->name
), i
));
180 cell
->attributes
["\\keep"] = RTLIL::Const(1);
185 RTLIL::Cell
*cell
= module
->addCell(NEW_ID
, RTLIL::escape_id(celltype
));
186 cell
->setPort(RTLIL::escape_id(portname
), RTLIL::SigSpec(wire
));
187 if (!portname2
.empty())
188 cell
->setPort(RTLIL::escape_id(portname2
), RTLIL::SigSpec(new_wire
));
189 if (!widthparam
.empty())
190 cell
->parameters
[RTLIL::escape_id(widthparam
)] = RTLIL::Const(wire
->width
);
191 if (!nameparam
.empty())
192 cell
->parameters
[RTLIL::escape_id(nameparam
)] = RTLIL::Const(RTLIL::id2cstr(wire
->name
));
193 cell
->attributes
["\\keep"] = RTLIL::Const(1);
197 wire
->port_input
= false;
198 wire
->port_output
= false;
201 module
->fixup_ports();
206 PRIVATE_NAMESPACE_END