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 static void rename_in_module(RTLIL::Module
*module
, std::string from_name
, std::string to_name
, bool flag_output
)
29 from_name
= RTLIL::escape_id(from_name
);
30 to_name
= RTLIL::escape_id(to_name
);
32 if (module
->count_id(to_name
))
33 log_cmd_error("There is already an object `%s' in module `%s'.\n", to_name
.c_str(), module
->name
.c_str());
35 RTLIL::Wire
*wire_to_rename
= module
->wire(from_name
);
36 RTLIL::Cell
*cell_to_rename
= module
->cell(from_name
);
38 if (wire_to_rename
!= nullptr) {
39 log("Renaming wire %s to %s in module %s.\n", log_id(wire_to_rename
), log_id(to_name
), log_id(module
));
40 module
->rename(wire_to_rename
, to_name
);
41 if (wire_to_rename
->port_id
|| flag_output
) {
43 wire_to_rename
->port_output
= true;
44 module
->fixup_ports();
49 if (cell_to_rename
!= nullptr) {
51 log_cmd_error("Called with -output but the specified object is a cell.\n");
52 log("Renaming cell %s to %s in module %s.\n", log_id(cell_to_rename
), log_id(to_name
), log_id(module
));
53 module
->rename(cell_to_rename
, to_name
);
57 log_cmd_error("Object `%s' not found!\n", from_name
.c_str());
60 static std::string
derive_name_from_src(const std::string
&src
, int counter
)
62 std::string src_base
= src
.substr(0, src
.find('|'));
64 return stringf("$%d", counter
);
66 return stringf("\\%s$%d", src_base
.c_str(), counter
);
69 static IdString
derive_name_from_cell_output_wire(const RTLIL::Cell
*cell
)
72 const SigSpec
*output
= nullptr;
74 for (auto &connection
: cell
->connections()) {
75 if (cell
->output(connection
.first
)) {
76 output
= &connection
.second
;
81 if (num_outputs
!= 1) // Skip cells thad drive multiple outputs
84 std::string name
= "";
85 for (auto &chunk
: output
->chunks()) {
86 // Skip cells that drive privately named wires
87 if (!chunk
.wire
|| chunk
.wire
->name
.str()[0] == '$')
93 name
+= chunk
.wire
->name
.str();
94 if (chunk
.wire
->width
!= chunk
.width
) {
97 name
+= std::to_string(chunk
.offset
+ chunk
.width
) + ":";
98 name
+= std::to_string(chunk
.offset
) + "]";
102 return name
+ cell
->type
.str();
105 struct RenamePass
: public Pass
{
106 RenamePass() : Pass("rename", "rename object in the design") { }
107 void help() YS_OVERRIDE
109 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
111 log(" rename old_name new_name\n");
113 log("Rename the specified object. Note that selection patterns are not supported\n");
114 log("by this command.\n");
118 log(" rename -output old_name new_name\n");
120 log("Like above, but also make the wire an output. This will fail if the object is\n");
121 log("not a wire.\n");
124 log(" rename -src [selection]\n");
126 log("Assign names auto-generated from the src attribute to all selected wires and\n");
127 log("cells with private names.\n");
130 log(" rename -wire [selection]\n");
132 log("Assign auto-generated names based on the wires they drive to all selected\n");
133 log("cells with private names. Ignores cells driving privatly named wires.\n");
136 log(" rename -enumerate [-pattern <pattern>] [selection]\n");
138 log("Assign short auto-generated names to all selected wires and cells with private\n");
139 log("names. The -pattern option can be used to set the pattern for the new names.\n");
140 log("The character %% in the pattern is replaced with a integer number. The default\n");
141 log("pattern is '_%%_'.\n");
144 log(" rename -hide [selection]\n");
146 log("Assign private names (the ones with $-prefix) to all selected wires and cells\n");
147 log("with public names. This ignores all selected ports.\n");
150 log(" rename -top new_name\n");
152 log("Rename top module.\n");
155 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
157 std::string pattern_prefix
= "_", pattern_suffix
= "_";
158 bool flag_src
= false;
159 bool flag_wire
= false;
160 bool flag_enumerate
= false;
161 bool flag_hide
= false;
162 bool flag_top
= false;
163 bool flag_output
= false;
164 bool got_mode
= false;
167 for (argidx
= 1; argidx
< args
.size(); argidx
++)
169 std::string arg
= args
[argidx
];
170 if (arg
== "-src" && !got_mode
) {
175 if (arg
== "-output" && !got_mode
) {
180 if (arg
== "-wire" && !got_mode
) {
185 if (arg
== "-enumerate" && !got_mode
) {
186 flag_enumerate
= true;
190 if (arg
== "-hide" && !got_mode
) {
195 if (arg
== "-top" && !got_mode
) {
200 if (arg
== "-pattern" && argidx
+1 < args
.size() && args
[argidx
+1].find('%') != std::string::npos
) {
201 int pos
= args
[++argidx
].find('%');
202 pattern_prefix
= args
[argidx
].substr(0, pos
);
203 pattern_suffix
= args
[argidx
].substr(pos
+1);
211 extra_args(args
, argidx
, design
);
213 for (auto module
: design
->selected_modules())
216 dict
<RTLIL::Wire
*, IdString
> new_wire_names
;
217 dict
<RTLIL::Cell
*, IdString
> new_cell_names
;
219 for (auto wire
: module
->selected_wires())
220 if (wire
->name
[0] == '$')
221 new_wire_names
.emplace(wire
, derive_name_from_src(wire
->get_src_attribute(), counter
++));
223 for (auto cell
: module
->selected_cells())
224 if (cell
->name
[0] == '$')
225 new_cell_names
.emplace(cell
, derive_name_from_src(cell
->get_src_attribute(), counter
++));
227 for (auto &it
: new_wire_names
)
228 module
->rename(it
.first
, it
.second
);
230 for (auto &it
: new_cell_names
)
231 module
->rename(it
.first
, it
.second
);
237 extra_args(args
, argidx
, design
);
239 for (auto module
: design
->selected_modules()) {
240 dict
<RTLIL::Cell
*, IdString
> new_cell_names
;
241 for (auto cell
: module
->selected_cells())
242 if (cell
->name
[0] == '$')
243 new_cell_names
[cell
] = derive_name_from_cell_output_wire(cell
);
244 for (auto &it
: new_cell_names
)
245 module
->rename(it
.first
, it
.second
);
251 extra_args(args
, argidx
, design
);
253 for (auto module
: design
->selected_modules())
256 dict
<RTLIL::Wire
*, IdString
> new_wire_names
;
257 dict
<RTLIL::Cell
*, IdString
> new_cell_names
;
259 for (auto wire
: module
->selected_wires())
260 if (wire
->name
[0] == '$') {
262 do buf
= stringf("\\%s%d%s", pattern_prefix
.c_str(), counter
++, pattern_suffix
.c_str());
263 while (module
->wire(buf
) != nullptr);
264 new_wire_names
[wire
] = buf
;
267 for (auto cell
: module
->selected_cells())
268 if (cell
->name
[0] == '$') {
270 do buf
= stringf("\\%s%d%s", pattern_prefix
.c_str(), counter
++, pattern_suffix
.c_str());
271 while (module
->cell(buf
) != nullptr);
272 new_cell_names
[cell
] = buf
;
275 for (auto &it
: new_wire_names
)
276 module
->rename(it
.first
, it
.second
);
278 for (auto &it
: new_cell_names
)
279 module
->rename(it
.first
, it
.second
);
285 extra_args(args
, argidx
, design
);
287 for (auto module
: design
->selected_modules())
289 dict
<RTLIL::Wire
*, IdString
> new_wire_names
;
290 dict
<RTLIL::Cell
*, IdString
> new_cell_names
;
292 for (auto wire
: module
->selected_wires())
293 if (wire
->name
[0] == '\\' && wire
->port_id
== 0)
294 new_wire_names
[wire
] = NEW_ID
;
296 for (auto cell
: module
->selected_cells())
297 if (cell
->name
[0] == '\\')
298 new_cell_names
[cell
] = NEW_ID
;
300 for (auto &it
: new_wire_names
)
301 module
->rename(it
.first
, it
.second
);
303 for (auto &it
: new_cell_names
)
304 module
->rename(it
.first
, it
.second
);
310 if (argidx
+1 != args
.size())
311 log_cmd_error("Invalid number of arguments!\n");
313 IdString new_name
= RTLIL::escape_id(args
[argidx
]);
314 RTLIL::Module
*module
= design
->top_module();
316 if (module
== nullptr)
317 log_cmd_error("No top module found!\n");
319 log("Renaming module %s to %s.\n", log_id(module
), log_id(new_name
));
320 design
->rename(module
, new_name
);
324 if (argidx
+2 != args
.size())
325 log_cmd_error("Invalid number of arguments!\n");
327 std::string from_name
= args
[argidx
++];
328 std::string to_name
= args
[argidx
++];
330 if (!design
->selected_active_module
.empty())
332 if (design
->module(design
->selected_active_module
) != nullptr)
333 rename_in_module(design
->module(design
->selected_active_module
), from_name
, to_name
, flag_output
);
338 log_cmd_error("Mode -output requires that there is an active module selected.\n");
340 RTLIL::Module
*module_to_rename
= nullptr;
341 for (auto module
: design
->modules())
342 if (module
->name
== from_name
|| RTLIL::unescape_id(module
->name
) == from_name
) {
343 module_to_rename
= module
;
347 if (module_to_rename
!= nullptr) {
348 to_name
= RTLIL::escape_id(to_name
);
349 log("Renaming module %s to %s.\n", module_to_rename
->name
.c_str(), to_name
.c_str());
350 design
->rename(module_to_rename
, to_name
);
352 log_cmd_error("Object `%s' not found!\n", from_name
.c_str());
358 PRIVATE_NAMESPACE_END