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 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
63 log_header("Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n");
65 std::string inpad_celltype
, inpad_portname
, inpad_portname2
;
66 std::string outpad_celltype
, outpad_portname
, outpad_portname2
;
67 std::string inoutpad_celltype
, inoutpad_portname
, inoutpad_portname2
;
68 std::string widthparam
, nameparam
;
71 for (argidx
= 1; argidx
< args
.size(); argidx
++)
73 std::string arg
= args
[argidx
];
74 if (arg
== "-inpad" && argidx
+2 < args
.size()) {
75 inpad_celltype
= args
[++argidx
];
76 inpad_portname
= args
[++argidx
];
77 split_portname_pair(inpad_portname
, inpad_portname2
);
80 if (arg
== "-outpad" && argidx
+2 < args
.size()) {
81 outpad_celltype
= args
[++argidx
];
82 outpad_portname
= args
[++argidx
];
83 split_portname_pair(outpad_portname
, outpad_portname2
);
86 if (arg
== "-inoutpad" && argidx
+2 < args
.size()) {
87 inoutpad_celltype
= args
[++argidx
];
88 inoutpad_portname
= args
[++argidx
];
89 split_portname_pair(inoutpad_portname
, inoutpad_portname2
);
92 if (arg
== "-widthparam" && argidx
+1 < args
.size()) {
93 widthparam
= args
[++argidx
];
96 if (arg
== "-nameparam" && argidx
+1 < args
.size()) {
97 nameparam
= args
[++argidx
];
102 extra_args(args
, argidx
, design
);
104 for (auto &it
: design
->modules
)
106 RTLIL::Module
*module
= it
.second
;
108 if (!design
->selected(module
))
111 for (auto &it2
: module
->wires
)
113 RTLIL::Wire
*wire
= it2
.second
;
115 if (!wire
->port_id
|| !design
->selected(module
, wire
))
118 std::string celltype
, portname
, portname2
;
120 if (wire
->port_input
&& !wire
->port_output
) {
121 if (inpad_celltype
.empty()) {
122 log("Don't map input port %s.%s: Missing option -inpad.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
));
125 celltype
= inpad_celltype
;
126 portname
= inpad_portname
;
127 portname2
= inpad_portname2
;
129 if (!wire
->port_input
&& wire
->port_output
) {
130 if (outpad_celltype
.empty()) {
131 log("Don't map output port %s.%s: Missing option -outpad.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
));
134 celltype
= outpad_celltype
;
135 portname
= outpad_portname
;
136 portname2
= outpad_portname2
;
138 if (wire
->port_input
&& wire
->port_output
) {
139 if (inoutpad_celltype
.empty()) {
140 log("Don't map inout port %s.%s: Missing option -inoutpad.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
));
143 celltype
= inoutpad_celltype
;
144 portname
= inoutpad_portname
;
145 portname2
= inoutpad_portname2
;
149 if (wire
->width
!= 1 && widthparam
.empty()) {
150 log("Don't map multi-bit port %s.%s: Missing option -widthparam.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
));
154 log("Mapping port %s.%s using %s.\n", RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(wire
->name
), celltype
.c_str());
156 RTLIL::Cell
*cell
= new RTLIL::Cell
;
158 cell
->type
= RTLIL::escape_id(celltype
);
159 cell
->connections
[RTLIL::escape_id(portname
)] = RTLIL::SigSpec(wire
);
160 if (!portname2
.empty()) {
161 RTLIL::Wire
*new_wire
= new RTLIL::Wire
;
164 module
->wires
[wire
->name
] = wire
;
165 module
->wires
[new_wire
->name
] = new_wire
;
166 cell
->connections
[RTLIL::escape_id(portname2
)] = RTLIL::SigSpec(new_wire
);
168 if (!widthparam
.empty())
169 cell
->parameters
[RTLIL::escape_id(widthparam
)] = RTLIL::Const(wire
->width
);
170 if (!nameparam
.empty())
171 cell
->parameters
[RTLIL::escape_id(nameparam
)] = RTLIL::Const(RTLIL::id2cstr(wire
->name
));
172 cell
->attributes
["\\keep"] = RTLIL::Const(1);
176 wire
->port_input
= false;
177 wire
->port_output
= false;
180 module
->fixup_ports();