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