added stimulus mode and param check
[yosys.git] / passes / sat / mutate.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
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 mutate_t {
27 string mode;
28 pool<string> src;
29 IdString module, cell;
30 IdString port, wire;
31 int portbit = -1;
32 int ctrlbit = -1;
33 int wirebit = -1;
34 bool used = false;
35 };
36
37 struct mutate_opts_t {
38 int seed = 0;
39 std::string mode;
40 pool<string> src;
41 IdString module, cell, port, wire;
42 int portbit = -1;
43 int ctrlbit = -1;
44 int wirebit = -1;
45
46 IdString ctrl_name;
47 int ctrl_width = -1, ctrl_value = -1;
48
49 bool none = false;
50
51 int pick_cover_prcnt = 80;
52
53 int weight_cover = 500;
54
55 int weight_pq_w = 100;
56 int weight_pq_b = 100;
57 int weight_pq_c = 100;
58 int weight_pq_s = 100;
59
60 int weight_pq_mw = 100;
61 int weight_pq_mb = 100;
62 int weight_pq_mc = 100;
63 int weight_pq_ms = 100;
64 };
65
66 void database_add(std::vector<mutate_t> &database, const mutate_opts_t &opts, const mutate_t &entry)
67 {
68 if (!opts.mode.empty() && opts.mode != entry.mode)
69 return;
70
71 if (!opts.src.empty()) {
72 bool found_match = false;
73 for (auto &s : opts.src) {
74 if (entry.src.count(s))
75 found_match = true;
76 }
77 if (!found_match)
78 return;
79 }
80
81 if (!opts.module.empty() && opts.module != entry.module)
82 return;
83
84 if (!opts.cell.empty() && opts.cell != entry.cell)
85 return;
86
87 if (!opts.port.empty() && opts.port != entry.port)
88 return;
89
90 if (opts.portbit >= 0 && opts.portbit != entry.portbit)
91 return;
92
93 if (opts.ctrlbit >= 0 && opts.ctrlbit != entry.ctrlbit)
94 return;
95
96 if (!opts.wire.empty() && opts.wire != entry.wire)
97 return;
98
99 if (opts.wirebit >= 0 && opts.wirebit != entry.wirebit)
100 return;
101
102 database.push_back(entry);
103 }
104
105 struct xs128_t
106 {
107 uint32_t x = 123456789;
108 uint32_t y = 0, z = 0, w = 0;
109
110 xs128_t(int seed = 0) : w(seed) {
111 next();
112 next();
113 next();
114 }
115
116 void next() {
117 uint32_t t = x ^ (x << 11);
118 x = y, y = z, z = w;
119 w ^= (w >> 19) ^ t ^ (t >> 8);
120 }
121
122 int operator()() {
123 next();
124 return w & 0x3fffffff;
125 }
126
127 int operator()(int n) {
128 if (n < 2)
129 return 0;
130 while (1) {
131 int k = (*this)(), p = k % n;
132 if ((k - p + n) <= 0x40000000)
133 return p;
134 }
135 }
136 };
137
138 struct coverdb_t
139 {
140 dict<string, int> src_db;
141 dict<tuple<IdString, IdString>, int> wire_db;
142 dict<tuple<IdString, IdString, int>, int> wirebit_db;
143
144 void insert(const mutate_t &m) {
145 if (!m.wire.empty()) {
146 wire_db[tuple<IdString, IdString>(m.module, m.wire)] = 0;
147 wirebit_db[tuple<IdString, IdString, int>(m.module, m.wire, m.wirebit)] = 0;
148 }
149 for (auto &s : m.src) {
150 src_db[s] = 0;
151 }
152 }
153
154 void update(const mutate_t &m) {
155 if (!m.wire.empty()) {
156 wire_db.at(tuple<IdString, IdString>(m.module, m.wire))++;
157 wirebit_db.at(tuple<IdString, IdString, int>(m.module, m.wire, m.wirebit))++;
158 }
159 for (auto &s : m.src) {
160 src_db.at(s)++;
161 }
162 }
163
164 int score(const mutate_t &m) {
165 int this_score = m.src.empty() ? 0 : 1;
166 if (!m.wire.empty()) {
167 this_score += wire_db.at(tuple<IdString, IdString>(m.module, m.wire)) ? 0 : 5;
168 this_score += wirebit_db.at(tuple<IdString, IdString, int>(m.module, m.wire, m.wirebit)) ? 0 : 1;
169 }
170 for (auto &s : m.src) {
171 this_score += src_db.at(s) ? 0 : 5;
172 }
173 return this_score;
174 }
175 };
176
177 struct mutate_queue_t
178 {
179 pool<mutate_t*, hash_ptr_ops> db;
180
181 mutate_t *pick(xs128_t &rng, coverdb_t &coverdb, const mutate_opts_t &opts) {
182 mutate_t *m = nullptr;
183 if (rng(100) < opts.pick_cover_prcnt) {
184 vector<mutate_t*> candidates, rmqueue;
185 int best_score = -1;
186 for (auto p : db) {
187 if (p->used) {
188 rmqueue.push_back(p);
189 continue;
190 }
191 int this_score = coverdb.score(*p);
192 if (this_score > best_score) {
193 best_score = this_score;
194 candidates.clear();
195 }
196 if (best_score == this_score)
197 candidates.push_back(p);
198 }
199 for (auto p : rmqueue)
200 db.erase(p);
201 if (!candidates.empty())
202 m = candidates[rng(GetSize(candidates))];
203 }
204 if (m == nullptr) {
205 while (!db.empty()) {
206 int i = rng(GetSize(db));
207 auto it = db.element(i);
208 mutate_t *p = *it;
209 db.erase(it);
210 if (p->used == false) {
211 m = p;
212 break;
213 }
214 }
215 }
216 return m;
217 }
218
219 void add(mutate_t *m) {
220 db.insert(m);
221 }
222 };
223
224 template <typename K, typename T>
225 struct mutate_chain_queue_t
226 {
227 dict<K, T> db;
228
229 mutate_t *pick(xs128_t &rng, coverdb_t &coverdb, const mutate_opts_t &opts) {
230 while (!db.empty()) {
231 int i = rng(GetSize(db));
232 auto it = db.element(i);
233 mutate_t *m = it->second.pick(rng, coverdb, opts);
234 if (m != nullptr)
235 return m;
236 db.erase(it);
237 }
238 return nullptr;
239 }
240
241 template<typename... Args>
242 void add(mutate_t *m, K key, Args... args) {
243 db[key].add(m, args...);
244 }
245 };
246
247 template <typename K, typename T>
248 struct mutate_once_queue_t
249 {
250 dict<K, T> db;
251
252 mutate_t *pick(xs128_t &rng, coverdb_t &coverdb, const mutate_opts_t &opts) {
253 while (!db.empty()) {
254 int i = rng(GetSize(db));
255 auto it = db.element(i);
256 mutate_t *m = it->second.pick(rng, coverdb, opts);
257 db.erase(it);
258 if (m != nullptr)
259 return m;
260 }
261 return nullptr;
262 }
263
264 template<typename... Args>
265 void add(mutate_t *m, K key, Args... args) {
266 db[key].add(m, args...);
267 }
268 };
269
270 void database_reduce(std::vector<mutate_t> &database, const mutate_opts_t &opts, int N, xs128_t &rng)
271 {
272 std::vector<mutate_t> new_database;
273 coverdb_t coverdb;
274
275 int total_weight = opts.weight_cover + opts.weight_pq_w + opts.weight_pq_b + opts.weight_pq_c + opts.weight_pq_s;
276 total_weight += opts.weight_pq_mw + opts.weight_pq_mb + opts.weight_pq_mc + opts.weight_pq_ms;
277
278 if (N >= GetSize(database))
279 return;
280
281 mutate_once_queue_t<tuple<IdString, IdString>, mutate_queue_t> primary_queue_wire;
282 mutate_once_queue_t<tuple<IdString, IdString, int>, mutate_queue_t> primary_queue_bit;
283 mutate_once_queue_t<tuple<IdString, IdString>, mutate_queue_t> primary_queue_cell;
284 mutate_once_queue_t<string, mutate_queue_t> primary_queue_src;
285
286 mutate_chain_queue_t<IdString, mutate_once_queue_t<IdString, mutate_queue_t>> primary_queue_module_wire;
287 mutate_chain_queue_t<IdString, mutate_once_queue_t<pair<IdString, int>, mutate_queue_t>> primary_queue_module_bit;
288 mutate_chain_queue_t<IdString, mutate_once_queue_t<IdString, mutate_queue_t>> primary_queue_module_cell;
289 mutate_chain_queue_t<IdString, mutate_once_queue_t<string, mutate_queue_t>> primary_queue_module_src;
290
291 for (auto &m : database)
292 {
293 coverdb.insert(m);
294
295 if (!m.wire.empty()) {
296 primary_queue_wire.add(&m, tuple<IdString, IdString>(m.module, m.wire));
297 primary_queue_bit.add(&m, tuple<IdString, IdString, int>(m.module, m.wire, m.wirebit));
298 primary_queue_module_wire.add(&m, m.module, m.wire);
299 primary_queue_module_bit.add(&m, m.module, pair<IdString, int>(m.wire, m.wirebit));
300 }
301
302 primary_queue_cell.add(&m, tuple<IdString, IdString>(m.module, m.cell));
303 primary_queue_module_cell.add(&m, m.module, m.cell);
304
305 for (auto &s : m.src) {
306 primary_queue_src.add(&m, s);
307 primary_queue_module_src.add(&m, m.module, s);
308 }
309 }
310
311 vector<mutate_t*> cover_candidates;
312 int best_cover_score = -1;
313 bool skip_cover = false;
314
315 while (GetSize(new_database) < N)
316 {
317 int k = rng(total_weight);
318
319 k -= opts.weight_cover;
320 if (k < 0) {
321 while (!skip_cover) {
322 if (cover_candidates.empty()) {
323 best_cover_score = -1;
324 for (auto &m : database) {
325 if (m.used || m.src.empty())
326 continue;
327 int this_score = -1;
328 for (auto &s : m.src) {
329 if (this_score == -1 || this_score > coverdb.src_db.at(s))
330 this_score = coverdb.src_db.at(s);
331 }
332 log_assert(this_score != -1);
333 if (best_cover_score == -1 || this_score < best_cover_score) {
334 cover_candidates.clear();
335 best_cover_score = this_score;
336 }
337 if (best_cover_score == this_score)
338 cover_candidates.push_back(&m);
339 }
340 if (best_cover_score == -1) {
341 skip_cover = true;
342 break;
343 }
344 }
345
346 mutate_t *m = nullptr;
347 while (!cover_candidates.empty())
348 {
349 int idx = rng(GetSize(cover_candidates));
350 mutate_t *p = cover_candidates[idx];
351 cover_candidates[idx] = cover_candidates.back();
352 cover_candidates.pop_back();
353
354 if (p->used)
355 continue;
356
357 int this_score = -1;
358 for (auto &s : p->src) {
359 if (this_score == -1 || this_score > coverdb.src_db.at(s))
360 this_score = coverdb.src_db.at(s);
361 }
362
363 if (this_score != best_cover_score)
364 continue;
365
366 m = p;
367 break;
368 }
369
370 if (m != nullptr) {
371 m->used = true;
372 coverdb.update(*m);
373 new_database.push_back(*m);
374 break;
375 }
376 }
377 continue;
378 }
379
380 #define X(__wght, __queue) \
381 k -= __wght; \
382 if (k < 0) { \
383 mutate_t *m = __queue.pick(rng, coverdb, opts); \
384 if (m != nullptr) { \
385 m->used = true; \
386 coverdb.update(*m); \
387 new_database.push_back(*m); \
388 }; \
389 continue; \
390 }
391
392 X(opts.weight_pq_w, primary_queue_wire)
393 X(opts.weight_pq_b, primary_queue_bit)
394 X(opts.weight_pq_c, primary_queue_cell)
395 X(opts.weight_pq_s, primary_queue_src)
396
397 X(opts.weight_pq_mw, primary_queue_module_wire)
398 X(opts.weight_pq_mb, primary_queue_module_bit)
399 X(opts.weight_pq_mc, primary_queue_module_cell)
400 X(opts.weight_pq_ms, primary_queue_module_src)
401 #undef X
402 }
403
404 std::swap(new_database, database);
405
406 int covered_src_cnt = 0;
407 int covered_wire_cnt = 0;
408 int covered_wirebit_cnt = 0;
409
410 for (auto &it : coverdb.src_db)
411 if (it.second)
412 covered_src_cnt++;
413
414 for (auto &it : coverdb.wire_db)
415 if (it.second)
416 covered_wire_cnt++;
417
418 for (auto &it : coverdb.wirebit_db)
419 if (it.second)
420 covered_wirebit_cnt++;
421
422 log("Covered %d/%d src attributes (%.2f%%).\n", covered_src_cnt, GetSize(coverdb.src_db), 100.0 * covered_src_cnt / GetSize(coverdb.src_db));
423 log("Covered %d/%d wires (%.2f%%).\n", covered_wire_cnt, GetSize(coverdb.wire_db), 100.0 * covered_wire_cnt / GetSize(coverdb.wire_db));
424 log("Covered %d/%d wire bits (%.2f%%).\n", covered_wirebit_cnt, GetSize(coverdb.wirebit_db), 100.0 * covered_wirebit_cnt / GetSize(coverdb.wirebit_db));
425 }
426
427 void mutate_list(Design *design, const mutate_opts_t &opts, const string &filename, const string &srcsfile, int N)
428 {
429 pool<string> sources;
430 std::vector<mutate_t> database;
431 xs128_t rng(opts.seed);
432
433 for (auto module : design->selected_modules())
434 {
435 if (!opts.module.empty() && module->name != opts.module)
436 continue;
437
438 SigMap sigmap(module);
439 dict<SigBit, int> bit_user_cnt;
440
441 for (auto wire : module->wires()) {
442 if (wire->name.isPublic() && wire->attributes.count(ID::src))
443 sigmap.add(wire);
444 }
445
446 for (auto cell : module->cells()) {
447 for (auto &conn : cell->connections()) {
448 if (cell->output(conn.first))
449 continue;
450 for (auto bit : sigmap(conn.second))
451 bit_user_cnt[bit]++;
452 }
453 }
454
455 for (auto wire : module->selected_wires())
456 {
457 for (SigBit bit : SigSpec(wire))
458 {
459 SigBit sigbit = sigmap(bit);
460
461 if (bit.wire == nullptr || sigbit.wire == nullptr)
462 continue;
463
464 if (!bit.wire->port_id != !sigbit.wire->port_id) {
465 if (bit.wire->port_id)
466 sigmap.add(bit);
467 continue;
468 }
469
470 if (!bit.wire->name[0] != !sigbit.wire->name[0]) {
471 if (bit.wire->name.isPublic())
472 sigmap.add(bit);
473 continue;
474 }
475 }
476 }
477
478 for (auto cell : module->selected_cells())
479 {
480 if (!opts.cell.empty() && cell->name != opts.cell)
481 continue;
482
483 for (auto &conn : cell->connections())
484 {
485 for (int i = 0; i < GetSize(conn.second); i++) {
486 mutate_t entry;
487 entry.module = module->name;
488 entry.cell = cell->name;
489 entry.port = conn.first;
490 entry.portbit = i;
491
492 for (auto &s : cell->get_strpool_attribute(ID::src))
493 entry.src.insert(s);
494
495 SigBit bit = sigmap(conn.second[i]);
496 if (bit.wire && bit.wire->name.isPublic() && (cell->output(conn.first) || bit_user_cnt[bit] == 1)) {
497 for (auto &s : bit.wire->get_strpool_attribute(ID::src))
498 entry.src.insert(s);
499 entry.wire = bit.wire->name;
500 entry.wirebit = bit.offset;
501 }
502
503 if (!srcsfile.empty())
504 sources.insert(entry.src.begin(), entry.src.end());
505
506 entry.mode = "inv";
507 database_add(database, opts, entry);
508
509 entry.mode = "const0";
510 database_add(database, opts, entry);
511
512 entry.mode = "const1";
513 database_add(database, opts, entry);
514
515 entry.mode = "cnot0";
516 entry.ctrlbit = rng(GetSize(conn.second));
517 if (entry.ctrlbit != entry.portbit && conn.second[entry.ctrlbit].wire)
518 database_add(database, opts, entry);
519
520 entry.mode = "cnot1";
521 entry.ctrlbit = rng(GetSize(conn.second));
522 if (entry.ctrlbit != entry.portbit && conn.second[entry.ctrlbit].wire)
523 database_add(database, opts, entry);
524 }
525 }
526 }
527 }
528
529 log("Raw database size: %d\n", GetSize(database));
530 if (N != 0) {
531 database_reduce(database, opts, opts.none ? N-1 : N, rng);
532 log("Reduced database size: %d\n", GetSize(database));
533 }
534
535 if (!srcsfile.empty()) {
536 std::ofstream sout;
537 sout.open(srcsfile, std::ios::out | std::ios::trunc);
538 if (!sout.is_open())
539 log_error("Could not open file \"%s\" with write access.\n", srcsfile.c_str());
540 sources.sort();
541 for (auto &s : sources)
542 sout << s << std::endl;
543 }
544
545 std::ofstream fout;
546
547 if (!filename.empty()) {
548 fout.open(filename, std::ios::out | std::ios::trunc);
549 if (!fout.is_open())
550 log_error("Could not open file \"%s\" with write access.\n", filename.c_str());
551 }
552
553 int ctrl_value = opts.ctrl_value;
554
555 if (opts.none) {
556 string str = "mutate";
557 if (!opts.ctrl_name.empty())
558 str += stringf(" -ctrl %s %d %d", log_id(opts.ctrl_name), opts.ctrl_width, ctrl_value++);
559 str += " -mode none";
560 if (filename.empty())
561 log("%s\n", str.c_str());
562 else
563 fout << str << std::endl;
564 }
565
566 for (auto &entry : database) {
567 string str = "mutate";
568 if (!opts.ctrl_name.empty())
569 str += stringf(" -ctrl %s %d %d", log_id(opts.ctrl_name), opts.ctrl_width, ctrl_value++);
570 str += stringf(" -mode %s", entry.mode.c_str());
571 if (!entry.module.empty())
572 str += stringf(" -module %s", log_id(entry.module));
573 if (!entry.cell.empty())
574 str += stringf(" -cell %s", log_id(entry.cell));
575 if (!entry.port.empty())
576 str += stringf(" -port %s", log_id(entry.port));
577 if (entry.portbit >= 0)
578 str += stringf(" -portbit %d", entry.portbit);
579 if (entry.ctrlbit >= 0)
580 str += stringf(" -ctrlbit %d", entry.ctrlbit);
581 if (!entry.wire.empty())
582 str += stringf(" -wire %s", log_id(entry.wire));
583 if (entry.wirebit >= 0)
584 str += stringf(" -wirebit %d", entry.wirebit);
585 for (auto &s : entry.src)
586 str += stringf(" -src %s", s.c_str());
587 if (filename.empty())
588 log("%s\n", str.c_str());
589 else
590 fout << str << std::endl;
591 }
592 }
593
594 SigSpec mutate_ctrl_sig(Module *module, IdString name, int width)
595 {
596 Wire *ctrl_wire = module->wire(name);
597
598 if (ctrl_wire == nullptr)
599 {
600 log("Adding ctrl port %s to module %s.\n", log_id(name), log_id(module));
601
602 ctrl_wire = module->addWire(name, width);
603 ctrl_wire->port_input = true;
604 module->fixup_ports();
605
606 for (auto mod : module->design->modules())
607 for (auto cell : mod->cells())
608 {
609 if (cell->type != module->name)
610 continue;
611
612 SigSpec ctrl = mutate_ctrl_sig(mod, name, width);
613
614 log("Connecting ctrl port to cell %s in module %s.\n", log_id(cell), log_id(mod));
615 cell->setPort(name, ctrl);
616 }
617 }
618
619 log_assert(GetSize(ctrl_wire) == width);
620 return ctrl_wire;
621 }
622
623 SigBit mutate_ctrl(Module *module, const mutate_opts_t &opts)
624 {
625 if (opts.ctrl_name.empty())
626 return State::S1;
627
628 SigSpec sig = mutate_ctrl_sig(module, opts.ctrl_name, opts.ctrl_width);
629 return module->Eq(NEW_ID, sig, Const(opts.ctrl_value, GetSize(sig)));
630 }
631
632 SigSpec mutate_ctrl_mux(Module *module, const mutate_opts_t &opts, SigSpec unchanged_sig, SigSpec changed_sig)
633 {
634 SigBit ctrl_bit = mutate_ctrl(module, opts);
635 if (ctrl_bit == State::S0)
636 return unchanged_sig;
637 if (ctrl_bit == State::S1)
638 return changed_sig;
639 return module->Mux(NEW_ID, unchanged_sig, changed_sig, ctrl_bit);
640 }
641
642 void mutate_inv(Design *design, const mutate_opts_t &opts)
643 {
644 Module *module = design->module(opts.module);
645 Cell *cell = module->cell(opts.cell);
646
647 SigBit bit = cell->getPort(opts.port)[opts.portbit];
648 SigBit inbit, outbit;
649
650 if (cell->input(opts.port))
651 {
652 log("Add input inverter at %s.%s.%s[%d].\n", log_id(module), log_id(cell), log_id(opts.port), opts.portbit);
653 SigBit outbit = module->Not(NEW_ID, bit);
654 bit = mutate_ctrl_mux(module, opts, bit, outbit);
655 }
656 else
657 {
658 log("Add output inverter at %s.%s.%s[%d].\n", log_id(module), log_id(cell), log_id(opts.port), opts.portbit);
659 SigBit inbit = module->addWire(NEW_ID);
660 SigBit outbit = module->Not(NEW_ID, inbit);
661 module->connect(bit, mutate_ctrl_mux(module, opts, inbit, outbit));
662 bit = inbit;
663 }
664
665 SigSpec s = cell->getPort(opts.port);
666 s[opts.portbit] = bit;
667 cell->setPort(opts.port, s);
668 }
669
670 void mutate_const(Design *design, const mutate_opts_t &opts, bool one)
671 {
672 Module *module = design->module(opts.module);
673 Cell *cell = module->cell(opts.cell);
674
675 SigBit bit = cell->getPort(opts.port)[opts.portbit];
676 SigBit inbit, outbit;
677
678 if (cell->input(opts.port))
679 {
680 log("Add input constant %d at %s.%s.%s[%d].\n", one ? 1 : 0, log_id(module), log_id(cell), log_id(opts.port), opts.portbit);
681 SigBit outbit = one ? State::S1 : State::S0;
682 bit = mutate_ctrl_mux(module, opts, bit, outbit);
683 }
684 else
685 {
686 log("Add output constant %d at %s.%s.%s[%d].\n", one ? 1 : 0, log_id(module), log_id(cell), log_id(opts.port), opts.portbit);
687 SigBit inbit = module->addWire(NEW_ID);
688 SigBit outbit = one ? State::S1 : State::S0;
689 module->connect(bit, mutate_ctrl_mux(module, opts, inbit, outbit));
690 bit = inbit;
691 }
692
693 SigSpec s = cell->getPort(opts.port);
694 s[opts.portbit] = bit;
695 cell->setPort(opts.port, s);
696 }
697
698 void mutate_cnot(Design *design, const mutate_opts_t &opts, bool one)
699 {
700 Module *module = design->module(opts.module);
701 Cell *cell = module->cell(opts.cell);
702
703 SigBit bit = cell->getPort(opts.port)[opts.portbit];
704 SigBit ctrl = cell->getPort(opts.port)[opts.ctrlbit];
705 SigBit inbit, outbit;
706
707 if (cell->input(opts.port))
708 {
709 log("Add input cnot%d at %s.%s.%s[%d,%d].\n", one ? 1 : 0, log_id(module), log_id(cell), log_id(opts.port), opts.portbit, opts.ctrlbit);
710 SigBit outbit = one ? module->Xor(NEW_ID, bit, ctrl) : module->Xnor(NEW_ID, bit, ctrl);
711 bit = mutate_ctrl_mux(module, opts, bit, outbit);
712 }
713 else
714 {
715 log("Add output cnot%d at %s.%s.%s[%d,%d].\n", one ? 1 : 0, log_id(module), log_id(cell), log_id(opts.port), opts.portbit, opts.ctrlbit);
716 SigBit inbit = module->addWire(NEW_ID);
717 SigBit outbit = one ? module->Xor(NEW_ID, inbit, ctrl) : module->Xnor(NEW_ID, inbit, ctrl);
718 module->connect(bit, mutate_ctrl_mux(module, opts, inbit, outbit));
719 bit = inbit;
720 }
721
722 SigSpec s = cell->getPort(opts.port);
723 s[opts.portbit] = bit;
724 cell->setPort(opts.port, s);
725 }
726
727 struct MutatePass : public Pass {
728 MutatePass() : Pass("mutate", "generate or apply design mutations") { }
729 void help() override
730 {
731 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
732 log("\n");
733 log(" mutate -list N [options] [selection]\n");
734 log("\n");
735 log("Create a list of N mutations using an even sampling.\n");
736 log("\n");
737 log(" -o filename\n");
738 log(" Write list to this file instead of console output\n");
739 log("\n");
740 log(" -s filename\n");
741 log(" Write a list of all src tags found in the design to the specified file\n");
742 log("\n");
743 log(" -seed N\n");
744 log(" RNG seed for selecting mutations\n");
745 log("\n");
746 log(" -none\n");
747 log(" Include a \"none\" mutation in the output\n");
748 log("\n");
749 log(" -ctrl name width value\n");
750 log(" Add -ctrl options to the output. Use 'value' for first mutation, then\n");
751 log(" simply count up from there.\n");
752 log("\n");
753 log(" -mode name\n");
754 log(" -module name\n");
755 log(" -cell name\n");
756 log(" -port name\n");
757 log(" -portbit int\n");
758 log(" -ctrlbit int\n");
759 log(" -wire name\n");
760 log(" -wirebit int\n");
761 log(" -src string\n");
762 log(" Filter list of mutation candidates to those matching\n");
763 log(" the given parameters.\n");
764 log("\n");
765 log(" -cfg option int\n");
766 log(" Set a configuration option. Options available:\n");
767 log(" weight_pq_w weight_pq_b weight_pq_c weight_pq_s\n");
768 log(" weight_pq_mw weight_pq_mb weight_pq_mc weight_pq_ms\n");
769 log(" weight_cover pick_cover_prcnt\n");
770 log("\n");
771 log("\n");
772 log(" mutate -mode MODE [options]\n");
773 log("\n");
774 log("Apply the given mutation.\n");
775 log("\n");
776 log(" -ctrl name width value\n");
777 log(" Add a control signal with the given name and width. The mutation is\n");
778 log(" activated if the control signal equals the given value.\n");
779 log("\n");
780 log(" -module name\n");
781 log(" -cell name\n");
782 log(" -port name\n");
783 log(" -portbit int\n");
784 log(" -ctrlbit int\n");
785 log(" Mutation parameters, as generated by 'mutate -list N'.\n");
786 log("\n");
787 log(" -wire name\n");
788 log(" -wirebit int\n");
789 log(" -src string\n");
790 log(" Ignored. (They are generated by -list for documentation purposes.)\n");
791 log("\n");
792 }
793 void execute(std::vector<std::string> args, RTLIL::Design *design) override
794 {
795 mutate_opts_t opts;
796 string filename;
797 string srcsfile;
798 int N = -1;
799
800 log_header(design, "Executing MUTATE pass.\n");
801
802 size_t argidx;
803 for (argidx = 1; argidx < args.size(); argidx++)
804 {
805 if (args[argidx] == "-list" && argidx+1 < args.size()) {
806 N = atoi(args[++argidx].c_str());
807 continue;
808 }
809 if (args[argidx] == "-o" && argidx+1 < args.size()) {
810 filename = args[++argidx];
811 continue;
812 }
813 if (args[argidx] == "-s" && argidx+1 < args.size()) {
814 srcsfile = args[++argidx];
815 continue;
816 }
817 if (args[argidx] == "-seed" && argidx+1 < args.size()) {
818 opts.seed = atoi(args[++argidx].c_str());
819 continue;
820 }
821 if (args[argidx] == "-none") {
822 opts.none = true;
823 continue;
824 }
825 if (args[argidx] == "-mode" && argidx+1 < args.size()) {
826 opts.mode = args[++argidx];
827 continue;
828 }
829 if (args[argidx] == "-ctrl" && argidx+3 < args.size()) {
830 opts.ctrl_name = RTLIL::escape_id(args[++argidx]);
831 opts.ctrl_width = atoi(args[++argidx].c_str());
832 opts.ctrl_value = atoi(args[++argidx].c_str());
833 continue;
834 }
835 if (args[argidx] == "-module" && argidx+1 < args.size()) {
836 opts.module = RTLIL::escape_id(args[++argidx]);
837 continue;
838 }
839 if (args[argidx] == "-cell" && argidx+1 < args.size()) {
840 opts.cell = RTLIL::escape_id(args[++argidx]);
841 continue;
842 }
843 if (args[argidx] == "-port" && argidx+1 < args.size()) {
844 opts.port = RTLIL::escape_id(args[++argidx]);
845 continue;
846 }
847 if (args[argidx] == "-portbit" && argidx+1 < args.size()) {
848 opts.portbit = atoi(args[++argidx].c_str());
849 continue;
850 }
851 if (args[argidx] == "-ctrlbit" && argidx+1 < args.size()) {
852 opts.ctrlbit = atoi(args[++argidx].c_str());
853 continue;
854 }
855 if (args[argidx] == "-wire" && argidx+1 < args.size()) {
856 opts.wire = RTLIL::escape_id(args[++argidx]);
857 continue;
858 }
859 if (args[argidx] == "-wirebit" && argidx+1 < args.size()) {
860 opts.wirebit = atoi(args[++argidx].c_str());
861 continue;
862 }
863 if (args[argidx] == "-src" && argidx+1 < args.size()) {
864 opts.src.insert(args[++argidx]);
865 continue;
866 }
867 if (args[argidx] == "-cfg" && argidx+2 < args.size()) {
868 if (args[argidx+1] == "pick_cover_prcnt") {
869 opts.pick_cover_prcnt = atoi(args[argidx+2].c_str());
870 argidx += 2;
871 continue;
872 }
873 if (args[argidx+1] == "weight_cover") {
874 opts.weight_cover = atoi(args[argidx+2].c_str());
875 argidx += 2;
876 continue;
877 }
878 if (args[argidx+1] == "weight_pq_w") {
879 opts.weight_pq_w = atoi(args[argidx+2].c_str());
880 argidx += 2;
881 continue;
882 }
883 if (args[argidx+1] == "weight_pq_b") {
884 opts.weight_pq_b = atoi(args[argidx+2].c_str());
885 argidx += 2;
886 continue;
887 }
888 if (args[argidx+1] == "weight_pq_c") {
889 opts.weight_pq_c = atoi(args[argidx+2].c_str());
890 argidx += 2;
891 continue;
892 }
893 if (args[argidx+1] == "weight_pq_s") {
894 opts.weight_pq_s = atoi(args[argidx+2].c_str());
895 argidx += 2;
896 continue;
897 }
898 if (args[argidx+1] == "weight_pq_mw") {
899 opts.weight_pq_mw = atoi(args[argidx+2].c_str());
900 argidx += 2;
901 continue;
902 }
903 if (args[argidx+1] == "weight_pq_mb") {
904 opts.weight_pq_mb = atoi(args[argidx+2].c_str());
905 argidx += 2;
906 continue;
907 }
908 if (args[argidx+1] == "weight_pq_mc") {
909 opts.weight_pq_mc = atoi(args[argidx+2].c_str());
910 argidx += 2;
911 continue;
912 }
913 if (args[argidx+1] == "weight_pq_ms") {
914 opts.weight_pq_ms = atoi(args[argidx+2].c_str());
915 argidx += 2;
916 continue;
917 }
918 }
919 break;
920 }
921 extra_args(args, argidx, design);
922
923 if (N >= 0) {
924 mutate_list(design, opts, filename, srcsfile, N);
925 return;
926 }
927
928 if (opts.mode == "none") {
929 if (!opts.ctrl_name.empty()) {
930 Module *topmod = opts.module.empty() ? design->top_module() : design->module(opts.module);
931 if (topmod)
932 mutate_ctrl_sig(topmod, opts.ctrl_name, opts.ctrl_width);
933 }
934 return;
935 }
936
937 if (opts.module.empty())
938 log_cmd_error("Missing -module argument.\n");
939
940 Module *module = design->module(opts.module);
941 if (module == nullptr)
942 log_cmd_error("Module %s not found.\n", log_id(opts.module));
943
944 if (opts.cell.empty())
945 log_cmd_error("Missing -cell argument.\n");
946
947 Cell *cell = module->cell(opts.cell);
948 if (cell == nullptr)
949 log_cmd_error("Cell %s not found in module %s.\n", log_id(opts.cell), log_id(opts.module));
950
951 if (opts.port.empty())
952 log_cmd_error("Missing -port argument.\n");
953
954 if (!cell->hasPort(opts.port))
955 log_cmd_error("Port %s not found on cell %s.%s.\n", log_id(opts.port), log_id(opts.module), log_id(opts.cell));
956
957 if (opts.portbit < 0)
958 log_cmd_error("Missing -portbit argument.\n");
959
960 if (GetSize(cell->getPort(opts.port)) <= opts.portbit)
961 log_cmd_error("Out-of-range -portbit argument for port %s on cell %s.%s.\n", log_id(opts.port), log_id(opts.module), log_id(opts.cell));
962
963 if (opts.mode == "inv") {
964 mutate_inv(design, opts);
965 return;
966 }
967
968 if (opts.mode == "const0" || opts.mode == "const1") {
969 mutate_const(design, opts, opts.mode == "const1");
970 return;
971 }
972
973 if (opts.ctrlbit < 0)
974 log_cmd_error("Missing -ctrlbit argument.\n");
975
976 if (GetSize(cell->getPort(opts.port)) <= opts.ctrlbit)
977 log_cmd_error("Out-of-range -ctrlbit argument for port %s on cell %s.%s.\n", log_id(opts.port), log_id(opts.module), log_id(opts.cell));
978
979 if (opts.mode == "cnot0" || opts.mode == "cnot1") {
980 mutate_cnot(design, opts, opts.mode == "cnot1");
981 return;
982 }
983
984 log_cmd_error("Invalid mode: %s\n", opts.mode.c_str());
985 }
986 } MutatePass;
987
988 PRIVATE_NAMESPACE_END