ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
acd66.hpp
Go to the documentation of this file.
1
24
25#ifndef _ACD66_H_
26#define _ACD66_H_
27#pragma once
28
29#include <algorithm>
30#include <array>
31#include <cassert>
32#include <cstdint>
33#include <type_traits>
34
35#include "kitty_constants.hpp"
37#include "kitty_dynamic_tt.hpp"
38#include "kitty_operations.hpp"
39#include "kitty_operators.hpp"
40#include "kitty_static_tt.hpp"
41
42#ifdef _MSC_VER
43# include <intrin.h>
44# define __builtin_popcount __popcnt
45#endif
46
48
49namespace acd
50{
51
53{
54private:
55 static constexpr uint32_t max_num_vars = 11;
58
59public:
60 explicit acd66_impl( uint32_t const num_vars, bool multiple_shared_set = false, bool const verify = false )
61 : num_vars( num_vars ), multiple_ss( multiple_shared_set ), verify( verify )
62 {
63 std::iota( permutations.begin(), permutations.end(), 0 );
64 }
65
67 bool run( word* ptt )
68 {
69 assert( num_vars > 6 );
70
71 /* truth table is too large for the settings */
72 if ( num_vars > max_num_vars || num_vars > 11 )
73 {
74 return false;
75 }
76
77 /* convert to static TT */
78 init_truth_table( ptt );
79
80 /* run ACD trying different bound sets and free sets */
81 return find_decomposition();
82 }
83
85 int run( word* ptt, unsigned delay_profile )
86 {
87 assert( num_vars > 6 );
88
89 /* truth table is too large for the settings */
90 if ( num_vars > max_num_vars || num_vars > 11 )
91 {
92 return false;
93 }
94
95 uint32_t late_arriving = __builtin_popcount( delay_profile );
96
97 /* too many late arriving variables */
98 if ( late_arriving > 5 )
99 return 0;
100
101 /* convert to static TT */
102 init_truth_table( ptt );
103 best_tt = start_tt;
104
105 /* permute late arriving variables to be the least significant */
106 reposition_late_arriving_variables( delay_profile, late_arriving );
107
108 /* run ACD trying different bound sets and free sets */
109 return find_decomposition_offset( late_arriving ) ? ( delay_profile == 0 ? 2 : 1 ) : 0;
110 }
111
113 {
114 if ( best_multiplicity == UINT32_MAX )
115 return -1;
116
117 compute_decomposition_impl();
118
119 if ( verify && !verify_impl() )
120 {
121 return 1;
122 }
123
124 return 0;
125 }
126
128 {
129 if ( bs_support_size == UINT32_MAX )
130 {
131 return num_vars + 1 + num_shared_vars;
132 }
133
134 /* real value after support minimization */
135 return bs_support_size + best_free_set + 1 + num_shared_vars;
136 }
137
138 /* contains a 1 for FS variables */
139 unsigned get_profile()
140 {
141 unsigned profile = 0;
142
143 if ( best_multiplicity == UINT32_MAX )
144 return -1;
145
146 if ( bs_support_size == UINT32_MAX )
147 {
148 for ( uint32_t i = 0; i < best_free_set; ++i )
149 {
150 profile |= 1 << permutations[i];
151 }
152 }
153 else
154 {
155 for ( uint32_t i = 0; i < bs_support_size; ++i )
156 {
157 profile |= 1 << permutations[bs_support[i] + best_free_set];
158 }
159 profile = ~profile & ( ( 1u << num_vars ) - 1 );
160 }
161
162 return profile;
163 }
164
165 void get_decomposition( unsigned char* decompArray )
166 {
167 if ( bs_support_size == UINT32_MAX )
168 return;
169
170 get_decomposition_abc( decompArray );
171 }
172
173private:
174 bool find_decomposition()
175 {
176 best_multiplicity = UINT32_MAX;
177 best_free_set = UINT32_MAX;
178
179 /* use multiple shared set variables */
180 if ( multiple_ss )
181 {
182 return find_decomposition_bs_multi_ss( num_vars - 6 );
183 }
184
185 uint32_t max_free_set = num_vars == 11 ? 5 : 4;
186
187 /* find ACD "66" for different number of variables in the free set */
188 for ( uint32_t i = num_vars - 6; i <= max_free_set; ++i )
189 {
190 if ( find_decomposition_bs( i ) )
191 return true;
192 }
193
194 best_multiplicity = UINT32_MAX;
195 return false;
196 }
197
198 bool find_decomposition_offset( uint32_t offset )
199 {
200 best_multiplicity = UINT32_MAX;
201 best_free_set = UINT32_MAX;
202
203 /* use multiple shared set variables */
204 if ( multiple_ss )
205 {
206 return find_decomposition_bs_offset_multi_ss( std::max( num_vars - 6, offset ), offset );
207 }
208
209 uint32_t max_free_set = ( num_vars == 11 || offset == 5 ) ? 5 : 4;
210
211 /* find ACD "66" for different number of variables in the free set */
212 for ( uint32_t i = std::max( num_vars - 6, offset ); i <= max_free_set; ++i )
213 {
214 if ( find_decomposition_bs_offset( i, offset ) )
215 return true;
216 }
217
218 best_multiplicity = UINT32_MAX;
219 return false;
220 }
221
222 void init_truth_table( word* ptt )
223 {
224 uint32_t const num_blocks = ( num_vars <= 6 ) ? 1 : ( 1 << ( num_vars - 6 ) );
225
226 for ( uint32_t i = 0; i < num_blocks; ++i )
227 {
228 start_tt._bits[i] = ptt[i];
229 }
230
231 local_extend_to( start_tt, num_vars );
232 }
233
234 uint32_t column_multiplicity( STT const& tt, uint32_t const free_set_size )
235 {
236 assert( free_set_size <= 5 );
237
238 uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1;
239 uint64_t const shift = UINT64_C( 1 ) << free_set_size;
240 uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1;
241 uint32_t const limit = free_set_size < 5 ? 4 : 2;
242 uint32_t cofactors[4];
243 uint32_t size = 0;
244
245 /* extract iset functions */
246 for ( auto i = 0u; i < num_blocks; ++i )
247 {
248 uint64_t sub = tt._bits[i];
249 for ( auto j = 0; j < ( 64 >> free_set_size ); ++j )
250 {
251 uint32_t fs_fn = static_cast<uint32_t>( sub & mask );
252 uint32_t k;
253 for ( k = 0; k < size; ++k )
254 {
255 if ( fs_fn == cofactors[k] )
256 break;
257 }
258 if ( k == limit )
259 return 5;
260 if ( k == size )
261 cofactors[size++] = fs_fn;
262 sub >>= shift;
263 }
264 }
265
266 return size;
267 }
268
269 uint32_t column_multiplicity2( STT const& tt, uint32_t const free_set_size, uint32_t const limit )
270 {
271 assert( free_set_size <= 5 );
272
273 uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1;
274 uint64_t const shift = UINT64_C( 1 ) << free_set_size;
275 uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1;
276 uint32_t cofactors[32];
277 uint32_t size = 0;
278
279 /* extract iset functions */
280 for ( auto i = 0u; i < num_blocks; ++i )
281 {
282 uint64_t sub = tt._bits[i];
283 for ( auto j = 0; j < ( 64 >> free_set_size ); ++j )
284 {
285 uint32_t fs_fn = static_cast<uint32_t>( sub & mask );
286 uint32_t k;
287 for ( k = 0; k < size; ++k )
288 {
289 if ( fs_fn == cofactors[k] )
290 break;
291 }
292 if ( k == limit )
293 return limit + 1;
294 if ( k == size )
295 cofactors[size++] = fs_fn;
296 sub >>= shift;
297 }
298 }
299
300 return size;
301 }
302
303 inline bool combinations_next( uint32_t k, uint32_t offset, uint32_t* pComb, uint32_t* pInvPerm, STT& tt )
304 {
305 uint32_t i;
306
307 for ( i = k - 1; pComb[i] == num_vars - k + i; --i )
308 {
309 if ( i == offset )
310 return false;
311 }
312
313 /* move vars */
314 uint32_t var_old = pComb[i];
315 uint32_t pos_new = pInvPerm[var_old + 1];
316 std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] );
317 std::swap( pComb[i], pComb[pos_new] );
318 swap_inplace_local( tt, i, pos_new );
319
320 for ( uint32_t j = i + 1; j < k; j++ )
321 {
322 var_old = pComb[j];
323 pos_new = pInvPerm[pComb[j - 1] + 1];
324 std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] );
325 std::swap( pComb[j], pComb[pos_new] );
326 swap_inplace_local( tt, j, pos_new );
327 }
328
329 return true;
330 }
331
332 inline bool combinations_next_simple( uint32_t k, uint32_t* pComb, uint32_t* pInvPerm, uint32_t size )
333 {
334 uint32_t i;
335
336 for ( i = k - 1; pComb[i] == size - k + i; --i )
337 {
338 if ( i == 0 )
339 return false;
340 }
341
342 /* move vars */
343 uint32_t var_old = pComb[i];
344 uint32_t pos_new = pInvPerm[var_old + 1];
345 std::swap( pInvPerm[var_old + 1], pInvPerm[var_old] );
346 std::swap( pComb[i], pComb[pos_new] );
347
348 for ( uint32_t j = i + 1; j < k; j++ )
349 {
350 var_old = pComb[j];
351 pos_new = pInvPerm[pComb[j - 1] + 1];
352 std::swap( pInvPerm[pComb[j - 1] + 1], pInvPerm[var_old] );
353 std::swap( pComb[j], pComb[pos_new] );
354 }
355
356 return true;
357 }
358
359 bool find_decomposition_bs( uint32_t free_set_size )
360 {
361 STT tt = start_tt;
362
363 /* works up to 16 input truth tables */
364 assert( num_vars <= 16 );
365
366 /* init combinations */
367 uint32_t pComb[16], pInvPerm[16];
368 for ( uint32_t i = 0; i < num_vars; ++i )
369 {
370 pComb[i] = pInvPerm[i] = i;
371 }
372
373 /* enumerate combinations */
374 best_free_set = free_set_size;
375 do
376 {
377 uint32_t cost = column_multiplicity( tt, free_set_size );
378 if ( cost == 2 )
379 {
380 best_tt = tt;
381 best_multiplicity = cost;
382 for ( uint32_t i = 0; i < num_vars; ++i )
383 {
384 permutations[i] = pComb[i];
385 }
386 return true;
387 }
388 else if ( cost <= 4 && free_set_size < 5 )
389 {
390 /* look for a shared variable */
391 best_multiplicity = cost;
392 int res = check_shared_set( tt );
393
394 if ( res >= 0 )
395 {
396 best_tt = tt;
397 for ( uint32_t i = 0; i < num_vars; ++i )
398 {
399 permutations[i] = pComb[i];
400 }
401 /* move shared variable as the most significative one */
402 swap_inplace_local( best_tt, res, num_vars - 1 );
403 std::swap( permutations[res], permutations[num_vars - 1] );
404 num_shared_vars = 1;
405 return true;
406 }
407 }
408 } while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) );
409
410 return false;
411 }
412
413 bool find_decomposition_bs_offset( uint32_t free_set_size, uint32_t offset )
414 {
415 STT tt = best_tt;
416
417 /* works up to 16 input truth tables */
418 assert( num_vars <= 16 );
419 best_free_set = free_set_size;
420
421 /* special case */
422 if ( free_set_size == offset )
423 {
424 uint32_t cost = column_multiplicity( tt, free_set_size );
425 if ( cost == 2 )
426 {
427 best_tt = tt;
428 best_multiplicity = cost;
429 return true;
430 }
431 else if ( cost <= 4 && free_set_size < 5 )
432 {
433 /* look for a shared variable */
434 best_multiplicity = cost;
435 int res = check_shared_set( tt );
436
437 if ( res >= 0 )
438 {
439 best_tt = tt;
440 /* move shared variable as the most significative one */
441 swap_inplace_local( best_tt, res, num_vars - 1 );
442 std::swap( permutations[res], permutations[num_vars - 1] );
443 num_shared_vars = 1;
444 return true;
445 }
446 }
447 return false;
448 }
449
450 /* init combinations */
451 uint32_t pComb[16], pInvPerm[16];
452 for ( uint32_t i = 0; i < num_vars; ++i )
453 {
454 pComb[i] = pInvPerm[i] = i;
455 }
456
457 /* enumerate combinations */
458 do
459 {
460 uint32_t cost = column_multiplicity( tt, free_set_size );
461 if ( cost == 2 )
462 {
463 best_tt = tt;
464 best_multiplicity = cost;
465 for ( uint32_t i = 0; i < num_vars; ++i )
466 {
467 pInvPerm[i] = permutations[pComb[i]];
468 }
469 for ( uint32_t i = 0; i < num_vars; ++i )
470 {
471 permutations[i] = pInvPerm[i];
472 }
473 return true;
474 }
475 else if ( cost <= 4 && free_set_size < 5 )
476 {
477 /* look for a shared variable */
478 best_multiplicity = cost;
479 int res = check_shared_set( tt );
480
481 if ( res >= 0 )
482 {
483 best_tt = tt;
484 for ( uint32_t i = 0; i < num_vars; ++i )
485 {
486 pInvPerm[i] = permutations[pComb[i]];
487 }
488 for ( uint32_t i = 0; i < num_vars; ++i )
489 {
490 permutations[i] = pInvPerm[i];
491 }
492 /* move shared variable as the most significative one */
493 swap_inplace_local( best_tt, res, num_vars - 1 );
494 std::swap( permutations[res], permutations[num_vars - 1] );
495 num_shared_vars = 1;
496 return true;
497 }
498 }
499 } while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) );
500
501 return false;
502 }
503
504 bool find_decomposition_bs_multi_ss( uint32_t free_set_size )
505 {
506 STT tt = start_tt;
507
508 /* works up to 16 input truth tables */
509 assert( num_vars <= 16 );
510
511 /* init combinations */
512 uint32_t pComb[16], pInvPerm[16], shared_set[4];
513 for ( uint32_t i = 0; i < num_vars; ++i )
514 {
515 pComb[i] = pInvPerm[i] = i;
516 }
517
518 /* enumerate combinations */
519 best_free_set = free_set_size;
520 do
521 {
522 uint32_t cost = column_multiplicity2( tt, free_set_size, 1 << ( 6 - free_set_size ) );
523 if ( cost <= 2 )
524 {
525 best_tt = tt;
526 best_multiplicity = cost;
527 for ( uint32_t i = 0; i < num_vars; ++i )
528 {
529 permutations[i] = pComb[i];
530 }
531 return true;
532 }
533
534 uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2
535 : cost <= 16 ? 3
536 : cost <= 32 ? 4
537 : 5;
538 if ( ss_vars_needed + free_set_size < 6 )
539 {
540 /* look for a shared variable */
541 best_multiplicity = cost;
542 int res = check_shared_set_multi( tt, ss_vars_needed, shared_set );
543
544 if ( res >= 0 )
545 {
546 best_tt = tt;
547 for ( uint32_t i = 0; i < num_vars; ++i )
548 {
549 permutations[i] = pComb[i];
550 }
551 /* move shared variables as the most significative ones */
552 for ( int32_t i = res - 1; i >= 0; --i )
553 {
554 swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i );
555 std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] );
556 }
557 num_shared_vars = res;
558 return true;
559 }
560 }
561 } while ( combinations_next( free_set_size, 0, pComb, pInvPerm, tt ) );
562
563 best_multiplicity = UINT32_MAX;
564 return false;
565 }
566
567 bool find_decomposition_bs_offset_multi_ss( uint32_t free_set_size, uint32_t offset )
568 {
569 STT tt = best_tt;
570
571 /* works up to 16 input truth tables */
572 assert( num_vars <= 16 );
573 best_free_set = free_set_size;
574 uint32_t shared_set[4];
575
576 /* special case */
577 if ( free_set_size == offset )
578 {
579 uint32_t cost = column_multiplicity2( tt, free_set_size, 1 << ( 6 - free_set_size ) );
580 if ( cost == 2 )
581 {
582 best_tt = tt;
583 best_multiplicity = cost;
584 return true;
585 }
586
587 uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2
588 : cost <= 16 ? 3
589 : cost <= 32 ? 4
590 : 5;
591
592 if ( ss_vars_needed + free_set_size < 6 )
593 {
594 /* look for a shared variable */
595 best_multiplicity = cost;
596 int res = check_shared_set_multi( tt, ss_vars_needed, shared_set );
597
598 if ( res >= 0 )
599 {
600 best_tt = tt;
601 /* move shared variables as the most significative ones */
602 for ( int32_t i = res - 1; i >= 0; --i )
603 {
604 swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i );
605 std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] );
606 }
607 num_shared_vars = res;
608 return true;
609 }
610 }
611
612 best_multiplicity = UINT32_MAX;
613 return false;
614 }
615
616 /* init combinations */
617 uint32_t pComb[16], pInvPerm[16];
618 for ( uint32_t i = 0; i < num_vars; ++i )
619 {
620 pComb[i] = pInvPerm[i] = i;
621 }
622
623 /* enumerate combinations */
624 do
625 {
626 uint32_t cost = column_multiplicity2( tt, free_set_size, 1 << ( 6 - free_set_size ) );
627 if ( cost == 2 )
628 {
629 best_tt = tt;
630 best_multiplicity = cost;
631 for ( uint32_t i = 0; i < num_vars; ++i )
632 {
633 pInvPerm[i] = permutations[pComb[i]];
634 }
635 for ( uint32_t i = 0; i < num_vars; ++i )
636 {
637 permutations[i] = pInvPerm[i];
638 }
639 return true;
640 }
641
642 uint32_t ss_vars_needed = cost <= 4 ? 1 : cost <= 8 ? 2
643 : cost <= 16 ? 3
644 : cost <= 32 ? 4
645 : 5;
646
647 if ( ss_vars_needed + free_set_size < 6 )
648 {
649 /* look for a shared variable */
650 best_multiplicity = cost;
651 int res = check_shared_set_multi( tt, ss_vars_needed, shared_set );
652
653 if ( res >= 0 )
654 {
655 best_tt = tt;
656 for ( uint32_t i = 0; i < num_vars; ++i )
657 {
658 pInvPerm[i] = permutations[pComb[i]];
659 }
660 for ( uint32_t i = 0; i < num_vars; ++i )
661 {
662 permutations[i] = pInvPerm[i];
663 }
664 /* move shared variables as the most significative ones */
665 for ( int32_t i = res - 1; i >= 0; --i )
666 {
667 swap_inplace_local( best_tt, shared_set[i] + best_free_set, num_vars - res + i );
668 std::swap( permutations[shared_set[i] + best_free_set], permutations[num_vars - res + i] );
669 }
670 num_shared_vars = res;
671 return true;
672 }
673 }
674 } while ( combinations_next( free_set_size, offset, pComb, pInvPerm, tt ) );
675
676 best_multiplicity = UINT32_MAX;
677 return false;
678 }
679
680 bool check_shared_var( STT const& tt, uint32_t free_set_size, uint32_t shared_var )
681 {
682 assert( free_set_size <= 5 );
683
684 uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1;
685 uint64_t const shift = UINT64_C( 1 ) << free_set_size;
686 uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1;
687 uint32_t cofactors[2][4];
688 uint32_t size[2] = { 0, 0 };
689 uint32_t shared_var_shift = shared_var - free_set_size;
690
691 /* extract iset functions */
692 uint32_t iteration_counter = 0;
693 for ( auto i = 0u; i < num_blocks; ++i )
694 {
695 uint64_t sub = tt._bits[i];
696 for ( auto j = 0; j < ( 64 >> free_set_size ); ++j )
697 {
698 uint32_t fs_fn = static_cast<uint32_t>( sub & mask );
699 uint32_t p = ( iteration_counter >> shared_var_shift ) & 1;
700 uint32_t k;
701 for ( k = 0; k < size[p]; ++k )
702 {
703 if ( fs_fn == cofactors[p][k] )
704 break;
705 }
706 if ( k == 2 )
707 return false;
708 if ( k == size[p] )
709 cofactors[p][size[p]++] = fs_fn;
710 sub >>= shift;
711 ++iteration_counter;
712 }
713 }
714
715 return true;
716 }
717
718 inline int check_shared_set( STT const& tt )
719 {
720 /* find one shared set variable */
721 for ( uint32_t i = best_free_set; i < num_vars; ++i )
722 {
723 /* check the multiplicity of cofactors */
724 if ( check_shared_var( tt, best_free_set, i ) )
725 {
726 return i;
727 }
728 }
729
730 return -1;
731 }
732
733 bool check_shared_var_combined( STT const& tt, uint32_t free_set_size, uint32_t shared_vars[6], uint32_t num_shared_vars )
734 {
735 assert( free_set_size <= 5 );
736 assert( num_shared_vars <= 4 );
737
738 uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1;
739 uint64_t const shift = UINT64_C( 1 ) << free_set_size;
740 uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1;
741 uint32_t cofactors[16][2];
742 uint32_t size[16] = { 0 };
743
744 /* extract iset functions */
745 uint32_t iteration_counter = 0;
746 for ( auto i = 0u; i < num_blocks; ++i )
747 {
748 uint64_t sub = tt._bits[i];
749 for ( auto j = 0; j < ( 64 >> free_set_size ); ++j )
750 {
751 uint32_t fs_fn = static_cast<uint32_t>( sub & mask );
752 uint32_t p = 0;
753 for ( uint32_t k = 0; k < num_shared_vars; ++k )
754 {
755 p |= ( ( iteration_counter >> shared_vars[k] ) & 1 ) << k;
756 }
757
758 uint32_t k;
759 for ( k = 0; k < size[p]; ++k )
760 {
761 if ( fs_fn == cofactors[p][k] )
762 break;
763 }
764 if ( k == 2 )
765 return false;
766 if ( k == size[p] )
767 cofactors[p][size[p]++] = fs_fn;
768 sub >>= shift;
769 ++iteration_counter;
770 }
771 }
772
773 return true;
774 }
775
776 inline int check_shared_set_multi( STT const& tt, uint32_t target_num_ss, uint32_t* res_shared )
777 {
778 /* init combinations */
779 uint32_t pComb[6], pInvPerm[6];
780
781 /* search for a feasible shared set */
782 for ( uint32_t i = target_num_ss; i < 6 - best_free_set; ++i )
783 {
784 for ( uint32_t i = 0; i < 6; ++i )
785 {
786 pComb[i] = pInvPerm[i] = i;
787 }
788
789 do
790 {
791 /* check for combined shared set */
792 if ( check_shared_var_combined( tt, best_free_set, pComb, i ) )
793 {
794 for ( uint32_t j = 0; j < i; ++j )
795 {
796 res_shared[j] = pComb[j];
797 }
798 /* sort vars */
799 std::sort( res_shared, res_shared + i );
800 return i;
801 }
802 } while ( combinations_next_simple( i, pComb, pInvPerm, num_vars - best_free_set ) );
803 }
804
805 return -1;
806 }
807
808 void compute_decomposition_impl( bool verbose = false )
809 {
810 /* construct isets involved in multiplicity */
811 LTT composition;
812 LTT bs;
813 LTT bs_dc;
814
815 /* construct isets */
816 uint32_t offset = 0;
817 uint32_t num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1;
818 uint64_t const shift = UINT64_C( 1 ) << best_free_set;
819 uint64_t const mask = ( UINT64_C( 1 ) << shift ) - 1;
820 uint32_t const num_groups = 1 << num_shared_vars;
821 uint32_t const next_group = 1 << ( num_vars - best_free_set - num_shared_vars );
822
823 uint64_t fs_fun[32] = { 0 };
824 uint64_t dc_mask = ( ( UINT64_C( 1 ) << next_group ) - 1 );
825
826 uint32_t group_index = 0;
827 uint32_t set_index = 0;
828 fs_fun[0] = best_tt._bits[0] & mask;
829 bool set_dc = true;
830 for ( auto i = 0u; i < num_blocks; ++i )
831 {
832 uint64_t cof = best_tt._bits[i];
833 for ( auto j = 0; j < ( 64 >> best_free_set ); ++j )
834 {
835 uint64_t val = cof & mask;
836 /* move to next block */
837 if ( set_index == next_group )
838 {
839 if ( set_dc )
840 {
841 /* only one cofactor can be found in the group --> encoding can be 0 or 1 */
842 fs_fun[group_index + 1] = fs_fun[group_index];
843 bs_dc._bits |= dc_mask;
844 }
845 /* set don't care */
846 set_dc = true;
847 group_index += 2;
848 set_index = 0;
849 fs_fun[group_index] = val;
850 dc_mask <<= next_group;
851 }
852 /* gather encoding */
853 if ( val != fs_fun[group_index] )
854 {
855 bs._bits |= UINT64_C( 1 ) << ( j + offset );
856 fs_fun[group_index + 1] = val;
857 set_dc = false; // two cofactors are present
858 }
859 cof >>= shift;
860 ++set_index;
861 }
862 offset = ( offset + ( 64 >> best_free_set ) ) & 0x3F;
863 }
864
865 if ( set_dc )
866 {
867 /* only one cofactor can be found in the group --> encoding can be 0 or 1 */
868 fs_fun[group_index + 1] = fs_fun[group_index];
869 bs_dc._bits |= dc_mask;
870 }
871
872 /* create composition function */
873 for ( uint32_t i = 0; i < 2 * num_groups; ++i )
874 {
875 composition._bits |= fs_fun[i] << ( i * shift );
876 }
877
878 /* minimize support BS */
879 LTT care;
880 bs_support_size = 0;
881 uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF, UINT64_MAX };
882 care._bits = masks[num_vars - best_free_set] & ~bs_dc._bits;
883 for ( uint32_t i = 0; i < num_vars - best_free_set; ++i )
884 {
885 if ( !has_var6( bs, care, i ) )
886 {
887 adjust_truth_table_on_dc( bs, care, i );
888 continue;
889 }
890
891 if ( bs_support_size < i )
892 {
893 kitty::swap_inplace( bs, bs_support_size, i );
894 }
895
896 bs_support[bs_support_size] = i;
897 ++bs_support_size;
898 }
899
900 /* assign functions */
901 dec_funcs[0] = bs._bits;
902 dec_funcs[1] = composition._bits;
903
904 /* print functions */
905 if ( verbose )
906 {
907 LTT f;
908 f._bits = dec_funcs[0];
909 std::cout << "BS function : ";
910 kitty::print_hex( f );
911 std::cout << "\n";
912 f._bits = dec_funcs[1];
913 std::cout << "Composition function: ";
914 kitty::print_hex( f );
915 std::cout << "\n";
916 }
917 }
918
919 template<typename TT_type>
920 void local_extend_to( TT_type& tt, uint32_t real_num_vars )
921 {
922 if ( real_num_vars < 6 )
923 {
924 auto mask = *tt.begin();
925
926 for ( auto i = real_num_vars; i < num_vars; ++i )
927 {
928 mask |= ( mask << ( 1 << i ) );
929 }
930
931 std::fill( tt.begin(), tt.end(), mask );
932 }
933 else
934 {
935 uint32_t num_blocks = ( 1u << ( real_num_vars - 6 ) );
936 auto it = tt.begin();
937 while ( it != tt.end() )
938 {
939 it = std::copy( tt.cbegin(), tt.cbegin() + num_blocks, it );
940 }
941 }
942 }
943
944 inline void reposition_late_arriving_variables( unsigned delay_profile, uint32_t late_arriving )
945 {
946 uint32_t k = 0;
947 for ( uint32_t i = 0; i < late_arriving; ++i )
948 {
949 while ( ( ( delay_profile >> k ) & 1 ) == 0 )
950 ++k;
951
952 if ( permutations[i] == k )
953 {
954 ++k;
955 continue;
956 }
957
958 std::swap( permutations[i], permutations[k] );
959 swap_inplace_local( best_tt, i, k );
960 ++k;
961 }
962 }
963
964 void swap_inplace_local( STT& tt, uint8_t var_index1, uint8_t var_index2 )
965 {
966 if ( var_index1 == var_index2 )
967 {
968 return;
969 }
970
971 if ( var_index1 > var_index2 )
972 {
973 std::swap( var_index1, var_index2 );
974 }
975
976 assert( num_vars > 6 );
977 const uint32_t num_blocks = 1 << ( num_vars - 6 );
978
979 if ( var_index2 <= 5 )
980 {
981 const auto& pmask = kitty::detail::ppermutation_masks[var_index1][var_index2];
982 const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 );
983 std::transform( std::begin( tt._bits ), std::begin( tt._bits ) + num_blocks, std::begin( tt._bits ),
984 [shift, &pmask]( uint64_t word ) {
985 return ( word & pmask[0] ) | ( ( word & pmask[1] ) << shift ) | ( ( word & pmask[2] ) >> shift );
986 } );
987 }
988 else if ( var_index1 <= 5 ) /* in this case, var_index2 > 5 */
989 {
990 const auto step = 1 << ( var_index2 - 6 );
991 const auto shift = 1 << var_index1;
992 auto it = std::begin( tt._bits );
993 while ( it != std::begin( tt._bits ) + num_blocks )
994 {
995 for ( auto i = decltype( step ){ 0 }; i < step; ++i )
996 {
997 const auto low_to_high = ( *( it + i ) & kitty::detail::projections[var_index1] ) >> shift;
998 const auto high_to_low = ( *( it + i + step ) << shift ) & kitty::detail::projections[var_index1];
999 *( it + i ) = ( *( it + i ) & ~kitty::detail::projections[var_index1] ) | high_to_low;
1000 *( it + i + step ) = ( *( it + i + step ) & kitty::detail::projections[var_index1] ) | low_to_high;
1001 }
1002 it += 2 * step;
1003 }
1004 }
1005 else
1006 {
1007 const auto step1 = 1 << ( var_index1 - 6 );
1008 const auto step2 = 1 << ( var_index2 - 6 );
1009 auto it = std::begin( tt._bits );
1010 while ( it != std::begin( tt._bits ) + num_blocks )
1011 {
1012 for ( auto i = 0; i < step2; i += 2 * step1 )
1013 {
1014 for ( auto j = 0; j < step1; ++j )
1015 {
1016 std::swap( *( it + i + j + step1 ), *( it + i + j + step2 ) );
1017 }
1018 }
1019 it += 2 * step2;
1020 }
1021 }
1022 }
1023
1024 inline bool has_var6( const LTT& tt, const LTT& care, uint8_t var_index )
1025 {
1026 if ( ( ( ( tt._bits >> ( uint64_t( 1 ) << var_index ) ) ^ tt._bits ) & kitty::detail::projections_neg[var_index] & ( care._bits >> ( uint64_t( 1 ) << var_index ) ) & care._bits ) != 0 )
1027 {
1028 return true;
1029 }
1030
1031 return false;
1032 }
1033
1034 void adjust_truth_table_on_dc( LTT& tt, LTT& care, uint32_t var_index )
1035 {
1036 uint64_t new_bits = tt._bits & care._bits;
1037 tt._bits = ( ( new_bits | ( new_bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index] ) |
1038 ( ( new_bits | ( new_bits << ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections[var_index] );
1039 care._bits = ( care._bits | ( care._bits >> ( uint64_t( 1 ) << var_index ) ) ) & kitty::detail::projections_neg[var_index];
1040 care._bits = care._bits | ( care._bits << ( uint64_t( 1 ) << var_index ) );
1041 }
1042
1043 /* Decomposition format for ABC
1044 *
1045 * The record is an array of unsigned chars where:
1046 * - the first unsigned char entry stores the number of unsigned chars in the record
1047 * - the second entry stores the number of LUTs
1048 * After this, several sub-records follow, each representing one LUT as follows:
1049 * - an unsigned char entry listing the number of fanins
1050 * - a list of fanins, from the LSB to the MSB of the truth table. The N inputs of the original function
1051 * have indexes from 0 to N-1, followed by the internal signals in a topological order
1052 * - the LUT truth table occupying 2^(M-3) bytes, where M is the fanin count of the LUT, from the LSB to the MSB.
1053 * A 2-input LUT, which takes 4 bits, should be stretched to occupy 8 bits (one unsigned char)
1054 * A 0- or 1-input LUT can be represented similarly but it is not expected that such LUTs will be represented
1055 */
1056 void get_decomposition_abc( unsigned char* decompArray )
1057 {
1058 unsigned char* pArray = decompArray;
1059 unsigned char bytes = 2;
1060
1061 /* write number of LUTs */
1062 pArray++;
1063 *pArray = 2;
1064 pArray++;
1065
1066 /* write BS LUT */
1067 /* write fanin size */
1068 *pArray = bs_support_size;
1069 pArray++;
1070 ++bytes;
1071
1072 /* write support */
1073 for ( uint32_t i = 0; i < bs_support_size; ++i )
1074 {
1075 *pArray = (unsigned char)permutations[bs_support[i] + best_free_set];
1076 pArray++;
1077 ++bytes;
1078 }
1079
1080 /* write truth table */
1081 uint32_t tt_num_bytes = ( bs_support_size <= 3 ) ? 1 : ( 1 << ( bs_support_size - 3 ) );
1082 for ( uint32_t i = 0; i < tt_num_bytes; ++i )
1083 {
1084 *pArray = (unsigned char)( ( dec_funcs[0] >> ( 8 * i ) ) & 0xFF );
1085 pArray++;
1086 ++bytes;
1087 }
1088
1089 /* write top LUT */
1090 /* write fanin size */
1091 uint32_t support_size = best_free_set + 1 + num_shared_vars;
1092 *pArray = support_size;
1093 pArray++;
1094 ++bytes;
1095
1096 /* write support */
1097 for ( uint32_t i = 0; i < best_free_set; ++i )
1098 {
1099 *pArray = (unsigned char)permutations[i];
1100 pArray++;
1101 ++bytes;
1102 }
1103
1104 *pArray = (unsigned char)num_vars;
1105 pArray++;
1106 ++bytes;
1107
1108 for ( uint32_t i = 0; i < num_shared_vars; ++i )
1109 {
1110 *pArray = (unsigned char)permutations[num_vars - num_shared_vars + i];
1111 pArray++;
1112 ++bytes;
1113 }
1114
1115 /* write truth table */
1116 tt_num_bytes = ( support_size <= 3 ) ? 1 : ( 1 << ( support_size - 3 ) );
1117 for ( uint32_t i = 0; i < tt_num_bytes; ++i )
1118 {
1119 *pArray = (unsigned char)( ( dec_funcs[1] >> ( 8 * i ) ) & 0xFF );
1120 pArray++;
1121 ++bytes;
1122 }
1123
1124 /* write numBytes */
1125 *decompArray = bytes;
1126 }
1127
1128 bool verify_impl()
1129 {
1130 /* create PIs */
1131 STT pis[max_num_vars];
1132 for ( uint32_t i = 0; i < num_vars; ++i )
1133 {
1134 kitty::create_nth_var( pis[i], permutations[i] );
1135 }
1136
1137 /* BS function patterns */
1138 STT bsi[6];
1139 for ( uint32_t i = 0; i < bs_support_size; ++i )
1140 {
1141 bsi[i] = pis[best_free_set + bs_support[i]];
1142 }
1143
1144 /* compute first function */
1145 STT bsf_sim;
1146 for ( uint32_t i = 0u; i < ( 1 << num_vars ); ++i )
1147 {
1148 uint32_t pattern = 0u;
1149 for ( auto j = 0; j < bs_support_size; ++j )
1150 {
1151 pattern |= get_bit( bsi[j], i ) << j;
1152 }
1153 if ( ( dec_funcs[0] >> pattern ) & 1 )
1154 {
1155 set_bit( bsf_sim, i );
1156 }
1157 }
1158
1159 /* compute first function */
1160 STT top_sim;
1161 for ( uint32_t i = 0u; i < ( 1 << num_vars ); ++i )
1162 {
1163 uint32_t pattern = 0u;
1164 for ( auto j = 0; j < best_free_set; ++j )
1165 {
1166 pattern |= get_bit( pis[j], i ) << j;
1167 }
1168 pattern |= get_bit( bsf_sim, i ) << best_free_set;
1169
1170 /* shared variables */
1171 for ( auto j = 0u; j < num_shared_vars; ++j )
1172 {
1173 pattern |= get_bit( pis[num_vars - num_shared_vars + j], i ) << ( best_free_set + 1 + j );
1174 }
1175
1176 if ( ( dec_funcs[1] >> pattern ) & 1 )
1177 {
1178 set_bit( top_sim, i );
1179 }
1180 }
1181
1182 for ( uint32_t i = 0; i < ( 1 << ( num_vars - 6 ) ); ++i )
1183 {
1184 if ( top_sim._bits[i] != start_tt._bits[i] )
1185 {
1186 /* convert to dynamic_truth_table */
1187 // report_tt( bsf_sim );
1188 std::cout << "Found incorrect decomposition\n";
1189 report_tt( top_sim );
1190 std::cout << " instead_of\n";
1191 report_tt( start_tt );
1192 return false;
1193 }
1194 }
1195
1196 return true;
1197 }
1198
1199 uint32_t get_bit( const STT& tt, uint64_t index )
1200 {
1201 return ( tt._bits[index >> 6] >> ( index & 0x3f ) ) & 0x1;
1202 }
1203
1204 void set_bit( STT& tt, uint64_t index )
1205 {
1206 tt._bits[index >> 6] |= uint64_t( 1 ) << ( index & 0x3f );
1207 }
1208
1209 void report_tt( STT const& stt )
1210 {
1211 kitty::dynamic_truth_table tt( num_vars );
1212
1213 std::copy( std::begin( stt._bits ), std::begin( stt._bits ) + ( 1 << ( num_vars - 6 ) ), std::begin( tt ) );
1214 kitty::print_hex( tt );
1215 std::cout << "\n";
1216 }
1217
1218private:
1219 uint32_t best_multiplicity{ UINT32_MAX };
1220 uint32_t best_free_set{ UINT32_MAX };
1221 uint32_t bs_support_size{ UINT32_MAX };
1222 uint32_t num_shared_vars{ 0 };
1223 STT best_tt;
1224 STT start_tt;
1225 uint64_t dec_funcs[2];
1226 uint32_t bs_support[6];
1227
1228 uint32_t const num_vars;
1229 bool const multiple_ss;
1230 bool const verify;
1231 std::array<uint32_t, max_num_vars> permutations;
1232};
1233
1234} // namespace acd
1235
1237
1238#endif // _ACD66_H_
unsigned int uint32_t
Definition Fxch.h:32
ABC_NAMESPACE_HEADER_START typedef unsigned char uint8_t
Definition Fxch.h:31
#define ABC_NAMESPACE_CXX_HEADER_START
#define ABC_NAMESPACE_CXX_HEADER_END
#define UINT32_MAX
Definition pstdint.h:388
int run(word *ptt, unsigned delay_profile)
Runs ACD 66.
Definition acd66.hpp:85
acd66_impl(uint32_t const num_vars, bool multiple_shared_set=false, bool const verify=false)
Definition acd66.hpp:60
uint32_t get_num_edges()
Definition acd66.hpp:127
unsigned get_profile()
Definition acd66.hpp:139
int compute_decomposition()
Definition acd66.hpp:112
void get_decomposition(unsigned char *decompArray)
Definition acd66.hpp:165
bool run(word *ptt)
Runs ACD 66.
Definition acd66.hpp:67
Cube * p
Definition exorList.c:222
unsigned __int64 word
DECLARATIONS ///.
Definition kitPerm.c:36
unsigned long long size
Definition giaNewBdd.h:39
void create_nth_var(TT &tt, uint8_t var_index, bool complement=false)
Constructs projections (single-variable functions)
void swap_inplace(TT &tt, uint8_t var_index1, uint8_t var_index2)
Swaps two variables in a truth table.
void print_hex(const TT &tt, std::ostream &os=std::cout)
Prints truth table in hexadecimal representation.
#define assert(ex)
Definition util_old.h:213