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/ast/ast.h"
25 std::map
<std::string
, RTLIL::Design
*> saved_designs
;
26 std::vector
<RTLIL::Design
*> pushed_designs
;
28 struct DesignPass
: public Pass
{
29 DesignPass() : Pass("design", "save, restore and reset current design") { }
30 ~DesignPass() YS_OVERRIDE
{
31 for (auto &it
: saved_designs
)
33 saved_designs
.clear();
34 for (auto &it
: pushed_designs
)
36 pushed_designs
.clear();
38 void help() YS_OVERRIDE
40 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
42 log(" design -reset\n");
44 log("Clear the current design.\n");
47 log(" design -save <name>\n");
49 log("Save the current design under the given name.\n");
52 log(" design -stash <name>\n");
54 log("Save the current design under the given name and then clear the current design.\n");
57 log(" design -push\n");
59 log("Push the current design to the stack and then clear the current design.\n");
62 log(" design -pop\n");
64 log("Reset the current design and pop the last design from the stack.\n");
67 log(" design -load <name>\n");
69 log("Reset the current design and load the design previously saved under the given\n");
73 log(" design -copy-from <name> [-as <new_mod_name>] <selection>\n");
75 log("Copy modules from the specified design into the current one. The selection is\n");
76 log("evaluated in the other design.\n");
79 log(" design -copy-to <name> [-as <new_mod_name>] [selection]\n");
81 log("Copy modules from the current design into the specified one.\n");
84 log(" design -import <name> [-as <new_top_name>] [selection]\n");
86 log("Import the specified design into the current design. The source design must\n");
87 log("either have a selected top module or the selection must contain exactly one\n");
88 log("module that is then used as top module for this command.\n");
91 log(" design -reset-vlog\n");
93 log("The Verilog front-end remembers defined macros and top-level declarations\n");
94 log("between calls to 'read_verilog'. This command resets this memory.\n");
97 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
99 bool got_mode
= false;
100 bool reset_mode
= false;
101 bool reset_vlog_mode
= false;
102 bool push_mode
= false;
103 bool pop_mode
= false;
104 bool import_mode
= false;
105 RTLIL::Design
*copy_from_design
= NULL
, *copy_to_design
= NULL
;
106 std::string save_name
, load_name
, as_name
;
107 std::vector
<RTLIL::Module
*> copy_src_modules
;
110 for (argidx
= 1; argidx
< args
.size(); argidx
++)
112 std::string arg
= args
[argidx
];
113 if (!got_mode
&& args
[argidx
] == "-reset") {
118 if (!got_mode
&& args
[argidx
] == "-reset-vlog") {
120 reset_vlog_mode
= true;
123 if (!got_mode
&& args
[argidx
] == "-push") {
128 if (!got_mode
&& args
[argidx
] == "-pop") {
133 if (!got_mode
&& args
[argidx
] == "-save" && argidx
+1 < args
.size()) {
135 save_name
= args
[++argidx
];
138 if (!got_mode
&& args
[argidx
] == "-stash" && argidx
+1 < args
.size()) {
140 save_name
= args
[++argidx
];
144 if (!got_mode
&& args
[argidx
] == "-load" && argidx
+1 < args
.size()) {
146 load_name
= args
[++argidx
];
147 if (saved_designs
.count(load_name
) == 0)
148 log_cmd_error("No saved design '%s' found!\n", load_name
.c_str());
151 if (!got_mode
&& args
[argidx
] == "-copy-from" && argidx
+1 < args
.size()) {
153 if (saved_designs
.count(args
[++argidx
]) == 0)
154 log_cmd_error("No saved design '%s' found!\n", args
[argidx
].c_str());
155 copy_from_design
= saved_designs
.at(args
[argidx
]);
156 copy_to_design
= design
;
159 if (!got_mode
&& args
[argidx
] == "-copy-to" && argidx
+1 < args
.size()) {
161 if (saved_designs
.count(args
[++argidx
]) == 0)
162 saved_designs
[args
[argidx
]] = new RTLIL::Design
;
163 copy_to_design
= saved_designs
.at(args
[argidx
]);
164 copy_from_design
= design
;
167 if (!got_mode
&& args
[argidx
] == "-import" && 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
;
174 as_name
= args
[argidx
];
177 if (copy_from_design
!= NULL
&& args
[argidx
] == "-as" && argidx
+1 < args
.size()) {
178 as_name
= args
[++argidx
];
184 if (copy_from_design
!= NULL
)
186 if (copy_from_design
!= design
&& argidx
== args
.size() && !import_mode
)
187 cmd_error(args
, argidx
, "Missing selection.");
189 RTLIL::Selection sel
;
190 if (argidx
!= args
.size()) {
191 handle_extra_select_args(this, args
, argidx
, args
.size(), copy_from_design
);
192 sel
= copy_from_design
->selection_stack
.back();
193 copy_from_design
->selection_stack
.pop_back();
194 argidx
= args
.size();
197 for (auto &it
: copy_from_design
->modules_
) {
198 if (sel
.selected_whole_module(it
.first
)) {
199 copy_src_modules
.push_back(it
.second
);
202 if (sel
.selected_module(it
.first
))
203 log_cmd_error("Module %s is only partly selected.\n", RTLIL::id2cstr(it
.first
));
207 for (auto module
: copy_src_modules
)
209 if (module
->get_bool_attribute("\\top")) {
210 copy_src_modules
.clear();
211 copy_src_modules
.push_back(module
);
218 extra_args(args
, argidx
, design
, false);
221 cmd_error(args
, argidx
, "Missing mode argument.");
223 if (pop_mode
&& pushed_designs
.empty())
224 log_cmd_error("No pushed designs.\n");
228 std::string prefix
= RTLIL::escape_id(as_name
);
231 dict
<IdString
, IdString
> done
;
233 if (copy_to_design
->modules_
.count(prefix
))
234 delete copy_to_design
->modules_
.at(prefix
);
236 if (GetSize(copy_src_modules
) != 1)
237 log_cmd_error("No top module found in source design.\n");
239 for (auto mod
: copy_src_modules
)
241 log("Importing %s as %s.\n", log_id(mod
), log_id(prefix
));
243 copy_to_design
->modules_
[prefix
] = mod
->clone();
244 copy_to_design
->modules_
[prefix
]->name
= prefix
;
245 copy_to_design
->modules_
[prefix
]->design
= copy_to_design
;
246 copy_to_design
->modules_
[prefix
]->attributes
.erase("\\top");
248 queue
.insert(copy_to_design
->modules_
[prefix
]);
249 done
[mod
->name
] = prefix
;
252 while (!queue
.empty())
254 pool
<Module
*> old_queue
;
255 old_queue
.swap(queue
);
257 for (auto mod
: old_queue
)
258 for (auto cell
: mod
->cells())
260 Module
*fmod
= copy_from_design
->module(cell
->type
);
265 if (done
.count(cell
->type
) == 0)
267 std::string trg_name
= prefix
+ "." + (cell
->type
.c_str() + (*cell
->type
.c_str() == '\\'));
269 log("Importing %s as %s.\n", log_id(fmod
), log_id(trg_name
));
271 if (copy_to_design
->modules_
.count(trg_name
))
272 delete copy_to_design
->modules_
.at(trg_name
);
274 copy_to_design
->modules_
[trg_name
] = fmod
->clone();
275 copy_to_design
->modules_
[trg_name
]->name
= trg_name
;
276 copy_to_design
->modules_
[trg_name
]->design
= copy_to_design
;
277 copy_to_design
->modules_
[trg_name
]->attributes
.erase("\\top");
279 queue
.insert(copy_to_design
->modules_
[trg_name
]);
280 done
[cell
->type
] = trg_name
;
283 cell
->type
= done
.at(cell
->type
);
288 if (copy_to_design
!= NULL
)
290 if (!as_name
.empty() && copy_src_modules
.size() > 1)
291 log_cmd_error("Only one module can be selected in combination with -as.\n");
293 for (auto mod
: copy_src_modules
)
295 std::string trg_name
= as_name
.empty() ? mod
->name
.str() : RTLIL::escape_id(as_name
);
297 if (copy_to_design
->modules_
.count(trg_name
))
298 delete copy_to_design
->modules_
.at(trg_name
);
300 copy_to_design
->modules_
[trg_name
] = mod
->clone();
301 copy_to_design
->modules_
[trg_name
]->name
= trg_name
;
302 copy_to_design
->modules_
[trg_name
]->design
= copy_to_design
;
306 if (!save_name
.empty() || push_mode
)
308 RTLIL::Design
*design_copy
= new RTLIL::Design
;
310 for (auto &it
: design
->modules_
)
311 design_copy
->add(it
.second
->clone());
313 design_copy
->selection_stack
= design
->selection_stack
;
314 design_copy
->selection_vars
= design
->selection_vars
;
315 design_copy
->selected_active_module
= design
->selected_active_module
;
317 if (saved_designs
.count(save_name
))
318 delete saved_designs
.at(save_name
);
321 pushed_designs
.push_back(design_copy
);
323 saved_designs
[save_name
] = design_copy
;
326 if (reset_mode
|| !load_name
.empty() || push_mode
|| pop_mode
)
328 for (auto &it
: design
->modules_
)
330 design
->modules_
.clear();
332 design
->selection_stack
.clear();
333 design
->selection_vars
.clear();
334 design
->selected_active_module
.clear();
336 design
->selection_stack
.push_back(RTLIL::Selection());
339 if (reset_mode
|| reset_vlog_mode
|| !load_name
.empty() || push_mode
|| pop_mode
)
341 for (auto node
: design
->verilog_packages
)
343 design
->verilog_packages
.clear();
345 for (auto node
: design
->verilog_globals
)
347 design
->verilog_globals
.clear();
349 design
->verilog_defines
.clear();
352 if (!load_name
.empty() || pop_mode
)
354 RTLIL::Design
*saved_design
= pop_mode
? pushed_designs
.back() : saved_designs
.at(load_name
);
356 for (auto &it
: saved_design
->modules_
)
357 design
->add(it
.second
->clone());
359 design
->selection_stack
= saved_design
->selection_stack
;
360 design
->selection_vars
= saved_design
->selection_vars
;
361 design
->selected_active_module
= saved_design
->selected_active_module
;
365 pushed_designs
.pop_back();