ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
rrrSimulator.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <random>
5#include <bitset>
6
7#include "rrrParameter.h"
8#include "rrrUtils.h"
9
11
12namespace rrr {
13
14 template <typename Ntk>
15 class Simulator {
16 private:
17 // aliases
18 using word = unsigned long long;
19 using itr = std::vector<word>::iterator;
20 using citr = std::vector<word>::const_iterator;
21 static constexpr word one = 0xffffffffffffffff;
22 static constexpr bool fKeepStimula = true;
23
24 // pointer to network
25 Ntk *pNtk;
26
27 // parameters
28 int nVerbose;
29 int nWords;
30
31 // data
32 bool fGenerated;
33 bool fInitialized;
34 int target; // node for which the careset has been computed
35 std::vector<word> vValues;
36 std::vector<word> vValues2; // simulation with an inverter
37 std::vector<word> care; // careset
38 std::vector<word> tmp;
39
40 // partial cex
41 int iPivot;
42 std::vector<word> vAssignedStimuli;
43
44 // updates
45 bool fUpdate;
46 std::set<int> sUpdates;
47
48 // backups
49 std::vector<Simulator> vBackups;
50
51 // stats
52 int nCex;
53 int nDiscarded;
54 int nPackedCountOld;
55 std::vector<int> vPackedCount;
56 std::vector<int> vPackedCountEvicted;
57 double durationSimulation;
58 double durationCare;
59
60 // vector computations
61 void Clear(int n, itr x) const;
62 void Fill(int n, itr x) const;
63 void Copy(int n, itr dst, citr src, bool c) const;
64 void And(int n, itr dst, citr src0, citr src1, bool c0, bool c1) const;
65 void Xor(int n, itr dst, citr src0, citr src1, bool c) const;
66 bool IsZero(int n, citr x) const;
67 bool IsEq(int n, citr x, citr y) const;
68 void Print(int n, citr x) const;
69
70 // callback
71 void ActionCallback(Action const &action);
72
73 // simulation
74 void SimulateNode(std::vector<word> &v, int id, int to_negate = -1);
75 bool ResimulateNode(std::vector<word> &v, int id, int to_negate = -1);
76 void SimulateOneWordNode(std::vector<word> &v, int id, int offset, int to_negate = -1);
77 void Simulate();
78 void Resimulate();
79 void SimulateOneWord(int offset);
80
81 // generate stimuli
82 void GenerateRandomStimuli();
83
84 // careset computation
85 void ComputeCare(int id);
86
87 // preparation
88 void Initialize();
89
90 // save & load
91 void Save(int slot);
92 void Load(int slot);
93
94 public:
95 // constructors
96 Simulator();
97 Simulator(Parameter const *pPar);
98 void AssignNetwork(Ntk *pNtk_, bool fReuse);
99
100 // checks
101 bool CheckRedundancy(int id, int idx);
102 bool CheckFeasibility(int id, int fi, bool c);
103
104 // cex
105 void AddCex(std::vector<VarValue> const &vCex);
106
107 // summary
108 void ResetSummary();
111 };
112
113
114 /* {{{ Vector computations */
115
116 template <typename Ntk>
117 inline void Simulator<Ntk>::Clear(int n, itr x) const {
118 std::fill(x, x + n, 0);
119 }
120
121 template <typename Ntk>
122 inline void Simulator<Ntk>::Fill(int n, itr x) const {
123 std::fill(x, x + n, one);
124 }
125
126 template <typename Ntk>
127 inline void Simulator<Ntk>::Copy(int n, itr dst, citr src, bool c) const {
128 if(!c) {
129 for(int i = 0; i < n; i++, dst++, src++) {
130 *dst = *src;
131 }
132 } else {
133 for(int i = 0; i < n; i++, dst++, src++) {
134 *dst = ~*src;
135 }
136 }
137 }
138
139 template <typename Ntk>
140 inline void Simulator<Ntk>::And(int n, itr dst, citr src0, citr src1, bool c0, bool c1) const {
141 if(!c0) {
142 if(!c1) {
143 for(int i = 0; i < n; i++, dst++, src0++, src1++) {
144 *dst = *src0 & *src1;
145 }
146 } else {
147 for(int i = 0; i < n; i++, dst++, src0++, src1++) {
148 *dst = *src0 & ~*src1;
149 }
150 }
151 } else {
152 if(!c1) {
153 for(int i = 0; i < n; i++, dst++, src0++, src1++) {
154 *dst = ~*src0 & *src1;
155 }
156 } else {
157 for(int i = 0; i < n; i++, dst++, src0++, src1++) {
158 *dst = ~*src0 & ~*src1;
159 }
160 }
161 }
162 }
163
164 template <typename Ntk>
165 inline void Simulator<Ntk>::Xor(int n, itr dst, citr src0, citr src1, bool c) const {
166 if(!c) {
167 for(int i = 0; i < n; i++, dst++, src0++, src1++) {
168 *dst = *src0 ^ *src1;
169 }
170 } else {
171 for(int i = 0; i < n; i++, dst++, src0++, src1++) {
172 *dst = *src0 ^ ~*src1;
173 }
174 }
175 }
176
177 template <typename Ntk>
178 inline bool Simulator<Ntk>::IsZero(int n, citr x) const {
179 for(int i = 0; i < n; i++, x++) {
180 if(*x) {
181 return false;
182 }
183 }
184 return true;
185 }
186
187 template <typename Ntk>
188 inline bool Simulator<Ntk>::IsEq(int n, citr x, citr y) const {
189 for(int i = 0; i < n; i++, x++, y++) {
190 if(*x != *y) {
191 return false;
192 }
193 }
194 return true;
195 }
196
197 template <typename Ntk>
198 inline void Simulator<Ntk>::Print(int n, citr x) const {
199 std::cout << std::bitset<64>(*x);
200 x++;
201 for(int i = 1; i < n; i++, x++) {
202 std::cout << std::endl << std::string(10, ' ') << std::bitset<64>(*x);
203 }
204 }
205
206 /* }}} */
207
208 /* {{{ Callback */
209
210 template <typename Ntk>
211 void Simulator<Ntk>::ActionCallback(Action const &action) {
212 switch(action.type) {
213 case REMOVE_FANIN:
214 assert(fInitialized);
215 if(target != -1) {
216 if(action.id == target) {
217 fUpdate = true;
218 } else {
219 sUpdates.insert(action.id);
220 }
221 }
222 break;
223 case REMOVE_UNUSED:
224 break;
225 case REMOVE_BUFFER:
226 case REMOVE_CONST:
227 if(fInitialized) {
228 if(target != -1) {
229 if(action.id == target) {
230 if(fUpdate) {
231 for(int fo: action.vFanouts) {
232 sUpdates.insert(fo);
233 }
234 fUpdate = false;
235 }
236 target = -1;
237 } else {
238 if(sUpdates.count(action.id)) {
239 sUpdates.erase(action.id);
240 for(int fo: action.vFanouts) {
241 sUpdates.insert(fo);
242 }
243 }
244 }
245 }
246 }
247 break;
248 case ADD_FANIN:
249 assert(fInitialized);
250 if(target != -1) {
251 if(action.id == target) {
252 fUpdate = true;
253 } else {
254 sUpdates.insert(action.id);
255 }
256 }
257 break;
258 case TRIVIAL_COLLAPSE:
259 break;
261 if(fInitialized) {
262 if(target != -1) {
263 vValues.resize(nWords * pNtk->GetNumNodes());
264 SimulateNode(vValues, action.fi);
265 // time of this simulation is not measured for simplicity sake
266 }
267 }
268 break;
269 case SORT_FANINS:
270 break;
271 case READ:
272 fInitialized = false;
273 if(action.fNew) {
274 fGenerated = false;
275 }
276 break;
277 case SAVE:
278 Save(action.idx);
279 break;
280 case LOAD:
281 Load(action.idx);
282 break;
283 case POP_BACK:
284 // Do nothing: it may be good to keep the word vector allocated
285 break;
286 default:
287 assert(0);
288 }
289 }
290
291 /* }}} */
292
293 /* {{{ Simulation */
294
295 template <typename Ntk>
296 void Simulator<Ntk>::SimulateNode(std::vector<word> &v, int id, int to_negate) {
297 itr x = v.end();
298 itr y = v.begin() + id * nWords;
299 bool cx = false;
300 switch(pNtk->GetNodeType(id)) {
301 case AND:
302 pNtk->ForEachFanin(id, [&](int fi, bool c) {
303 if(x == v.end()) {
304 x = v.begin() + fi * nWords;
305 cx = c ^ (fi == to_negate);
306 } else {
307 And(nWords, y, x, v.begin() + fi * nWords, cx, c ^ (fi == to_negate));
308 x = y;
309 cx = false;
310 }
311 });
312 if(x == v.end()) {
313 Fill(nWords, y);
314 }
315 break;
316 default:
317 assert(0);
318 }
319 }
320
321 template <typename Ntk>
322 bool Simulator<Ntk>::ResimulateNode(std::vector<word> &v, int id, int to_negate) {
323 itr x = v.end();
324 bool cx = false;
325 switch(pNtk->GetNodeType(id)) {
326 case AND:
327 pNtk->ForEachFanin(id, [&](int fi, bool c) {
328 if(x == v.end()) {
329 x = v.begin() + fi * nWords;
330 cx = c ^ (fi == to_negate);
331 } else {
332 And(nWords, tmp.begin(), x, v.begin() + fi * nWords, cx, c ^ (fi == to_negate));
333 x = tmp.begin();
334 cx = false;
335 }
336 });
337 if(x == v.end()) {
338 Fill(nWords, tmp.begin());
339 }
340 break;
341 default:
342 assert(0);
343 }
344 itr y = v.begin() + id * nWords;
345 if(IsEq(nWords, y, tmp.begin())) {
346 return false;
347 }
348 Copy(nWords, y, tmp.begin(), false);
349 return true;
350 }
351
352 template <typename Ntk>
353 void Simulator<Ntk>::SimulateOneWordNode(std::vector<word> &v, int id, int offset, int to_negate) {
354 itr x = v.end();
355 itr y = v.begin() + id * nWords + offset;
356 bool cx = false;
357 switch(pNtk->GetNodeType(id)) {
358 case AND:
359 pNtk->ForEachFanin(id, [&](int fi, bool c) {
360 if(x == v.end()) {
361 x = v.begin() + fi * nWords + offset;
362 cx = c ^ (fi == to_negate);
363 } else {
364 And(1, y, x, v.begin() + fi * nWords + offset, cx, c ^ (fi == to_negate));
365 x = y;
366 cx = false;
367 }
368 });
369 if(x == v.end()) {
370 Fill(1, y);
371 }
372 break;
373 default:
374 assert(0);
375 }
376 }
377
378 template <typename Ntk>
379 void Simulator<Ntk>::Simulate() {
380 time_point timeStart = GetCurrentTime();
381 if(nVerbose) {
382 std::cout << "simulating" << std::endl;
383 }
384 pNtk->ForEachInt([&](int id) {
385 SimulateNode(vValues, id);
386 if(nVerbose) {
387 std::cout << "node " << std::setw(3) << id << ": ";
388 Print(nWords, vValues.begin() + id * nWords);
389 std::cout << std::endl;
390 }
391 });
392 durationSimulation += Duration(timeStart, GetCurrentTime());
393 }
394
395 template <typename Ntk>
396 void Simulator<Ntk>::Resimulate() {
397 time_point timeStart = GetCurrentTime();
398 if(nVerbose) {
399 std::cout << "resimulating" << std::endl;
400 }
401 pNtk->ForEachTfosUpdate(sUpdates, false, [&](int fo) {
402 bool fUpdated = ResimulateNode(vValues, fo);
403 if(nVerbose) {
404 std::cout << "node " << std::setw(3) << fo << ": ";
405 Print(nWords, vValues.begin() + fo * nWords);
406 std::cout << std::endl;
407 }
408 return fUpdated;
409 });
410 /* alternative version that updates entire TFO
411 pNtk->ForEachTfos(sUpdates, false, [&](int fo) {
412 SimulateNode(vValues, fo);
413 if(nVerbose) {
414 std::cout << "node " << std::setw(3) << fo << ": ";
415 Print(nWords, vValues.begin() + fo * nWords);
416 std::cout << std::endl;
417 }
418 });
419 */
420 durationSimulation += Duration(timeStart, GetCurrentTime());
421 }
422
423 template <typename Ntk>
424 void Simulator<Ntk>::SimulateOneWord(int offset) {
425 time_point timeStart = GetCurrentTime();
426 if(nVerbose) {
427 std::cout << "simulating word " << offset << std::endl;
428 }
429 pNtk->ForEachInt([&](int id) {
430 SimulateOneWordNode(vValues, id, offset);
431 if(nVerbose) {
432 std::cout << "node " << std::setw(3) << id << ": ";
433 Print(1, vValues.begin() + id * nWords + offset);
434 std::cout << std::endl;
435 }
436 });
437 durationSimulation += Duration(timeStart, GetCurrentTime());
438 }
439
440 /* }}} */
441
442 /* {{{ Generate stimuli */
443
444 template <typename Ntk>
445 void Simulator<Ntk>::GenerateRandomStimuli() {
446 if(nVerbose) {
447 std::cout << "generating random stimuli" << std::endl;
448 }
449 std::mt19937_64 rng;
450 pNtk->ForEachPi([&](int id) {
451 for(int i = 0; i < nWords; i++) {
452 vValues[id * nWords + i] = rng();
453 }
454 if(nVerbose) {
455 std::cout << "node " << std::setw(3) << id << ": ";
456 Print(nWords, vValues.begin() + id * nWords);
457 std::cout << std::endl;
458 }
459 });
460 Clear(nWords * pNtk->GetNumPis(), vAssignedStimuli.begin());
461 }
462
463 /* }}} */
464
465 /* {{{ Careset computation */
466
467 template <typename Ntk>
468 void Simulator<Ntk>::ComputeCare(int id) {
469 if(sUpdates.empty() && id == target) {
470 return;
471 }
472 if(fUpdate) {
473 sUpdates.insert(target);
474 fUpdate = false;
475 }
476 if(!sUpdates.empty()) {
477 Resimulate();
478 sUpdates.clear();
479 }
480 target = id;
481 time_point timeStart = GetCurrentTime();
482 if(nVerbose) {
483 std::cout << "computing careset of " << target << std::endl;
484 }
485 if(pNtk->IsPoDriver(target)) {
486 Fill(nWords, care.begin());
487 if(nVerbose) {
488 std::cout << "care " << std::setw(3) << target << ": ";
489 Print(nWords, care.begin());
490 std::cout << std::endl;
491 }
492 durationCare += Duration(timeStart, GetCurrentTime());
493 return;
494 }
495 vValues2 = vValues;
496 pNtk->ForEachTfo(target, false, [&](int id) {
497 SimulateNode(vValues2, id, target);
498 if(nVerbose) {
499 std::cout << "node " << std::setw(3) << id << ": ";
500 Print(nWords, vValues2.begin() + id * nWords);
501 std::cout << std::endl;
502 }
503 });
504 /* alternative version that updates only affected TFO
505 pNtk->ForEachTfoUpdate(target, false, [&](int id) {
506 bool fUpdated = ResimulateNode(vValues2, id, target);
507 if(nVerbose) {
508 std::cout << "node " << std::setw(3) << id << ": ";
509 Print(nWords, vValues2.begin() + id * nWords);
510 std::cout << std::endl;
511 }
512 return fUpdated;
513 });
514 */
515 Clear(nWords, care.begin());
516 pNtk->ForEachPoDriver([&](int fi) {
517 assert(fi != target);
518 for(int i = 0; i < nWords; i++) {
519 care[i] = care[i] | (vValues[fi * nWords + i] ^ vValues2[fi * nWords + i]);
520 }
521 });
522 if(nVerbose) {
523 std::cout << "care " << std::setw(3) << target << ": ";
524 Print(nWords, care.begin());
525 std::cout << std::endl;
526 }
527 durationCare += Duration(timeStart, GetCurrentTime());
528 }
529
530 /* }}} */
531
532 /* {{{ Preparation */
533
534 template <typename Ntk>
535 void Simulator<Ntk>::Initialize() {
536 if(!fGenerated) {
537 // TODO: reset nWords to default here maybe, if such a mechanism that changes nWords has been implemneted
538 vValues.resize(nWords * pNtk->GetNumNodes());
539 iPivot = 0;
540 vAssignedStimuli.clear();
541 vAssignedStimuli.resize(nWords * pNtk->GetNumPis());
542 for(int count: vPackedCount) {
543 if(count) {
544 vPackedCountEvicted.push_back(count);
545 }
546 }
547 vPackedCount.clear();
548 vPackedCount.resize(nWords * 64);
549 GenerateRandomStimuli();
550 fGenerated = true;
551 } else {
552 // use same nWords as we are reusing patterns even if nWords has changed
553 vValues.resize(nWords * pNtk->GetNumNodes());
554 }
555 Simulate();
556 fInitialized = true;
557 }
558
559 /* }}} */
560
561 /* {{{ Save & load */
562
563 template <typename Ntk>
564 void Simulator<Ntk>::Save(int slot) {
565 assert(slot >= 0);
566 assert(!check_int_max(slot));
567 if(slot >= int_size(vBackups)) {
568 vBackups.resize(slot + 1);
569 }
570 vBackups[slot].nWords = nWords;
571 if(sUpdates.empty()) {
572 vBackups[slot].target = target;
573 vBackups[slot].care = care;
574 } else {
575 vBackups[slot].target = -1;
576 vBackups[slot].care = care;
577 }
578 if(fUpdate) {
579 sUpdates.insert(target);
580 fUpdate = false;
581 }
582 if(!sUpdates.empty()) {
583 Resimulate();
584 sUpdates.clear();
585 }
586 vBackups[slot].vValues = vValues;
587 vBackups[slot].iPivot = iPivot;
588 vBackups[slot].vAssignedStimuli = vAssignedStimuli;
589 target = vBackups[slot].target; // assigned to -1 when careset needs updating
590 if(!fKeepStimula) {
591 vBackups[slot].nCex = nCex;
592 vBackups[slot].nPackedCountOld = nPackedCountOld;
593 vBackups[slot].vPackedCount = vPackedCount;
594 vBackups[slot].vPackedCountEvicted = vPackedCountEvicted;
595 }
596 }
597
598 template <typename Ntk>
599 void Simulator<Ntk>::Load(int slot) {
600 assert(slot >= 0);
601 assert(slot < int_size(vBackups));
602 fUpdate = false;
603 sUpdates.clear();
604 if(!fKeepStimula) {
605 nWords = vBackups[slot].nWords;
606 target = vBackups[slot].target;
607 vValues = vBackups[slot].vValues;
608 care = vBackups[slot].care;
609 iPivot = vBackups[slot].iPivot;
610 vAssignedStimuli = vBackups[slot].vAssignedStimuli;
611 nDiscarded += nCex - vBackups[slot].nCex;
612 nCex = vBackups[slot].nCex;
613 nPackedCountOld = vBackups[slot].nPackedCountOld;
614 vPackedCount = vBackups[slot].vPackedCount;
615 vPackedCountEvicted = vBackups[slot].vPackedCountEvicted;
616 tmp.resize(nWords);
617 } else {
618 std::vector<int> vOffsets;
619 for(int i = 0; i < vBackups[slot].nWords; i++) {
620 bool fDifferent = false;
621 pNtk->ForEachPi([&](int id) {
622 if(vValues[id * vBackups[slot].nWords + i] != vValues[id * nWords + i]) {
623 fDifferent = true;
624 }
625 });
626 if(fDifferent) {
627 vOffsets.push_back(i);
628 }
629 }
630 if(nWords == vBackups[slot].nWords) {
631 if(vOffsets.empty()) {
632 target = vBackups[slot].target;
633 vValues = vBackups[slot].vValues;
634 care = vBackups[slot].care;
635 } else {
636 target = -1;
637 std::vector<std::vector<word>> vInputStimuli(pNtk->GetNumPis());
638 pNtk->ForEachPiIdx([&](int idx, int id) {
639 vInputStimuli[idx].resize(nWords);
640 Copy(nWords, vInputStimuli[idx].begin(), vValues.begin() + id * nWords, false);
641 });
642 vValues = vBackups[slot].vValues;
643 pNtk->ForEachPiIdx([&](int idx, int id) {
644 Copy(nWords, vValues.begin() + id * nWords, vInputStimuli[idx].begin(), false);
645 });
646 for(int i: vOffsets) {
647 SimulateOneWord(i);
648 }
649 }
650 } else {
651 // TODO: when nWords has changed
652 assert(0);
653 }
654 }
655 }
656
657 /* }}} */
658
659 /* {{{ Constructors */
660
661 template <typename Ntk>
663 pNtk(NULL),
664 nVerbose(0),
665 nWords(0),
666 fGenerated(false),
667 fInitialized(false),
668 target(-1),
669 iPivot(0),
670 fUpdate(false) {
671 ResetSummary();
672 }
673
674 template <typename Ntk>
676 pNtk(NULL),
677 nVerbose(pPar->nSimulatorVerbose),
678 nWords(pPar->nWords),
679 fGenerated(false),
680 fInitialized(false),
681 target(-1),
682 iPivot(0),
683 fUpdate(false) {
684 care.resize(nWords);
685 tmp.resize(nWords);
686 ResetSummary();
687 }
688
689 template <typename Ntk>
690 void Simulator<Ntk>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
691 if(!fReuse) {
692 fGenerated = false;
693 }
694 fInitialized = false;
695 target = -1;
696 fUpdate = false;
697 sUpdates.clear();
698 pNtk = pNtk_;
699 pNtk->AddCallback(std::bind(&Simulator<Ntk>::ActionCallback, this, std::placeholders::_1));
700 }
701
702 /* }}} */
703
704 /* {{{ Checks */
705
706 template <typename Ntk>
707 bool Simulator<Ntk>::CheckRedundancy(int id, int idx) {
708 if(!fInitialized) {
709 Initialize();
710 }
711 ComputeCare(id);
712 switch(pNtk->GetNodeType(id)) {
713 case AND: {
714 itr x = vValues.end();
715 bool cx = false;
716 pNtk->ForEachFaninIdx(id, [&](int idx2, int fi, bool c) {
717 if(idx == idx2) {
718 return;
719 }
720 if(x == vValues.end()) {
721 x = vValues.begin() + fi * nWords;
722 cx = c;
723 } else {
724 And(nWords, tmp.begin(), x, vValues.begin() + fi * nWords, cx, c);
725 x = tmp.begin();
726 cx = false;
727 }
728 });
729 if(x == vValues.end()) {
730 x = care.begin();
731 } else {
732 And(nWords, tmp.begin(), x, care.begin(), cx, false);
733 x = tmp.begin();
734 }
735 int fi = pNtk->GetFanin(id, idx);
736 bool c = pNtk->GetCompl(id, idx);
737 And(nWords, tmp.begin(), x, vValues.begin() + fi * nWords, false, !c);
738 return IsZero(nWords, tmp.begin());
739 }
740 default:
741 assert(0);
742 }
743 return false;
744 }
745
746 template <typename Ntk>
747 bool Simulator<Ntk>::CheckFeasibility(int id, int fi, bool c) {
748 if(!fInitialized) {
749 Initialize();
750 }
751 ComputeCare(id);
752 switch(pNtk->GetNodeType(id)) {
753 case AND: {
754 itr x = vValues.end();
755 bool cx = false;
756 pNtk->ForEachFanin(id, [&](int fi, bool c) {
757 if(x == vValues.end()) {
758 x = vValues.begin() + fi * nWords;
759 cx = c;
760 } else {
761 And(nWords, tmp.begin(), x, vValues.begin() + fi * nWords, cx, c);
762 x = tmp.begin();
763 cx = false;
764 }
765 });
766 if(x == vValues.end()) {
767 x = care.begin();
768 } else {
769 And(nWords, tmp.begin(), x, care.begin(), cx, false);
770 x = tmp.begin();
771 }
772 And(nWords, tmp.begin(), x, vValues.begin() + fi * nWords, false, !c);
773 return IsZero(nWords, tmp.begin());
774 }
775 default:
776 assert(0);
777 }
778 return false;
779 }
780
781 /* }}} */
782
783 /* {{{ Cex */
784
785 template <typename Ntk>
786 void Simulator<Ntk>::AddCex(std::vector<VarValue> const &vCex) {
787 if(nVerbose) {
788 std::cout << "cex: ";
789 for(VarValue c: vCex) {
790 std::cout << GetVarValueChar(c);
791 }
792 std::cout << std::endl;
793 }
794 // record care pi indices
795 assert(int_size(vCex) == pNtk->GetNumPis());
796 std::vector<int> vCarePiIdxs;
797 for(int idx = 0; idx < pNtk->GetNumPis(); idx++) {
798 switch(vCex[idx]) {
799 case TRUE:
800 vCarePiIdxs.push_back(idx);
801 break;
802 case FALSE:
803 vCarePiIdxs.push_back(idx);
804 break;
805 default:
806 break;
807 }
808 }
809 assert(!vCarePiIdxs.empty());
810 // find compatible word
811 int iWord = 0;
812 std::vector<word> vCompatibleBits(1);
813 itr it = vCompatibleBits.begin();
814 for(; iWord < nWords; iWord++) {
815 Fill(1, it);
816 for(int idx: vCarePiIdxs) {
817 int id = pNtk->GetPi(idx);
818 bool c;
819 if(vCex[idx] == TRUE) {
820 c = false;
821 } else {
822 assert(vCex[idx] == FALSE);
823 c = true;
824 }
825 itr x = vValues.begin() + id * nWords + iWord;
826 itr y = vAssignedStimuli.begin() + idx * nWords + iWord;
827 And(1, tmp.begin(), x, y, !c, false);
828 And(1, it, it, tmp.begin(), false, true);
829 if(IsZero(1, it)) {
830 break;
831 }
832 }
833 if(!IsZero(1, it)) {
834 break;
835 }
836 }
837 // find compatible bit
838 int iBit;
839 if(iWord < nWords) {
840 assert(!IsZero(1, it));
841 iBit = 0;
842 while(!((*it >> iBit) & 1)) {
843 iBit++;
844 }
845 if(nVerbose) {
846 std::cout << "fusing into stimulus word " << iWord << " bit " << iBit << std::endl;
847 }
848 vPackedCount[iWord * 64 + iBit]++;
849 } else {
850 // no bits are compatible, so reset at pivot
851 iWord = iPivot / 64;
852 iBit = iPivot % 64;
853 if(nVerbose) {
854 std::cout << "resetting stimulus word " << iWord << " bit " << iBit << std::endl;
855 }
856 if(vPackedCount[iWord * 64 + iBit]) {
857 // this can be zero only when stats has been reset
858 vPackedCountEvicted.push_back(vPackedCount[iWord * 64 + iBit]);
859 }
860 vPackedCount[iWord * 64 + iBit] = 1;
861 word mask = 1ull << iBit;
862 for(int idx = 0; idx < pNtk->GetNumPis(); idx++) {
863 vAssignedStimuli[idx * nWords + iWord] &= ~mask;
864 }
865 iPivot++;
866 if(iPivot == 64 * nWords) {
867 iPivot = 0;
868 }
869 }
870 // update stimulus
871 for(int idx: vCarePiIdxs) {
872 int id = pNtk->GetPi(idx);
873 word mask = 1ull << iBit;
874 if(vCex[idx] == TRUE) {
875 vValues[id * nWords + iWord] |= mask;
876 } else {
877 assert(vCex[idx] == FALSE);
878 vValues[id * nWords + iWord] &= ~mask;
879 }
880 vAssignedStimuli[idx * nWords + iWord] |= mask;
881 if(nVerbose) {
882 std::cout << "node " << std::setw(3) << id << ": ";
883 Print(1, vValues.begin() + id * nWords + iWord);
884 std::cout << std::endl;
885 std::cout << "asgn " << std::setw(3) << id << ": ";
886 Print(1, vAssignedStimuli.begin() + idx * nWords + iWord);
887 std::cout << std::endl;
888 }
889 }
890 // simulate
891 SimulateOneWord(iWord);
892 // recompute care with new stimulus
893 time_point timeStart = GetCurrentTime();
894 if(target != -1 && !pNtk->IsPoDriver(target)) {
895 if(nVerbose) {
896 std::cout << "recomputing careset of " << target << std::endl;
897 }
898 vValues2.resize(vValues.size());
899 pNtk->ForEachPi([&](int id) {
900 vValues2[id * nWords + iWord] = vValues[id * nWords + iWord];
901 });
902 pNtk->ForEachInt([&](int id) {
903 vValues2[id * nWords + iWord] = vValues[id * nWords + iWord];
904 });
905 pNtk->ForEachTfo(target, false, [&](int id) {
906 SimulateOneWordNode(vValues2, id, iWord, target);
907 if(nVerbose) {
908 std::cout << "node " << std::setw(3) << id << ": ";
909 Print(1, vValues2.begin() + id * nWords + iWord);
910 std::cout << std::endl;
911 }
912 });
913 Clear(1, care.begin() + iWord);
914 pNtk->ForEachPoDriver([&](int fi) {
915 assert(fi != target);
916 care[iWord] = care[iWord] | (vValues[fi * nWords + iWord] ^ vValues2[fi * nWords + iWord]);
917 });
918 if(nVerbose) {
919 std::cout << "care " << std::setw(3) << target << ": ";
920 Print(1, care.begin() + iWord);
921 std::cout << std::endl;
922 }
923 }
924 durationCare += Duration(timeStart, GetCurrentTime());
925 nCex++;
926 }
927
928 /* }}} */
929
930 /* {{{ Summary */
931
932 template <typename Ntk>
934 nCex = 0;
935 nDiscarded = 0;
936 nPackedCountOld = 0;
937 for(int count: vPackedCount) {
938 if(count) {
939 nPackedCountOld++;
940 }
941 }
942 vPackedCountEvicted.clear();
943 durationSimulation = 0;
944 durationCare = 0;
945 };
946
947 template <typename Ntk>
949 summary<int> v;
950 v.emplace_back("sim cex", nCex);
951 if(!fKeepStimula) {
952 v.emplace_back("sim discarded cex", nDiscarded);
953 }
954 int nPackedCount = vPackedCountEvicted.size() - nPackedCountOld;
955 for(int count: vPackedCount) {
956 if(count) {
957 nPackedCount++;
958 }
959 }
960 v.emplace_back("sim packed pattern", nPackedCount);
961 v.emplace_back("sim evicted pattern", vPackedCountEvicted.size());
962 return v;
963 };
964
965 template <typename Ntk>
968 v.emplace_back("sim simulation", durationSimulation);
969 v.emplace_back("sim care computation", durationCare);
970 return v;
971 };
972
973 /* }}} */
974
975}
976
int nWords
Definition abcNpn.c:127
#define ABC_NAMESPACE_CXX_HEADER_START
#define ABC_NAMESPACE_CXX_HEADER_END
bool CheckFeasibility(int id, int fi, bool c)
void AddCex(std::vector< VarValue > const &vCex)
summary< int > GetStatsSummary() const
bool CheckRedundancy(int id, int idx)
summary< double > GetTimesSummary() const
void AssignNetwork(Ntk *pNtk_, bool fReuse)
Definition rrr.h:16
std::vector< std::pair< std::string, T > > summary
Definition rrrTypes.h:66
VarValue
Definition rrrTypes.h:24
@ TRUE
Definition rrrTypes.h:26
@ FALSE
Definition rrrTypes.h:27
@ POP_BACK
Definition rrrTypes.h:45
@ REMOVE_BUFFER
Definition rrrTypes.h:36
@ REMOVE_UNUSED
Definition rrrTypes.h:35
@ TRIVIAL_DECOMPOSE
Definition rrrTypes.h:40
@ TRIVIAL_COLLAPSE
Definition rrrTypes.h:39
@ SAVE
Definition rrrTypes.h:43
@ REMOVE_CONST
Definition rrrTypes.h:37
@ LOAD
Definition rrrTypes.h:44
@ SORT_FANINS
Definition rrrTypes.h:41
@ REMOVE_FANIN
Definition rrrTypes.h:34
@ ADD_FANIN
Definition rrrTypes.h:38
@ READ
Definition rrrTypes.h:42
std::chrono::time_point< clock_type > time_point
Definition rrrTypes.h:63
@ AND
Definition rrrTypes.h:13
#define false
Definition place_base.h:29
#define assert(ex)
Definition util_old.h:213