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 "kernel/sigtools.h"
24 PRIVATE_NAMESPACE_BEGIN
29 IdString module
, cell
;
37 struct mutate_opts_t
{
41 IdString module
, cell
, port
, wire
;
47 int ctrl_width
= -1, ctrl_value
= -1;
51 int pick_cover_prcnt
= 80;
53 int weight_cover
= 500;
55 int weight_pq_w
= 100;
56 int weight_pq_b
= 100;
57 int weight_pq_c
= 100;
58 int weight_pq_s
= 100;
60 int weight_pq_mw
= 100;
61 int weight_pq_mb
= 100;
62 int weight_pq_mc
= 100;
63 int weight_pq_ms
= 100;
66 void database_add(std::vector
<mutate_t
> &database
, const mutate_opts_t
&opts
, const mutate_t
&entry
)
68 if (!opts
.mode
.empty() && opts
.mode
!= entry
.mode
)
71 if (!opts
.src
.empty()) {
72 bool found_match
= false;
73 for (auto &s
: opts
.src
) {
74 if (entry
.src
.count(s
))
81 if (!opts
.module
.empty() && opts
.module
!= entry
.module
)
84 if (!opts
.cell
.empty() && opts
.cell
!= entry
.cell
)
87 if (!opts
.port
.empty() && opts
.port
!= entry
.port
)
90 if (opts
.portbit
>= 0 && opts
.portbit
!= entry
.portbit
)
93 if (opts
.ctrlbit
>= 0 && opts
.ctrlbit
!= entry
.ctrlbit
)
96 if (!opts
.wire
.empty() && opts
.wire
!= entry
.wire
)
99 if (opts
.wirebit
>= 0 && opts
.wirebit
!= entry
.wirebit
)
102 database
.push_back(entry
);
107 uint32_t x
= 123456789;
108 uint32_t y
= 0, z
= 0, w
= 0;
110 xs128_t(int seed
= 0) : w(seed
) {
117 uint32_t t
= x
^ (x
<< 11);
119 w
^= (w
>> 19) ^ t
^ (t
>> 8);
124 return w
& 0x3fffffff;
127 int operator()(int n
) {
131 int k
= (*this)(), p
= k
% n
;
132 if ((k
- p
+ n
) <= 0x40000000)
140 dict
<string
, int> src_db
;
141 dict
<tuple
<IdString
, IdString
>, int> wire_db
;
142 dict
<tuple
<IdString
, IdString
, int>, int> wirebit_db
;
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;
149 for (auto &s
: m
.src
) {
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
))++;
159 for (auto &s
: m
.src
) {
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;
170 for (auto &s
: m
.src
) {
171 this_score
+= src_db
.at(s
) ? 0 : 5;
177 struct mutate_queue_t
179 pool
<mutate_t
*, hash_ptr_ops
> db
;
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
;
188 rmqueue
.push_back(p
);
191 int this_score
= coverdb
.score(*p
);
192 if (this_score
> best_score
) {
193 best_score
= this_score
;
196 if (best_score
== this_score
)
197 candidates
.push_back(p
);
199 for (auto p
: rmqueue
)
201 if (!candidates
.empty())
202 m
= candidates
[rng(GetSize(candidates
))];
205 while (!db
.empty()) {
206 int i
= rng(GetSize(db
));
207 auto it
= db
.element(i
);
210 if (p
->used
== false) {
219 void add(mutate_t
*m
) {
224 template <typename K
, typename T
>
225 struct mutate_chain_queue_t
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
);
241 template<typename
... Args
>
242 void add(mutate_t
*m
, K key
, Args
... args
) {
243 db
[key
].add(m
, args
...);
247 template <typename K
, typename T
>
248 struct mutate_once_queue_t
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
);
264 template<typename
... Args
>
265 void add(mutate_t
*m
, K key
, Args
... args
) {
266 db
[key
].add(m
, args
...);
270 void database_reduce(std::vector
<mutate_t
> &database
, const mutate_opts_t
&opts
, int N
, xs128_t
&rng
)
272 std::vector
<mutate_t
> new_database
;
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
;
278 if (N
>= GetSize(database
))
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
;
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
;
291 for (auto &m
: database
)
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
));
302 primary_queue_cell
.add(&m
, tuple
<IdString
, IdString
>(m
.module
, m
.cell
));
303 primary_queue_module_cell
.add(&m
, m
.module
, m
.cell
);
305 for (auto &s
: m
.src
) {
306 primary_queue_src
.add(&m
, s
);
307 primary_queue_module_src
.add(&m
, m
.module
, s
);
311 vector
<mutate_t
*> cover_candidates
;
312 int best_cover_score
= -1;
313 bool skip_cover
= false;
315 while (GetSize(new_database
) < N
)
317 int k
= rng(total_weight
);
319 k
-= opts
.weight_cover
;
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())
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
);
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
;
337 if (best_cover_score
== this_score
)
338 cover_candidates
.push_back(&m
);
340 if (best_cover_score
== -1) {
346 mutate_t
*m
= nullptr;
347 while (!cover_candidates
.empty())
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();
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
);
363 if (this_score
!= best_cover_score
)
373 new_database
.push_back(*m
);
380 #define X(__wght, __queue) \
383 mutate_t *m = __queue.pick(rng, coverdb, opts); \
384 if (m != nullptr) { \
386 coverdb.update(*m); \
387 new_database.push_back(*m); \
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
)
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
)
404 std::swap(new_database
, database
);
406 int covered_src_cnt
= 0;
407 int covered_wire_cnt
= 0;
408 int covered_wirebit_cnt
= 0;
410 for (auto &it
: coverdb
.src_db
)
414 for (auto &it
: coverdb
.wire_db
)
418 for (auto &it
: coverdb
.wirebit_db
)
420 covered_wirebit_cnt
++;
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
));
427 void mutate_list(Design
*design
, const mutate_opts_t
&opts
, const string
&filename
, const string
&srcsfile
, int N
)
429 pool
<string
> sources
;
430 std::vector
<mutate_t
> database
;
431 xs128_t
rng(opts
.seed
);
433 for (auto module
: design
->selected_modules())
435 if (!opts
.module
.empty() && module
->name
!= opts
.module
)
438 SigMap
sigmap(module
);
439 dict
<SigBit
, int> bit_user_cnt
;
441 for (auto wire
: module
->wires()) {
442 if (wire
->name
[0] == '\\' && wire
->attributes
.count("\\src"))
446 for (auto cell
: module
->cells()) {
447 for (auto &conn
: cell
->connections()) {
448 if (cell
->output(conn
.first
))
450 for (auto bit
: sigmap(conn
.second
))
455 for (auto wire
: module
->selected_wires())
457 for (SigBit bit
: SigSpec(wire
))
459 SigBit sigbit
= sigmap(bit
);
461 if (bit
.wire
== nullptr || sigbit
.wire
== nullptr)
464 if (!bit
.wire
->port_id
!= !sigbit
.wire
->port_id
) {
465 if (bit
.wire
->port_id
)
470 if (!bit
.wire
->name
[0] != !sigbit
.wire
->name
[0]) {
471 if (bit
.wire
->name
[0] == '\\')
478 for (auto cell
: module
->selected_cells())
480 if (!opts
.cell
.empty() && cell
->name
!= opts
.cell
)
483 for (auto &conn
: cell
->connections())
485 for (int i
= 0; i
< GetSize(conn
.second
); i
++) {
487 entry
.module
= module
->name
;
488 entry
.cell
= cell
->name
;
489 entry
.port
= conn
.first
;
492 for (auto &s
: cell
->get_strpool_attribute("\\src"))
495 SigBit bit
= sigmap(conn
.second
[i
]);
496 if (bit
.wire
&& bit
.wire
->name
[0] == '\\' && (cell
->output(conn
.first
) || bit_user_cnt
[bit
] == 1)) {
497 for (auto &s
: bit
.wire
->get_strpool_attribute("\\src"))
499 entry
.wire
= bit
.wire
->name
;
500 entry
.wirebit
= bit
.offset
;
503 if (!srcsfile
.empty())
504 sources
.insert(entry
.src
.begin(), entry
.src
.end());
507 database_add(database
, opts
, entry
);
509 entry
.mode
= "const0";
510 database_add(database
, opts
, entry
);
512 entry
.mode
= "const1";
513 database_add(database
, opts
, entry
);
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
);
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
);
529 log("Raw database size: %d\n", GetSize(database
));
531 database_reduce(database
, opts
, opts
.none
? N
-1 : N
, rng
);
532 log("Reduced database size: %d\n", GetSize(database
));
535 if (!srcsfile
.empty()) {
537 sout
.open(srcsfile
, std::ios::out
| std::ios::trunc
);
539 log_error("Could not open file \"%s\" with write access.\n", srcsfile
.c_str());
541 for (auto &s
: sources
)
542 sout
<< s
<< std::endl
;
547 if (!filename
.empty()) {
548 fout
.open(filename
, std::ios::out
| std::ios::trunc
);
550 log_error("Could not open file \"%s\" with write access.\n", filename
.c_str());
553 int ctrl_value
= opts
.ctrl_value
;
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());
563 fout
<< str
<< std::endl
;
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());
590 fout
<< str
<< std::endl
;
594 SigSpec
mutate_ctrl_sig(Module
*module
, IdString name
, int width
)
596 Wire
*ctrl_wire
= module
->wire(name
);
598 if (ctrl_wire
== nullptr)
600 log("Adding ctrl port %s to module %s.\n", log_id(name
), log_id(module
));
602 ctrl_wire
= module
->addWire(name
, width
);
603 ctrl_wire
->port_input
= true;
604 module
->fixup_ports();
606 for (auto mod
: module
->design
->modules())
607 for (auto cell
: mod
->cells())
609 if (cell
->type
!= module
->name
)
612 SigSpec ctrl
= mutate_ctrl_sig(mod
, name
, width
);
614 log("Connecting ctrl port to cell %s in module %s.\n", log_id(cell
), log_id(mod
));
615 cell
->setPort(name
, ctrl
);
619 log_assert(GetSize(ctrl_wire
) == width
);
623 SigBit
mutate_ctrl(Module
*module
, const mutate_opts_t
&opts
)
625 if (opts
.ctrl_name
.empty())
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
)));
632 SigSpec
mutate_ctrl_mux(Module
*module
, const mutate_opts_t
&opts
, SigSpec unchanged_sig
, SigSpec changed_sig
)
634 SigBit ctrl_bit
= mutate_ctrl(module
, opts
);
635 if (ctrl_bit
== State::S0
)
636 return unchanged_sig
;
637 if (ctrl_bit
== State::S1
)
639 return module
->Mux(NEW_ID
, unchanged_sig
, changed_sig
, ctrl_bit
);
642 void mutate_inv(Design
*design
, const mutate_opts_t
&opts
)
644 Module
*module
= design
->module(opts
.module
);
645 Cell
*cell
= module
->cell(opts
.cell
);
647 SigBit bit
= cell
->getPort(opts
.port
)[opts
.portbit
];
648 SigBit inbit
, outbit
;
650 if (cell
->input(opts
.port
))
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
);
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
));
665 SigSpec s
= cell
->getPort(opts
.port
);
666 s
[opts
.portbit
] = bit
;
667 cell
->setPort(opts
.port
, s
);
670 void mutate_const(Design
*design
, const mutate_opts_t
&opts
, bool one
)
672 Module
*module
= design
->module(opts
.module
);
673 Cell
*cell
= module
->cell(opts
.cell
);
675 SigBit bit
= cell
->getPort(opts
.port
)[opts
.portbit
];
676 SigBit inbit
, outbit
;
678 if (cell
->input(opts
.port
))
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
);
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
));
693 SigSpec s
= cell
->getPort(opts
.port
);
694 s
[opts
.portbit
] = bit
;
695 cell
->setPort(opts
.port
, s
);
698 void mutate_cnot(Design
*design
, const mutate_opts_t
&opts
, bool one
)
700 Module
*module
= design
->module(opts
.module
);
701 Cell
*cell
= module
->cell(opts
.cell
);
703 SigBit bit
= cell
->getPort(opts
.port
)[opts
.portbit
];
704 SigBit ctrl
= cell
->getPort(opts
.port
)[opts
.ctrlbit
];
705 SigBit inbit
, outbit
;
707 if (cell
->input(opts
.port
))
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
);
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
));
722 SigSpec s
= cell
->getPort(opts
.port
);
723 s
[opts
.portbit
] = bit
;
724 cell
->setPort(opts
.port
, s
);
727 struct MutatePass
: public Pass
{
728 MutatePass() : Pass("mutate", "generate or apply design mutations") { }
729 void help() YS_OVERRIDE
731 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
733 log(" mutate -list N [options] [selection]\n");
735 log("Create a list of N mutations using an even sampling.\n");
737 log(" -o filename\n");
738 log(" Write list to this file instead of console output\n");
740 log(" -s filename\n");
741 log(" Write a list of all src tags found in the design to the specified file\n");
744 log(" RNG seed for selecting mutations\n");
747 log(" Include a \"none\" mutation in the output\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");
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");
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");
772 log(" mutate -mode MODE [options]\n");
774 log("Apply the given mutation.\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");
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");
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");
793 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
800 log_header(design
, "Executing MUTATE pass.\n");
803 for (argidx
= 1; argidx
< args
.size(); argidx
++)
805 if (args
[argidx
] == "-list" && argidx
+1 < args
.size()) {
806 N
= atoi(args
[++argidx
].c_str());
809 if (args
[argidx
] == "-o" && argidx
+1 < args
.size()) {
810 filename
= args
[++argidx
];
813 if (args
[argidx
] == "-s" && argidx
+1 < args
.size()) {
814 srcsfile
= args
[++argidx
];
817 if (args
[argidx
] == "-seed" && argidx
+1 < args
.size()) {
818 opts
.seed
= atoi(args
[++argidx
].c_str());
821 if (args
[argidx
] == "-none") {
825 if (args
[argidx
] == "-mode" && argidx
+1 < args
.size()) {
826 opts
.mode
= args
[++argidx
];
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());
835 if (args
[argidx
] == "-module" && argidx
+1 < args
.size()) {
836 opts
.module
= RTLIL::escape_id(args
[++argidx
]);
839 if (args
[argidx
] == "-cell" && argidx
+1 < args
.size()) {
840 opts
.cell
= RTLIL::escape_id(args
[++argidx
]);
843 if (args
[argidx
] == "-port" && argidx
+1 < args
.size()) {
844 opts
.port
= RTLIL::escape_id(args
[++argidx
]);
847 if (args
[argidx
] == "-portbit" && argidx
+1 < args
.size()) {
848 opts
.portbit
= atoi(args
[++argidx
].c_str());
851 if (args
[argidx
] == "-ctrlbit" && argidx
+1 < args
.size()) {
852 opts
.ctrlbit
= atoi(args
[++argidx
].c_str());
855 if (args
[argidx
] == "-wire" && argidx
+1 < args
.size()) {
856 opts
.wire
= RTLIL::escape_id(args
[++argidx
]);
859 if (args
[argidx
] == "-wirebit" && argidx
+1 < args
.size()) {
860 opts
.wirebit
= atoi(args
[++argidx
].c_str());
863 if (args
[argidx
] == "-src" && argidx
+1 < args
.size()) {
864 opts
.src
.insert(args
[++argidx
]);
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());
873 if (args
[argidx
+1] == "weight_cover") {
874 opts
.weight_cover
= atoi(args
[argidx
+2].c_str());
878 if (args
[argidx
+1] == "weight_pq_w") {
879 opts
.weight_pq_w
= atoi(args
[argidx
+2].c_str());
883 if (args
[argidx
+1] == "weight_pq_b") {
884 opts
.weight_pq_b
= atoi(args
[argidx
+2].c_str());
888 if (args
[argidx
+1] == "weight_pq_c") {
889 opts
.weight_pq_c
= atoi(args
[argidx
+2].c_str());
893 if (args
[argidx
+1] == "weight_pq_s") {
894 opts
.weight_pq_s
= atoi(args
[argidx
+2].c_str());
898 if (args
[argidx
+1] == "weight_pq_mw") {
899 opts
.weight_pq_mw
= atoi(args
[argidx
+2].c_str());
903 if (args
[argidx
+1] == "weight_pq_mb") {
904 opts
.weight_pq_mb
= atoi(args
[argidx
+2].c_str());
908 if (args
[argidx
+1] == "weight_pq_mc") {
909 opts
.weight_pq_mc
= atoi(args
[argidx
+2].c_str());
913 if (args
[argidx
+1] == "weight_pq_ms") {
914 opts
.weight_pq_ms
= atoi(args
[argidx
+2].c_str());
921 extra_args(args
, argidx
, design
);
924 mutate_list(design
, opts
, filename
, srcsfile
, N
);
928 if (opts
.mode
== "none") {
929 if (!opts
.ctrl_name
.empty()) {
930 Module
*topmod
= opts
.module
.empty() ? design
->top_module() : design
->module(opts
.module
);
932 mutate_ctrl_sig(topmod
, opts
.ctrl_name
, opts
.ctrl_width
);
937 if (opts
.module
.empty())
938 log_cmd_error("Missing -module argument.\n");
940 Module
*module
= design
->module(opts
.module
);
941 if (module
== nullptr)
942 log_cmd_error("Module %s not found.\n", log_id(opts
.module
));
944 if (opts
.cell
.empty())
945 log_cmd_error("Missing -cell argument.\n");
947 Cell
*cell
= module
->cell(opts
.cell
);
949 log_cmd_error("Cell %s not found in module %s.\n", log_id(opts
.cell
), log_id(opts
.module
));
951 if (opts
.port
.empty())
952 log_cmd_error("Missing -port argument.\n");
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
));
957 if (opts
.portbit
< 0)
958 log_cmd_error("Missing -portbit argument.\n");
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
));
963 if (opts
.mode
== "inv") {
964 mutate_inv(design
, opts
);
968 if (opts
.mode
== "const0" || opts
.mode
== "const1") {
969 mutate_const(design
, opts
, opts
.mode
== "const1");
973 if (opts
.ctrlbit
< 0)
974 log_cmd_error("Missing -ctrlbit argument.\n");
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
));
979 if (opts
.mode
== "cnot0" || opts
.mode
== "cnot1") {
980 mutate_cnot(design
, opts
, opts
.mode
== "cnot1");
984 log_cmd_error("Invalid mode: %s\n", opts
.mode
.c_str());
988 PRIVATE_NAMESPACE_END