14 template <
typename Ntk>
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;
35 std::vector<word> vValues;
36 std::vector<word> vValues2;
37 std::vector<word> care;
38 std::vector<word> tmp;
42 std::vector<word> vAssignedStimuli;
46 std::set<int> sUpdates;
49 std::vector<Simulator> vBackups;
55 std::vector<int> vPackedCount;
56 std::vector<int> vPackedCountEvicted;
57 double durationSimulation;
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;
71 void ActionCallback(
Action const &action);
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);
79 void SimulateOneWord(
int offset);
82 void GenerateRandomStimuli();
85 void ComputeCare(
int id);
105 void AddCex(std::vector<VarValue>
const &vCex);
116 template <
typename Ntk>
117 inline void Simulator<Ntk>::Clear(
int n, itr x)
const {
118 std::fill(x, x + n, 0);
121 template <
typename Ntk>
122 inline void Simulator<Ntk>::Fill(
int n, itr x)
const {
123 std::fill(x, x + n, one);
126 template <
typename Ntk>
127 inline void Simulator<Ntk>::Copy(
int n, itr dst, citr src,
bool c)
const {
129 for(
int i = 0; i < n; i++, dst++, src++) {
133 for(
int i = 0; i < n; i++, dst++, src++) {
139 template <
typename Ntk>
140 inline void Simulator<Ntk>::And(
int n, itr dst, citr src0, citr src1,
bool c0,
bool c1)
const {
143 for(
int i = 0; i < n; i++, dst++, src0++, src1++) {
144 *dst = *src0 & *src1;
147 for(
int i = 0; i < n; i++, dst++, src0++, src1++) {
148 *dst = *src0 & ~*src1;
153 for(
int i = 0; i < n; i++, dst++, src0++, src1++) {
154 *dst = ~*src0 & *src1;
157 for(
int i = 0; i < n; i++, dst++, src0++, src1++) {
158 *dst = ~*src0 & ~*src1;
164 template <
typename Ntk>
165 inline void Simulator<Ntk>::Xor(
int n, itr dst, citr src0, citr src1,
bool c)
const {
167 for(
int i = 0; i < n; i++, dst++, src0++, src1++) {
168 *dst = *src0 ^ *src1;
171 for(
int i = 0; i < n; i++, dst++, src0++, src1++) {
172 *dst = *src0 ^ ~*src1;
177 template <
typename Ntk>
178 inline bool Simulator<Ntk>::IsZero(
int n, citr x)
const {
179 for(
int i = 0; i < n; i++, x++) {
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++) {
197 template <
typename Ntk>
198 inline void Simulator<Ntk>::Print(
int n, citr x)
const {
199 std::cout << std::bitset<64>(*x);
201 for(
int i = 1; i < n; i++, x++) {
202 std::cout << std::endl << std::string(10, ' ') << std::bitset<64>(*x);
210 template <
typename Ntk>
211 void Simulator<Ntk>::ActionCallback(
Action const &action) {
212 switch(action.type) {
216 if(action.id == target) {
219 sUpdates.insert(action.id);
229 if(action.id == target) {
231 for(
int fo: action.vFanouts) {
238 if(sUpdates.count(action.id)) {
239 sUpdates.erase(action.id);
240 for(
int fo: action.vFanouts) {
251 if(action.id == target) {
254 sUpdates.insert(action.id);
263 vValues.resize(
nWords * pNtk->GetNumNodes());
264 SimulateNode(vValues, action.fi);
272 fInitialized =
false;
295 template <
typename Ntk>
296 void Simulator<Ntk>::SimulateNode(std::vector<word> &v,
int id,
int to_negate) {
298 itr y = v.begin() +
id *
nWords;
300 switch(pNtk->GetNodeType(
id)) {
302 pNtk->ForEachFanin(
id, [&](
int fi,
bool c) {
304 x = v.begin() + fi *
nWords;
305 cx = c ^ (fi == to_negate);
307 And(
nWords, y, x, v.begin() + fi *
nWords, cx, c ^ (fi == to_negate));
321 template <
typename Ntk>
322 bool Simulator<Ntk>::ResimulateNode(std::vector<word> &v,
int id,
int to_negate) {
325 switch(pNtk->GetNodeType(
id)) {
327 pNtk->ForEachFanin(
id, [&](
int fi,
bool c) {
329 x = v.begin() + fi *
nWords;
330 cx = c ^ (fi == to_negate);
332 And(
nWords, tmp.begin(), x, v.begin() + fi *
nWords, cx, c ^ (fi == to_negate));
338 Fill(
nWords, tmp.begin());
344 itr y = v.begin() +
id *
nWords;
345 if(IsEq(
nWords, y, tmp.begin())) {
348 Copy(
nWords, y, tmp.begin(),
false);
352 template <
typename Ntk>
353 void Simulator<Ntk>::SimulateOneWordNode(std::vector<word> &v,
int id,
int offset,
int to_negate) {
355 itr y = v.begin() +
id *
nWords + offset;
357 switch(pNtk->GetNodeType(
id)) {
359 pNtk->ForEachFanin(
id, [&](
int fi,
bool c) {
361 x = v.begin() + fi *
nWords + offset;
362 cx = c ^ (fi == to_negate);
364 And(1, y, x, v.begin() + fi *
nWords + offset, cx, c ^ (fi == to_negate));
378 template <
typename Ntk>
379 void Simulator<Ntk>::Simulate() {
382 std::cout <<
"simulating" << std::endl;
384 pNtk->ForEachInt([&](
int id) {
385 SimulateNode(vValues,
id);
387 std::cout <<
"node " << std::setw(3) <<
id <<
": ";
389 std::cout << std::endl;
392 durationSimulation += Duration(timeStart, GetCurrentTime());
395 template <
typename Ntk>
396 void Simulator<Ntk>::Resimulate() {
399 std::cout <<
"resimulating" << std::endl;
401 pNtk->ForEachTfosUpdate(sUpdates,
false, [&](
int fo) {
402 bool fUpdated = ResimulateNode(vValues, fo);
404 std::cout <<
"node " << std::setw(3) << fo <<
": ";
406 std::cout << std::endl;
420 durationSimulation += Duration(timeStart, GetCurrentTime());
423 template <
typename Ntk>
424 void Simulator<Ntk>::SimulateOneWord(
int offset) {
427 std::cout <<
"simulating word " << offset << std::endl;
429 pNtk->ForEachInt([&](
int id) {
430 SimulateOneWordNode(vValues,
id, offset);
432 std::cout <<
"node " << std::setw(3) <<
id <<
": ";
433 Print(1, vValues.begin() +
id *
nWords + offset);
434 std::cout << std::endl;
437 durationSimulation += Duration(timeStart, GetCurrentTime());
444 template <
typename Ntk>
445 void Simulator<Ntk>::GenerateRandomStimuli() {
447 std::cout <<
"generating random stimuli" << std::endl;
450 pNtk->ForEachPi([&](
int id) {
451 for(
int i = 0; i <
nWords; i++) {
452 vValues[
id *
nWords + i] = rng();
455 std::cout <<
"node " << std::setw(3) <<
id <<
": ";
457 std::cout << std::endl;
460 Clear(
nWords * pNtk->GetNumPis(), vAssignedStimuli.begin());
467 template <
typename Ntk>
468 void Simulator<Ntk>::ComputeCare(
int id) {
469 if(sUpdates.empty() &&
id == target) {
473 sUpdates.insert(target);
476 if(!sUpdates.empty()) {
483 std::cout <<
"computing careset of " << target << std::endl;
485 if(pNtk->IsPoDriver(target)) {
486 Fill(
nWords, care.begin());
488 std::cout <<
"care " << std::setw(3) << target <<
": ";
489 Print(
nWords, care.begin());
490 std::cout << std::endl;
492 durationCare += Duration(timeStart, GetCurrentTime());
496 pNtk->ForEachTfo(target,
false, [&](
int id) {
497 SimulateNode(vValues2,
id, target);
499 std::cout <<
"node " << std::setw(3) <<
id <<
": ";
501 std::cout << std::endl;
515 Clear(
nWords, care.begin());
516 pNtk->ForEachPoDriver([&](
int fi) {
518 for(
int i = 0; i <
nWords; i++) {
519 care[i] = care[i] | (vValues[fi *
nWords + i] ^ vValues2[fi *
nWords + i]);
523 std::cout <<
"care " << std::setw(3) << target <<
": ";
524 Print(
nWords, care.begin());
525 std::cout << std::endl;
527 durationCare += Duration(timeStart, GetCurrentTime());
534 template <
typename Ntk>
535 void Simulator<Ntk>::Initialize() {
538 vValues.resize(
nWords * pNtk->GetNumNodes());
540 vAssignedStimuli.clear();
541 vAssignedStimuli.resize(
nWords * pNtk->GetNumPis());
542 for(
int count: vPackedCount) {
544 vPackedCountEvicted.push_back(count);
547 vPackedCount.clear();
548 vPackedCount.resize(
nWords * 64);
549 GenerateRandomStimuli();
553 vValues.resize(
nWords * pNtk->GetNumNodes());
563 template <
typename Ntk>
564 void Simulator<Ntk>::Save(
int slot) {
566 assert(!check_int_max(slot));
567 if(slot >= int_size(vBackups)) {
568 vBackups.resize(slot + 1);
570 vBackups[slot].nWords =
nWords;
571 if(sUpdates.empty()) {
572 vBackups[slot].target = target;
573 vBackups[slot].care = care;
575 vBackups[slot].target = -1;
576 vBackups[slot].care = care;
579 sUpdates.insert(target);
582 if(!sUpdates.empty()) {
586 vBackups[slot].vValues = vValues;
587 vBackups[slot].iPivot = iPivot;
588 vBackups[slot].vAssignedStimuli = vAssignedStimuli;
589 target = vBackups[slot].target;
591 vBackups[slot].nCex = nCex;
592 vBackups[slot].nPackedCountOld = nPackedCountOld;
593 vBackups[slot].vPackedCount = vPackedCount;
594 vBackups[slot].vPackedCountEvicted = vPackedCountEvicted;
598 template <
typename Ntk>
599 void Simulator<Ntk>::Load(
int slot) {
601 assert(slot < int_size(vBackups));
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;
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]) {
627 vOffsets.push_back(i);
631 if(vOffsets.empty()) {
632 target = vBackups[slot].target;
633 vValues = vBackups[slot].vValues;
634 care = vBackups[slot].care;
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);
642 vValues = vBackups[slot].vValues;
643 pNtk->ForEachPiIdx([&](
int idx,
int id) {
644 Copy(
nWords, vValues.begin() +
id *
nWords, vInputStimuli[idx].begin(),
false);
646 for(
int i: vOffsets) {
661 template <
typename Ntk>
674 template <
typename Ntk>
677 nVerbose(pPar->nSimulatorVerbose),
678 nWords(pPar->nWords),
689 template <
typename Ntk>
694 fInitialized =
false;
699 pNtk->AddCallback(std::bind(&Simulator<Ntk>::ActionCallback,
this, std::placeholders::_1));
706 template <
typename Ntk>
712 switch(pNtk->GetNodeType(
id)) {
714 itr x = vValues.end();
716 pNtk->ForEachFaninIdx(
id, [&](
int idx2,
int fi,
bool c) {
720 if(x == vValues.end()) {
721 x = vValues.begin() + fi * nWords;
724 And(nWords, tmp.begin(), x, vValues.begin() + fi * nWords, cx, c);
729 if(x == vValues.end()) {
732 And(nWords, tmp.begin(), x, care.begin(), cx,
false);
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());
746 template <
typename Ntk>
752 switch(pNtk->GetNodeType(
id)) {
754 itr x = vValues.end();
756 pNtk->ForEachFanin(
id, [&](
int fi,
bool c) {
757 if(x == vValues.end()) {
758 x = vValues.begin() + fi * nWords;
761 And(nWords, tmp.begin(), x, vValues.begin() + fi * nWords, cx, c);
766 if(x == vValues.end()) {
769 And(nWords, tmp.begin(), x, care.begin(), cx,
false);
772 And(nWords, tmp.begin(), x, vValues.begin() + fi * nWords,
false, !c);
773 return IsZero(nWords, tmp.begin());
785 template <
typename Ntk>
788 std::cout <<
"cex: ";
790 std::cout << GetVarValueChar(c);
792 std::cout << std::endl;
795 assert(int_size(vCex) == pNtk->GetNumPis());
796 std::vector<int> vCarePiIdxs;
797 for(
int idx = 0; idx < pNtk->GetNumPis(); idx++) {
800 vCarePiIdxs.push_back(idx);
803 vCarePiIdxs.push_back(idx);
809 assert(!vCarePiIdxs.empty());
812 std::vector<word> vCompatibleBits(1);
813 itr it = vCompatibleBits.begin();
814 for(; iWord < nWords; iWord++) {
816 for(
int idx: vCarePiIdxs) {
817 int id = pNtk->GetPi(idx);
819 if(vCex[idx] ==
TRUE) {
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);
842 while(!((*it >> iBit) & 1)) {
846 std::cout <<
"fusing into stimulus word " << iWord <<
" bit " << iBit << std::endl;
848 vPackedCount[iWord * 64 + iBit]++;
854 std::cout <<
"resetting stimulus word " << iWord <<
" bit " << iBit << std::endl;
856 if(vPackedCount[iWord * 64 + iBit]) {
858 vPackedCountEvicted.push_back(vPackedCount[iWord * 64 + iBit]);
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;
866 if(iPivot == 64 * nWords) {
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;
878 vValues[
id * nWords + iWord] &= ~mask;
880 vAssignedStimuli[idx * nWords + iWord] |= mask;
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;
891 SimulateOneWord(iWord);
894 if(target != -1 && !pNtk->IsPoDriver(target)) {
896 std::cout <<
"recomputing careset of " << target << std::endl;
898 vValues2.resize(vValues.size());
899 pNtk->ForEachPi([&](
int id) {
900 vValues2[
id * nWords + iWord] = vValues[
id * nWords + iWord];
902 pNtk->ForEachInt([&](
int id) {
903 vValues2[
id * nWords + iWord] = vValues[
id * nWords + iWord];
905 pNtk->ForEachTfo(target,
false, [&](
int id) {
906 SimulateOneWordNode(vValues2,
id, iWord, target);
908 std::cout <<
"node " << std::setw(3) <<
id <<
": ";
909 Print(1, vValues2.begin() +
id * nWords + iWord);
910 std::cout << std::endl;
913 Clear(1, care.begin() + iWord);
914 pNtk->ForEachPoDriver([&](
int fi) {
916 care[iWord] = care[iWord] | (vValues[fi * nWords + iWord] ^ vValues2[fi * nWords + iWord]);
919 std::cout <<
"care " << std::setw(3) << target <<
": ";
920 Print(1, care.begin() + iWord);
921 std::cout << std::endl;
924 durationCare += Duration(timeStart, GetCurrentTime());
932 template <
typename Ntk>
937 for(
int count: vPackedCount) {
942 vPackedCountEvicted.clear();
943 durationSimulation = 0;
947 template <
typename Ntk>
950 v.emplace_back(
"sim cex", nCex);
952 v.emplace_back(
"sim discarded cex", nDiscarded);
954 int nPackedCount = vPackedCountEvicted.size() - nPackedCountOld;
955 for(
int count: vPackedCount) {
960 v.emplace_back(
"sim packed pattern", nPackedCount);
961 v.emplace_back(
"sim evicted pattern", vPackedCountEvicted.size());
965 template <
typename Ntk>
968 v.emplace_back(
"sim simulation", durationSimulation);
969 v.emplace_back(
"sim care computation", durationCare);
#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)
std::vector< std::pair< std::string, T > > summary
std::chrono::time_point< clock_type > time_point