44 #pragma GCC diagnostic push 45 #pragma GCC diagnostic ignored "-Wswitch-enum" 47 #pragma region needed by mockturtle / algorithms / satlut_mapping.hpp 49 #define ABC_NAMESPACE pabc 50 #define ABC_NO_USE_READLINE 52 #define FMT_HEADER_ONLY 1 53 #define PHMAP_BIDIRECTIONAL 0 54 #define MCDBGQ_NOLOCKFREE_FREELIST 0 55 #define MCDBGQ_TRACKMEM 0 56 #define MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX 0 57 #define MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH 0 58 #define MCDBGQ_USEDEBUGFREELIST 0 60 #define MIG_SYNTHESIS 0 62 #include <kitty/print.hpp> 63 #include <mockturtle/algorithms/aig_resub.hpp> 64 #include <mockturtle/algorithms/balancing.hpp> 65 #include <mockturtle/algorithms/balancing/sop_balancing.hpp> 66 #include <mockturtle/algorithms/cleanup.hpp> 67 #include <mockturtle/algorithms/collapse_mapped.hpp> 68 #include <mockturtle/algorithms/cut_rewriting.hpp> 69 #include <mockturtle/algorithms/functional_reduction.hpp> 70 #include <mockturtle/algorithms/lut_mapping.hpp> 71 #include <mockturtle/algorithms/node_resynthesis.hpp> 72 #include <mockturtle/algorithms/node_resynthesis/bidecomposition.hpp> 73 #include <mockturtle/algorithms/node_resynthesis/dsd.hpp> 74 #include <mockturtle/algorithms/node_resynthesis/shannon.hpp> 75 #include <mockturtle/algorithms/node_resynthesis/xag_npn.hpp> 76 #include <mockturtle/algorithms/refactoring.hpp> 77 #include <mockturtle/generators/arithmetic.hpp> 78 #include <mockturtle/io/write_bench.hpp> 79 #include <mockturtle/networks/aig.hpp> 80 #include <mockturtle/networks/klut.hpp> 81 #include <mockturtle/views/mapping_view.hpp> 82 #include <type_traits> 84 #include <mockturtle/algorithms/mig_algebraic_rewriting.hpp> 85 #include <mockturtle/algorithms/node_resynthesis/mig_npn.hpp> 88 #include <mockturtle/algorithms/satlut_mapping.hpp> 115 #pragma region Macros declaration 151 bool is_simple_case = [&]() ->
bool {
158 return (
k == lt_expr_K ||
k == gt_expr_K) && cst_val == 0;
161 (is_simple_case && !
parameters->isOption(OPT_context_switch));
198 #define VECT_CONTAINS(v, x) (std::find((v).begin(), (v).end(), x) != (v).end()) 203 auto code = op_node->get_kind();
205 return !(GetPointer<lut_expr>(op_node) ||
206 (GetPointer<truth_not_expr>(op_node) &&
CHECK_NOT_EXPR_SIZE(GetPointer<truth_not_expr>(op_node))) ||
207 (GetPointer<bit_not_expr>(op_node) &&
CHECK_NOT_EXPR_SIZE(GetPointer<bit_not_expr>(op_node))) ||
213 parameters->GetParameter<
unsigned int>(
"MAX_LUT_INT_SIZE"))));
218 #pragma region Types declaration 226 void fix_inputs_size(std::vector<signal>* a, std::vector<signal>* b,
bool signedValues)
228 if(a->size() > b->size())
230 auto msbPos = b->size() - 1;
231 auto niter = a->size() - b->size();
232 for(
size_t i = 0; i < niter; ++i)
236 b->push_back(b->at(msbPos));
240 b->push_back(this->get_constant(
false));
244 else if(a->size() < b->size())
246 auto msbPos = a->size() - 1;
247 auto niter = b->size() - a->size();
248 for(
size_t i = 0; i < niter; ++i)
252 a->push_back(a->at(msbPos));
256 a->push_back(this->get_constant(
false));
264 kitty::dynamic_truth_table tt(bits * 2);
267 for(
unsigned int i = 0; i < bits; ++i)
269 for(
unsigned int j = i + 1; j < bits; ++j)
271 kitty::set_bit(tt, j + i * bits);
279 #pragma region single - bit operations 290 return this->create_not(this->create_lt(a, b));
303 return this->create_not(this->create_le(a, b));
316 return this->create_not(this->create_xor(a, b));
329 return this->create_xor(a, b);
333 #pragma region utilities 337 std::vector<signal> pis(size);
339 for(
size_t i = 0; i < size; ++i)
341 pis[i] = create_pi();
349 for(
size_t i = 0; i < pos.size(); ++i)
357 std::vector<signal> outputs;
360 outputs.push_back(b ==
false ? this->get_constant(
false) : this->create_not(this->get_constant(
false)));
379 return this->create_not(this->get_constant(
false));
381 kitty::dynamic_truth_table tt(static_cast<unsigned>(s.size()));
382 std::stringstream resHex;
383 resHex << std::hex << static_cast<unsigned long long>(f);
384 std::string res0 = resHex.str();
385 if(tt.num_vars() > 1)
387 while((res0.size() << 2) < tt.num_bits())
392 while((res0.size() << 2) > tt.num_bits() && tt.num_vars() > 1)
394 res0 = res0.substr(1);
397 kitty::create_from_hex_string(tt, res0);
398 return create_node(s, tt);
403 #pragma region multi - bit operations 412 std::vector<signal> outputs;
415 outputs.push_back(this->create_not(s));
420 std::vector<signal>
create_and_v(std::vector<signal>
const& a, std::vector<signal>
const& b,
bool signedValues)
422 std::vector<signal> a_c(a), b_c(b);
423 this->fix_inputs_size(&a_c, &b_c, signedValues);
425 std::vector<signal> outputs;
426 outputs.reserve(a_c.size());
427 std::transform(a_c.begin(), a_c.end(), b_c.begin(), std::back_inserter(outputs),
428 [&](
auto const& s1,
auto const& s2) {
return this->create_and(s1, s2); });
433 std::vector<signal>
create_or_v(std::vector<signal>
const& a, std::vector<signal>
const& b,
bool signedValues)
435 std::vector<signal> a_c(a), b_c(b);
436 this->fix_inputs_size(&a_c, &b_c, signedValues);
438 std::vector<signal> outputs;
439 outputs.reserve(a_c.size());
440 std::transform(a_c.begin(), a_c.end(), b_c.begin(), std::back_inserter(outputs),
441 [&](
auto const& s1,
auto const& s2) {
return this->create_or(s1, s2); });
446 std::vector<signal>
create_xor_v(std::vector<signal>
const& a, std::vector<signal>
const& b,
bool signedValues)
448 std::vector<signal> a_c(a), b_c(b);
449 this->fix_inputs_size(&a_c, &b_c, signedValues);
451 std::vector<signal> outputs;
452 outputs.reserve(a_c.size());
453 std::transform(a_c.begin(), a_c.end(), b_c.begin(), std::back_inserter(outputs),
454 [&](
auto const& s1,
auto const& s2) {
return this->create_xor(s1, s2); });
459 std::vector<signal>
create_lt_v(std::vector<signal>
const& a, std::vector<signal>
const& b,
bool signedValues)
461 std::vector<signal> a_c(a), b_c(b);
462 this->fix_inputs_size(&a_c, &b_c, signedValues);
466 a_c.push_back(this->get_constant(
false));
467 b_c.push_back(this->get_constant(
false));
469 a_c.push_back(a_c.at(a_c.size() - 1));
470 b_c.push_back(b_c.at(b_c.size() - 1));
472 signal cbit = this->create_not(this->get_constant(
false));
473 signal neg1,
result = this->get_constant(
false);
474 for(
auto column = 0u; column < a_c.size(); ++column)
476 neg1 = this->create_not(b_c.at(column));
477 std::tie(result, cbit) = mockturtle::full_adder(*
this, a_c.at(column), neg1, cbit);
482 std::vector<signal>
create_ge_v(std::vector<signal>
const& a, std::vector<signal>
const& b,
bool signedValues)
484 auto lt_res = this->create_lt_v(a, b, signedValues);
485 return {this->create_not(lt_res.at(0))};
488 std::vector<signal>
create_gt_v(std::vector<signal>
const& a, std::vector<signal>
const& b,
bool signedValues)
490 return this->create_lt_v(b, a, signedValues);
493 std::vector<signal>
create_le_v(std::vector<signal>
const& a, std::vector<signal>
const& b,
bool signedValues)
495 return this->create_ge_v(b, a, signedValues);
498 std::vector<signal>
create_eq_v(std::vector<signal>
const& a, std::vector<signal>
const& b,
bool signedValues)
500 std::vector<signal> a_c(a), b_c(b);
501 this->fix_inputs_size(&a_c, &b_c, signedValues);
503 std::vector<signal> outputs;
504 outputs.reserve(a_c.size());
505 std::transform(a_c.begin(), a_c.end(), b_c.begin(), std::back_inserter(outputs),
506 [&](
auto const& s1,
auto const& s2) {
return this->create_eq(s1, s2); });
508 return {this->create_nary_and(outputs)};
511 std::vector<signal>
create_ne_v(std::vector<signal>
const& a, std::vector<signal>
const& b,
bool signedValues)
513 return this->create_not_v(this->create_eq_v(a, b, signedValues));
541 explicit klut_network_node(uint64_t _index,
long long _lut_constant,
const std::vector<uint64_t>& _fan_in,
542 bool _is_po, uint64_t _po_index,
bool _is_constant)
544 lut_constant(_lut_constant),
548 is_constant(_is_constant)
558 const mockturtle::klut_network::signal);
565 const std::vector<mockturtle::klut_network::signal>&,
const std::vector<mockturtle::klut_network::signal>&,
bool);
576 auto ssa = GetPointer<ssa_name>(
GET_NODE(in));
582 if(def_stmt->
get_kind() != gimple_assign_K)
586 auto* gaDef = GetPointer<gimple_assign>(def_stmt);
587 if(gaDef->bb_index != BB_index)
604 for(
const auto& statement : block.second->CGetStmtList())
608 if(
GET_NODE(statement)->get_kind() != gimple_assign_K)
613 auto* gimpleAssign = GetPointer<gimple_assign>(
GET_NODE(statement));
614 enum kind code =
GET_NODE(gimpleAssign->op1)->get_kind();
616 if(code == lut_expr_K)
618 auto* lut = GetPointer<lut_expr>(
GET_NODE(gimpleAssign->op1));
621 for(
auto node : {lut->op1, lut->op2, lut->op3, lut->op4, lut->op5, lut->op6, lut->op7, lut->op8})
630 if(GetPointer<integer_cst>(
GET_NODE(node)))
633 "---CheckIfProcessable: lut with a constant input returns true");
641 "---CheckIfProcessable: " +
GET_NODE(gimpleAssign->op1)->get_kind_text() +
" can be a LUT");
659 const unsigned int currentBBIndex = gimpleAssign->
bb_index;
662 auto ssa0 = GetPointer<ssa_name>(op0);
664 const auto usedIn = ssa0->CGetUseStmts();
666 for(
auto node : usedIn)
668 auto* childGimpleNode = GetPointer<gimple_node>(
GET_NODE(node.first));
675 if(childGimpleNode->bb_index != currentBBIndex)
681 auto* childGimpleAssign = GetPointer<gimple_assign>(
GET_NODE(node.first));
682 if(!childGimpleAssign)
700 case truth_and_expr_K:
701 return &klut_network_ext::create_and;
703 case truth_or_expr_K:
704 case truth_orif_expr_K:
705 return &klut_network_ext::create_or;
707 case truth_xor_expr_K:
708 return &klut_network_ext::create_xor;
716 return &klut_network_ext::create_le;
718 return &klut_network_ext::create_lt;
728 const auto oldbits = [&]() {
729 std::vector<bool> bits;
730 for(
size_t i = 0; i < size; ++i)
732 bits.push_back((static_cast<unsigned long long int>(n) & (1ULL << i)) ?
true :
false);
736 std::vector<bool> bits;
737 for(
size_t i = 0; i < size; ++i)
739 bits.push_back((n & (
integer_cst_t(1) << i)) ?
true :
false);
747 std::vector<tree_nodeRef>& prev_stmts_to_add)
751 const std::string srcp_default(
"built-in:0:0");
757 prev_stmts_to_add.push_back(eb_ga);
758 return GetPointer<const gimple_assign>(
GET_CONST_NODE(eb_ga))->op0;
783 static std::string
ConvertBitsToString(
const std::vector<bool>& bits,
const std::string& true_string =
"vdd",
784 const std::string& false_string =
"gnd",
const std::string& sep =
", ")
788 for(
size_t i = 0; i < bits.size(); ++i)
794 s += bits[i] ? true_string : false_string;
801 template <
typename T>
805 std::stringstream ss;
806 ss << std::hex << hex0;
812 static void ParseKLutNetwork(
const mockturtle::klut_network& klut, std::vector<klut_network_node>& luts)
814 std::map<mockturtle::klut_network::node, CustomOrderedSet<unsigned>> po_set;
816 mockturtle::topo_view ntk_topo{klut};
818 ntk_topo.foreach_po([&](
auto const& s,
auto i) { po_set[s].insert(i); });
820 ntk_topo.foreach_node([&](
const auto& node) {
821 if(ntk_topo.is_pi(node) || ntk_topo.is_constant(node))
825 auto func = ntk_topo.node_function(node);
827 std::vector<uint64_t> fanIns;
828 ntk_topo.foreach_fanin(node, [&](
auto const& fanin_node,
auto) { fanIns.push_back(fanin_node); });
829 auto LUT_func = ConvertHexToNumber<long long>(kitty::to_hex(func));
830 auto is_zero = LUT_func == 0;
833 if(po_set.find(node) != po_set.end())
835 for(
auto po_i : po_set.find(node)->second)
838 luts.push_back(lut_node);
844 luts.push_back(lut_node);
849 ntk_topo.foreach_po([&](
auto const& s,
auto i) {
850 if(ntk_topo.is_constant(ntk_topo.get_node(s)))
852 std::vector<uint64_t> fanIns;
854 s, static_cast<long long>(ntk_topo.constant_value(ntk_topo.get_node(s)) ^ ntk_topo.is_complemented(s)),
855 fanIns,
true, i,
true);
856 luts.push_back(lut_node);
860 auto func = ntk_topo.node_function(s);
861 auto LUT_func = ConvertHexToNumber<uint64_t>(kitty::to_hex(func));
862 auto is_zero = LUT_func == 0;
865 std::vector<uint64_t> fanIns;
867 s, static_cast<long long>(ntk_topo.constant_value(ntk_topo.get_node(s)) ^ ntk_topo.is_complemented(s)),
868 fanIns,
true, i,
true);
869 luts.push_back(lut_node);
871 else if(ntk_topo.is_pi(ntk_topo.get_node(s)))
873 std::vector<uint64_t> fanIns;
875 klut_network_node lut_node(s, static_cast<long long>(ntk_topo.is_complemented(s) ? 1 : 2), fanIns,
true, i,
877 luts.push_back(lut_node);
888 mockturtle::shannon_resynthesis<mockturtle::mig_network> fallback;
889 mockturtle::dsd_resynthesis<mockturtle::mig_network, decltype(fallback)> mig_resyn(fallback);
890 auto mig0 = mockturtle::node_resynthesis<mockturtle::mig_network>(klut_e, mig_resyn);
891 auto resyn2 = [&](mockturtle::mig_network& mig) -> mockturtle::mig_network {
892 mockturtle::depth_view mig_depth{mig};
894 mockturtle::mig_algebraic_depth_rewriting_params pm;
899 mockturtle::mig_algebraic_depth_rewriting(mig_depth, pm);
901 mig = mockturtle::cleanup_dangling(mig);
906 mockturtle::mig_npn_resynthesis resyn;
907 mockturtle::cut_rewriting_params ps;
909 ps.cut_enumeration_ps.cut_size = 4;
911 mockturtle::cut_rewriting(mig, resyn, ps);
912 mig = mockturtle::cleanup_dangling(mig);
917 mockturtle::cut_rewriting(mig, resyn, ps);
918 mig = mockturtle::cleanup_dangling(mig);
923 mockturtle::depth_view mig_depth1{mig};
925 mockturtle::mig_algebraic_depth_rewriting(mig_depth1, pm);
926 mig = mockturtle::cleanup_dangling(mig);
931 mockturtle::cut_rewriting(mig, resyn, ps);
932 mig = mockturtle::cleanup_dangling(mig);
937 mockturtle::cut_rewriting(mig, resyn, ps);
938 mig = mockturtle::cleanup_dangling(mig);
943 mockturtle::depth_view mig_depth2{mig};
945 mockturtle::mig_algebraic_depth_rewriting(mig_depth2, pm);
946 mig = mockturtle::cleanup_dangling(mig);
951 mockturtle::cut_rewriting(mig, resyn, ps);
952 mig = mockturtle::cleanup_dangling(mig);
957 mockturtle::cut_rewriting(mig, resyn, ps);
958 mig = mockturtle::cleanup_dangling(mig);
963 mockturtle::depth_view mig_depth3{mig};
967 mockturtle::mig_algebraic_depth_rewriting(mig_depth3, pm);
968 mig = mockturtle::cleanup_dangling(mig);
975 auto cleanedUp = mockturtle::cleanup_dangling(mig0);
977 mockturtle::mapping_view<mockturtle::mig_network, true> mapped_klut{cleanedUp};
978 std::cerr <<
"std\n";
979 mockturtle::write_bench(mapped_klut, std::cout);
980 std::cerr <<
"===============\n";
982 mockturtle::lut_mapping_params mp;
983 mp.cut_enumeration_ps.cut_size =
static_cast<uint32_t
>(
max_lut_size);
984 mp.cut_enumeration_ps.cut_limit = 16;
988 mp.cut_enumeration_ps.very_verbose =
false;
991 mockturtle::lut_mapping<decltype(mapped_klut), true>(mapped_klut, mp);
992 std::cerr <<
"lut\n";
993 std::cerr <<
"===============\n";
994 mockturtle::write_bench(mapped_klut, std::cout);
996 auto collapsed = *mockturtle::collapse_mapped_network<mockturtle::klut_network>(mapped_klut);
997 collapsed = mockturtle::cleanup_luts(collapsed);
998 std::cerr <<
"res\n";
999 mockturtle::write_bench(collapsed, std::cout);
1000 std::cerr <<
"===============\n";
1003 mockturtle::shannon_resynthesis<mockturtle::aig_network> fallback;
1004 mockturtle::dsd_resynthesis<mockturtle::aig_network, decltype(fallback)> aig_resyn(fallback);
1005 auto aig = mockturtle::node_resynthesis<mockturtle::aig_network>(klut_e, aig_resyn);
1008 auto resyn2 = [&](mockturtle::aig_network& aig) -> mockturtle::aig_network {
1009 mockturtle::xag_npn_resynthesis<mockturtle::aig_network> resyn;
1010 mockturtle::cut_rewriting_params ps;
1011 ps.cut_enumeration_ps.cut_size = 4;
1013 mockturtle::cut_rewriting(aig, resyn, ps);
1014 aig = mockturtle::cleanup_dangling(aig);
1015 mockturtle::cut_rewriting(aig, resyn, ps);
1016 aig = mockturtle::cleanup_dangling(aig);
1018 mockturtle::cut_rewriting(aig, resyn, ps);
1019 aig = mockturtle::cleanup_dangling(aig);
1021 mockturtle::cut_rewriting(aig, resyn, ps);
1022 aig = mockturtle::cleanup_dangling(aig);
1024 mockturtle::cut_rewriting(aig, resyn, ps);
1025 aig = mockturtle::cleanup_dangling(aig);
1027 mockturtle::cut_rewriting(aig, resyn, ps);
1028 aig = mockturtle::cleanup_dangling(aig);
1030 mockturtle::cut_rewriting(aig, resyn, ps);
1031 aig = mockturtle::cleanup_dangling(aig);
1033 mockturtle::cut_rewriting(aig, resyn, ps);
1034 aig = mockturtle::cleanup_dangling(aig);
1036 mockturtle::cut_rewriting(aig, resyn, ps);
1037 aig = mockturtle::cleanup_dangling(aig);
1039 mockturtle::cut_rewriting(aig, resyn, ps);
1040 aig = mockturtle::cleanup_dangling(aig);
1045 auto resyn2_v2 = [&](mockturtle::aig_network& aig) -> mockturtle::aig_network {
1046 mockturtle::xag_npn_resynthesis<mockturtle::aig_network> resyn;
1047 mockturtle::bidecomposition_resynthesis<mockturtle::aig_network> fallback;
1048 mockturtle::dsd_resynthesis<mockturtle::aig_network, decltype( fallback )> rf_resyn( fallback );
1049 mockturtle::cut_rewriting_params ps;
1050 mockturtle::refactoring_params rp;
1052 ps.cut_enumeration_ps.cut_size = 4;
1053 rp.allow_zero_gain =
false;
1055 aig= mockturtle::balancing(aig, {mockturtle::sop_rebalancing<mockturtle::aig_network>{}});
1056 aig = mockturtle::cleanup_dangling(aig);
1058 mockturtle::cut_rewriting(aig, resyn, ps);
1059 aig = mockturtle::cleanup_dangling(aig);
1061 mockturtle::refactoring(aig, rf_resyn, rp);
1062 aig = mockturtle::cleanup_dangling(aig);
1064 aig= mockturtle::balancing(aig, {mockturtle::sop_rebalancing<mockturtle::aig_network>{}});
1065 aig = mockturtle::cleanup_dangling(aig);
1067 mockturtle::cut_rewriting(aig, resyn, ps);
1068 aig = mockturtle::cleanup_dangling(aig);
1070 ps.allow_zero_gain =
true;
1071 mockturtle::cut_rewriting(aig, resyn, ps);
1072 aig = mockturtle::cleanup_dangling(aig);
1074 aig= mockturtle::balancing(aig, {mockturtle::sop_rebalancing<mockturtle::aig_network>{}});
1075 aig = mockturtle::cleanup_dangling(aig);
1077 rp.allow_zero_gain =
true;
1078 mockturtle::refactoring(aig, rf_resyn, rp);
1079 aig = mockturtle::cleanup_dangling(aig);
1081 mockturtle::cut_rewriting(aig, resyn, ps);
1082 aig = mockturtle::cleanup_dangling(aig);
1084 aig= mockturtle::balancing(aig, {mockturtle::sop_rebalancing<mockturtle::aig_network>{}});
1085 aig = mockturtle::cleanup_dangling(aig);
1090 auto cleanedUp = resyn2(aig);
1092 auto cleanedUp = cleanup_dangling(aig);
1094 mockturtle::mapping_view<mockturtle::aig_network, true> mapped_klut{cleanedUp};
1099 mockturtle::lut_mapping_params mp;
1100 mp.cut_enumeration_ps.cut_size =
static_cast<uint32_t
>(
max_lut_size);
1101 mp.cut_enumeration_ps.cut_limit = 16;
1105 mp.cut_enumeration_ps.very_verbose =
false;
1108 mockturtle::lut_mapping<decltype(mapped_klut), true>(mapped_klut, mp);
1114 mockturtle::satlut_mapping_params satlut_mp;
1116 satlut_mp.cut_enumeration_ps.cut_limit = 16;
1117 satlut_mp.conflict_limit = 100;
1118 satlut_mp.progress =
true;
1119 mockturtle::satlut_mapping_stats st;
1121 mockturtle::satlut_mapping<decltype(mapped_klut), true>(mapped_klut, 32, satlut_mp, &st);
1122 std::cerr <<
"sat\n";
1123 std::cerr <<
"===============\n";
1124 mockturtle::write_bench(mapped_klut, std::cout);
1126 auto collapsed = *mockturtle::collapse_mapped_network<mockturtle::klut_network>(mapped_klut);
1127 collapsed = mockturtle::cleanup_luts(collapsed);
1138 auto BB_index = block.first;
1140 std::map<unsigned int, mockturtle::klut_network::signal> nodeRefToSignal;
1141 std::map<unsigned int, std::vector<mockturtle::klut_network::signal>> nodeRefToSignalBus;
1143 std::vector<tree_nodeRef> pis;
1144 std::vector<int> pis_offset;
1145 std::vector<tree_nodeRef> pos;
1146 std::vector<unsigned> pos_offset;
1154 pis_offset.push_back(0);
1160 pis_offset.push_back(0);
1163 const auto& statements = block.second->CGetStmtList();
1166 bool modified =
false;
1168 for(
const auto& statement : statements)
1172 if(!
AppM->ApplyNewTransformation())
1178 if(
GET_NODE(statement)->get_kind() != gimple_assign_K)
1184 auto* gimpleAssign = GetPointer<gimple_assign>(
GET_NODE(statement));
1185 enum kind code1 =
GET_NODE(gimpleAssign->op1)->get_kind();
1187 "---Analyzing code " +
GET_NODE(gimpleAssign->op1)->get_kind_text());
1189 if(code1 == lut_expr_K)
1191 auto* le = GetPointer<lut_expr>(
GET_NODE(gimpleAssign->op1));
1193 std::vector<mockturtle::klut_network::signal> ops;
1194 for(
auto op : {le->op1, le->op2, le->op3, le->op4, le->op5, le->op6, le->op7, le->op8})
1202 if(nodeRefToSignal.find(
GET_INDEX_NODE(op)) != nodeRefToSignal.end())
1209 mockturtle::klut_network::signal kop = 0;
1211 if(
GET_NODE(op)->get_kind() == integer_cst_K)
1214 kop = cst_val == 0 ? klut_e.get_constant(
false) : klut_e.create_not(klut_e.get_constant(
false));
1221 kop = klut_e.create_pi();
1223 pis_offset.push_back(0);
1239 "Cast will change signedness of current value: " +
STR(cst_val));
1240 auto res = klut_e.
create_lut(ops, static_cast<long long>(cst_val));
1246 klut_e.create_po(res);
1247 pos.push_back(statement);
1248 pos_offset.push_back(0);
1258 if(code1 == truth_not_expr_K || code1 == bit_not_expr_K)
1260 auto* ne = GetPointer<unary_expr>(
GET_NODE(gimpleAssign->op1));
1267 std::vector<mockturtle::klut_network::signal> ops;
1268 for(
auto op : {ne->op})
1271 if(nodeRefToSignal.find(
GET_INDEX_NODE(op)) != nodeRefToSignal.end())
1278 mockturtle::klut_network::signal kop = 0;
1280 if(
GET_NODE(op)->get_kind() == integer_cst_K)
1283 kop = cst_val == 0 ? klut_e.get_constant(
false) : klut_e.create_not(klut_e.get_constant(
false));
1289 kop = klut_e.create_pi();
1291 pis_offset.push_back(0);
1304 auto res = klut_e.create_not(ops.at(0));
1310 klut_e.create_po(res);
1311 pos.push_back(statement);
1312 pos_offset.push_back(0);
1324 if(code1 == cond_expr_K)
1326 auto* ce = GetPointer<cond_expr>(
GET_NODE(gimpleAssign->op1));
1333 std::vector<mockturtle::klut_network::signal> ops;
1334 for(
auto op : {ce->op0, ce->op1, ce->op2})
1337 if(nodeRefToSignal.find(
GET_INDEX_NODE(op)) != nodeRefToSignal.end())
1344 mockturtle::klut_network::signal kop = 0;
1346 if(
GET_NODE(op)->get_kind() == integer_cst_K)
1349 kop = cst_val == 0 ? klut_e.get_constant(
false) : klut_e.create_not(klut_e.get_constant(
false));
1355 kop = klut_e.create_pi();
1357 pis_offset.push_back(0);
1370 auto res = klut_e.create_ite(ops.at(0), ops.at(1), ops.at(2));
1376 klut_e.create_po(res);
1377 pos.push_back(statement);
1378 pos_offset.push_back(0);
1390 auto* binaryExpression = GetPointer<binary_expr>(
GET_NODE(gimpleAssign->op1));
1391 if(!binaryExpression)
1403 if(nodeCreateFn ==
nullptr)
1411 mockturtle::klut_network::signal res;
1412 mockturtle::klut_network::signal op1 = 0;
1413 mockturtle::klut_network::signal op2 = 0;
1416 if(nodeRefToSignal.find(
GET_INDEX_NODE(binaryExpression->op0)) != nodeRefToSignal.end())
1419 "---used PI " +
GET_NODE(binaryExpression->op0)->ToString());
1424 if(
GET_NODE(binaryExpression->op0)->get_kind() == integer_cst_K)
1427 op1 = cst_val == 0 ? klut_e.get_constant(
false) : klut_e.create_not(klut_e.get_constant(
false));
1430 else if(
CheckIfPI(binaryExpression->op0, BB_index))
1433 "---used PI " +
GET_NODE(binaryExpression->op0)->ToString());
1434 op1 = klut_e.create_pi();
1435 pis.push_back(binaryExpression->op0);
1436 pis_offset.push_back(0);
1446 if(nodeRefToSignal.find(
GET_INDEX_NODE(binaryExpression->op1)) != nodeRefToSignal.end())
1449 "---used PI " +
GET_NODE(binaryExpression->op1)->ToString());
1454 if(
GET_NODE(binaryExpression->op1)->get_kind() == integer_cst_K)
1457 op2 = cst_val == 0 ? klut_e.get_constant(
false) : klut_e.create_not(klut_e.get_constant(
false));
1460 else if(
CheckIfPI(binaryExpression->op1, BB_index))
1463 "---used PI " +
GET_NODE(binaryExpression->op1)->ToString());
1464 op2 = klut_e.create_pi();
1465 pis.push_back(binaryExpression->op1);
1466 pis_offset.push_back(0);
1475 res = (klut_e.*nodeCreateFn)(op1, op2);
1481 klut_e.create_po(res);
1482 pos.push_back(statement);
1483 pos_offset.push_back(0);
1500 if(nodeCreateFn ==
nullptr)
1508 std::vector<mockturtle::klut_network::signal> res;
1509 std::vector<mockturtle::klut_network::signal> op1 = {};
1510 std::vector<mockturtle::klut_network::signal> op2 = {};
1513 if(nodeRefToSignalBus.find(
GET_INDEX_NODE(binaryExpression->op0)) != nodeRefToSignalBus.end())
1516 "---used PI " +
GET_NODE(binaryExpression->op0)->ToString());
1521 if(
GET_NODE(binaryExpression->op0)->get_kind() == integer_cst_K)
1529 else if(
CheckIfPI(binaryExpression->op0, BB_index))
1532 "---used PIs " +
GET_NODE(binaryExpression->op0)->ToString());
1536 std::for_each(op1.begin(), op1.end(), [&binaryExpression, &pis, &pis_offset, &
index](
auto ) {
1537 pis.push_back(binaryExpression->op0);
1538 pis_offset.push_back(index);
1551 if(nodeRefToSignalBus.find(
GET_INDEX_NODE(binaryExpression->op1)) != nodeRefToSignalBus.end())
1554 "---used PI " +
GET_NODE(binaryExpression->op1)->ToString());
1559 if(
GET_NODE(binaryExpression->op1)->get_kind() == integer_cst_K)
1567 else if(
CheckIfPI(binaryExpression->op1, BB_index))
1570 "---used PIs " +
GET_NODE(binaryExpression->op1)->ToString());
1574 std::for_each(op2.begin(), op2.end(), [&binaryExpression, &pis, &pis_offset, &
index](
auto ) {
1575 pis.push_back(binaryExpression->op1);
1576 pis_offset.push_back(index);
1588 res = (klut_e.*nodeCreateFn)(op1, op2, isSigned);
1599 unsigned int index = 0;
1600 std::for_each(res.begin(), res.end(), [&statement, &pos, &pos_offset, &
index](
auto ) {
1601 pos.push_back(statement);
1602 pos_offset.push_back(index);
1629 mockturtle::write_bench(klut, std::cout);
1632 std::vector<klut_network_node> luts;
1635 std::map<mockturtle::klut_network::node, tree_nodeRef> internal_nets;
1636 std::vector<tree_nodeRef> prev_stmts_to_add;
1637 for(
auto lut : luts)
1639 if(!
AppM->ApplyNewTransformation())
1649 for(
auto in : lut.fan_in)
1655 auto po_stmpt = pos.at(lut.po_index);
1657 for(
auto stmt : prev_stmts_to_add)
1661 block.second->PushBefore(stmt, po_stmpt,
AppM);
1663 prev_stmts_to_add.clear();
1668 for(
auto in : lut.fan_in)
1673 operand = pis.at(in);
1674 auto operand_offset = pis_offset.at(in);
1678 THROW_ASSERT(operand_offset == 0,
"unexpected condition");
1686 else if(internal_nets.find(in) != internal_nets.end())
1688 operand = internal_nets.find(in)->second;
1699 else if(p_index == 2)
1703 else if(p_index == 3)
1707 else if(p_index == 4)
1711 else if(p_index == 5)
1715 else if(p_index == 6)
1719 else if(p_index == 7)
1723 else if(p_index == 8)
1736 auto po_stmpt = pos.at(lut.po_index);
1739 for(
auto stmt : prev_stmts_to_add)
1743 block.second->PushBefore(stmt, po_stmpt,
AppM);
1745 prev_stmts_to_add.clear();
1748 auto* gimpleAssign = GetPointer<gimple_assign>(
GET_NODE(po_stmpt));
1750 const std::string srcp_default = gimpleAssign->include_name +
":" +
STR(gimpleAssign->line_number) +
":" +
1751 STR(gimpleAssign->column_number);
1752 auto ga_op0 =
GET_NODE(gimpleAssign->op0);
1753 auto* ssa_ga_op0 = GetPointer<ssa_name>(ga_op0);
1755 if(!lut.is_constant)
1757 internal_nets[lut.index] = gimpleAssign->op0;
1765 else if(lut.fan_in.size() == 1 && lut.lut_constant == 2)
1771 "---Replacing " +
STR(gimpleAssign->op1) +
" with " +
STR(op1));
1776 const auto new_op1 =
1779 "---Replacing " +
STR(gimpleAssign->op1) +
" with " +
STR(new_op1));
1787 auto check_lut_compatibility = [&](
tree_nodeRef& lut_operand) {
1792 block.second->PushBefore(ga_nop, po_stmpt,
AppM);
1793 lut_operand = GetPointer<gimple_assign>(
GET_NODE(ga_nop))->op0;
1796 check_lut_compatibility(op1);
1797 check_lut_compatibility(op2);
1798 check_lut_compatibility(op3);
1799 check_lut_compatibility(op4);
1800 check_lut_compatibility(op5);
1801 check_lut_compatibility(op6);
1802 check_lut_compatibility(op7);
1803 check_lut_compatibility(op8);
1807 op4, op5, op6, op7, op8, srcp_default);
1809 "---Replacing " +
STR(gimpleAssign->op1) +
" with " +
STR(op1));
1815 op5, op6, op7, op8, srcp_default);
1821 block.second->PushBefore(lut_ga, po_stmpt,
AppM);
1822 auto ssa_vd = GetPointer<gimple_assign>(
GET_NODE(lut_ga))->op0;
1826 "---Replacing " +
STR(gimpleAssign->op1) +
" with " +
STR(op1));
1830 AppM->RegisterTransformation(
GetName(), po_stmpt);
1838 auto check_lut_compatibility = [&](
tree_nodeRef& lut_operand) {
1843 prev_stmts_to_add.push_back(ga_nop);
1844 lut_operand = GetPointer<gimple_assign>(
GET_NODE(ga_nop))->op0;
1847 check_lut_compatibility(op1);
1848 check_lut_compatibility(op2);
1849 check_lut_compatibility(op3);
1850 check_lut_compatibility(op4);
1851 check_lut_compatibility(op5);
1852 check_lut_compatibility(op6);
1853 check_lut_compatibility(op7);
1854 check_lut_compatibility(op8);
1860 auto ssa_vd = GetPointer<gimple_assign>(
GET_NODE(lut_ga))->op0;
1861 prev_stmts_to_add.push_back(lut_ga);
1862 internal_nets[lut.index] = ssa_vd;
1865 THROW_ASSERT(prev_stmts_to_add.empty(),
"unexpected condition");
1868 auto nStmts = statements.size();
1872 block.second->ReorderLUTs();
1875 THROW_ASSERT(nStmts == statements.size(),
"unexpected result");
1883 #pragma region Life cycle 1886 unsigned int _function_id,
const DesignFlowManagerConstRef _design_flow_manager)
1899 switch(relationship_type)
1903 if(!
parameters->getOption<
int>(OPT_gcc_openmp_simd))
1905 relationships.insert(std::make_pair(BITVALUE_RANGE,
SAME_FUNCTION));
1907 relationships.insert(std::make_pair(CSE_STEP,
SAME_FUNCTION));
1908 relationships.insert(std::make_pair(DEAD_CODE_ELIMINATION_IPA,
WHOLE_APPLICATION));
1913 relationships.insert(std::make_pair(DEAD_CODE_ELIMINATION,
SAME_FUNCTION));
1920 if(!
parameters->getOption<
int>(OPT_gcc_openmp_simd))
1922 relationships.insert(std::make_pair(BIT_VALUE,
SAME_FUNCTION));
1924 relationships.insert(std::make_pair(DEAD_CODE_ELIMINATION,
SAME_FUNCTION));
1931 return relationships;
1937 switch(relationship_type)
1944 const auto technology_flow_step_factory = GetPointerS<const TechnologyFlowStepFactory>(
1946 const auto technology_flow_signature =
1949 const auto technology_design_flow_step =
1950 technology_flow_step ?
1951 design_flow_graph->CGetDesignFlowStepInfo(technology_flow_step)->design_flow_step :
1953 relationship.insert(technology_design_flow_step);
1967 TM =
AppM->get_tree_manager();
1969 THROW_ASSERT(GetPointer<const HLS_manager>(
AppM)->get_HLS_device(),
"unexpected condition");
1970 const auto hls_d = GetPointerS<const HLS_manager>(
AppM)->get_HLS_device();
1971 THROW_ASSERT(hls_d->has_parameter(
"max_lut_size"),
"unexpected condition");
1972 max_lut_size = hls_d->get_parameter<
size_t>(
"max_lut_size");
1978 (
parameters->IsParameter(
"lut-transformation") && !
parameters->GetParameter<
unsigned int>(
"lut-transformation")))
1983 THROW_ASSERT(fd && fd->body,
"Node is not a function or it has not a body");
1984 const auto sl = GetPointer<const statement_list>(
GET_CONST_NODE(fd->body));
1987 bool modified =
false;
1988 for(std::pair<unsigned int, blocRef>
block :
sl->list_of_bloc)
2006 #pragma GCC diagnostic pop #define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
static bool IsComplexType(const tree_nodeConstRef &type)
Return if treenode is a complex.
Data structure representing the entire HLS information.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
File containing functions and utilities to support the printing of debug messagges.
static bool is_int(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode is of integer type.
Step successfully executed.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
void ReplaceTreeNode(const tree_nodeRef &stmt, const tree_nodeRef &old_node, const tree_nodeRef &new_node)
Replace the occurrences of tree node old_node with new_node in statement identified by tn...
Definition of the class representing a generic C application.
refcount< tree_manipulation > tree_manipulationRef
kitty::dynamic_truth_table create_lt_tt(unsigned int bits)
std::string GetName() const override
Return the name of this design step.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
mathematical utility function not provided by standard libraries
std::vector< signal > create_eq_v(std::vector< signal > const &a, std::vector< signal > const &b, bool signedValues)
std::vector< signal > create_pi_v(size_t size)
std::vector< signal > get_constant_v(std::vector< bool > bits)
bool is_constant
true in case the node is a constant value
Collect information about resource performance.
struct definition of the unary node structures.
tree_nodeRef op0
The first operand of the binary expression.
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
tree_nodeRef op1
The second operand of the binary expression.
Class specification of the manager of the technology library data structures.
Data structure describing a basic block at tree level.
signal create_ne(signal const a, signal const b)
Creates a 'not equal' operation.
tree_nodeRef create_unary_operation(const tree_nodeConstRef &type, const tree_nodeRef &op, const std::string &srcp, enum kind operation_kind) const
EXPRESSION_TREE_NODES.
const tree_nodeConstRef CGetTreeNode(const unsigned int i) const
std::vector< signal > create_or_v(std::vector< signal > const &a, std::vector< signal > const &b, bool signedValues)
tree_nodeRef CreateGimpleAssign(const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, const tree_nodeRef &op, unsigned int function_decl_nid, const std::string &srcp) const
Create gimple assignment.
std::vector< signal > create_xor_v(std::vector< signal > const &a, std::vector< signal > const &b, bool signedValues)
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
void ComputeRelationships(DesignFlowStepSet &relationship, const DesignFlowStep::RelationshipType relationship_type) override
Compute the relationships of a step with other steps.
uint64_t po_index
in case the current node is a primary output, holds the index of the primary output ...
static bool IsSignedIntegerType(const tree_nodeConstRef &type)
Return true if the treenode is of integer type.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
tree_nodeRef create_lut_expr(const tree_nodeConstRef &type, const tree_nodeRef &op0, const tree_nodeRef &op1, const tree_nodeRef &op2, const tree_nodeRef &op3, const tree_nodeRef &op4, const tree_nodeRef &op5, const tree_nodeRef &op6, const tree_nodeRef &op7, const tree_nodeRef &op8, const std::string &srcp) const
create_lut_expr: function used to create a generic lut_expr operation
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
static bool IsBooleanType(const tree_nodeConstRef &type)
Return true if the treenode is of bool type.
unsigned int bb_index
The basic block to which this gimple_node belongs.
This struct specifies the gimple_assign node (GCC 4.3 tree node).
std::vector< signal > create_not_v(std::vector< signal > const &a)
static const uint32_t k[]
Class specification of the data structures used to manage technology information. ...
signal create_lut(std::vector< signal > s, long long f)
Creates a 'lut' operation from an std::vector of mockturtle::klut_network::signal with the associated...
bool is_po
whether the current node is a primary output
Classes to describe design flow graph.
tree_nodeRef CreateUniqueIntegerCst(integer_cst_t value, const tree_nodeConstRef &type)
memoization of integer constants
Target must be reexecuted.
static const std::string ComputeSignature(const TechnologyFlowStep_Type technology_flow_step_type)
Compute the signature of a technology flow step.
Factory for technology flow step.
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
static bool IsVectorType(const tree_nodeConstRef &type)
Return true if the treenode is a vector.
#define GET_CONST_NODE(t)
DesignFlowStep_Status GetStatus() const
Return the status of this design step.
const ParameterConstRef parameters
Set of input parameters.
std::vector< signal > create_and_v(std::vector< signal > const &a, std::vector< signal > const &b, bool signedValues)
DesignFlowStep_Status
The status of a step.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
std::vector< signal > create_gt_v(std::vector< signal > const &a, std::vector< signal > const &b, bool signedValues)
long long lut_constant
the lut constant
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
tree_nodeRef GetBooleanType() const
Function that creates a boolean type if it is not already present, otherwise it returns the one that ...
std::vector< signal > create_le_v(std::vector< signal > const &a, std::vector< signal > const &b, bool signedValues)
This struct specifies the block node.
This file collects some utility functions.
tree_nodeRef op0
The first operand of the binary expression.
constants used by HLS constants
signal create_gt(signal const a, signal const b)
Creates a 'greater' operation.
refcount< T > lock() const
const unsigned int function_id
The index of the function to be analyzed.
klut_network_ext class provides operations derived from the one already existing in mockturtle::klut_...
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
std::vector< signal > create_lt_v(std::vector< signal > const &a, std::vector< signal > const &b, bool signedValues)
#define NUM_CST_allocation_default_max_lut_size
The default number of inputs of a LUT.
tree_nodeRef GetUnsignedLongLongType() const
Function that creates a long long unsigned int type if it is not already present, otherwise return th...
std::vector< signal > create_ge_v(std::vector< signal > const &a, std::vector< signal > const &b, bool signedValues)
tree_nodeRef CreateNopExpr(const tree_nodeConstRef &operand, const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, unsigned int function_decl_nid) const
Create a nop_expr to perform a conversion.
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
static bool IsStructType(const tree_nodeConstRef &type)
Return true if treenode is a record.
void fix_inputs_size(std::vector< signal > *a, std::vector< signal > *b, bool signedValues)
this class is used to manage the command-line or XML options.
std::vector< signal > create_ne_v(std::vector< signal > const &a, std::vector< signal > const &b, bool signedValues)
klut_network_node(uint64_t _index, long long _lut_constant, const std::vector< uint64_t > &_fan_in, bool _is_po, uint64_t _po_index, bool _is_constant)
tree_nodeRef create_extract_bit_expr(const tree_nodeRef &op0, const tree_nodeRef &op1, const std::string &srcp) const
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
std::string container_to_string(_InputIt first, _InputIt last, const std::string &separator, bool trim_empty=true)
std::vector< uint64_t > fan_in
a std::vector containing the indexes of all inputs of the current node
x
Return the smallest n such that 2^n >= _x.
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
uint64_t index
the index of the node
signal create_ge(signal const a, signal const b)
Creates a 'greater' or equal operation.
std::vector< signal > create_buf_v(std::vector< signal > const &a)
struct definition of the binary node structures.
void create_po_v(std::vector< signal > pos)
tree_nodeRef op
op field is the operand of the unary expression
signal create_eq(signal const a, signal const b)
Creates a 'equal' operation.
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
Class specification of the manager of the tree structures extracted from the raw file.
Base class for technology flow steps.
HLS specialization of generic_device.
A brief description of the C++ Header File.
static bool IsRealType(const tree_nodeConstRef &type)
Return true if the treenode is of real type.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
Helper structure that better represents a mockturtle::klut_network's node.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...