Added support for more gate types to simplec back-end
[yosys.git] / backends / simplec / simplec.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/yosys.h"
21 #include "kernel/sigtools.h"
22
23 USING_YOSYS_NAMESPACE
24 PRIVATE_NAMESPACE_BEGIN
25
26 struct HierDirtyFlags;
27
28 struct HierDirtyFlags
29 {
30 int dirty;
31 Module *module;
32 IdString hiername;
33 HierDirtyFlags *parent;
34 pool<SigBit> dirty_bits;
35 pool<Cell*> dirty_cells;
36 dict<IdString, HierDirtyFlags*> children;
37
38 HierDirtyFlags(Module *module, IdString hiername, HierDirtyFlags *parent) : dirty(0), module(module), hiername(hiername), parent(parent)
39 {
40 for (Cell *cell : module->cells()) {
41 Module *mod = module->design->module(cell->type);
42 if (mod) children[cell->name] = new HierDirtyFlags(mod, cell->name, this);
43 }
44 }
45
46 ~HierDirtyFlags()
47 {
48 for (auto &child : children)
49 delete child.second;
50 }
51
52 void set_dirty(SigBit bit)
53 {
54 if (dirty_bits.count(bit))
55 return;
56
57 dirty_bits.insert(bit);
58
59 HierDirtyFlags *p = this;
60 while (p != nullptr) {
61 p->dirty++;
62 p = p->parent;
63 }
64 }
65
66 void unset_dirty(SigBit bit)
67 {
68 if (dirty_bits.count(bit) == 0)
69 return;
70
71 dirty_bits.erase(bit);
72
73 HierDirtyFlags *p = this;
74 while (p != nullptr) {
75 p->dirty--;
76 log_assert(p->dirty >= 0);
77 p = p->parent;
78 }
79 }
80
81 void set_dirty(Cell *cell)
82 {
83 if (dirty_cells.count(cell))
84 return;
85
86 dirty_cells.insert(cell);
87
88 HierDirtyFlags *p = this;
89 while (p != nullptr) {
90 p->dirty++;
91 p = p->parent;
92 }
93 }
94
95 void unset_dirty(Cell *cell)
96 {
97 if (dirty_cells.count(cell) == 0)
98 return;
99
100 dirty_cells.erase(cell);
101
102 HierDirtyFlags *p = this;
103 while (p != nullptr) {
104 p->dirty--;
105 log_assert(p->dirty >= 0);
106 p = p->parent;
107 }
108 }
109 };
110
111 struct SimplecWorker
112 {
113 bool verbose = false;
114 int max_uintsize = 32;
115
116 Design *design;
117 dict<Module*, SigMap> sigmaps;
118 HierDirtyFlags *dirty_flags = nullptr;
119
120 vector<string> signal_declarations;
121 pool<int> generated_sigtypes;
122
123 vector<string> util_declarations;
124 pool<string> generated_utils;
125
126 vector<string> struct_declarations;
127 pool<IdString> generated_structs;
128
129 vector<string> funct_declarations;
130
131 pool<string> reserved_cids;
132 dict<IdString, string> id2cid;
133
134 dict<Module*, dict<SigBit, pool<tuple<Cell*, IdString, int>>>> bit2cell;
135 dict<Module*, dict<SigBit, pool<SigBit>>> bit2output;
136
137 SimplecWorker(Design *design) : design(design)
138 {
139 }
140
141 string sigtype(int n)
142 {
143 string struct_name = stringf("signal%d_t", n);
144
145 if (generated_sigtypes.count(n) == 0)
146 {
147 signal_declarations.push_back("");
148 signal_declarations.push_back(stringf("#ifndef YOSYS_SIMPLEC_SIGNAL%d_T", n));
149 signal_declarations.push_back(stringf("#define YOSYS_SIMPLEC_SIGNAL%d_T", n));
150 signal_declarations.push_back(stringf("typedef struct {"));
151
152 for (int k = 8; k <= max_uintsize; k = 2*k)
153 if (n <= k && k <= max_uintsize) {
154 signal_declarations.push_back(stringf(" uint%d_t value_%d_0 : %d;", k, n-1, n));
155 goto end_struct;
156 }
157
158 for (int k = 0; k < n; k += max_uintsize) {
159 int bits = std::min(max_uintsize, n-k);
160 signal_declarations.push_back(stringf(" uint%d_t value_%d_%d : %d;", max_uintsize, k+bits-1, k, bits));
161 }
162
163 end_struct:
164 signal_declarations.push_back(stringf("} signal%d_t;", n));
165 signal_declarations.push_back(stringf("#endif"));
166 generated_sigtypes.insert(n);
167 }
168
169 return struct_name;
170 }
171
172 void util_ifdef_guard(string s)
173 {
174 for (int i = 0; i < GetSize(s); i++)
175 if ('a' <= s[i] && s[i] <= 'z')
176 s[i] -= 'a' - 'A';
177
178 util_declarations.push_back(stringf("#ifndef %s", s.c_str()));
179 util_declarations.push_back(stringf("#define %s", s.c_str()));
180 }
181
182 string util_get_bit(int n, int idx)
183 {
184 string util_name = stringf("yosys_simplec_get_bit_%d_of_%d", idx, n);
185
186 if (generated_utils.count(util_name) == 0)
187 {
188 util_ifdef_guard(util_name);
189 util_declarations.push_back(stringf("bool %s(const %s *sig)", util_name.c_str(), sigtype(n).c_str()));
190 util_declarations.push_back(stringf("{"));
191
192 int word_idx = idx / max_uintsize, word_offset = idx % max_uintsize;
193 string value_name = stringf("value_%d_%d", std::min(n-1, (word_idx+1)*max_uintsize-1), word_idx*max_uintsize);
194
195 util_declarations.push_back(stringf(" return (sig->%s >> %d) & 1;", value_name.c_str(), word_offset));
196
197 util_declarations.push_back(stringf("}"));
198 util_declarations.push_back(stringf("#endif"));
199 generated_utils.insert(util_name);
200 }
201
202 return util_name;
203 }
204
205 string util_set_bit(int n, int idx)
206 {
207 string util_name = stringf("yosys_simplec_set_bit_%d_of_%d", idx, n);
208
209 if (generated_utils.count(util_name) == 0)
210 {
211 util_ifdef_guard(util_name);
212 util_declarations.push_back(stringf("void %s(%s *sig, bool value)", util_name.c_str(), sigtype(n).c_str()));
213 util_declarations.push_back(stringf("{"));
214
215 int word_idx = idx / max_uintsize, word_offset = idx % max_uintsize;
216 string value_name = stringf("value_%d_%d", std::min(n-1, (word_idx+1)*max_uintsize-1), word_idx*max_uintsize);
217
218 util_declarations.push_back(stringf(" if (value)"));
219 util_declarations.push_back(stringf(" sig->%s |= 1UL << %d;", value_name.c_str(), word_offset));
220 util_declarations.push_back(stringf(" else"));
221 util_declarations.push_back(stringf(" sig->%s &= ~(1UL << %d);", value_name.c_str(), word_offset));
222
223 util_declarations.push_back(stringf("}"));
224 util_declarations.push_back(stringf("#endif"));
225 generated_utils.insert(util_name);
226 }
227
228 return util_name;
229 }
230
231 string cid(IdString id)
232 {
233 if (id2cid.count(id) == 0)
234 {
235 string s = id.str();
236 if (GetSize(s) < 2) log_abort();
237
238 if (s[0] == '\\')
239 s = s.substr(1);
240
241 if ('0' <= s[0] && s[0] <= '9') {
242 s = "_" + s;
243 }
244
245 for (int i = 0; i < GetSize(s); i++) {
246 if ('0' <= s[i] && s[i] <= '9') continue;
247 if ('A' <= s[i] && s[i] <= 'Z') continue;
248 if ('a' <= s[i] && s[i] <= 'z') continue;
249 s[i] = '_';
250 }
251
252 while (reserved_cids.count(s))
253 s += "_";
254
255 reserved_cids.insert(s);
256 id2cid[id] = s;
257 }
258
259 return id2cid.at(id);
260 }
261
262 void create_module_struct(Module *mod)
263 {
264 if (generated_structs.count(mod->name))
265 return;
266
267 generated_structs.insert(mod->name);
268 sigmaps[mod].set(mod);
269
270 for (Wire *w : mod->wires())
271 {
272 if (w->port_output)
273 for (auto bit : SigSpec(w))
274 bit2output[mod][sigmaps.at(mod)(bit)].insert(bit);
275 }
276
277 for (Cell *c : mod->cells())
278 {
279 for (auto &conn : c->connections())
280 {
281 if (!c->input(conn.first))
282 continue;
283
284 int idx = 0;
285 for (auto bit : sigmaps.at(mod)(conn.second))
286 bit2cell[mod][bit].insert(tuple<Cell*, IdString, int>(c, conn.first, idx++));
287 }
288
289 if (design->module(c->type))
290 create_module_struct(design->module(c->type));
291 }
292
293 struct_declarations.push_back("");
294 struct_declarations.push_back(stringf("struct %s_state_t {", cid(mod->name).c_str()));
295
296 for (Wire *w : mod->wires())
297 struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w)));
298
299 for (Cell *c : mod->cells())
300 if (design->module(c->type))
301 struct_declarations.push_back(stringf(" struct %s_state_t %s; // %s", cid(c->type).c_str(), cid(c->name).c_str(), log_id(c)));
302
303 struct_declarations.push_back(stringf("};"));
304 }
305
306 void eval_cell(HierDirtyFlags *work, string &prefix, string &/* log_prefix */, Cell *cell)
307 {
308 if (cell->type.in("$_BUF_", "$_NOT_"))
309 {
310 SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
311 SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
312
313 string a_expr = a.wire ? stringf("%s(&%s)", util_get_bit(a.wire->width, a.offset).c_str(), (prefix + cid(a.wire->name)).c_str()) : a.data ? "1" : "0";
314 string expr;
315
316 if (cell->type == "$_BUF_") expr = a_expr;
317 if (cell->type == "$_NOT_") expr = "!" + a_expr;
318
319 log_assert(y.wire);
320 funct_declarations.push_back(stringf(" %s(&%s, %s); // %s (%s)", util_set_bit(y.wire->width, y.offset).c_str(),
321 (prefix + cid(y.wire->name)).c_str(), expr.c_str(), log_id(cell), log_id(cell->type)));
322
323 work->set_dirty(y);
324 return;
325 }
326
327 if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_"))
328 {
329 SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
330 SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
331 SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
332
333 string a_expr = a.wire ? stringf("%s(&%s)", util_get_bit(a.wire->width, a.offset).c_str(), (prefix + cid(a.wire->name)).c_str()) : a.data ? "1" : "0";
334 string b_expr = b.wire ? stringf("%s(&%s)", util_get_bit(b.wire->width, b.offset).c_str(), (prefix + cid(b.wire->name)).c_str()) : b.data ? "1" : "0";
335 string expr;
336
337 if (cell->type == "$_AND_") expr = stringf("%s & %s", a_expr.c_str(), b_expr.c_str());
338 if (cell->type == "$_NAND_") expr = stringf("!(%s & %s)", a_expr.c_str(), b_expr.c_str());
339 if (cell->type == "$_OR_") expr = stringf("%s | %s", a_expr.c_str(), b_expr.c_str());
340 if (cell->type == "$_NOR_") expr = stringf("!(%s | %s)", a_expr.c_str(), b_expr.c_str());
341 if (cell->type == "$_XOR_") expr = stringf("%s ^ %s", a_expr.c_str(), b_expr.c_str());
342 if (cell->type == "$_XNOR_") expr = stringf("!(%s ^ %s)", a_expr.c_str(), b_expr.c_str());
343
344 log_assert(y.wire);
345 funct_declarations.push_back(stringf(" %s(&%s, %s); // %s (%s)", util_set_bit(y.wire->width, y.offset).c_str(),
346 (prefix + cid(y.wire->name)).c_str(), expr.c_str(), log_id(cell), log_id(cell->type)));
347
348 work->set_dirty(y);
349 return;
350 }
351
352 if (cell->type.in("$_AOI3_", "$_OAI3_"))
353 {
354 SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
355 SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
356 SigBit c = sigmaps.at(work->module)(cell->getPort("\\C"));
357 SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
358
359 string a_expr = a.wire ? stringf("%s(&%s)", util_get_bit(a.wire->width, a.offset).c_str(), (prefix + cid(a.wire->name)).c_str()) : a.data ? "1" : "0";
360 string b_expr = b.wire ? stringf("%s(&%s)", util_get_bit(b.wire->width, b.offset).c_str(), (prefix + cid(b.wire->name)).c_str()) : b.data ? "1" : "0";
361 string c_expr = c.wire ? stringf("%s(&%s)", util_get_bit(c.wire->width, c.offset).c_str(), (prefix + cid(c.wire->name)).c_str()) : c.data ? "1" : "0";
362 string expr;
363
364 if (cell->type == "$_AOI3_") expr = stringf("!((%s & %s) | %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str());
365 if (cell->type == "$_OAI3_") expr = stringf("!((%s | %s) & %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str());
366
367 log_assert(y.wire);
368 funct_declarations.push_back(stringf(" %s(&%s, %s); // %s (%s)", util_set_bit(y.wire->width, y.offset).c_str(),
369 (prefix + cid(y.wire->name)).c_str(), expr.c_str(), log_id(cell), log_id(cell->type)));
370
371 work->set_dirty(y);
372 return;
373 }
374
375 if (cell->type.in("$_AOI4_", "$_OAI4_"))
376 {
377 SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
378 SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
379 SigBit c = sigmaps.at(work->module)(cell->getPort("\\C"));
380 SigBit d = sigmaps.at(work->module)(cell->getPort("\\D"));
381 SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
382
383 string a_expr = a.wire ? stringf("%s(&%s)", util_get_bit(a.wire->width, a.offset).c_str(), (prefix + cid(a.wire->name)).c_str()) : a.data ? "1" : "0";
384 string b_expr = b.wire ? stringf("%s(&%s)", util_get_bit(b.wire->width, b.offset).c_str(), (prefix + cid(b.wire->name)).c_str()) : b.data ? "1" : "0";
385 string c_expr = c.wire ? stringf("%s(&%s)", util_get_bit(c.wire->width, c.offset).c_str(), (prefix + cid(c.wire->name)).c_str()) : c.data ? "1" : "0";
386 string d_expr = d.wire ? stringf("%s(&%s)", util_get_bit(d.wire->width, d.offset).c_str(), (prefix + cid(d.wire->name)).c_str()) : d.data ? "1" : "0";
387 string expr;
388
389 if (cell->type == "$_AOI4_") expr = stringf("!((%s & %s) | (%s & %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str());
390 if (cell->type == "$_OAI4_") expr = stringf("!((%s | %s) & (%s | %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str());
391
392 log_assert(y.wire);
393 funct_declarations.push_back(stringf(" %s(&%s, %s); // %s (%s)", util_set_bit(y.wire->width, y.offset).c_str(),
394 (prefix + cid(y.wire->name)).c_str(), expr.c_str(), log_id(cell), log_id(cell->type)));
395
396 work->set_dirty(y);
397 return;
398 }
399
400 if (cell->type == "$_MUX_")
401 {
402 SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
403 SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
404 SigBit s = sigmaps.at(work->module)(cell->getPort("\\S"));
405 SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
406
407 string a_expr = a.wire ? stringf("%s(&%s)", util_get_bit(a.wire->width, a.offset).c_str(), (prefix + cid(a.wire->name)).c_str()) : a.data ? "1" : "0";
408 string b_expr = b.wire ? stringf("%s(&%s)", util_get_bit(b.wire->width, b.offset).c_str(), (prefix + cid(b.wire->name)).c_str()) : b.data ? "1" : "0";
409 string s_expr = s.wire ? stringf("%s(&%s)", util_get_bit(s.wire->width, s.offset).c_str(), (prefix + cid(s.wire->name)).c_str()) : s.data ? "1" : "0";
410 string expr = stringf("%s ? %s : %s", s_expr.c_str(), b_expr.c_str(), a_expr.c_str());
411
412 log_assert(y.wire);
413 funct_declarations.push_back(stringf(" %s(&%s, %s); // %s (%s)", util_set_bit(y.wire->width, y.offset).c_str(),
414 (prefix + cid(y.wire->name)).c_str(), expr.c_str(), log_id(cell), log_id(cell->type)));
415
416 work->set_dirty(y);
417 return;
418 }
419
420 log_error("No C model for %s available at the moment (FIXME).\n", log_id(cell->type));
421 }
422
423 void eval_dirty(HierDirtyFlags *work, string prefix, string log_prefix, string parent_prefix)
424 {
425 while (work->dirty)
426 {
427 while (!work->dirty_bits.empty() || !work->dirty_cells.empty())
428 {
429 if (!work->dirty_bits.empty())
430 {
431 SigSpec dirtysig(work->dirty_bits);
432 dirtysig.sort_and_unify();
433
434 for (SigChunk chunk : dirtysig.chunks())
435 funct_declarations.push_back(stringf(" // New dirty bits in %s: %s", log_prefix.c_str(), log_signal(chunk)));
436
437 for (SigBit bit : dirtysig)
438 {
439 if (bit2output[work->module].count(bit) && work->parent)
440 for (auto outbit : bit2output[work->module][bit])
441 {
442 Module *parent_mod = work->parent->module;
443 Cell *parent_cell = parent_mod->cell(work->hiername);
444
445 IdString port_name = outbit.wire->name;
446 int port_offset = outbit.offset;
447 SigBit parent_bit = sigmaps.at(parent_mod)(parent_cell->getPort(port_name)[port_offset]);
448
449 log_assert(bit.wire && parent_bit.wire);
450 funct_declarations.push_back(stringf(" %s(&%s, %s(&%s));",
451 util_set_bit(parent_bit.wire->width, parent_bit.offset).c_str(),
452 (parent_prefix + cid(parent_bit.wire->name)).c_str(),
453 util_get_bit(bit.wire->width, bit.offset).c_str(),
454 (prefix + cid(bit.wire->name)).c_str()));
455 work->parent->set_dirty(parent_bit);
456 }
457
458 for (auto &port : bit2cell[work->module][bit])
459 {
460 if (work->children.count(std::get<0>(port)->name)) {
461 HierDirtyFlags *child = work->children.at(std::get<0>(port)->name);
462 SigBit child_bit = sigmaps.at(child->module)(SigBit(child->module->wire(std::get<1>(port)), std::get<2>(port)));
463 log_assert(bit.wire && child_bit.wire);
464 funct_declarations.push_back(stringf(" %s(&%s, %s(&%s));",
465 util_set_bit(child_bit.wire->width, child_bit.offset).c_str(),
466 (prefix + cid(child->hiername) + "." + cid(child_bit.wire->name)).c_str(),
467 util_get_bit(bit.wire->width, bit.offset).c_str(),
468 (prefix + cid(bit.wire->name)).c_str()));
469 child->set_dirty(child_bit);
470 } else {
471 work->set_dirty(std::get<0>(port));
472 }
473 }
474 work->unset_dirty(bit);
475 }
476 }
477
478 if (!work->dirty_cells.empty())
479 {
480 Cell *cell = *work->dirty_cells.begin();
481 eval_cell(work, prefix, log_prefix, cell);
482 work->unset_dirty(cell);
483 }
484 }
485
486 for (auto &child : work->children)
487 eval_dirty(child.second, prefix + cid(child.first) + ".", log_prefix + "." + cid(child.first), prefix);
488 }
489 }
490
491 void run(Module *mod)
492 {
493 create_module_struct(mod);
494
495 dirty_flags = new HierDirtyFlags(mod, IdString(), nullptr);
496
497 funct_declarations.push_back("");
498 funct_declarations.push_back(stringf("void %s_init(struct %s_state_t *state)", cid(mod->name).c_str(), cid(mod->name).c_str()));
499 funct_declarations.push_back("{");
500 funct_declarations.push_back("}");
501
502 funct_declarations.push_back("");
503 funct_declarations.push_back(stringf("void %s_eval(struct %s_state_t *state)", cid(mod->name).c_str(), cid(mod->name).c_str()));
504 funct_declarations.push_back("{");
505
506 for (Wire *w : mod->wires()) {
507 if (w->port_input)
508 for (SigBit bit : sigmaps.at(mod)(w))
509 dirty_flags->set_dirty(bit);
510 }
511
512 eval_dirty(dirty_flags, "state->", log_id(mod), "");
513
514 funct_declarations.push_back("}");
515
516 funct_declarations.push_back("");
517 funct_declarations.push_back(stringf("void %s_tick(struct %s_state_t *state)", cid(mod->name).c_str(), cid(mod->name).c_str()));
518 funct_declarations.push_back("{");
519 funct_declarations.push_back("}");
520
521 delete dirty_flags;
522 dirty_flags = nullptr;
523 }
524
525 void write(std::ostream &f)
526 {
527 f << "#include <stdint.h>" << std::endl;
528 f << "#include <stdbool.h>" << std::endl;
529
530 for (auto &line : signal_declarations)
531 f << line << std::endl;
532
533 for (auto &line : util_declarations)
534 f << line << std::endl;
535
536 for (auto &line : struct_declarations)
537 f << line << std::endl;
538
539 for (auto &line : funct_declarations)
540 f << line << std::endl;
541 }
542 };
543
544 struct SimplecBackend : public Backend {
545 SimplecBackend() : Backend("simplec", "convert design to simple C code") { }
546 virtual void help()
547 {
548 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
549 log("\n");
550 log(" write_simplec [options] [filename]\n");
551 log("\n");
552 log("Write simple C code for simulating the design. The C code writen can be used to\n");
553 log("simulate the design in a C environment, but the purpose of this command is to\n");
554 log("generate code that works well with C-based formal verification.\n");
555 log("\n");
556 log(" -verbose\n");
557 log(" this will print the recursive walk used to export the modules.\n");
558 log("\n");
559 log(" -i8, -i16, -i32, -i64\n");
560 log(" set the maximum integer bit width to use in the generated code.\n");
561 log("\n");
562 log("THIS COMMAND IS UNDER CONSTRUCTION\n");
563 log("\n");
564 }
565 virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
566 {
567 SimplecWorker worker(design);
568
569 log_header(design, "Executing SIMPLEC backend.\n");
570
571 size_t argidx;
572 for (argidx = 1; argidx < args.size(); argidx++)
573 {
574 if (args[argidx] == "-verbose") {
575 worker.verbose = true;
576 continue;
577 }
578 if (args[argidx] == "-i8") {
579 worker.max_uintsize = 8;
580 continue;
581 }
582 if (args[argidx] == "-i16") {
583 worker.max_uintsize = 16;
584 continue;
585 }
586 if (args[argidx] == "-i32") {
587 worker.max_uintsize = 32;
588 continue;
589 }
590 if (args[argidx] == "-i64") {
591 worker.max_uintsize = 64;
592 continue;
593 }
594 break;
595 }
596 extra_args(f, filename, args, argidx);
597
598 Module *topmod = design->top_module();
599
600 if (topmod == nullptr)
601 log_error("Current design has no top module.\n");
602
603 worker.run(topmod);
604 worker.write(*f);
605 }
606 } SimplecBackend;
607
608 PRIVATE_NAMESPACE_END