update for exact synthesis

noah
panhongyang 2023-08-02 18:08:30 +08:00
parent b0ca41c4aa
commit ed84ad922e
23 changed files with 9346 additions and 5 deletions

4
.gitmodules vendored
View File

@ -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

@ -1 +1 @@
Subproject commit da2b5e697d2dc988746fb94aceaebb277d385b83
Subproject commit fac58aa217f7b4c4d5327b201f5e9fe8cbf9ee6a

134
src/commands/cutrw.hpp Normal file
View File

@ -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 <mockturtle/algorithms/node_resynthesis/bidecomposition.hpp>
#include <mockturtle/mockturtle.hpp>
#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<xag_network>().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<xag_network> resyn2;
refactoring(xag, resyn2);
xag = cleanup_dangling(xag);
phyLS::print_stats(xag);
store<xag_network>().extend();
store<xag_network>().current() = cleanup_dangling(xag);
} else if (is_set("xag_npn")) {
begin = clock();
xag_network xag = store<xag_network>().current();
phyLS::print_stats(xag);
xag_npn_resynthesis<xag_network> 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<xag_network>().extend();
store<xag_network>().current() = cleanup_dangling(xag);
} else if (is_set("klut_npn")) {
klut_network klut = store<klut_network>().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<klut_network>().extend();
store<klut_network>().current() = cleanup_dangling(klut);
} else {
xmg_network xmg = store<xmg_network>().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<xmg_network>().extend();
store<xmg_network>().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

View File

@ -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 <time.h>
#include <alice/alice.hpp>
#include <mockturtle/mockturtle.hpp>
#include <percy/percy.hpp>
#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<chain>& 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<chain>& 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<string>& 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<chain> 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<mockturtle::gate> gates =
store<std::vector<mockturtle::gate>>().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<klut_network>().extend();
store<klut_network>().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<mockturtle::gate> gates =
store<std::vector<mockturtle::gate>>().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<chain> 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<mockturtle::gate> gates =
store<std::vector<mockturtle::gate>>().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<std::vector<mockturtle::gate>>().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<string> 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

View File

@ -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 <time.h>
#include <alice/alice.hpp>
#include <mockturtle/mockturtle.hpp>
#include <mockturtle/networks/klut.hpp>
#include <percy/percy.hpp>
#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<mockturtle::klut_network>().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_network>(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<mockturtle::klut_network>().extend();
store<mockturtle::klut_network>().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

View File

@ -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<uint32_t, uint32_t> operator()(uint32_t num_leaves) const {
if (num_leaves < 2u) return {0u, 0u};
return {num_leaves, 1u}; /* area, delay */
}
std::pair<uint32_t, uint32_t> 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<mig_network>().size() == 0u)
@ -109,7 +124,7 @@ class lutmap_command : public command {
std::cerr << "Error: Empty AIG network\n";
else {
auto aig = store<aig_network>().current();
mapping_view mapped_aig{aig};
mapping_view<aig_network, true> 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<decltype(mapped_aig), true, lut_custom_cost>(
mapped_aig, ps);
else
phyLS::lut_map(mapped_aig, ps);
mapped_aig.clear_mapping();
}
}

View File

