diff --git a/.gitmodules b/.gitmodules index f4287fe..6c8f746 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = https://github.com/msoeken/alice.git [submodule "lib/mockturtle"] path = lib/mockturtle - url = https://github.com/lsils/mockturtle.git + url = https://github.com/panhomyoung/mockturtle.git [submodule "lib/abc"] path = lib/abc - url = https://github.com/berkeley-abc/abc.git + url = https://github.com/berkeley-abc/abc.git \ No newline at end of file diff --git a/lib/mockturtle b/lib/mockturtle index da2b5e6..fac58aa 160000 --- a/lib/mockturtle +++ b/lib/mockturtle @@ -1 +1 @@ -Subproject commit da2b5e697d2dc988746fb94aceaebb277d385b83 +Subproject commit fac58aa217f7b4c4d5327b201f5e9fe8cbf9ee6a diff --git a/src/commands/cutrw.hpp b/src/commands/cutrw.hpp new file mode 100644 index 0000000..26ee596 --- /dev/null +++ b/src/commands/cutrw.hpp @@ -0,0 +1,134 @@ +/* phyLS: Advanced Logic Synthesis and Optimization tool + * Copyright (C) 2019- Ningbo University, Ningbo, China */ + +/** + * @file cutrw.hpp + * + * @brief cut rewriting + * + * @author Zhufei Chu + * @since 0.1 + */ + +#ifndef CUTRW_HPP +#define CUTRW_HPP + +#include +#include + +#include "../core/misc.hpp" +#include "../networks/aoig/xag_lut_npn.hpp" +#include "../networks/stp/stp_npn.hpp" + +using namespace std; + +namespace alice { + +class cutrw_command : public command { + public: + explicit cutrw_command(const environment::ptr& env) + : command(env, "Performs cut rewriting") { + add_flag("--xag_npn_lut,-g", "cut rewriting based on xag_npn_lut"); + add_flag("--xag_npn,-p", "cut rewriting based on xag_npn"); + add_flag("--klut_npn,-l", "cut rewriting based on klut_npn"); + add_flag("--compatibility_graph, -c", "In-place cut rewriting"); + } + + void execute() { + clock_t begin, end; + double totalTime = 0.0; + begin = clock(); + /* parameters */ + if (is_set("xag_npn_lut")) { + xag_network xag = store().current(); + + phyLS::print_stats(xag); + + xag_npn_lut_resynthesis resyn; + cut_rewriting_params ps; + ps.cut_enumeration_ps.cut_size = 4u; + xag = cut_rewriting(xag, resyn, ps); + + xag = cleanup_dangling(xag); + + // bidecomposition refactoring + bidecomposition_resynthesis resyn2; + refactoring(xag, resyn2); + + xag = cleanup_dangling(xag); + + phyLS::print_stats(xag); + + store().extend(); + store().current() = cleanup_dangling(xag); + } else if (is_set("xag_npn")) { + begin = clock(); + xag_network xag = store().current(); + + phyLS::print_stats(xag); + + xag_npn_resynthesis resyn; + cut_rewriting_params ps; + ps.cut_enumeration_ps.cut_size = 4u; + ps.min_cand_cut_size = 2; + ps.min_cand_cut_size_override = 3; + xag = cut_rewriting(xag, resyn, ps); + xag = cleanup_dangling(xag); + + phyLS::print_stats(xag); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + + store().extend(); + store().current() = cleanup_dangling(xag); + } else if (is_set("klut_npn")) { + klut_network klut = store().current(); + phyLS::print_stats(klut); + + stp_npn_resynthesis resyn; + cut_rewriting_params ps; + ps.cut_enumeration_ps.cut_size = 4u; + ps.allow_zero_gain = false; + if (is_set("compatibility_graph")) + cut_rewriting_with_compatibility_graph(klut, resyn); + else + klut = cut_rewriting(klut, resyn, ps); + klut = cleanup_dangling(klut); + + phyLS::print_stats(klut); + store().extend(); + store().current() = cleanup_dangling(klut); + } else { + xmg_network xmg = store().current(); + + phyLS::print_stats(xmg); + + xmg_npn_resynthesis resyn; + cut_rewriting_params ps; + ps.cut_enumeration_ps.cut_size = 4u; + xmg = cut_rewriting(xmg, resyn, ps); + xmg = cleanup_dangling(xmg); + + phyLS::print_stats(xmg); + + store().extend(); + store().current() = cleanup_dangling(xmg); + } + + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + + cout.setf(ios::fixed); + cout << "[Total CPU time] : " << setprecision(3) << totalTime << " s" + << endl; + } + + private: + bool verbose = false; +}; + +ALICE_ADD_COMMAND(cutrw, "Synthesis") + +} // namespace alice + +#endif diff --git a/src/commands/exact/exact_lut.hpp b/src/commands/exact/exact_lut.hpp new file mode 100644 index 0000000..387379c --- /dev/null +++ b/src/commands/exact/exact_lut.hpp @@ -0,0 +1,590 @@ +/* phyLS: Advanced Logic Synthesis and Optimization tool + * Copyright (C) 2019-2021 Ningbo University, Ningbo, China */ + +/** + * @file exact_lut.hpp + * + * @brief STP based exact synthesis + * + * @author Homyoung + * @since 2022/11/23 + */ + +#ifndef EXACTLUT_HPP +#define EXACTLUT_HPP + +#include + +#include +#include +#include + +#include "../../core/exact/exact_dag.hpp" +#include "../../core/exact/exact_lut.hpp" + +using namespace std; +using namespace percy; +using namespace mockturtle; +using kitty::dynamic_truth_table; + +namespace alice { +class exact_command : public command { + public: + explicit exact_command(const environment::ptr& env) + : command(env, "exact synthesis to find optimal 2-LUTs") { + add_option("function, -f", tt, "exact synthesis of function in hex"); + add_flag("--cegar_dag, -c", "cegar encoding and partial DAG structure"); + add_flag("--stp_cegar_dag, -s", + "stp based cegar encoding and partial DAG structure"); + add_flag("--dag_depth, -t", + "cegar encoding and partial DAG structure for Delay"); + add_option("--output, -o", filename, "the verilog filename"); + add_flag("--enumeration, -e", "enumerate all solutions"); + add_flag("--new_entry, -w", "adds k-LUT store entry"); + add_flag("--map, -m", "ASIC map each k-LUT"); + add_flag("--aig, -a", "enable exact synthesis for AIG, default = false"); + add_flag("--xag, -g", "enable exact synthesis for XAG, default = false"); + add_flag("--npn, -n", "print result for NPN storing, default = false"); + add_flag("--depth, -d", "print the depth of each result, default = false"); + add_flag("--verbose, -v", "verbose results, default = true"); + } + + protected: + string binary_to_hex() { + string t_temp; + for (int i = 0; i < tt.length(); i++) { + switch (tt[i]) { + case '0': + t_temp += "0000"; + continue; + case '1': + t_temp += "0001"; + continue; + case '2': + t_temp += "0010"; + continue; + case '3': + t_temp += "0011"; + continue; + case '4': + t_temp += "0100"; + continue; + case '5': + t_temp += "0101"; + continue; + case '6': + t_temp += "0110"; + continue; + case '7': + t_temp += "0111"; + continue; + case '8': + t_temp += "1000"; + continue; + case '9': + t_temp += "1001"; + continue; + case 'a': + t_temp += "1010"; + continue; + case 'b': + t_temp += "1011"; + continue; + case 'c': + t_temp += "1100"; + continue; + case 'd': + t_temp += "1101"; + continue; + case 'e': + t_temp += "1110"; + continue; + case 'f': + t_temp += "1111"; + continue; + case 'A': + t_temp += "1010"; + continue; + case 'B': + t_temp += "1011"; + continue; + case 'C': + t_temp += "1100"; + continue; + case 'D': + t_temp += "1101"; + continue; + case 'E': + t_temp += "1110"; + continue; + case 'F': + t_temp += "1111"; + continue; + } + } + return t_temp; + } + + void enu_es(int nr_in, list& chains) { + int node = nr_in - 1; + bool target = false; + while (true) { + spec spec; + bsat_wrapper solver; + partial_dag_encoder encoder2(solver); + encoder2.reset_sim_tts(nr_in); + + spec.add_alonce_clauses = false; + spec.add_nontriv_clauses = false; + spec.add_lex_func_clauses = false; + spec.add_colex_clauses = false; + spec.add_noreapply_clauses = false; + spec.add_symvar_clauses = false; + spec.verbosity = 0; + + kitty::dynamic_truth_table f(nr_in); + kitty::create_from_hex_string(f, tt); + spec[0] = f; + + auto dags = pd_generate_filter(node, nr_in); + spec.preprocess(); + for (auto& dag : dags) { + chain c; + synth_result status; + status = pd_cegar_synthesize(spec, c, dag, solver, encoder2); + if (status == success) { + chains.push_back(c); + target = true; + } + } + if (target) break; + node++; + } + } + + void es(int nr_in, chain& result) { + int node = nr_in - 1; + bool target = false; + while (true) { + spec spec; + bsat_wrapper solver; + partial_dag_encoder encoder2(solver); + encoder2.reset_sim_tts(nr_in); + + spec.add_alonce_clauses = false; + spec.add_nontriv_clauses = false; + spec.add_lex_func_clauses = false; + spec.add_colex_clauses = false; + spec.add_noreapply_clauses = false; + spec.add_symvar_clauses = false; + spec.verbosity = 0; + + kitty::dynamic_truth_table f(nr_in); + kitty::create_from_hex_string(f, tt); + spec[0] = f; + + auto dags = pd_generate_filter(node, nr_in); + spec.preprocess(); + for (auto& dag : dags) { + chain c; + synth_result status; + status = pd_cegar_synthesize(spec, c, dag, solver, encoder2); + if (status == success) { + result.copy(c); + target = true; + break; + } + } + if (target) break; + node++; + } + } + + void es_delay(int nr_in, list& chains) { + int node = nr_in - 1, max_level = 0, count = 0; + bool target = false; + while (true) { + spec spec; + spec.add_alonce_clauses = false; + spec.add_nontriv_clauses = false; + spec.add_lex_func_clauses = false; + spec.add_colex_clauses = false; + spec.add_noreapply_clauses = false; + spec.add_symvar_clauses = false; + spec.verbosity = 0; + bsat_wrapper solver; + partial_dag_encoder encoder2(solver); + encoder2.reset_sim_tts(nr_in); + kitty::dynamic_truth_table f(nr_in); + kitty::create_from_hex_string(f, tt); + spec[0] = f; + + auto dags = pd_generate_filter(node, nr_in); + spec.preprocess(); + for (auto dag : dags) { + chain c; + const auto status = pd_cegar_synthesize(spec, c, dag, solver, encoder2); + if (status == success) { + target = true; + int level_temp = c.get_nr_level(); + if (max_level == 0) { + chains.push_back(c); + max_level = level_temp; + } else if (level_temp == max_level) { + chains.push_back(c); + } else if (level_temp < max_level) { + chains.clear(); + chains.push_back(c); + max_level = level_temp; + } + } + } + if (target) break; + node++; + } + while (true) { + if (max_level == 2 || count > 2) break; + bool target_count = false; + spec spec; + spec.add_alonce_clauses = false; + spec.add_nontriv_clauses = false; + spec.add_lex_func_clauses = false; + spec.add_colex_clauses = false; + spec.add_noreapply_clauses = false; + spec.add_symvar_clauses = false; + spec.verbosity = 0; + bsat_wrapper solver; + partial_dag_encoder encoder2(solver); + encoder2.reset_sim_tts(nr_in); + kitty::dynamic_truth_table f(nr_in); + kitty::create_from_hex_string(f, tt); + spec[0] = f; + + node++; + auto dags = pd_generate_filter(node, nr_in); + spec.preprocess(); + for (auto dag : dags) { + if (dag.nr_level() > max_level) continue; + chain c; + const auto status = pd_cegar_synthesize(spec, c, dag, solver, encoder2); + if (status == success) { + int level_temp = c.get_nr_level(); + if (level_temp == max_level) { + chains.push_back(c); + } else if (level_temp < max_level) { + max_level = level_temp; + chains.clear(); + chains.push_back(c); + target_count = true; + } + } + } + if (!target_count) count++; + } + } + + klut_network create_network(chain& c) { + klut_network klut; + c.store_bench(0); + std::string filename = "r_0.bench"; + if (lorina::read_bench(filename, mockturtle::bench_reader(klut)) != + lorina::return_code::success) { + std::cout << "[w] parse error\n"; + } + return klut; + } + + bool compare_min_area(double area_temp, double delay_temp, int gate) { + bool target = false; + if (min_area == 0.00 && min_delay == 0.00) { + min_area = area_temp; + min_delay = delay_temp; + mapping_gate = gate; + target = true; + } else if (area_temp < min_area) { + min_area = area_temp; + min_delay = delay_temp; + mapping_gate = gate; + target = true; + } else if (area_temp == min_area) { + if (delay_temp < min_delay) { + min_delay = delay_temp; + mapping_gate = gate; + target = true; + } + } + return target; + } + + bool compare_min_delay(double area_temp, double delay_temp, int gate) { + bool target = false; + if (min_area == 0.00 && min_delay == 0.00) { + min_area = area_temp; + min_delay = delay_temp; + mapping_gate = gate; + target = true; + } else if (delay_temp < min_delay) { + min_area = area_temp; + min_delay = delay_temp; + mapping_gate = gate; + target = true; + } else if (delay_temp == min_delay) { + if (area_temp < min_area) { + min_area = area_temp; + mapping_gate = gate; + target = true; + } + } + return target; + } + + void execute() { + t.clear(); + t.push_back(binary_to_hex()); + vector& tt_h = t; + + int nr_in = 0, value = 0; + while (value < tt.size()) { + value = pow(2, nr_in); + if (value == tt.size()) break; + nr_in++; + } + nr_in += 2; + + cout << "Running exact synthesis for " << nr_in << "-input function." + << endl + << endl; + + clock_t begin, end; + double totalTime = 0.0; + + phyLS::exact_lut_params ps; + + if (is_set("verbose")) ps.verbose = false; + if (is_set("aig")) ps.aig = true; + if (is_set("xag")) ps.xag = true; + if (is_set("npn")) ps.npn = true; + if (is_set("depth")) ps.depth = true; + if (is_set("map")) ps.map = true; + + if (is_set("cegar_dag")) { + if (is_set("enumeration")) { + begin = clock(); + list chains; + enu_es(nr_in, chains); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + int count = 0; + chain best_chain; + for (auto x : chains) { + count += 1; + if (ps.verbose) { + x.print_bench(); + if (ps.depth) + std::cout << "level = " << x.get_nr_level() << std::endl; + } + if (ps.npn) { + x.print_npn(); + if (ps.depth) { + std::cout << ": l{" << x.get_nr_level() << "}" << std::endl; + } else { + std::cout << std::endl; + } + } + if (is_set("map")) { + std::vector gates = + store>().current(); + mockturtle::tech_library<5> lib(gates); + mockturtle::map_params ps; + mockturtle::map_stats st; + klut_network klut = create_network(x); + auto res = mockturtle::map(klut, lib, ps, &st); + if (compare_min_area(st.area, st.delay, res.num_gates())) { + if (is_set("output")) { + write_verilog_with_binding(res, filename); + } + best_chain.copy(x); + } + } + } + if (is_set("map")) { + best_chain.print_npn(); + if (ps.depth) { + std::cout << ": l{" << best_chain.get_nr_level() << "}" + << std::endl; + } else { + std::cout << std::endl; + } + std::cout << "Mapped gates = " << mapping_gate + << ", area = " << min_area << ", delay = " << min_delay + << std::endl; + } + cout << "[Total realization]: " << count << endl; + } else { + begin = clock(); + chain chain; + es(nr_in, chain); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + if (is_set("new_entry")) { + klut_network klut = create_network(chain); + store().extend(); + store().current() = klut; + } + if (ps.verbose) { + chain.print_bench(); + if (ps.depth) { + klut_network klut = create_network(chain); + mockturtle::depth_view depth_lut{klut}; + std::cout << "level = " << depth_lut.depth() - 1 << std::endl; + } + } + if (ps.npn) { + chain.print_npn(); + if (ps.depth) { + klut_network klut = create_network(chain); + mockturtle::depth_view depth_lut{klut}; + std::cout << "l{" << depth_lut.depth() - 1 << "}" << std::endl; + } else { + std::cout << std::endl; + } + } + if (is_set("map")) { + std::vector gates = + store>().current(); + mockturtle::tech_library<5> lib(gates); + mockturtle::map_params ps; + mockturtle::map_stats st; + klut_network klut = create_network(chain); + auto res = mockturtle::map(klut, lib, ps, &st); + compare_min_area(st.area, st.delay, res.num_gates()); + chain.print_npn(); + if (is_set("output")) { + write_verilog_with_binding(res, filename); + } + if (is_set("depth")) { + klut_network klut = create_network(chain); + mockturtle::depth_view depth_lut{klut}; + std::cout << ": l{" << depth_lut.depth() - 1 << "}" << std::endl; + } else { + std::cout << std::endl; + } + std::cout << "Mapped gates = " << mapping_gate + << ", area = " << min_area << ", delay = " << min_delay + << std::endl; + } + } + } else if (is_set("dag_depth")) { + begin = clock(); + list chains; + es_delay(nr_in, chains); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + int count = 0; + chain best_chain; + for (auto x : chains) { + count += 1; + if (is_set("verbose")) { + x.print_bench(); + if (ps.depth) + std::cout << "level = " << x.get_nr_level() << std::endl; + } + if (is_set("npn")) { + x.print_npn(); + if (ps.depth) { + std::cout << ": l{" << x.get_nr_level() << "}" << std::endl; + } else { + std::cout << std::endl; + } + } + if (is_set("map")) { + std::vector gates = + store>().current(); + mockturtle::tech_library<5> lib(gates); + mockturtle::map_params ps; + mockturtle::map_stats st; + klut_network klut = create_network(x); + auto res = mockturtle::map(klut, lib, ps, &st); + if (compare_min_delay(st.area, st.delay, res.num_gates())) + best_chain.copy(x); + } + } + if (is_set("map")) { + best_chain.print_npn(); + if (ps.depth) { + std::cout << ": l{" << best_chain.get_nr_level() << "}" << std::endl; + } else { + std::cout << std::endl; + } + std::cout << "Mapped gates = " << mapping_gate + << ", area = " << min_area << ", delay = " << min_delay + << std::endl; + } + cout << "[Total realization]: " << count << endl; + } else if (is_set("stp_cegar_dag")) { + if (is_set("map")){ + ps.gates = store>().current(); + begin = clock(); + exact_lut_dag_enu_map(tt, nr_in, ps); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + std::cout << "Mapped gates = " << ps.mapping_gate + << ", area = " << ps.min_area << ", delay = " << ps.min_delay + << std::endl; + } else if (is_set("enumeration")) { + begin = clock(); + exact_lut_dag_enu(tt, nr_in, ps); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + cout << "[Total realization]: " << nr_in << endl; + } else { + begin = clock(); + exact_lut_dag(tt, nr_in, ps); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + cout << "[Total realization]: " << nr_in << endl; + } + } else { + if (is_set("enumeration")) { + begin = clock(); + phyLS::exact_lut_enu(tt_h, nr_in); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + int count = 0; + for (auto x : tt_h) { + if (ps.verbose) cout << x << endl; + count += 1; + } + cout << "[Total realization]: " << count << endl; + } else { + begin = clock(); + phyLS::exact_lut(tt_h, nr_in); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + int count = 0; + for (auto x : tt_h) { + if (ps.verbose) cout << x << endl; + count += 1; + } + cout << "[Total realization]: " << count << endl; + } + } + + cout.setf(ios::fixed); + cout << "[Total CPU time] : " << setprecision(3) << totalTime << " s" + << endl; + } + + private: + string tt; + vector t; + double min_area = 0.00; + double min_delay = 0.00; + int mapping_gate = 0; + std::string filename = "techmap.v"; +}; + +ALICE_ADD_COMMAND(exact, "Synthesis") +} // namespace alice + +#endif \ No newline at end of file diff --git a/src/commands/exact/lutrw.hpp b/src/commands/exact/lutrw.hpp new file mode 100644 index 0000000..e2cad21 --- /dev/null +++ b/src/commands/exact/lutrw.hpp @@ -0,0 +1,94 @@ +/* phyLS: Advanced Logic Synthesis and Optimization tool + * Copyright (C) 2019-2021 Ningbo University, Ningbo, China */ + +/** + * @file lutrw.hpp + * + * @brief 2-lut rewriting with STP based exact synthesis + * + * @author Homyoung + * @since 2022/11/30 + */ + +#ifndef LUTRW_COMMAND_HPP +#define LUTRW_COMMAND_HPP + +#include + +#include +#include +#include +#include + +#include "../../core/exact/lut_rewriting.hpp" +#include "../../core/misc.hpp" + +using namespace std; +using namespace percy; +using kitty::dynamic_truth_table; + +namespace alice { +class lutrw_command : public command { + public: + explicit lutrw_command(const environment::ptr& env) + : command(env, "Performs 2-LUT rewriting") { + add_flag("--techmap, -t", "rewriting by the lowest cost of realization"); + add_flag("--enumeration_techmap, -e", + "rewriting by the lowest cost of enumerated realization"); + add_flag("--cec, -c,", "apply equivalence checking in rewriting"); + add_flag("--xag, -g", "enable exact synthesis for XAG, default = false"); + } + + protected: + void execute() { + mockturtle::klut_network klut = store().current(); + mockturtle::klut_network klut_orig, klut_opt; + klut_orig = klut; + phyLS::lut_rewriting_params ps; + if (is_set("xag")) ps.xag = true; + + clock_t begin, end; + double totalTime; + if (is_set("techmap")) { + begin = clock(); + klut_opt = phyLS::lut_rewriting_s(klut, ps); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + } else if (is_set("enumeration_techmap")) { + begin = clock(); + klut_opt = phyLS::lut_rewriting_s_enu(klut, ps); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + } else { + begin = clock(); + klut_opt = phyLS::lut_rewriting_c(klut, ps); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + } + + if (is_set("cec")) { + /* equivalence checking */ + const auto miter_klut = *miter(klut_orig, klut_opt); + equivalence_checking_stats eq_st; + const auto result = equivalence_checking(miter_klut, {}, &eq_st); + assert(*result); + } + + std::cout << "[lutrw] "; + phyLS::print_stats(klut_opt); + + store().extend(); + store().current() = klut_opt; + + cout.setf(ios::fixed); + cout << "[Total CPU time] : " << setprecision(3) << totalTime << " s" + << endl; + } + + private: +}; + +ALICE_ADD_COMMAND(lutrw, "Synthesis") +} // namespace alice + +#endif \ No newline at end of file diff --git a/src/commands/lutmap.hpp b/src/commands/lutmap.hpp index 7c96c00..1fa62d5 100644 --- a/src/commands/lutmap.hpp +++ b/src/commands/lutmap.hpp @@ -43,12 +43,27 @@ class lutmap_command : public command { add_flag("--recompute_cuts, -c", "recompute cuts at each step [default = true]"); add_flag("--edge, -e", "Use edge count reduction [default = true]"); + add_flag("--cost_function, -f", + "LUT map with cost function [default = false]"); add_flag("--dominated_cuts, -d", "Remove the cuts that are contained in others [default = true]"); add_flag("--verbose, -v", "print the information"); } protected: + struct lut_custom_cost { + std::pair operator()(uint32_t num_leaves) const { + if (num_leaves < 2u) return {0u, 0u}; + return {num_leaves, 1u}; /* area, delay */ + } + + std::pair operator()( + kitty::dynamic_truth_table const& tt) const { + if (tt.num_vars() < 2u) return {0u, 0u}; + return {tt.num_vars(), 1u}; /* area, delay */ + } + }; + void execute() { if (is_set("mig")) { if (store().size() == 0u) @@ -109,7 +124,7 @@ class lutmap_command : public command { std::cerr << "Error: Empty AIG network\n"; else { auto aig = store().current(); - mapping_view mapped_aig{aig}; + mapping_view mapped_aig{aig}; phyLS::lut_map_params ps; if (is_set("area")) ps.area_oriented_mapping = true; if (is_set("relax_required")) ps.relax_required = relax_required; @@ -119,7 +134,11 @@ class lutmap_command : public command { if (is_set("edge")) ps.edge_optimization = false; if (is_set("dominated_cuts")) ps.remove_dominated_cuts = false; cout << "Mapped AIG into " << cut_size << "-LUT : "; - phyLS::lut_map(mapped_aig, ps); + if (is_set("cost_function")) + phyLS::lut_map( + mapped_aig, ps); + else + phyLS::lut_map(mapped_aig, ps); mapped_aig.clear_mapping(); } } diff --git a/src/commands/node_resynthesis.hpp b/src/commands/node_resynthesis.hpp index 035f81f..b761e29 100644 --- a/src/commands/node_resynthesis.hpp +++ b/src/commands/node_resynthesis.hpp @@ -43,6 +43,7 @@ class resyn_command : public command { "performs technology-independent restructuring [default = MIG]") { add_flag("--xmg, -x", "Resubstitution for XMG"); add_flag("--xag, -g", "Resubstitution for XAG"); + add_flag("--aig, -a", "Resubstitution for AIG"); add_flag("--direct, -d", "Node resynthesis with direct synthesis"); add_flag("--verbose, -v", "print the information"); } @@ -81,6 +82,19 @@ class resyn_command : public command { phyLS::print_stats(xag); end = clock(); totalTime = (double)(end - begin) / CLOCKS_PER_SEC; + } else if (is_set("aig")) { + begin = clock(); + exact_resynthesis_params ps; + ps.cache = std::make_shared(); + exact_aig_resynthesis exact_resyn(false, ps); + node_resynthesis_stats nrst; + dsd_resynthesis resyn(exact_resyn); + const auto aig = node_resynthesis(klut, resyn, {}, &nrst); + store().extend(); + store().current() = cleanup_dangling(aig); + phyLS::print_stats(aig); + end = clock(); + totalTime = (double)(end - begin) / CLOCKS_PER_SEC; } else { begin = clock(); if (is_set("direct")) { diff --git a/src/core/exact/exact_dag.hpp b/src/core/exact/exact_dag.hpp new file mode 100644 index 0000000..1f37206 --- /dev/null +++ b/src/core/exact/exact_dag.hpp @@ -0,0 +1,2249 @@ +/* phyLS: Advanced Logic Synthesis and Optimization tool + * Copyright (C) 2019-2021 Ningbo University, Ningbo, China */ + +/** + * @file exact_dag.hpp + * + * @brief dag generate + * + * @author Homyoung + * @since 0.1 + */ + +#ifndef EXACT_DAG_HPP +#define EXACT_DAG_HPP + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace percy; +using namespace mockturtle; +using kitty::dynamic_truth_table; +using namespace std; + +namespace phyLS { + +template +struct CollectionReverse { + using iterator = typename T::reverse_iterator; + using const_iterator = typename T::const_reverse_iterator; + + explicit CollectionReverse(T& col) : _M_collection(col) {} + + iterator begin() { return _M_collection.rbegin(); } + + const_iterator begin() const { return _M_collection.rbegin(); } + + iterator end() { return _M_collection.rend(); } + + const_iterator end() const { return _M_collection.rend(); } + + private: + T& _M_collection; +}; + +template +CollectionReverse reverse(T& col) { + return CollectionReverse(col); +} + +struct exact_lut_params { + /*! \brief Enable exact synthesis for AIG. */ + bool aig{false}; + + /*! \brief Enable exact synthesis for XAG. */ + bool xag{false}; + + /*! \brief Print result for NPN storing. */ + bool npn{false}; + + /*! \brief Print depth of each result. */ + bool depth{false}; + + /*! \brief ASIC map each k-LUT. */ + bool map{false}; + std::vector gates; + double min_area = 0.00; + double min_delay = 0.00; + int mapping_gate = 0; + + /*! \brief Be verbose. */ + bool verbose{true}; +}; + +struct node_inf { + int num; + int level; + bool fan_out = 0; + bool fan_in = 0; +}; + +struct bench { + int node; + int right = 0; + int left = 0; + std::string tt = "2222"; +}; + +struct dag { + int node; + int level; + vector count; + vector> lut; +}; + +struct matrix { + int eye = 0; + int node = 0; + std::string name; + bool input = 0; +}; + +struct result_lut { + std::string computed_input; + vector possible_result; +}; + +struct coordinate_dag { + int Abscissa; + int Ordinate; + int parameter_Intermediate; + int parameter_Gate; +}; + +struct cdccl_impl_dag { + vector Intermediate; + std::string Result; + vector Gate; + vector + Level; // Define the network as a coordinate_dag system +}; + +class dag_impl { + public: + dag_impl(std::string& tt, int& input, exact_lut_params& ps) + : tt(tt), input(input), ps(ps) {} + + vector> exact_synthesis_results; + + void run() { stp_exact_synthesis(); } + + void run_enu() { stp_exact_synthesis_enu(); } + + void run_enu_map() { stp_exact_synthesis_enu_map(); } + + void run_rewrite() { stp_exact_synthesis_enu_for_rewrite(); } + + void run_rewrite_enu() { stp_exact_synthesis_enu_for_rewrite_enu(); } + + private: + void stp_exact_synthesis() { + int node = input - 1; + bool target = false; + while (true) { + percy::spec spec; + bsat_wrapper solver; + partial_dag_encoder encoder(solver); + encoder.reset_sim_tts(input); + + kitty::dynamic_truth_table f(input); + kitty::create_from_hex_string(f, tt); + spec[0] = f; + spec.preprocess(); + + auto dags = pd_generate_filter(node, input); + int count = 0; + for (auto& dag : dags) { + percy::chain c; + synth_result status; + status = pd_cegar_synthesize(spec, c, dag, solver, encoder); + if (status == success) { + vector lut = chain_to_bench(c); + vector> luts; + luts.push_back(lut); + stp_simulate(luts); + if (luts.size()) { + exact_synthesis_results.assign(luts.begin(), luts.end()); + if (ps.verbose) print_chain(); + if (ps.npn) print_npn(); + count += exact_synthesis_results.size(); + target = true; + break; + } + } + } + if (target) { + input = count; + break; + } + node++; + } + } + + void stp_exact_synthesis_enu() { + int node = input - 1; + bool target = false; + while (true) { + percy::spec spec; + spec.add_alonce_clauses = false; + spec.add_nontriv_clauses = false; + spec.add_lex_func_clauses = false; + spec.add_colex_clauses = false; + spec.add_noreapply_clauses = false; + spec.add_symvar_clauses = false; + bsat_wrapper solver; + partial_dag_encoder encoder(solver); + encoder.reset_sim_tts(input); + kitty::dynamic_truth_table f(input); + kitty::create_from_hex_string(f, tt); + spec[0] = f; + spec.preprocess(); + + auto dags = pd_generate_filter(node, input); + int count = 0; + for (auto& dag : dags) { + exact_synthesis_results.clear(); + percy::chain c; + synth_result status; + status = pd_cegar_synthesize(spec, c, dag, solver, encoder); + if (status == success) { + vector lut = chain_to_bench(c); + vector> luts; + luts.push_back(lut); + stp_simulate(luts); + if (luts.size()) { + exact_synthesis_results.assign(luts.begin(), luts.end()); + if (ps.verbose) print_chain(); + if (ps.npn) print_npn(); + target = true; + count += exact_synthesis_results.size(); + } + } + } + if (target) { + input = count; + break; + } + node++; + } + } + + void stp_exact_synthesis_enu_map() { + int node = input - 1; + bool target = false; + chain best_chain; + while (true) { + percy::spec spec; + spec.add_alonce_clauses = false; + spec.add_nontriv_clauses = false; + spec.add_lex_func_clauses = false; + spec.add_colex_clauses = false; + spec.add_noreapply_clauses = false; + spec.add_symvar_clauses = false; + bsat_wrapper solver; + partial_dag_encoder encoder(solver); + encoder.reset_sim_tts(input); + kitty::dynamic_truth_table f(input); + kitty::create_from_hex_string(f, tt); + spec[0] = f; + spec.preprocess(); + + auto dags = pd_generate_filter(node, input); + for (auto dag : dags) { + chain c; + synth_result status = + pd_cegar_synthesize(spec, c, dag, solver, encoder); + if (status == success) { + target = true; + std::vector gates = ps.gates; + mockturtle::tech_library<5> lib(gates); + mockturtle::map_params pss; + mockturtle::map_stats st; + klut_network klut = create_network(c); + auto res = mockturtle::map(klut, lib, pss, &st); + if (compare_min_area(st.area, st.delay, res.num_gates())) + best_chain.copy(c); + } + } + if (target) { + vector lut = chain_to_bench(best_chain); + vector> luts; + luts.push_back(lut); + stp_simulate(luts); + if (luts.size()) + exact_synthesis_results.assign(luts.begin(), luts.end()); + break; + } + node++; + } + store_bench(); + vector exact_synthesis_result; + for (int i = 0; i < exact_synthesis_results.size(); i++) { + std::vector gates = ps.gates; + mockturtle::tech_library<5> lib(gates); + mockturtle::map_params ps; + mockturtle::map_stats st; + mockturtle::klut_network klut; + std::string filename = "r_" + std::to_string(i) + ".bench"; + if (lorina::read_bench(filename, mockturtle::bench_reader(klut)) != + lorina::return_code::success) { + std::cout << "[w] parse error\n"; + } + auto res = mockturtle::map(klut, lib, ps, &st); + if (compare_min_area(st.area, st.delay, res.num_gates())) + exact_synthesis_result = exact_synthesis_results[i]; + } + if (exact_synthesis_result.size()) { + for (auto x : exact_synthesis_result) { + cout << x.node << "-" << BinToHex(x.tt) << "-" << x.left << "-" + << x.right << " "; + } + } else { + best_chain.print_npn(); + } + std::cout << ": l{" << best_chain.get_nr_level() << "}" << std::endl; + ps.mapping_gate = mapping_gate; + ps.min_area = min_area; + ps.min_delay = min_delay; + } + + void stp_exact_synthesis_enu_for_rewrite() { + int node = input - 1; + bool target = false; + while (true) { + percy::spec spec; + bsat_wrapper solver; + partial_dag_encoder encoder(solver); + encoder.reset_sim_tts(input); + + kitty::dynamic_truth_table f(input); + kitty::create_from_hex_string(f, tt); + spec[0] = f; + spec.preprocess(); + + auto dags = pd_generate_filter(node, input); + for (auto& dag : dags) { + percy::chain c; + synth_result status; + status = pd_cegar_synthesize(spec, c, dag, solver, encoder); + if (status == success) { + vector lut = chain_to_bench(c); + vector> luts; + luts.push_back(lut); + stp_simulate(luts); + if (luts.size()) { + exact_synthesis_results.assign(luts.begin(), luts.end()); + target = true; + break; + } + } + } + if (target) break; + node++; + } + } + + void stp_exact_synthesis_enu_for_rewrite_enu() { + int node = input - 1; + bool target = false; + while (true) { + percy::spec spec; + bsat_wrapper solver; + partial_dag_encoder encoder(solver); + encoder.reset_sim_tts(input); + + kitty::dynamic_truth_table f(input); + kitty::create_from_hex_string(f, tt); + spec[0] = f; + spec.preprocess(); + + auto dags = pd_generate_filter(node, input); + exact_synthesis_results.clear(); + for (auto& dag : dags) { + percy::chain c; + synth_result status; + status = pd_cegar_synthesize(spec, c, dag, solver, encoder); + if (status == success) { + vector lut = chain_to_bench(c); + vector> luts; + luts.push_back(lut); + stp_simulate(luts); + if (luts.size()) { + exact_synthesis_results.insert(exact_synthesis_results.end(), + luts.begin(), luts.end()); + target = true; + } + } + } + if (target) break; + node++; + } + } + + vector chain_to_bench(percy::chain c) { + vector results; + vector node, left, right; + c.bench_infor(node, left, right); + for (int i = node.size() - 1; i >= 0; i--) { + bench result; + result.node = node[i]; + result.left = left[i]; + result.right = right[i]; + results.push_back(result); + } + return results; + } + + void stp_simulate(vector>& lut_dags) { + std::string tt_binary = hex_to_binary(); + int flag_node = lut_dags[0][lut_dags[0].size() - 1].node; + vector> lut_dags_new; + for (int i = lut_dags.size() - 1; i >= 0; i--) { + std::string input_tt(tt_binary); + + vector matrix_form = chain_to_matrix(lut_dags[i], flag_node); + matrix_computution(matrix_form); + + vector bench_result; + result_lut first_result; + first_result.computed_input = input_tt; + first_result.possible_result = lut_dags[i]; + bench_result.push_back(first_result); + for (int l = matrix_form.size() - 1; l >= 1; l--) { + int length_string = input_tt.size(); + if (matrix_form[l].input == 0) { + if (matrix_form[l].name == "W") { + if (matrix_form[l].eye == 0) { + std::string temp1, temp2; + temp1 = input_tt.substr(length_string / 4, length_string / 4); + temp2 = input_tt.substr(length_string / 2, length_string / 4); + input_tt.replace(length_string / 4, length_string / 4, temp2); + input_tt.replace(length_string / 2, length_string / 4, temp1); + } else { + int length2 = length_string / pow(2.0, matrix_form[l].eye + 2); + for (int l1 = pow(2.0, matrix_form[l].eye), add = 1; l1 > 0; + l1--) { + std::string temp1, temp2; + temp1 = input_tt.substr( + (length_string / pow(2.0, matrix_form[l].eye + 1)) * add - + length2, + length2); + temp2 = input_tt.substr( + (length_string / pow(2.0, matrix_form[l].eye + 1)) * add, + length2); + input_tt.replace( + (length_string / pow(2.0, matrix_form[l].eye + 1)) * add - + length2, + length2, temp2); + input_tt.replace( + (length_string / pow(2.0, matrix_form[l].eye + 1)) * add, + length2, temp1); + add += 2; + } + } + bench_result[0].computed_input = input_tt; + } else if (matrix_form[l].name == "R") { + if (matrix_form[l].eye == 0) { + std::string temp(length_string, '2'); + input_tt.insert(input_tt.begin() + (length_string / 2), + temp.begin(), temp.end()); + } else { + std::string temp(length_string / pow(2.0, matrix_form[l].eye), + '2'); + for (int l2 = pow(2.0, matrix_form[l].eye), + add1 = pow(2.0, matrix_form[l].eye + 1) - 1; + l2 > 0; l2--) { + input_tt.insert( + input_tt.begin() + + ((length_string / pow(2.0, matrix_form[l].eye + 1)) * + add1), + temp.begin(), temp.end()); + add1 -= 2; + } + } + bench_result[0].computed_input = input_tt; + } else if (matrix_form[l].name == "M") { + vector bench_result_temp; + for (int q = bench_result.size() - 1; q >= 0; q--) { + int length_string2 = bench_result[q].computed_input.size(); + int length1 = length_string2 / + pow(2.0, matrix_form[l].eye + 2); // abcd的长度 + std::string standard(length1, '2'); + vector standard_int(4, 0); + vector> result; + + for (int l3 = 0; l3 < pow(2.0, matrix_form[l].eye); l3++) { + vector> result_t; + + int ind = (length_string2 / pow(2.0, matrix_form[l].eye)) * l3; + std::string a = + bench_result[q].computed_input.substr(ind, length1); + std::string b = bench_result[q].computed_input.substr( + ind + length1, length1); + std::string c = bench_result[q].computed_input.substr( + ind + (2 * length1), length1); + std::string d = bench_result[q].computed_input.substr( + ind + (3 * length1), length1); + + if (a != standard) { + vector result_temp(4); // size为4的可能结果 + result_temp[0] = 0; // a=0 + if (compare_string(a, b)) // b=a + { + if (b == standard) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(a, c) && + compare_string(b, c)) // c=(b=a) + { + if (c == standard) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + if (compare_string(a, d) && compare_string(b, d) && + compare_string(c, d)) // d=(c=b=a) + { + result_temp[0] = 2; + result_temp[1] = 2; + result_temp[2] = 2; + result_temp[3] = 2; + } else // d!=(c=b=a) + { + result_temp[3] = 1; // d=1 + if (compare_string(b, d)) result_temp[1] = 2; + if (compare_string(c, d)) result_temp[2] = 2; + } + } else // c!=(b=a) + { + result_temp[2] = 1; // c=1 + if (compare_string(b, c)) result_temp[1] = 2; + if (compare_string(a, d) && + compare_string(b, d)) // d=(b=a) + { + if (d == standard || compare_string(c, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(c, d)) // d=c + { + result_temp[3] = 1; // d=1 + if (compare_string(b, d)) result_temp[1] = 2; + } else // 其他 + break; + } + } else // b!=a + { + result_temp[1] = 1; // b=1 + if (compare_string(a, c)) // c=a + { + if (c == standard || compare_string(b, c)) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + if (compare_string(a, d) && + compare_string(c, d)) // d=(c=a) + { + if (d == standard || compare_string(b, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(b, d)) // d=b + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else if (compare_string(b, c)) // c=b + { + result_temp[2] = 1; // c=1 + if (compare_string(a, d)) // d=a + { + if (d == standard || + (compare_string(b, d) && compare_string(c, d))) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(b, d) && + compare_string(c, d)) // d=(c=b) + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else // 其他 + break; + } + if (result_t.empty()) + vector_generate(result_temp, result_t); + else { + vector> result_t_temp; + vector_generate(result_temp, result_t_temp); + for (int j = result_t.size() - 1; j >= 0; j--) { + for (int k = result_t_temp.size() - 1; k >= 0; k--) { + if (compare_vector(result_t[j], result_t_temp[k])) + result_t_temp.erase(result_t_temp.begin() + k); + } + } + if (!result_t_temp.empty()) { + result_t.insert(result_t.end(), result_t_temp.begin(), + result_t_temp.end()); + } + } + } + if (b != standard) { + vector result_temp(4); // size为4的可能结果 + result_temp[1] = 0; // b=0 + if (compare_string(a, b)) // a=b + { + if (a == standard) + result_temp[0] = 2; + else + result_temp[0] = 0; // a=0 + if (compare_string(a, c) && + compare_string(b, c)) // c=(a=b) + { + if (c == standard) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + if (compare_string(a, d) && compare_string(b, d) && + compare_string(c, d)) // d=(c=a=b) + { + result_temp[0] = 2; + result_temp[1] = 2; + result_temp[2] = 2; + result_temp[3] = 2; + } else // d!=(c=a=b) + { + result_temp[3] = 1; // d=1 + if (compare_string(a, d)) result_temp[0] = 2; + if (compare_string(c, d)) result_temp[2] = 2; + } + } else // c!=(a=b) + { + result_temp[2] = 1; // c=1 + if (compare_string(a, c)) result_temp[0] = 2; + if (compare_string(a, d) && + compare_string(b, d)) // d=(a=b) + { + if (d == standard || compare_string(c, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(c, d)) // d=c + { + result_temp[3] = 1; // d=1 + if (compare_string(a, d)) result_temp[0] = 2; + } else // 其他 + break; + } + } else // a!=b + { + result_temp[0] = 1; // a=1 + if (compare_string(c, b)) // c=b + { + if (c == standard || compare_string(a, c)) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + if (compare_string(b, d) && + compare_string(c, d)) // d=(c=b) + { + if (d == standard || compare_string(a, d)) + result_temp[3] = 2; // d=0 + else + result_temp[3] = 0; // d=0 + } else if (compare_string(a, d)) // d=a + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else if (compare_string(a, c)) // c=a + { + result_temp[2] = 1; // c=1 + if (compare_string(b, d)) // d=b + { + if (d == standard || + (compare_string(a, d) && compare_string(c, d))) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(a, d) && + compare_string(c, d)) // d=(c=a) + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else // 其他 + break; + } + if (result_t.empty()) + vector_generate(result_temp, result_t); + else { + vector> result_t_temp; + vector_generate(result_temp, result_t_temp); + for (int j = result_t.size() - 1; j >= 0; j--) { + for (int k = result_t_temp.size() - 1; k >= 0; k--) { + if (compare_vector(result_t[j], result_t_temp[k])) + result_t_temp.erase(result_t_temp.begin() + k); + } + } + if (!result_t_temp.empty()) { + result_t.insert(result_t.end(), result_t_temp.begin(), + result_t_temp.end()); + } + } + } + if (c != standard) { + vector result_temp(4); // size为4的可能结果 + result_temp[2] = 0; // c=0 + if (compare_string(a, c)) // a=c + { + if (a == standard) + result_temp[0] = 2; + else + result_temp[0] = 0; // a=0 + if (compare_string(b, c) && + compare_string(b, a)) // b=(a=c) + { + if (b == standard) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(a, d) && compare_string(b, d) && + compare_string(c, d)) // d=(b=a=c) + { + result_temp[0] = 2; + result_temp[1] = 2; + result_temp[2] = 2; + result_temp[3] = 2; + } else // d!=(b=a=c) + { + result_temp[3] = 1; // d=1 + if (compare_string(a, d)) result_temp[0] = 2; + if (compare_string(b, d)) result_temp[1] = 2; + } + } else // b!=(a=c) + { + result_temp[1] = 1; // b=1 + if (compare_string(a, b)) result_temp[0] = 2; + if (compare_string(a, d) && + compare_string(c, d)) // d=(a=c) + { + if (d == standard || compare_string(b, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(b, d)) // d=b + { + result_temp[3] = 1; // d=1 + if (compare_string(a, d)) result_temp[0] = 2; + } else // 其他 + break; + } + } else // a!=c + { + result_temp[0] = 1; // a=1 + if (compare_string(b, c)) // b=c + { + if (b == standard || compare_string(b, a)) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(b, d) && + compare_string(c, d)) // d=(b=c) + { + if (d == standard || compare_string(a, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(a, d)) // d=a + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else if (compare_string(a, b)) // b=a + { + result_temp[1] = 1; // b=1 + if (compare_string(c, d)) // d=c + { + if (d == standard || + (compare_string(a, d) && compare_string(b, d))) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(a, d) && + compare_string(b, d)) // d=(b=a) + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else // 其他 + break; + } + if (result_t.empty()) + vector_generate(result_temp, result_t); + else { + vector> result_t_temp; + vector_generate(result_temp, result_t_temp); + for (int j = result_t.size() - 1; j >= 0; j--) { + for (int k = result_t_temp.size() - 1; k >= 0; k--) { + if (compare_vector(result_t[j], result_t_temp[k])) + result_t_temp.erase(result_t_temp.begin() + k); + } + } + if (!result_t_temp.empty()) { + result_t.insert(result_t.end(), result_t_temp.begin(), + result_t_temp.end()); + } + } + } + if (d != standard) { + vector result_temp(4); // size为4的可能结果 + result_temp[3] = 0; // d=0 + if (compare_string(a, d)) // a=d + { + if (a == standard) + result_temp[0] = 2; + else + result_temp[0] = 0; // a=0 + if (compare_string(b, a) && + compare_string(b, d)) // b=(a=d) + { + if (b == standard) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(a, c) && compare_string(b, c) && + compare_string(d, c)) // c=(b=a=d) + { + result_temp[0] = 2; + result_temp[1] = 2; + result_temp[2] = 2; + result_temp[3] = 2; + } else // c!=(b=a=d) + { + result_temp[2] = 1; // c=1 + if (compare_string(a, c)) result_temp[0] = 2; + if (compare_string(b, c)) result_temp[1] = 2; + } + } else // b!=(a=d) + { + result_temp[1] = 1; // b=1 + if (compare_string(a, b)) result_temp[0] = 2; + if (compare_string(c, a) && + compare_string(c, d)) // c=(a=d) + { + if (c == standard || compare_string(c, b)) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + } else if (compare_string(c, b)) // c=b + { + result_temp[2] = 1; // c=1 + if (compare_string(a, c)) result_temp[0] = 2; + } else // 其他 + break; + } + } else // a!=d + { + result_temp[0] = 1; // a=1 + if (compare_string(b, d)) // b=d + { + if (b == standard || compare_string(b, a)) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(c, d) && + compare_string(c, b)) // c=(b=d) + { + if (c == standard || compare_string(c, a)) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + } else if (compare_string(c, a)) // c=a + result_temp[2] = 1; // c=1 + else // 其他 + break; + } else if (compare_string(b, a)) // b=a + { + result_temp[1] = 1; // b=1 + if (compare_string(c, d)) // c=d + { + if (c == standard || + (compare_string(a, c) && compare_string(b, c))) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + } else if (compare_string(c, a) && + compare_string(c, b)) // c=(b=a) + result_temp[2] = 1; // c=1 + else // 其他 + break; + } else // 其他 + break; + } + if (result_t.empty()) + vector_generate(result_temp, result_t); + else { + vector> result_t_temp; + vector_generate(result_temp, result_t_temp); + for (int j = result_t.size() - 1; j >= 0; j--) { + for (int k = result_t_temp.size() - 1; k >= 0; k--) { + if (compare_vector(result_t[j], result_t_temp[k])) + result_t_temp.erase(result_t_temp.begin() + k); + } + } + if (!result_t_temp.empty()) { + result_t.insert(result_t.end(), result_t_temp.begin(), + result_t_temp.end()); + } + } + } + if (result.empty()) + result.assign(result_t.begin(), result_t.end()); + else { + for (int j = result.size() - 1; j >= 0; j--) { + if (result[j] == standard_int) { + result.assign(result_t.begin(), result_t.end()); + break; + } else { + bool target1 = 0, target2 = 0; + for (int k = result_t.size() - 1; k >= 0; k--) { + if (result_t[k] == standard_int) { + target1 = 1; + break; + } else { + if (compare_vector(result_t[k], result[j])) { + target2 = 1; + break; + } + } + } + if (target1) break; + if (!target2) result.erase(result.begin() + j); + } + } + if (result.empty()) break; + } + } + if (result.empty()) { + bench_result.erase(bench_result.begin() + q); + continue; + } else { + for (int m = 0; m < result.size(); m++) { + std::string count1, count2; + std::string res1, res2; + for (int n = 0; n < result[m].size(); n++) { + if (result[m][n] == 0) { + count1 += "1"; + count2 += "0"; + } else { + count1 += "0"; + count2 += "1"; + } + } + if (count1 == "0000" || count1 == "1111" || + count2 == "0000" || count2 == "1111") + continue; + for (int n = 0; n < pow(2.0, matrix_form[l].eye); n++) { + std::string s1(2 * length1, '2'); + std::string s2(2 * length1, '2'); + int ind = + (length_string2 / pow(2.0, matrix_form[l].eye)) * n; + std::string a, b, c, d; + a = bench_result[q].computed_input.substr(ind, length1); + b = bench_result[q].computed_input.substr(ind + length1, + length1); + c = bench_result[q].computed_input.substr( + ind + (length1 * 2), length1); + d = bench_result[q].computed_input.substr( + ind + (length1 * 3), length1); + + if (count1[0] == '0') { + if (s1.substr(length1, length1) == standard) + s1.replace(length1, length1, a); + } else { + if (s1.substr(0, length1) == standard) + s1.replace(0, length1, a); + } + if (count1[1] == '0') { + if (s1.substr(length1, length1) == standard) + s1.replace(length1, length1, b); + } else { + if (s1.substr(0, length1) == standard) + s1.replace(0, length1, b); + } + if (count1[2] == '0') { + if (s1.substr(length1, length1) == standard) + s1.replace(length1, length1, c); + } else { + if (s1.substr(0, length1) == standard) + s1.replace(0, length1, c); + } + if (count1[3] == '0') { + if (s1.substr(length1, length1) == standard) + s1.replace(length1, length1, d); + } else { + if (s1.substr(0, length1) == standard) + s1.replace(0, length1, d); + } + + if (count2[0] == '0') { + if (s2.substr(length1, length1) == standard) + s2.replace(length1, length1, a); + } else { + if (s2.substr(0, length1) == standard) + s2.replace(0, length1, a); + } + if (count2[1] == '0') { + if (s2.substr(length1, length1) == standard) + s2.replace(length1, length1, b); + } else { + if (s2.substr(0, length1) == standard) + s2.replace(0, length1, b); + } + if (count2[2] == '0') { + if (s2.substr(length1, length1) == standard) + s2.replace(length1, length1, c); + } else { + if (s2.substr(0, length1) == standard) + s2.replace(0, length1, c); + } + if (count2[3] == '0') { + if (s2.substr(length1, length1) == standard) + s2.replace(length1, length1, d); + } else { + if (s2.substr(0, length1) == standard) + s2.replace(0, length1, d); + } + res1 += s1; + res2 += s2; + } + result_lut result_temp_1, result_temp_2; + result_temp_1.possible_result = + bench_result[q].possible_result; + result_temp_2.possible_result = + bench_result[q].possible_result; + for (int p = 0; p < result_temp_1.possible_result.size(); + p++) { + if (result_temp_1.possible_result[p].node == + matrix_form[l].node) + result_temp_1.possible_result[p].tt = count1; + if (result_temp_2.possible_result[p].node == + matrix_form[l].node) + result_temp_2.possible_result[p].tt = count2; + } + if (res1.size() == 4) { + for (int p = 0; p < result_temp_1.possible_result.size(); + p++) { + if (result_temp_1.possible_result[p].node == + matrix_form[0].node) + result_temp_1.possible_result[p].tt = res1; + if (result_temp_2.possible_result[p].node == + matrix_form[0].node) + result_temp_2.possible_result[p].tt = res2; + } + } else { + result_temp_1.computed_input = res1; + result_temp_2.computed_input = res2; + } + + bench_result_temp.push_back(result_temp_1); + bench_result_temp.push_back(result_temp_2); + } + } + } + if (bench_result_temp.empty()) + break; + else + bench_result.assign(bench_result_temp.begin(), + bench_result_temp.end()); + } + } + } + + vector bench_result1; + if (ps.aig) { + for (auto x : bench_result) { + bool aig_target = true; + for (auto y : x.possible_result) { + if (y.tt == "0001" || y.tt == "0010" || y.tt == "0100" || + y.tt == "0111" || y.tt == "1000" || y.tt == "1011" || + y.tt == "1101" || y.tt == "1110") { + continue; + } else { + aig_target = false; + } + } + if (aig_target) { + bench_result1.push_back(x); + } + } + } else if (ps.xag) { + for (auto x : bench_result) { + bool xag_target = true; + for (auto y : x.possible_result) { + if (y.tt == "0001" || y.tt == "0010" || y.tt == "0100" || + y.tt == "0111" || y.tt == "1000" || y.tt == "1011" || + y.tt == "1101" || y.tt == "1110" || y.tt == "0110" || + y.tt == "1001") { + continue; + } else { + xag_target = false; + } + } + if (xag_target) { + bench_result1.push_back(x); + } + } + } else { + bench_result1 = bench_result; + } + + for (int j = bench_result1.size() - 1; j >= 0; j--) { + vector> mtxvec; + vector mtx1, mtx2; + vector in; + for (int k = bench_result1[j].possible_result.size() - 1; k >= 0; k--) { + vector mtxvec_temp; + in.push_back(bench_result1[j].possible_result[k].tt); + mtxvec_temp.push_back(bench_result1[j].possible_result[k].left); + mtxvec_temp.push_back(bench_result1[j].possible_result[k].right); + mtxvec_temp.push_back(bench_result1[j].possible_result[k].node); + mtxvec.push_back(mtxvec_temp); + } + in.push_back("10"); + mtx1.push_back(bench_result1[j].possible_result[0].node); + mtx2.push_back(input); + mtx2.push_back(1); + mtxvec.push_back(mtx1); + mtxvec.push_back(mtx2); + vector> in_expansion = bench_expansion(in); + vector bench_temp; + for (int k = in_expansion.size() - 1; k >= 0; k--) { + std::string tt_temp = in_expansion[k][in_expansion[k].size() - 2]; + bench_solve(in_expansion[k], mtxvec); + if (!compare_result(in_expansion[k], tt_binary)) { + in_expansion.erase(in_expansion.begin() + k); + } else { + result_lut bench_temp_temp = bench_result1[j]; + bench_temp_temp.possible_result[0].tt = tt_temp; + bench_temp.push_back(bench_temp_temp); + } + } + if (in_expansion.empty()) + bench_result1.erase(bench_result1.begin() + j); + else { + bench_result1.erase(bench_result1.begin() + j); + bench_result1.insert(bench_result1.end(), bench_temp.begin(), + bench_temp.end()); + } + } + + if (bench_result1.size()) { + for (int j = 0; j < bench_result1.size(); j++) + lut_dags_new.push_back(bench_result1[j].possible_result); + } + } + lut_dags.assign(lut_dags_new.begin(), lut_dags_new.end()); + } + + std::string hex_to_binary() { + std::string t_temp; + for (int i = 0; i < tt.size(); i++) { + switch (tt[i]) { + case '0': + t_temp += "0000"; + continue; + case '1': + t_temp += "0001"; + continue; + case '2': + t_temp += "0010"; + continue; + case '3': + t_temp += "0011"; + continue; + case '4': + t_temp += "0100"; + continue; + case '5': + t_temp += "0101"; + continue; + case '6': + t_temp += "0110"; + continue; + case '7': + t_temp += "0111"; + continue; + case '8': + t_temp += "1000"; + continue; + case '9': + t_temp += "1001"; + continue; + case 'a': + t_temp += "1010"; + continue; + case 'b': + t_temp += "1011"; + continue; + case 'c': + t_temp += "1100"; + continue; + case 'd': + t_temp += "1101"; + continue; + case 'e': + t_temp += "1110"; + continue; + case 'f': + t_temp += "1111"; + continue; + case 'A': + t_temp += "1010"; + continue; + case 'B': + t_temp += "1011"; + continue; + case 'C': + t_temp += "1100"; + continue; + case 'D': + t_temp += "1101"; + continue; + case 'E': + t_temp += "1110"; + continue; + case 'F': + t_temp += "1111"; + continue; + } + } + return t_temp; + } + + std::string BinToHex(std::string& strBin) { + std::string strHex; + strHex.resize(strBin.size() / 4); + if (strBin == "0000") { + strHex = "0"; + } else if (strBin == "0001") { + strHex = "1"; + } else if (strBin == "0010") { + strHex = "2"; + } else if (strBin == "0011") { + strHex = "3"; + } else if (strBin == "0100") { + strHex = "4"; + } else if (strBin == "0101") { + strHex = "5"; + } else if (strBin == "0110") { + strHex = "6"; + } else if (strBin == "0111") { + strHex = "7"; + } else if (strBin == "1000") { + strHex = "8"; + } else if (strBin == "1001") { + strHex = "9"; + } else if (strBin == "1010") { + strHex = "a"; + } else if (strBin == "1011") { + strHex = "b"; + } else if (strBin == "1100") { + strHex = "c"; + } else if (strBin == "1101") { + strHex = "d"; + } else if (strBin == "1110") { + strHex = "e"; + } else { + strHex = "f"; + } + return strHex; + } + + vector chain_to_matrix(vector lut_dags, int flag_node) { + vector matrix_form; + matrix temp_node, temp_left, temp_right; + temp_node.node = lut_dags[0].node; + temp_node.name = "M"; + temp_left.node = lut_dags[0].left; + temp_right.node = lut_dags[0].right; + matrix_form.push_back(temp_node); + + if (lut_dags[0].right >= flag_node) { + vector matrix_form_temp2; + matrix_generate(lut_dags, matrix_form_temp2, lut_dags[0].right); + matrix_form.insert(matrix_form.end(), matrix_form_temp2.begin(), + matrix_form_temp2.end()); + } else { + temp_right.input = 1; + std::string str = to_string(lut_dags[0].right); + temp_right.name = str; + matrix_form.push_back(temp_right); + } + + if (lut_dags[0].left >= flag_node) { + vector matrix_form_temp1; + matrix_generate(lut_dags, matrix_form_temp1, lut_dags[0].left); + matrix_form.insert(matrix_form.end(), matrix_form_temp1.begin(), + matrix_form_temp1.end()); + } else { + temp_left.input = 1; + std::string str = to_string(lut_dags[0].left); + temp_left.name = str; + matrix_form.push_back(temp_left); + } + + return matrix_form; + } + + void matrix_computution(vector& matrix_form) { + bool status = true; + while (status) { + status = false; + for (int i = matrix_form.size() - 1; i > 1; i--) { + // 两个变量交换 + if (((matrix_form[i].name != "M") && (matrix_form[i].name != "R") && + (matrix_form[i].name != "W")) && + ((matrix_form[i - 1].name != "M") && + (matrix_form[i - 1].name != "R") && + (matrix_form[i - 1].name != "W"))) { + int left, right; + left = atoi(matrix_form[i - 1].name.c_str()); + right = atoi(matrix_form[i].name.c_str()); + // 相等变量降幂 + if (left == right) { + status = true; + matrix reduce_matrix; + reduce_matrix.name = "R"; + matrix_form.insert(matrix_form.begin() + (i - 1), reduce_matrix); + matrix_form.erase(matrix_form.begin() + i); + } else if (left < right) { + status = true; + matrix swap_matrix; + swap_matrix.name = "W"; + swap(matrix_form[i - 1], matrix_form[i]); + matrix_form.insert(matrix_form.begin() + (i - 1), swap_matrix); + } + } + // 变量与矩阵交换 + if (((matrix_form[i].name == "M") || (matrix_form[i].name == "R") || + (matrix_form[i].name == "W")) && + ((matrix_form[i - 1].name != "M") && + (matrix_form[i - 1].name != "R") && + (matrix_form[i - 1].name != "W"))) { + status = true; + matrix_form[i].eye += 1; + swap(matrix_form[i - 1], matrix_form[i]); + } + } + } + } + + void matrix_generate(vector lut, vector& matrix_form, + int node) { + int flag = lut[lut.size() - 1].node; + for (int i = 0; i < lut.size(); i++) { + if (lut[i].node == node) { + matrix temp_node, temp_left, temp_right; + temp_node.node = node; + temp_node.name = "M"; + matrix_form.push_back(temp_node); + if (lut[i].right >= flag) { + vector matrix_form_temp2; + matrix_generate(lut, matrix_form_temp2, lut[i].right); + matrix_form.insert(matrix_form.end(), matrix_form_temp2.begin(), + matrix_form_temp2.end()); + } else { + temp_right.input = 1; + temp_right.node = lut[i].right; + std::string str = to_string(lut[i].right); + temp_right.name = str; + matrix_form.push_back(temp_right); + } + if (lut[i].left >= flag) { + vector matrix_form_temp1; + matrix_generate(lut, matrix_form_temp1, lut[i].left); + matrix_form.insert(matrix_form.begin() + 1, matrix_form_temp1.begin(), + matrix_form_temp1.end()); + } else { + temp_left.input = 1; + temp_left.node = lut[i].left; + std::string str = to_string(lut[i].left); + temp_left.name = str; + matrix_form.push_back(temp_left); + } + } + } + } + + bool compare_string(std::string a, std::string b) { + bool target = true; + for (int i = 0; i < a.size(); i++) { + if ((a[i] != b[i]) && a[i] != '2' && b[i] != '2') { + target = false; + break; + } + } + return target; + } + + bool compare_vector(vector a, vector b) { + bool target = 0; + if (a == b) { + target = 1; + } else { + for (int i = 0; i < a.size(); i++) { + if (a[i] == 1) { + a[i] = 0; + } else if (a[i] == 0) { + a[i] = 1; + } + } + if (a == b) { + target = 1; + } + } + return target; + } + + bool compare_result(vector t1, std::string t2) { + bool target = false; + std::string t3(t2.size(), '0'); + for (int i = 0; i < t1.size(); i++) { + char temp; + for (int j = 0; j < t1[i].size() / 2; j++) { + temp = t1[i][j]; + t1[i][j] = t1[i][t1[i].size() - 1 - j]; + t1[i][t1[i].size() - 1 - j] = temp; + } + vector local; + for (int j = 0; j < t1[i].size(); j++) { + if (t1[i][j] == '2') local.push_back(j); + } + if (local.size()) { + vector t_temp; + t_temp.push_back(t1[i]); + for (auto x : local) { + vector t_temp_temp; + for (auto y : t_temp) { + string temp1 = y, temp2 = y; + temp1[x] = '1'; + temp2[x] = '0'; + t_temp_temp.push_back(temp1); + t_temp_temp.push_back(temp2); + } + t_temp = t_temp_temp; + } + for (auto x : t_temp) { + int value = stoi(x, 0, 2); + int ind = t3.size() - value - 1; + t3[ind] = '1'; + } + } else { + int value = stoi(t1[i], 0, 2); + int ind = t3.size() - value - 1; + t3[ind] = '1'; + } + } + + if (t2 == t3) target = true; + return target; + } + + void vector_generate(vector result_b, vector>& result_a) { + for (int i = 0; i < result_b.size(); i++) { + if (result_b[i] != 2) { + if (result_a.empty()) { + vector temp; + temp.push_back(result_b[i]); + result_a.push_back(temp); + } else { + vector> result_a_temp; + for (int j = 0; j < result_a.size(); j++) { + vector temp(result_a[j]); + temp.push_back(result_b[i]); + result_a_temp.push_back(temp); + } + result_a.assign(result_a_temp.begin(), result_a_temp.end()); + } + } else { + if (result_a.empty()) { + vector temp1(1, 1); + vector temp2(1, 0); + result_a.push_back(temp1); + result_a.push_back(temp2); + } else { + vector> result_a_temp; + for (int j = 0; j < result_a.size(); j++) { + vector temp1(result_a[j]); + vector temp2(result_a[j]); + temp1.push_back(1); + temp2.push_back(0); + result_a_temp.push_back(temp1); + result_a_temp.push_back(temp2); + } + result_a.assign(result_a_temp.begin(), result_a_temp.end()); + } + } + } + } + + void print_chain() { to_chain(std::cout); } + + void to_chain(std::ostream& s) { + for (int i = 0; i < exact_synthesis_results.size(); i++) { + for (auto x : phyLS::reverse(exact_synthesis_results[i])) { + s << x.node << " = 4'b" << x.tt << " (" << x.left << ", " << x.right + << ") "; + } + s << "\n"; + } + } + + void print_npn() { to_npn(std::cout); } + + void to_npn(std::ostream& s) { + for (int i = 0; i < exact_synthesis_results.size(); i++) { + for (auto x : phyLS::reverse(exact_synthesis_results[i])) { + s << x.node << "-" << BinToHex(x.tt) << "-" << x.left << "-" << x.right + << " "; + } + s << "\n"; + } + } + + void store_bench() { + for (int i = 0; i < exact_synthesis_results.size(); i++) { + std::ofstream file; + std::string filename = "r_" + std::to_string(i) + ".bench"; + file.open(filename, std::ios::out); + for (int i = 0; i < input; i++) { + const auto idx = i + 1; + file << "INPUT(n" << idx << ")\n"; + } + file << "OUTPUT(po" << 0 << ")\n"; + file << "n0 = gnd\n"; + for (auto x : phyLS::reverse(exact_synthesis_results[i])) { + file << "n" << x.node << " = "; + file << "LUT 0x" << BinToHex(x.tt) << " (n" << x.left << ", n" + << x.right << ")\n"; + } + file << "po0 = LUT 0x2 (n" << exact_synthesis_results[i][0].node << ")\n"; + file.close(); + } + } + + klut_network create_network(chain& c) { + klut_network klut; + c.store_bench(0); + std::string filename = "r_0.bench"; + if (lorina::read_bench(filename, mockturtle::bench_reader(klut)) != + lorina::return_code::success) { + std::cout << "[w] parse error\n"; + } + return klut; + } + + bool compare_min_area(double area_temp, double delay_temp, int gate) { + bool target = false; + if (min_area == 0.00 && min_delay == 0.00) { + min_area = area_temp; + min_delay = delay_temp; + mapping_gate = gate; + target = true; + } else if (area_temp < min_area) { + min_area = area_temp; + min_delay = delay_temp; + mapping_gate = gate; + target = true; + } else if (area_temp == min_area) { + if (delay_temp < min_delay) { + min_delay = delay_temp; + mapping_gate = gate; + target = true; + } + } + return target; + } + + void bench_solve(vector& in, vector> mtxvec) { + int length1 = mtxvec[mtxvec.size() - 1][0]; // number of primary input + int length2 = mtxvec[mtxvec.size() - 1][1]; // number of primary output + int length3 = mtxvec[0][2]; // the minimum minuend + int length4 = + mtxvec[mtxvec.size() - 2 - length2][2]; // the maximum variable + vector> + list; // the solution space is two dimension vector + vector list_temp; + cdccl_impl_dag list_temp_temp; + + std::string Result_temp(length1, '2'); // temporary result + coordinate_dag Level_temp; + Level_temp.Abscissa = -1; + Level_temp.Ordinate = -1; + Level_temp.parameter_Intermediate = -1; + Level_temp.parameter_Gate = -1; + list_temp_temp.Level.resize( + length4, Level_temp); // Initialize level as a space with the size of + // variables(length4) + /* + * initialization + */ + coordinate_dag Gate_level; + Gate_level.Abscissa = 0; + Gate_level.Ordinate = 0; + Gate_level.parameter_Intermediate = -1; + Gate_level.parameter_Gate = -1; + std::string Intermediate_temp; + for (int i = mtxvec.size() - 1 - length2; i < mtxvec.size() - 1; + i++) // the original intermediate + { + if (mtxvec[i][0] < length3) { + if (in[i][0] == '1') + Result_temp[mtxvec[i][0] - 1] = '1'; + else + Result_temp[mtxvec[i][0] - 1] = '0'; + } else { + list_temp_temp.Gate.push_back(mtxvec[i][0]); + if (in[i][0] == '1') + Intermediate_temp += "1"; + else + Intermediate_temp += "0"; + } + list_temp_temp.Level[mtxvec[i][0] - 1] = Gate_level; + } + list_temp_temp.Result = Result_temp; + list_temp_temp.Intermediate.push_back(Intermediate_temp); + list_temp.push_back(list_temp_temp); // level 0 + list.push_back(list_temp); + /* + * The first level information + */ + int count1 = 0; + for (int level = 0;; level++) // the computation process + { + int flag = 0, ordinate = 0; // the flag of the end of the loop & the + // ordinate of each level's gate + vector list_temp1; + for (int k = 0; k < list[level].size(); k++) { + cdccl_impl_dag temp1; // temporary gate + temp1.Result = list[level][k].Result; // first, next level's Result is + // same as the front level + for (int j = 0; j < list[level][k].Intermediate.size(); j++) { + temp1.Level = list[level][k].Level; // next level's Level information + for (int j1 = 0; j1 < list[level][k].Gate.size(); j1++) { + temp1.Level[list[level][k].Gate[j1] - 1].parameter_Intermediate = j; + temp1.Level[list[level][k].Gate[j1] - 1].parameter_Gate = j1; + } + + coordinate_dag level_current; // new level + level_current.Abscissa = level + 1; + level_current.parameter_Intermediate = -1; + level_current.parameter_Gate = -1; + level_current.Ordinate = ordinate; + + temp1.Gate.assign(list[level][k].Gate.begin(), + list[level][k].Gate.end()); // need more!!!!! + temp1.Intermediate.push_back(list[level][k].Intermediate[j]); + + vector Intermediate_temp; + vector Gate_temp; + vector Gate_judge(length4, -1); + int count_cdccl = 0; + for (int i = 0; i < temp1.Gate.size(); i++) { + int length = temp1.Gate[i] - length3; + int Gate_f = mtxvec[length][0]; // the front Gate variable + int Gate_b = mtxvec[length][1]; // the behind Gate variable + std::string tt = in[length]; // the correndsponding Truth Table + char target = temp1.Intermediate[0][i]; // the SAT target + vector Intermediate_temp_temp; + + int flag_cdccl = 0; + std::string Intermediate_temp_temp_F, Intermediate_temp_temp_B; + if (temp1.Level[Gate_f - 1].Abscissa >= 0) { + if (Gate_f < length3) { + char contrast_R1 = list[temp1.Level[Gate_f - 1].Abscissa] + [temp1.Level[Gate_f - 1].Ordinate] + .Result[Gate_f - 1]; + Intermediate_temp_temp_F.push_back(contrast_R1); + } else { + char contrast_I1 = + list[temp1.Level[Gate_f - 1].Abscissa] + [temp1.Level[Gate_f - 1].Ordinate] + .Intermediate + [temp1.Level[Gate_f - 1].parameter_Intermediate] + [temp1.Level[Gate_f - 1].parameter_Gate]; + Intermediate_temp_temp_F.push_back(contrast_I1); + } + flag_cdccl += 1; + } + if (temp1.Level[Gate_b - 1].Abscissa >= 0) { + if (Gate_b < length3) { + char contrast_R2 = list[temp1.Level[Gate_b - 1].Abscissa] + [temp1.Level[Gate_b - 1].Ordinate] + .Result[Gate_b - 1]; + Intermediate_temp_temp_B.push_back(contrast_R2); + } else { + char contrast_I2 = + list[temp1.Level[Gate_b - 1].Abscissa] + [temp1.Level[Gate_b - 1].Ordinate] + .Intermediate + [temp1.Level[Gate_b - 1].parameter_Intermediate] + [temp1.Level[Gate_b - 1].parameter_Gate]; + Intermediate_temp_temp_B.push_back(contrast_I2); + } + flag_cdccl += 2; + } + if (Intermediate_temp.size() == 0) { + if (flag_cdccl == 0) { + Gate_judge[Gate_f - 1] = count_cdccl; + count_cdccl += 1; + Gate_judge[Gate_b - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_f); + Gate_temp.push_back(Gate_b); + if (tt[0] == target) Intermediate_temp_temp.push_back("11"); + if (tt[1] == target) Intermediate_temp_temp.push_back("01"); + if (tt[2] == target) Intermediate_temp_temp.push_back("10"); + if (tt[3] == target) Intermediate_temp_temp.push_back("00"); + } else if (flag_cdccl == 1) { + Gate_judge[Gate_b - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_b); + if (tt[0] == target) { + if (Intermediate_temp_temp_F == "1") + Intermediate_temp_temp.push_back("1"); + } + if (tt[1] == target) { + if (Intermediate_temp_temp_F == "0") + Intermediate_temp_temp.push_back("1"); + } + if (tt[2] == target) { + if (Intermediate_temp_temp_F == "1") + Intermediate_temp_temp.push_back("0"); + } + if (tt[3] == target) { + if (Intermediate_temp_temp_F == "0") + Intermediate_temp_temp.push_back("0"); + } + } else if (flag_cdccl == 2) { + Gate_judge[Gate_f - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_f); + if (tt[0] == target) { + if (Intermediate_temp_temp_B == "1") + Intermediate_temp_temp.push_back("1"); + } + if (tt[1] == target) { + if (Intermediate_temp_temp_B == "1") + Intermediate_temp_temp.push_back("0"); + } + if (tt[2] == target) { + if (Intermediate_temp_temp_B == "0") + Intermediate_temp_temp.push_back("1"); + } + if (tt[3] == target) { + if (Intermediate_temp_temp_B == "0") + Intermediate_temp_temp.push_back("0"); + } + } else { + int t0 = 0, t1 = 0, t2 = 0, t3 = 0; + if (tt[0] == target) { + if ((Intermediate_temp_temp_F == "1") && + (Intermediate_temp_temp_B == "1")) + t0 = 1; + } + if (tt[1] == target) { + if ((Intermediate_temp_temp_F == "0") && + (Intermediate_temp_temp_B == "1")) + t1 = 1; + } + if (tt[2] == target) { + if ((Intermediate_temp_temp_F == "1") && + (Intermediate_temp_temp_B == "0")) + t2 = 1; + } + if (tt[3] == target) { + if ((Intermediate_temp_temp_F == "0") && + (Intermediate_temp_temp_B == "0")) + t3 = 1; + } + if ((t0 == 1) || (t1 == 1) || (t2 == 1) || (t3 == 1)) { + Gate_judge[Gate_f - 1] = count_cdccl; + count_cdccl += 1; + Gate_judge[Gate_b - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_f); + Gate_temp.push_back(Gate_b); + if (t0 == 1) Intermediate_temp_temp.push_back("11"); + if (t1 == 1) Intermediate_temp_temp.push_back("01"); + if (t2 == 1) Intermediate_temp_temp.push_back("10"); + if (t3 == 1) Intermediate_temp_temp.push_back("00"); + } + } + } else { + if (flag_cdccl == 0) { + int count_Gate_f = 0, count_Gate_b = 0; + for (int j = 0; j < Intermediate_temp.size(); j++) { + int flag; + std::string t1, t2, t3, t4; + if (Gate_judge[Gate_f - 1] < 0) { + count_Gate_f = 1; + if (tt[0] == target) t1 = "1"; + if (tt[1] == target) t2 = "0"; + if (tt[2] == target) t3 = "1"; + if (tt[3] == target) t4 = "0"; + flag = 1; + } else { + int count_sat = 0; + if (tt[0] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_f - 1]] == '1') { + t1 = "11"; + count_sat += 1; + } + } + if (tt[1] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_f - 1]] == '0') { + t2 = "01"; + count_sat += 1; + } + } + if (tt[2] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_f - 1]] == '1') { + t3 = "10"; + count_sat += 1; + } + } + if (tt[3] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_f - 1]] == '0') { + t4 = "00"; + count_sat += 1; + } + } + if (count_sat == 0) continue; + flag = 2; + } + if (Gate_judge[Gate_b - 1] < 0) { + count_Gate_b = 1; + if (flag == 1) { + if (t1 == "1") { + t1 += "1"; + std::string result_temporary(Intermediate_temp[j]); + result_temporary += t1; + Intermediate_temp_temp.push_back(result_temporary); + } + if (t2 == "0") { + t2 += "1"; + std::string result_temporary(Intermediate_temp[j]); + result_temporary += t2; + Intermediate_temp_temp.push_back(result_temporary); + } + if (t3 == "1") { + t3 += "0"; + std::string result_temporary(Intermediate_temp[j]); + result_temporary += t3; + Intermediate_temp_temp.push_back(result_temporary); + } + if (t4 == "0") { + t4 += "0"; + std::string result_temporary(Intermediate_temp[j]); + result_temporary += t4; + Intermediate_temp_temp.push_back(result_temporary); + } + } + if (flag == 2) { + if (t1 == "11") { + t1 = "1"; + std::string result_temporary(Intermediate_temp[j]); + result_temporary += t1; + Intermediate_temp_temp.push_back(result_temporary); + } + if (t2 == "01") { + t2 = "1"; + std::string result_temporary(Intermediate_temp[j]); + result_temporary += t2; + Intermediate_temp_temp.push_back(result_temporary); + } + if (t3 == "10") { + t3 = "0"; + std::string result_temporary(Intermediate_temp[j]); + result_temporary += t3; + Intermediate_temp_temp.push_back(result_temporary); + } + if (t4 == "00") { + t4 = "0"; + std::string result_temporary(Intermediate_temp[j]); + result_temporary += t4; + Intermediate_temp_temp.push_back(result_temporary); + } + } + } else { + if (flag == 1) { + if (tt[0] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '1') { + std::string result_temporary(Intermediate_temp[j]); + result_temporary += t1; + Intermediate_temp_temp.push_back(result_temporary); + } + } + if (tt[1] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '1') { + std::string result_temporary(Intermediate_temp[j]); + result_temporary += t2; + Intermediate_temp_temp.push_back(result_temporary); + } + } + if (tt[2] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '0') { + std::string result_temporary(Intermediate_temp[j]); + result_temporary += t3; + Intermediate_temp_temp.push_back(result_temporary); + } + } + if (tt[3] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '0') { + std::string result_temporary(Intermediate_temp[j]); + result_temporary += t4; + Intermediate_temp_temp.push_back(result_temporary); + } + } + } + if (flag == 2) { + int count_sat1 = 0; + if (t1 == "11") { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == '1') + count_sat1 += 1; + } + if (t2 == "01") { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == '1') + count_sat1 += 1; + } + if (t3 == "10") { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == '0') + count_sat1 += 1; + } + if (t4 == "00") { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == '0') + count_sat1 += 1; + } + if (count_sat1 > 0) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + } + } + if (count_Gate_f == 1) { + Gate_judge[Gate_f - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_f); + } + if (count_Gate_b == 1) { + Gate_judge[Gate_b - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_b); + } + } else if (flag_cdccl == 1) { + int flag_1 = 0; + for (int j = 0; j < Intermediate_temp.size(); j++) { + if (Gate_judge[Gate_b - 1] < 0) { + flag_1 = 1; + if (tt[0] == target) { + if (Intermediate_temp_temp_F == "1") { + std::string Intermediate_temp_temp1( + Intermediate_temp[j]); + Intermediate_temp_temp1 += "1"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + if (tt[1] == target) { + if (Intermediate_temp_temp_F == "0") { + std::string Intermediate_temp_temp1( + Intermediate_temp[j]); + Intermediate_temp_temp1 += "1"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + if (tt[2] == target) { + if (Intermediate_temp_temp_F == "1") { + std::string Intermediate_temp_temp1( + Intermediate_temp[j]); + Intermediate_temp_temp1 += "0"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + if (tt[3] == target) { + if (Intermediate_temp_temp_F == "0") { + std::string Intermediate_temp_temp1( + Intermediate_temp[j]); + Intermediate_temp_temp1 += "0"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + } else { + if (tt[0] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '1') && + (Intermediate_temp_temp_F == "1")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[1] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '1') && + (Intermediate_temp_temp_F == "0")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[2] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '0') && + (Intermediate_temp_temp_F == "1")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[3] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '0') && + (Intermediate_temp_temp_F == "0")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + } + } + if (flag_1 == 1) { + Gate_judge[Gate_b - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_b); + } + } else if (flag_cdccl == 2) { + int flag_2 = 0; + for (int j = 0; j < Intermediate_temp.size(); j++) { + if (Gate_judge[Gate_f - 1] < 0) { + flag_2 = 1; + if (tt[0] == target) { + if (Intermediate_temp_temp_B == "1") { + std::string Intermediate_temp_temp1( + Intermediate_temp[j]); + Intermediate_temp_temp1 += "1"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + if (tt[1] == target) { + if (Intermediate_temp_temp_B == "1") { + std::string Intermediate_temp_temp1( + Intermediate_temp[j]); + Intermediate_temp_temp1 += "0"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + if (tt[2] == target) { + if (Intermediate_temp_temp_B == "0") { + std::string Intermediate_temp_temp1( + Intermediate_temp[j]); + Intermediate_temp_temp1 += "1"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + if (tt[3] == target) { + if (Intermediate_temp_temp_B == "0") { + std::string Intermediate_temp_temp1( + Intermediate_temp[j]); + Intermediate_temp_temp1 += "0"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + } else { + if (tt[0] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_f - 1]] == + '1') && + (Intermediate_temp_temp_B == "1")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[1] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_f - 1]] == + '0') && + (Intermediate_temp_temp_B == "1")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[2] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_f - 1]] == + '1') && + (Intermediate_temp_temp_B == "0")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[3] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_f - 1]] == + '0') && + (Intermediate_temp_temp_B == "0")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + } + } + if (flag_2 == 1) { + Gate_judge[Gate_f - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_f); + } + } else { + for (int j = 0; j < Intermediate_temp.size(); j++) { + if (tt[0] == target) { + if ((Intermediate_temp_temp_F == "1") && + (Intermediate_temp_temp_B == "1")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[1] == target) { + if ((Intermediate_temp_temp_F == "0") && + (Intermediate_temp_temp_B == "1")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[2] == target) { + if ((Intermediate_temp_temp_F == "1") && + (Intermediate_temp_temp_B == "0")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[3] == target) { + if ((Intermediate_temp_temp_F == "0") && + (Intermediate_temp_temp_B == "0")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + } + } + } + Intermediate_temp.assign(Intermediate_temp_temp.begin(), + Intermediate_temp_temp.end()); + if (Intermediate_temp_temp.size() == 0) break; + } + temp1.Intermediate.assign(Intermediate_temp.begin(), + Intermediate_temp.end()); + temp1.Gate.assign(Gate_temp.begin(), Gate_temp.end()); + for (int l = 0; l < temp1.Gate.size(); l++) + temp1.Level[temp1.Gate[l] - 1] = level_current; + + int count = 0; // whether there is a PI assignment + for (int k = 0; k < temp1.Intermediate.size(); + k++) // mix the Result and the Intermediate information in one + // level + { + count = 1; + cdccl_impl_dag temp2; + temp2.Level = temp1.Level; + std::string Result_temp(temp1.Result); + temp2.Gate.assign(temp1.Gate.begin(), temp1.Gate.end()); + std::string Intermediate_temp1(temp1.Intermediate[k]); + int count1 = 0, count2 = 0; // whether the assignment made + for (int k11 = 0; k11 < temp1.Gate.size(); k11++) { + if (temp1.Gate[k11] < + length3) // if the Gate is smaller than length3, it is PI + { + temp2.Level[temp1.Gate[k11] - 1].Ordinate = ordinate; + if ((temp1.Result[temp1.Gate[k11] - 1] == '2') || + (temp1.Result[temp1.Gate[k11] - 1] == + temp1.Intermediate[k][k11])) // whether the PI can be + // assigned a value + Result_temp[temp1.Gate[k11] - 1] = temp1.Intermediate[k][k11]; + else + count1 = 1; // if one assignment can't make, the count1 = 1 + Intermediate_temp1.erase(Intermediate_temp1.begin() + + (k11 - count2)); + temp2.Gate.erase(temp2.Gate.begin() + (k11 - count2)); + count++, count2++; + } + } + if (count1 == 0) { + temp2.Result = Result_temp; + temp2.Intermediate.push_back(Intermediate_temp1); + for (int k12 = 0; k12 < temp2.Gate.size(); k12++) + temp2.Level[temp2.Gate[k12] - 1].Ordinate = ordinate; + } + if (count == 1) + break; + else if (temp2.Result.size() > 0) { + list_temp1.push_back(temp2); + ordinate += 1; + if (temp2.Gate.empty()) flag += 1; + } + } + if (count == 1) { + list_temp1.push_back(temp1); + ordinate += 1; + if (temp1.Gate.empty()) flag += 1; + } + temp1.Intermediate.clear(); + } + } + list.push_back(list_temp1); // next level's information + if (flag == list[level + 1].size()) // in one level, if all node's Gate + // is empty, then break the loop + break; + } + + in.clear(); + for (int j = 0; j < list[list.size() - 1].size(); j++) // all result + in.push_back(list[list.size() - 1][j].Result); + } + + vector> bench_expansion(vector in) { + vector> in_expansion; + in_expansion.push_back(in); + std::string in_end = in[in.size() - 2]; + for (int i = 0; i < in_end.size(); i++) { + if (in_end[i] == '2') { + vector> in_expansion_temp; + for (int j = 0; j < in_expansion.size(); j++) { + vector in_temp_1(in_expansion[j]); + vector in_temp_0(in_expansion[j]); + in_temp_1[in_expansion[j].size() - 2][i] = '1'; + in_temp_0[in_expansion[j].size() - 2][i] = '0'; + in_expansion_temp.push_back(in_temp_1); + in_expansion_temp.push_back(in_temp_0); + } + in_expansion.assign(in_expansion_temp.begin(), in_expansion_temp.end()); + } + } + return in_expansion; + } + + private: + std::string& tt; + int& input; + exact_lut_params& ps; + double min_area = 0.00; + double min_delay = 0.00; + int mapping_gate = 0; +}; + +void exact_lut_dag(std::string& tt, int& input, exact_lut_params& ps) { + dag_impl p(tt, input, ps); + p.run(); +} + +void exact_lut_dag_enu(std::string& tt, int& input, exact_lut_params& ps) { + dag_impl p(tt, input, ps); + p.run_enu(); +} + +void exact_lut_dag_enu_map(std::string& tt, int& input, exact_lut_params& ps) { + dag_impl p(tt, input, ps); + p.run_enu_map(); +} + +} // namespace phyLS + +#endif \ No newline at end of file diff --git a/src/core/exact/exact_lut.cpp b/src/core/exact/exact_lut.cpp new file mode 100644 index 0000000..f46f616 --- /dev/null +++ b/src/core/exact/exact_lut.cpp @@ -0,0 +1,2898 @@ +#include "exact_lut.hpp" + +using namespace std; + +namespace phyLS { +struct node_inf { + int num; + int level; + bool fan_out = 0; + bool fan_in = 0; +}; + +struct bench { + int node; + int right = 0; + int left = 0; + string tt = "2222"; +}; + +struct dag { + int node; + int level; + vector count; + vector> lut; +}; + +struct matrix { + int eye = 0; + int node = 0; + string name; + bool input = 0; +}; + +struct result_lut { + string computed_input; + vector possible_result; +}; + +struct coordinate { + int Abscissa; + int Ordinate; + int parameter_Intermediate; + int parameter_Gate; +}; + +struct cdccl_impl { + vector Intermediate; + string Result; + vector Gate; + vector Level; // Define the network as a coordinate system +}; + +class exact_lut_impl { + public: + exact_lut_impl(vector& tt, int& input) : tt(tt), input(input) {} + + void run() { exact_lut_network(); } + + void run_enu() { exact_lut_network_enu(); } + + private: + void exact_lut_network() { + // the DAG topology family of r nodes and k levels + // initialization + int num_node = input - 1; // first, number of node is number of input - 1 + int num_level = 2; + while (1) { + vector> lut; + create_dags(lut, num_node, num_level); + + if (lut.empty()) { + if (num_level <= num_node) { + num_level += 1; + } + if (num_level > num_node) { + num_level = 2; + num_node += 1; + } + continue; + } + // AllSAT solving to judge the DAGs + stp_simulate(lut); + if (lut.size()) { + vector result_final; + for (int i = 0; i < lut.size(); i++) { + string result; + for (int j = 0; j < lut[i].size(); j++) { + result += to_string(lut[i][j].node); + result += " = 4'b"; + result += lut[i][j].tt; + result += " ("; + if (lut[i][j].left <= input) { + char temp; + temp = 'a' + lut[i][j].left - 1; + result.push_back(temp); + } else { + result += to_string(lut[i][j].left); + } + result += ", "; + if (lut[i][j].right <= input) { + char temp; + temp = 'a' + lut[i][j].right - 1; + result.push_back(temp); + } else { + result += to_string(lut[i][j].right); + } + result += ") "; + } + result_final.push_back(result); + } + tt.assign(result_final.begin(), result_final.end()); + break; + } else { + if (num_level <= num_node) { + num_level += 1; + } + if (num_level > num_node) { + num_level = 2; + num_node += 1; + } + } + } + } + + void exact_lut_network_enu() { + // the DAG topology family of r nodes and k levels + // initialization + int num_node = input - 1; // first, number of node is number of input - 1 + int num_level = 2; + while (1) { + vector> lut; + create_dags(lut, num_node, num_level); + + if (lut.empty()) { + if (num_level <= num_node) { + num_level += 1; + } + if (num_level > num_node) { + num_level = 2; + num_node += 1; + } + continue; + } + // AllSAT solving to judge the DAGs + stp_simulate_enu(lut); + if (lut.size()) { + vector result_final; + for (int i = 0; i < lut.size(); i++) { + string result; + for (int j = 0; j < lut[i].size(); j++) { + result += to_string(lut[i][j].node); + result += " = 4'b"; + result += lut[i][j].tt; + result += " ("; + if (lut[i][j].left <= input) { + char temp; + temp = 'a' + lut[i][j].left - 1; + result.push_back(temp); + } else { + result += to_string(lut[i][j].left); + } + result += ", "; + if (lut[i][j].right <= input) { + char temp; + temp = 'a' + lut[i][j].right - 1; + result.push_back(temp); + } else { + result += to_string(lut[i][j].right); + } + result += ") "; + } + result_final.push_back(result); + } + tt.assign(result_final.begin(), result_final.end()); + break; + } else { + if (num_level <= num_node) { + num_level += 1; + } + if (num_level > num_node) { + num_level = 2; + num_node += 1; + } + } + } + } + + void create_dags(vector>& lut_dags, int node, int level) { + dag lut_dag_init; + lut_dag_init.node = node; + lut_dag_init.level = level; + lut_dag_init.count.resize(level + 1, 1); + lut_dag_init.count[0] = input; + int numnodes = node - level; + int numlevels = level - 1; + vector> q; + if (numlevels > 0) { + if (numnodes == 0) { + vector> lut_dags_temp; + bench_dag(lut_dag_init, lut_dags_temp); + lut_dags.insert(lut_dags.end(), lut_dags_temp.begin(), + lut_dags_temp.end()); + } else { + dag_classify(q, numnodes, numlevels); + for (int i = 0; i < q.size(); i++) { + dag lut_dag_temp = lut_dag_init; + for (int j = 1, k = 0; j < level; j++, k++) { + lut_dag_temp.count[j] += q[i][k]; + } + judge_dag(lut_dag_temp); + if (lut_dag_temp.count.size() != 0) { + vector> lut_dags_temp; + bench_dag(lut_dag_temp, lut_dags_temp); + lut_dags.insert(lut_dags.end(), lut_dags_temp.begin(), + lut_dags_temp.end()); + } + } + } + } + } + + void dag_classify(vector>& result, int numnodes, int numlevels) { + int q[numlevels]; + int x = numnodes; + int j; + for (int i = 0; i < numlevels; i++) { + q[i] = 0; + } + while (1) { + j = 0; + q[0] = x; + while (1) { + vector result_temp; + for (int i = numlevels - 1; i >= 0; i--) { + result_temp.push_back(q[i]); + } + result.push_back(result_temp); + if (j == 0) { + x = q[0] - 1; + j = 1; + } else if (q[0] == 0) { + x = q[j] - 1; + q[j] = 0; + j++; + } + if (j >= numlevels) { + return; + } else if (q[j] == numnodes) { + x = x + numlevels; + q[j] = 0; + j++; + if (j >= numlevels) { + return; + } + } + q[j]++; + if (x == 0) { + q[0] = 0; + continue; + } else { + break; + } + } + } + } + + void judge_dag(dag& lut_dag) { + for (int i = 0; i < lut_dag.count.size(); i++) { + int sum = + accumulate(lut_dag.count.begin() + i + 1, lut_dag.count.end(), 0); + if (lut_dag.count[i] - 1 > sum) { + lut_dag.count.clear(); + break; + } + } + } + + void bench_dag(dag lut_dag, vector>& lut_dags) { + int sum = 0, level_temp = 0, self_temp = 1; + // 第一个for循环 + // 通过lut_dag的count,初始化lut_dag的lut + // 编号每一个节点,并且将其放置在对应的层中 + // 每一层就是lut的层 + for (int i = 0; i < lut_dag.count.size(); i++, level_temp++) { + vector node_vec; + sum += lut_dag.count[i]; + for (; self_temp < sum + 1; self_temp++) { + node_inf node; + node.num = self_temp; + node.level = level_temp; + if (self_temp <= lut_dag.count[0]) { + node.fan_in = 1; + } else if (i == lut_dag.count.size() - 1) { + node.fan_out = 1; + } + node_vec.push_back(node); + } + lut_dag.lut.push_back(node_vec); + } + + /* + cout << "node information : " << endl; + for (auto x : lut_dag.lut) + { + for (auto y : x) + { + cout << y.num << " " << y.level << " " << y.fan_in << " " << + y.fan_out << endl; + } + } + */ + + // 第二个for循环 + // 生成所有满足的DAG结构 + for (int i = lut_dag.lut.size() - 1; i >= 0; i--) { + vector lut_dags_mid; + vector permutation; + // 第2.1个for循环 + // 从lut的最上层开始向下进行遍历 + // 若为输出节点,则直接构造节点,不排列组合并放入结果中 + // 若为输入节点,不构造,直接进行排列组合(permutation) + // 否则,先构造,再排列组合 + for (int j = lut_dag.lut[i].size() - 1; j >= 0; j--) { + if (lut_dag.lut[i][j].fan_out) { + bench LUT_fanout; + LUT_fanout.node = lut_dag.lut[i][j].num; + vector lut_dags_fanout; + lut_dags_fanout.push_back(LUT_fanout); + lut_dags.push_back(lut_dags_fanout); + } else if (lut_dag.lut[i][j].fan_in) { + permutation.push_back(lut_dag.lut[i][j].num); + } else { + bench LUT_mid; + LUT_mid.node = lut_dag.lut[i][j].num; + lut_dags_mid.push_back(LUT_mid); + permutation.push_back(lut_dag.lut[i][j].num); + } + } + // 排列组合算法 + // 仅针对中间节点进行排列组合 + if (permutation.size()) { + vector> lut_dags_result; + // 第2.2个for循环 + // 遍历已存在的所有结果(lut_dags) + for (int k = 0; k < lut_dags.size(); k++) { + vector lut_dags_rst_temp; // 尚未满足的节点 + vector lut_dags_rst; // 已满足的节点 + vector count; + // 第2.2.1个for循环 + // 为排列组合做准备 + // 判断还有哪些节点未填满,并确定剩余空间 + for (int l = 0; l < lut_dags[k].size(); l++) { + if (lut_dags[k][l].left == 0 || lut_dags[k][l].right == 0) { + int space_temp = 0; + if (lut_dags[k][l].right == 0) { + space_temp += 1; + } + if (lut_dags[k][l].left == 0) { + space_temp += 1; + } + count.push_back(space_temp); + lut_dags_rst_temp.push_back(lut_dags[k][l]); + } else { + lut_dags_rst.push_back(lut_dags[k][l]); + } + } + vector> result; + int numnodes = permutation.size(); + int space = accumulate(count.begin(), count.end(), 0); + if (space == numnodes) { + vector> result_temp; + dag_generate_complete(result, result_temp, permutation, count, 0); + } else if (space < numnodes) { + result.clear(); + } else { + vector> result_temp; + dag_generate_uncomplete(result, result_temp, permutation, + permutation, count, 0); + } + // result有结果 + if (result.size()) { + if (i == 0) { + for (int m = 0; m < result.size(); m++) { + bool target = 1; + vector result_temp1; + int n2 = 0; + for (int n1 = 0; n1 < lut_dags_rst_temp.size(); n1++) { + bench result_temp_temp = lut_dags_rst_temp[n1]; + if (result_temp_temp.left == 0 && + result_temp_temp.right == 0) { + if (result[m][n2] != 0) { + result_temp_temp.left = result[m][n2]; + } else { + target = 0; + } + if (result[m][n2 + 1] != 0) { + result_temp_temp.right = result[m][n2 + 1]; + } else { + target = 0; + } + n2 += 2; + } else if (result_temp_temp.left == 0 && + result_temp_temp.right != 0) { + if (result[m][n2] != 0) { + result_temp_temp.left = result[m][n2]; + } else { + target = 0; + } + n2 += 1; + } + if (!target) { + break; + } + result_temp1.push_back(result_temp_temp); + } + if (target) { + if (lut_dags_mid.size()) { + result_temp1.insert(result_temp1.end(), + lut_dags_mid.begin(), + lut_dags_mid.end()); + } + if (lut_dags_rst.size()) { + result_temp1.insert(result_temp1.begin(), + lut_dags_rst.begin(), + lut_dags_rst.end()); + } + lut_dags_result.push_back(result_temp1); + } + } + } else { + for (int m = 0; m < result.size(); m++) { + vector result_temp1; + int n2 = 0; + for (int n1 = 0; n1 < lut_dags_rst_temp.size(); n1++) { + bench result_temp_temp = lut_dags_rst_temp[n1]; + if (result_temp_temp.left == 0 && + result_temp_temp.right == 0) { + result_temp_temp.left = result[m][n2]; + result_temp_temp.right = result[m][n2 + 1]; + n2 += 2; + } else if (result_temp_temp.left == 0 && + result_temp_temp.right != 0) { + result_temp_temp.left = result[m][n2]; + n2 += 1; + } + result_temp1.push_back(result_temp_temp); + } + if (lut_dags_mid.size()) { + result_temp1.insert(result_temp1.end(), lut_dags_mid.begin(), + lut_dags_mid.end()); + } + if (lut_dags_rst.size()) { + result_temp1.insert(result_temp1.begin(), + lut_dags_rst.begin(), lut_dags_rst.end()); + } + lut_dags_result.push_back(result_temp1); + } + } + } + } + lut_dags.assign(lut_dags_result.begin(), lut_dags_result.end()); + } + } + } + + void LUT_classify(vector>& result, int numnodes, int numlevels) { + int q[numlevels]; + int x = numnodes; + int j; + for (int i = 0; i < numlevels; i++) { + q[i] = 0; + } + + while (1) { + j = 0; + q[0] = x; + while (1) { + vector result_temp; + bool target = 0; + for (int i = numlevels - 1; i >= 0; i--) { + result_temp.push_back(q[i]); + if (q[i] > 2) { + target = 1; + } + } + if (!target) { + result.push_back(result_temp); + } + if (j == 0) { + x = q[0] - 1; + j = 1; + } else if (q[0] == 0) { + x = q[j] - 1; + q[j] = 0; + j++; + } + if (j >= numlevels) { + return; + } else if (q[j] == numnodes) { + x = x + numlevels; + q[j] = 0; + j++; + if (j >= numlevels) { + return; + } + } + q[j]++; + if (x == 0) { + q[0] = 0; + continue; + } else { + break; + } + } + } + } + + void dag_generate_complete(vector>& result, + vector>& rst, vector permutation, + vector count, int level) { + vector> result_temp; + vector q(count[level]); + combinate(0, 0, permutation.size(), count[level], permutation, q, + result_temp); + for (int j = 0; j < result_temp.size(); j++) { + vector elected(permutation); + vector result_1; + for (int k = 0; k < result_temp[j].size(); k++) { + result_1.push_back(result_temp[j][k]); + if (level + 1 < count.size()) { + // 从vector中删除指定的某一个元素 + for (vector::iterator iter = elected.begin(); + iter != elected.end(); iter++) { + if (*iter == result_temp[j][k]) { + elected.erase(iter); + break; + } + } + } + } + sort(result_1.begin(), result_1.end()); + if (level + 1 < count.size()) { + vector> rst_temp; + dag_generate_complete(result, rst_temp, elected, count, level + 1); + for (int l = 0; l < rst_temp.size(); l++) { + vector result_2(result_1); + result_2.insert(result_2.end(), rst_temp[l].begin(), + rst_temp[l].end()); + rst.push_back(result_2); + } + } else { + rst.push_back(result_1); + } + + if (level == 0) { + result.insert(result.end(), rst.begin(), rst.end()); + rst.clear(); + } + } + } + + void dag_generate_uncomplete(vector>& result, + vector>& rst, + vector permutation_f, + vector permutation_b, vector count, + int level) { + vector> result_temp2; + for (int i = 0; i <= count[level]; i++) { + vector> result_temp; + vector q(count[level]); + combinate(0, 0, permutation_f.size(), i, permutation_f, q, result_temp); + result_temp2.insert(result_temp2.end(), result_temp.begin(), + result_temp.end()); + } + for (int j = 0; j < result_temp2.size(); j++) { + vector permutation_b_b(permutation_b); + vector result_1; + for (int k = 0; k < result_temp2[j].size(); k++) { + result_1.push_back(result_temp2[j][k]); + // 从vector中删除指定的某一个元素 + for (vector::iterator iter = permutation_b_b.begin(); + iter != permutation_b_b.end(); iter++) { + if (*iter == result_temp2[j][k]) { + permutation_b_b.erase(iter); + break; + } + } + } + sort(result_1.begin(), result_1.end()); + if (level + 1 < count.size()) { + vector> rst_temp; + dag_generate_uncomplete(result, rst_temp, permutation_f, + permutation_b_b, count, level + 1); + for (int l = 0; l < rst_temp.size(); l++) { + vector result_2(result_1); + result_2.insert(result_2.end(), rst_temp[l].begin(), + rst_temp[l].end()); + rst.push_back(result_2); + } + } else { + if (!permutation_b_b.size()) { + rst.push_back(result_1); + } + } + if (level == 0) { + result.insert(result.end(), rst.begin(), rst.end()); + rst.clear(); + } + } + } + + void combinate(int iPos, int iProc, int numnodes, int numlevels, + vector data, vector des, + vector>& result) { + if (iProc > numnodes) { + return; + } + if (iPos == numlevels) { + result.push_back(des); + return; + } else { + combinate(iPos, iProc + 1, numnodes, numlevels, data, des, result); + des[iPos] = data[iProc]; + combinate(iPos + 1, iProc + 1, numnodes, numlevels, data, des, result); + } + } + + void stp_simulate(vector>& lut_dags) { + string tt_binary = tt[0]; + int flag_node = lut_dags[0][lut_dags[0].size() - 1].node; + vector> lut_dags_new; + for (int i = lut_dags.size() - 1; i >= 0; i--) { + string input_tt(tt_binary); + + vector matrix_form = chain_to_matrix(lut_dags[i], flag_node); + matrix_computution(matrix_form); + + vector bench_result; + result_lut first_result; + first_result.computed_input = input_tt; + first_result.possible_result = lut_dags[i]; + bench_result.push_back(first_result); + for (int l = matrix_form.size() - 1; l >= 1; l--) { + int length_string = input_tt.size(); + if (matrix_form[l].input == 0) { + if (matrix_form[l].name == "W") { + if (matrix_form[l].eye == 0) { + string temp1, temp2; + temp1 = input_tt.substr(length_string / 4, length_string / 4); + temp2 = input_tt.substr(length_string / 2, length_string / 4); + input_tt.replace(length_string / 4, length_string / 4, temp2); + input_tt.replace(length_string / 2, length_string / 4, temp1); + } else { + int length2 = length_string / pow(2.0, matrix_form[l].eye + 2); + for (int l1 = pow(2.0, matrix_form[l].eye), add = 1; l1 > 0; + l1--) { + string temp1, temp2; + temp1 = input_tt.substr( + (length_string / pow(2.0, matrix_form[l].eye + 1)) * add - + length2, + length2); + temp2 = input_tt.substr( + (length_string / pow(2.0, matrix_form[l].eye + 1)) * add, + length2); + input_tt.replace( + (length_string / pow(2.0, matrix_form[l].eye + 1)) * add - + length2, + length2, temp2); + input_tt.replace( + (length_string / pow(2.0, matrix_form[l].eye + 1)) * add, + length2, temp1); + add += 2; + } + } + bench_result[0].computed_input = input_tt; + } else if (matrix_form[l].name == "R") { + if (matrix_form[l].eye == 0) { + string temp(length_string, '2'); + input_tt.insert(input_tt.begin() + (length_string / 2), + temp.begin(), temp.end()); + } else { + string temp(length_string / pow(2.0, matrix_form[l].eye), '2'); + for (int l2 = pow(2.0, matrix_form[l].eye), + add1 = pow(2.0, matrix_form[l].eye + 1) - 1; + l2 > 0; l2--) { + input_tt.insert( + input_tt.begin() + + ((length_string / pow(2.0, matrix_form[l].eye + 1)) * + add1), + temp.begin(), temp.end()); + add1 -= 2; + } + } + bench_result[0].computed_input = input_tt; + } else if (matrix_form[l].name == "M") { + vector bench_result_temp; + for (int q = bench_result.size() - 1; q >= 0; q--) { + int length_string2 = bench_result[q].computed_input.size(); + int length1 = length_string2 / + pow(2.0, matrix_form[l].eye + 2); // abcd的长度 + string standard(length1, '2'); + vector standard_int(4, 0); + vector> result; + + for (int l3 = 0; l3 < pow(2.0, matrix_form[l].eye); l3++) { + vector> result_t; + + int ind = (length_string2 / pow(2.0, matrix_form[l].eye)) * l3; + string a = bench_result[q].computed_input.substr(ind, length1); + string b = bench_result[q].computed_input.substr(ind + length1, + length1); + string c = bench_result[q].computed_input.substr( + ind + (2 * length1), length1); + string d = bench_result[q].computed_input.substr( + ind + (3 * length1), length1); + + if (a != standard) { + vector result_temp(4); // size为4的可能结果 + result_temp[0] = 0; // a=0 + if (compare_string(a, b)) // b=a + { + if (b == standard) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(a, c) && + compare_string(b, c)) // c=(b=a) + { + if (c == standard) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + if (compare_string(a, d) && compare_string(b, d) && + compare_string(c, d)) // d=(c=b=a) + { + result_temp[0] = 2; + result_temp[1] = 2; + result_temp[2] = 2; + result_temp[3] = 2; + } else // d!=(c=b=a) + { + result_temp[3] = 1; // d=1 + if (compare_string(b, d)) result_temp[1] = 2; + if (compare_string(c, d)) result_temp[2] = 2; + } + } else // c!=(b=a) + { + result_temp[2] = 1; // c=1 + if (compare_string(b, c)) result_temp[1] = 2; + if (compare_string(a, d) && + compare_string(b, d)) // d=(b=a) + { + if (d == standard || compare_string(c, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(c, d)) // d=c + { + result_temp[3] = 1; // d=1 + if (compare_string(b, d)) result_temp[1] = 2; + } else // 其他 + break; + } + } else // b!=a + { + result_temp[1] = 1; // b=1 + if (compare_string(a, c)) // c=a + { + if (c == standard || compare_string(b, c)) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + if (compare_string(a, d) && + compare_string(c, d)) // d=(c=a) + { + if (d == standard || compare_string(b, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(b, d)) // d=b + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else if (compare_string(b, c)) // c=b + { + result_temp[2] = 1; // c=1 + if (compare_string(a, d)) // d=a + { + if (d == standard || + (compare_string(b, d) && compare_string(c, d))) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(b, d) && + compare_string(c, d)) // d=(c=b) + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else // 其他 + break; + } + if (result_t.empty()) + vector_generate(result_temp, result_t); + else { + vector> result_t_temp; + vector_generate(result_temp, result_t_temp); + for (int j = result_t.size() - 1; j >= 0; j--) { + for (int k = result_t_temp.size() - 1; k >= 0; k--) { + if (compare_vector(result_t[j], result_t_temp[k])) + result_t_temp.erase(result_t_temp.begin() + k); + } + } + if (!result_t_temp.empty()) { + result_t.insert(result_t.end(), result_t_temp.begin(), + result_t_temp.end()); + } + } + } + if (b != standard) { + vector result_temp(4); // size为4的可能结果 + result_temp[1] = 0; // b=0 + if (compare_string(a, b)) // a=b + { + if (a == standard) + result_temp[0] = 2; + else + result_temp[0] = 0; // a=0 + if (compare_string(a, c) && + compare_string(b, c)) // c=(a=b) + { + if (c == standard) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + if (compare_string(a, d) && compare_string(b, d) && + compare_string(c, d)) // d=(c=a=b) + { + result_temp[0] = 2; + result_temp[1] = 2; + result_temp[2] = 2; + result_temp[3] = 2; + } else // d!=(c=a=b) + { + result_temp[3] = 1; // d=1 + if (compare_string(a, d)) result_temp[0] = 2; + if (compare_string(c, d)) result_temp[2] = 2; + } + } else // c!=(a=b) + { + result_temp[2] = 1; // c=1 + if (compare_string(a, c)) result_temp[0] = 2; + if (compare_string(a, d) && + compare_string(b, d)) // d=(a=b) + { + if (d == standard || compare_string(c, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(c, d)) // d=c + { + result_temp[3] = 1; // d=1 + if (compare_string(a, d)) result_temp[0] = 2; + } else // 其他 + break; + } + } else // a!=b + { + result_temp[0] = 1; // a=1 + if (compare_string(c, b)) // c=b + { + if (c == standard || compare_string(a, c)) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + if (compare_string(b, d) && + compare_string(c, d)) // d=(c=b) + { + if (d == standard || compare_string(a, d)) + result_temp[3] = 2; // d=0 + else + result_temp[3] = 0; // d=0 + } else if (compare_string(a, d)) // d=a + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else if (compare_string(a, c)) // c=a + { + result_temp[2] = 1; // c=1 + if (compare_string(b, d)) // d=b + { + if (d == standard || + (compare_string(a, d) && compare_string(c, d))) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(a, d) && + compare_string(c, d)) // d=(c=a) + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else // 其他 + break; + } + if (result_t.empty()) + vector_generate(result_temp, result_t); + else { + vector> result_t_temp; + vector_generate(result_temp, result_t_temp); + for (int j = result_t.size() - 1; j >= 0; j--) { + for (int k = result_t_temp.size() - 1; k >= 0; k--) { + if (compare_vector(result_t[j], result_t_temp[k])) + result_t_temp.erase(result_t_temp.begin() + k); + } + } + if (!result_t_temp.empty()) { + result_t.insert(result_t.end(), result_t_temp.begin(), + result_t_temp.end()); + } + } + } + if (c != standard) { + vector result_temp(4); // size为4的可能结果 + result_temp[2] = 0; // c=0 + if (compare_string(a, c)) // a=c + { + if (a == standard) + result_temp[0] = 2; + else + result_temp[0] = 0; // a=0 + if (compare_string(b, c) && + compare_string(b, a)) // b=(a=c) + { + if (b == standard) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(a, d) && compare_string(b, d) && + compare_string(c, d)) // d=(b=a=c) + { + result_temp[0] = 2; + result_temp[1] = 2; + result_temp[2] = 2; + result_temp[3] = 2; + } else // d!=(b=a=c) + { + result_temp[3] = 1; // d=1 + if (compare_string(a, d)) result_temp[0] = 2; + if (compare_string(b, d)) result_temp[1] = 2; + } + } else // b!=(a=c) + { + result_temp[1] = 1; // b=1 + if (compare_string(a, b)) result_temp[0] = 2; + if (compare_string(a, d) && + compare_string(c, d)) // d=(a=c) + { + if (d == standard || compare_string(b, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(b, d)) // d=b + { + result_temp[3] = 1; // d=1 + if (compare_string(a, d)) result_temp[0] = 2; + } else // 其他 + break; + } + } else // a!=c + { + result_temp[0] = 1; // a=1 + if (compare_string(b, c)) // b=c + { + if (b == standard || compare_string(b, a)) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(b, d) && + compare_string(c, d)) // d=(b=c) + { + if (d == standard || compare_string(a, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(a, d)) // d=a + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else if (compare_string(a, b)) // b=a + { + result_temp[1] = 1; // b=1 + if (compare_string(c, d)) // d=c + { + if (d == standard || + (compare_string(a, d) && compare_string(b, d))) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(a, d) && + compare_string(b, d)) // d=(b=a) + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else // 其他 + break; + } + if (result_t.empty()) + vector_generate(result_temp, result_t); + else { + vector> result_t_temp; + vector_generate(result_temp, result_t_temp); + for (int j = result_t.size() - 1; j >= 0; j--) { + for (int k = result_t_temp.size() - 1; k >= 0; k--) { + if (compare_vector(result_t[j], result_t_temp[k])) + result_t_temp.erase(result_t_temp.begin() + k); + } + } + if (!result_t_temp.empty()) { + result_t.insert(result_t.end(), result_t_temp.begin(), + result_t_temp.end()); + } + } + } + if (d != standard) { + vector result_temp(4); // size为4的可能结果 + result_temp[3] = 0; // d=0 + if (compare_string(a, d)) // a=d + { + if (a == standard) + result_temp[0] = 2; + else + result_temp[0] = 0; // a=0 + if (compare_string(b, a) && + compare_string(b, d)) // b=(a=d) + { + if (b == standard) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(a, c) && compare_string(b, c) && + compare_string(d, c)) // c=(b=a=d) + { + result_temp[0] = 2; + result_temp[1] = 2; + result_temp[2] = 2; + result_temp[3] = 2; + } else // c!=(b=a=d) + { + result_temp[2] = 1; // c=1 + if (compare_string(a, c)) result_temp[0] = 2; + if (compare_string(b, c)) result_temp[1] = 2; + } + } else // b!=(a=d) + { + result_temp[1] = 1; // b=1 + if (compare_string(a, b)) result_temp[0] = 2; + if (compare_string(c, a) && + compare_string(c, d)) // c=(a=d) + { + if (c == standard || compare_string(c, b)) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + } else if (compare_string(c, b)) // c=b + { + result_temp[2] = 1; // c=1 + if (compare_string(a, c)) result_temp[0] = 2; + } else // 其他 + break; + } + } else // a!=d + { + result_temp[0] = 1; // a=1 + if (compare_string(b, d)) // b=d + { + if (b == standard || compare_string(b, a)) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(c, d) && + compare_string(c, b)) // c=(b=d) + { + if (c == standard || compare_string(c, a)) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + } else if (compare_string(c, a)) // c=a + result_temp[2] = 1; // c=1 + else // 其他 + break; + } else if (compare_string(b, a)) // b=a + { + result_temp[1] = 1; // b=1 + if (compare_string(c, d)) // c=d + { + if (c == standard || + (compare_string(a, c) && compare_string(b, c))) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + } else if (compare_string(c, a) && + compare_string(c, b)) // c=(b=a) + result_temp[2] = 1; // c=1 + else // 其他 + break; + } else // 其他 + break; + } + if (result_t.empty()) + vector_generate(result_temp, result_t); + else { + vector> result_t_temp; + vector_generate(result_temp, result_t_temp); + for (int j = result_t.size() - 1; j >= 0; j--) { + for (int k = result_t_temp.size() - 1; k >= 0; k--) { + if (compare_vector(result_t[j], result_t_temp[k])) + result_t_temp.erase(result_t_temp.begin() + k); + } + } + if (!result_t_temp.empty()) { + result_t.insert(result_t.end(), result_t_temp.begin(), + result_t_temp.end()); + } + } + } + if (result.empty()) + result.assign(result_t.begin(), result_t.end()); + else { + for (int j = result.size() - 1; j >= 0; j--) { + if (result[j] == standard_int) { + result.assign(result_t.begin(), result_t.end()); + break; + } else { + bool target1 = 0, target2 = 0; + for (int k = result_t.size() - 1; k >= 0; k--) { + if (result_t[k] == standard_int) { + target1 = 1; + break; + } else { + if (compare_vector(result_t[k], result[j])) { + target2 = 1; + break; + } + } + } + if (target1) break; + if (!target2) result.erase(result.begin() + j); + } + } + if (result.empty()) break; + } + } + if (result.empty()) { + bench_result.erase(bench_result.begin() + q); + continue; + } else { + for (int m = 0; m < result.size(); m++) { + string count1, count2; + string res1, res2; + for (int n = 0; n < result[m].size(); n++) { + if (result[m][n] == 0) { + count1 += "1"; + count2 += "0"; + } else { + count1 += "0"; + count2 += "1"; + } + } + if (count1 == "0000" || count1 == "1111" || + count2 == "0000" || count2 == "1111") + continue; + for (int n = 0; n < pow(2.0, matrix_form[l].eye); n++) { + string s1(2 * length1, '2'); + string s2(2 * length1, '2'); + int ind = + (length_string2 / pow(2.0, matrix_form[l].eye)) * n; + string a, b, c, d; + a = bench_result[q].computed_input.substr(ind, length1); + b = bench_result[q].computed_input.substr(ind + length1, + length1); + c = bench_result[q].computed_input.substr( + ind + (length1 * 2), length1); + d = bench_result[q].computed_input.substr( + ind + (length1 * 3), length1); + + if (count1[0] == '0') { + if (s1.substr(length1, length1) == standard) + s1.replace(length1, length1, a); + } else { + if (s1.substr(0, length1) == standard) + s1.replace(0, length1, a); + } + if (count1[1] == '0') { + if (s1.substr(length1, length1) == standard) + s1.replace(length1, length1, b); + } else { + if (s1.substr(0, length1) == standard) + s1.replace(0, length1, b); + } + if (count1[2] == '0') { + if (s1.substr(length1, length1) == standard) + s1.replace(length1, length1, c); + } else { + if (s1.substr(0, length1) == standard) + s1.replace(0, length1, c); + } + if (count1[3] == '0') { + if (s1.substr(length1, length1) == standard) + s1.replace(length1, length1, d); + } else { + if (s1.substr(0, length1) == standard) + s1.replace(0, length1, d); + } + + if (count2[0] == '0') { + if (s2.substr(length1, length1) == standard) + s2.replace(length1, length1, a); + } else { + if (s2.substr(0, length1) == standard) + s2.replace(0, length1, a); + } + if (count2[1] == '0') { + if (s2.substr(length1, length1) == standard) + s2.replace(length1, length1, b); + } else { + if (s2.substr(0, length1) == standard) + s2.replace(0, length1, b); + } + if (count2[2] == '0') { + if (s2.substr(length1, length1) == standard) + s2.replace(length1, length1, c); + } else { + if (s2.substr(0, length1) == standard) + s2.replace(0, length1, c); + } + if (count2[3] == '0') { + if (s2.substr(length1, length1) == standard) + s2.replace(length1, length1, d); + } else { + if (s2.substr(0, length1) == standard) + s2.replace(0, length1, d); + } + res1 += s1; + res2 += s2; + } + result_lut result_temp_1, result_temp_2; + result_temp_1.possible_result = + bench_result[q].possible_result; + result_temp_2.possible_result = + bench_result[q].possible_result; + for (int p = 0; p < result_temp_1.possible_result.size(); + p++) { + if (result_temp_1.possible_result[p].node == + matrix_form[l].node) + result_temp_1.possible_result[p].tt = count1; + if (result_temp_2.possible_result[p].node == + matrix_form[l].node) + result_temp_2.possible_result[p].tt = count2; + } + if (res1.size() == 4) { + for (int p = 0; p < result_temp_1.possible_result.size(); + p++) { + if (result_temp_1.possible_result[p].node == + matrix_form[0].node) + result_temp_1.possible_result[p].tt = res1; + if (result_temp_2.possible_result[p].node == + matrix_form[0].node) + result_temp_2.possible_result[p].tt = res2; + } + } else { + result_temp_1.computed_input = res1; + result_temp_2.computed_input = res2; + } + + bench_result_temp.push_back(result_temp_1); + bench_result_temp.push_back(result_temp_2); + } + } + } + if (bench_result_temp.empty()) + break; + else + bench_result.assign(bench_result_temp.begin(), + bench_result_temp.end()); + } + } + } + + for (int j = bench_result.size() - 1; j >= 0; j--) { + vector> mtxvec; + vector mtx1, mtx2; + vector in; + for (int k = bench_result[j].possible_result.size() - 1; k >= 0; k--) { + vector mtxvec_temp; + in.push_back(bench_result[j].possible_result[k].tt); + mtxvec_temp.push_back(bench_result[j].possible_result[k].left); + mtxvec_temp.push_back(bench_result[j].possible_result[k].right); + mtxvec_temp.push_back(bench_result[j].possible_result[k].node); + mtxvec.push_back(mtxvec_temp); + } + in.push_back("10"); + mtx1.push_back(bench_result[j].possible_result[0].node); + mtx2.push_back(input); + mtx2.push_back(1); + mtxvec.push_back(mtx1); + mtxvec.push_back(mtx2); + vector> in_expansion = bench_expansion(in); + vector bench_temp; + for (int k = in_expansion.size() - 1; k >= 0; k--) { + string tt_temp = in_expansion[k][in_expansion[k].size() - 2]; + bench_solve(in_expansion[k], mtxvec); + if (!compare_result(in_expansion[k], tt_binary)) { + in_expansion.erase(in_expansion.begin() + k); + } else { + result_lut bench_temp_temp = bench_result[j]; + bench_temp_temp.possible_result[0].tt = tt_temp; + bench_temp.push_back(bench_temp_temp); + } + } + if (in_expansion.empty()) + bench_result.erase(bench_result.begin() + j); + else { + bench_result.erase(bench_result.begin() + j); + bench_result.insert(bench_result.end(), bench_temp.begin(), + bench_temp.end()); + } + } + + if (bench_result.size()) { + for (int j = 0; j < bench_result.size(); j++) + lut_dags_new.push_back(bench_result[j].possible_result); + break; + } + } + lut_dags.assign(lut_dags_new.begin(), lut_dags_new.end()); + } + + void stp_simulate_enu(vector>& lut_dags) { + string tt_binary = tt[0]; + int flag_node = lut_dags[0][lut_dags[0].size() - 1].node; + vector> lut_dags_new; + for (int i = lut_dags.size() - 1; i >= 0; i--) { + string input_tt(tt_binary); + + vector matrix_form = chain_to_matrix(lut_dags[i], flag_node); + matrix_computution(matrix_form); + + vector bench_result; + result_lut first_result; + first_result.computed_input = input_tt; + first_result.possible_result = lut_dags[i]; + bench_result.push_back(first_result); + for (int l = matrix_form.size() - 1; l >= 1; l--) { + int length_string = input_tt.size(); + if (matrix_form[l].input == 0) { + if (matrix_form[l].name == "W") { + if (matrix_form[l].eye == 0) { + string temp1, temp2; + temp1 = input_tt.substr(length_string / 4, length_string / 4); + temp2 = input_tt.substr(length_string / 2, length_string / 4); + input_tt.replace(length_string / 4, length_string / 4, temp2); + input_tt.replace(length_string / 2, length_string / 4, temp1); + } else { + int length2 = length_string / pow(2.0, matrix_form[l].eye + 2); + for (int l1 = pow(2.0, matrix_form[l].eye), add = 1; l1 > 0; + l1--) { + string temp1, temp2; + temp1 = input_tt.substr( + (length_string / pow(2.0, matrix_form[l].eye + 1)) * add - + length2, + length2); + temp2 = input_tt.substr( + (length_string / pow(2.0, matrix_form[l].eye + 1)) * add, + length2); + input_tt.replace( + (length_string / pow(2.0, matrix_form[l].eye + 1)) * add - + length2, + length2, temp2); + input_tt.replace( + (length_string / pow(2.0, matrix_form[l].eye + 1)) * add, + length2, temp1); + add += 2; + } + } + bench_result[0].computed_input = input_tt; + } else if (matrix_form[l].name == "R") { + if (matrix_form[l].eye == 0) { + string temp(length_string, '2'); + input_tt.insert(input_tt.begin() + (length_string / 2), + temp.begin(), temp.end()); + } else { + string temp(length_string / pow(2.0, matrix_form[l].eye), '2'); + for (int l2 = pow(2.0, matrix_form[l].eye), + add1 = pow(2.0, matrix_form[l].eye + 1) - 1; + l2 > 0; l2--) { + input_tt.insert( + input_tt.begin() + + ((length_string / pow(2.0, matrix_form[l].eye + 1)) * + add1), + temp.begin(), temp.end()); + add1 -= 2; + } + } + bench_result[0].computed_input = input_tt; + } else if (matrix_form[l].name == "M") { + vector bench_result_temp; + for (int q = bench_result.size() - 1; q >= 0; q--) { + int length_string2 = bench_result[q].computed_input.size(); + int length1 = length_string2 / + pow(2.0, matrix_form[l].eye + 2); // abcd的长度 + string standard(length1, '2'); + vector standard_int(4, 0); + vector> result; + + for (int l3 = 0; l3 < pow(2.0, matrix_form[l].eye); l3++) { + vector> result_t; + + int ind = (length_string2 / pow(2.0, matrix_form[l].eye)) * l3; + string a = bench_result[q].computed_input.substr(ind, length1); + string b = bench_result[q].computed_input.substr(ind + length1, + length1); + string c = bench_result[q].computed_input.substr( + ind + (2 * length1), length1); + string d = bench_result[q].computed_input.substr( + ind + (3 * length1), length1); + + if (a != standard) { + vector result_temp(4); // size为4的可能结果 + result_temp[0] = 0; // a=0 + if (compare_string(a, b)) // b=a + { + if (b == standard) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(a, c) && + compare_string(b, c)) // c=(b=a) + { + if (c == standard) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + if (compare_string(a, d) && compare_string(b, d) && + compare_string(c, d)) // d=(c=b=a) + { + result_temp[0] = 2; + result_temp[1] = 2; + result_temp[2] = 2; + result_temp[3] = 2; + } else // d!=(c=b=a) + { + result_temp[3] = 1; // d=1 + if (compare_string(b, d)) result_temp[1] = 2; + if (compare_string(c, d)) result_temp[2] = 2; + } + } else // c!=(b=a) + { + result_temp[2] = 1; // c=1 + if (compare_string(b, c)) result_temp[1] = 2; + if (compare_string(a, d) && + compare_string(b, d)) // d=(b=a) + { + if (d == standard || compare_string(c, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(c, d)) // d=c + { + result_temp[3] = 1; // d=1 + if (compare_string(b, d)) result_temp[1] = 2; + } else // 其他 + break; + } + } else // b!=a + { + result_temp[1] = 1; // b=1 + if (compare_string(a, c)) // c=a + { + if (c == standard || compare_string(b, c)) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + if (compare_string(a, d) && + compare_string(c, d)) // d=(c=a) + { + if (d == standard || compare_string(b, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(b, d)) // d=b + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else if (compare_string(b, c)) // c=b + { + result_temp[2] = 1; // c=1 + if (compare_string(a, d)) // d=a + { + if (d == standard || + (compare_string(b, d) && compare_string(c, d))) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(b, d) && + compare_string(c, d)) // d=(c=b) + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else // 其他 + break; + } + if (result_t.empty()) + vector_generate(result_temp, result_t); + else { + vector> result_t_temp; + vector_generate(result_temp, result_t_temp); + for (int j = result_t.size() - 1; j >= 0; j--) { + for (int k = result_t_temp.size() - 1; k >= 0; k--) { + if (compare_vector(result_t[j], result_t_temp[k])) + result_t_temp.erase(result_t_temp.begin() + k); + } + } + if (!result_t_temp.empty()) { + result_t.insert(result_t.end(), result_t_temp.begin(), + result_t_temp.end()); + } + } + } + if (b != standard) { + vector result_temp(4); // size为4的可能结果 + result_temp[1] = 0; // b=0 + if (compare_string(a, b)) // a=b + { + if (a == standard) + result_temp[0] = 2; + else + result_temp[0] = 0; // a=0 + if (compare_string(a, c) && + compare_string(b, c)) // c=(a=b) + { + if (c == standard) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + if (compare_string(a, d) && compare_string(b, d) && + compare_string(c, d)) // d=(c=a=b) + { + result_temp[0] = 2; + result_temp[1] = 2; + result_temp[2] = 2; + result_temp[3] = 2; + } else // d!=(c=a=b) + { + result_temp[3] = 1; // d=1 + if (compare_string(a, d)) result_temp[0] = 2; + if (compare_string(c, d)) result_temp[2] = 2; + } + } else // c!=(a=b) + { + result_temp[2] = 1; // c=1 + if (compare_string(a, c)) result_temp[0] = 2; + if (compare_string(a, d) && + compare_string(b, d)) // d=(a=b) + { + if (d == standard || compare_string(c, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(c, d)) // d=c + { + result_temp[3] = 1; // d=1 + if (compare_string(a, d)) result_temp[0] = 2; + } else // 其他 + break; + } + } else // a!=b + { + result_temp[0] = 1; // a=1 + if (compare_string(c, b)) // c=b + { + if (c == standard || compare_string(a, c)) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + if (compare_string(b, d) && + compare_string(c, d)) // d=(c=b) + { + if (d == standard || compare_string(a, d)) + result_temp[3] = 2; // d=0 + else + result_temp[3] = 0; // d=0 + } else if (compare_string(a, d)) // d=a + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else if (compare_string(a, c)) // c=a + { + result_temp[2] = 1; // c=1 + if (compare_string(b, d)) // d=b + { + if (d == standard || + (compare_string(a, d) && compare_string(c, d))) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(a, d) && + compare_string(c, d)) // d=(c=a) + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else // 其他 + break; + } + if (result_t.empty()) + vector_generate(result_temp, result_t); + else { + vector> result_t_temp; + vector_generate(result_temp, result_t_temp); + for (int j = result_t.size() - 1; j >= 0; j--) { + for (int k = result_t_temp.size() - 1; k >= 0; k--) { + if (compare_vector(result_t[j], result_t_temp[k])) + result_t_temp.erase(result_t_temp.begin() + k); + } + } + if (!result_t_temp.empty()) { + result_t.insert(result_t.end(), result_t_temp.begin(), + result_t_temp.end()); + } + } + } + if (c != standard) { + vector result_temp(4); // size为4的可能结果 + result_temp[2] = 0; // c=0 + if (compare_string(a, c)) // a=c + { + if (a == standard) + result_temp[0] = 2; + else + result_temp[0] = 0; // a=0 + if (compare_string(b, c) && + compare_string(b, a)) // b=(a=c) + { + if (b == standard) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(a, d) && compare_string(b, d) && + compare_string(c, d)) // d=(b=a=c) + { + result_temp[0] = 2; + result_temp[1] = 2; + result_temp[2] = 2; + result_temp[3] = 2; + } else // d!=(b=a=c) + { + result_temp[3] = 1; // d=1 + if (compare_string(a, d)) result_temp[0] = 2; + if (compare_string(b, d)) result_temp[1] = 2; + } + } else // b!=(a=c) + { + result_temp[1] = 1; // b=1 + if (compare_string(a, b)) result_temp[0] = 2; + if (compare_string(a, d) && + compare_string(c, d)) // d=(a=c) + { + if (d == standard || compare_string(b, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(b, d)) // d=b + { + result_temp[3] = 1; // d=1 + if (compare_string(a, d)) result_temp[0] = 2; + } else // 其他 + break; + } + } else // a!=c + { + result_temp[0] = 1; // a=1 + if (compare_string(b, c)) // b=c + { + if (b == standard || compare_string(b, a)) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(b, d) && + compare_string(c, d)) // d=(b=c) + { + if (d == standard || compare_string(a, d)) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(a, d)) // d=a + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else if (compare_string(a, b)) // b=a + { + result_temp[1] = 1; // b=1 + if (compare_string(c, d)) // d=c + { + if (d == standard || + (compare_string(a, d) && compare_string(b, d))) + result_temp[3] = 2; + else + result_temp[3] = 0; // d=0 + } else if (compare_string(a, d) && + compare_string(b, d)) // d=(b=a) + result_temp[3] = 1; // d=1 + else // 其他 + break; + } else // 其他 + break; + } + if (result_t.empty()) + vector_generate(result_temp, result_t); + else { + vector> result_t_temp; + vector_generate(result_temp, result_t_temp); + for (int j = result_t.size() - 1; j >= 0; j--) { + for (int k = result_t_temp.size() - 1; k >= 0; k--) { + if (compare_vector(result_t[j], result_t_temp[k])) + result_t_temp.erase(result_t_temp.begin() + k); + } + } + if (!result_t_temp.empty()) { + result_t.insert(result_t.end(), result_t_temp.begin(), + result_t_temp.end()); + } + } + } + if (d != standard) { + vector result_temp(4); // size为4的可能结果 + result_temp[3] = 0; // d=0 + if (compare_string(a, d)) // a=d + { + if (a == standard) + result_temp[0] = 2; + else + result_temp[0] = 0; // a=0 + if (compare_string(b, a) && + compare_string(b, d)) // b=(a=d) + { + if (b == standard) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(a, c) && compare_string(b, c) && + compare_string(d, c)) // c=(b=a=d) + { + result_temp[0] = 2; + result_temp[1] = 2; + result_temp[2] = 2; + result_temp[3] = 2; + } else // c!=(b=a=d) + { + result_temp[2] = 1; // c=1 + if (compare_string(a, c)) result_temp[0] = 2; + if (compare_string(b, c)) result_temp[1] = 2; + } + } else // b!=(a=d) + { + result_temp[1] = 1; // b=1 + if (compare_string(a, b)) result_temp[0] = 2; + if (compare_string(c, a) && + compare_string(c, d)) // c=(a=d) + { + if (c == standard || compare_string(c, b)) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + } else if (compare_string(c, b)) // c=b + { + result_temp[2] = 1; // c=1 + if (compare_string(a, c)) result_temp[0] = 2; + } else // 其他 + break; + } + } else // a!=d + { + result_temp[0] = 1; // a=1 + if (compare_string(b, d)) // b=d + { + if (b == standard || compare_string(b, a)) + result_temp[1] = 2; + else + result_temp[1] = 0; // b=0 + if (compare_string(c, d) && + compare_string(c, b)) // c=(b=d) + { + if (c == standard || compare_string(c, a)) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + } else if (compare_string(c, a)) // c=a + result_temp[2] = 1; // c=1 + else // 其他 + break; + } else if (compare_string(b, a)) // b=a + { + result_temp[1] = 1; // b=1 + if (compare_string(c, d)) // c=d + { + if (c == standard || + (compare_string(a, c) && compare_string(b, c))) + result_temp[2] = 2; + else + result_temp[2] = 0; // c=0 + } else if (compare_string(c, a) && + compare_string(c, b)) // c=(b=a) + result_temp[2] = 1; // c=1 + else // 其他 + break; + } else // 其他 + break; + } + if (result_t.empty()) + vector_generate(result_temp, result_t); + else { + vector> result_t_temp; + vector_generate(result_temp, result_t_temp); + for (int j = result_t.size() - 1; j >= 0; j--) { + for (int k = result_t_temp.size() - 1; k >= 0; k--) { + if (compare_vector(result_t[j], result_t_temp[k])) + result_t_temp.erase(result_t_temp.begin() + k); + } + } + if (!result_t_temp.empty()) { + result_t.insert(result_t.end(), result_t_temp.begin(), + result_t_temp.end()); + } + } + } + if (result.empty()) + result.assign(result_t.begin(), result_t.end()); + else { + for (int j = result.size() - 1; j >= 0; j--) { + if (result[j] == standard_int) { + result.assign(result_t.begin(), result_t.end()); + break; + } else { + bool target1 = 0, target2 = 0; + for (int k = result_t.size() - 1; k >= 0; k--) { + if (result_t[k] == standard_int) { + target1 = 1; + break; + } else { + if (compare_vector(result_t[k], result[j])) { + target2 = 1; + break; + } + } + } + if (target1) break; + if (!target2) result.erase(result.begin() + j); + } + } + if (result.empty()) break; + } + } + if (result.empty()) { + bench_result.erase(bench_result.begin() + q); + continue; + } else { + for (int m = 0; m < result.size(); m++) { + string count1, count2; + string res1, res2; + for (int n = 0; n < result[m].size(); n++) { + if (result[m][n] == 0) { + count1 += "1"; + count2 += "0"; + } else { + count1 += "0"; + count2 += "1"; + } + } + if (count1 == "0000" || count1 == "1111" || + count2 == "0000" || count2 == "1111") + continue; + for (int n = 0; n < pow(2.0, matrix_form[l].eye); n++) { + string s1(2 * length1, '2'); + string s2(2 * length1, '2'); + int ind = + (length_string2 / pow(2.0, matrix_form[l].eye)) * n; + string a, b, c, d; + a = bench_result[q].computed_input.substr(ind, length1); + b = bench_result[q].computed_input.substr(ind + length1, + length1); + c = bench_result[q].computed_input.substr( + ind + (length1 * 2), length1); + d = bench_result[q].computed_input.substr( + ind + (length1 * 3), length1); + + if (count1[0] == '0') { + if (s1.substr(length1, length1) == standard) + s1.replace(length1, length1, a); + } else { + if (s1.substr(0, length1) == standard) + s1.replace(0, length1, a); + } + if (count1[1] == '0') { + if (s1.substr(length1, length1) == standard) + s1.replace(length1, length1, b); + } else { + if (s1.substr(0, length1) == standard) + s1.replace(0, length1, b); + } + if (count1[2] == '0') { + if (s1.substr(length1, length1) == standard) + s1.replace(length1, length1, c); + } else { + if (s1.substr(0, length1) == standard) + s1.replace(0, length1, c); + } + if (count1[3] == '0') { + if (s1.substr(length1, length1) == standard) + s1.replace(length1, length1, d); + } else { + if (s1.substr(0, length1) == standard) + s1.replace(0, length1, d); + } + + if (count2[0] == '0') { + if (s2.substr(length1, length1) == standard) + s2.replace(length1, length1, a); + } else { + if (s2.substr(0, length1) == standard) + s2.replace(0, length1, a); + } + if (count2[1] == '0') { + if (s2.substr(length1, length1) == standard) + s2.replace(length1, length1, b); + } else { + if (s2.substr(0, length1) == standard) + s2.replace(0, length1, b); + } + if (count2[2] == '0') { + if (s2.substr(length1, length1) == standard) + s2.replace(length1, length1, c); + } else { + if (s2.substr(0, length1) == standard) + s2.replace(0, length1, c); + } + if (count2[3] == '0') { + if (s2.substr(length1, length1) == standard) + s2.replace(length1, length1, d); + } else { + if (s2.substr(0, length1) == standard) + s2.replace(0, length1, d); + } + res1 += s1; + res2 += s2; + } + result_lut result_temp_1, result_temp_2; + result_temp_1.possible_result = + bench_result[q].possible_result; + result_temp_2.possible_result = + bench_result[q].possible_result; + for (int p = 0; p < result_temp_1.possible_result.size(); + p++) { + if (result_temp_1.possible_result[p].node == + matrix_form[l].node) + result_temp_1.possible_result[p].tt = count1; + if (result_temp_2.possible_result[p].node == + matrix_form[l].node) + result_temp_2.possible_result[p].tt = count2; + } + if (res1.size() == 4) { + for (int p = 0; p < result_temp_1.possible_result.size(); + p++) { + if (result_temp_1.possible_result[p].node == + matrix_form[0].node) + result_temp_1.possible_result[p].tt = res1; + if (result_temp_2.possible_result[p].node == + matrix_form[0].node) + result_temp_2.possible_result[p].tt = res2; + } + } else { + result_temp_1.computed_input = res1; + result_temp_2.computed_input = res2; + } + + bench_result_temp.push_back(result_temp_1); + bench_result_temp.push_back(result_temp_2); + } + } + } + if (bench_result_temp.empty()) + break; + else + bench_result.assign(bench_result_temp.begin(), + bench_result_temp.end()); + } + } + } + + for (int j = bench_result.size() - 1; j >= 0; j--) { + vector> mtxvec; + vector mtx1, mtx2; + vector in; + for (int k = bench_result[j].possible_result.size() - 1; k >= 0; k--) { + vector mtxvec_temp; + in.push_back(bench_result[j].possible_result[k].tt); + mtxvec_temp.push_back(bench_result[j].possible_result[k].left); + mtxvec_temp.push_back(bench_result[j].possible_result[k].right); + mtxvec_temp.push_back(bench_result[j].possible_result[k].node); + mtxvec.push_back(mtxvec_temp); + } + in.push_back("10"); + mtx1.push_back(bench_result[j].possible_result[0].node); + mtx2.push_back(input); + mtx2.push_back(1); + mtxvec.push_back(mtx1); + mtxvec.push_back(mtx2); + vector> in_expansion = bench_expansion(in); + vector bench_temp; + for (int k = in_expansion.size() - 1; k >= 0; k--) { + string tt_temp = in_expansion[k][in_expansion[k].size() - 2]; + bench_solve(in_expansion[k], mtxvec); + if (!compare_result(in_expansion[k], tt_binary)) { + in_expansion.erase(in_expansion.begin() + k); + } else { + result_lut bench_temp_temp = bench_result[j]; + bench_temp_temp.possible_result[0].tt = tt_temp; + bench_temp.push_back(bench_temp_temp); + } + } + if (in_expansion.empty()) + bench_result.erase(bench_result.begin() + j); + else { + bench_result.erase(bench_result.begin() + j); + bench_result.insert(bench_result.end(), bench_temp.begin(), + bench_temp.end()); + } + } + + if (bench_result.size()) { + for (int j = 0; j < bench_result.size(); j++) + lut_dags_new.push_back(bench_result[j].possible_result); + } + } + lut_dags.assign(lut_dags_new.begin(), lut_dags_new.end()); + } + + vector chain_to_matrix(vector lut_dags, int flag_node) { + vector matrix_form; + matrix temp_node, temp_left, temp_right; + temp_node.node = lut_dags[0].node; + temp_node.name = "M"; + temp_left.node = lut_dags[0].left; + temp_right.node = lut_dags[0].right; + matrix_form.push_back(temp_node); + + if (lut_dags[0].right >= flag_node) { + vector matrix_form_temp2; + matrix_generate(lut_dags, matrix_form_temp2, lut_dags[0].right); + matrix_form.insert(matrix_form.end(), matrix_form_temp2.begin(), + matrix_form_temp2.end()); + } else { + temp_right.input = 1; + string str = to_string(lut_dags[0].right); + temp_right.name = str; + matrix_form.push_back(temp_right); + } + + if (lut_dags[0].left >= flag_node) { + vector matrix_form_temp1; + matrix_generate(lut_dags, matrix_form_temp1, lut_dags[0].left); + matrix_form.insert(matrix_form.end(), matrix_form_temp1.begin(), + matrix_form_temp1.end()); + } else { + temp_left.input = 1; + string str = to_string(lut_dags[0].left); + temp_left.name = str; + matrix_form.push_back(temp_left); + } + + return matrix_form; + } + + void matrix_computution(vector& matrix_form) { + bool status = true; + while (status) { + status = false; + for (int i = matrix_form.size() - 1; i > 1; i--) { + // 两个变量交换 + if (((matrix_form[i].name != "M") && (matrix_form[i].name != "R") && + (matrix_form[i].name != "W")) && + ((matrix_form[i - 1].name != "M") && + (matrix_form[i - 1].name != "R") && + (matrix_form[i - 1].name != "W"))) { + int left, right; + left = atoi(matrix_form[i - 1].name.c_str()); + right = atoi(matrix_form[i].name.c_str()); + // 相等变量降幂 + if (left == right) { + status = true; + matrix reduce_matrix; + reduce_matrix.name = "R"; + matrix_form.insert(matrix_form.begin() + (i - 1), reduce_matrix); + matrix_form.erase(matrix_form.begin() + i); + } else if (left < right) { + status = true; + matrix swap_matrix; + swap_matrix.name = "W"; + swap(matrix_form[i - 1], matrix_form[i]); + matrix_form.insert(matrix_form.begin() + (i - 1), swap_matrix); + } + } + // 变量与矩阵交换 + if (((matrix_form[i].name == "M") || (matrix_form[i].name == "R") || + (matrix_form[i].name == "W")) && + ((matrix_form[i - 1].name != "M") && + (matrix_form[i - 1].name != "R") && + (matrix_form[i - 1].name != "W"))) { + status = true; + matrix_form[i].eye += 1; + swap(matrix_form[i - 1], matrix_form[i]); + } + } + } + } + + void matrix_generate(vector lut, vector& matrix_form, + int node) { + int flag = lut[lut.size() - 1].node; + for (int i = 0; i < lut.size(); i++) { + if (lut[i].node == node) { + matrix temp_node, temp_left, temp_right; + temp_node.node = node; + temp_node.name = "M"; + matrix_form.push_back(temp_node); + if (lut[i].right >= flag) { + vector matrix_form_temp2; + matrix_generate(lut, matrix_form_temp2, lut[i].right); + matrix_form.insert(matrix_form.end(), matrix_form_temp2.begin(), + matrix_form_temp2.end()); + } else { + temp_right.input = 1; + temp_right.node = lut[i].right; + string str = to_string(lut[i].right); + temp_right.name = str; + matrix_form.push_back(temp_right); + } + if (lut[i].left >= flag) { + vector matrix_form_temp1; + matrix_generate(lut, matrix_form_temp1, lut[i].left); + matrix_form.insert(matrix_form.begin() + 1, matrix_form_temp1.begin(), + matrix_form_temp1.end()); + } else { + temp_left.input = 1; + temp_left.node = lut[i].left; + string str = to_string(lut[i].left); + temp_left.name = str; + matrix_form.push_back(temp_left); + } + } + } + } + + bool compare_string(string a, string b) { + bool target = 1; + for (int i = 0; i < a.size(); i++) { + if ((a[i] != b[i]) && a[i] != '2' && b[i] != '2') { + target = 0; + } + } + return target; + } + + bool compare_vector(vector a, vector b) { + bool target = 0; + if (a == b) { + target = 1; + } else { + for (int i = 0; i < a.size(); i++) { + if (a[i] == 1) { + a[i] = 0; + } else if (a[i] == 0) { + a[i] = 1; + } + } + if (a == b) { + target = 1; + } + } + return target; + } + + bool compare_result(vector t1, string t2) { + bool target = false; + string t3(t2.size(), '0'); + for (int i = 0; i < t1.size(); i++) { + char temp; + for (int j = 0; j < t1[i].size() / 2; j++) { + temp = t1[i][j]; + t1[i][j] = t1[i][t1[i].size() - 1 - j]; + t1[i][t1[i].size() - 1 - j] = temp; + } + int value = stoi(t1[i], 0, 2); + int ind = t3.size() - value - 1; + t3[ind] = '1'; + } + if (t2 == t3) { + target = true; + } + return target; + } + + void vector_generate(vector result_b, vector>& result_a) { + for (int i = 0; i < result_b.size(); i++) { + if (result_b[i] != 2) { + if (result_a.empty()) { + vector temp; + temp.push_back(result_b[i]); + result_a.push_back(temp); + } else { + vector> result_a_temp; + for (int j = 0; j < result_a.size(); j++) { + vector temp(result_a[j]); + temp.push_back(result_b[i]); + result_a_temp.push_back(temp); + } + result_a.assign(result_a_temp.begin(), result_a_temp.end()); + } + } else { + if (result_a.empty()) { + vector temp1(1, 1); + vector temp2(1, 0); + result_a.push_back(temp1); + result_a.push_back(temp2); + } else { + vector> result_a_temp; + for (int j = 0; j < result_a.size(); j++) { + vector temp1(result_a[j]); + vector temp2(result_a[j]); + temp1.push_back(1); + temp2.push_back(0); + result_a_temp.push_back(temp1); + result_a_temp.push_back(temp2); + } + result_a.assign(result_a_temp.begin(), result_a_temp.end()); + } + } + } + } + + void bench_solve(vector& in, vector> mtxvec) { + int length1 = mtxvec[mtxvec.size() - 1][0]; // number of primary input + int length2 = mtxvec[mtxvec.size() - 1][1]; // number of primary output + int length3 = mtxvec[0][2]; // the minimum minuend + int length4 = + mtxvec[mtxvec.size() - 2 - length2][2]; // the maximum variable + vector> + list; // the solution space is two dimension vector + vector list_temp; + cdccl_impl list_temp_temp; + + string Result_temp(length1, '2'); // temporary result + coordinate Level_temp; + Level_temp.Abscissa = -1; + Level_temp.Ordinate = -1; + Level_temp.parameter_Intermediate = -1; + Level_temp.parameter_Gate = -1; + list_temp_temp.Level.resize( + length4, Level_temp); // Initialize level as a space with the size of + // variables(length4) + /* + * initialization + */ + coordinate Gate_level; + Gate_level.Abscissa = 0; + Gate_level.Ordinate = 0; + Gate_level.parameter_Intermediate = -1; + Gate_level.parameter_Gate = -1; + string Intermediate_temp; + for (int i = mtxvec.size() - 1 - length2; i < mtxvec.size() - 1; + i++) // the original intermediate + { + if (mtxvec[i][0] < length3) { + if (in[i][0] == '1') + Result_temp[mtxvec[i][0] - 1] = '1'; + else + Result_temp[mtxvec[i][0] - 1] = '0'; + } else { + list_temp_temp.Gate.push_back(mtxvec[i][0]); + if (in[i][0] == '1') + Intermediate_temp += "1"; + else + Intermediate_temp += "0"; + } + list_temp_temp.Level[mtxvec[i][0] - 1] = Gate_level; + } + list_temp_temp.Result = Result_temp; + list_temp_temp.Intermediate.push_back(Intermediate_temp); + list_temp.push_back(list_temp_temp); // level 0 + list.push_back(list_temp); + /* + * The first level information + */ + int count1 = 0; + for (int level = 0;; level++) // the computation process + { + int flag = 0, ordinate = 0; // the flag of the end of the loop & the + // ordinate of each level's gate + vector list_temp1; + for (int k = 0; k < list[level].size(); k++) { + cdccl_impl temp1; // temporary gate + temp1.Result = list[level][k].Result; // first, next level's Result is + // same as the front level + for (int j = 0; j < list[level][k].Intermediate.size(); j++) { + temp1.Level = list[level][k].Level; // next level's Level information + for (int j1 = 0; j1 < list[level][k].Gate.size(); j1++) { + temp1.Level[list[level][k].Gate[j1] - 1].parameter_Intermediate = j; + temp1.Level[list[level][k].Gate[j1] - 1].parameter_Gate = j1; + } + + coordinate level_current; // new level + level_current.Abscissa = level + 1; + level_current.parameter_Intermediate = -1; + level_current.parameter_Gate = -1; + level_current.Ordinate = ordinate; + + temp1.Gate.assign(list[level][k].Gate.begin(), + list[level][k].Gate.end()); // need more!!!!! + temp1.Intermediate.push_back(list[level][k].Intermediate[j]); + + vector Intermediate_temp; + vector Gate_temp; + vector Gate_judge(length4, -1); + int count_cdccl = 0; + for (int i = 0; i < temp1.Gate.size(); i++) { + int length = temp1.Gate[i] - length3; + int Gate_f = mtxvec[length][0]; // the front Gate variable + int Gate_b = mtxvec[length][1]; // the behind Gate variable + string tt = in[length]; // the correndsponding Truth Table + char target = temp1.Intermediate[0][i]; // the SAT target + vector Intermediate_temp_temp; + + int flag_cdccl = 0; + string Intermediate_temp_temp_F, Intermediate_temp_temp_B; + if (temp1.Level[Gate_f - 1].Abscissa >= 0) { + if (Gate_f < length3) { + char contrast_R1 = list[temp1.Level[Gate_f - 1].Abscissa] + [temp1.Level[Gate_f - 1].Ordinate] + .Result[Gate_f - 1]; + Intermediate_temp_temp_F.push_back(contrast_R1); + } else { + char contrast_I1 = + list[temp1.Level[Gate_f - 1].Abscissa] + [temp1.Level[Gate_f - 1].Ordinate] + .Intermediate + [temp1.Level[Gate_f - 1].parameter_Intermediate] + [temp1.Level[Gate_f - 1].parameter_Gate]; + Intermediate_temp_temp_F.push_back(contrast_I1); + } + flag_cdccl += 1; + } + if (temp1.Level[Gate_b - 1].Abscissa >= 0) { + if (Gate_b < length3) { + char contrast_R2 = list[temp1.Level[Gate_b - 1].Abscissa] + [temp1.Level[Gate_b - 1].Ordinate] + .Result[Gate_b - 1]; + Intermediate_temp_temp_B.push_back(contrast_R2); + } else { + char contrast_I2 = + list[temp1.Level[Gate_b - 1].Abscissa] + [temp1.Level[Gate_b - 1].Ordinate] + .Intermediate + [temp1.Level[Gate_b - 1].parameter_Intermediate] + [temp1.Level[Gate_b - 1].parameter_Gate]; + Intermediate_temp_temp_B.push_back(contrast_I2); + } + flag_cdccl += 2; + } + if (Intermediate_temp.size() == 0) { + if (flag_cdccl == 0) { + Gate_judge[Gate_f - 1] = count_cdccl; + count_cdccl += 1; + Gate_judge[Gate_b - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_f); + Gate_temp.push_back(Gate_b); + if (tt[0] == target) Intermediate_temp_temp.push_back("11"); + if (tt[1] == target) Intermediate_temp_temp.push_back("01"); + if (tt[2] == target) Intermediate_temp_temp.push_back("10"); + if (tt[3] == target) Intermediate_temp_temp.push_back("00"); + } else if (flag_cdccl == 1) { + Gate_judge[Gate_b - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_b); + if (tt[0] == target) { + if (Intermediate_temp_temp_F == "1") + Intermediate_temp_temp.push_back("1"); + } + if (tt[1] == target) { + if (Intermediate_temp_temp_F == "0") + Intermediate_temp_temp.push_back("1"); + } + if (tt[2] == target) { + if (Intermediate_temp_temp_F == "1") + Intermediate_temp_temp.push_back("0"); + } + if (tt[3] == target) { + if (Intermediate_temp_temp_F == "0") + Intermediate_temp_temp.push_back("0"); + } + } else if (flag_cdccl == 2) { + Gate_judge[Gate_f - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_f); + if (tt[0] == target) { + if (Intermediate_temp_temp_B == "1") + Intermediate_temp_temp.push_back("1"); + } + if (tt[1] == target) { + if (Intermediate_temp_temp_B == "1") + Intermediate_temp_temp.push_back("0"); + } + if (tt[2] == target) { + if (Intermediate_temp_temp_B == "0") + Intermediate_temp_temp.push_back("1"); + } + if (tt[3] == target) { + if (Intermediate_temp_temp_B == "0") + Intermediate_temp_temp.push_back("0"); + } + } else { + int t0 = 0, t1 = 0, t2 = 0, t3 = 0; + if (tt[0] == target) { + if ((Intermediate_temp_temp_F == "1") && + (Intermediate_temp_temp_B == "1")) + t0 = 1; + } + if (tt[1] == target) { + if ((Intermediate_temp_temp_F == "0") && + (Intermediate_temp_temp_B == "1")) + t1 = 1; + } + if (tt[2] == target) { + if ((Intermediate_temp_temp_F == "1") && + (Intermediate_temp_temp_B == "0")) + t2 = 1; + } + if (tt[3] == target) { + if ((Intermediate_temp_temp_F == "0") && + (Intermediate_temp_temp_B == "0")) + t3 = 1; + } + if ((t0 == 1) || (t1 == 1) || (t2 == 1) || (t3 == 1)) { + Gate_judge[Gate_f - 1] = count_cdccl; + count_cdccl += 1; + Gate_judge[Gate_b - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_f); + Gate_temp.push_back(Gate_b); + if (t0 == 1) Intermediate_temp_temp.push_back("11"); + if (t1 == 1) Intermediate_temp_temp.push_back("01"); + if (t2 == 1) Intermediate_temp_temp.push_back("10"); + if (t3 == 1) Intermediate_temp_temp.push_back("00"); + } + } + } else { + if (flag_cdccl == 0) { + int count_Gate_f = 0, count_Gate_b = 0; + for (int j = 0; j < Intermediate_temp.size(); j++) { + int flag; + string t1, t2, t3, t4; + if (Gate_judge[Gate_f - 1] < 0) { + count_Gate_f = 1; + if (tt[0] == target) t1 = "1"; + if (tt[1] == target) t2 = "0"; + if (tt[2] == target) t3 = "1"; + if (tt[3] == target) t4 = "0"; + flag = 1; + } else { + int count_sat = 0; + if (tt[0] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_f - 1]] == '1') { + t1 = "11"; + count_sat += 1; + } + } + if (tt[1] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_f - 1]] == '0') { + t2 = "01"; + count_sat += 1; + } + } + if (tt[2] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_f - 1]] == '1') { + t3 = "10"; + count_sat += 1; + } + } + if (tt[3] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_f - 1]] == '0') { + t4 = "00"; + count_sat += 1; + } + } + if (count_sat == 0) continue; + flag = 2; + } + if (Gate_judge[Gate_b - 1] < 0) { + count_Gate_b = 1; + if (flag == 1) { + if (t1 == "1") { + t1 += "1"; + string result_temporary(Intermediate_temp[j]); + result_temporary += t1; + Intermediate_temp_temp.push_back(result_temporary); + } + if (t2 == "0") { + t2 += "1"; + string result_temporary(Intermediate_temp[j]); + result_temporary += t2; + Intermediate_temp_temp.push_back(result_temporary); + } + if (t3 == "1") { + t3 += "0"; + string result_temporary(Intermediate_temp[j]); + result_temporary += t3; + Intermediate_temp_temp.push_back(result_temporary); + } + if (t4 == "0") { + t4 += "0"; + string result_temporary(Intermediate_temp[j]); + result_temporary += t4; + Intermediate_temp_temp.push_back(result_temporary); + } + } + if (flag == 2) { + if (t1 == "11") { + t1 = "1"; + string result_temporary(Intermediate_temp[j]); + result_temporary += t1; + Intermediate_temp_temp.push_back(result_temporary); + } + if (t2 == "01") { + t2 = "1"; + string result_temporary(Intermediate_temp[j]); + result_temporary += t2; + Intermediate_temp_temp.push_back(result_temporary); + } + if (t3 == "10") { + t3 = "0"; + string result_temporary(Intermediate_temp[j]); + result_temporary += t3; + Intermediate_temp_temp.push_back(result_temporary); + } + if (t4 == "00") { + t4 = "0"; + string result_temporary(Intermediate_temp[j]); + result_temporary += t4; + Intermediate_temp_temp.push_back(result_temporary); + } + } + } else { + if (flag == 1) { + if (tt[0] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '1') { + string result_temporary(Intermediate_temp[j]); + result_temporary += t1; + Intermediate_temp_temp.push_back(result_temporary); + } + } + if (tt[1] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '1') { + string result_temporary(Intermediate_temp[j]); + result_temporary += t2; + Intermediate_temp_temp.push_back(result_temporary); + } + } + if (tt[2] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '0') { + string result_temporary(Intermediate_temp[j]); + result_temporary += t3; + Intermediate_temp_temp.push_back(result_temporary); + } + } + if (tt[3] == target) { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '0') { + string result_temporary(Intermediate_temp[j]); + result_temporary += t4; + Intermediate_temp_temp.push_back(result_temporary); + } + } + } + if (flag == 2) { + int count_sat1 = 0; + if (t1 == "11") { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == '1') + count_sat1 += 1; + } + if (t2 == "01") { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == '1') + count_sat1 += 1; + } + if (t3 == "10") { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == '0') + count_sat1 += 1; + } + if (t4 == "00") { + if (Intermediate_temp[j][Gate_judge[Gate_b - 1]] == '0') + count_sat1 += 1; + } + if (count_sat1 > 0) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + } + } + if (count_Gate_f == 1) { + Gate_judge[Gate_f - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_f); + } + if (count_Gate_b == 1) { + Gate_judge[Gate_b - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_b); + } + } else if (flag_cdccl == 1) { + int flag_1 = 0; + for (int j = 0; j < Intermediate_temp.size(); j++) { + if (Gate_judge[Gate_b - 1] < 0) { + flag_1 = 1; + if (tt[0] == target) { + if (Intermediate_temp_temp_F == "1") { + string Intermediate_temp_temp1(Intermediate_temp[j]); + Intermediate_temp_temp1 += "1"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + if (tt[1] == target) { + if (Intermediate_temp_temp_F == "0") { + string Intermediate_temp_temp1(Intermediate_temp[j]); + Intermediate_temp_temp1 += "1"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + if (tt[2] == target) { + if (Intermediate_temp_temp_F == "1") { + string Intermediate_temp_temp1(Intermediate_temp[j]); + Intermediate_temp_temp1 += "0"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + if (tt[3] == target) { + if (Intermediate_temp_temp_F == "0") { + string Intermediate_temp_temp1(Intermediate_temp[j]); + Intermediate_temp_temp1 += "0"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + } else { + if (tt[0] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '1') && + (Intermediate_temp_temp_F == "1")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[1] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '1') && + (Intermediate_temp_temp_F == "0")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[2] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '0') && + (Intermediate_temp_temp_F == "1")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[3] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_b - 1]] == + '0') && + (Intermediate_temp_temp_F == "0")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + } + } + if (flag_1 == 1) { + Gate_judge[Gate_b - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_b); + } + } else if (flag_cdccl == 2) { + int flag_2 = 0; + for (int j = 0; j < Intermediate_temp.size(); j++) { + if (Gate_judge[Gate_f - 1] < 0) { + flag_2 = 1; + if (tt[0] == target) { + if (Intermediate_temp_temp_B == "1") { + string Intermediate_temp_temp1(Intermediate_temp[j]); + Intermediate_temp_temp1 += "1"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + if (tt[1] == target) { + if (Intermediate_temp_temp_B == "1") { + string Intermediate_temp_temp1(Intermediate_temp[j]); + Intermediate_temp_temp1 += "0"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + if (tt[2] == target) { + if (Intermediate_temp_temp_B == "0") { + string Intermediate_temp_temp1(Intermediate_temp[j]); + Intermediate_temp_temp1 += "1"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + if (tt[3] == target) { + if (Intermediate_temp_temp_B == "0") { + string Intermediate_temp_temp1(Intermediate_temp[j]); + Intermediate_temp_temp1 += "0"; + Intermediate_temp_temp.push_back( + Intermediate_temp_temp1); + } + } + } else { + if (tt[0] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_f - 1]] == + '1') && + (Intermediate_temp_temp_B == "1")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[1] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_f - 1]] == + '0') && + (Intermediate_temp_temp_B == "1")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[2] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_f - 1]] == + '1') && + (Intermediate_temp_temp_B == "0")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[3] == target) { + if ((Intermediate_temp[j][Gate_judge[Gate_f - 1]] == + '0') && + (Intermediate_temp_temp_B == "0")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + } + } + if (flag_2 == 1) { + Gate_judge[Gate_f - 1] = count_cdccl; + count_cdccl += 1; + Gate_temp.push_back(Gate_f); + } + } else { + for (int j = 0; j < Intermediate_temp.size(); j++) { + if (tt[0] == target) { + if ((Intermediate_temp_temp_F == "1") && + (Intermediate_temp_temp_B == "1")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[1] == target) { + if ((Intermediate_temp_temp_F == "0") && + (Intermediate_temp_temp_B == "1")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[2] == target) { + if ((Intermediate_temp_temp_F == "1") && + (Intermediate_temp_temp_B == "0")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + if (tt[3] == target) { + if ((Intermediate_temp_temp_F == "0") && + (Intermediate_temp_temp_B == "0")) + Intermediate_temp_temp.push_back(Intermediate_temp[j]); + } + } + } + } + Intermediate_temp.assign(Intermediate_temp_temp.begin(), + Intermediate_temp_temp.end()); + if (Intermediate_temp_temp.size() == 0) break; + } + temp1.Intermediate.assign(Intermediate_temp.begin(), + Intermediate_temp.end()); + temp1.Gate.assign(Gate_temp.begin(), Gate_temp.end()); + for (int l = 0; l < temp1.Gate.size(); l++) + temp1.Level[temp1.Gate[l] - 1] = level_current; + + int count = 0; // whether there is a PI assignment + for (int k = 0; k < temp1.Intermediate.size(); + k++) // mix the Result and the Intermediate information in one + // level + { + count = 1; + cdccl_impl temp2; + temp2.Level = temp1.Level; + string Result_temp(temp1.Result); + temp2.Gate.assign(temp1.Gate.begin(), temp1.Gate.end()); + string Intermediate_temp1(temp1.Intermediate[k]); + int count1 = 0, count2 = 0; // whether the assignment made + for (int k11 = 0; k11 < temp1.Gate.size(); k11++) { + if (temp1.Gate[k11] < + length3) // if the Gate is smaller than length3, it is PI + { + temp2.Level[temp1.Gate[k11] - 1].Ordinate = ordinate; + if ((temp1.Result[temp1.Gate[k11] - 1] == '2') || + (temp1.Result[temp1.Gate[k11] - 1] == + temp1.Intermediate[k][k11])) // whether the PI can be + // assigned a value + Result_temp[temp1.Gate[k11] - 1] = temp1.Intermediate[k][k11]; + else + count1 = 1; // if one assignment can't make, the count1 = 1 + Intermediate_temp1.erase(Intermediate_temp1.begin() + + (k11 - count2)); + temp2.Gate.erase(temp2.Gate.begin() + (k11 - count2)); + count++, count2++; + } + } + if (count1 == 0) { + temp2.Result = Result_temp; + temp2.Intermediate.push_back(Intermediate_temp1); + for (int k12 = 0; k12 < temp2.Gate.size(); k12++) + temp2.Level[temp2.Gate[k12] - 1].Ordinate = ordinate; + } + if (count == 1) + break; + else if (temp2.Result.size() > 0) { + list_temp1.push_back(temp2); + ordinate += 1; + if (temp2.Gate.empty()) flag += 1; + } + } + if (count == 1) { + list_temp1.push_back(temp1); + ordinate += 1; + if (temp1.Gate.empty()) flag += 1; + } + temp1.Intermediate.clear(); + } + } + list.push_back(list_temp1); // next level's information + if (flag == list[level + 1].size()) // in one level, if all node's Gate + // is empty, then break the loop + break; + } + + in.clear(); + for (int j = 0; j < list[list.size() - 1].size(); j++) // all result + in.push_back(list[list.size() - 1][j].Result); + } + + vector> bench_expansion(vector in) { + vector> in_expansion; + in_expansion.push_back(in); + string in_end = in[in.size() - 2]; + for (int i = 0; i < in_end.size(); i++) { + if (in_end[i] == '2') { + vector> in_expansion_temp; + for (int j = 0; j < in_expansion.size(); j++) { + vector in_temp_1(in_expansion[j]); + vector in_temp_0(in_expansion[j]); + in_temp_1[in_expansion[j].size() - 2][i] = '1'; + in_temp_0[in_expansion[j].size() - 2][i] = '0'; + in_expansion_temp.push_back(in_temp_1); + in_expansion_temp.push_back(in_temp_0); + } + in_expansion.assign(in_expansion_temp.begin(), in_expansion_temp.end()); + } + } + return in_expansion; + } + + private: + vector& tt; + int& input; +}; + +void exact_lut(vector& tt, int& input) { + exact_lut_impl p(tt, input); + p.run(); +} + +void exact_lut_enu(vector& tt, int& input) { + exact_lut_impl p(tt, input); + p.run_enu(); +} +} // namespace phyLS diff --git a/src/core/exact/exact_lut.hpp b/src/core/exact/exact_lut.hpp new file mode 100644 index 0000000..1c8bf8a --- /dev/null +++ b/src/core/exact/exact_lut.hpp @@ -0,0 +1,23 @@ +#ifndef EXACT_LUT_HPP +#define EXACT_LUT_HPP + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace phyLS { +void exact_lut(vector& tt, int& input); +void exact_lut_enu(vector& tt, int& input); +} // namespace phyLS + +#endif diff --git a/src/core/exact/lut_rewriting.hpp b/src/core/exact/lut_rewriting.hpp new file mode 100644 index 0000000..3efb915 --- /dev/null +++ b/src/core/exact/lut_rewriting.hpp @@ -0,0 +1,408 @@ +#ifndef LUT_REWRITING_HPP +#define LUT_REWRITING_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include "exact_dag.hpp" + +using namespace percy; +using namespace mockturtle; + +namespace phyLS { + +struct lut_rewriting_params { + /*! \brief Enable exact synthesis for XAG. */ + bool xag{false}; +}; + +class lut_rewriting_manager { + public: + lut_rewriting_manager(klut_network klut, lut_rewriting_params const& ps) + : klut(klut), ps(ps) {} + + klut_network run_c() { + klut.foreach_node([&](auto const& n) { + if (klut.is_constant(n) || klut.is_pi(n)) return true; /* continue */ + std::string func = kitty::to_hex(klut.node_function(n)); + std::vector lut_inputs; + + klut.foreach_fanin( + n, [&](auto const& c) { lut_inputs.push_back(klut.get_node(c)); }); + if (lut_inputs.size() <= 2) return true; /* continue */ + + // exact synthesis for each node + int input_num = lut_inputs.size(); + percy::chain chain; + es(input_num, func, chain); + std::vector node; + std::vector right; + std::vector left; + std::vector tt; + chain.bench_infor(node, left, right, tt); + if (tt.size() != node.size()) { + tt.pop_back(); + hex_invert(tt[tt.size() - 1]); + } + + // rewrite origin node by the optimal Boolean chains of exact synthesis + std::vector new_lut; + for (int i = 0; i < node.size(); i++) { + kitty::dynamic_truth_table node_tt(2u); + kitty::create_from_hex_string(node_tt, tt[i]); + if (left[i] <= input_num && right[i] <= input_num) { + const auto node_new = klut.create_node( + {lut_inputs[left[i] - 1], lut_inputs[right[i] - 1]}, node_tt); + new_lut.push_back(node_new); + } else if (left[i] <= input_num && right[i] > input_num) { + const auto node_new = klut.create_node( + {lut_inputs[left[i] - 1], new_lut[right[i] - 1 - input_num]}, + node_tt); + new_lut.push_back(node_new); + } else if (left[i] > input_num && right[i] > input_num) { + const auto node_new = + klut.create_node({new_lut[left[i] - 1 - input_num], + new_lut[right[i] - 1 - input_num]}, + node_tt); + new_lut.push_back(node_new); + } + } + klut.substitute_node(n, new_lut[new_lut.size() - 1]); + return true; + }); + + // clean all redundant luts + auto klut_opt = mockturtle::cleanup_luts(klut); + return klut_opt; + } + + klut_network run_s() { + klut.foreach_node([&](auto const& n) { + if (klut.is_constant(n) || klut.is_pi(n)) return true; /* continue */ + std::string func = kitty::to_hex(klut.node_function(n)); + std::vector lut_inputs; + + klut.foreach_fanin( + n, [&](auto const& c) { lut_inputs.push_back(klut.get_node(c)); }); + if (lut_inputs.size() <= 2) return true; /* continue */ + + // exact synthesis for each node + int input_num = lut_inputs.size(); + phyLS::exact_lut_params ps; + dag_impl mgr(func, input_num, ps); + mgr.run_rewrite(); + + // compute the techmap costs of all realizations + float cost = 0; + int min_cost_realization = 0; + for (int i = 0; i < mgr.exact_synthesis_results.size(); i++) { + float cost_temp = 0; + for (auto y : mgr.exact_synthesis_results[i]) + cost_temp += bench_cost_area(y.tt); + if (cost_temp < cost || cost == 0) { + cost = cost_temp; + min_cost_realization = i; + } + } + std::vector nodes; + std::vector rights; + std::vector lefts; + std::vector tts; + for (auto x : mgr.exact_synthesis_results[min_cost_realization]) { + nodes.push_back(x.node); + lefts.push_back(x.left); + rights.push_back(x.right); + tts.push_back(x.tt); + } + + // rewrite origin node by the optimal Boolean chains of exact synthesis + std::vector new_lut; + for (int i = nodes.size() - 1; i >= 0; i--) { + kitty::dynamic_truth_table node_tt(2u); + kitty::create_from_binary_string(node_tt, tts[i]); + if (lefts[i] <= input_num && rights[i] <= input_num) { + const auto node_new = klut.create_node( + {lut_inputs[lefts[i] - 1], lut_inputs[rights[i] - 1]}, node_tt); + new_lut.push_back(node_new); + } else if (lefts[i] <= input_num && rights[i] > input_num) { + const auto node_new = klut.create_node( + {lut_inputs[lefts[i] - 1], new_lut[rights[i] - 1 - input_num]}, + node_tt); + new_lut.push_back(node_new); + } else if (lefts[i] > input_num && rights[i] > input_num) { + const auto node_new = + klut.create_node({new_lut[lefts[i] - 1 - input_num], + new_lut[rights[i] - 1 - input_num]}, + node_tt); + new_lut.push_back(node_new); + } + } + klut.substitute_node(n, new_lut[new_lut.size() - 1]); + return true; + }); + + // clean all redundant luts + auto klut_opt = mockturtle::cleanup_luts(klut); + return klut_opt; + } + + klut_network run_s_enu() { + klut.foreach_node([&](auto const& n) { + if (klut.is_constant(n) || klut.is_pi(n)) return true; /* continue */ + std::string func = kitty::to_hex(klut.node_function(n)); + std::vector lut_inputs; + + klut.foreach_fanin( + n, [&](auto const& c) { lut_inputs.push_back(klut.get_node(c)); }); + if (lut_inputs.size() <= 2) return true; /* continue */ + + // exact synthesis for each node + int input_num = lut_inputs.size(); + phyLS::exact_lut_params ps; + dag_impl mgr(func, input_num, ps); + mgr.run_rewrite_enu(); + + // compute the techmap costs of all realizations + float cost = 0; + int min_cost_realization = 0; + for (int i = 0; i < mgr.exact_synthesis_results.size(); i++) { + float cost_temp = 0; + for (auto y : mgr.exact_synthesis_results[i]) + cost_temp += bench_cost_area(y.tt); + if (cost_temp < cost || cost == 0) { + cost = cost_temp; + min_cost_realization = i; + } + } + std::vector nodes; + std::vector rights; + std::vector lefts; + std::vector tts; + for (auto x : mgr.exact_synthesis_results[min_cost_realization]) { + nodes.push_back(x.node); + lefts.push_back(x.left); + rights.push_back(x.right); + tts.push_back(x.tt); + } + + // rewrite origin node by the optimal Boolean chains of exact synthesis + std::vector new_lut; + for (int i = nodes.size() - 1; i >= 0; i--) { + kitty::dynamic_truth_table node_tt(2u); + kitty::create_from_binary_string(node_tt, tts[i]); + if (lefts[i] <= input_num && rights[i] <= input_num) { + const auto node_new = klut.create_node( + {lut_inputs[lefts[i] - 1], lut_inputs[rights[i] - 1]}, node_tt); + new_lut.push_back(node_new); + } else if (lefts[i] <= input_num && rights[i] > input_num) { + const auto node_new = klut.create_node( + {lut_inputs[lefts[i] - 1], new_lut[rights[i] - 1 - input_num]}, + node_tt); + new_lut.push_back(node_new); + } else if (lefts[i] > input_num && rights[i] > input_num) { + const auto node_new = + klut.create_node({new_lut[lefts[i] - 1 - input_num], + new_lut[rights[i] - 1 - input_num]}, + node_tt); + new_lut.push_back(node_new); + } + } + klut.substitute_node(n, new_lut[new_lut.size() - 1]); + return true; + }); + + // clean all redundant luts + auto klut_opt = mockturtle::cleanup_luts(klut); + return klut_opt; + } + + private: + void hex_invert(std::string& tt_temp) { + if (tt_temp == "1") + tt_temp = "e"; + else if (tt_temp == "2") + tt_temp = "d"; + else if (tt_temp == "3") + tt_temp = "c"; + else if (tt_temp == "4") + tt_temp = "b"; + else if (tt_temp == "5") + tt_temp = "a"; + else if (tt_temp == "6") + tt_temp = "9"; + else if (tt_temp == "7") + tt_temp = "8"; + else if (tt_temp == "8") + tt_temp = "7"; + else if (tt_temp == "9") + tt_temp = "6"; + else if (tt_temp == "a") + tt_temp = "5"; + else if (tt_temp == "b") + tt_temp = "4"; + else if (tt_temp == "c") + tt_temp = "3"; + else if (tt_temp == "d") + tt_temp = "2"; + else if (tt_temp == "e") + tt_temp = "1"; + else + tt_temp = "0"; + } + + // TODO + float techmap_cost(std::vector> tt) { + float cost = 0; + for (auto x : tt) { + float cost_temp = 0; + for (auto y : x) { + cost_temp += bench_cost_area(y); + } + if (cost_temp < cost || cost == 0) cost = cost_temp; + } + return cost; + } + + // TODO + float bench_cost_area(std::string tt) { + float area_cost = 0; + if (tt == "0001") + area_cost = 2; + else if (tt == "0010") + area_cost = 3; + else if (tt == "0011") + area_cost = 1; + else if (tt == "0100") + area_cost = 3; + else if (tt == "0101") + area_cost = 1; + else if (tt == "0110") + area_cost = 5; + else if (tt == "0111") + area_cost = 2; + else if (tt == "1000") + area_cost = 3; + else if (tt == "1001") + area_cost = 5; + else if (tt == "1010") + area_cost = 1; + else if (tt == "1011") + area_cost = 3; + else if (tt == "1100") + area_cost = 1; + else if (tt == "1101") + area_cost = 3; + else if (tt == "1110") + area_cost = 4; + else + area_cost = 0; + return area_cost; + } + + // TODO + float bench_cost_depth(std::string tt) { + float depth_cost = 0; + if (tt == "0001") + depth_cost = 1.4; + else if (tt == "0010") + depth_cost = 2.3; + else if (tt == "0011") + depth_cost = 0.9; + else if (tt == "0100") + depth_cost = 2.3; + else if (tt == "0101") + depth_cost = 0.9; + else if (tt == "0110") + depth_cost = 1.9; + else if (tt == "0111") + depth_cost = 1; + else if (tt == "1000") + depth_cost = 1.9; + else if (tt == "1001") + depth_cost = 2.1; + else if (tt == "1010") + depth_cost = 1; + else if (tt == "1011") + depth_cost = 1.9; + else if (tt == "1100") + depth_cost = 1; + else if (tt == "1101") + depth_cost = 1.9; + else if (tt == "1110") + depth_cost = 1.9; + else + depth_cost = 0; + return depth_cost; + } + + void es(int nr_in, std::string tt, percy::chain& result) { + int node = nr_in - 1; + bool target = false; + while (true) { + spec spec; + bsat_wrapper solver; + percy::partial_dag_encoder encoder2(solver); + encoder2.reset_sim_tts(nr_in); + + spec.add_alonce_clauses = false; + spec.add_nontriv_clauses = false; + spec.add_lex_func_clauses = false; + spec.add_colex_clauses = false; + spec.add_noreapply_clauses = false; + spec.add_symvar_clauses = false; + spec.verbosity = 0; + + kitty::dynamic_truth_table f(nr_in); + kitty::create_from_hex_string(f, tt); + spec[0] = f; + + auto dags = percy::pd_generate_filtered(node, nr_in); + spec.preprocess(); + for (auto& dag : dags) { + percy::chain c; + synth_result status; + status = percy::pd_cegar_synthesize(spec, c, dag, solver, encoder2); + if (status == success) { + result.copy(c); + target = true; + break; + } + } + if (target) { + break; + } + node++; + } + } + + private: + klut_network klut; + lut_rewriting_params const& ps; +}; + +klut_network lut_rewriting_c(klut_network& klut, + lut_rewriting_params const& ps = {}) { + lut_rewriting_manager mgr(klut, ps); + return mgr.run_c(); +} + +klut_network lut_rewriting_s(klut_network& klut, + lut_rewriting_params const& ps = {}) { + lut_rewriting_manager mgr(klut, ps); + return mgr.run_s(); +} + +klut_network lut_rewriting_s_enu(klut_network& klut, + lut_rewriting_params const& ps = {}) { + lut_rewriting_manager mgr(klut, ps); + return mgr.run_s_enu(); +} + +} // namespace phyLS + +#endif diff --git a/src/networks/aoig/aoig.hpp b/src/networks/aoig/aoig.hpp new file mode 100644 index 0000000..4fe8323 --- /dev/null +++ b/src/networks/aoig/aoig.hpp @@ -0,0 +1,644 @@ +#pragma once + /*! + \file aoig.hpp + \brief aoig logic network implementation + */ +#include +#include + +namespace mockturtle +{ + struct aoig_storage_data + { + truth_table_cache cache; + uint32_t num_pis = 0u; + uint32_t num_pos = 0u; + std::vector latches; + uint32_t trav_id = 0u; + }; + + /*! \brief k-LUT node + * + * `data[0].h1`: Fan-out size + * `data[0].h2`: Application-specific value + * `data[1].h1`: Function literal in truth table cache + * `data[2].h2`: Visited flags + */ + struct aoig_storage_node : mixed_fanin_node<2> + { + bool operator==(aoig_storage_node const& other) const + { + return data[1].h1 == other.data[1].h1 && children == other.children; + } + }; + + /*! \brief k-LUT storage container */ + using aoig_storage = storage; + + class aoig_network + { + public: +#pragma region Types and constructors + static constexpr auto min_fanin_size = 1; + static constexpr auto max_fanin_size = 3; + + using base_type = aoig_network; + using storage = std::shared_ptr; + using node = uint64_t; + using signal = uint64_t; + + aoig_network() + : _storage(std::make_shared()), + _events(std::make_shared()) + { + _init(); + } + + aoig_network(std::shared_ptr storage) + : _storage(storage), + _events(std::make_shared()) + { + _init(); + } + + private: + inline void _init() + { + /* reserve the second node for constant 1 */ + _storage->nodes.emplace_back(); + + /* reserve some truth tables for nodes */ + kitty::dynamic_truth_table tt_zero(0); + _storage->data.cache.insert(tt_zero); + + static uint64_t _not = 0x1; + kitty::dynamic_truth_table tt_not(1); + kitty::create_from_words(tt_not, &_not, &_not + 1); + _storage->data.cache.insert(tt_not); + + static uint64_t _and = 0x8; + kitty::dynamic_truth_table tt_and(2); + kitty::create_from_words(tt_and, &_and, &_and + 1); + _storage->data.cache.insert(tt_and); + + static uint64_t _or = 0xe; + kitty::dynamic_truth_table tt_or(2); + kitty::create_from_words(tt_or, &_or, &_or + 1); + _storage->data.cache.insert(tt_or); + + static uint64_t _xor = 0x6; + kitty::dynamic_truth_table tt_xor(2); + kitty::create_from_words(tt_xor, &_xor, &_xor + 1); + _storage->data.cache.insert(tt_xor); + + static uint64_t _mux= 0xd8; + kitty::dynamic_truth_table tt_mux(3); + kitty::create_from_words(tt_mux, &_mux, &_mux + 1); + _storage->data.cache.insert(tt_mux); + + + /* truth tables for constants */ + _storage->nodes[0].data[1].h1 = 0; + _storage->nodes[1].data[1].h1 = 1; + } +#pragma endregion + +#pragma region Primary I / O and constants + public: + signal get_constant(bool value = false) const + { + return value ? 1 : 0; + } + + signal create_pi(std::string const& name = std::string()) + { + (void)name; + + const auto index = _storage->nodes.size(); + _storage->nodes.emplace_back(); + _storage->inputs.emplace_back(index); + _storage->nodes[index].data[1].h1 = 2; + ++_storage->data.num_pis; + return index; + } + + uint32_t create_po(signal const& f, std::string const& name = std::string()) + { + (void)name; + + /* increase ref-count to children */ + _storage->nodes[f].data[0].h1++; + + auto const po_index = _storage->outputs.size(); + _storage->outputs.emplace_back(f); + ++_storage->data.num_pos; + return po_index; + } + + uint32_t create_ri(signal const& f, int8_t reset = 0, std::string const& name = std::string()) + { + (void)name; + + /* increase ref-count to children */ + _storage->nodes[f].data[0].h1++; + auto const ri_index = _storage->outputs.size(); + _storage->outputs.emplace_back(f); + _storage->data.latches.emplace_back(reset); + return ri_index; + } + + int8_t latch_reset(uint32_t index) const + { + assert(index < _storage->data.latches.size()); + return _storage->data.latches[index]; + } + + bool is_combinational() const + { + return (static_cast(_storage->inputs.size()) == _storage->data.num_pis && + static_cast(_storage->outputs.size()) == _storage->data.num_pos); + } + + bool is_constant(node const& n) const + { + return n <= 1; + } + + bool is_ci(node const& n) const + { + bool found = false; + detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), [&found, &n](auto const& node) { + if (node == n) + { + found = true; + return false; + } + return true; + }); + return found; + } + + bool is_pi(node const& n) const + { + bool found = false; + detail::foreach_element(_storage->inputs.begin(), _storage->inputs.begin() + _storage->data.num_pis, [&found, &n](auto const& node) { + if (node == n) + { + found = true; + return false; + } + return true; + }); + return found; + } + + bool constant_value(node const& n) const + { + return n == 1; + } +#pragma endregion + +#pragma region Create unary functions + signal create_buf(signal const& a) + { + return a; + } + + signal create_not(signal const& a) + { + return _create_node({ a }, 3); + } +#pragma endregion + +#pragma region Create binary/ternary functions + signal create_and(signal a, signal b) + { + return _create_node({ a, b }, 4); + } + + signal create_or(signal a, signal b) + { + return _create_node({ a, b }, 6); + } + + signal create_xor(signal a, signal b) + { + return _create_node({ a, b }, 8); + } + + signal create_mux(signal a, signal b, signal c) + { + return _create_node({ a, b, c }, 10); + } + +#pragma endregion + +#pragma region Create arbitrary functions + signal _create_node(std::vector const& children, uint32_t literal) + { + storage::element_type::node_type node; + std::copy(children.begin(), children.end(), std::back_inserter(node.children)); + node.data[1].h1 = literal; + + const auto it = _storage->hash.find(node); + if (it != _storage->hash.end()) + { + return it->second; + } + + const auto index = _storage->nodes.size(); + _storage->nodes.push_back(node); + _storage->hash[node] = index; + + /* increase ref-count to children */ + for (auto c : children) + { + _storage->nodes[c].data[0].h1++; + } + + set_value(index, 0); + + for (auto const& fn : _events->on_add) + { + (*fn)(index); + } + + return index; + } + + signal create_node(std::vector const& children, kitty::dynamic_truth_table const& function) + { + if (children.size() == 0u) + { + assert(function.num_vars() == 0u); + return get_constant(!kitty::is_const0(function)); + } + return _create_node(children, _storage->data.cache.insert(function)); + } + + signal clone_node(aoig_network const& other, node const& source, std::vector const& children) + { + assert(!children.empty()); + const auto tt = other._storage->data.cache[other._storage->nodes[source].data[1].h1]; + return create_node(children, tt); + } +#pragma endregion + +#pragma region Restructuring + void substitute_node(node const& old_node, signal const& new_signal) + { + /* find all parents from old_node */ + for (auto i = 0u; i < _storage->nodes.size(); ++i) + { + auto& n = _storage->nodes[i]; + for (auto& child : n.children) + { + if (child == old_node) + { + std::vector old_children(n.children.size()); + std::transform(n.children.begin(), n.children.end(), old_children.begin(), [](auto c) { return c.index; }); + child = new_signal; + + // increment fan-out of new node + _storage->nodes[new_signal].data[0].h1++; + + for (auto const& fn : _events->on_modified) + { + (*fn)(i, old_children); + } + } + } + } + + /* check outputs */ + for (auto& output : _storage->outputs) + { + if (output == old_node) + { + output = new_signal; + + // increment fan-out of new node + _storage->nodes[new_signal].data[0].h1++; + } + } + + // reset fan-out of old node + _storage->nodes[old_node].data[0].h1 = 0; + } +#pragma endregion + +#pragma region Structural properties + auto size() const + { + return static_cast(_storage->nodes.size()); + } + + auto num_cis() const + { + return static_cast(_storage->inputs.size()); + } + + auto num_cos() const + { + return static_cast(_storage->outputs.size()); + } + + auto num_pis() const + { + return _storage->data.num_pis; + } + + auto num_pos() const + { + return _storage->data.num_pos; + } + + + auto num_gates() const + { + return static_cast(_storage->nodes.size() - _storage->inputs.size() - 2); + } + + uint32_t fanin_size(node const& n) const + { + return static_cast(_storage->nodes[n].children.size()); + } + + uint32_t fanout_size(node const& n) const + { + return _storage->nodes[n].data[0].h1; + } + + bool is_function(node const& n) const + { + return n > 1 && !is_ci(n); + } +#pragma endregion + +#pragma region Functional properties + kitty::dynamic_truth_table node_function(const node& n) const + { + return _storage->data.cache[_storage->nodes[n].data[1].h1]; + } +#pragma endregion + +#pragma region Nodes and signals + node get_node(signal const& f) const + { + return f; + } + + bool is_complemented( signal const& f ) const + { + (void)f; + return false; + } + + signal make_signal(node const& n) const + { + return n; + } + + uint32_t node_to_index(node const& n) const + { + return static_cast(n); + } + + node index_to_node(uint32_t index) const + { + return index; + } + + node ci_at(uint32_t index) const + { + assert(index < _storage->inputs.size()); + return *(_storage->inputs.begin() + index); + } + + signal co_at(uint32_t index) const + { + assert(index < _storage->outputs.size()); + return (_storage->outputs.begin() + index)->index; + } + + node pi_at(uint32_t index) const + { + assert(index < _storage->data.num_pis); + return *(_storage->inputs.begin() + index); + } + + signal po_at(uint32_t index) const + { + assert(index < _storage->data.num_pos); + return (_storage->outputs.begin() + index)->index; + } + + uint32_t ci_index(node const& n) const + { + assert(_storage->nodes[n].children[0].data == _storage->nodes[n].children[1].data); + return (_storage->nodes[n].children[0].data); + } + + uint32_t co_index(signal const& s) const + { + uint32_t i = -1; + foreach_co([&](const auto& x, auto index) { + if (x == s) + { + i = index; + return false; + } + return true; + }); + return i; + } + + uint32_t pi_index(node const& n) const + { + assert(_storage->nodes[n].children[0].data == _storage->nodes[n].children[1].data); + return (_storage->nodes[n].children[0].data); + } + + uint32_t po_index(signal const& s) const + { + uint32_t i = -1; + foreach_po([&](const auto& x, auto index) { + if (x == s) + { + i = index; + return false; + } + return true; + }); + return i; + } +#pragma endregion + +#pragma region Node and signal iterators + template + void foreach_node(Fn&& fn) const + { + detail::foreach_element(ez::make_direct_iterator(0), + ez::make_direct_iterator(_storage->nodes.size()), + fn); + } + + template + void foreach_ci(Fn&& fn) const + { + detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); + } + + template + void foreach_co(Fn&& fn) const + { + using IteratorType = decltype(_storage->outputs.begin()); + detail::foreach_element_transform(_storage->outputs.begin(), _storage->outputs.end(), [](auto o) { return o.index; }, fn); + } + + template + void foreach_pi(Fn&& fn) const + { + detail::foreach_element(_storage->inputs.begin(), _storage->inputs.begin() + _storage->data.num_pis, fn); + } + + template + void foreach_po(Fn&& fn) const + { + using IteratorType = decltype(_storage->outputs.begin()); + detail::foreach_element_transform(_storage->outputs.begin(), _storage->outputs.begin() + _storage->data.num_pos, [](auto o) { return o.index; }, fn); + } + + template + void foreach_gate(Fn&& fn) const + { + detail::foreach_element_if(ez::make_direct_iterator(2), /* start from 2 to avoid constants */ + ez::make_direct_iterator(_storage->nodes.size()), + [this](auto n) { return !is_ci(n); }, + fn); + } + + template + void foreach_fanin(node const& n, Fn&& fn) const + { + if (n == 0 || is_ci(n)) + return; + + using IteratorType = decltype(_storage->outputs.begin()); + detail::foreach_element_transform(_storage->nodes[n].children.begin(), _storage->nodes[n].children.end(), [](auto f) { return f.index; }, fn); + } +#pragma endregion + +#pragma region Simulate values + template + iterates_over_t + compute(node const& n, Iterator begin, Iterator end) const + { + uint32_t index{ 0 }; + while (begin != end) + { + index <<= 1; + index ^= *begin++ ? 1 : 0; + } + return kitty::get_bit(_storage->data.cache[_storage->nodes[n].data[1].h1], index); + } + + template + iterates_over_truth_table_t + compute(node const& n, Iterator begin, Iterator end) const + { + const auto nfanin = _storage->nodes[n].children.size(); + std::vector tts(begin, end); + + assert(nfanin != 0); + assert(tts.size() == nfanin); + + /* resulting truth table has the same size as any of the children */ + auto result = tts.front().construct(); + const auto gate_tt = _storage->data.cache[_storage->nodes[n].data[1].h1]; + + for (auto i = 0u; i < result.num_bits(); ++i) + { + uint32_t pattern = 0u; + for (auto j = 0u; j < nfanin; ++j) + { + pattern |= kitty::get_bit(tts[j], i) << j; + } + if (kitty::get_bit(gate_tt, pattern)) + { + kitty::set_bit(result, i); + } + } + + return result; + } +#pragma endregion + +#pragma region Custom node values + void clear_values() const + { + std::for_each(_storage->nodes.begin(), _storage->nodes.end(), [](auto& n) { n.data[0].h2 = 0; }); + } + + uint32_t value(node const& n) const + { + return _storage->nodes[n].data[0].h2; + } + + void set_value(node const& n, uint32_t v) const + { + _storage->nodes[n].data[0].h2 = v; + } + + uint32_t incr_value(node const& n) const + { + return static_cast(_storage->nodes[n].data[0].h2++); + } + + uint32_t decr_value(node const& n) const + { + return static_cast(--_storage->nodes[n].data[0].h2); + } +#pragma endregion + +#pragma region Visited flags + void clear_visited() const + { + std::for_each(_storage->nodes.begin(), _storage->nodes.end(), [](auto& n) { n.data[1].h2 = 0; }); + } + + auto visited(node const& n) const + { + return _storage->nodes[n].data[1].h2; + } + + void set_visited(node const& n, uint32_t v) const + { + _storage->nodes[n].data[1].h2 = v; + } + + uint32_t trav_id() const + { + return _storage->data.trav_id; + } + + void incr_trav_id() const + { + ++_storage->data.trav_id; + } +#pragma endregion + +#pragma region General methods + auto& events() const + { + return *_events; + } +#pragma endregion + + public: + std::shared_ptr _storage; + std::shared_ptr> _events; + }; + +} // namespace mockturtle + diff --git a/src/networks/aoig/build_xag_db.hpp b/src/networks/aoig/build_xag_db.hpp new file mode 100644 index 0000000..8402925 --- /dev/null +++ b/src/networks/aoig/build_xag_db.hpp @@ -0,0 +1,222 @@ +/* phyLS: Advanced Logic Synthesis and Optimization tool + * Copyright (C) 2019- Ningbo University, Ningbo, China */ + +/** + * @file build_xag_db.hpp + * + * @brief build an optimal XAG database based on optimal NPN4 + * classes + * + * @author Zhufei Chu + * @since 0.1 + */ + +#ifndef BUILD_XAG_DB_HPP +#define BUILD_XAG_DB_HPP + +namespace phyLS +{ + + class build_xag_db + { + public: + build_xag_db( xag_network& xag ) + : db( xag ) + { + } + + std::unordered_map get_opt_xag_map() + { + return load_optimal_xags(); + } + + std::unordered_map> run() + { + std::unordered_map> class2signal; + std::vector signals; + signals.push_back( db.get_constant( false ) ); + + for ( auto i = 0u; i < 4; ++i ) + { + signals.push_back( db.create_pi() ); + } + + auto opt_xags = load_optimal_xags(); //size optimization + + for ( const auto e : opt_xags ) + { + if( e.first == "0x0000" ) + { + std::vector tmp{ signals[0] }; + class2signal.insert( std::make_pair( e.first, tmp ) ); + } + else if( e.first == "0x00ff" ) + { + std::vector tmp{ signals[4] ^ true }; + class2signal.insert( std::make_pair( e.first, tmp ) ); + } + else + { + class2signal.insert( std::make_pair( e.first, create_xag_from_str( e.second, signals ) ) ); + } + } + return class2signal; + } + + private: + xag_network db; + + inline std::vector split( const std::string& str, const std::string& sep ) + { + std::vector result; + + size_t last = 0; + size_t next = 0; + while ( ( next = str.find( sep, last ) ) != std::string::npos ) + { + result.push_back( str.substr( last, next - last ) ); + last = next + 1; + } + result.push_back( str.substr( last ) ); + + return result; + } + + std::unordered_map load_optimal_xags() + { + std::unordered_map opt; + std::vector result; + + result = split( npn4, "\n" ); + + for ( auto record : result ) + { + auto p = split( record, " " ); + assert( p.size() == 2u ); + opt.insert( std::make_pair( p[0], p[1] ) ); + } + + return opt; + } + + std::vector create_xag_from_str( const std::string& str, const std::vector& signals ) + { + auto sig = signals; + std::vector result; + + std::stack polar; + std::stack inputs; + + for ( auto i = 0ul; i < str.size(); i++ ) + { + // operators polarity + if ( str[i] == '[' || str[i] == '(' || str[i] == '{' ) + { + polar.push( i > 0 && str[i - 1] == '!' ? 1 : 0 ); + } + + //input signals + if ( str[i] >= 'a' && str[i] <= 'd' ) + { + inputs.push( sig[str[i] - 'a' + 1] ); + + polar.push( i > 0 && str[i - 1] == '!' ? 1 : 0 ); + } + + //create signals + if ( str[i] == ']' ) + { + assert( inputs.size() >= 2u ); + auto x1 = inputs.top(); + inputs.pop(); + auto x2 = inputs.top(); + inputs.pop(); + + assert( polar.size() >= 3u ); + auto p1 = polar.top(); + polar.pop(); + auto p2 = polar.top(); + polar.pop(); + + auto p3 = polar.top(); + polar.pop(); + + inputs.push( db.create_xor( x1 ^ p1, x2 ^ p2 ) ^ p3 ); + polar.push( 0 ); + } + + if ( str[i] == ')' ) + { + assert( inputs.size() >= 2u ); + auto x1 = inputs.top(); + inputs.pop(); + auto x2 = inputs.top(); + inputs.pop(); + + assert( polar.size() >= 3u ); + auto p1 = polar.top(); + polar.pop(); + auto p2 = polar.top(); + polar.pop(); + + auto p3 = polar.top(); + polar.pop(); + + inputs.push( db.create_and( x1 ^ p1, x2 ^ p2 ) ^ p3 ); + polar.push( 0 ); + } + + if ( str[i] == '}' ) + { + assert( inputs.size() >= 2u ); + auto x1 = inputs.top(); + inputs.pop(); + auto x2 = inputs.top(); + inputs.pop(); + + assert( polar.size() >= 3u ); + auto p1 = polar.top(); + polar.pop(); + auto p2 = polar.top(); + polar.pop(); + + auto p3 = polar.top(); + polar.pop(); + + inputs.push( db.create_or( x1 ^ p1, x2 ^ p2 ) ^ p3 ); + polar.push( 0 ); + } + } + + assert( !polar.empty() ); + auto po = polar.top(); + polar.pop(); + db.create_po( inputs.top() ^ po ); + result.push_back( inputs.top() ^ po ); + return result; + } + + + + std::string npn4 = "0x1b ![b(a[bc])]\n0x17 ![b([ab][bc])]\n0x16 [[ab](c!(ab))]\n0x18 ([ac][bc])\n0x19 ![a(b!(ac))]\n0x0000 0\n0x00ff 0\n0x3cc3 ![d[bc]]\n0x1ee1 ![{ab}[cd]]\n0x1be4 [c[d(!a[bc])]]\n0x19e6 [[ad](b!(ac))]\n0x19e1 ![[a(c!d)](b!(a!(!cd)))]\n0x18e7 ![d([ac][bc])]\n0x1798 [d{(ab)(c![d[ab]])}]\n0x1796 [a{[bc](d![ab])}]\n0x177e [(ab){[cd][d[ab]]}]\n0x16e9 ![d(!(ab)[c{ab}])]\n0x169b ![[b[ad]]([c(a[b[ad]])][d(a[b[ad]])])]\n0x1699 ![b[a(d!(c!(ab)))]]\n0x1696 [a[b(c!(b(ad)))]]\n0x017e [d{[a(b!(ad))][c(b!(ad))]}]\n0x168e (!(c[d[ac]])[b([ac]!(b!d))])\n0x0666 ([ab]!(cd))\n0x1687 ![c([a(d!(a!c))][b(d!(a!c))])]\n0x016f !{(c![ab])(d{ab})}\n0x166e [(cd)[a(b!(a![cd]))]]\n0x1683 ![{bc}(![a(bc)][d(bc)])]\n0x1681 ![([ad][bd]){c[[ad]{b([ad][bd])}]}]\n0x17e8 [d({ab}!(!c[ab]))]\n0x166a [[a(!d[bc])]{[bc](c!(!ad))}]\n0x168b ![[c(b![ac])](d![b{a(b![ac])}])]\n0x1669 ![[b[ac]](d!(c(ab)))]\n0x16ac {([bc][ad])([bd][a[bc]])}\n0x07f8 [d{c(ab)}]\n0x07b5 !{(cd)([ac]!(!b[cd]))}\n0x07b4 [c{(!ab)(d!(b!c))}]\n0x001f !{d(c{ab})}\n0x03c7 !{(bd)({ac}[bc])}\n0x0ff0 [cd]\n0x03d7 !({ad}[b(c!(bd))])\n0x07b1 !{(b![ad])[d(!c{ad})]}\n0x077e (!(cd){[a[cd]][b[cd]]})\n0x0778 [d[c(b(a!(cd)))]]\n0x06f0 ([cd]!(d![ab]))\n0x06f9 ![d(!c[ab])]\n0x07b0 ([cd]!(b[ac]))\n0x06f6 [d{c[b[ad]]}]\n0x06b6 ([c[a{b(ac)}]]!(d![a{b(ac)}]))\n0x06b4 (!(cd)[[bc](a{bd})])\n0x019a [a{(ad)(!b[cd])}]\n0x06b0 ([cd]{(ac)[a[bc]]})\n0x07e3 ![(b!(!ad))(c!(a![bd]))]\n0x0697 !(!(!c[b(a!c)]){d[a[b(a!c)]]})\n0x06b5 !({d[ac]}!([cd][b[ac]]))\n0x0696 (!(cd)[b[ac]])\n0x178e [c{[a[cd]][b[cd]]}]\n0x0691 !{[b[ad]](![cd]{c[ad]})}\n0x169a (!(c(bd))[(!bc)[a(bd)]])\n0x077a (!(cd)[{cd}(a!(!b{cd}))])\n0x0679 ![d([b[ac]]!(c!(b!d)))]\n0x0678 [[c(ab)](d{[ab][c(ab)]})]\n0x0672 (!(cd)[{ac}(b{ad})])\n0x066b !({b{cd}}!(!(cd)[a(b{cd})]))\n0x0662 ([ab]![c(!d{bc})])\n0x6996 [d[c[ab]]]\n0x0661 !{({ac}![cd])[a[b[cd]]]}\n0x07e0 ([cd]!([ac][bc]))\n0x0690 ([cd][b[ac]])\n0x0660 ([ab][cd])\n0x011e [{cd}{b{a(cd)}}]\n0x03dd ![{bc}(!d{b[ac]})]\n0x1668 [[ac](![bd]{[ab][ac]})]\n0x0007 !{d{c(ab)}}\n0x06b1 ![(!c[b[ac]]){d(b[ac])}]\n0x03dc [d{b(c!(a!d))}]\n0x0667 !(!(!c[b{ac}]){d[a[b{ac}]]})\n0x01eb !{(d{ab})(!a[bc])}\n0x03d5 !({ad}!(![bc][cd]))\n0x066f ![(!c[b[ac]]){d[b[ac]]}]\n0x03d8 ([d[c(a[bc])]]!([bc]![c(a[bc])]))\n0x06b3 !{(cd)[(!ad)(b!(ac))]}\n0x03d6 [{bc}{d(a!(bc))}]\n0x0180 ([bd]([ad][cd]))\n0x03fc [d{bc}]\n0x03d4 [{bc}{d(a[bc])}]\n0x016a (!(d{bc})[(bc)[ad]])\n0x07e9 ![{c(ab)}(!d{ab})]\n0x06b9 ![d([ab]!(c!(b!d)))]\n0x03c6 [(!c{ad})(b!(d!(!c{ad})))]\n0x0669 !{(cd)[b[a{cd}]]}\n0x03c1 !{[bc]({ad}![cd])}\n0x036f ![{bc}(!d[b(ac)])]\n0x036e {(!c[bd])(!d[a[bd]])}\n0x07f2 [d{c(a![bd])}]\n0x03db !({bc}!(!d[c(a!(bc))]))\n0x036d ![{(b!c)(a!d)}[c(b!d)]]\n0x0189 ![{b(!ac)}(a!(d{b(!ac)}))]\n0x0369 !{[c[b(a!d)]](d[b(a!d)])}\n0x035e [c{(a!d)[d(b!c)]}]\n0x035b !({bc}!(!d[ac]))\n0x033f !{(bc)(d[bc])}\n0x01fe [d{c{ab}}]\n0x01ee [d{b{a(cd)}}]\n0x003d !{d[b(!c{ab})]}\n0x06bd ![d([ab]![c(b!d)])]\n0x035f !{(ac)(d{bc})}\n0x1bd8 [a[c(![bc][ad])]]\n0x0116 (!(c{ab})(!(ab)[c[d{ab}]]))\n0x03d9 ![b{(a!d)(c[bd])}]\n0x06f2 ([(a!c){bc}]{(a!c)[cd]})\n0x0358 [c({ad}{c[bd]})]\n0x033d !{(bc)[d(!b(!c{ad}))]}\n0x006f !{d(c![ab])}\n0x019e (!(c![b[ac]])[d{a[b[ac]]}])\n0x01e8 ([d{ab}]!(!(ab)[c{ab}]))\n0x07f0 [d{c(b(ad))}]\n0x01af !{(!ac)(d{ab})}\n0x0197 ![{d[ab]}(!c[d{ab}])]\n0x01bf !{(c(!a[bd]))(d!(!a[bd]))}\n0x03c5 ![{c(a!d)}(b[cd])]\n0x01bd ![{bc}({a[bc]}!(d{bc}))]\n0x011f !({cd}{b{a(cd)}})\n0x06b7 ![d([b(ad)][c{ad}])]\n0x013f !{(bc)(d{a[bc]})}\n0x01bc ([d{a[bc]}]!(![bc][c{a[bc]}]))\n0x036a [{bc}{d[a[bc]]}]\n0x036c [[b(ac)](d!(c![b(ac)]))]\n0x167e (!(d![c[ab]]){[ab][b[c[ab]]]})\n0x06b2 (!(!a[bd])[d{c[a[bd]]}])\n0x01ad ![a{(!ac)({bc}[ad])}]\n0x035a [{ad}{c(bd)}]\n0x01ab ![{bc}(a[d{bc}])]\n0x018b !{(ad)[c(b![ac])]}\n0x01ac ([a(!c[b{ad}])]!(d!(!c[b{ad}])))\n0x01be (!(bd)[d{a[bc]}])\n0x16ad ![(bd)[[cd](a!(b![cd]))]]\n0x0186 (![c(ab)][d{ab}])\n0x01aa ([ad]!(d{bc}))\n0x1686 ([b[ac]]!(c![ad]))\n0x01a9 ![a({bc}!(ad))]\n0x07b6 [{c(a![bd])}{d(!a[bd])}]\n0x01a8 (![a{bc}][d{bc}])\n0x007e (!d{[ab][ac]})\n0x019f !{(d!(!a[cd]))[(!a[cd])(!b[cd])]}\n0x0676 (!(cd)[a{b(!ac)}])\n0x0663 !{(cd)[b(!a[cd])]}\n0x013d ![(!d[bc]){b{a[bc]}}]\n0x019b !{(cd)[b(a{c[bd]})]}\n0x0119 ![{a(cd)}(b!({cd}{a(cd)}))]\n0x0168 (![c[ab]][d{ab}])\n0x16a9 ![{bc}[a(d!(!a(bc)))]]\n0x0368 [(a!d)(![bc][d{c(a!d)}])]\n0x0198 (![ab][d{ac}])\n0x018f !{(c!(ab))(d{ab})}\n0x06f1 ![d(!c[a(b!(a!d))])]\n0x0183 !{[bc][b(a[cd])]}\n0x0182 (!(bd)(![bc][ad]))\n0x0181 !{[a(b!(ad))][c(b!(ad))]}\n0x07bc [[cd](b![d(a[cd])])]\n0x03c3 ![b(c!(bd))]\n0x0199 !{[ab](d{bc})}\n0x19e3 ![{b(ac)}(!(!ad)[cd])]\n0x003c (!d[bc])\n0x0016 (!{d(ab)}[a[bc]])\n0x0779 !({c[b[a[cd]]]}!([cd]!(a[b[a[cd]]])))\n0x0359 ![{ad}(!c[bd])]\n0x0006 ([ab]!{cd})\n0x016e (!(c![ab])[d{ab}])\n0x1698 ({b[ac]}![[bd]{a(d[ac])}])\n0x01e9 ![{c(ab)}({ab}!(d{c(ab)}))]\n0x16bc [c[b(a[d(bc)])]]\n0x166b ![d([a[bc]]!(a![bd]))]\n0x0118 (![a(b!(ac))][c[d(b!(ac))]])\n0x017f ![d([cd]([ad][bd]))]\n0x0001 !{{ab}{cd}}\n0x0187 !{[c(ab)](d{ab})}\n0x07e1 ![c{(a!d)(b![d(a!c)])}]\n0x067e [d{[c(a!d)][a[bd]]}]\n0x0117 ![(!d(!(ab)[c{ab}])){{ab}(!(ab)[c{ab}])}]\n0x013e [{d(bc)}{a{bc}}]\n0x033c [b[c(d!(bc))]]\n0x07e6 [{c(ab)}{d[c{ab}]}]\n0x036b !({bc}!(!d[a(bc)]))\n0x012f !{(b[cd])[c(a[cd])]}\n0x0356 [{bc}{ad}]\n0x011b ![{b{a(cd)}}(!{cd}{a(cd)})]\n0x01ef ![d(!b(!a[cd]))]\n0x037c [{bc}{d(a(bc))}]\n0x012d !{(d{ab})[b[c{ab}]]}\n0x169e [c[a(b!(a![cd]))]]\n0x01ae (!(!ac)[d{ab}])\n0x01ea ([d{ab}]!(!a[bc]))\n0x0019 !{d[a(b!(ac))]}\n0x067a {(!d[a[cd]])([cd]![b[a[cd]]])}\n0x007f !{d(c(ab))}\n0x0776 (!(cd)[a{b(!a{cd})}])\n0x006b !{d[c[b(a{bc})]]}\n0x17ac [[d{bc}](!a[c(bd)])]\n0x011a ([d[ac]][c{a[bd]}])\n0x013c ([c[bd]]!(d!(!a[bd])))\n0x07f1 ![d(!c{[ad][bd]})]\n0x067b ![{d(a![bc])}(!c[a[bc]])]\n0x037d ![d({ad}!{[bc](cd)})]\n0x0003 !{d{bc}}\n0x0069 !{d[c[ab]]}\n0x003f !{d(bc)}\n0x012c ([b[cd]]![d(!a[cd])])\n0x0196 (!(d!(!b[ad]))[b[c[ad]]])\n0x001e (!d[c{ab}])\n0x0169 !{(d{ab})[b[ac]]}\n0x07e2 (!(cd)[{ad}(b[ac])])\n0x0693 ![(a[cd])[b(d!(bc))]]\n0x016b ![{bc}([a(bc)][d{bc}])]\n0x03c0 ([bd][cd])\n0x037e [d{[b(a!d)][c(a!d)]}]\n0x000f !{cd}\n0x001b !{d[b(a[bc])]}\n0x0357 !({bc}{ad})\n0x0018 (!d([ac][bc]))\n0x1689 ![[ad]{[b(!ac)](c![ad])}]\n0x0673 !({bd}!([ab][cd]))\n0x03cf ![c(b[cd])]\n0x069f ![c(![ab][cd])]\n0x1697 ![c(![ab]{[ad][cd]})]\n0x03de [d{b[c(a!d)]}]\n0x179a [a[{c[b(!ad)]}(b!(d[b(!ad)]))]]\n0x0017 !{(ab){d(c[ab])}}"; + + + }; + + + std::unordered_map> get_xag_db( xag_network& xag ) + { + build_xag_db manager( xag ); + return manager.run(); + } + + std::unordered_map load_xag_string_db( xag_network& xag ) + { + build_xag_db manager( xag ); + return manager.get_opt_xag_map(); + } + + +} + +#endif diff --git a/src/networks/aoig/opt_aoig.txt b/src/networks/aoig/opt_aoig.txt new file mode 100644 index 0000000..4706650 --- /dev/null +++ b/src/networks/aoig/opt_aoig.txt @@ -0,0 +1,220 @@ +0x3cc3 ![d[bc]] +0x1ee1 ![{ab}[cd]] +0x1be4 [c[d(!a[bc])]] +0x19e6 [[ad](b!(ac))] +0x19e1 ![[a(c!d)](b!(a!(!cd)))] +0x18e7 ![d([ac][bc])] +0x1798 [d{(ab)(c![d[ab]])}] +0x1796 [a{[bc](d![ab])}] +0x177e [(ab){[cd][d[ab]]}] +0x16e9 ![d(!(ab)[c{ab}])] +0x169b ![[b[ad]]([c(a[b[ad]])][d(a[b[ad]])])] +0x1699 ![b[a(d!(c!(ab)))]] +0x1696 [a[b(c!(b(ad)))]] +0x017e [d{[a(b!(ad))][c(b!(ad))]}] +0x168e (!(c[d[ac]])[b([ac]!(b!d))]) +0x0666 ([ab]!(cd)) +0x1687 ![c([a(d!(a!c))][b(d!(a!c))])] +0x016f !{(c![ab])(d{ab})} +0x166e [(cd)[a(b!(a![cd]))]] +0x1683 ![{bc}(![a(bc)][d(bc)])] +0x1681 ![([ad][bd]){c[[ad]{b([ad][bd])}]}] +0x17e8 [d({ab}!(!c[ab]))] +0x166a [[a(!d[bc])]{[bc](c!(!ad))}] +0x168b ![[c(b![ac])](d![b{a(b![ac])}])] +0x1669 ![[b[ac]](d!(c(ab)))] +0x16ac {([bc][ad])([bd][a[bc]])} +0x07f8 [d{c(ab)}] +0x07b5 !{(cd)([ac]!(!b[cd]))} +0x07b4 [c{(!ab)(d!(b!c))}] +0x001f !{d(c{ab})} +0x03c7 !{(bd)({ac}[bc])} +0x0ff0 [cd] +0x03d7 !({ad}[b(c!(bd))]) +0x07b1 !{(b![ad])[d(!c{ad})]} +0x077e (!(cd){[a[cd]][b[cd]]}) +0x0778 [d[c(b(a!(cd)))]] +0x06f0 ([cd]!(d![ab])) +0x06f9 ![d(!c[ab])] +0x07b0 ([cd]!(b[ac])) +0x06f6 [d{c[b[ad]]}] +0x06b6 ([c[a{b(ac)}]]!(d![a{b(ac)}])) +0x06b4 (!(cd)[[bc](a{bd})]) +0x019a [a{(ad)(!b[cd])}] +0x06b0 ([cd]{(ac)[a[bc]]}) +0x07e3 ![(b!(!ad))(c!(a![bd]))] +0x0697 !(!(!c[b(a!c)]){d[a[b(a!c)]]}) +0x06b5 !({d[ac]}!([cd][b[ac]])) +0x0696 (!(cd)[b[ac]]) +0x178e [c{[a[cd]][b[cd]]}] +0x0691 !{[b[ad]](![cd]{c[ad]})} +0x169a (!(c(bd))[(!bc)[a(bd)]]) +0x077a (!(cd)[{cd}(a!(!b{cd}))]) +0x0679 ![d([b[ac]]!(c!(b!d)))] +0x0678 [[c(ab)](d{[ab][c(ab)]})] +0x0672 (!(cd)[{ac}(b{ad})]) +0x066b !({b{cd}}!(!(cd)[a(b{cd})])) +0x0662 ([ab]![c(!d{bc})]) +0x6996 [d[c[ab]]] +0x0661 !{({ac}![cd])[a[b[cd]]]} +0x07e0 ([cd]!([ac][bc])) +0x0690 ([cd][b[ac]]) +0x0660 ([ab][cd]) +0x011e [{cd}{b{a(cd)}}] +0x03dd ![{bc}(!d{b[ac]})] +0x1668 [[ac](![bd]{[ab][ac]})] +0x0007 !{d{c(ab)}} +0x06b1 ![(!c[b[ac]]){d(b[ac])}] +0x03dc [d{b(c!(a!d))}] +0x0667 !(!(!c[b{ac}]){d[a[b{ac}]]}) +0x01eb !{(d{ab})(!a[bc])} +0x03d5 !({ad}!(![bc][cd])) +0x066f ![(!c[b[ac]]){d[b[ac]]}] +0x03d8 ([d[c(a[bc])]]!([bc]![c(a[bc])])) +0x06b3 !{(cd)[(!ad)(b!(ac))]} +0x03d6 [{bc}{d(a!(bc))}] +0x0180 ([bd]([ad][cd])) +0x03fc [d{bc}] +0x03d4 [{bc}{d(a[bc])}] +0x016a (!(d{bc})[(bc)[ad]]) +0x07e9 ![{c(ab)}(!d{ab})] +0x06b9 ![d([ab]!(c!(b!d)))] +0x03c6 [(!c{ad})(b!(d!(!c{ad})))] +0x0669 !{(cd)[b[a{cd}]]} +0x03c1 !{[bc]({ad}![cd])} +0x036f ![{bc}(!d[b(ac)])] +0x036e {(!c[bd])(!d[a[bd]])} +0x07f2 [d{c(a![bd])}] +0x03db !({bc}!(!d[c(a!(bc))])) +0x036d ![{(b!c)(a!d)}[c(b!d)]] +0x0189 ![{b(!ac)}(a!(d{b(!ac)}))] +0x0369 !{[c[b(a!d)]](d[b(a!d)])} +0x035e [c{(a!d)[d(b!c)]}] +0x035b !({bc}!(!d[ac])) +0x033f !{(bc)(d[bc])} +0x01fe [d{c{ab}}] +0x01ee [d{b{a(cd)}}] +0x003d !{d[b(!c{ab})]} +0x06bd ![d([ab]![c(b!d)])] +0x035f !{(ac)(d{bc})} +0x1bd8 [a[c(![bc][ad])]] +0x0116 (!(c{ab})(!(ab)[c[d{ab}]])) +0x03d9 ![b{(a!d)(c[bd])}] +0x06f2 ([(a!c){bc}]{(a!c)[cd]}) +0x0358 [c({ad}{c[bd]})] +0x033d !{(bc)[d(!b(!c{ad}))]} +0x006f !{d(c![ab])} +0x019e (!(c![b[ac]])[d{a[b[ac]]}]) +0x01e8 ([d{ab}]!(!(ab)[c{ab}])) +0x07f0 [d{c(b(ad))}] +0x01af !{(!ac)(d{ab})} +0x0197 ![{d[ab]}(!c[d{ab}])] +0x01bf !{(c(!a[bd]))(d!(!a[bd]))} +0x03c5 ![{c(a!d)}(b[cd])] +0x01bd ![{bc}({a[bc]}!(d{bc}))] +0x011f !({cd}{b{a(cd)}}) +0x06b7 ![d([b(ad)][c{ad}])] +0x013f !{(bc)(d{a[bc]})} +0x01bc ([d{a[bc]}]!(![bc][c{a[bc]}])) +0x036a [{bc}{d[a[bc]]}] +0x036c [[b(ac)](d!(c![b(ac)]))] +0x167e (!(d![c[ab]]){[ab][b[c[ab]]]}) +0x06b2 (!(!a[bd])[d{c[a[bd]]}]) +0x01ad ![a{(!ac)({bc}[ad])}] +0x035a [{ad}{c(bd)}] +0x01ab ![{bc}(a[d{bc}])] +0x018b !{(ad)[c(b![ac])]} +0x01ac ([a(!c[b{ad}])]!(d!(!c[b{ad}]))) +0x01be (!(bd)[d{a[bc]}]) +0x16ad ![(bd)[[cd](a!(b![cd]))]] +0x0186 (![c(ab)][d{ab}]) +0x01aa ([ad]!(d{bc})) +0x1686 ([b[ac]]!(c![ad])) +0x01a9 ![a({bc}!(ad))] +0x07b6 [{c(a![bd])}{d(!a[bd])}] +0x01a8 (![a{bc}][d{bc}]) +0x007e (!d{[ab][ac]}) +0x019f !{(d!(!a[cd]))[(!a[cd])(!b[cd])]} +0x0676 (!(cd)[a{b(!ac)}]) +0x0663 !{(cd)[b(!a[cd])]} +0x013d ![(!d[bc]){b{a[bc]}}] +0x019b !{(cd)[b(a{c[bd]})]} +0x0119 ![{a(cd)}(b!({cd}{a(cd)}))] +0x0168 (![c[ab]][d{ab}]) +0x16a9 ![{bc}[a(d!(!a(bc)))]] +0x0368 [(a!d)(![bc][d{c(a!d)}])] +0x0198 (![ab][d{ac}]) +0x018f !{(c!(ab))(d{ab})} +0x06f1 ![d(!c[a(b!(a!d))])] +0x0183 !{[bc][b(a[cd])]} +0x0182 (!(bd)(![bc][ad])) +0x0181 !{[a(b!(ad))][c(b!(ad))]} +0x07bc [[cd](b![d(a[cd])])] +0x03c3 ![b(c!(bd))] +0x0199 !{[ab](d{bc})} +0x19e3 ![{b(ac)}(!(!ad)[cd])] +0x003c (!d[bc]) +0x0016 (!{d(ab)}[a[bc]]) +0x0779 !({c[b[a[cd]]]}!([cd]!(a[b[a[cd]]]))) +0x0359 ![{ad}(!c[bd])] +0x0006 ([ab]!{cd}) +0x016e (!(c![ab])[d{ab}]) +0x1698 ({b[ac]}![[bd]{a(d[ac])}]) +0x01e9 ![{c(ab)}({ab}!(d{c(ab)}))] +0x16bc [c[b(a[d(bc)])]] +0x166b ![d([a[bc]]!(a![bd]))] +0x0118 (![a(b!(ac))][c[d(b!(ac))]]) +0x017f ![d([cd]([ad][bd]))] +0x0001 !{{ab}{cd}} +0x0187 !{[c(ab)](d{ab})} +0x07e1 ![c{(a!d)(b![d(a!c)])}] +0x067e [d{[c(a!d)][a[bd]]}] +0x0117 ![(!d(!(ab)[c{ab}])){{ab}(!(ab)[c{ab}])}] +0x013e [{d(bc)}{a{bc}}] +0x033c [b[c(d!(bc))]] +0x07e6 [{c(ab)}{d[c{ab}]}] +0x036b !({bc}!(!d[a(bc)])) +0x012f !{(b[cd])[c(a[cd])]} +0x0356 [{bc}{ad}] +0x011b ![{b{a(cd)}}(!{cd}{a(cd)})] +0x01ef ![d(!b(!a[cd]))] +0x037c [{bc}{d(a(bc))}] +0x012d !{(d{ab})[b[c{ab}]]} +0x169e [c[a(b!(a![cd]))]] +0x01ae (!(!ac)[d{ab}]) +0x01ea ([d{ab}]!(!a[bc])) +0x0019 !{d[a(b!(ac))]} +0x067a {(!d[a[cd]])([cd]![b[a[cd]]])} +0x007f !{d(c(ab))} +0x0776 (!(cd)[a{b(!a{cd})}]) +0x006b !{d[c[b(a{bc})]]} +0x17ac [[d{bc}](!a[c(bd)])] +0x011a ([d[ac]][c{a[bd]}]) +0x013c ([c[bd]]!(d!(!a[bd]))) +0x07f1 ![d(!c{[ad][bd]})] +0x067b ![{d(a![bc])}(!c[a[bc]])] +0x037d ![d({ad}!{[bc](cd)})] +0x0003 !{d{bc}} +0x0069 !{d[c[ab]]} +0x003f !{d(bc)} +0x012c ([b[cd]]![d(!a[cd])]) +0x0196 (!(d!(!b[ad]))[b[c[ad]]]) +0x001e (!d[c{ab}]) +0x0169 !{(d{ab})[b[ac]]} +0x07e2 (!(cd)[{ad}(b[ac])]) +0x0693 ![(a[cd])[b(d!(bc))]] +0x016b ![{bc}([a(bc)][d{bc}])] +0x03c0 ([bd][cd]) +0x037e [d{[b(a!d)][c(a!d)]}] +0x000f !{cd} +0x001b !{d[b(a[bc])]} +0x0357 !({bc}{ad}) +0x0018 (!d([ac][bc])) +0x1689 ![[ad]{[b(!ac)](c![ad])}] +0x0673 !({bd}!([ab][cd])) +0x03cf ![c(b[cd])] +0x069f ![c(![ab][cd])] +0x1697 ![c(![ab]{[ad][cd]})] +0x03de [d{b[c(a!d)]}] +0x179a [a[{c[b(!ad)]}(b!(d[b(!ad)]))]] +0x0017 !{(ab){d(c[ab])}} diff --git a/src/networks/aoig/xag_dec.hpp b/src/networks/aoig/xag_dec.hpp new file mode 100644 index 0000000..33df21f --- /dev/null +++ b/src/networks/aoig/xag_dec.hpp @@ -0,0 +1,339 @@ +/* phyLS: Advanced Logic Synthesis and Optimization tool + * Copyright (C) 2019- Ningbo University, Ningbo, China */ + +/** + * @file xag_dec.hpp + * + * @brief Deompose a truth table into an XAG signal by combined + * decompostion methods (DSD, Shannon, and NPN ) + * + * @author Zhufei Chu + * @since 0.1 + */ + +#ifndef XAG_DEC_HPP +#define XAG_DEC_HPP + +#include "../../core/misc.hpp" +#include "build_xag_db.hpp" + +namespace phyLS +{ + /*! \brief Parameters for xag_dec */ + struct xag_dec_params + { + /*! \brief Apply NPN4. */ + bool with_npn4{true}; + }; + + class xag_dec_impl + { + private: + std::vector get_func_supports( kitty::dynamic_truth_table const& spec ) + { + std::vector supports; + + for( auto i = 0u; i < spec.num_vars(); ++i ) + { + if( kitty::has_var( spec, i ) ) + { + supports.push_back( i ); + } + } + + return supports; + } + + public: + xag_dec_impl( xag_network& ntk, kitty::dynamic_truth_table const& func, std::vector const& children, + std::unordered_map& opt_xags, + xag_dec_params const& ps ) + : _ntk( ntk ), + _func( func ), + pis( children ), + opt_xags( opt_xags ), + _ps( ps ) + { + } + + xag_network::signal decompose( kitty::dynamic_truth_table& remainder, std::vector const& children ) + { + auto sup = get_func_supports( remainder ); + + /* check constants */ + if ( kitty::is_const0( remainder ) ) + { + return _ntk.get_constant( false ); + } + if ( kitty::is_const0( ~remainder ) ) + { + return _ntk.get_constant( true ); + } + + /* check primary inputs */ + if( sup.size() == 1u ) + { + auto var = remainder.construct(); + + kitty::create_nth_var( var, sup.front() ); + if( remainder == var ) + { + return children[sup.front()]; + } + else + { + assert( remainder == ~var ); + return _ntk.create_not( children[sup.front()] ); + } + assert( false && "ERROR for primary inputs" ); + } + + /* top decomposition */ + for( auto var : sup ) + { + if ( auto res = kitty::is_top_decomposable( remainder, var, &remainder, true ); + res != kitty::top_decomposition::none ) + { + const auto right = decompose( remainder, children ); + + switch ( res ) + { + default: + assert( false ); + case kitty::top_decomposition::and_: + return _ntk.create_and( children[var], right ); + case kitty::top_decomposition::or_: + return _ntk.create_or( children[var], right ); + case kitty::top_decomposition::lt_: + return _ntk.create_lt( children[var], right ); + case kitty::top_decomposition::le_: + return _ntk.create_le( children[var], right ); + case kitty::top_decomposition::xor_: + return _ntk.create_xor( children[var], right ); + } + } + } + + /* bottom decomposition */ + for ( auto j = 1u; j < sup.size(); ++j ) + { + for ( auto i = 0u; i < j; ++i ) + { + if ( auto res = kitty::is_bottom_decomposable( remainder, sup[i], sup[j], &remainder, true ); + res != kitty::bottom_decomposition::none ) /* allow XOR */ + { + auto copy = children; + switch ( res ) + { + default: + assert( false ); + case kitty::bottom_decomposition::and_: + copy[sup[i]] = _ntk.create_and( copy[sup[i]], copy[sup[j]] ); + break; + case kitty::bottom_decomposition::or_: + copy[sup[i]] = _ntk.create_or( copy[sup[i]], copy[sup[j]] ); + break; + case kitty::bottom_decomposition::lt_: + copy[sup[i]] = _ntk.create_lt( copy[sup[i]], copy[sup[j]] ); + break; + case kitty::bottom_decomposition::le_: + copy[sup[i]] = _ntk.create_le( copy[sup[i]], copy[sup[j]] ); + break; + case kitty::bottom_decomposition::xor_: + copy[sup[i]] = _ntk.create_xor( copy[sup[i]], copy[sup[j]] ); + break; + } + + return decompose( remainder, copy ); + } + } + } + + if( sup.size() > 4u || !_ps.with_npn4 ) + { + /* shannon decomposition */ + auto var = sup.front(); + auto c0 = kitty::cofactor0( remainder, var ); + auto c1 = kitty::cofactor1( remainder, var ); + + const auto f0 = decompose( c0, children ); + const auto f1 = decompose( c1, children ); + + return _ntk.create_ite( children[var], f1, f0 ); + } + else + { + /* NPN transformation */ + return xag_from_npn( remainder, children ); + } + + assert( false ); + } + + xag_network::signal xag_from_npn( kitty::dynamic_truth_table const& remainder, std::vector const& children ) + { + /* get pi signals */ + auto sup = get_func_supports( remainder ); + std::vector small_pis; + for( auto const i : sup ) + { + small_pis.push_back( children[i] ); + } + + auto copy = remainder; + const auto support = kitty::min_base_inplace( copy ); + const auto small_func = kitty::shrink_to( copy, static_cast( support.size() ) ); + + auto tt = small_func; + + auto ttsup = get_func_supports( tt ); + + const auto config = kitty::exact_npn_canonization( tt ); + + auto func_str = "0x" + kitty::to_hex( std::get<0>( config ) ); + //std::cout << " process function " << func_str << std::endl; + + const auto it = opt_xags.find( func_str ); + assert( it != opt_xags.end() ); + + std::vector pis( support.size(), _ntk.get_constant( false ) ); + std::copy( small_pis.begin(), small_pis.end(), pis.begin() ); + + std::vector pis_perm( support.size() ); + auto perm = std::get<2>( config ); + for ( auto i = 0; i < support.size(); ++i ) + { + pis_perm[i] = pis[perm[i]]; + } + + const auto& phase = std::get<1>( config ); + for ( auto i = 0; i < support.size(); ++i ) + { + if ( ( phase >> perm[i] ) & 1 ) + { + pis_perm[i] = !pis_perm[i]; + } + } + + auto res = create_xag_from_str( it->second, pis_perm ); + + return ( ( phase >> support.size() ) & 1 ) ? !res : res; + } + + xag_network::signal create_xag_from_str( const std::string& str, const std::vector& pis_perm ) + { + std::stack polar; + std::stack inputs; + + for ( auto i = 0ul; i < str.size(); i++ ) + { + // operators polarity + if ( str[i] == '[' || str[i] == '(' || str[i] == '{' ) + { + polar.push( (i > 0 && str[i - 1] == '!') ? 1 : 0 ); + } + + //input signals + if ( str[i] >= 'a' && str[i] <= 'd' ) + { + inputs.push( pis_perm[str[i] - 'a'] ); + + polar.push( ( i > 0 && str[i - 1] == '!' ) ? 1 : 0 ); + } + + //create signals + if ( str[i] == ']' ) + { + assert( inputs.size() >= 2u ); + auto x1 = inputs.top(); + inputs.pop(); + auto x2 = inputs.top(); + inputs.pop(); + + assert( polar.size() >= 3u ); + auto p1 = polar.top(); + polar.pop(); + auto p2 = polar.top(); + polar.pop(); + + auto p3 = polar.top(); + polar.pop(); + + inputs.push( _ntk.create_xor( x1 ^ p1, x2 ^ p2 ) ^ p3 ); + polar.push( 0 ); + } + + if ( str[i] == ')' ) + { + assert( inputs.size() >= 2u ); + auto x1 = inputs.top(); + inputs.pop(); + auto x2 = inputs.top(); + inputs.pop(); + + assert( polar.size() >= 3u ); + auto p1 = polar.top(); + polar.pop(); + auto p2 = polar.top(); + polar.pop(); + + auto p3 = polar.top(); + polar.pop(); + + inputs.push( _ntk.create_and( x1 ^ p1, x2 ^ p2 ) ^ p3 ); + polar.push( 0 ); + } + + if ( str[i] == '}' ) + { + assert( inputs.size() >= 2u ); + auto x1 = inputs.top(); + inputs.pop(); + auto x2 = inputs.top(); + inputs.pop(); + + assert( polar.size() >= 3u ); + auto p1 = polar.top(); + polar.pop(); + auto p2 = polar.top(); + polar.pop(); + + auto p3 = polar.top(); + polar.pop(); + + inputs.push( _ntk.create_or( x1 ^ p1, x2 ^ p2 ) ^ p3 ); + polar.push( 0 ); + } + } + + assert( !polar.empty() ); + auto po = polar.top(); + polar.pop(); + return inputs.top() ^ po; + } + + xag_network::signal run() + { + return decompose( _func, pis ); + } + + private: + xag_network& _ntk; + kitty::dynamic_truth_table _func; + std::vector pis; + std::unordered_map& opt_xags; + xag_dec_params const& _ps; + }; + + xag_network::signal xag_dec( xag_network& ntk, kitty::dynamic_truth_table const& func, std::vector const& children, + std::unordered_map& opt_xags, + xag_dec_params const& ps = {} ) + { + xag_dec_impl impl( ntk, func, children, opt_xags, ps ); + return impl.run(); + } + + +} //end of namespace + +#endif diff --git a/src/networks/aoig/xag_lut_dec.hpp b/src/networks/aoig/xag_lut_dec.hpp new file mode 100644 index 0000000..aa30694 --- /dev/null +++ b/src/networks/aoig/xag_lut_dec.hpp @@ -0,0 +1,45 @@ +/* phyLS: Advanced Logic Synthesis and Optimization tool + * Copyright (C) 2019- Ningbo University, Ningbo, China */ + +/** + * @file xag_lut_dec.hpp + * + * @brief resynthesis using xag decomposition + * + * @author Zhufei + * @since 0.1 + */ + +#ifndef XAG_LUT_DEC_HPP +#define XAG_LUT_DEC_HPP + +#include "xag_dec.hpp" +#include "build_xag_db.hpp" + +namespace mockturtle +{ + + template + class xag_lut_dec_resynthesis + { + public: + explicit xag_lut_dec_resynthesis( std::unordered_map& opt_xags ) + : opt_xags( opt_xags ) + { + } + + template + void operator()( Ntk& ntk, kitty::dynamic_truth_table const& function, LeavesIterator begin, LeavesIterator end, Fn&& fn ) const + { + const auto f = phyLS::xag_dec( ntk, function, std::vector>( begin, end ), opt_xags ); + fn( f ); + } + + private: + std::unordered_map& opt_xags; + }; + + +} + +#endif diff --git a/src/networks/aoig/xag_lut_npn.hpp b/src/networks/aoig/xag_lut_npn.hpp new file mode 100644 index 0000000..fae05fd --- /dev/null +++ b/src/networks/aoig/xag_lut_npn.hpp @@ -0,0 +1,129 @@ +/* mockturtle: C++ logic network library + * Copyright (C) 2018-2019 EPFL + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/*! + \file xag_lut_npn.hpp + \brief Replace with size-optimum XAGs from NPN + + \author Zhufei Chu +*/ + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "build_xag_db.hpp" + +namespace mockturtle +{ + +/*! \brief Resynthesis function based on pre-computed size-optimum xags. + * + * This resynthesis function can be passed to ``node_resynthesis``, + * ``cut_rewriting``, and ``refactoring``. It will produce an xag based on + * pre-computed size-optimum xags with up to at most 4 variables. + * Consequently, the nodes' fan-in sizes in the input network must not exceed + * 4. + * + \verbatim embed:rst + + Example + + .. code-block:: c++ + + const klut_network klut = ...; + xag_npn_lut_resynthesis resyn; + const auto xag = node_resynthesis( klut, resyn ); + \endverbatim + */ +class xag_npn_lut_resynthesis +{ +public: + /*! \brief Default constructor. + * + */ + xag_npn_lut_resynthesis() + { + class2signal = phyLS::get_xag_db( db ); + } + + template + void operator()( xag_network& xag, kitty::dynamic_truth_table const& function, LeavesIterator begin, LeavesIterator end, Fn&& fn ) const + { + assert( function.num_vars() <= 4 ); + const auto fe = kitty::extend_to( function, 4 ); + const auto config = kitty::exact_npn_canonization( fe ); + + auto func_str = "0x" + kitty::to_hex( std::get<0>( config ) ); + const auto it = class2signal.find( func_str ); + assert( it != class2signal.end() ); + + //const auto it = class2signal.find( static_cast( std::get<0>( config )._bits[0] ) ); + + std::vector pis( 4, xag.get_constant( false ) ); + std::copy( begin, end, pis.begin() ); + + std::vector pis_perm( 4 ); + auto perm = std::get<2>( config ); + for ( auto i = 0; i < 4; ++i ) + { + pis_perm[i] = pis[perm[i]]; + } + + const auto& phase = std::get<1>( config ); + for ( auto i = 0; i < 4; ++i ) + { + if ( ( phase >> perm[i] ) & 1 ) + { + pis_perm[i] = !pis_perm[i]; + } + } + + for ( auto const& po : it->second ) + { + topo_view topo{db, po}; + auto f = cleanup_dangling( topo, xag, pis_perm.begin(), pis_perm.end() ).front(); + + if ( !fn( ( ( phase >> 4 ) & 1 ) ? !f : f ) ) + { + return; /* quit */ + } + } + } + +private: + xag_network db; + std::unordered_map> class2signal; +}; + +} /* namespace mockturtle */ diff --git a/src/networks/stp/mg.hpp b/src/networks/stp/mg.hpp new file mode 100644 index 0000000..a1ff85c --- /dev/null +++ b/src/networks/stp/mg.hpp @@ -0,0 +1,592 @@ +/* phyLS: Advanced Logic Synthesis and Optimization tool + * Copyright (C) 2019- Ningbo University, Ningbo, China + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/*! + \file mg.hpp + \brief Matrix logic network implementation + \brief Inspired from aig.hpp in mockturtle + \author Homyoung +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mockturtle { + +/*! \brief Hash function for AIGs (from ABC) */ +template +struct mg_hash { + uint64_t operator()(Node const& n) const { + uint64_t seed = -2011; + seed += n.children[0].index * 7937; + seed += n.children[1].index * 2971; + seed += n.children[0].weight * 911; + seed += n.children[1].weight * 353; + return seed; + } +}; + +using mg_storage = storage, empty_storage_data, + mg_hash>>; + +class mg_network { + public: +#pragma region Types and constructors + static constexpr auto min_fanin_size = 2u; + static constexpr auto max_fanin_size = 2u; + + using base_type = mg_network; + using storage = std::shared_ptr; + using node = uint64_t; + + struct signal { + signal() = default; + + signal(uint64_t index, uint64_t complement) + : complement(complement), index(index) {} + + explicit signal(uint64_t data) : data(data) {} + + signal(mg_storage::node_type::pointer_type const& p) + : complement(p.weight), index(p.index) {} + + union { + struct { + uint64_t complement : 1; + uint64_t index : 63; + }; + uint64_t data; + }; + + signal operator!() const { return signal(data ^ 1); } + + signal operator+() const { return {index, 0}; } + + signal operator-() const { return {index, 1}; } + + signal operator^(bool complement) const { + return signal(data ^ (complement ? 1 : 0)); + } + + bool operator==(signal const& other) const { return data == other.data; } + + bool operator!=(signal const& other) const { return data != other.data; } + + bool operator<(signal const& other) const { return data < other.data; } + + operator mg_storage::node_type::pointer_type() const { + return {index, complement}; + } + +#if __cplusplus > 201703L + bool operator==(mg_storage::node_type::pointer_type const& other) const { + return data == other.data; + } +#endif + }; + + mg_network() + : _storage(std::make_shared()), + _events(std::make_shared()) {} + + mg_network(std::shared_ptr storage) + : _storage(storage), + _events(std::make_shared()) {} + + mg_network clone() const { return {std::make_shared(*_storage)}; } +#pragma endregion + +#pragma region Primary I / O and constants + signal get_constant(bool value) const { + return {0, static_cast(value ? 1 : 0)}; + } + + signal create_pi() { + const auto index = _storage->nodes.size(); + auto& node = _storage->nodes.emplace_back(); + node.children[0].data = node.children[1].data = _storage->inputs.size(); + _storage->inputs.emplace_back(index); + return {index, 0}; + } + + uint32_t create_po(signal const& f) { + /* increase ref-count to children */ + _storage->nodes[f.index].data[0].h1++; + auto const po_index = _storage->outputs.size(); + _storage->outputs.emplace_back(f.index, f.complement); + return static_cast(po_index); + } + + bool is_combinational() const { return true; } + + bool is_constant(node const& n) const { return n == 0; } + + bool is_ci(node const& n) const { + return _storage->nodes[n].children[0].data == + _storage->nodes[n].children[1].data; + } + + bool is_pi(node const& n) const { + return _storage->nodes[n].children[0].data == + _storage->nodes[n].children[1].data && + !is_constant(n); + } + + bool constant_value(node const& n) const { + (void)n; + return false; + } +#pragma endregion + +#pragma region Create unary functions + signal create_buf(signal const& a) { return a; } + signal create_not(signal const& a) { return !a; } +#pragma endregion + +#pragma region Create binary functions + signal create_node(signal a, signal b, uint32_t literal) { + storage::element_type::node_type node; + node.children[0] = a; + node.children[1] = b; + node.data[1].h1 = literal; + + /* structural hashing */ + const auto it = _storage->hash.find(node); + if (it != _storage->hash.end()) return {it->second, 0}; + + const auto index = _storage->nodes.size(); + + if (index >= .9 * _storage->nodes.capacity()) { + _storage->nodes.reserve(static_cast(3.1415f * index)); + _storage->hash.reserve(static_cast(3.1415f * index)); + } + + _storage->nodes.push_back(node); + _storage->hash[node] = index; + + /* increase ref-count to children */ + _storage->nodes[a.index].data[0].h1++; + _storage->nodes[b.index].data[0].h1++; + + for (auto const& fn : _events->on_add) (*fn)(index); + + return {index, 0}; + } + + signal create_0(signal a, signal b) { return get_constant(false); } + signal create_1(signal a, signal b) { + if (a.index > b.index) std::swap(a, b); + if (a.index == b.index) { + return create_not(a); + } else if (a.index == 0) { + return create_not(b); + } else if (a.index == 1) { + return get_constant(false); + } else if (b.index == 0) { + return create_not(a); + } else if (b.index == 1) { + return get_constant(false); + } + return create_node(a, b, 1); + } + signal create_2(signal a, signal b) { return create_node(a, b, 2); } + signal create_not(signal a, signal b) { return create_node(a, b, 3); } + signal create_and(signal a, signal b) { return create_node(a, b, 4); } + signal create_nand(signal a, signal b) { return create_node(a, b, 5); } + signal create_or(signal a, signal b) { return create_node(a, b, 6); } + signal create_7(signal a, signal b) { return create_node(a, b, 7); } + signal create_lt(signal a, signal b) { return create_node(a, b, 8); } + signal create_9(signal a, signal b) { return create_node(a, b, 9); } + signal create_a(signal a, signal b) { return create_node(a, b, 10); } + signal create_le(signal a, signal b) { return create_node(a, b, 11); } + signal create_xor(signal a, signal b) { return create_node(a, b, 12); } + signal create_d(signal a, signal b) { return create_node(a, b, 13); } + signal create_e(signal a, signal b) { return create_node(a, b, 14); } + signal create_f(signal a, signal b) { return get_constant(true); } + +#pragma endregion + +#pragma region Createy ternary functions + +#pragma endregion + +#pragma region Create nary functions + +#pragma endregion + +#pragma region Create arbitrary functions + signal clone_node(mg_network const& other, node const& source, + std::vector const& children) { + (void)other; + (void)source; + assert(children.size() == 2u); + const auto tt = other._storage->nodes[source].data[1].h1; + return create_node(children[0u], children[1u], tt); + } +#pragma endregion + +#pragma region Restructuring + void substitute_node(node const& old_node, signal const& new_signal) { + /* find all parents from old_node */ + for (auto i = 0u; i < _storage->nodes.size(); ++i) { + auto& n = _storage->nodes[i]; + for (auto& child : n.children) { + if (child == old_node) { + std::vector old_children(n.children.size()); + std::transform(n.children.begin(), n.children.end(), + old_children.begin(), [](auto c) { return c.index; }); + child = new_signal; + + // increment fan-out of new node + _storage->nodes[new_signal].data[0].h1++; + + for (auto const& fn : _events->on_modified) { + (*fn)(i, old_children); + } + } + } + } + + /* check outputs */ + for (auto& output : _storage->outputs) { + if (output == old_node) { + output = new_signal; + + // increment fan-out of new node + _storage->nodes[new_signal].data[0].h1++; + } + } + + // reset fan-out of old node + _storage->nodes[old_node].data[0].h1 = 0; + } + + inline bool is_dead(node const& n) const { return false; } +#pragma endregion + +#pragma region Structural properties + auto size() const { return static_cast(_storage->nodes.size()); } + + auto num_cis() const { + return static_cast(_storage->inputs.size()); + } + + auto num_cos() const { + return static_cast(_storage->outputs.size()); + } + + auto num_pis() const { + return static_cast(_storage->inputs.size()); + } + + auto num_pos() const { + return static_cast(_storage->outputs.size()); + } + + auto num_gates() const { + return static_cast(_storage->hash.size()); + } + + uint32_t fanin_size(node const& n) const { + if (is_constant(n) || is_ci(n)) return 0; + return 2; + } + + uint32_t fanout_size(node const& n) const { + return _storage->nodes[n].data[0].h1 & UINT32_C(0x7FFFFFFF); + } + + uint32_t incr_fanout_size(node const& n) const { + return _storage->nodes[n].data[0].h1++ & UINT32_C(0x7FFFFFFF); + } + + uint32_t decr_fanout_size(node const& n) const { + return --_storage->nodes[n].data[0].h1 & UINT32_C(0x7FFFFFFF); + } +#pragma endregion + +#pragma region Functional properties +// kitty::dynamic_truth_table node_function(const node& n) const { +// return _storage->nodes[n].data[1].h1; +// } +#pragma endregion + +#pragma region Nodes and signals + node get_node(signal const& f) const { return f.index; } + + signal make_signal(node const& n) const { return signal(n, 0); } + + bool is_complemented(signal const& f) const { return f.complement; } + + uint32_t node_to_index(node const& n) const { + return static_cast(n); + } + + node index_to_node(uint32_t index) const { return index; } + + node ci_at(uint32_t index) const { + assert(index < _storage->inputs.size()); + return *(_storage->inputs.begin() + index); + } + + signal co_at(uint32_t index) const { + assert(index < _storage->outputs.size()); + return *(_storage->outputs.begin() + index); + } + + node pi_at(uint32_t index) const { + assert(index < _storage->inputs.size()); + return *(_storage->inputs.begin() + index); + } + + signal po_at(uint32_t index) const { + assert(index < _storage->outputs.size()); + return *(_storage->outputs.begin() + index); + } + + uint32_t ci_index(node const& n) const { + assert(_storage->nodes[n].children[0].data == + _storage->nodes[n].children[1].data); + return static_cast(_storage->nodes[n].children[0].data); + } + + uint32_t co_index(signal const& s) const { + uint32_t i = -1; + foreach_co([&](const auto& x, auto index) { + if (x == s) { + i = index; + return false; + } + return true; + }); + return i; + } + + uint32_t pi_index(node const& n) const { + assert(_storage->nodes[n].children[0].data == + _storage->nodes[n].children[1].data); + return static_cast(_storage->nodes[n].children[0].data); + } + + uint32_t po_index(signal const& s) const { + uint32_t i = -1; + foreach_po([&](const auto& x, auto index) { + if (x == s) { + i = index; + return false; + } + return true; + }); + return i; + } +#pragma endregion + +#pragma region Node and signal iterators + template + void foreach_node(Fn&& fn) const { + auto r = range(_storage->nodes.size()); + detail::foreach_element_if( + r.begin(), r.end(), [this](auto n) { return !is_dead(n); }, fn); + } + + template + void foreach_ci(Fn&& fn) const { + detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), + fn); + } + + template + void foreach_co(Fn&& fn) const { + detail::foreach_element(_storage->outputs.begin(), _storage->outputs.end(), + fn); + } + + template + void foreach_pi(Fn&& fn) const { + detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), + fn); + } + + template + void foreach_po(Fn&& fn) const { + detail::foreach_element(_storage->outputs.begin(), _storage->outputs.end(), + fn); + } + + template + void foreach_gate(Fn&& fn) const { + auto r = range( + 1u, _storage->nodes.size()); /* start from 1 to avoid constant */ + detail::foreach_element_if( + r.begin(), r.end(), [this](auto n) { return !is_ci(n) && !is_dead(n); }, + fn); + } + + template + void foreach_fanin(node const& n, Fn&& fn) const { + if (n == 0 || is_ci(n)) return; + + static_assert(detail::is_callable_without_index_v || + detail::is_callable_with_index_v || + detail::is_callable_without_index_v || + detail::is_callable_with_index_v); + + /* we don't use foreach_element here to have better performance */ + if constexpr (detail::is_callable_without_index_v) { + if (!fn(signal{_storage->nodes[n].children[0]})) return; + fn(signal{_storage->nodes[n].children[1]}); + } else if constexpr (detail::is_callable_with_index_v) { + if (!fn(signal{_storage->nodes[n].children[0]}, 0)) return; + fn(signal{_storage->nodes[n].children[1]}, 1); + } else if constexpr (detail::is_callable_without_index_v) { + fn(signal{_storage->nodes[n].children[0]}); + fn(signal{_storage->nodes[n].children[1]}); + } else if constexpr (detail::is_callable_with_index_v) { + fn(signal{_storage->nodes[n].children[0]}, 0); + fn(signal{_storage->nodes[n].children[1]}, 1); + } + } +#pragma endregion + +#pragma region Value simulation + template + iterates_over_t compute(node const& n, Iterator begin, + Iterator end) const { + (void)end; + + assert(n != 0 && !is_ci(n)); + + auto const& c1 = _storage->nodes[n].children[0]; + auto const& c2 = _storage->nodes[n].children[1]; + + auto v1 = *begin++; + auto v2 = *begin++; + + if (c2.index == 0) { + return ~v1 ^ c1.weight; + } else { + return (~v1 ^ c1.weight) || (v2 ^ c2.weight); + } + } + + template + iterates_over_truth_table_t compute(node const& n, Iterator begin, + Iterator end) const { + (void)end; + + assert(n != 0 && !is_ci(n)); + + auto const& c1 = _storage->nodes[n].children[0]; + auto const& c2 = _storage->nodes[n].children[1]; + + auto tt1 = *begin++; + auto tt2 = *begin++; + + if (c2.index == 0) { + return c1.weight ? tt1 : ~tt1; + } else { + return (c1.weight ? tt1 : ~tt1) | (c2.weight ? ~tt2 : tt2); + } + } +#pragma endregion + +#pragma region Custom node values + void clear_values() const { + std::for_each(_storage->nodes.begin(), _storage->nodes.end(), + [](auto& n) { n.data[0].h2 = 0; }); + } + + auto value(node const& n) const { return _storage->nodes[n].data[0].h2; } + + void set_value(node const& n, uint32_t v) const { + _storage->nodes[n].data[0].h2 = v; + } + + auto incr_value(node const& n) const { + return _storage->nodes[n].data[0].h2++; + } + + auto decr_value(node const& n) const { + return --_storage->nodes[n].data[0].h2; + } +#pragma endregion + +#pragma region Visited flags + void clear_visited() const { + std::for_each(_storage->nodes.begin(), _storage->nodes.end(), + [](auto& n) { n.data[1].h1 = 0; }); + } + + auto visited(node const& n) const { return _storage->nodes[n].data[1].h1; } + + void set_visited(node const& n, uint32_t v) const { + _storage->nodes[n].data[1].h1 = v; + } + + uint32_t trav_id() const { return _storage->trav_id; } + + void incr_trav_id() const { ++_storage->trav_id; } +#pragma endregion + +#pragma region General methods + auto& events() const { return *_events; } +#pragma endregion + + public: + std::shared_ptr _storage; + std::shared_ptr> _events; +}; + +} // namespace mockturtle + +namespace std { + +template <> +struct hash { + uint64_t operator()(mockturtle::mg_network::signal const& s) const noexcept { + uint64_t k = s.data; + k ^= k >> 33; + k *= 0xff51afd7ed558ccd; + k ^= k >> 33; + k *= 0xc4ceb9fe1a85ec53; + k ^= k >> 33; + return k; + } +}; /* hash */ + +} // namespace std diff --git a/src/networks/stp/opt_map.txt b/src/networks/stp/opt_map.txt new file mode 100644 index 0000000..1ddc84a --- /dev/null +++ b/src/networks/stp/opt_map.txt @@ -0,0 +1,222 @@ +0x0000 5-1-3-4 6-1-4-5 7-8-4-6 +0x0001 5-14-2-3 6-14-1-4 7-1-5-6 +0x0003 5-14-2-4 6-4-2-3 7-1-5-6 +0x0006 5-6-1-2 6-4-4-5 7-4-3-6 +0x0007 5-14-3-4 6-8-1-2 7-1-5-6 +0x000f 5-14-3-4 6-4-2-3 7-1-5-6 +0x0016 5-14-2-3 6-6-1-5 7-8-2-3 8-14-4-7 9-2-6-8 +0x0017 5-6-2-3 6-14-2-3 7-4-1-5 8-6-6-7 9-1-4-8 +0x0018 5-6-1-3 6-6-2-3 7-4-4-5 8-8-6-7 +0x0019 5-8-1-3 6-6-1-2 7-14-4-5 8-1-6-7 +0x001b 5-8-1-3 6-4-1-2 7-6-5-6 8-1-4-7 +0x001e 5-14-1-2 6-6-3-5 7-4-4-6 +0x001f 5-14-1-2 6-8-3-5 7-1-4-6 +0x003c 5-10-3-4 6-6-2-5 7-4-4-6 +0x003d 5-6-2-3 6-14-1-2 7-4-5-6 8-1-4-7 +0x003f 5-14-3-4 6-14-2-4 7-7-5-6 +0x0069 5-6-1-3 6-6-2-5 7-1-4-6 +0x006b 5-14-2-3 6-8-1-5 7-6-3-6 8-6-2-7 9-1-4-8 +0x006f 5-6-1-2 6-2-3-5 7-1-4-6 +0x007e 5-6-1-3 6-6-1-2 7-14-5-6 8-4-4-7 +0x007f 5-8-1-3 6-8-2-5 7-1-4-6 +0x00ff 5-8-3-4 6-4-3-4 7-1-5-6 +0x0116 5-8-3-4 6-14-2-5 7-14-1-6 8-8-1-2 9-14-4-8 10-14-3-9 11-6-7-10 +0x0117 5-8-3-4 6-14-3-4 7-14-1-5 8-6-2-7 9-6-6-7 10-2-8-9 11-9-2-10 +0x0118 5-14-3-4 6-6-1-5 7-8-3-4 8-14-2-7 9-6-1-8 10-2-6-9 +0x0119 5-8-2-4 6-14-2-4 7-6-1-2 8-14-3-5 9-8-6-8 10-1-7-9 +0x011a 5-8-3-4 6-14-3-4 7-14-2-5 8-4-1-7 9-2-6-8 10-6-1-9 +0x011b 5-14-3-4 6-6-3-4 7-4-1-2 8-4-1-6 9-6-5-8 10-1-7-9 +0x011e 5-8-3-4 6-14-3-4 7-14-1-5 8-14-2-7 9-6-6-8 +0x011f 5-6-3-4 6-14-3-4 7-14-1-2 8-2-5-7 9-13-6-8 +0x012c 5-14-2-3 6-6-4-5 7-2-1-2 8-6-3-7 9-2-6-8 +0x012d 5-6-2-3 6-14-1-2 7-8-4-5 8-2-6-7 9-9-5-8 +0x012f 5-2-1-2 6-2-3-5 7-14-1-2 8-8-4-7 9-1-6-8 +0x013c 5-14-1-3 6-14-3-4 7-8-4-5 8-14-2-7 9-6-6-8 +0x013d 5-14-1-3 6-6-2-3 7-4-4-6 8-14-5-6 9-11-7-8 +0x013e 5-8-2-3 6-14-4-5 7-14-2-3 8-14-1-7 9-6-6-8 +0x013f 5-14-2-3 6-14-1-5 7-8-2-3 8-14-4-7 9-7-6-8 +0x0168 5-6-1-3 6-6-2-5 7-14-1-3 8-6-4-7 9-4-6-8 +0x0169 5-6-1-3 6-6-2-5 7-14-1-2 8-8-4-7 9-1-6-8 +0x016a 5-14-2-3 6-8-4-5 7-8-2-3 8-14-4-7 9-6-1-8 10-4-6-9 +0x016b 5-14-2-3 6-8-2-3 7-6-1-6 8-4-4-7 9-14-5-7 10-11-8-9 +0x016e 5-14-1-2 6-6-4-5 7-6-1-2 8-2-3-7 9-2-6-8 +0x016f 5-14-1-2 6-8-4-5 7-6-1-2 8-2-3-7 9-1-6-8 +0x017e 5-14-2-3 6-14-1-5 7-8-2-3 8-8-1-7 9-14-4-8 10-6-6-9 +0x017f 5-7-1-3 6-2-2-5 7-1-2-3 8-11-1-7 9-7-4-8 10-4-6-9 +0x0180 5-6-1-4 6-6-2-3 7-6-3-4 8-2-5-6 9-8-7-8 +0x0181 5-6-1-3 6-8-1-4 7-6-2-3 8-14-5-6 9-1-7-8 +0x0182 5-6-2-3 6-4-1-2 7-6-1-4 8-14-5-6 9-2-7-8 +0x0183 5-4-1-3 6-8-1-4 7-6-2-3 8-14-5-7 9-1-6-8 +0x0186 5-8-1-2 6-6-3-5 7-14-1-2 8-6-4-7 9-4-6-8 +0x0187 5-8-1-2 6-6-3-5 7-14-1-2 8-8-4-7 9-1-6-8 +0x0189 5-8-2-4 6-2-1-5 7-4-2-3 8-14-6-7 9-9-2-8 +0x018b 5-8-1-4 6-4-2-3 7-4-1-2 8-6-5-7 9-1-6-8 +0x018f 5-14-1-2 6-8-4-5 7-8-1-2 8-2-3-7 9-1-6-8 +0x0196 5-14-1-3 6-6-1-2 7-14-3-4 8-8-4-5 9-14-6-8 10-6-7-9 +0x0197 5-6-2-3 6-14-1-2 7-6-1-5 8-8-4-7 9-2-6-7 10-9-8-9 +0x0198 5-14-1-3 6-6-1-2 7-6-4-5 8-4-6-7 +0x0199 5-14-2-3 6-6-1-2 7-8-4-5 8-1-6-7 +0x019a 5-6-3-4 6-8-1-4 7-4-2-5 8-14-6-7 9-6-1-8 +0x019b 5-14-2-3 6-6-1-2 7-8-4-5 8-6-4-5 9-8-6-8 10-9-7-9 +0x019e 5-14-2-3 6-14-1-5 7-6-1-2 8-8-3-7 9-14-4-8 10-6-6-9 +0x019f 5-14-2-3 6-6-1-2 7-8-3-6 8-14-5-6 9-8-4-8 10-1-7-9 +0x01a8 5-14-2-3 6-6-1-4 7-6-1-5 8-2-6-7 +0x01a9 5-14-2-3 6-8-1-4 7-2-5-6 8-9-1-7 +0x01aa 5-14-2-3 6-6-1-4 7-4-1-5 8-2-6-7 +0x01ab 5-2-1-4 6-14-1-3 7-14-2-6 8-11-5-7 +0x01ac 5-14-2-3 6-14-3-4 7-8-1-4 8-4-1-6 9-2-5-7 10-6-8-9 +0x01ad 5-14-2-3 6-14-1-2 7-4-1-3 8-4-4-5 9-2-6-8 10-1-7-9 +0x01ae 5-14-1-2 6-4-1-3 7-6-4-5 8-4-6-7 +0x01af 5-14-1-2 6-4-1-3 7-8-4-5 8-1-6-7 +0x01bc 5-14-2-3 6-6-2-3 7-6-1-5 8-6-4-5 9-4-6-7 10-2-8-9 +0x01bd 5-6-1-3 6-14-2-3 7-8-4-6 8-6-2-3 9-2-5-8 10-1-7-9 +0x01be 5-8-3-4 6-6-2-3 7-14-1-5 8-14-6-7 9-6-4-8 +0x01bf 5-6-2-3 6-6-3-4 7-14-1-5 8-8-6-7 9-9-3-8 +0x01e8 5-14-2-3 6-8-2-3 7-6-1-5 8-6-4-5 9-4-6-7 10-2-8-9 +0x01e9 5-8-1-3 6-14-1-3 7-14-2-5 8-8-4-7 9-2-6-8 10-9-7-9 +0x01ea 5-14-1-3 6-14-1-2 7-6-4-6 8-6-5-6 9-2-7-8 +0x01eb 5-14-1-3 6-14-1-2 7-8-4-5 8-2-6-7 9-9-5-8 +0x01ee 5-8-3-4 6-14-1-2 7-14-5-6 8-6-4-7 +0x01ef 5-6-3-4 6-14-1-2 7-2-5-6 8-9-4-7 +0x01fe 5-14-2-3 6-14-1-5 7-6-4-6 +0x033c 5-14-3-4 6-8-3-4 7-14-2-6 8-6-5-7 +0x033d 5-14-2-3 6-8-2-3 7-14-1-4 8-14-4-6 9-4-5-7 10-9-8-9 +0x033f 5-6-3-4 6-14-3-4 7-4-2-5 8-13-6-7 +0x0356 5-14-2-3 6-14-1-4 7-6-5-6 +0x0357 5-14-1-4 6-14-2-3 7-7-5-6 +0x0358 5-14-1-4 6-14-2-3 7-14-3-4 8-8-5-6 9-6-7-8 +0x0359 5-6-2-4 6-14-1-4 7-4-3-5 8-9-6-7 +0x035a 5-14-1-4 6-8-2-4 7-14-3-6 8-6-5-7 +0x035b 5-6-1-3 6-14-2-3 7-4-4-5 8-13-6-7 +0x035e 5-6-1-3 6-4-4-5 7-6-2-4 8-4-3-7 9-14-6-8 +0x035f 5-14-2-3 6-8-1-3 7-8-4-5 8-1-6-7 +0x0368 5-8-2-3 6-14-2-3 7-14-4-5 8-14-1-4 9-8-6-8 10-6-7-9 +0x0369 5-6-1-3 6-4-4-5 7-8-3-4 8-14-2-7 9-9-6-8 +0x036a 5-6-2-3 6-6-2-4 7-2-1-4 8-4-5-6 9-6-7-8 +0x036b 5-14-2-3 6-8-2-3 7-6-1-6 8-4-4-7 9-13-5-8 +0x036c 5-8-1-3 6-14-4-5 7-8-3-4 8-14-2-7 9-6-6-8 +0x036d 5-2-1-4 6-2-2-3 7-2-2-4 8-14-5-6 9-6-3-8 10-9-7-9 +0x036e 5-6-2-4 6-4-3-5 7-6-1-2 8-4-4-7 9-14-6-8 +0x036f 5-8-1-3 6-6-2-5 7-4-4-6 8-14-2-3 9-11-7-8 +0x037c 5-8-1-3 6-14-2-3 7-8-2-5 8-14-4-7 9-6-6-8 +0x037d 5-14-2-4 6-8-2-4 7-6-3-5 8-14-1-4 9-4-7-8 10-1-6-9 +0x037e 5-6-2-3 6-14-2-3 7-2-1-5 8-14-4-7 9-6-6-8 +0x03c0 5-6-3-4 6-6-2-4 7-8-5-6 +0x03c1 5-6-3-4 6-14-1-2 7-6-2-3 8-4-5-6 9-1-7-8 +0x03c3 5-8-3-4 6-2-2-5 7-9-3-6 +0x03c5 5-2-1-4 6-14-3-5 7-6-3-4 8-8-2-7 9-9-6-8 +0x03c6 5-8-3-4 6-14-2-5 7-2-1-3 8-14-4-7 9-6-6-8 +0x03c7 5-2-1-3 6-14-2-3 7-2-2-5 8-4-4-7 9-13-6-8 +0x03cf 5-4-2-3 6-8-2-4 7-9-5-6 +0x03d4 5-6-2-3 6-8-1-5 7-14-2-3 8-6-4-7 9-4-6-8 +0x03d5 5-6-2-4 6-6-3-4 7-14-1-4 8-8-5-6 9-13-7-8 +0x03d6 5-8-2-3 6-14-2-3 7-2-1-5 8-14-4-7 9-6-6-8 +0x03d7 5-8-2-3 6-14-2-3 7-2-1-5 8-14-4-7 9-7-6-8 +0x03d8 5-14-1-4 6-8-2-5 7-2-1-4 8-2-3-7 9-14-6-8 10-6-4-9 +0x03d9 5-6-2-4 6-2-1-4 7-8-3-5 8-14-6-7 9-9-2-8 +0x03db 5-14-1-3 6-2-1-2 7-14-2-3 8-14-4-6 9-2-5-8 10-13-7-9 +0x03dc 5-2-1-4 6-2-3-5 7-14-2-6 8-6-4-7 +0x03dd 5-14-1-4 6-8-3-4 7-4-2-5 8-4-6-7 9-9-4-8 +0x03de 5-2-1-2 6-14-2-3 7-14-4-5 8-6-6-7 +0x03fc 5-4-2-3 6-6-2-5 7-6-4-6 +0x0660 5-6-3-4 6-6-1-2 7-8-5-6 +0x0661 5-6-3-4 6-14-1-4 7-6-1-2 8-4-5-6 9-14-7-8 10-9-5-9 +0x0662 5-6-3-4 6-14-2-3 7-6-1-2 8-4-5-6 9-2-7-8 +0x0663 5-8-3-4 6-14-3-4 7-4-1-6 8-6-2-7 9-1-5-8 +0x0666 5-8-3-4 6-6-1-2 7-4-5-6 +0x0667 5-14-2-4 6-8-3-4 7-6-1-2 8-14-3-5 9-4-7-8 10-1-6-9 +0x0669 5-7-3-4 6-1-3-4 7-9-1-6 8-6-2-7 9-2-5-8 +0x066b 5-14-3-4 6-8-3-4 7-2-1-2 8-4-1-2 9-2-5-7 10-6-8-9 11-1-6-10 +0x066f 5-6-3-4 6-6-1-2 7-14-3-4 8-8-5-6 9-9-7-8 +0x0672 5-8-3-4 6-14-1-4 7-14-1-3 8-14-2-5 9-8-6-8 10-6-7-9 +0x0673 5-6-3-4 6-6-1-2 7-14-2-4 8-8-5-6 9-13-7-8 +0x0676 5-4-1-3 6-6-1-2 7-8-3-4 8-14-5-6 9-4-7-8 +0x0678 5-6-2-3 6-6-1-2 7-4-3-6 8-14-5-6 9-4-4-8 10-6-7-9 +0x0679 5-8-2-3 6-6-1-2 7-4-3-6 8-2-5-6 9-14-4-8 10-9-7-9 +0x067a 5-6-1-3 6-6-3-4 7-6-1-2 8-4-4-5 9-8-6-7 10-14-8-9 +0x067b 5-2-1-4 6-6-3-5 7-2-2-6 8-2-1-3 9-2-4-8 10-9-7-9 +0x067e 5-6-2-3 6-8-3-4 7-6-1-2 8-4-4-5 9-4-6-7 10-14-8-9 +0x0690 5-6-2-4 6-6-3-4 7-6-1-5 8-2-6-7 +0x0691 5-14-1-4 6-4-3-5 7-6-1-2 8-6-4-7 9-6-6-7 10-1-8-9 +0x0693 5-4-1-4 6-8-1-3 7-6-5-6 8-6-2-7 9-8-3-4 10-1-8-9 +0x0696 5-6-1-2 6-2-4-5 7-2-3-6 8-6-5-7 +0x0697 5-2-2-3 6-6-1-2 7-14-4-5 8-6-3-7 9-8-6-8 10-9-7-9 +0x069f 5-6-3-4 6-6-1-2 7-8-5-6 8-9-4-7 +0x06b0 5-2-1-4 6-6-3-4 7-2-2-5 8-14-1-3 9-6-7-8 10-8-6-9 +0x06b1 5-6-1-3 6-8-2-5 7-14-1-2 8-4-3-7 9-6-4-8 10-1-6-9 +0x06b2 5-6-2-4 6-6-1-5 7-14-3-6 8-8-5-6 9-14-4-8 10-6-7-9 +0x06b3 5-2-1-3 6-2-4-5 7-14-1-4 8-8-3-7 9-2-2-8 10-9-6-9 +0x06b4 5-14-2-4 6-8-1-5 7-6-2-6 8-2-4-7 9-2-3-8 10-6-7-9 +0x06b5 5-2-1-3 6-2-2-3 7-4-1-2 8-14-4-7 9-4-6-8 10-9-5-9 +0x06b6 5-13-3-4 6-6-1-2 7-4-1-2 8-4-3-6 9-1-5-7 10-14-8-9 +0x06b7 5-2-1-3 6-2-2-3 7-4-1-2 8-14-4-7 9-4-5-8 10-9-6-9 +0x06b9 5-6-1-2 6-14-1-4 7-8-3-6 8-2-5-7 9-9-4-8 +0x06bd 5-4-1-2 6-14-4-5 7-6-1-2 8-4-3-7 9-9-6-8 +0x06f0 5-6-1-2 6-6-3-4 7-14-3-5 8-8-6-7 +0x06f1 5-2-1-4 6-6-1-2 7-14-5-6 8-4-3-7 9-9-4-8 +0x06f2 5-2-3-4 6-14-1-4 7-8-2-6 8-6-1-7 9-4-3-8 10-14-5-9 +0x06f6 5-2-3-4 6-6-1-2 7-4-3-6 8-14-5-7 +0x06f9 5-6-1-2 6-4-3-5 7-9-4-6 +0x0776 5-6-3-4 6-14-1-2 7-8-1-2 8-4-4-6 9-14-5-8 10-4-7-9 +0x0778 5-8-3-4 6-8-1-2 7-14-3-4 8-14-5-6 9-6-7-8 +0x0779 5-14-3-4 6-8-1-2 7-6-5-6 8-8-3-4 9-14-1-2 10-4-7-9 11-1-8-10 +0x077a 5-14-3-4 6-8-3-4 7-6-1-5 8-2-1-2 9-14-7-8 10-4-6-9 +0x077e 5-14-3-4 6-8-3-4 7-6-1-2 8-6-2-5 9-14-7-8 10-4-6-9 +0x07b0 5-6-1-4 6-2-2-5 7-6-3-4 8-4-6-7 +0x07b1 5-6-1-4 6-14-1-4 7-6-3-4 8-2-2-5 9-2-6-7 10-1-8-9 +0x07b4 5-2-2-3 6-4-1-2 7-2-4-5 8-14-6-7 9-6-3-8 +0x07b5 5-14-3-4 6-6-1-3 7-8-3-4 8-4-2-5 9-2-6-8 10-1-7-9 +0x07b6 5-4-1-2 6-14-4-5 7-6-2-4 8-2-1-7 9-14-3-8 10-6-6-9 +0x07bc 5-8-1-2 6-14-3-5 7-4-1-2 8-14-4-7 9-6-6-8 +0x07e0 5-6-2-4 6-6-1-2 7-6-3-4 8-14-5-6 9-8-7-8 +0x07e1 5-14-1-2 6-8-1-2 7-4-4-5 8-2-6-7 9-14-3-8 10-9-7-9 +0x07e2 5-6-2-4 6-2-1-5 7-14-2-4 8-8-3-7 9-14-6-8 10-6-4-9 +0x07e3 5-4-1-4 6-2-2-5 7-6-4-6 8-2-1-7 9-2-3-8 10-9-6-9 +0x07e6 5-8-1-2 6-14-3-5 7-14-1-2 8-6-3-7 9-14-4-8 10-6-6-9 +0x07e9 5-8-1-2 6-14-3-5 7-14-1-2 8-4-4-7 9-9-6-8 +0x07f0 5-2-1-3 6-8-2-5 7-2-4-6 8-6-3-7 +0x07f1 5-6-1-4 6-6-1-2 7-14-5-6 8-4-3-7 9-9-4-8 +0x07f2 5-6-2-4 6-2-1-5 7-14-3-6 8-6-4-7 +0x07f8 5-8-1-2 6-14-3-5 7-6-4-6 +0x0ff0 5-6-2-4 6-6-2-3 7-6-5-6 +0x1668 5-6-2-3 6-6-1-2 7-6-1-4 8-14-5-6 9-4-7-8 10-6-5-9 +0x1669 5-8-2-4 6-8-3-5 7-2-1-6 8-6-4-7 9-6-2-8 10-9-3-9 +0x166a 5-8-2-3 6-8-4-5 7-14-1-6 8-6-2-3 9-8-4-8 10-6-5-9 11-6-7-10 +0x166b 5-6-2-3 6-6-3-4 7-6-1-2 8-2-1-5 9-14-6-8 10-9-7-9 +0x166e 5-6-3-4 6-6-1-2 7-8-3-4 8-2-2-5 9-14-6-8 10-6-7-9 +0x167e 5-6-1-3 6-6-2-5 7-2-4-6 8-6-2-3 9-14-5-8 10-4-7-9 +0x1681 5-6-1-3 6-2-2-4 7-8-1-3 8-4-2-4 9-14-5-6 10-14-7-8 11-9-9-10 +0x1683 5-6-1-4 6-6-2-3 7-4-1-4 8-2-3-5 9-14-6-8 10-9-7-9 +0x1686 5-6-2-4 6-6-1-2 7-2-3-5 8-14-6-7 9-6-3-8 +0x1687 5-6-2-4 6-4-3-4 7-6-1-2 8-14-5-6 9-4-7-8 10-9-3-9 +0x1689 5-6-1-4 6-2-3-5 7-8-3-4 8-6-2-7 9-14-6-8 10-9-5-9 +0x168b 5-8-2-3 6-2-1-4 7-4-1-4 8-2-2-6 9-14-5-7 10-6-3-9 11-9-8-10 +0x168e 5-6-1-2 6-2-2-5 7-2-3-6 8-14-2-3 9-4-4-8 10-14-5-9 11-6-7-10 +0x1696 5-8-2-3 6-6-2-3 7-8-4-5 8-2-1-7 9-6-6-8 +0x1697 5-6-3-4 6-6-2-3 7-6-1-3 8-14-5-6 9-4-7-8 10-9-2-9 +0x1698 5-14-1-2 6-8-1-2 7-4-4-5 8-2-3-7 9-2-5-7 10-14-6-8 11-6-9-10 +0x1699 5-8-1-2 6-2-3-5 7-2-4-6 8-6-2-7 9-9-1-8 +0x169a 5-8-2-4 6-8-3-5 7-14-1-6 8-4-2-3 9-6-5-8 10-6-7-9 +0x169b 5-6-3-4 6-2-1-5 7-14-2-6 8-6-4-7 9-8-3-4 10-14-1-9 11-9-8-10 +0x169e 5-6-3-4 6-6-1-2 7-2-1-5 8-14-6-7 9-6-3-8 +0x16a9 5-8-3-4 6-8-2-5 7-14-1-6 8-14-2-3 9-6-7-8 10-9-4-9 +0x16ac 5-8-1-3 6-14-2-5 7-4-1-6 8-14-4-7 9-14-1-3 10-8-8-9 11-6-6-10 +0x16ad 5-8-2-4 6-14-1-5 7-8-1-2 8-14-3-7 9-6-4-8 10-9-6-9 +0x16bc 5-8-1-3 6-8-1-4 7-2-2-5 8-6-3-7 9-6-6-8 +0x16e9 5-14-2-3 6-8-2-3 7-14-1-6 8-6-4-7 9-9-5-8 +0x177e 5-6-3-4 6-6-1-2 7-8-3-4 8-6-2-5 9-14-6-8 10-6-7-9 +0x178e 5-6-2-4 6-6-1-2 7-6-3-5 8-2-6-7 9-6-5-8 +0x1796 5-6-2-3 6-6-1-2 7-2-4-5 8-14-6-7 9-6-3-8 +0x1798 5-8-1-2 6-14-1-2 7-6-4-6 8-2-3-7 9-14-5-8 10-6-4-9 +0x179a 5-4-3-4 6-8-1-4 7-4-2-3 8-14-1-5 9-8-2-6 10-2-8-9 11-6-7-10 +0x17ac 5-8-1-3 6-14-2-5 7-6-3-4 8-4-1-7 9-2-6-8 10-6-4-9 +0x17e8 5-6-2-3 6-14-2-3 7-4-1-5 8-6-6-7 9-6-4-8 +0x18e7 5-6-2-3 6-6-1-3 7-8-5-6 8-9-4-7 +0x19e1 5-6-3-4 6-8-1-2 7-14-1-2 8-14-3-6 9-8-5-8 10-9-7-9 +0x19e3 5-8-2-3 6-14-3-4 7-2-1-5 8-2-6-7 9-6-2-8 10-9-4-9 +0x19e6 5-8-2-3 6-6-2-4 7-2-1-5 8-6-6-7 +0x1bd8 5-6-2-3 6-6-1-3 7-6-1-4 8-4-5-7 9-6-6-8 +0x1be4 5-2-1-3 6-1-1-2 7-1-5-6 8-6-4-7 +0x1ee1 5-14-1-2 6-6-4-5 7-9-3-6 +0x3cc3 5-6-1-4 6-6-1-3 7-6-2-5 8-9-6-7 +0x6996 5-6-1-4 6-6-2-5 7-6-3-6 diff --git a/src/networks/stp/opt_stp.txt b/src/networks/stp/opt_stp.txt new file mode 100644 index 0000000..febfa3d --- /dev/null +++ b/src/networks/stp/opt_stp.txt @@ -0,0 +1,222 @@ +0x0000 5-2-3-4 6-2-3-4 7-2-5-6 +0x0001 5-14-1-3 6-1-2-4 7-4-5-6 +0x0003 5-12-2-4 6-1-3-5 7-12-2-6 +0x0006 5-14-3-4 6-6-1-2 7-4-5-6 +0x0007 5-14-3-4 6-7-1-2 7-4-5-6 +0x000f 5-3-2-4 6-13-3-4 7-10-5-6 +0x0016 5-6-1-3 6-7-1-2 7-9-2-5 8-1-4-7 9-8-6-8 +0x0017 5-9-1-2 6-7-1-2 7-2-3-5 8-1-4-7 9-8-6-8 +0x0018 5-9-1-3 6-9-1-2 7-1-4-5 8-8-6-7 +0x0019 5-8-2-3 6-9-1-2 7-1-4-5 8-8-6-7 +0x001b 5-8-1-3 6-11-1-2 7-1-4-5 8-8-6-7 +0x001e 5-14-1-2 6-6-3-5 7-4-4-6 +0x001f 5-14-1-2 6-7-3-5 7-4-4-6 +0x003c 5-10-3-4 6-3-2-5 7-9-4-6 +0x003d 5-6-2-3 6-1-1-3 7-1-5-6 8-1-4-7 +0x003f 5-10-3-4 6-3-2-5 7-13-4-6 +0x0069 5-9-2-3 6-6-1-5 7-4-4-6 +0x006b 5-9-1-3 6-2-1-2 7-6-2-5 8-1-6-7 9-1-4-8 +0x006f 5-9-1-2 6-7-3-5 7-4-4-6 +0x007e 5-6-1-3 6-6-2-3 7-1-5-6 8-1-4-7 +0x007f 5-8-2-3 6-7-1-5 7-4-4-6 +0x00ff 5-1-1-3 6-1-1-2 7-1-5-6 8-5-4-7 +0x0116 5-1-3-4 6-7-1-2 7-6-2-5 8-6-1-7 9-7-3-4 10-7-6-9 11-1-8-10 +0x0117 5-6-1-4 6-7-2-3 7-4-3-5 8-4-2-7 9-1-1-4 10-7-6-9 11-9-8-10 +0x0118 5-7-3-4 6-1-3-4 7-9-1-2 8-6-2-6 9-7-5-7 10-1-8-9 +0x0119 5-1-3-4 6-7-3-4 7-9-1-2 8-2-1-5 9-7-6-7 10-1-8-9 +0x011a 5-7-3-4 6-1-3-4 7-11-1-2 8-6-1-6 9-7-5-7 10-1-8-9 +0x011b 5-1-3-4 6-11-1-2 7-7-3-4 8-2-1-5 9-7-6-7 10-1-8-9 +0x011e 5-7-3-4 6-1-1-2 7-1-3-4 8-7-5-6 9-9-7-8 +0x011f 5-7-3-4 6-1-1-2 7-1-3-4 8-7-5-6 9-11-7-8 +0x012c 5-6-3-4 6-6-2-5 7-14-1-2 8-6-4-7 9-8-6-8 +0x012d 5-1-2-3 6-13-4-5 7-13-1-2 8-6-3-7 9-8-6-8 +0x012f 5-1-1-2 6-13-4-5 7-13-1-2 8-7-3-7 9-8-6-8 +0x013c 5-1-1-2 6-1-2-4 7-13-4-5 8-4-3-7 9-6-6-8 +0x013d 5-1-1-2 6-1-2-4 7-9-4-5 8-4-3-7 9-6-6-8 +0x013e 5-9-2-3 6-7-2-3 7-4-1-5 8-6-4-7 9-2-6-8 +0x013f 5-1-1-3 6-7-2-3 7-11-2-5 8-7-4-7 9-8-6-8 +0x0168 5-6-1-3 6-9-2-5 7-14-1-3 8-6-4-7 9-8-6-8 +0x0169 5-1-2-3 6-13-4-5 7-9-1-2 8-6-3-7 9-8-6-8 +0x016a 5-1-2-3 6-6-1-4 7-7-2-3 8-2-4-5 9-6-6-7 10-1-8-9 +0x016b 5-1-2-3 6-4-1-5 7-7-2-3 8-9-1-7 9-4-4-8 10-6-6-9 +0x016e 5-1-1-2 6-9-4-5 7-9-1-2 8-7-3-7 9-8-6-8 +0x016f 5-1-1-2 6-13-4-5 7-9-1-2 8-7-3-7 9-8-6-8 +0x017e 5-7-1-4 6-6-2-3 7-6-1-3 8-1-6-7 9-7-5-8 10-6-4-9 +0x017f 5-1-1-3 6-4-2-5 7-7-2-3 8-13-1-7 9-4-4-8 10-14-6-9 +0x0180 5-2-3-4 6-6-1-2 7-6-3-4 8-6-2-5 9-4-6-7 10-4-8-9 +0x0181 5-8-2-4 6-9-1-3 7-6-1-2 8-4-5-6 9-4-7-8 +0x0182 5-6-1-4 6-4-1-2 7-9-2-3 8-7-5-7 9-1-6-8 +0x0183 5-9-2-4 6-6-2-3 7-2-1-5 8-6-3-7 9-1-6-8 +0x0186 5-7-1-2 6-9-3-5 7-14-1-2 8-6-4-7 9-4-6-8 +0x0187 5-1-1-2 6-13-4-5 7-8-1-2 8-6-3-7 9-2-6-8 +0x0189 5-8-1-4 6-4-1-3 7-2-2-5 8-1-6-7 9-6-1-8 +0x018b 5-11-2-3 6-7-1-4 7-4-1-2 8-7-5-6 9-1-7-8 +0x018f 5-7-1-2 6-7-3-5 7-14-1-2 8-7-4-7 9-8-6-8 +0x0196 5-1-2-3 6-6-1-2 7-9-3-4 8-2-4-5 9-6-6-7 10-1-8-9 +0x0197 5-1-1-3 6-6-2-3 7-6-4-5 8-14-6-7 9-1-1-4 10-9-8-9 +0x0198 5-14-1-3 6-6-1-2 7-6-4-5 8-4-6-7 +0x0199 5-14-2-3 6-6-1-2 7-7-4-5 8-4-6-7 +0x019a 5-6-3-4 6-7-1-4 7-11-2-5 8-9-1-7 9-8-6-8 +0x019b 5-6-2-4 6-6-1-4 7-11-2-3 8-1-1-5 9-7-6-7 10-9-8-9 +0x019e 5-1-1-3 6-4-2-5 7-6-1-2 8-8-3-7 9-1-4-8 10-6-6-9 +0x019f 5-1-2-3 6-6-1-2 7-9-3-4 8-2-4-5 9-2-6-7 10-1-8-9 +0x01a8 5-14-2-3 6-9-1-4 7-6-4-5 8-4-6-7 +0x01a9 5-14-2-3 6-7-1-4 7-6-1-5 8-2-6-7 +0x01aa 5-14-2-3 6-9-1-4 7-7-4-5 8-4-6-7 +0x01ab 5-14-1-3 6-2-1-4 7-1-2-5 8-6-6-7 +0x01ac 5-4-1-3 6-7-1-4 7-1-2-3 8-1-4-5 9-7-6-7 10-9-8-9 +0x01ad 5-4-1-3 6-6-1-4 7-1-2-3 8-1-4-5 9-7-6-7 10-9-8-9 +0x01ae 5-14-1-2 6-11-1-3 7-6-4-5 8-8-6-7 +0x01af 5-14-1-2 6-11-1-3 7-7-4-5 8-8-6-7 +0x01bc 5-1-2-3 6-6-2-3 7-6-4-5 8-9-1-4 9-4-6-8 10-1-7-9 +0x01bd 5-14-2-3 6-6-1-2 7-6-1-3 8-8-4-5 9-8-6-7 10-1-8-9 +0x01be 5-6-2-3 6-7-2-4 7-14-1-5 8-6-4-7 9-8-6-8 +0x01bf 5-6-3-4 6-9-2-3 7-4-1-5 8-7-6-7 9-6-4-8 +0x01e8 5-1-2-3 6-6-1-4 7-7-2-3 8-6-4-5 9-4-6-7 10-1-8-9 +0x01e9 5-14-2-3 6-8-2-3 7-6-1-5 8-8-4-5 9-4-6-7 10-1-8-9 +0x01ea 5-1-1-3 6-9-4-5 7-9-2-3 8-1-1-7 9-2-6-8 +0x01eb 5-9-2-3 6-1-1-5 7-14-1-2 8-7-4-7 9-4-6-8 +0x01ee 5-14-1-2 6-7-3-4 7-6-4-5 8-8-6-7 +0x01ef 5-9-3-4 6-1-1-2 7-1-5-6 8-9-3-7 +0x01fe 5-14-2-3 6-1-1-5 7-9-4-6 +0x033c 5-8-2-3 6-6-2-3 7-2-4-5 8-6-6-7 +0x033d 5-6-2-3 6-13-1-4 7-1-2-3 8-4-4-5 9-7-6-7 10-9-8-9 +0x033f 5-6-3-4 6-14-3-4 7-4-2-5 8-13-6-7 +0x0356 5-14-1-4 6-1-2-3 7-9-5-6 +0x0357 5-14-1-4 6-1-2-3 7-13-5-6 +0x0358 5-1-2-3 6-1-1-4 7-1-3-4 8-1-5-6 9-9-7-8 +0x0359 5-9-1-3 6-1-2-3 7-1-4-5 8-6-6-7 +0x035a 5-8-2-4 6-1-1-4 7-1-3-5 8-6-6-7 +0x035b 5-9-1-3 6-1-2-3 7-1-4-5 8-14-6-7 +0x035e 5-13-1-4 6-13-2-3 7-6-3-4 8-7-5-6 9-6-7-8 +0x035f 5-8-2-4 6-1-1-4 7-1-3-5 8-14-6-7 +0x0368 5-1-2-3 6-9-2-3 7-13-1-4 8-6-4-5 9-9-6-7 10-4-8-9 +0x0369 5-9-2-3 6-13-1-4 7-7-2-4 8-9-5-6 9-8-7-8 +0x036a 5-6-2-3 6-1-2-3 7-9-1-5 8-4-4-7 9-6-6-8 +0x036b 5-6-1-3 6-1-2-3 7-9-2-5 8-4-4-7 9-14-6-8 +0x036c 5-6-2-4 6-7-1-3 7-7-3-4 8-6-5-6 9-2-7-8 +0x036d 5-2-2-4 6-13-1-4 7-13-2-3 8-6-3-5 9-7-6-7 10-9-8-9 +0x036e 5-6-2-4 6-4-3-5 7-9-1-2 8-1-4-7 9-14-6-8 +0x036f 5-7-1-3 6-1-2-3 7-9-2-5 8-4-4-7 9-6-6-8 +0x037c 5-7-2-3 6-1-2-3 7-13-1-5 8-4-4-7 9-6-6-8 +0x037d 5-1-2-3 6-13-1-4 7-6-2-3 8-2-4-5 9-1-6-7 10-1-8-9 +0x037e 5-6-2-3 6-1-2-3 7-13-1-5 8-4-4-7 9-6-6-8 +0x03c0 5-6-3-4 6-6-2-4 7-8-5-6 +0x03c1 5-6-2-3 6-6-3-4 7-1-1-2 8-1-6-7 9-1-5-8 +0x03c3 5-1-1-3 6-8-2-4 7-1-5-6 8-7-3-7 9-6-2-8 +0x03c5 5-2-1-3 6-1-2-3 7-9-2-5 8-1-4-7 9-6-6-8 +0x03c6 5-1-1-4 6-7-2-4 7-14-3-5 8-6-2-7 9-2-6-8 +0x03c7 5-11-1-2 6-8-2-4 7-4-3-5 8-1-6-7 9-9-2-8 +0x03cf 5-12-1-4 6-9-3-4 7-1-2-6 8-6-5-7 9-3-1-8 +0x03d4 5-6-2-3 6-1-2-3 7-8-1-5 8-1-4-7 9-6-6-8 +0x03d5 5-9-2-3 6-6-3-4 7-8-5-6 8-1-1-4 9-14-7-8 +0x03d6 5-7-2-3 6-1-2-3 7-8-1-5 8-1-4-7 9-6-6-8 +0x03d7 5-1-1-4 6-7-2-4 7-9-2-3 8-1-5-7 9-2-6-8 +0x03d8 5-7-3-4 6-4-2-5 7-9-2-3 8-14-1-7 9-4-4-8 10-6-6-9 +0x03d9 5-6-2-4 6-13-1-4 7-7-3-5 8-7-6-7 9-9-2-8 +0x03db 5-6-2-4 6-2-1-4 7-2-3-5 8-9-2-3 9-1-6-8 10-9-7-9 +0x03dc 5-13-1-4 6-8-3-5 7-1-2-6 8-9-4-7 +0x03dd 5-14-1-4 6-7-3-4 7-4-2-5 8-7-6-7 9-6-4-8 +0x03de 5-13-1-2 6-1-2-3 7-4-4-5 8-6-6-7 +0x03fc 5-1-2-3 6-9-4-5 7-3-1-6 8-3-6-7 +0x0660 5-9-3-4 6-6-1-2 7-4-5-6 +0x0661 5-6-3-4 6-14-1-4 7-6-1-2 8-4-5-6 9-14-7-8 10-9-5-9 +0x0662 5-6-3-4 6-1-2-4 7-14-5-6 8-6-1-2 9-8-7-8 +0x0663 5-9-3-4 6-7-3-4 7-14-1-5 8-9-2-7 9-2-6-8 +0x0666 5-8-3-4 6-6-1-2 7-4-5-6 +0x0667 5-1-3-4 6-7-3-4 7-6-1-2 8-4-1-5 9-7-6-7 10-11-8-9 +0x0669 5-7-3-4 6-6-1-2 7-1-3-4 8-7-5-6 9-9-7-8 +0x066b 5-6-3-4 6-6-1-2 7-4-1-2 8-14-3-4 9-8-5-6 10-14-7-8 11-9-9-10 +0x066f 5-7-3-4 6-6-1-2 7-1-3-4 8-7-5-6 9-11-7-8 +0x0672 5-7-3-4 6-4-2-5 7-2-2-4 8-9-3-7 9-4-1-8 10-6-6-9 +0x0673 5-6-3-4 6-6-1-2 7-1-2-4 8-7-5-6 9-11-7-8 +0x0676 5-4-2-3 6-1-1-5 7-9-2-6 8-7-3-4 9-8-7-8 +0x0678 5-6-1-2 6-7-1-2 7-9-3-4 8-2-4-5 9-6-6-7 10-4-8-9 +0x0679 5-2-1-4 6-13-1-3 7-2-3-5 8-13-2-7 9-9-6-8 10-6-4-9 +0x067a 5-6-1-3 6-6-1-2 7-6-3-4 8-4-4-5 9-7-6-7 10-11-8-9 +0x067b 5-6-1-3 6-2-2-5 7-9-2-3 8-7-1-7 9-7-4-8 10-6-6-9 +0x067e 5-6-2-3 6-7-3-4 7-6-1-2 8-4-4-5 9-7-6-7 10-11-8-9 +0x0690 5-9-1-3 6-6-3-4 7-6-2-5 8-2-6-7 +0x0691 5-6-1-4 6-1-1-2 7-6-2-5 8-9-3-4 9-4-6-8 10-1-7-9 +0x0693 5-1-3-4 6-8-3-4 7-14-1-5 8-6-2-7 9-1-6-8 10-9-3-9 +0x0696 5-9-2-3 6-7-3-4 7-6-1-5 8-2-6-7 +0x0697 5-9-3-4 6-6-1-2 7-2-1-3 8-13-5-7 9-4-6-8 10-9-3-9 +0x069f 5-9-3-4 6-6-1-2 7-1-5-6 8-9-3-7 +0x06b0 5-1-2-4 6-2-1-5 7-6-4-6 8-9-2-7 9-6-3-4 10-8-8-9 +0x06b1 5-6-1-4 6-2-2-5 7-1-1-2 8-14-3-7 9-6-4-8 10-4-6-9 +0x06b2 5-2-2-4 6-9-1-2 7-6-3-5 8-14-6-7 9-2-3-4 10-9-8-9 +0x06b3 5-2-1-3 6-2-4-5 7-1-1-4 8-2-3-7 9-13-2-8 10-6-6-9 +0x06b4 5-1-2-4 6-8-3-4 7-2-1-5 8-6-2-7 9-1-6-8 10-9-3-9 +0x06b5 5-6-3-4 6-8-1-3 7-8-2-5 8-9-1-7 9-1-6-8 10-9-4-9 +0x06b6 5-2-1-2 6-11-1-2 7-7-3-4 8-1-3-5 9-7-6-7 10-9-8-9 +0x06b7 5-6-1-3 6-7-2-5 7-9-1-2 8-14-3-7 9-7-4-8 10-8-6-9 +0x06b9 5-1-1-4 6-6-1-2 7-13-3-5 8-7-6-7 9-6-4-8 +0x06bd 5-2-2-4 6-6-1-2 7-9-3-5 8-7-6-7 9-6-4-8 +0x06f0 5-9-1-2 6-6-3-4 7-4-3-5 8-2-6-7 +0x06f1 5-13-1-4 6-9-1-2 7-8-5-6 8-1-3-7 9-9-4-8 +0x06f2 5-1-1-4 6-9-1-4 7-2-2-5 8-9-6-7 9-1-3-8 10-9-4-9 +0x06f6 5-9-1-2 6-2-3-4 7-1-3-5 8-6-6-7 +0x06f9 5-9-1-2 6-1-3-5 7-9-4-6 +0x0776 5-6-3-4 6-7-3-4 7-6-1-2 8-4-1-5 9-7-6-7 10-11-8-9 +0x0778 5-7-3-4 6-7-1-2 7-1-3-4 8-7-5-6 9-9-7-8 +0x0779 5-2-1-3 6-6-3-4 7-6-2-5 8-1-4-7 9-7-1-2 10-7-6-9 11-11-8-10 +0x077a 5-2-1-3 6-6-3-4 7-7-1-2 8-4-4-5 9-7-6-7 10-9-8-9 +0x077e 5-6-2-4 6-6-1-2 7-6-3-5 8-14-6-7 9-7-3-4 10-8-8-9 +0x07b0 5-9-1-4 6-6-3-4 7-7-2-5 8-8-6-7 +0x07b1 5-1-1-3 6-1-4-5 7-6-3-6 8-6-1-4 9-2-2-8 10-1-7-9 +0x07b4 5-2-2-3 6-11-1-2 7-13-4-5 8-7-6-7 9-6-3-8 +0x07b5 5-13-2-3 6-7-4-5 7-4-2-3 8-14-1-7 9-7-6-8 10-6-3-9 +0x07b6 5-4-1-2 6-1-4-5 7-9-2-4 8-8-1-7 9-1-3-8 10-6-6-9 +0x07bc 5-6-3-4 6-7-1-2 7-2-2-4 8-7-5-6 9-9-7-8 +0x07e0 5-6-1-4 6-9-2-3 7-6-3-4 8-1-5-6 9-2-7-8 +0x07e1 5-2-2-3 6-14-1-2 7-7-1-5 8-7-4-7 9-7-6-8 10-6-3-9 +0x07e2 5-9-2-4 6-8-1-5 7-1-2-4 8-2-3-7 9-1-6-8 10-9-4-9 +0x07e3 5-4-1-4 6-2-2-5 7-9-2-4 8-7-1-7 9-7-3-8 10-6-6-9 +0x07e6 5-1-1-2 6-1-4-5 7-7-1-2 8-6-4-7 9-1-3-8 10-6-6-9 +0x07e9 5-1-1-2 6-1-4-5 7-8-1-2 8-1-3-7 9-6-6-8 +0x07f0 5-8-2-4 6-6-3-4 7-7-1-5 8-8-6-7 +0x07f1 5-9-2-4 6-9-1-4 7-8-5-6 8-1-3-7 9-9-4-8 +0x07f2 5-9-2-4 6-8-1-5 7-1-3-6 8-9-4-7 +0x07f8 5-8-1-2 6-1-3-5 7-9-4-6 +0x0ff0 5-1-1-3 6-1-2-5 7-5-3-6 8-9-4-7 +0x1668 5-6-2-3 6-6-1-2 7-6-1-4 8-14-5-6 9-4-7-8 10-6-5-9 +0x1669 5-7-2-3 6-9-1-3 7-9-2-4 8-2-1-5 9-9-6-7 10-4-8-9 +0x166a 5-4-1-4 6-6-2-4 7-6-2-3 8-6-1-4 9-14-5-6 10-4-7-9 11-6-8-10 +0x166b 5-6-3-4 6-6-2-3 7-2-1-5 8-14-6-7 9-6-1-4 10-9-8-9 +0x166e 5-6-3-4 6-8-3-4 7-2-1-5 8-13-2-7 9-6-6-8 10-9-1-9 +0x167e 5-6-1-3 6-6-2-5 7-2-4-6 8-6-2-3 9-14-5-8 10-4-7-9 +0x1681 5-4-1-4 6-9-1-4 7-6-2-5 8-6-3-7 9-1-2-3 10-6-6-9 11-1-8-10 +0x1683 5-6-1-4 6-9-2-3 7-11-1-4 8-2-2-5 9-9-6-7 10-4-8-9 +0x1686 5-9-1-4 6-9-1-2 7-7-3-5 8-7-6-7 9-6-3-8 +0x1687 5-6-1-2 6-4-3-4 7-6-1-4 8-1-6-7 9-1-5-8 10-9-3-9 +0x1689 5-6-2-4 6-9-1-4 7-1-2-3 8-2-3-5 9-6-6-7 10-1-8-9 +0x168b 5-14-1-3 6-6-1-2 7-6-1-4 8-14-2-3 9-8-5-6 10-2-7-9 11-9-8-10 +0x168e 5-6-2-4 6-6-1-4 7-14-1-3 8-14-2-3 9-8-5-6 10-2-7-9 11-6-8-10 +0x1696 5-7-1-4 6-6-1-2 7-13-2-5 8-7-3-7 9-9-6-8 +0x1697 5-6-2-4 6-6-1-2 7-6-1-3 8-1-5-6 9-1-7-8 10-9-2-9 +0x1698 5-4-3-4 6-6-1-2 7-8-1-4 8-14-2-3 9-6-5-6 10-6-7-8 11-4-9-10 +0x1699 5-7-1-2 6-6-1-2 7-8-3-5 8-2-4-7 9-9-6-8 +0x169a 5-4-2-3 6-4-1-3 7-7-2-4 8-6-1-5 9-1-6-7 10-6-8-9 +0x169b 5-4-3-4 6-8-2-4 7-2-1-3 8-6-2-5 9-2-1-6 10-14-7-8 11-9-9-10 +0x169e 5-9-3-4 6-6-1-3 7-8-1-5 8-13-2-7 9-9-6-8 +0x16a9 5-7-2-3 6-9-1-4 7-1-2-3 8-2-4-5 9-6-6-7 10-1-8-9 +0x16ac 5-14-2-3 6-8-1-4 7-4-1-3 8-4-2-4 9-6-5-6 10-2-7-8 11-6-9-10 +0x16ad 5-7-2-4 6-7-1-2 7-9-3-4 8-6-1-5 9-7-6-7 10-6-8-9 +0x16bc 5-7-2-3 6-6-2-3 7-6-4-5 8-2-1-7 9-6-6-8 +0x16e9 5-9-1-3 6-7-2-3 7-9-2-5 8-7-6-7 9-6-4-8 +0x177e 5-6-1-3 6-6-2-3 7-6-4-5 8-14-6-7 9-7-1-4 10-9-8-9 +0x178e 5-6-3-4 6-6-1-2 7-6-1-5 8-1-6-7 9-9-3-8 +0x1796 5-6-2-3 6-9-1-2 7-13-4-5 8-7-6-7 9-6-3-8 +0x1798 5-6-1-4 6-8-1-2 7-6-2-5 8-2-3-7 9-14-6-8 10-6-4-9 +0x179a 5-6-1-4 6-8-3-4 7-2-1-2 8-4-2-3 9-2-5-6 10-14-7-9 11-6-8-10 +0x17ac 5-4-1-4 6-8-1-3 7-6-3-5 8-13-2-7 9-4-6-8 10-9-4-9 +0x17e8 5-6-1-2 6-1-1-2 7-11-3-5 8-6-4-7 9-6-6-8 +0x18e7 5-6-2-3 6-9-1-2 7-7-5-6 8-6-4-7 +0x19e1 5-4-3-4 6-13-3-4 7-2-1-5 8-13-2-7 9-9-6-8 10-6-1-9 +0x19e3 5-7-2-3 6-1-3-4 7-8-1-5 8-6-4-7 9-1-6-8 10-9-2-9 +0x19e6 5-8-1-3 6-6-1-4 7-2-2-5 8-6-6-7 +0x1bd8 5-6-2-3 6-9-1-4 7-6-1-3 8-1-5-6 9-6-7-8 +0x1be4 5-9-2-3 6-6-3-4 7-1-1-5 8-6-6-7 +0x1ee1 5-9-3-4 6-1-1-2 7-9-5-6 +0x3cc3 5-3-1-3 6-12-1-2 7-6-4-6 8-6-5-7 +0x6996 5-9-1-3 6-6-2-4 7-9-5-6 diff --git a/src/networks/stp/stp_cleanup.hpp b/src/networks/stp/stp_cleanup.hpp new file mode 100644 index 0000000..08e51e8 --- /dev/null +++ b/src/networks/stp/stp_cleanup.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include + +#include + +#include +#include +#include + +namespace mockturtle +{ + +template +std::vector> stp_cleanup_dangling( NtkSource const& ntk, NtkDest& dest, LeavesIterator begin, LeavesIterator end ) +{ + (void)end; + + node_map, NtkSource> old_to_new( ntk ); + old_to_new[ntk.get_constant( false )] = dest.get_constant( false ); + + /* create inputs in same order */ + auto it = begin; + ntk.foreach_pi( [&]( auto node ) { + old_to_new[node] = *it++; + } ); + assert( it == end ); + + /* foreach node in topological order */ + topo_view topo{ntk}; + topo.foreach_node( [&]( auto node ) { + if ( ntk.is_constant( node ) || ntk.is_pi( node ) ) + return; + + /* collect children */ + std::vector> children; + ntk.foreach_fanin( node, [&]( auto child, auto ) { + const auto f = old_to_new[child]; + children.push_back( f ); + } ); + + old_to_new[node] = dest.clone_node( ntk, node, children ); + } ); + + /* create outputs in same order */ + std::vector> fs; + ntk.foreach_po( [&]( auto po ) { + const auto f = old_to_new[po]; + fs.push_back( f ); + } ); + + return fs; +} + + +} // namespace mockturtle diff --git a/src/networks/stp/stp_npn.hpp b/src/networks/stp/stp_npn.hpp new file mode 100644 index 0000000..77c331a --- /dev/null +++ b/src/networks/stp/stp_npn.hpp @@ -0,0 +1,216 @@ +/* phyLS: Advanced Logic Synthesis and Optimization tool + * Copyright (C) 2019- Ningbo University, Ningbo, China +/* + \file stp_npn.hpp + \brief Replace with size-optimum STP-based exact synthesis from NPN + + \author Homyoung +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../core/misc.hpp" +#include "stp_cleanup.hpp" + +namespace mockturtle { + +class stp_npn_resynthesis { + public: + /*! \brief Default constructor. + * + */ + stp_npn_resynthesis() { build_db(); } + + template + void operator()(klut_network& klut, + kitty::dynamic_truth_table const& function, + LeavesIterator begin, LeavesIterator end, Fn&& fn) const { + assert(function.num_vars() <= 4); + const auto fe = kitty::extend_to(function, 4); + const auto config = kitty::exact_npn_canonization(fe); + + auto func_str = "0x" + kitty::to_hex(std::get<0>(config)); + const auto it = class2signal.find(func_str); + assert(it != class2signal.end()); + + std::vector pis(4, klut.get_constant(false)); + std::copy(begin, end, pis.begin()); + + std::vector pis_perm(4); + auto perm = std::get<2>(config); + for (auto i = 0; i < 4; ++i) { + pis_perm[i] = pis[perm[i]]; + } + + // const auto& phase = std::get<1>(config); + // for (auto i = 0; i < 4; ++i) { + // if ((phase >> perm[i]) & 1) { + // pis_perm[i] = !pis_perm[i]; + // } + // } + + for (auto const& po : it->second) { + topo_view topo{db, po}; + auto f = + stp_cleanup_dangling(topo, klut, pis_perm.begin(), pis_perm.end()) + .front(); + + if (!fn(f)) return; /* quit */ + } + } + + private: + std::unordered_map> opt_klut; + + void load_optimal_klut() { + std::ifstream infile("../src/networks/stp/opt_stp.txt"); + if (!infile) { + std::cout << " Cannot open file " << std::endl; + assert(false); + } + + std::string line; + std::vector v; + while (std::getline(infile, line)) { + v.clear(); + auto strs = phyLS::split_by_delim(line, ' '); + for (auto i = 1u; i < strs.size(); i++) v.push_back(strs[i]); + opt_klut.insert(std::make_pair(strs[0], v)); + } + } + + std::vector create_klut_from_str_vec( + const std::vector strs, + const std::vector& signals) { + auto sig = signals; + std::vector result; + + int a, b; + for (auto i = 0; i < strs.size(); i++) { + const auto substrs = phyLS::split_by_delim(strs[i], '-'); + assert(substrs.size() == 4u); + + a = std::stoi(substrs[2]); + b = std::stoi(substrs[3]); + switch (std::stoi(substrs[1])) { + case 0: { + sig.push_back(db._create_node({sig[a], sig[b]}, 15)); + break; + } + + case 1: { + sig.push_back(db._create_node({sig[a], sig[b]}, 14)); + break; + } + + case 2: { + sig.push_back(db._create_node({sig[a], sig[b]}, 13)); + break; + } + + case 3: { + sig.push_back(db._create_node({sig[a], sig[b]}, 12)); + break; + } + + case 4: { + sig.push_back(db._create_node({sig[a], sig[b]}, 11)); + break; + } + + case 5: { + sig.push_back(db._create_node({sig[a], sig[b]}, 10)); + break; + } + + case 6: { + sig.push_back(db._create_node({sig[a], sig[b]}, 9)); + break; + } + + case 7: { + sig.push_back(db._create_node({sig[a], sig[b]}, 8)); + break; + } + + case 8: { + sig.push_back(db._create_node({sig[a], sig[b]}, 7)); + break; + } + + case 9: { + sig.push_back(db._create_node({sig[a], sig[b]}, 6)); + break; + } + + case 10: { + sig.push_back(db._create_node({sig[a], sig[b]}, 5)); + break; + } + + case 11: { + sig.push_back(db._create_node({sig[a], sig[b]}, 4)); + break; + } + + case 12: { + sig.push_back(db._create_node({sig[a], sig[b]}, 3)); + break; + } + + case 13: { + sig.push_back(db._create_node({sig[a], sig[b]}, 2)); + break; + } + + case 14: { + sig.push_back(db._create_node({sig[a], sig[b]}, 1)); + break; + } + + case 15: { + sig.push_back(db._create_node({sig[a], sig[b]}, 0)); + break; + } + + default: + assert(false); + break; + } + } + + const auto driver = sig[sig.size() - 1]; + db.create_po(driver); + result.push_back(driver); + return result; + } + + void build_db() { + std::vector signals; + signals.push_back(db.get_constant(false)); + + for (auto i = 0u; i < 4; ++i) signals.push_back(db.create_pi()); + + load_optimal_klut(); + + for (const auto e : opt_klut) { + class2signal.insert( + std::make_pair(e.first, create_klut_from_str_vec(e.second, signals))); + } + } + + klut_network db; + std::unordered_map> + class2signal; +}; + +} /* namespace mockturtle */ diff --git a/src/phyLS.cpp b/src/phyLS.cpp index d6fa710..ed0d9da 100644 --- a/src/phyLS.cpp +++ b/src/phyLS.cpp @@ -51,5 +51,8 @@ #include "commands/simulator.hpp" #include "commands/abc/cec.hpp" #include "commands/stpfr.hpp" +#include "commands/cutrw.hpp" +#include "commands/exact/exact_lut.hpp" +#include "commands/exact/lutrw.hpp" ALICE_MAIN(phyLS) \ No newline at end of file