From 74d13d1dfe4ac9d64020fee9a8b52843c6c34ffe Mon Sep 17 00:00:00 2001 From: Ashton Snelgrove Date: Wed, 30 Mar 2022 16:38:08 -0600 Subject: [PATCH] Move optimizers to own files. --- core/CMakeLists.txt | 1 + core/algorithms/optimization/optimizer.cpp | 95 ++ core/algorithms/optimization/optimizer.hpp | 147 +++ .../optimization/optimizers/abc.hpp | 84 ++ .../optimization/optimizers/aig.hpp | 231 +++++ .../optimization/optimizers/mig.hpp | 179 ++++ .../optimization/optimizers/noop.hpp | 124 +++ .../optimization/optimizers/techmapping.hpp | 91 ++ .../optimization/optimizers/xag.hpp | 116 +++ .../optimization/optimizers/xmg.hpp | 114 +++ core/algorithms/optimization/resynthesis.cpp | 848 +----------------- core/algorithms/optimization/resynthesis.hpp | 46 +- 12 files changed, 1205 insertions(+), 871 deletions(-) create mode 100644 core/algorithms/optimization/optimizer.cpp create mode 100644 core/algorithms/optimization/optimizer.hpp create mode 100644 core/algorithms/optimization/optimizers/abc.hpp create mode 100644 core/algorithms/optimization/optimizers/aig.hpp create mode 100644 core/algorithms/optimization/optimizers/mig.hpp create mode 100644 core/algorithms/optimization/optimizers/noop.hpp create mode 100644 core/algorithms/optimization/optimizers/techmapping.hpp create mode 100644 core/algorithms/optimization/optimizers/xag.hpp create mode 100644 core/algorithms/optimization/optimizers/xmg.hpp diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 993a3d0da..cc5482f8b 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -25,6 +25,7 @@ add_custom_command( set(LSORACLE_SOURCE ${CMAKE_CURRENT_BINARY_DIR}/kahypar_config.cpp kahypar_temp_config.cpp + algorithms/optimization/optimizer.cpp algorithms/optimization/resynthesis.cpp utility.cpp ) diff --git a/core/algorithms/optimization/optimizer.cpp b/core/algorithms/optimization/optimizer.cpp new file mode 100644 index 000000000..6525fded3 --- /dev/null +++ b/core/algorithms/optimization/optimizer.cpp @@ -0,0 +1,95 @@ +/* LSOracle: A learning based Oracle for Logic Synthesis + + * MIT License + * Copyright 2019 Laboratory for Nano Integrated Systems (LNIS) + * + * 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. + */ +#include "algorithms/optimization/optimizer.hpp" +#include "algorithms/optimization/optimizers/aig.hpp" +#include "algorithms/optimization/optimizers/mig.hpp" +#include "algorithms/optimization/optimizers/xag.hpp" +#include "algorithms/optimization/optimizers/xmg.hpp" +#include "algorithms/optimization/optimizers/abc.hpp" +#include "algorithms/optimization/optimizers/noop.hpp" +namespace oracle { +template +optimizer *optimize(optimization_strategy_comparator &comparator, + optimization_strategy strategy, + const mockturtle::window_view> &part, + int index, + const std::string &abc_exec) +{ + std::cout << "******************************** optimizing partition " << index << " ********************************" << std::endl; + std::cout << "Optimizing based on strategy " << comparator.name() << std::endl; + // depth_view part_depth(part); + // std::cout << "Original depth " << part_depth.depth() << " gates " << part_depth.num_gates() << " size " << part_depth.size() << std::endl; + // todo this is gonna leak memory. + std::vector*>optimizers { + new noop(index, part, strategy, abc_exec), + new migscript_optimizer(index, part, strategy, abc_exec), + new migscript2_optimizer(index, part, strategy, abc_exec), + new migscript3_optimizer(index, part, strategy, abc_exec), + new aigscript_optimizer(index, part, strategy, abc_exec), + new aigscript2_optimizer(index, part, strategy, abc_exec), + new aigscript3_optimizer(index, part, strategy, abc_exec), + new aigscript4_optimizer(index, part, strategy, abc_exec), + new aigscript5_optimizer(index, part, strategy, abc_exec), + new xmg_optimizer(index, part, strategy, abc_exec), + new xag_optimizer(index, part, strategy, abc_exec), + // new abc_optimizer(index, part, strategy, abc_exec), + }; + optimizer *best = nullptr; + for (auto opt = optimizers.begin(); opt != optimizers.end(); opt++) { + std::cout << "running optimization " << (*opt)->optimizer_name() << std::endl; + // std::cout << "converting network" << std::endl; + (*opt)->convert(); + // std::cout << "trying to optimize" << std::endl; + (*opt)->optimize(); + // std::cout << "checking tech independent metrics." << std::endl; + node_depth result = (*opt)->independent_metric(); + std::cout << "result depth " << result.depth + << " size " << result.nodes << std::endl; + + if (best == nullptr) { + best = *opt; + continue; + } + + if (comparator(**opt, *best)) { + best = *opt; + //std::cout << "found a better result" << std::endl; + continue; + } + } + std::cout << "using " << best->optimizer_name() << " for " << index << std::endl; + + return best; + +} +template optimizer *optimize( + optimization_strategy_comparator &, + optimization_strategy, + const mockturtle::window_view> &, + int, + const std::string &); +} diff --git a/core/algorithms/optimization/optimizer.hpp b/core/algorithms/optimization/optimizer.hpp new file mode 100644 index 000000000..12135f9cd --- /dev/null +++ b/core/algorithms/optimization/optimizer.hpp @@ -0,0 +1,147 @@ +/* LSOracle: A learning based Oracle for Logic Synthesis + + * MIT License + * Copyright 2019 Laboratory for Nano Integrated Systems (LNIS) + * + * 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. + */ +#pragma once +#include +#include +// #include "algorithms/optimization/optimizers/strategy.hpp" +// #include "algorithms/optimization/optimizers/aig.hpp" +// #include "algorithms/optimization/optimizers/mig.hpp" +// #include "algorithms/optimization/optimizers/xag.hpp" +// #include "algorithms/optimization/optimizers/xmg.hpp" +// #include "algorithms/optimization/optimizers/abc.hpp" + +namespace oracle { + +enum optimization_strategy { size, balanced, depth }; + +struct node_depth { + int nodes; + int depth; +}; + +template +class optimizer +{ +public: + /** + * human readable name + */ + virtual const std::string optimizer_name() = 0; + /** + * Do any conversion necessary from original network type to the internal network type. + */ + virtual void convert() = 0; + /** + * Perform optimization + */ + virtual void optimize() = 0; + /** + * Calculate tech independent depth and nodes metrics. + */ + virtual node_depth independent_metric() = 0; + /** + * List the type of optimization: area, delay, or balanced. + */ + virtual optimization_strategy target() = 0; + /** + * Techmap, then return a path to a file containing the techmapped verilog. + */ + virtual std::string techmap(const std::string &liberty_file, const std::string &temp_prefix) = 0; + /** + * convert the network to the superset. + */ + virtual mockturtle::names_view export_superset() = 0; + /** + * Reapply this optimization to a different network. + */ + virtual optimizer *reapply(int index, const mockturtle::window_view> &part) = 0; +}; + +template +class optimization_strategy_comparator { +public: + // Comparator function + virtual bool operator()(optimizer &a, optimizer &b) = 0; + virtual const std::string name() = 0; +}; + +template +optimizer *optimize(optimization_strategy_comparator &comparator, + optimization_strategy strategy, + const mockturtle::window_view> &part, + int index, + const std::string &abc_exec); + +template +class ndp_strategy : public optimization_strategy_comparator +{ + bool operator()(optimizer &a, optimizer &b) + { + node_depth x = a.independent_metric(); + node_depth y = b.independent_metric(); + + return x.nodes * x.depth < y.nodes * y.depth; + } + const std::string name() + { + return "node-depth product"; + } +}; + +template +class d_strategy : public optimization_strategy_comparator +{ + bool operator()(optimizer &a, optimizer &b) + { + node_depth x = a.independent_metric(); + node_depth y = b.independent_metric(); + + return x.depth < y.depth; + } + const std::string name() + { + return "depth"; + } +}; + + template + class n_strategy : public optimization_strategy_comparator + { + bool operator()(optimizer &a, optimizer &b) + { + node_depth x = a.independent_metric(); + node_depth y = b.independent_metric(); + + return x.nodes < y.nodes; + } + const std::string name() + { + return "node"; + } +}; + +}; diff --git a/core/algorithms/optimization/optimizers/abc.hpp b/core/algorithms/optimization/optimizers/abc.hpp new file mode 100644 index 000000000..1a2912e93 --- /dev/null +++ b/core/algorithms/optimization/optimizers/abc.hpp @@ -0,0 +1,84 @@ +/* LSOracle: A learning based Oracle for Logic Synthesis + + * MIT License + * Copyright 2019 Laboratory for Nano Integrated Systems (LNIS) + * + * 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. + */ +#pragma once +#include +#include +#include "algorithms/optimization/optimizers/techmapping.hpp" +#include "algorithms/optimization/optimizers/aig.hpp" + +namespace oracle { + +template< typename network> +class abc_optimizer: public aig_optimizer +{ + using partition = mockturtle::window_view>; +public: + abc_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): aig_optimizer(index, original, target, abc_exec) {} + + const std::string optimizer_name() + { + return "abc resyn2"; + } + + optimizer *reapply(int index, const xmg_partition &part) + { + return new abc_optimizer(index, part, this->strategy, this->abc_exec); + } + + void optimize() + { + char *blif_name_char = strdup("/tmp/lsoracle_XXXXXX.blif"); + if (mkstemps(blif_name_char, 5) == -1) { + throw std::exception(); + } + std::string blif_name = std::string(blif_name_char); + std::cout << "writing blif to " << blif_name << std::endl; + + char *blif_output_name_char = strdup("/tmp/lsoracle_XXXXXX_optimized.blif"); + if (mkstemps(blif_output_name_char, 15) == -1) { + throw std::exception(); + } + std::string blif_output_name = std::string(blif_output_name_char); + std::cout << "writing abc output to " << blif_output_name << std::endl; + + mockturtle::write_blif_params ps; + ps.skip_feedthrough = 1u; + mockturtle::write_blif(this->converted, blif_name, ps); + std::string script = "abc -c \"read_blif " + blif_name + "; resyn2; write_blif " + blif_output_name + " \""; + int code = system((script).c_str()); + assert(code == 0); + std::cout << "optimized with abc" << std::endl; + + mockturtle::names_view klut; + lorina::return_code read_blif_return_code = lorina::read_blif(blif_output_name, mockturtle::blif_reader(klut)); + assert(read_blif_return_code == lorina::return_code::success); + mockturtle::xag_npn_resynthesis resyn; + mockturtle::node_resynthesis(this->optimal, klut, resyn); + this->optimal.set_network_name(this->converted.get_network_name()); + } +}; +}; diff --git a/core/algorithms/optimization/optimizers/aig.hpp b/core/algorithms/optimization/optimizers/aig.hpp new file mode 100644 index 000000000..6cfa3fca7 --- /dev/null +++ b/core/algorithms/optimization/optimizers/aig.hpp @@ -0,0 +1,231 @@ +/* LSOracle: A learning based Oracle for Logic Synthesis + + * MIT License + * Copyright 2019 Laboratory for Nano Integrated Systems (LNIS) + * + * 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. + */ +#pragma once +#include +#include +#include "algorithms/optimization/aig_script.hpp" +#include "algorithms/optimization/aig_script2.hpp" +#include "algorithms/optimization/aig_script3.hpp" +#include "algorithms/optimization/aig_script4.hpp" +#include "algorithms/optimization/aig_script5.hpp" + +#include "algorithms/optimization/optimizers/techmapping.hpp" + +namespace oracle { + using xmg_names = mockturtle::names_view; + using aig_names = mockturtle::names_view; + using xmg_partition = mockturtle::window_view>; + +template +class aig_optimizer: public optimizer +{ + using partition = mockturtle::window_view>; + +public: + aig_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): index(index), original(original), strategy(target), abc_exec(abc_exec) + { + } + + xmg_names export_superset() + { + mockturtle::direct_resynthesis resyn; + return mockturtle::node_resynthesis(optimal, resyn); + } + + void convert() + { + mockturtle::xag_npn_resynthesis resyn; + converted = mockturtle::node_resynthesis (original, resyn); + converted.set_network_name("partition_" + std::to_string(index)); + } + + aig_names optimized() + { + return optimal; + } + + node_depth independent_metric() + { + mockturtle::depth_view part_aig_opt_depth{optimal}; + int aig_opt_size = optimal.num_gates(); + int aig_opt_depth = part_aig_opt_depth.depth(); + metric = node_depth{aig_opt_size, aig_opt_depth}; + return metric; + } + + std::string techmap(const std::string &liberty_file, const std::string &temp_prefix) + { + if (techmapped.empty()) { + + std::string script = + "read_lib " + liberty_file + + "; strash; dch; map -B 0.9; topo; stime -c; buffer -c; upsize -c; dnsize -c"; + techmapped = basic_techmap ( + script, abc_exec, optimal, temp_prefix); + } + return techmapped; + } + + optimization_strategy target() + { + return strategy; + } +protected: + int index; + partition original; + aig_names optimal; + aig_names converted; + node_depth metric; + std::string techmapped; + optimization_strategy strategy; + const std::string &abc_exec; +}; +template class aig_optimizer; + + + +template +class aigscript_optimizer: public aig_optimizer +{ + using partition = mockturtle::window_view>; + using xmg_partition = mockturtle::window_view>; +public: + aigscript_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): aig_optimizer(index, original, target, abc_exec) {} + + optimizer *reapply(int index, const xmg_partition &part) + { + return new aigscript_optimizer(index, part, this->strategy, this->abc_exec); + } + + const std::string optimizer_name() + { + return "aigscript"; + } + + void optimize() + { + oracle::aig_script opt; + this->optimal = opt.run(this->converted); + } +}; + +template +class aigscript2_optimizer: public aig_optimizer +{ + using partition = mockturtle::window_view>; +public: + aigscript2_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): aig_optimizer(index, original, target, abc_exec) {} + + optimizer *reapply(int index, const xmg_partition &part) + { + return new aigscript2_optimizer(index, part, this->strategy, this->abc_exec); + } + + const std::string optimizer_name() + { + return "aigscript2"; + } + + void optimize() + { + oracle::aig_script2 opt; + this->optimal = opt.run(this->converted); + } +}; + +template +class aigscript3_optimizer: public aig_optimizer +{ + using partition = mockturtle::window_view>; +public: + aigscript3_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): aig_optimizer(index, original, target, abc_exec) {} + + optimizer *reapply(int index, const xmg_partition &part) + { + return new aigscript3_optimizer(index, part, this->strategy, this->abc_exec); + } + + const std::string optimizer_name() + { + return "aigscript3"; + } + + void optimize() + { + oracle::aig_script3 opt; + this->optimal = opt.run(this->converted); + } +}; + +template +class aigscript4_optimizer: public aig_optimizer +{ + using partition = mockturtle::window_view>; +public: + aigscript4_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): aig_optimizer(index, original, target, abc_exec) {} + + optimizer *reapply(int index, const xmg_partition &part) + { + return new aigscript4_optimizer(index, part, this->strategy, this->abc_exec); + } + + const std::string optimizer_name() + { + return "aigscript4"; + } + + void optimize() + { + oracle::aig_script4 opt; + this->optimal = opt.run(this->converted); + } +}; + +template +class aigscript5_optimizer: public aig_optimizer +{ + using partition = mockturtle::window_view>; +public: + aigscript5_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): aig_optimizer(index, original, target, abc_exec) {} + + optimizer *reapply(int index, const xmg_partition &part) + { + return new aigscript5_optimizer(index, part, this->strategy, this->abc_exec); + } + + const std::string optimizer_name() + { + return "aigscript5"; + } + + void optimize() + { + oracle::aig_script5 opt; + this->optimal = opt.run(this->converted); + } +}; +}; diff --git a/core/algorithms/optimization/optimizers/mig.hpp b/core/algorithms/optimization/optimizers/mig.hpp new file mode 100644 index 000000000..b8483af18 --- /dev/null +++ b/core/algorithms/optimization/optimizers/mig.hpp @@ -0,0 +1,179 @@ +/* LSOracle: A learning based Oracle for Logic Synthesis + + * MIT License + * Copyright 2019 Laboratory for Nano Integrated Systems (LNIS) + * + * 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. + */ +#pragma once +#include +#include +#include "algorithms/optimization/optimizers/techmapping.hpp" +#include "algorithms/optimization/mig_script.hpp" +#include "algorithms/optimization/mig_script2.hpp" +#include "algorithms/optimization/mig_script3.hpp" + +namespace oracle { +template +class mig_optimizer: public optimizer +{ + using names = mockturtle::names_view; + using partition = mockturtle::window_view; + using manager = mockturtle::window_view; + +public: + mig_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): index(index), original(original), strategy(target), abc_exec(abc_exec) + { + } + + xmg_names export_superset() + { + mockturtle::direct_resynthesis resyn; + return mockturtle::node_resynthesis + (optimal, resyn); + } + + void convert() + { + // mockturtle::mig_npn_resynthesis resyn; + mockturtle::direct_resynthesis resyn; + converted = + mockturtle::node_resynthesis>> + (original, resyn); + converted.set_network_name("partition_" + std::to_string(index)); + + } + + mig_names optimized() + { + return optimal; + } + + node_depth independent_metric() + { + mockturtle::depth_view part_mig_opt_depth{optimal}; + int mig_opt_size = optimal.num_gates(); + int mig_opt_depth = part_mig_opt_depth.depth(); + metric = node_depth{mig_opt_size, mig_opt_depth}; + return metric; + } + + std::string techmap(const std::string &liberty_file, const std::string &temp_prefix) + { + if (techmapped.empty()) { + std::string script = + "read_lib " + liberty_file + + "; strash; dch; map -B 0.9; topo; stime -c; buffer -c; upsize -c; dnsize -c"; + techmapped = basic_techmap (script, abc_exec, optimal, temp_prefix); + } + return techmapped; + } + + optimization_strategy target() + { + return strategy; + } +protected: + int index; + partition original; + mig_names optimal; + mig_names converted; + node_depth metric; + std::string techmapped; + std::string name; + optimization_strategy strategy; + const std::string &abc_exec; +}; +template class mig_optimizer; + +template +class migscript_optimizer: public mig_optimizer +{ + using partition = mockturtle::window_view>; +public: + migscript_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): mig_optimizer(index, original, target, abc_exec) {} + + const std::string optimizer_name() + { + return "migscript"; + } + + optimizer *reapply(int index, const xmg_partition &part) + { + return new migscript_optimizer(index, part, this->strategy, this->abc_exec); + } + + void optimize() + { + oracle::mig_script migopt; + this->optimal = migopt.run(this->converted); + } +}; + +template +class migscript2_optimizer: public mig_optimizer +{ + using partition = mockturtle::window_view>; +public: + migscript2_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): mig_optimizer(index, original, target, abc_exec) {} + + const std::string optimizer_name() + { + return "migscript2"; + } + + optimizer *reapply(int index, const xmg_partition &part) + { + return new migscript2_optimizer(index, part, this->strategy, this->abc_exec); + } + + void optimize() + { + oracle::mig_script2 migopt; + this->optimal = migopt.run(this->converted); + } +}; + +template +class migscript3_optimizer: public mig_optimizer +{ + using partition = mockturtle::window_view>; +public: + migscript3_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): mig_optimizer(index, original, target, abc_exec) {} + + optimizer *reapply(int index, const xmg_partition &part) + { + return new migscript3_optimizer(index, part, this->strategy, this->abc_exec); + } + + const std::string optimizer_name() + { + return "migscript3"; + } + + void optimize() + { + oracle::mig_script3 migopt; + this->optimal = migopt.run(this->converted); + } +}; +}; diff --git a/core/algorithms/optimization/optimizers/noop.hpp b/core/algorithms/optimization/optimizers/noop.hpp new file mode 100644 index 000000000..aeccea0b3 --- /dev/null +++ b/core/algorithms/optimization/optimizers/noop.hpp @@ -0,0 +1,124 @@ +/* LSOracle: A learning based Oracle for Logic Synthesis + + * MIT License + * Copyright 2019 Laboratory for Nano Integrated Systems (LNIS) + * + * 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. + */ +#pragma once + +namespace oracle { + +template +class noop: public optimizer +{ + using names = mockturtle::names_view; + using partition = mockturtle::window_view; + // using manager = partition_manager_junior; + +public: + noop(int index, const partition &part, optimization_strategy target, const std::string &abc_exec): index(index), original(part), strategy(target), abc_exec(abc_exec) + { + } + + const std::string optimizer_name() + { + return "noop"; + } + + + optimizer *reapply(int index, const xmg_partition &part) + { + return new noop(index, part, this->strategy, this->abc_exec); + } + + + // mockturtle::window_view> partition() + // { + // return partman.create_part(ntk, index); + // } + + optimization_strategy target() + { + return strategy; + } + + xmg_names export_superset() + { + mockturtle::direct_resynthesis resyn; + return mockturtle::node_resynthesis(copy, resyn); + } + + /* + * Do direct resynthesis to create a copy. + */ + void convert() + { + // partition original = partman.partition(index); + // // original.set_network_name("partition_" + std::to_string(index)); // TODO not working? + mockturtle::direct_resynthesis resyn; + copy = mockturtle::node_resynthesis (original, resyn); + copy.set_network_name("partition_" + std::to_string(index)); + } + + names optimized() + { + return copy; + } + + void optimize() + { + } + + std::string techmap(const std::string &liberty_file, const std::string &temp_prefix) + { + if (techmapped.empty()) { + std::string script = + "read_lib " + liberty_file + + "; strash; dch; map -B 0.9; topo; stime -c; buffer -c; upsize -c; dnsize -c;"; + techmapped = basic_techmap(script, abc_exec, copy, temp_prefix); + } + return techmapped; + } + + node_depth independent_metric() + { + mockturtle::depth_view part_depth(copy); + int opt_size = part_depth.num_gates(); + int opt_depth = part_depth.depth(); + metric = node_depth{opt_size, opt_depth}; + return metric; + } +private: + int index; + partition original; + names copy; + node_depth metric; + optimization_strategy strategy; + std::string techmapped; + const std::string &abc_exec; +}; +template class noop; +template class noop; +template class noop; +template class noop; +}; diff --git a/core/algorithms/optimization/optimizers/techmapping.hpp b/core/algorithms/optimization/optimizers/techmapping.hpp new file mode 100644 index 000000000..732250428 --- /dev/null +++ b/core/algorithms/optimization/optimizers/techmapping.hpp @@ -0,0 +1,91 @@ +/* LSOracle: A learning based Oracle for Logic Synthesis + + * MIT License + * Copyright 2019 Laboratory for Nano Integrated Systems (LNIS) + * + * 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. + */ +#pragma once +#include +#include + + +namespace oracle { +using xmg_names = mockturtle::names_view; +using aig_names = mockturtle::names_view; +using mig_names = mockturtle::names_view; +using xag_names = mockturtle::names_view; + +template +std::string basic_techmap(const std::string &tech_script, const std::string &abc_exec, const T &optimal, const std::string &temp_prefix) +{ + std::cout << "starting basic techmapping" << std::endl; + std::string input_blif, output_verilog, abc_script; + if (temp_prefix.empty()) { + char *blif = strdup("/tmp/lsoracle_XXXXXX.blif"); + if (mkstemps(blif, 5) == -1) { + throw std::exception(); + } + input_blif = std::string(blif); + + char *verilog = strdup("/tmp/lsoracle_XXXXXX.v"); + if (mkstemps(verilog, 2) == -1) { + throw std::exception(); + } + output_verilog = std::string(verilog); + + char *abc = strdup("/tmp/lsoracle_XXXXXX.abc"); + if (mkstemps(abc, 4) == -1) { + throw std::exception(); + } + abc_script = std::string(abc); + } else { + input_blif = fmt::format("{}.{}.tech.blif", temp_prefix, optimal.get_network_name()); + output_verilog = fmt::format("{}.{}.tech.v", temp_prefix, optimal.get_network_name()); + abc_script = fmt::format("{}.{}.tech.abc", temp_prefix, optimal.get_network_name()); + } + + std::cout << "generated blif " << input_blif << std::endl; + std::cout << "writing output to " << output_verilog << std::endl; + std::cout << "generated ABC script " << abc_script << std::endl; + + std::ofstream script(abc_script); + script << "print_fanio; " << tech_script << "; print_fanio;" << std::endl; + script.close(); + std::cout << "calling ABC" << std::endl; + mockturtle::write_blif_params ps; + ps.skip_feedthrough = 1u; + mockturtle::write_blif(optimal, input_blif, ps); + int code = system((abc_exec + " -F " + abc_script + + " -o " + output_verilog + + " " + input_blif).c_str()); + assert(code == 0); + std::cout << "done techmapping" << std::endl; + // TODO close everything + return output_verilog; +}; +template std::string basic_techmap(const std::string &, const std::string &, const aig_names &, const std::string &); +template std::string basic_techmap(const std::string &, const std::string &, const xag_names &, const std::string &); +template std::string basic_techmap(const std::string &, const std::string &, const mig_names &, const std::string &); +template std::string basic_techmap(const std::string &, const std::string &, const xmg_names &, const std::string &); + +}; diff --git a/core/algorithms/optimization/optimizers/xag.hpp b/core/algorithms/optimization/optimizers/xag.hpp new file mode 100644 index 000000000..4598e3924 --- /dev/null +++ b/core/algorithms/optimization/optimizers/xag.hpp @@ -0,0 +1,116 @@ +/* LSOracle: A learning based Oracle for Logic Synthesis + + * MIT License + * Copyright 2019 Laboratory for Nano Integrated Systems (LNIS) + * + * 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. + */ +#pragma once +namespace oracle { +#include +#include +#include "algorithms/optimization/optimizers/techmapping.hpp" +#include "algorithms/optimization/xag_script.hpp" + +template +class xag_optimizer: public optimizer +{ + using partition = mockturtle::window_view>; +public: + xag_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): index(index), original(original), strategy(target), abc_exec(abc_exec) + { + } + + xmg_names export_superset() + { + mockturtle::direct_resynthesis resyn; + return mockturtle::node_resynthesis(optimal, resyn); + } + + optimizer *reapply(int index, const xmg_partition &part) + { + return new xag_optimizer(index, part, this->strategy, this->abc_exec); + } + + void convert() + { + mockturtle::xag_npn_resynthesis resyn; + converted = mockturtle::node_resynthesis (original, resyn); + converted.set_network_name("partition_" + std::to_string(index)); + } + + xag_names optimized() + { + return optimal; + } + + node_depth independent_metric() + { + mockturtle::depth_view part_xag_opt_depth{optimal}; + int xag_opt_size = optimal.num_gates(); + int xag_opt_depth = part_xag_opt_depth.depth(); + metric = node_depth{xag_opt_size, xag_opt_depth}; + return metric; + } + + std::string techmap(const std::string &liberty_file, const std::string &temp_prefix) + { + if (techmapped.empty()) { + + std::string script = + "read_lib " + liberty_file + + "; strash; dch; map -B 0.9; topo; stime -c; buffer -c; upsize -c; dnsize -c"; + techmapped = basic_techmap ( + script, abc_exec, optimal, temp_prefix); + } + return techmapped; + } + + const std::string optimizer_name() + { + return "xagscript"; + } + + void optimize() + { + oracle::xag_script opt; + this->optimal = opt.run(this->converted); + } + + optimization_strategy target() + { + return strategy; + } + +protected: + int index; + partition original; + xag_names optimal; + xag_names converted; + node_depth metric; + std::string techmapped; + optimization_strategy strategy; + const std::string &abc_exec; +}; +template class xag_optimizer; + +} diff --git a/core/algorithms/optimization/optimizers/xmg.hpp b/core/algorithms/optimization/optimizers/xmg.hpp new file mode 100644 index 000000000..c1e30ecf6 --- /dev/null +++ b/core/algorithms/optimization/optimizers/xmg.hpp @@ -0,0 +1,114 @@ +/* LSOracle: A learning based Oracle for Logic Synthesis + + * MIT License + * Copyright 2019 Laboratory for Nano Integrated Systems (LNIS) + * + * 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. + */ +#pragma once +#include +#include +#include "algorithms/optimization/optimizers/techmapping.hpp" +#include "algorithms/optimization/xmg_script.hpp" + +namespace oracle { +template +class xmg_optimizer: public optimizer +{ + using partition = mockturtle::window_view>; +public: + xmg_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): index(index), original(original), strategy(target), abc_exec(abc_exec) + { + } + + optimizer *reapply(int index, const xmg_partition &part) + { + return new xmg_optimizer(index, part, this->strategy, this->abc_exec); + } + + xmg_names export_superset() + { + mockturtle::direct_resynthesis resyn; + return mockturtle::node_resynthesis(optimal, resyn); + } + + void convert() + { + mockturtle::xmg_npn_resynthesis resyn; + converted = mockturtle::node_resynthesis(original, resyn); + converted.set_network_name("partition_" + std::to_string(index)); + } + + xmg_names optimized() + { + return optimal; + } + + node_depth independent_metric() + { + mockturtle::depth_view part_xmg_opt_depth{optimal}; + int xmg_opt_size = optimal.num_gates(); + int xmg_opt_depth = part_xmg_opt_depth.depth(); + metric = node_depth{xmg_opt_size, xmg_opt_depth}; + return metric; + } + + std::string techmap(const std::string &liberty_file, const std::string &temp_prefix) + { + if (techmapped.empty()) { + std::string script = + "read_lib " + liberty_file + + "; strash; dch; map -B 0.9; topo; stime -c; buffer -c; upsize -c; dnsize -c"; + techmapped = basic_techmap ( + script, abc_exec, optimal, temp_prefix); + } + return techmapped; + } + + const std::string optimizer_name() + { + return "xmgscript"; + } + + void optimize() + { + xmg_script opt; + this->optimal = opt.run(this->converted); + } + + optimization_strategy target() + { + return strategy; + } + +protected: + int index; + partition original; + xmg_names optimal; + xmg_names converted; + node_depth metric; + std::string techmapped; + optimization_strategy strategy; + const std::string &abc_exec; +}; +template class xmg_optimizer; +}; diff --git a/core/algorithms/optimization/resynthesis.cpp b/core/algorithms/optimization/resynthesis.cpp index 8cff58db0..7a5c381d3 100644 --- a/core/algorithms/optimization/resynthesis.cpp +++ b/core/algorithms/optimization/resynthesis.cpp @@ -57,18 +57,10 @@ extern int Sta_Init(Tcl_Interp *interp); #include #include #include "algorithms/optimization/resynthesis.hpp" -#include "algorithms/optimization/mig_script.hpp" -#include "algorithms/optimization/mig_script2.hpp" -#include "algorithms/optimization/mig_script3.hpp" -#include "algorithms/optimization/aig_script.hpp" -#include "algorithms/optimization/aig_script2.hpp" -#include "algorithms/optimization/aig_script3.hpp" -#include "algorithms/optimization/aig_script4.hpp" -#include "algorithms/optimization/aig_script5.hpp" -#include "algorithms/optimization/xag_script.hpp" -#include "algorithms/optimization/xmg_script.hpp" #include "algorithms/partitioning/slack_view.hpp" #include "utility.hpp" +#include "algorithms/optimization/optimizer.hpp" + // TODO replace "pi/po" with "ci/co" namespace oracle { @@ -79,59 +71,6 @@ using xmg_names = mockturtle::names_view; using xmg_manager = partition_manager_junior; using xmg_partition = mockturtle::window_view>; -template -std::string basic_techmap(const std::string &tech_script, const std::string &abc_exec, const T &optimal, const std::string &temp_prefix) -{ - std::cout << "starting basic techmapping" << std::endl; - std::string input_blif, output_verilog, abc_script; - if (temp_prefix.empty()) { - char *blif = strdup("/tmp/lsoracle_XXXXXX.blif"); - if (mkstemps(blif, 5) == -1) { - throw std::exception(); - } - input_blif = std::string(blif); - - char *verilog = strdup("/tmp/lsoracle_XXXXXX.v"); - if (mkstemps(verilog, 2) == -1) { - throw std::exception(); - } - output_verilog = std::string(verilog); - - char *abc = strdup("/tmp/lsoracle_XXXXXX.abc"); - if (mkstemps(abc, 4) == -1) { - throw std::exception(); - } - abc_script = std::string(abc); - } else { - input_blif = fmt::format("{}.{}.tech.blif", temp_prefix, optimal.get_network_name()); - output_verilog = fmt::format("{}.{}.tech.v", temp_prefix, optimal.get_network_name()); - abc_script = fmt::format("{}.{}.tech.abc", temp_prefix, optimal.get_network_name()); - } - - std::cout << "generated blif " << input_blif << std::endl; - std::cout << "writing output to " << output_verilog << std::endl; - std::cout << "generated ABC script " << abc_script << std::endl; - - std::ofstream script(abc_script); - script << "print_fanio; " << tech_script << "; print_fanio;" << std::endl; - script.close(); - std::cout << "calling ABC" << std::endl; - mockturtle::write_blif_params ps; - ps.skip_feedthrough = 1u; - mockturtle::write_blif(optimal, input_blif, ps); - int code = system((abc_exec + " -F " + abc_script + - " -o " + output_verilog + - " " + input_blif).c_str()); - assert(code == 0); - std::cout << "done techmapping" << std::endl; - // TODO close everything - return output_verilog; -}; -template std::string basic_techmap(const std::string &, const std::string &, const aig_names &, const std::string &); -template std::string basic_techmap(const std::string &, const std::string &, const xag_names &, const std::string &); -template std::string basic_techmap(const std::string &, const std::string &, const mig_names &, const std::string &); -template std::string basic_techmap(const std::string &, const std::string &, const xmg_names &, const std::string &); - template std::string get_po_name_or_default(const network &ntk, const typename network::signal &signal) { int index = ntk.po_index(signal); @@ -240,760 +179,6 @@ mockturtle::window_view> fix_names2(partition_ma return part; } -template -class noop: public optimizer -{ - using names = mockturtle::names_view; - using partition = mockturtle::window_view; - // using manager = partition_manager_junior; - -public: - noop(int index, const partition &part, optimization_strategy target, const std::string &abc_exec): index(index), original(part), strategy(target), abc_exec(abc_exec) - { - } - - const std::string optimizer_name() - { - return "noop"; - } - - - optimizer *reapply(int index, const xmg_partition &part) - { - return new noop(index, part, this->strategy, this->abc_exec); - } - - - // mockturtle::window_view> partition() - // { - // return partman.create_part(ntk, index); - // } - - optimization_strategy target() - { - return strategy; - } - - xmg_names export_superset() - { - mockturtle::direct_resynthesis resyn; - return mockturtle::node_resynthesis(copy, resyn); - } - - /* - * Do direct resynthesis to create a copy. - */ - void convert() - { - // partition original = partman.partition(index); - // // original.set_network_name("partition_" + std::to_string(index)); // TODO not working? - mockturtle::direct_resynthesis resyn; - copy = mockturtle::node_resynthesis (original, resyn); - copy.set_network_name("partition_" + std::to_string(index)); - } - - names optimized() - { - return copy; - } - - void optimize() - { - } - - std::string techmap(const std::string &liberty_file, const std::string &temp_prefix) - { - if (techmapped.empty()) { - string script = - "read_lib " + liberty_file + - "; strash; dch; map -B 0.9; topo; stime -c; buffer -c; upsize -c; dnsize -c;"; - techmapped = basic_techmap(script, abc_exec, copy, temp_prefix); - } - return techmapped; - } - - node_depth independent_metric() - { - mockturtle::depth_view part_depth(copy); - int opt_size = part_depth.num_gates(); - int opt_depth = part_depth.depth(); - metric = node_depth{opt_size, opt_depth}; - return metric; - } -private: - int index; - partition original; - names copy; - node_depth metric; - optimization_strategy strategy; - std::string techmapped; - const std::string &abc_exec; -}; -template class noop; -template class noop; -template class noop; -template class noop; - -template -class mig_optimizer: public optimizer -{ - using names = mockturtle::names_view; - using partition = mockturtle::window_view; - using manager = mockturtle::window_view; - -public: - mig_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): index(index), original(original), strategy(target), abc_exec(abc_exec) - { - } - - xmg_names export_superset() - { - mockturtle::direct_resynthesis resyn; - return mockturtle::node_resynthesis - (optimal, resyn); - } - - void convert() - { - // mockturtle::mig_npn_resynthesis resyn; - mockturtle::direct_resynthesis resyn; - converted = - mockturtle::node_resynthesis>> - (original, resyn); - converted.set_network_name("partition_" + std::to_string(index)); - - } - - mig_names optimized() - { - return optimal; - } - - node_depth independent_metric() - { - mockturtle::depth_view part_mig_opt_depth{optimal}; - int mig_opt_size = optimal.num_gates(); - int mig_opt_depth = part_mig_opt_depth.depth(); - metric = node_depth{mig_opt_size, mig_opt_depth}; - return metric; - } - - std::string techmap(const std::string &liberty_file, const std::string &temp_prefix) - { - if (techmapped.empty()) { - string script = - "read_lib " + liberty_file + - "; strash; dch; map -B 0.9; topo; stime -c; buffer -c; upsize -c; dnsize -c"; - techmapped = basic_techmap (script, abc_exec, optimal, temp_prefix); - } - return techmapped; - } - - optimization_strategy target() - { - return strategy; - } -protected: - int index; - partition original; - mig_names optimal; - mig_names converted; - node_depth metric; - string techmapped; - string name; - optimization_strategy strategy; - const std::string &abc_exec; -}; -template class mig_optimizer; - -template -class aig_optimizer: public optimizer -{ - using partition = mockturtle::window_view>; -public: - aig_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): index(index), original(original), strategy(target), abc_exec(abc_exec) - { - } - - xmg_names export_superset() - { - mockturtle::direct_resynthesis resyn; - return mockturtle::node_resynthesis(optimal, resyn); - } - - void convert() - { - mockturtle::xag_npn_resynthesis resyn; - converted = mockturtle::node_resynthesis (original, resyn); - converted.set_network_name("partition_" + std::to_string(index)); - } - - aig_names optimized() - { - return optimal; - } - - node_depth independent_metric() - { - mockturtle::depth_view part_aig_opt_depth{optimal}; - int aig_opt_size = optimal.num_gates(); - int aig_opt_depth = part_aig_opt_depth.depth(); - metric = node_depth{aig_opt_size, aig_opt_depth}; - return metric; - } - - std::string techmap(const std::string &liberty_file, const std::string &temp_prefix) - { - if (techmapped.empty()) { - - string script = - "read_lib " + liberty_file + - "; strash; dch; map -B 0.9; topo; stime -c; buffer -c; upsize -c; dnsize -c"; - techmapped = basic_techmap ( - script, abc_exec, optimal, temp_prefix); - } - return techmapped; - } - - optimization_strategy target() - { - return strategy; - } -protected: - int index; - partition original; - aig_names optimal; - aig_names converted; - node_depth metric; - string techmapped; - optimization_strategy strategy; - const std::string &abc_exec; -}; -template class aig_optimizer; - - -template< typename network> -class abc_optimizer: public aig_optimizer -{ - using partition = mockturtle::window_view>; -public: - abc_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): aig_optimizer(index, original, target, abc_exec) {} - - const std::string optimizer_name() - { - return "abc resyn2"; - } - - optimizer *reapply(int index, const xmg_partition &part) - { - return new abc_optimizer(index, part, this->strategy, this->abc_exec); - } - - void optimize() - { - char *blif_name_char = strdup("/tmp/lsoracle_XXXXXX.blif"); - if (mkstemps(blif_name_char, 5) == -1) { - throw std::exception(); - } - std::string blif_name = std::string(blif_name_char); - std::cout << "writing blif to " << blif_name << std::endl; - - char *blif_output_name_char = strdup("/tmp/lsoracle_XXXXXX_optimized.blif"); - if (mkstemps(blif_output_name_char, 15) == -1) { - throw std::exception(); - } - std::string blif_output_name = std::string(blif_output_name_char); - std::cout << "writing abc output to " << blif_output_name << std::endl; - - mockturtle::write_blif_params ps; - ps.skip_feedthrough = 1u; - mockturtle::write_blif(this->converted, blif_name, ps); - std::string script = "abc -c \"read_blif " + blif_name + "; resyn2; write_blif " + blif_output_name + " \""; - int code = system((script).c_str()); - assert(code == 0); - std::cout << "optimized with abc" << std::endl; - - mockturtle::names_view klut; - lorina::return_code read_blif_return_code = lorina::read_blif(blif_output_name, mockturtle::blif_reader(klut)); - assert(read_blif_return_code == lorina::return_code::success); - mockturtle::xag_npn_resynthesis resyn; - mockturtle::node_resynthesis(this->optimal, klut, resyn); - this->optimal.set_network_name(this->converted.get_network_name()); - } -}; - -template -class xag_optimizer: public optimizer -{ - using partition = mockturtle::window_view>; -public: - xag_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): index(index), original(original), strategy(target), abc_exec(abc_exec) - { - } - - xmg_names export_superset() - { - mockturtle::direct_resynthesis resyn; - return mockturtle::node_resynthesis(optimal, resyn); - } - - optimizer *reapply(int index, const xmg_partition &part) - { - return new xag_optimizer(index, part, this->strategy, this->abc_exec); - } - - void convert() - { - mockturtle::xag_npn_resynthesis resyn; - converted = mockturtle::node_resynthesis (original, resyn); - converted.set_network_name("partition_" + std::to_string(index)); - } - - xag_names optimized() - { - return optimal; - } - - node_depth independent_metric() - { - mockturtle::depth_view part_xag_opt_depth{optimal}; - int xag_opt_size = optimal.num_gates(); - int xag_opt_depth = part_xag_opt_depth.depth(); - metric = node_depth{xag_opt_size, xag_opt_depth}; - return metric; - } - - std::string techmap(const std::string &liberty_file, const std::string &temp_prefix) - { - if (techmapped.empty()) { - - string script = - "read_lib " + liberty_file + - "; strash; dch; map -B 0.9; topo; stime -c; buffer -c; upsize -c; dnsize -c"; - techmapped = basic_techmap ( - script, abc_exec, optimal, temp_prefix); - } - return techmapped; - } - - const std::string optimizer_name() - { - return "xagscript"; - } - - void optimize() - { - oracle::xag_script opt; - this->optimal = opt.run(this->converted); - } - - optimization_strategy target() - { - return strategy; - } - -protected: - int index; - partition original; - xag_names optimal; - xag_names converted; - node_depth metric; - string techmapped; - optimization_strategy strategy; - const std::string &abc_exec; -}; -template class xag_optimizer; - -template -class xmg_optimizer: public optimizer -{ - using partition = mockturtle::window_view>; -public: - xmg_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): index(index), original(original), strategy(target), abc_exec(abc_exec) - { - } - - optimizer *reapply(int index, const xmg_partition &part) - { - return new xmg_optimizer(index, part, this->strategy, this->abc_exec); - } - - xmg_names export_superset() - { - mockturtle::direct_resynthesis resyn; - return mockturtle::node_resynthesis(optimal, resyn); - } - - void convert() - { - mockturtle::xmg_npn_resynthesis resyn; - converted = mockturtle::node_resynthesis(original, resyn); - converted.set_network_name("partition_" + std::to_string(index)); - } - - xmg_names optimized() - { - return optimal; - } - - node_depth independent_metric() - { - mockturtle::depth_view part_xmg_opt_depth{optimal}; - int xmg_opt_size = optimal.num_gates(); - int xmg_opt_depth = part_xmg_opt_depth.depth(); - metric = node_depth{xmg_opt_size, xmg_opt_depth}; - return metric; - } - - std::string techmap(const std::string &liberty_file, const std::string &temp_prefix) - { - if (techmapped.empty()) { - string script = - "read_lib " + liberty_file + - "; strash; dch; map -B 0.9; topo; stime -c; buffer -c; upsize -c; dnsize -c"; - techmapped = basic_techmap ( - script, abc_exec, optimal, temp_prefix); - } - return techmapped; - } - - const std::string optimizer_name() - { - return "xmgscript"; - } - - void optimize() - { - oracle::xmg_script opt; - this->optimal = opt.run(this->converted); - } - - optimization_strategy target() - { - return strategy; - } - -protected: - int index; - partition original; - xmg_names optimal; - xmg_names converted; - node_depth metric; - string techmapped; - optimization_strategy strategy; - const std::string &abc_exec; -}; -template class xmg_optimizer; - -template -class migscript_optimizer: public mig_optimizer -{ - using partition = mockturtle::window_view>; -public: - migscript_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): mig_optimizer(index, original, target, abc_exec) {} - - const std::string optimizer_name() - { - return "migscript"; - } - - optimizer *reapply(int index, const xmg_partition &part) - { - return new migscript_optimizer(index, part, this->strategy, this->abc_exec); - } - - void optimize() - { - oracle::mig_script migopt; - this->optimal = migopt.run(this->converted); - } -}; - -template -class migscript2_optimizer: public mig_optimizer -{ - using partition = mockturtle::window_view>; -public: - migscript2_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): mig_optimizer(index, original, target, abc_exec) {} - - const std::string optimizer_name() - { - return "migscript2"; - } - - optimizer *reapply(int index, const xmg_partition &part) - { - return new migscript2_optimizer(index, part, this->strategy, this->abc_exec); - } - - void optimize() - { - oracle::mig_script2 migopt; - this->optimal = migopt.run(this->converted); - } -}; - -template -class migscript3_optimizer: public mig_optimizer -{ - using partition = mockturtle::window_view>; -public: - migscript3_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): mig_optimizer(index, original, target, abc_exec) {} - - optimizer *reapply(int index, const xmg_partition &part) - { - return new migscript3_optimizer(index, part, this->strategy, this->abc_exec); - } - - const std::string optimizer_name() - { - return "migscript3"; - } - - void optimize() - { - oracle::mig_script3 migopt; - this->optimal = migopt.run(this->converted); - } -}; - -template -class aigscript_optimizer: public aig_optimizer -{ - using partition = mockturtle::window_view>; -public: - aigscript_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): aig_optimizer(index, original, target, abc_exec) {} - - optimizer *reapply(int index, const xmg_partition &part) - { - return new aigscript_optimizer(index, part, this->strategy, this->abc_exec); - } - - const std::string optimizer_name() - { - return "aigscript"; - } - - void optimize() - { - oracle::aig_script opt; - this->optimal = opt.run(this->converted); - } -}; - -template -class aigscript2_optimizer: public aig_optimizer -{ - using partition = mockturtle::window_view>; -public: - aigscript2_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): aig_optimizer(index, original, target, abc_exec) {} - - optimizer *reapply(int index, const xmg_partition &part) - { - return new aigscript2_optimizer(index, part, this->strategy, this->abc_exec); - } - - const std::string optimizer_name() - { - return "aigscript2"; - } - - void optimize() - { - oracle::aig_script2 opt; - this->optimal = opt.run(this->converted); - } -}; - -template -class aigscript3_optimizer: public aig_optimizer -{ - using partition = mockturtle::window_view>; -public: - aigscript3_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): aig_optimizer(index, original, target, abc_exec) {} - - optimizer *reapply(int index, const xmg_partition &part) - { - return new aigscript3_optimizer(index, part, this->strategy, this->abc_exec); - } - - const std::string optimizer_name() - { - return "aigscript3"; - } - - void optimize() - { - oracle::aig_script3 opt; - this->optimal = opt.run(this->converted); - } -}; - -template -class aigscript4_optimizer: public aig_optimizer -{ - using partition = mockturtle::window_view>; -public: - aigscript4_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): aig_optimizer(index, original, target, abc_exec) {} - - optimizer *reapply(int index, const xmg_partition &part) - { - return new aigscript4_optimizer(index, part, this->strategy, this->abc_exec); - } - - const std::string optimizer_name() - { - return "aigscript4"; - } - - void optimize() - { - oracle::aig_script4 opt; - this->optimal = opt.run(this->converted); - } -}; - -template -class aigscript5_optimizer: public aig_optimizer -{ - using partition = mockturtle::window_view>; -public: - aigscript5_optimizer(int index, const partition &original, optimization_strategy target, const std::string &abc_exec): aig_optimizer(index, original, target, abc_exec) {} - - optimizer *reapply(int index, const xmg_partition &part) - { - return new aigscript5_optimizer(index, part, this->strategy, this->abc_exec); - } - - const std::string optimizer_name() - { - return "aigscript5"; - } - - void optimize() - { - oracle::aig_script5 opt; - this->optimal = opt.run(this->converted); - } -}; - -template -class optimization_strategy_comparator { -public: - // Comparator function - virtual bool operator()(optimizer &a, optimizer &b) = 0; - virtual const string name() = 0; -}; - -template -class ndp_strategy : public optimization_strategy_comparator -{ - bool operator()(optimizer &a, optimizer &b) - { - node_depth x = a.independent_metric(); - node_depth y = b.independent_metric(); - - return x.nodes * x.depth < y.nodes * y.depth; - } - const string name() - { - return "node-depth product"; - } -}; - -template -class d_strategy : public optimization_strategy_comparator -{ - bool operator()(optimizer &a, optimizer &b) - { - node_depth x = a.independent_metric(); - node_depth y = b.independent_metric(); - - return x.depth < y.depth; - } - const string name() - { - return "depth"; - } -}; - - template - class n_strategy : public optimization_strategy_comparator - { - bool operator()(optimizer &a, optimizer &b) - { - node_depth x = a.independent_metric(); - node_depth y = b.independent_metric(); - - return x.nodes < y.nodes; - } - const string name() - { - return "node"; - } -}; - -template -optimizer *optimize(optimization_strategy_comparator &comparator, - optimization_strategy strategy, - partition_manager_junior &partman, - int index, - const std::string &abc_exec) - -{ - std::cout << "******************************** optimizing partition " << index << " ********************************" << std::endl; - std::cout << "Optimizing based on strategy " << comparator.name() << std::endl; - // mockturtle::window_view> orig = partman.partition(index); - // mockturtle::depth_view part_depth(orig); - // std::cout << "Original depth " << part_depth.depth() << " gates " << part_depth.num_gates() << " size " << part_depth.size() << std::endl; - // todo this is gonna leak memory. - // const mockturtle::window_view> part = partman.partition(index); - // todo remove double network. - // fix_names(partman, part, partman.get_network(), index); - const mockturtle::window_view> part = fix_names2(partman, index); - std::vector*>optimizers { - new noop(index, part, strategy, abc_exec), - new migscript_optimizer(index, part, strategy, abc_exec), - new migscript2_optimizer(index, part, strategy, abc_exec), - new migscript3_optimizer(index, part, strategy, abc_exec), - new aigscript_optimizer(index, part, strategy, abc_exec), - new aigscript2_optimizer(index, part, strategy, abc_exec), - new aigscript3_optimizer(index, part, strategy, abc_exec), - new aigscript4_optimizer(index, part, strategy, abc_exec), - new aigscript5_optimizer(index, part, strategy, abc_exec), - new xmg_optimizer(index, part, strategy, abc_exec), - new xag_optimizer(index, part, strategy, abc_exec), - // new abc_optimizer(index, part, strategy, abc_exec), - }; - optimizer *best = nullptr; - for (auto opt = optimizers.begin(); opt != optimizers.end(); opt++) { - std::cout << "running optimization " << (*opt)->optimizer_name() << std::endl; - // std::cout << "converting network" << std::endl; - (*opt)->convert(); - // std::cout << "trying to optimize" << std::endl; - (*opt)->optimize(); - // std::cout << "checking tech independent metrics." << std::endl; - node_depth result = (*opt)->independent_metric(); - std::cout << "result depth " << result.depth - << " size " << result.nodes << std::endl; - - if (best == nullptr) { - best = *opt; - continue; - } - - if (comparator(**opt, *best)) { - best = *opt; - //std::cout << "found a better result" << std::endl; - continue; - } - } - std::cout << "using " << best->optimizer_name() << " for " << index << std::endl; - - return best; - -} - string join(std::string delim, std::set input) { std::vector data(input.begin(), input.end()); @@ -1457,7 +642,8 @@ template xmg_names optimize_timing( std::vector*> optimized(num_parts); for (int i = 0; i < num_parts; i++) { n_strategy strategy; - optimized[i] = optimize(strategy, optimization_strategy::size, partitions, i, abc_exec); + const mockturtle::window_view> part = fix_names2(partitions, i); + optimized[i] = optimize(strategy, optimization_strategy::size, part, i, abc_exec); } assert(num_parts == optimized.size()); @@ -1477,16 +663,19 @@ template xmg_names optimize_timing( std::cout << "met timing" << std::endl; break; } - if (worst_part == -2) { // TODO this is terrible way to use return value + if (worst_part == -2) { std::cout << "exhausted depth optimization for critical path" << std::endl; break; } if (optimized[worst_part]->target() == optimization_strategy::size) { ndp_strategy strategy; - optimized[worst_part] = optimize(strategy, optimization_strategy::balanced, partitions, worst_part, abc_exec); + const mockturtle::window_view> part = fix_names2(partitions, worst_part); + optimized[worst_part] = optimize(strategy, optimization_strategy::balanced, part, worst_part, abc_exec); } else if (optimized[worst_part]->target() == optimization_strategy::balanced) { d_strategy strategy; - optimized[worst_part] = optimize(strategy, optimization_strategy::depth, partitions, worst_part, abc_exec); + const mockturtle::window_view> part = fix_names2(partitions, worst_part); + + optimized[worst_part] = optimize(strategy, optimization_strategy::depth, part, worst_part, abc_exec); } else if (optimized[worst_part]->target() == optimization_strategy::depth) { std::cout << "previous result was already the best we can do." << std::endl; break; // met timing, or it's the best we can do. @@ -1512,7 +701,9 @@ template xmg_names optimize_resynthesis( std::vector*> optimized(num_parts); for (int i = 0; i < num_parts; i++) { n_strategy strategy; - optimized[i] = optimize(strategy, optimization_strategy::size, partitions, i, abc_exec); + const mockturtle::window_view> part = fix_names2(partitions, i); + + optimized[i] = optimize(strategy, optimization_strategy::size, part, i, abc_exec); } assert(num_parts == optimized.size()); @@ -1528,16 +719,19 @@ template xmg_names optimize_resynthesis( std::cout << "met timing" << std::endl; break; } - if (worst_part == -2) { // TODO this is terrible way to use return value + if (worst_part == -2) { std::cout << "exhausted depth optimization for critical path" << std::endl; break; } if (optimized[worst_part]->target() == optimization_strategy::size) { ndp_strategy strategy; - optimized[worst_part] = optimize(strategy, optimization_strategy::balanced, partitions, worst_part, abc_exec); + const mockturtle::window_view> part = fix_names2(partitions, worst_part); + + optimized[worst_part] = optimize(strategy, optimization_strategy::balanced, part, worst_part, abc_exec); } else if (optimized[worst_part]->target() == optimization_strategy::balanced) { d_strategy strategy; - optimized[worst_part] = optimize(strategy, optimization_strategy::depth, partitions, worst_part, abc_exec); + const mockturtle::window_view> part = fix_names2(partitions, worst_part); + optimized[worst_part] = optimize(strategy, optimization_strategy::depth, part, worst_part, abc_exec); } else if (optimized[worst_part]->target() == optimization_strategy::depth) { std::cout << "previous result was already the best we can do." << std::endl; break; // met timing, or it's the best we can do. @@ -1575,7 +769,9 @@ xmg_names optimize_basic ( } std::cout << std::endl; for (int i = 0; i < num_parts; i++) { - optimized[i] = optimize(*target, strategy, partitions, i, abc_exec); + const mockturtle::window_view> part = fix_names2(partitions, i); + + optimized[i] = optimize(*target, strategy, part, i, abc_exec); } delete target; assert(num_parts == optimized.size()); diff --git a/core/algorithms/optimization/resynthesis.hpp b/core/algorithms/optimization/resynthesis.hpp index 290e23194..9fbd7ddb7 100644 --- a/core/algorithms/optimization/resynthesis.hpp +++ b/core/algorithms/optimization/resynthesis.hpp @@ -29,6 +29,7 @@ #ifdef ENABLE_ABC #include #include "algorithms/partitioning/partition_manager_junior.hpp" +#include "algorithms/optimization/optimizer.hpp" #include "utility.hpp" namespace oracle @@ -43,8 +44,6 @@ mockturtle::names_view optimize_timing( const std::string &output_file, const std::string &abc_exec, const std::string &temp_prefix); #endif -enum optimization_strategy { size, balanced, depth }; - template mockturtle::names_view optimize_basic( oracle::partition_manager_junior &partitions, @@ -55,49 +54,6 @@ template mockturtle::names_view optimize_resynthesis( oracle::partition_manager_junior &partitions, const std::string &abc_exec); -struct node_depth { - int nodes; - int depth; -}; - - -template -class optimizer -{ -public: - /** - * human readable name - */ - virtual const std::string optimizer_name() = 0; - /** - * Do any conversion necessary from original network type to the internal network type. - */ - virtual void convert() = 0; - /** - * Perform optimization - */ - virtual void optimize() = 0; - /** - * Calculate tech independent depth and nodes metrics. - */ - virtual node_depth independent_metric() = 0; - /** - * List the type of optimization: area, delay, or balanced. - */ - virtual optimization_strategy target() = 0; - /** - * Techmap, then return a path to a file containing the techmapped verilog. - */ - virtual std::string techmap(const std::string &liberty_file, const std::string &temp_prefix) = 0; - /** - * convert the network to the superset. - */ - virtual mockturtle::names_view export_superset() = 0; - /** - * Reapply this optimization to a different network. - */ - virtual optimizer *reapply(int index, const mockturtle::window_view> &part) = 0; -}; } #endif