@ -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_resynthesis_params::cache_map_t>();
exact_aig_resynthesis<aig_network> exact_resyn(false, ps);
node_resynthesis_stats nrst;
dsd_resynthesis<aig_network, decltype(exact_resyn)> resyn(exact_resyn);
const auto aig = node_resynthesis<aig_network>(klut, resyn, {}, &nrst);
store<aig_network>().extend();
store<aig_network>().current() = cleanup_dangling(aig);
phyLS::print_stats(aig);
end = clock();
totalTime = (double)(end - begin) / CLOCKS_PER_SEC;
} else {
begin = clock();
if (is_set("direct")) {

2249
src/core/exact/exact_dag.hpp Normal file

File diff suppressed because it is too large Load Diff

2898
src/core/exact/exact_lut.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
#ifndef EXACT_LUT_HPP
#define EXACT_LUT_HPP
#include <math.h>
#include <algorithm>
#include <chrono>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <numeric>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
namespace phyLS {
void exact_lut(vector<string>& tt, int& input);
void exact_lut_enu(vector<string>& tt, int& input);
} // namespace phyLS
#endif

View File

@ -0,0 +1,408 @@
#ifndef LUT_REWRITING_HPP
#define LUT_REWRITING_HPP
#include <algorithm>
#include <mockturtle/algorithms/cleanup.hpp>
#include <mockturtle/mockturtle.hpp>
#include <mockturtle/networks/klut.hpp>
#include <percy/percy.hpp>
#include <string>
#include <vector>
#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<klut_network::node> 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<int> node;
std::vector<int> right;
std::vector<int> left;
std::vector<std::string> 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<mockturtle::klut_network::node> 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<klut_network::node> 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<int> nodes;
std::vector<int> rights;
std::vector<int> lefts;
std::vector<std::string> 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<mockturtle::klut_network::node> 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<klut_network::node> 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<int> nodes;
std::vector<int> rights;
std::vector<int> lefts;
std::vector<std::string> 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<mockturtle::klut_network::node> 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<std::vector<std::string>> 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

644
src/networks/aoig/aoig.hpp Normal file
View File

@ -0,0 +1,644 @@
#pragma once
/*!
\file aoig.hpp
\brief aoig logic network implementation
*/
#include <mockturtle/mockturtle.hpp>
#include <kitty/kitty.hpp>
namespace mockturtle
{
struct aoig_storage_data
{
truth_table_cache<kitty::dynamic_truth_table> cache;
uint32_t num_pis = 0u;
uint32_t num_pos = 0u;
std::vector<int8_t> 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<aoig_storage_node, aoig_storage_data>;
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<aoig_storage>;
using node = uint64_t;
using signal = uint64_t;
aoig_network()
: _storage(std::make_shared<aoig_storage>()),
_events(std::make_shared<decltype(_events)::element_type>())
{
_init();
}
aoig_network(std::shared_ptr<aoig_storage> storage)
: _storage(storage),
_events(std::make_shared<decltype(_events)::element_type>())
{
_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<uint32_t>(_storage->inputs.size()) == _storage->data.num_pis &&
static_cast<uint32_t>(_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<signal> 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<signal> 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<signal> 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<signal> 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<uint32_t>(_storage->nodes.size());
}
auto num_cis() const
{
return static_cast<uint32_t>(_storage->inputs.size());
}
auto num_cos() const
{
return static_cast<uint32_t>(_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<uint32_t>(_storage->nodes.size() - _storage->inputs.size() - 2);
}
uint32_t fanin_size(node const& n) const
{
return static_cast<uint32_t>(_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<uint32_t>(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<typename Fn>
void foreach_node(Fn&& fn) const
{
detail::foreach_element(ez::make_direct_iterator<uint64_t>(0),
ez::make_direct_iterator<uint64_t>(_storage->nodes.size()),
fn);
}
template<typename Fn>
void foreach_ci(Fn&& fn) const
{
detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn);
}
template<typename Fn>
void foreach_co(Fn&& fn) const
{
using IteratorType = decltype(_storage->outputs.begin());
detail::foreach_element_transform<IteratorType, uint32_t>(_storage->outputs.begin(), _storage->outputs.end(), [](auto o) { return o.index; }, fn);
}
template<typename Fn>
void foreach_pi(Fn&& fn) const
{
detail::foreach_element(_storage->inputs.begin(), _storage->inputs.begin() + _storage->data.num_pis, fn);
}
template<typename Fn>
void foreach_po(Fn&& fn) const
{
using IteratorType = decltype(_storage->outputs.begin());
detail::foreach_element_transform<IteratorType, uint32_t>(_storage->outputs.begin(), _storage->outputs.begin() + _storage->data.num_pos, [](auto o) { return o.index; }, fn);
}
template<typename Fn>
void foreach_gate(Fn&& fn) const
{
detail::foreach_element_if(ez::make_direct_iterator<uint64_t>(2), /* start from 2 to avoid constants */
ez::make_direct_iterator<uint64_t>(_storage->nodes.size()),
[this](auto n) { return !is_ci(n); },
fn);
}
template<typename Fn>
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<IteratorType, uint32_t>(_storage->nodes[n].children.begin(), _storage->nodes[n].children.end(), [](auto f) { return f.index; }, fn);
}
#pragma endregion
#pragma region Simulate values
template<typename Iterator>
iterates_over_t<Iterator, bool>
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<typename Iterator>
iterates_over_truth_table_t<Iterator>
compute(node const& n, Iterator begin, Iterator end) const
{
const auto nfanin = _storage->nodes[n].children.size();
std::vector<typename Iterator::value_type> 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<uint32_t>(_storage->nodes[n].data[0].h2++);
}
uint32_t decr_value(node const& n) const
{
return static_cast<uint32_t>(--_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<aoig_storage> _storage;
std::shared_ptr<network_events<base_type>> _events;
};
} // namespace mockturtle

File diff suppressed because one or more lines are too long

View File

@ -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])}}

View File

@ -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<uint8_t> get_func_supports( kitty::dynamic_truth_table const& spec )
{
std::vector<uint8_t> 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<xag_network::signal> const& children,
std::unordered_map<std::string, std::string>& 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<xag_network::signal> 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<xag_network::signal> const& children )
{
/* get pi signals */
auto sup = get_func_supports( remainder );
std::vector<xag_network::signal> 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<unsigned int>( 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<xag_network::signal> pis( support.size(), _ntk.get_constant( false ) );
std::copy( small_pis.begin(), small_pis.end(), pis.begin() );
std::vector<xag_network::signal> 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<xag_network::signal>& pis_perm )
{
std::stack<int> polar;
std::stack<xag_network::signal> 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<xag_network::signal> pis;
std::unordered_map<std::string, std::string>& opt_xags;
xag_dec_params const& _ps;
};
xag_network::signal xag_dec( xag_network& ntk, kitty::dynamic_truth_table const& func, std::vector<xag_network::signal> const& children,
std::unordered_map<std::string, std::string>& opt_xags,
xag_dec_params const& ps = {} )
{
xag_dec_impl impl( ntk, func, children, opt_xags, ps );
return impl.run();
}
} //end of namespace
#endif

View File

@ -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 Ntk>
class xag_lut_dec_resynthesis
{
public:
explicit xag_lut_dec_resynthesis( std::unordered_map<std::string, std::string>& opt_xags )
: opt_xags( opt_xags )
{
}
template<typename LeavesIterator, typename Fn>
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<signal<Ntk>>( begin, end ), opt_xags );
fn( f );
}
private:
std::unordered_map<std::string, std::string>& opt_xags;
};
}
#endif

