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/yosys.h"
21 #include "frontends/verilog/preproc.h"
22 #include "frontends/ast/ast.h"
26 std::map
<std::string
, RTLIL::Design
*> saved_designs
;
27 std::vector
<RTLIL::Design
*> pushed_designs
;
29 struct DesignPass
: public Pass
{
30 DesignPass() : Pass("design", "save, restore and reset current design") { }
31 ~DesignPass() YS_OVERRIDE
{
32 for (auto &it
: saved_designs
)
34 saved_designs
.clear();
35 for (auto &it
: pushed_designs
)
37 pushed_designs
.clear();
39 void help() YS_OVERRIDE
41 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
43 log(" design -reset\n");
45 log("Clear the current design.\n");
48 log(" design -save <name>\n");
50 log("Save the current design under the given name.\n");
53 log(" design -stash <name>\n");
55 log("Save the current design under the given name and then clear the current design.\n");
58 log(" design -push\n");
60 log("Push the current design to the stack and then clear the current design.\n");
63 log(" design -push-copy\n");
65 log("Push the current design to the stack without clearing the current design.\n");
68 log(" design -pop\n");
70 log("Reset the current design and pop the last design from the stack.\n");
73 log(" design -load <name>\n");
75 log("Reset the current design and load the design previously saved under the given\n");
79 log(" design -copy-from <name> [-as <new_mod_name>] <selection>\n");
81 log("Copy modules from the specified design into the current one. The selection is\n");
82 log("evaluated in the other design.\n");
85 log(" design -copy-to <name> [-as <new_mod_name>] [selection]\n");
87 log("Copy modules from the current design into the specified one.\n");
90 log(" design -import <name> [-as <new_top_name>] [selection]\n");
92 log("Import the specified design into the current design. The source design must\n");
93 log("either have a selected top module or the selection must contain exactly one\n");
94 log("module that is then used as top module for this command.\n");
97 log(" design -reset-vlog\n");
99 log("The Verilog front-end remembers defined macros and top-level declarations\n");
100 log("between calls to 'read_verilog'. This command resets this memory.\n");
102 log(" design -delete <name>\n");
104 log("Delete the design previously saved under the given name.\n");
108 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
110 bool got_mode
= false;
111 bool reset_mode
= false;
112 bool reset_vlog_mode
= false;
113 bool push_mode
= false;
114 bool push_copy_mode
= false;
115 bool pop_mode
= false;
116 bool import_mode
= false;
117 RTLIL::Design
*copy_from_design
= NULL
, *copy_to_design
= NULL
;
118 std::string save_name
, load_name
, as_name
, delete_name
;
119 std::vector
<RTLIL::Module
*> copy_src_modules
;
122 for (argidx
= 1; argidx
< args
.size(); argidx
++)
124 std::string arg
= args
[argidx
];
125 if (!got_mode
&& args
[argidx
] == "-reset") {
130 if (!got_mode
&& args
[argidx
] == "-reset-vlog") {
132 reset_vlog_mode
= true;
135 if (!got_mode
&& args
[argidx
] == "-push") {
140 if (!got_mode
&& args
[argidx
] == "-push-copy") {
142 push_copy_mode
= true;
145 if (!got_mode
&& args
[argidx
] == "-pop") {
150 if (!got_mode
&& args
[argidx
] == "-save" && argidx
+1 < args
.size()) {
152 save_name
= args
[++argidx
];
155 if (!got_mode
&& args
[argidx
] == "-stash" && argidx
+1 < args
.size()) {
157 save_name
= args
[++argidx
];
161 if (!got_mode
&& args
[argidx
] == "-load" && argidx
+1 < args
.size()) {
163 load_name
= args
[++argidx
];
164 if (saved_designs
.count(load_name
) == 0)
165 log_cmd_error("No saved design '%s' found!\n", load_name
.c_str());
168 if (!got_mode
&& args
[argidx
] == "-copy-from" && argidx
+1 < args
.size()) {
170 if (saved_designs
.count(args
[++argidx
]) == 0)
171 log_cmd_error("No saved design '%s' found!\n", args
[argidx
].c_str());
172 copy_from_design
= saved_designs
.at(args
[argidx
]);
173 copy_to_design
= design
;
176 if (!got_mode
&& args
[argidx
] == "-copy-to" && argidx
+1 < args
.size()) {
178 if (saved_designs
.count(args
[++argidx
]) == 0)
179 saved_designs
[args
[argidx
]] = new RTLIL::Design
;
180 copy_to_design
= saved_designs
.at(args
[argidx
]);
181 copy_from_design
= design
;
184 if (!got_mode
&& args
[argidx
] == "-import" && argidx
+1 < args
.size()) {
187 if (saved_designs
.count(args
[++argidx
]) == 0)
188 log_cmd_error("No saved design '%s' found!\n", args
[argidx
].c_str());
189 copy_from_design
= saved_designs
.at(args
[argidx
]);
190 copy_to_design
= design
;
191 as_name
= args
[argidx
];
194 if (copy_from_design
!= NULL
&& args
[argidx
] == "-as" && argidx
+1 < args
.size()) {
195 as_name
= args
[++argidx
];
198 if (!got_mode
&& args
[argidx
] == "-delete" && argidx
+1 < args
.size()) {
200 delete_name
= args
[++argidx
];
201 if (saved_designs
.count(delete_name
) == 0)
202 log_cmd_error("No saved design '%s' found!\n", delete_name
.c_str());
208 if (copy_from_design
!= NULL
)
210 if (copy_from_design
!= design
&& argidx
== args
.size() && !import_mode
)
211 cmd_error(args
, argidx
, "Missing selection.");
213 RTLIL::Selection sel
;
214 if (argidx
!= args
.size()) {
215 handle_extra_select_args(this, args
, argidx
, args
.size(), copy_from_design
);
216 sel
= copy_from_design
->selection_stack
.back();
217 copy_from_design
->selection_stack
.pop_back();
218 argidx
= args
.size();
221 for (auto mod
: copy_from_design
->modules()) {
222 if (sel
.selected_whole_module(mod
->name
)) {
223 copy_src_modules
.push_back(mod
);
226 if (sel
.selected_module(mod
->name
))
227 log_cmd_error("Module %s is only partly selected.\n", log_id(mod
->name
));
231 std::vector
<RTLIL::Module
*> candidates
;
232 for (auto module
: copy_src_modules
)
234 if (module
->get_bool_attribute(ID::top
)) {
236 candidates
.push_back(module
);
239 if (!module
->get_blackbox_attribute())
240 candidates
.push_back(module
);
243 if (GetSize(candidates
) == 1)
244 copy_src_modules
= std::move(candidates
);
248 extra_args(args
, argidx
, design
, false);
251 cmd_error(args
, argidx
, "Missing mode argument.");
253 if (pop_mode
&& pushed_designs
.empty())
254 log_cmd_error("No pushed designs.\n");
258 std::string prefix
= RTLIL::escape_id(as_name
);
261 dict
<IdString
, IdString
> done
;
263 if (copy_to_design
->module(prefix
) != nullptr)
264 copy_to_design
->remove(copy_to_design
->module(prefix
));
266 if (GetSize(copy_src_modules
) != 1)
267 log_cmd_error("No top module found in source design.\n");
269 for (auto mod
: copy_src_modules
)
271 log("Importing %s as %s.\n", log_id(mod
), log_id(prefix
));
273 RTLIL::Module
*t
= mod
->clone();
275 t
->design
= copy_to_design
;
276 t
->attributes
.erase(ID::top
);
277 copy_to_design
->add(t
);
280 done
[mod
->name
] = prefix
;
283 while (!queue
.empty())
285 pool
<Module
*> old_queue
;
286 old_queue
.swap(queue
);
288 for (auto mod
: old_queue
)
289 for (auto cell
: mod
->cells())
291 Module
*fmod
= copy_from_design
->module(cell
->type
);
296 if (done
.count(cell
->type
) == 0)
298 std::string trg_name
= prefix
+ "." + (cell
->type
.c_str() + (*cell
->type
.c_str() == '\\'));
300 log("Importing %s as %s.\n", log_id(fmod
), log_id(trg_name
));
302 if (copy_to_design
->module(trg_name
) != nullptr)
303 copy_to_design
->remove(copy_to_design
->module(trg_name
));
305 RTLIL::Module
*t
= fmod
->clone();
307 t
->design
= copy_to_design
;
308 t
->attributes
.erase(ID::top
);
309 copy_to_design
->add(t
);
312 done
[cell
->type
] = trg_name
;
315 cell
->type
= done
.at(cell
->type
);
320 if (copy_to_design
!= NULL
)
322 if (!as_name
.empty() && copy_src_modules
.size() > 1)
323 log_cmd_error("Only one module can be selected in combination with -as.\n");
325 for (auto mod
: copy_src_modules
)
327 std::string trg_name
= as_name
.empty() ? mod
->name
.str() : RTLIL::escape_id(as_name
);
329 if (copy_to_design
->module(trg_name
) != nullptr)
330 copy_to_design
->remove(copy_to_design
->module(trg_name
));
332 RTLIL::Module
*t
= mod
->clone();
334 t
->design
= copy_to_design
;
335 copy_to_design
->add(t
);
339 if (!save_name
.empty() || push_mode
|| push_copy_mode
)
341 RTLIL::Design
*design_copy
= new RTLIL::Design
;
343 for (auto mod
: design
->modules())
344 design_copy
->add(mod
->clone());
346 design_copy
->selection_stack
= design
->selection_stack
;
347 design_copy
->selection_vars
= design
->selection_vars
;
348 design_copy
->selected_active_module
= design
->selected_active_module
;
350 if (saved_designs
.count(save_name
))
351 delete saved_designs
.at(save_name
);
353 if (push_mode
|| push_copy_mode
)
354 pushed_designs
.push_back(design_copy
);
356 saved_designs
[save_name
] = design_copy
;
359 if (reset_mode
|| !load_name
.empty() || push_mode
|| pop_mode
)
361 for (auto mod
: design
->modules().to_vector())
364 design
->selection_stack
.clear();
365 design
->selection_vars
.clear();
366 design
->selected_active_module
.clear();
368 design
->selection_stack
.push_back(RTLIL::Selection());
371 if (reset_mode
|| reset_vlog_mode
|| !load_name
.empty() || push_mode
|| pop_mode
)
373 for (auto node
: design
->verilog_packages
)
375 design
->verilog_packages
.clear();
377 for (auto node
: design
->verilog_globals
)
379 design
->verilog_globals
.clear();
381 design
->verilog_defines
->clear();
384 if (!load_name
.empty() || pop_mode
)
386 RTLIL::Design
*saved_design
= pop_mode
? pushed_designs
.back() : saved_designs
.at(load_name
);
388 for (auto mod
: saved_design
->modules())
389 design
->add(mod
->clone());
391 design
->selection_stack
= saved_design
->selection_stack
;
392 design
->selection_vars
= saved_design
->selection_vars
;
393 design
->selected_active_module
= saved_design
->selected_active_module
;
397 pushed_designs
.pop_back();
401 if (!delete_name
.empty())
403 auto it
= saved_designs
.find(delete_name
);
404 log_assert(it
!= saved_designs
.end());
406 saved_designs
.erase(it
);