substr() -> compare()
[yosys.git] / passes / cmds / setattr.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
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.
9 *
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.
17 *
18 */
19
20 #include "kernel/register.h"
21 #include "kernel/rtlil.h"
22 #include "kernel/log.h"
23
24 USING_YOSYS_NAMESPACE
25 PRIVATE_NAMESPACE_BEGIN
26
27 struct setunset_t
28 {
29 RTLIL::IdString name;
30 RTLIL::Const value;
31 bool unset;
32
33 setunset_t(std::string unset_name) : name(RTLIL::escape_id(unset_name)), value(), unset(true) { }
34
35 setunset_t(std::string set_name, std::string set_value) : name(RTLIL::escape_id(set_name)), value(), unset(false)
36 {
37 if (set_value.compare(0, 1, "\"") == 0 && set_value.compare(GetSize(set_value)-1, std::string::npos, "\"") == 0) {
38 value = RTLIL::Const(set_value.substr(1, GetSize(set_value)-2));
39 } else {
40 RTLIL::SigSpec sig_value;
41 if (!RTLIL::SigSpec::parse(sig_value, NULL, set_value))
42 log_cmd_error("Can't decode value '%s'!\n", set_value.c_str());
43 value = sig_value.as_const();
44 }
45 }
46 };
47
48 static void do_setunset(dict<RTLIL::IdString, RTLIL::Const> &attrs, const std::vector<setunset_t> &list)
49 {
50 for (auto &item : list)
51 if (item.unset)
52 attrs.erase(item.name);
53 else
54 attrs[item.name] = item.value;
55 }
56
57 struct SetattrPass : public Pass {
58 SetattrPass() : Pass("setattr", "set/unset attributes on objects") { }
59 void help() YS_OVERRIDE
60 {
61 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
62 log("\n");
63 log(" setattr [ -mod ] [ -set name value | -unset name ]... [selection]\n");
64 log("\n");
65 log("Set/unset the given attributes on the selected objects. String values must be\n");
66 log("passed in double quotes (\").\n");
67 log("\n");
68 log("When called with -mod, this command will set and unset attributes on modules\n");
69 log("instead of objects within modules.\n");
70 log("\n");
71 }
72 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
73 {
74 std::vector<setunset_t> setunset_list;
75 bool flag_mod = false;
76
77 size_t argidx;
78 for (argidx = 1; argidx < args.size(); argidx++)
79 {
80 std::string arg = args[argidx];
81 if (arg == "-set" && argidx+2 < args.size()) {
82 string set_key = args[++argidx];
83 string set_val = args[++argidx];
84 setunset_list.push_back(setunset_t(set_key, set_val));
85 continue;
86 }
87 if (arg == "-unset" && argidx+1 < args.size()) {
88 setunset_list.push_back(setunset_t(args[++argidx]));
89 continue;
90 }
91 if (arg == "-mod") {
92 flag_mod = true;
93 continue;
94 }
95 break;
96 }
97 extra_args(args, argidx, design);
98
99 for (auto &mod : design->modules_)
100 {
101 RTLIL::Module *module = mod.second;
102
103 if (flag_mod) {
104 if (design->selected_whole_module(module->name))
105 do_setunset(module->attributes, setunset_list);
106 continue;
107 }
108
109 if (!design->selected(module))
110 continue;
111
112 for (auto &it : module->wires_)
113 if (design->selected(module, it.second))
114 do_setunset(it.second->attributes, setunset_list);
115
116 for (auto &it : module->memories)
117 if (design->selected(module, it.second))
118 do_setunset(it.second->attributes, setunset_list);
119
120 for (auto &it : module->cells_)
121 if (design->selected(module, it.second))
122 do_setunset(it.second->attributes, setunset_list);
123
124 for (auto &it : module->processes)
125 if (design->selected(module, it.second))
126 do_setunset(it.second->attributes, setunset_list);
127 }
128 }
129 } SetattrPass;
130
131 struct WbflipPass : public Pass {
132 WbflipPass() : Pass("wbflip", "flip the whitebox attribute") { }
133 void help() YS_OVERRIDE
134 {
135 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
136 log("\n");
137 log(" wbflip [selection]\n");
138 log("\n");
139 log("Flip the whitebox attribute on selected cells. I.e. if it's set, unset it, and\n");
140 log("vice-versa. Blackbox cells are not effected by this command.\n");
141 log("\n");
142 }
143 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
144 {
145 size_t argidx;
146 for (argidx = 1; argidx < args.size(); argidx++)
147 {
148 std::string arg = args[argidx];
149 // if (arg == "-mod") {
150 // flag_mod = true;
151 // continue;
152 // }
153 break;
154 }
155 extra_args(args, argidx, design);
156
157 for (Module *module : design->modules())
158 {
159 if (!design->selected(module))
160 continue;
161
162 if (module->get_bool_attribute("\\blackbox"))
163 continue;
164
165 module->set_bool_attribute("\\whitebox", !module->get_bool_attribute("\\whitebox"));
166 }
167 }
168 } WbflipPass;
169
170 struct SetparamPass : public Pass {
171 SetparamPass() : Pass("setparam", "set/unset parameters on objects") { }
172 void help() YS_OVERRIDE
173 {
174 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
175 log("\n");
176 log(" setparam [ -type cell_type ] [ -set name value | -unset name ]... [selection]\n");
177 log("\n");
178 log("Set/unset the given parameters on the selected cells. String values must be\n");
179 log("passed in double quotes (\").\n");
180 log("\n");
181 log("The -type option can be used to change the cell type of the selected cells.\n");
182 log("\n");
183 }
184 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
185 {
186 vector<setunset_t> setunset_list;
187 string new_cell_type;
188
189 size_t argidx;
190 for (argidx = 1; argidx < args.size(); argidx++)
191 {
192 std::string arg = args[argidx];
193 if (arg == "-set" && argidx+2 < args.size()) {
194 string set_key = args[++argidx];
195 string set_val = args[++argidx];
196 setunset_list.push_back(setunset_t(set_key, set_val));
197 continue;
198 }
199 if (arg == "-unset" && argidx+1 < args.size()) {
200 setunset_list.push_back(setunset_t(args[++argidx]));
201 continue;
202 }
203 if (arg == "-type" && argidx+1 < args.size()) {
204 new_cell_type = RTLIL::escape_id(args[++argidx]);
205 continue;
206 }
207 break;
208 }
209 extra_args(args, argidx, design);
210
211 for (auto &mod : design->modules_)
212 {
213 RTLIL::Module *module = mod.second;
214
215 if (!design->selected(module))
216 continue;
217
218 for (auto &it : module->cells_)
219 if (design->selected(module, it.second)) {
220 if (!new_cell_type.empty())
221 it.second->type = new_cell_type;
222 do_setunset(it.second->parameters, setunset_list);
223 }
224 }
225 }
226 } SetparamPass;
227
228 struct ChparamPass : public Pass {
229 ChparamPass() : Pass("chparam", "re-evaluate modules with new parameters") { }
230 void help() YS_OVERRIDE
231 {
232 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
233 log("\n");
234 log(" chparam [ -set name value ]... [selection]\n");
235 log("\n");
236 log("Re-evaluate the selected modules with new parameters. String values must be\n");
237 log("passed in double quotes (\").\n");
238 log("\n");
239 log("\n");
240 log(" chparam -list [selection]\n");
241 log("\n");
242 log("List the available parameters of the selected modules.\n");
243 log("\n");
244 }
245 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
246 {
247 std::vector<setunset_t> setunset_list;
248 dict<RTLIL::IdString, RTLIL::Const> new_parameters;
249 bool list_mode = false;
250
251 size_t argidx;
252 for (argidx = 1; argidx < args.size(); argidx++)
253 {
254 std::string arg = args[argidx];
255 if (arg == "-set" && argidx+2 < args.size()) {
256 string set_key = args[++argidx];
257 string set_val = args[++argidx];
258 setunset_list.push_back(setunset_t(set_key, set_val));
259 continue;
260 }
261 if (arg == "-list") {
262 list_mode = true;
263 continue;
264 }
265 break;
266 }
267
268 for (int i = argidx; i < GetSize(args); i++)
269 if (design->module("$abstract\\" + args[i]) != nullptr &&
270 design->module(RTLIL::escape_id(args[i])) == nullptr)
271 args[i] = "$abstract\\" + args[i];
272
273 extra_args(args, argidx, design);
274
275 do_setunset(new_parameters, setunset_list);
276
277 if (list_mode) {
278 if (!new_parameters.empty())
279 log_cmd_error("The options -set and -list cannot be used together.\n");
280 for (auto module : design->selected_modules()) {
281 log("%s:\n", log_id(module));
282 for (auto param : module->avail_parameters)
283 log(" %s\n", log_id(param));
284 }
285 return;
286 }
287
288 pool<IdString> modnames, old_modnames;
289 for (auto module : design->selected_whole_modules_warn()) {
290 modnames.insert(module->name);
291 old_modnames.insert(module->name);
292 }
293 modnames.sort();
294
295 for (auto modname : modnames) {
296 Module *module = design->module(modname);
297 Module *new_module = design->module(module->derive(design, new_parameters));
298 if (module != new_module) {
299 Module *m = new_module->clone();
300 m->name = module->name;
301 design->remove(module);
302 design->add(m);
303 }
304 if (old_modnames.count(new_module->name) == 0)
305 design->remove(new_module);
306 }
307 }
308 } ChparamPass;
309
310 PRIVATE_NAMESPACE_END