View File

@ -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 <iostream>
#include <sstream>
#include <stack>
#include <unordered_map>
#include <vector>
#include <kitty/dynamic_truth_table.hpp>
#include <kitty/npn.hpp>
#include <kitty/print.hpp>
#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<xag_network>( klut, resyn );
\endverbatim
*/
class xag_npn_lut_resynthesis
{
public:
/*! \brief Default constructor.
*
*/
xag_npn_lut_resynthesis()
{
class2signal = phyLS::get_xag_db( db );
}
template<typename LeavesIterator, typename Fn>
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<uint16_t>( std::get<0>( config )._bits[0] ) );
std::vector<xag_network::signal> pis( 4, xag.get_constant( false ) );
std::copy( begin, end, pis.begin() );
std::vector<xag_network::signal> 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<std::string, std::vector<xag_network::signal>> class2signal;
};
} /* namespace mockturtle */

592
src/networks/stp/mg.hpp Normal file
View File

@ -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 <kitty/dynamic_truth_table.hpp>
#include <kitty/operators.hpp>
#include <kitty/partial_truth_table.hpp>
#include <memory>
#include <mockturtle/networks/detail/foreach.hpp>
#include <mockturtle/networks/events.hpp>
#include <mockturtle/networks/storage.hpp>
#include <mockturtle/traits.hpp>
#include <mockturtle/utils/algorithm.hpp>
#include <optional>
#include <stack>
#include <string>
namespace mockturtle {
/*! \brief Hash function for AIGs (from ABC) */
template <class Node>
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<regular_node<2, 2, 1>, empty_storage_data,
mg_hash<regular_node<2, 2, 1>>>;
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<mg_storage>;
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<mg_storage>()),
_events(std::make_shared<decltype(_events)::element_type>()) {}
mg_network(std::shared_ptr<mg_storage> storage)
: _storage(storage),
_events(std::make_shared<decltype(_events)::element_type>()) {}
mg_network clone() const { return {std::make_shared<mg_storage>(*_storage)}; }
#pragma endregion
#pragma region Primary I / O and constants
signal get_constant(bool value) const {
return {0, static_cast<uint64_t>(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<uint32_t>(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<uint64_t>(3.1415f * index));
_storage->hash.reserve(static_cast<uint64_t>(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<signal> 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<signal> 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<uint32_t>(_storage->nodes.size()); }
auto num_cis() const {
return static_cast<uint32_t>(_storage->inputs.size());
}
auto num_cos() const {
return static_cast<uint32_t>(_storage->outputs.size());
}
auto num_pis() const {
return static_cast<uint32_t>(_storage->inputs.size());
}
auto num_pos() const {
return static_cast<uint32_t>(_storage->outputs.size());
}
auto num_gates() const {
return static_cast<uint32_t>(_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<uint32_t>(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<uint32_t>(_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<uint32_t>(_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 <typename Fn>
void foreach_node(Fn&& fn) const {
auto r = range<uint64_t>(_storage->nodes.size());
detail::foreach_element_if(
r.begin(), r.end(), [this](auto n) { return !is_dead(n); }, fn);
}
template <typename Fn>
void foreach_ci(Fn&& fn) const {
detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(),
fn);
}
template <typename Fn>
void foreach_co(Fn&& fn) const {
detail::foreach_element(_storage->outputs.begin(), _storage->outputs.end(),
fn);
}
template <typename Fn>
void foreach_pi(Fn&& fn) const {
detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(),
fn);
}
template <typename Fn>
void foreach_po(Fn&& fn) const {
detail::foreach_element(_storage->outputs.begin(), _storage->outputs.end(),
fn);
}
template <typename Fn>
void foreach_gate(Fn&& fn) const {
auto r = range<uint64_t>(
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 <typename Fn>
void foreach_fanin(node const& n, Fn&& fn) const {
if (n == 0 || is_ci(n)) return;
static_assert(detail::is_callable_without_index_v<Fn, signal, bool> ||
detail::is_callable_with_index_v<Fn, signal, bool> ||
detail::is_callable_without_index_v<Fn, signal, void> ||
detail::is_callable_with_index_v<Fn, signal, void>);
/* we don't use foreach_element here to have better performance */
if constexpr (detail::is_callable_without_index_v<Fn, signal, bool>) {
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<Fn, signal, bool>) {
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,
void>) {
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, void>) {
fn(signal{_storage->nodes[n].children[0]}, 0);
fn(signal{_storage->nodes[n].children[1]}, 1);
}
}
#pragma endregion
#pragma region Value simulation
template <typename Iterator>
iterates_over_t<Iterator, bool> 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 <typename Iterator>
iterates_over_truth_table_t<Iterator> 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<mg_storage> _storage;
std::shared_ptr<network_events<base_type>> _events;
};
} // namespace mockturtle
namespace std {
template <>
struct hash<mockturtle::mg_network::signal> {
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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,58 @@
#pragma once
#include <iostream>
#include <type_traits>
#include <vector>
#include <kitty/operations.hpp>
#include <mockturtle/traits.hpp>
#include <mockturtle/utils/node_map.hpp>
#include <mockturtle/views/topo_view.hpp>
namespace mockturtle
{
template<typename NtkSource, typename NtkDest, typename LeavesIterator>
std::vector<signal<NtkDest>> stp_cleanup_dangling( NtkSource const& ntk, NtkDest& dest, LeavesIterator begin, LeavesIterator end )
{
(void)end;
node_map<signal<NtkDest>, 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<signal<NtkDest>> 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<signal<NtkDest>> fs;
ntk.foreach_po( [&]( auto po ) {
const auto f = old_to_new[po];
fs.push_back( f );
} );
return fs;
}
} // namespace mockturtle

View File

@ -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 <iostream>
#include <kitty/dynamic_truth_table.hpp>
#include <kitty/npn.hpp>
#include <kitty/print.hpp>
#include <mockturtle/mockturtle.hpp>
#include <sstream>
#include <unordered_map>
#include <vector>
#include "../../core/misc.hpp"
#include "stp_cleanup.hpp"
namespace mockturtle {
class stp_npn_resynthesis {
public:
/*! \brief Default constructor.
*
*/
stp_npn_resynthesis() { build_db(); }
template <typename LeavesIterator, typename Fn>
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<klut_network::signal> pis(4, klut.get_constant(false));
std::copy(begin, end, pis.begin());
std::vector<klut_network::signal> 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<std::string, std::vector<std::string>> 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<std::string> 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<klut_network::signal> create_klut_from_str_vec(
const std::vector<std::string> strs,
const std::vector<klut_network::signal>& signals) {
auto sig = signals;
std::vector<klut_network::signal> 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<klut_network::signal> 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<std::string, std::vector<klut_network::signal>>
class2signal;
};
} /* namespace mockturtle */

View File

@ -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)