From 0fa1a5215e1f4f9580c5be75a93ce6e66f56ba72 Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 12 Jun 2024 10:41:27 +0200 Subject: [PATCH 01/84] Init files --- .../node_duplication_planarization.hpp | 133 ++++++++++++++++++ .../node_duplication_planarization.cpp | 22 +++ 2 files changed, 155 insertions(+) create mode 100644 include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp create mode 100644 test/algorithms/network_transformation/node_duplication_planarization.cpp diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp new file mode 100644 index 000000000..e2ffde071 --- /dev/null +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -0,0 +1,133 @@ +// +// Created by benjamin on 6/11/24. +// + +#ifndef FICTION_NODE_DUPLICATION_PLANARIZATION_HPP +#define FICTION_NODE_DUPLICATION_PLANARIZATION_HPP + +#include "fiction/traits.hpp" +#include "fiction/algorithms/network_transformation/fanout_substitution.hpp" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if (PROGRESS_BARS) +#include +#endif + +namespace fiction +{ + +/*template +class RankViewNtk : public Ntk { + public: + using Ntk::Ntk; // Inherit constructors + + RankViewNtk(const Ntk& ntk): Ntk(mockturtle::rank_view(ntk)) {} // Convert from Ntk +};*/ + +/** + * Parameters for the fanout substitution algorithm. + */ +struct node_duplication_params +{ + /** + * Breadth-first vs. depth-first fanout-tree substitution strategies. + */ + enum substitution_strategy + { + /** + * Breadth-first substitution. Creates balanced fanout trees. + */ + BREADTH, + /** + * Depth-first substitution. Creates fanout trees with one deep branch. + */ + DEPTH + }; + + /** + * Substitution strategy of high-degree fanout networks (depth-first vs. breadth-first). + */ + substitution_strategy strategy = BREADTH; + /** + * Maximum output degree of each fan-out node. + */ + uint32_t degree = 2ul; + /** + * Maximum number of outputs any gate is allowed to have before substitution applies. + */ + uint32_t threshold = 1ul; +}; + +namespace detail +{ + +template +class node_duplication_planarization_impl +{ + public: + node_duplication_planarization_impl(const NtkSrc& src, const node_duplication_params p) : + ntk(convert_network(src)) + { + if (!is_fanout_substituted(ntk)) { + ntk = fanout_substitution(ntk); // Apply fanout substitution if needed + } + } + + NtkDest run() + { + // Create random node ranks for POs: maybe here a heuristic or some clustering algorithm can assist + // Iterate from POs to PIs and watch the current rank plus the fanin nodes at one time + // A between these two ranks: compute the Graph H and compute the shortest path + // B this might be simplified by just collecting all fanins also from the node with rank current_rank - 1 + // the order can then has to be applied before going to the next iteration step + // std::cout << ntk.width() << std::endl; + return ntk; + } + + private: + NtkDest ntk; + +}; + +} // namespace detail + +/** + * ToDo: Description + */ +template +NtkDest node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) +{ + /*static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); + static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); + + static_assert(mockturtle::has_is_constant_v, "NtkSrc does not implement the is_constant function"); + static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi function"); + static_assert(mockturtle::has_create_not_v, "NtkDest does not implement the create_not function"); + static_assert(mockturtle::has_create_po_v, "NtkDest does not implement the create_po function"); + static_assert(mockturtle::has_create_buf_v, "NtkDest does not implement the create_buf function"); + static_assert(mockturtle::has_clone_node_v, "NtkDest does not implement the clone_node function"); + static_assert(mockturtle::has_fanout_size_v, "NtkDest does not implement the fanout_size function"); + static_assert(mockturtle::has_foreach_gate_v, "NtkDest does not implement the foreach_gate function"); + static_assert(mockturtle::has_foreach_fanin_v, "NtkDest does not implement the foreach_fanin function"); + static_assert(mockturtle::has_foreach_po_v, "NtkDest does not implement the foreach_po function");*/ + + detail::node_duplication_planarization_impl p{ntk_src, ps}; + + auto result = p.run(); + + return result; +} + +} // namespace fiction + +#endif // FICTION_NODE_DUPLICATION_PLANARIZATION_HPP diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp new file mode 100644 index 000000000..48777f664 --- /dev/null +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -0,0 +1,22 @@ +// +// Created by benjamin on 6/11/24. +// + +#include + +#include "utils/blueprints/network_blueprints.hpp" +#include "utils/equivalence_checking_utils.hpp" + +#include +#include + +using namespace fiction; + +TEST_CASE("First test", "[node-duplication-planarization]") +{ + auto maj = blueprints::maj1_network(); + + const auto planarized_maj = node_duplication_planarization(maj); + + CHECK(1 == 1); +} From 1fab81fdb635828bfac1b5ba3cffe6534ede9bdc Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 12 Jun 2024 10:59:45 +0200 Subject: [PATCH 02/84] Rank Ntk Setup --- .../node_duplication_planarization.hpp | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index e2ffde071..6a048a0fd 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -71,31 +71,28 @@ struct node_duplication_params namespace detail { -template +template class node_duplication_planarization_impl { public: - node_duplication_planarization_impl(const NtkSrc& src, const node_duplication_params p) : - ntk(convert_network(src)) - { - if (!is_fanout_substituted(ntk)) { - ntk = fanout_substitution(ntk); // Apply fanout substitution if needed - } - } + node_duplication_planarization_impl(const Ntk& src, const node_duplication_params p) : + ntk(mockturtle::rank_view(src)) + { } - NtkDest run() + mockturtle::rank_view run() { // Create random node ranks for POs: maybe here a heuristic or some clustering algorithm can assist // Iterate from POs to PIs and watch the current rank plus the fanin nodes at one time // A between these two ranks: compute the Graph H and compute the shortest path // B this might be simplified by just collecting all fanins also from the node with rank current_rank - 1 // the order can then has to be applied before going to the next iteration step - // std::cout << ntk.width() << std::endl; + std::cout << "width: " < ntk; }; @@ -105,7 +102,7 @@ class node_duplication_planarization_impl * ToDo: Description */ template -NtkDest node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) +mockturtle::rank_view node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) { /*static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); @@ -121,7 +118,13 @@ NtkDest node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_p static_assert(mockturtle::has_foreach_fanin_v, "NtkDest does not implement the foreach_fanin function"); static_assert(mockturtle::has_foreach_po_v, "NtkDest does not implement the foreach_po function");*/ - detail::node_duplication_planarization_impl p{ntk_src, ps}; + auto t_ntk = convert_network(ntk_src); + + if (!is_fanout_substituted(t_ntk)) { + t_ntk = fanout_substitution(t_ntk); // Apply fanout substitution if needed + } + + detail::node_duplication_planarization_impl p{t_ntk, ps}; auto result = p.run(); From 9f77edac450d04322d6c264dc65b6b0fc899342d Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 12 Jun 2024 17:21:22 +0200 Subject: [PATCH 03/84] Compute Delay for H-graph. --- .../node_duplication_planarization.hpp | 131 +++++++++++++++++- .../node_duplication_planarization.cpp | 50 ++++++- 2 files changed, 174 insertions(+), 7 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 6a048a0fd..290be54da 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -71,21 +71,133 @@ struct node_duplication_params namespace detail { +template +struct node_pair +{ + std::pair, mockturtle::node> pair; + std::shared_ptr> fanin_pair; + uint64_t delay; + // constructor + node_pair(mockturtle::node node1, mockturtle::node node2, uint64_t delayValue) + : pair(node1, node2), delay(delayValue) {} +}; + +template +std::vector> calculate_pairs(const std::vector>& nodes) { + std::vector> pairwise_combinations; + + if(nodes.size() == 1) { + node_pair pair = {nodes[0], nodes[0], std::numeric_limits::max()}; // Initialize delay to inf + pairwise_combinations.push_back(pair); + return pairwise_combinations; + } + + for (auto it1 = nodes.begin(); it1 != nodes.end(); ++it1) { + for (auto it2 = it1 + 1; it2 != nodes.end(); ++it2) { + node_pair pair1 = {*it1, *it2, std::numeric_limits::max()}; // Initialize delay to inf + node_pair pair2 = {*it2, *it1, std::numeric_limits::max()}; // Initialize delay to inf + pairwise_combinations.push_back(pair1); + pairwise_combinations.push_back(pair2); + } + } + + return pairwise_combinations; +} +// ToDo: Hande combinations with more than two nodes. Then all the other nodes inbetween can be palced in arbitrary order template class node_duplication_planarization_impl { public: node_duplication_planarization_impl(const Ntk& src, const node_duplication_params p) : ntk(mockturtle::rank_view(src)) - { } + {} + + void compute_slice_delays( mockturtle::node po, std::vector> next_level ) + { + ntk.foreach_fanin(po, [this, &next_level] (auto fi){ + cur_fis.push_back(fi); + if(ntk.visited(fi) == ntk.trav_id()){ + next_level.push_back(fi); + ntk.set_visited(fi, ntk.trav_id() + 1); + } + + } ); + // Compute the combinations in one slice + auto combinations = calculate_pairs(cur_fis); + if (combinations.empty()) + { + throw std::runtime_error("Combinations are empty. There might be a dangling node"); + } + std::vector> combinations_last; + if (!cur_lvl_pairs.empty()) + { + combinations_last = cur_lvl_pairs.back(); + for (auto& node_pair_cur : combinations) { + for (auto& node_pair_last : combinations_last) { + // If there is a connection between the two node pairs the delay is calculated like this + if ((node_pair_cur.pair.first == node_pair_last.pair.second && node_pair_last.delay + 1 < node_pair_cur.delay)) + { + node_pair_cur.fanin_pair = std::make_shared>(node_pair_last); + node_pair_cur.delay = node_pair_last.delay + 1; + } + // If there is no connection between the two node pairs the delay is calculated like this + else if( node_pair_last.delay + 2 < node_pair_cur.delay ) + { + node_pair_cur.fanin_pair = std::make_shared>(node_pair_last); + node_pair_cur.delay = node_pair_last.delay + 2; + } + } + } + } + else + { + // The delay for the first node in the level is set to 1 + for (auto& node_pair : combinations) { + node_pair.delay = 1; + } + } + + for (const auto& node_pair : combinations) { + std::cout << "Fanin Pair: (" << node_pair.pair.first << ", " << node_pair.pair.second << "), Delay: " << node_pair.delay << std::endl; + } + + cur_lvl_pairs.push_back(combinations); + } mockturtle::rank_view run() { + std::vector> next_level; // needed to start the next level + ntk.foreach_po([this, &next_level](auto po){ + std::cout << ntk.level(po) << std::endl; + /*ntk.set_level(po, ntk.depth()); + std::cout << ntk.level(po) << std::endl;*/ + cur_fis.clear(); + compute_slice_delays(po, next_level); + }); + while (!next_level.empty()) + { + // We need to create a new vector to store the nodes of the next level + std::vector> new_level; + for (const auto& cur_node : next_level) + { + cur_fis.clear(); + compute_slice_delays(cur_node, new_level); + } + // The new level becomes the next level for the next iteration + next_level = new_level; + } // Create random node ranks for POs: maybe here a heuristic or some clustering algorithm can assist // Iterate from POs to PIs and watch the current rank plus the fanin nodes at one time // A between these two ranks: compute the Graph H and compute the shortest path // B this might be simplified by just collecting all fanins also from the node with rank current_rank - 1 // the order can then has to be applied before going to the next iteration step + /*static std::mt19937 generator(std::random_device{}()); + std::uniform_int_distribution distribution(0, ntk.rank_width(r) - 1);*/ + /*for(const auto node : cur_level) + { + assert( ntk.is_pi(node) ); + }*/ + std::cout << "width: " < ntk; + std::vector>> cur_lvl_pairs; + std::vector> cur_fis; + // std::vector> slice_node_pairs; }; @@ -104,7 +219,7 @@ class node_duplication_planarization_impl template mockturtle::rank_view node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) { - /*static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); + static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); static_assert(mockturtle::has_is_constant_v, "NtkSrc does not implement the is_constant function"); @@ -116,13 +231,19 @@ mockturtle::rank_view node_duplication_planarization(const NtkSrc& ntk_ static_assert(mockturtle::has_fanout_size_v, "NtkDest does not implement the fanout_size function"); static_assert(mockturtle::has_foreach_gate_v, "NtkDest does not implement the foreach_gate function"); static_assert(mockturtle::has_foreach_fanin_v, "NtkDest does not implement the foreach_fanin function"); - static_assert(mockturtle::has_foreach_po_v, "NtkDest does not implement the foreach_po function");*/ + static_assert(mockturtle::has_foreach_po_v, "NtkDest does not implement the foreach_po function"); + + // check for input degree + /*if (has_high_degree_fanin_nodes(ntk_src, 2)) + { + throw high_degree_fanin_exception(); + }*/ auto t_ntk = convert_network(ntk_src); - if (!is_fanout_substituted(t_ntk)) { + /*if (!is_fanout_substituted(t_ntk)) { t_ntk = fanout_substitution(t_ntk); // Apply fanout substitution if needed - } + }*/ detail::node_duplication_planarization_impl p{t_ntk, ps}; diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index 48777f664..87dce738a 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -14,9 +14,55 @@ using namespace fiction; TEST_CASE("First test", "[node-duplication-planarization]") { - auto maj = blueprints::maj1_network(); + technology_network tec{}; - const auto planarized_maj = node_duplication_planarization(maj); + CHECK(mockturtle::has_clear_visited_v); + CHECK(mockturtle::has_visited_v); + CHECK(mockturtle::has_set_visited_v); + + const auto x1 = tec.create_pi(); + const auto x2 = tec.create_pi(); + const auto x3 = tec.create_pi(); + + const auto f1 = tec.create_and(x1, x2); + const auto f2 = tec.create_and(x1, x2); + const auto f3 = tec.create_and(x2, x3); + const auto f4 = tec.create_not(x3); + tec.create_po(f1); + tec.create_po(f2); + tec.create_po(f3); + tec.create_po(f4); + + // auto maj = blueprints::maj1_network(); + + const auto planarized_maj = node_duplication_planarization(tec); + + CHECK(1 == 1); +} + +TEST_CASE("Multi Level test", "[node-duplication-planarization]") +{ + technology_network tec{}; + + CHECK(mockturtle::has_clear_visited_v); + CHECK(mockturtle::has_visited_v); + CHECK(mockturtle::has_set_visited_v); + + const auto x1 = tec.create_pi(); + const auto x2 = tec.create_pi(); + const auto x3 = tec.create_pi(); + const auto x4 = tec.create_pi(); + const auto x5 = tec.create_pi(); + const auto f1 = tec.create_not(x2); + const auto f2 = tec.create_nary_and({x1, x2, x3, x4}); + const auto f3 = tec.create_nary_and({x3, x4, x5}); + tec.create_po(f1); + tec.create_po(f2); + tec.create_po(f3); + + // auto maj = blueprints::maj1_network(); + + const auto planarized_maj = node_duplication_planarization(tec); CHECK(1 == 1); } From 35a5f6fa1d3de6c8edc98162af01f8d20228404e Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 12 Jun 2024 18:24:21 +0200 Subject: [PATCH 04/84] :heavy_plus_sign: Compute nodes of the next level choosing the smallest delay path. --- .../node_duplication_planarization.hpp | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 290be54da..722c7fcb6 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -103,7 +103,7 @@ std::vector> calculate_pairs(const std::vector class node_duplication_planarization_impl { @@ -166,16 +166,51 @@ class node_duplication_planarization_impl mockturtle::rank_view run() { - std::vector> next_level; // needed to start the next level + // ToDo: Determine the PO order + std::vector> po_level; // save the nodes of the next level + ntk_lvls.push_back(po_level); + std::vector> next_level; // save the nodes of the next level + std::vector> real_next_level; // save the nodes of the next level + // Process the first level ntk.foreach_po([this, &next_level](auto po){ + // Recalculate the levels to start from the pos std::cout << ntk.level(po) << std::endl; - /*ntk.set_level(po, ntk.depth()); - std::cout << ntk.level(po) << std::endl;*/ + ntk.set_level(po, ntk.depth()); cur_fis.clear(); compute_slice_delays(po, next_level); }); + std::cout << cur_lvl_pairs.size() << std::endl; + + const auto& combinations = cur_lvl_pairs.back(); + + auto minimum_it = std::min_element(combinations.begin(), combinations.end(), + [](const node_pair& a, const node_pair& b) { + return a.delay < b.delay; + }); + + if (minimum_it != combinations.end()) + { + std::shared_ptr> fanin_combination = minimum_it->fanin_pair; + + while (fanin_combination) { + real_next_level.insert(real_next_level.begin(), fanin_combination->pair.first); + fanin_combination = fanin_combination->fanin_pair; + } + + const auto& min_combination = *minimum_it; + std::cout << "Minimum delay: " << min_combination.delay << std::endl; + + real_next_level.insert(real_next_level.begin(), min_combination.pair.first); + } + /*ToDo: When pushing the real next level there will be the duplicated nodes and then the trav id wont be correct anymore + * The handling of duplicated nodes has to be thought over + * */ + // first push back the pos + ntk_lvls.push_back(next_level); + // Process all other levels while (!next_level.empty()) { + // ToDo: Recalculate the levels // We need to create a new vector to store the nodes of the next level std::vector> new_level; for (const auto& cur_node : next_level) @@ -207,6 +242,7 @@ class node_duplication_planarization_impl mockturtle::rank_view ntk; std::vector>> cur_lvl_pairs; std::vector> cur_fis; + std::vector>> ntk_lvls; // std::vector> slice_node_pairs; }; From 9d994a0921eea5427afbcaa75fc7efb4d3fff555 Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 12 Jun 2024 18:29:15 +0200 Subject: [PATCH 05/84] :art: refactoring for readability --- .../node_duplication_planarization.hpp | 139 ++++++++++-------- 1 file changed, 79 insertions(+), 60 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 722c7fcb6..6ed3fb707 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -5,8 +5,8 @@ #ifndef FICTION_NODE_DUPLICATION_PLANARIZATION_HPP #define FICTION_NODE_DUPLICATION_PLANARIZATION_HPP -#include "fiction/traits.hpp" #include "fiction/algorithms/network_transformation/fanout_substitution.hpp" +#include "fiction/traits.hpp" #include #include @@ -75,27 +75,33 @@ template struct node_pair { std::pair, mockturtle::node> pair; - std::shared_ptr> fanin_pair; - uint64_t delay; + std::shared_ptr> fanin_pair; + uint64_t delay; // constructor - node_pair(mockturtle::node node1, mockturtle::node node2, uint64_t delayValue) - : pair(node1, node2), delay(delayValue) {} + node_pair(mockturtle::node node1, mockturtle::node node2, uint64_t delayValue) : + pair(node1, node2), + delay(delayValue) + {} }; template -std::vector> calculate_pairs(const std::vector>& nodes) { +std::vector> calculate_pairs(const std::vector>& nodes) +{ std::vector> pairwise_combinations; - if(nodes.size() == 1) { - node_pair pair = {nodes[0], nodes[0], std::numeric_limits::max()}; // Initialize delay to inf + if (nodes.size() == 1) + { + node_pair pair = {nodes[0], nodes[0], std::numeric_limits::max()}; // Initialize delay to inf pairwise_combinations.push_back(pair); return pairwise_combinations; } - for (auto it1 = nodes.begin(); it1 != nodes.end(); ++it1) { - for (auto it2 = it1 + 1; it2 != nodes.end(); ++it2) { - node_pair pair1 = {*it1, *it2, std::numeric_limits::max()}; // Initialize delay to inf - node_pair pair2 = {*it2, *it1, std::numeric_limits::max()}; // Initialize delay to inf + for (auto it1 = nodes.begin(); it1 != nodes.end(); ++it1) + { + for (auto it2 = it1 + 1; it2 != nodes.end(); ++it2) + { + node_pair pair1 = {*it1, *it2, std::numeric_limits::max()}; // Initialize delay to inf + node_pair pair2 = {*it2, *it1, std::numeric_limits::max()}; // Initialize delay to inf pairwise_combinations.push_back(pair1); pairwise_combinations.push_back(pair2); } @@ -103,7 +109,8 @@ std::vector> calculate_pairs(const std::vector class node_duplication_planarization_impl { @@ -112,16 +119,18 @@ class node_duplication_planarization_impl ntk(mockturtle::rank_view(src)) {} - void compute_slice_delays( mockturtle::node po, std::vector> next_level ) + void compute_slice_delays(mockturtle::node po, std::vector> next_level) { - ntk.foreach_fanin(po, [this, &next_level] (auto fi){ + ntk.foreach_fanin(po, + [this, &next_level](auto fi) + { cur_fis.push_back(fi); - if(ntk.visited(fi) == ntk.trav_id()){ + if (ntk.visited(fi) == ntk.trav_id()) + { next_level.push_back(fi); ntk.set_visited(fi, ntk.trav_id() + 1); } - - } ); + }); // Compute the combinations in one slice auto combinations = calculate_pairs(cur_fis); if (combinations.empty()) @@ -132,19 +141,22 @@ class node_duplication_planarization_impl if (!cur_lvl_pairs.empty()) { combinations_last = cur_lvl_pairs.back(); - for (auto& node_pair_cur : combinations) { - for (auto& node_pair_last : combinations_last) { + for (auto& node_pair_cur : combinations) + { + for (auto& node_pair_last : combinations_last) + { // If there is a connection between the two node pairs the delay is calculated like this - if ((node_pair_cur.pair.first == node_pair_last.pair.second && node_pair_last.delay + 1 < node_pair_cur.delay)) + if ((node_pair_cur.pair.first == node_pair_last.pair.second && + node_pair_last.delay + 1 < node_pair_cur.delay)) { node_pair_cur.fanin_pair = std::make_shared>(node_pair_last); - node_pair_cur.delay = node_pair_last.delay + 1; + node_pair_cur.delay = node_pair_last.delay + 1; } // If there is no connection between the two node pairs the delay is calculated like this - else if( node_pair_last.delay + 2 < node_pair_cur.delay ) + else if (node_pair_last.delay + 2 < node_pair_cur.delay) { node_pair_cur.fanin_pair = std::make_shared>(node_pair_last); - node_pair_cur.delay = node_pair_last.delay + 2; + node_pair_cur.delay = node_pair_last.delay + 2; } } } @@ -152,64 +164,72 @@ class node_duplication_planarization_impl else { // The delay for the first node in the level is set to 1 - for (auto& node_pair : combinations) { + for (auto& node_pair : combinations) + { node_pair.delay = 1; } } - for (const auto& node_pair : combinations) { - std::cout << "Fanin Pair: (" << node_pair.pair.first << ", " << node_pair.pair.second << "), Delay: " << node_pair.delay << std::endl; + for (const auto& node_pair : combinations) + { + std::cout << "Fanin Pair: (" << node_pair.pair.first << ", " << node_pair.pair.second + << "), Delay: " << node_pair.delay << std::endl; } cur_lvl_pairs.push_back(combinations); } - mockturtle::rank_view run() + void compute_node_order_next_level(std::vector>& next_level) { - // ToDo: Determine the PO order - std::vector> po_level; // save the nodes of the next level - ntk_lvls.push_back(po_level); - std::vector> next_level; // save the nodes of the next level - std::vector> real_next_level; // save the nodes of the next level - // Process the first level - ntk.foreach_po([this, &next_level](auto po){ - // Recalculate the levels to start from the pos - std::cout << ntk.level(po) << std::endl; - ntk.set_level(po, ntk.depth()); - cur_fis.clear(); - compute_slice_delays(po, next_level); - }); - std::cout << cur_lvl_pairs.size() << std::endl; - const auto& combinations = cur_lvl_pairs.back(); - - auto minimum_it = std::min_element(combinations.begin(), combinations.end(), - [](const node_pair& a, const node_pair& b) { - return a.delay < b.delay; - }); - + auto minimum_it = + std::min_element(combinations.begin(), combinations.end(), + [](const node_pair& a, const node_pair& b) { return a.delay < b.delay; }); if (minimum_it != combinations.end()) { std::shared_ptr> fanin_combination = minimum_it->fanin_pair; - while (fanin_combination) { - real_next_level.insert(real_next_level.begin(), fanin_combination->pair.first); + while (fanin_combination) + { + next_level.insert(next_level.begin(), fanin_combination->pair.first); fanin_combination = fanin_combination->fanin_pair; } const auto& min_combination = *minimum_it; std::cout << "Minimum delay: " << min_combination.delay << std::endl; - real_next_level.insert(real_next_level.begin(), min_combination.pair.first); + next_level.insert(next_level.begin(), min_combination.pair.first); } - /*ToDo: When pushing the real next level there will be the duplicated nodes and then the trav id wont be correct anymore - * The handling of duplicated nodes has to be thought over + } + + mockturtle::rank_view run() + { + // ToDo: Determine the PO order + std::vector> po_level; // save the nodes of the next level + ntk_lvls.push_back(po_level); + std::vector> next_level; // save the nodes of the next level + std::vector> real_next_level; // save the nodes of the next level + // Process the first level + ntk.foreach_po( + [this, &next_level](auto po) + { + // Recalculate the levels to start from the pos + std::cout << ntk.level(po) << std::endl; + ntk.set_level(po, ntk.depth()); + cur_fis.clear(); + compute_slice_delays(po, next_level); + }); + compute_node_order_next_level(real_next_level); + + /*ToDo: When pushing the real next level there will be the duplicated nodes and then the trav id wont be correct + * anymore The handling of duplicated nodes has to be thought over * */ // first push back the pos ntk_lvls.push_back(next_level); // Process all other levels while (!next_level.empty()) { + cur_lvl_pairs.clear(); // ToDo: Recalculate the levels // We need to create a new vector to store the nodes of the next level std::vector> new_level; @@ -233,18 +253,17 @@ class node_duplication_planarization_impl assert( ntk.is_pi(node) ); }*/ - std::cout << "width: " < ntk; - std::vector>> cur_lvl_pairs; - std::vector> cur_fis; + mockturtle::rank_view ntk; + std::vector>> cur_lvl_pairs; + std::vector> cur_fis; std::vector>> ntk_lvls; // std::vector> slice_node_pairs; - }; } // namespace detail From 4a88b423580afe592f7ecbbe5feb44070fe21484 Mon Sep 17 00:00:00 2001 From: benjamin Date: Thu, 13 Jun 2024 14:13:50 +0200 Subject: [PATCH 06/84] :art: Node insertion for computing the next level nodes fixed. --- .../node_duplication_planarization.hpp | 90 ++++++++++++++----- 1 file changed, 70 insertions(+), 20 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 6ed3fb707..7bf8ff689 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -75,6 +75,7 @@ template struct node_pair { std::pair, mockturtle::node> pair; + std::vector> middle_nodes; std::shared_ptr> fanin_pair; uint64_t delay; // constructor @@ -88,6 +89,7 @@ template std::vector> calculate_pairs(const std::vector>& nodes) { std::vector> pairwise_combinations; + std::vector> middle_nodes; if (nodes.size() == 1) { @@ -100,8 +102,25 @@ std::vector> calculate_pairs(const std::vector pair1 = {*it1, *it2, std::numeric_limits::max()}; // Initialize delay to inf node_pair pair2 = {*it2, *it1, std::numeric_limits::max()}; // Initialize delay to inf + + // Add middle_nodes to pairs + pair1.middle_nodes = middle_nodes; + pair2.middle_nodes = middle_nodes; + pairwise_combinations.push_back(pair1); pairwise_combinations.push_back(pair2); } @@ -109,7 +128,8 @@ std::vector> calculate_pairs(const std::vector class node_duplication_planarization_impl @@ -179,32 +199,64 @@ class node_duplication_planarization_impl cur_lvl_pairs.push_back(combinations); } + void insert_if_unique(mockturtle::node node, std::vector>& vec) + { + if(vec.empty() || vec.front() != node) + { + vec.insert(vec.begin(), node); + } + } + void compute_node_order_next_level(std::vector>& next_level) { const auto& combinations = cur_lvl_pairs.back(); + // select the path with the least delay and follow it via fanin relations auto minimum_it = std::min_element(combinations.begin(), combinations.end(), [](const node_pair& a, const node_pair& b) { return a.delay < b.delay; }); if (minimum_it != combinations.end()) { + const auto &min_combination = *minimum_it; + std::cout << "Minimum delay: " << min_combination.delay << std::endl; + + // Insert the terminal node + insert_if_unique(min_combination.pair.second, next_level); + + // insert middle_nodes + for (const auto &node : min_combination.middle_nodes) + { + insert_if_unique(node, next_level); + } + + // Insert the first node + insert_if_unique(min_combination.pair.first, next_level); + std::shared_ptr> fanin_combination = minimum_it->fanin_pair; while (fanin_combination) { - next_level.insert(next_level.begin(), fanin_combination->pair.first); - fanin_combination = fanin_combination->fanin_pair; - } + // Insert the terminal node + insert_if_unique(fanin_combination->pair.second, next_level); - const auto& min_combination = *minimum_it; - std::cout << "Minimum delay: " << min_combination.delay << std::endl; + // Insert middle_nodes + for (const auto &node : fanin_combination->middle_nodes) + { + insert_if_unique(node, next_level); + } + + // insert the first node + insert_if_unique(fanin_combination->pair.first, next_level); - next_level.insert(next_level.begin(), min_combination.pair.first); + fanin_combination = fanin_combination->fanin_pair; + } } } mockturtle::rank_view run() { // ToDo: Determine the PO order + /*static std::mt19937 generator(std::random_device{}()); + std::uniform_int_distribution distribution(0, ntk.rank_width(r) - 1);*/ std::vector> po_level; // save the nodes of the next level ntk_lvls.push_back(po_level); std::vector> next_level; // save the nodes of the next level @@ -222,8 +274,11 @@ class node_duplication_planarization_impl compute_node_order_next_level(real_next_level); /*ToDo: When pushing the real next level there will be the duplicated nodes and then the trav id wont be correct - * anymore The handling of duplicated nodes has to be thought over + * anymore. The handling of duplicated nodes has to be thought over. * */ + // This function gets the nodes of the next level passed. They should be reordered and the duplicated nodes have + // to be inserted so that they will keep the same functionality reorder_and_duplicate_nodes(next_level) + // first push back the pos ntk_lvls.push_back(next_level); // Process all other levels @@ -236,22 +291,13 @@ class node_duplication_planarization_impl for (const auto& cur_node : next_level) { cur_fis.clear(); + // There is one slice in the H-Graph per node in the level compute_slice_delays(cur_node, new_level); } // The new level becomes the next level for the next iteration next_level = new_level; + // compute_node_order_next_level(next_level); } - // Create random node ranks for POs: maybe here a heuristic or some clustering algorithm can assist - // Iterate from POs to PIs and watch the current rank plus the fanin nodes at one time - // A between these two ranks: compute the Graph H and compute the shortest path - // B this might be simplified by just collecting all fanins also from the node with rank current_rank - 1 - // the order can then has to be applied before going to the next iteration step - /*static std::mt19937 generator(std::random_device{}()); - std::uniform_int_distribution distribution(0, ntk.rank_width(r) - 1);*/ - /*for(const auto node : cur_level) - { - assert( ntk.is_pi(node) ); - }*/ std::cout << "width: " << ntk.width() << std::endl; std::cout << "depth: " << ntk.depth() << std::endl; @@ -263,13 +309,17 @@ class node_duplication_planarization_impl std::vector>> cur_lvl_pairs; std::vector> cur_fis; std::vector>> ntk_lvls; - // std::vector> slice_node_pairs; }; } // namespace detail /** * ToDo: Description + * This implementation utilizes an H-Graph to capture all edge relations between two layers of a graph. + * The Node Duplication Crossing Minimization (NDCE) problem is addressed by finding the shortest x-y path on the + * H-Graph. Note that this minimization is valid only under a specific order at the primary output (PO) level. The + * algorithm traverses from primary outputs (POs) to primary inputs (PIs), constructing the H-Graph and computing the + * shortest x-y paths at each level of the graph. */ template mockturtle::rank_view node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) From fa968ffde607c934304d6fcca6297f80270f8d0e Mon Sep 17 00:00:00 2001 From: benjamin Date: Thu, 13 Jun 2024 16:53:50 +0200 Subject: [PATCH 07/84] :art: Pi propagation and next_level computation fixed. --- .../node_duplication_planarization.hpp | 94 +++++++++++-------- 1 file changed, 57 insertions(+), 37 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 7bf8ff689..6aff11d83 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -88,7 +88,7 @@ struct node_pair template std::vector> calculate_pairs(const std::vector>& nodes) { - std::vector> pairwise_combinations; + std::vector> pairwise_combinations; std::vector> middle_nodes; if (nodes.size() == 1) @@ -129,8 +129,6 @@ std::vector> calculate_pairs(const std::vector class node_duplication_planarization_impl { @@ -139,18 +137,14 @@ class node_duplication_planarization_impl ntk(mockturtle::rank_view(src)) {} - void compute_slice_delays(mockturtle::node po, std::vector> next_level) + void compute_slice_delays(mockturtle::node nd, const bool border_pis) { - ntk.foreach_fanin(po, - [this, &next_level](auto fi) - { - cur_fis.push_back(fi); - if (ntk.visited(fi) == ntk.trav_id()) - { - next_level.push_back(fi); - ntk.set_visited(fi, ntk.trav_id() + 1); - } - }); + // Pis need to be propagated into the next level, since they have to be connected without crossings + if (ntk.is_pi(nd) && border_pis) + { + cur_fis.push_back(nd); + } + ntk.foreach_fanin(nd, [this](auto fi) { cur_fis.push_back(fi); }); // Compute the combinations in one slice auto combinations = calculate_pairs(cur_fis); if (combinations.empty()) @@ -201,7 +195,7 @@ class node_duplication_planarization_impl void insert_if_unique(mockturtle::node node, std::vector>& vec) { - if(vec.empty() || vec.front() != node) + if (vec.empty() || vec.front() != node) { vec.insert(vec.begin(), node); } @@ -211,19 +205,19 @@ class node_duplication_planarization_impl { const auto& combinations = cur_lvl_pairs.back(); // select the path with the least delay and follow it via fanin relations - auto minimum_it = + auto minimum_it = std::min_element(combinations.begin(), combinations.end(), [](const node_pair& a, const node_pair& b) { return a.delay < b.delay; }); if (minimum_it != combinations.end()) { - const auto &min_combination = *minimum_it; + const auto& min_combination = *minimum_it; std::cout << "Minimum delay: " << min_combination.delay << std::endl; // Insert the terminal node insert_if_unique(min_combination.pair.second, next_level); // insert middle_nodes - for (const auto &node : min_combination.middle_nodes) + for (const auto& node : min_combination.middle_nodes) { insert_if_unique(node, next_level); } @@ -239,7 +233,7 @@ class node_duplication_planarization_impl insert_if_unique(fanin_combination->pair.second, next_level); // Insert middle_nodes - for (const auto &node : fanin_combination->middle_nodes) + for (const auto& node : fanin_combination->middle_nodes) { insert_if_unique(node, next_level); } @@ -252,51 +246,77 @@ class node_duplication_planarization_impl } } + void check_final_level(std::vector>& v_next_level, bool& f_final_level ) + { + for (const auto& nd : v_next_level) + { + if (!ntk.is_pi(nd)) + { + f_final_level = false; + break; + } + } + } + mockturtle::rank_view run() { + const bool border_pis = true; // ToDo: Determine the PO order /*static std::mt19937 generator(std::random_device{}()); std::uniform_int_distribution distribution(0, ntk.rank_width(r) - 1);*/ - std::vector> po_level; // save the nodes of the next level - ntk_lvls.push_back(po_level); - std::vector> next_level; // save the nodes of the next level - std::vector> real_next_level; // save the nodes of the next level + std::vector> v_po_level; // save the nodes of the next level + std::vector> v_next_level; // save the nodes of the next level // Process the first level ntk.foreach_po( - [this, &next_level](auto po) + [this, &v_po_level](auto po) { // Recalculate the levels to start from the pos std::cout << ntk.level(po) << std::endl; ntk.set_level(po, ntk.depth()); cur_fis.clear(); - compute_slice_delays(po, next_level); + compute_slice_delays(po, border_pis); + v_po_level.push_back(po); }); - compute_node_order_next_level(real_next_level); + int level = ntk.depth(); + std::cout << "push lvl: " << level << std::endl; + ntk_lvls.push_back(v_po_level); + // ToDo: try to push PIs to the beginning or end of he vector, since they have to be propagated with buffers + // until the last levels thsi should only happen if border_pis == true + compute_node_order_next_level(v_next_level); - /*ToDo: When pushing the real next level there will be the duplicated nodes and then the trav id wont be correct - * anymore. The handling of duplicated nodes has to be thought over. - * */ // This function gets the nodes of the next level passed. They should be reordered and the duplicated nodes have // to be inserted so that they will keep the same functionality reorder_and_duplicate_nodes(next_level) // first push back the pos - ntk_lvls.push_back(next_level); + + bool f_final_level = true; + check_final_level(v_next_level, f_final_level); + // Process all other levels - while (!next_level.empty()) + while (!v_next_level.empty() && !f_final_level) { + level--; + std::cout << "push lvl: " << level << std::endl; + ntk_lvls.push_back(v_next_level); cur_lvl_pairs.clear(); - // ToDo: Recalculate the levels // We need to create a new vector to store the nodes of the next level - std::vector> new_level; - for (const auto& cur_node : next_level) + for (const auto& cur_node : v_next_level) { cur_fis.clear(); // There is one slice in the H-Graph per node in the level - compute_slice_delays(cur_node, new_level); + compute_slice_delays(cur_node, border_pis); } + // + v_next_level.clear(); // The new level becomes the next level for the next iteration - next_level = new_level; - // compute_node_order_next_level(next_level); + compute_node_order_next_level(v_next_level); + f_final_level = true; + check_final_level(v_next_level, f_final_level); + if (f_final_level) + { + std::cout << "push lvl: " << level - 1 << std::endl; + ntk_lvls.push_back(v_next_level); + } } std::cout << "width: " << ntk.width() << std::endl; From 488a5885ccb358c568c76cee98d7794d7bab04e3 Mon Sep 17 00:00:00 2001 From: benjamin Date: Thu, 13 Jun 2024 17:23:47 +0200 Subject: [PATCH 08/84] :art: refactoring for readability --- .../node_duplication_planarization.hpp | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 6aff11d83..74708e8f6 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -264,25 +264,25 @@ class node_duplication_planarization_impl // ToDo: Determine the PO order /*static std::mt19937 generator(std::random_device{}()); std::uniform_int_distribution distribution(0, ntk.rank_width(r) - 1);*/ - std::vector> v_po_level; // save the nodes of the next level - std::vector> v_next_level; // save the nodes of the next level + std::vector> v_level; // save the nodes of the next level // Process the first level ntk.foreach_po( - [this, &v_po_level](auto po) + [this, &v_level](auto po) { // Recalculate the levels to start from the pos std::cout << ntk.level(po) << std::endl; ntk.set_level(po, ntk.depth()); cur_fis.clear(); compute_slice_delays(po, border_pis); - v_po_level.push_back(po); + v_level.push_back(po); }); int level = ntk.depth(); std::cout << "push lvl: " << level << std::endl; - ntk_lvls.push_back(v_po_level); + ntk_lvls.push_back(v_level); + v_level.clear(); // ToDo: try to push PIs to the beginning or end of he vector, since they have to be propagated with buffers // until the last levels thsi should only happen if border_pis == true - compute_node_order_next_level(v_next_level); + compute_node_order_next_level(v_level); // This function gets the nodes of the next level passed. They should be reordered and the duplicated nodes have // to be inserted so that they will keep the same functionality reorder_and_duplicate_nodes(next_level) @@ -290,33 +290,36 @@ class node_duplication_planarization_impl // first push back the pos bool f_final_level = true; - check_final_level(v_next_level, f_final_level); + check_final_level(v_level, f_final_level); // Process all other levels - while (!v_next_level.empty() && !f_final_level) + while (!v_level.empty() && !f_final_level) { level--; std::cout << "push lvl: " << level << std::endl; - ntk_lvls.push_back(v_next_level); + // Push the level to the network + ntk_lvls.push_back(v_level); cur_lvl_pairs.clear(); // We need to create a new vector to store the nodes of the next level - for (const auto& cur_node : v_next_level) + for (const auto& cur_node : v_level) { cur_fis.clear(); // There is one slice in the H-Graph per node in the level compute_slice_delays(cur_node, border_pis); } - // - v_next_level.clear(); - // The new level becomes the next level for the next iteration - compute_node_order_next_level(v_next_level); + // Clear before starting computations on the enxt level + v_level.clear(); + // Compute the next level + compute_node_order_next_level(v_level); + // Check if we are at the final level f_final_level = true; - check_final_level(v_next_level, f_final_level); - if (f_final_level) - { - std::cout << "push lvl: " << level - 1 << std::endl; - ntk_lvls.push_back(v_next_level); - } + check_final_level(v_level, f_final_level); + } + + if (f_final_level) + { + std::cout << "push lvl: " << level - 1 << std::endl; + ntk_lvls.push_back(v_level); } std::cout << "width: " << ntk.width() << std::endl; From fe10893e775e2b846a7d410a3fddefdd90f16d6b Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 17 Jun 2024 19:09:38 +0200 Subject: [PATCH 09/84] :heavy_plus_sign: created virtual_pi_network.hpp and virtual_pi_network.cpp (test cases have to be written as indicated in the ToDo) --- .../node_duplication_planarization.hpp | 8 +- .../fiction/networks/virtual_pi_network.hpp | 156 ++++++++++++++++++ test/networks/virtual_pi_network.cpp | 56 +++++++ 3 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 include/fiction/networks/virtual_pi_network.hpp create mode 100644 test/networks/virtual_pi_network.cpp diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 74708e8f6..f366d6ba0 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -280,15 +280,11 @@ class node_duplication_planarization_impl std::cout << "push lvl: " << level << std::endl; ntk_lvls.push_back(v_level); v_level.clear(); + // ToDo: try to push PIs to the beginning or end of he vector, since they have to be propagated with buffers - // until the last levels thsi should only happen if border_pis == true + // until the last levels this should only happen if border_pis == true compute_node_order_next_level(v_level); - // This function gets the nodes of the next level passed. They should be reordered and the duplicated nodes have - // to be inserted so that they will keep the same functionality reorder_and_duplicate_nodes(next_level) - - // first push back the pos - bool f_final_level = true; check_final_level(v_level, f_final_level); diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp new file mode 100644 index 000000000..153f4bc29 --- /dev/null +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -0,0 +1,156 @@ +// +// Created by benjamin on 6/14/24. +// + +#ifndef FICTION_NODE_DUPLICATION_VIEW_HPP +#define FICTION_NODE_DUPLICATION_VIEW_HPP + +#include "fiction/algorithms/network_transformation/network_conversion.hpp" + +#include +// #include +#include + +#include + +namespace fiction +{ + +/*!\brief Manager view for virtual PIs + * + * Virtual PIs are mapping of a "virtual" PI onto a "real" PI in the network. + * With virtual PIs PI-duplications are handled. + */ +class virtual_pi_network : public technology_network +{ + public: + using node = typename technology_network::node; + using signal = typename technology_network::signal; + + public: + explicit virtual_pi_network() = default; + + explicit virtual_pi_network(const technology_network& other) + { + _storage = std::make_shared(*(other._storage)); // create deep copy of storage + } + + auto num_gates() const + { + return static_cast(_storage->nodes.size() - virtual_inputs.size() - _storage->inputs.size() - 2); + } + + auto size() const + { + return static_cast(_storage->nodes.size() - virtual_inputs.size()); + } + + [[nodiscard]] auto size_virtual() const + { + return static_cast(_storage->nodes.size()); + } + + /*! \brief Creates a new virtual PI */ + signal create_virtual_pi(const node& real_pi) + { + const auto index = _storage->nodes.size(); + _storage->nodes.emplace_back(); + virtual_inputs.emplace_back(index); + _storage->nodes[index].data[1].h1 = 2; + map.emplace_back(index, real_pi); + return index; + } + + [[nodiscard]] bool is_virtual_pi(node const& n) const + { + return std::find(virtual_inputs.begin(), virtual_inputs.end(), n) != virtual_inputs.end(); + } + + [[nodiscard]] bool is_virtual_ci(node const& n) const + { + return std::find(virtual_inputs.begin(), virtual_inputs.end(), n) != virtual_inputs.end(); + } + + [[nodiscard]] auto num_cis_virtual() const + { + return static_cast(virtual_inputs.size()); + } + + [[nodiscard]] auto num_pis_virtual() const + { + return static_cast(virtual_inputs.size()); + } + + [[nodiscard]] auto num_cis_all() const + { + return static_cast(_storage->inputs.size() + virtual_inputs.size()); + } + + [[nodiscard]] auto num_pis_all() const + { + return static_cast(_storage->inputs.size() + virtual_inputs.size()); + } + + [[nodiscard]] auto get_real_pi(const node& v_pi) const + { + auto it = std::find_if(map.begin(), map.end(), [v_pi](const auto& pair) { return pair.first == v_pi; }); + + if (it != map.end()) + return it->second; + + throw std::runtime_error("Error: node is not a virtual pi"); + } + + // exclude virtual_inputs + template + void foreach_pi_virtual(Fn&& fn) const + { + mockturtle::detail::foreach_element(virtual_inputs.begin(), virtual_inputs.end(), fn); + } + + template + void foreach_ci_virtual(Fn&& fn) const + { + mockturtle::detail::foreach_element(virtual_inputs.begin(), virtual_inputs.end(), fn); + } + + template + void foreach_gate(Fn&& fn) const + { + auto r = mockturtle::range(2u, _storage->nodes.size()); /* start from 2 to avoid constants */ + mockturtle::detail::foreach_element_if( + r.begin(), r.end(), [this](auto n) { return (!is_ci(n) && !is_virtual_ci(n)); }, fn); + } + + // This function removed the virtual PIs and connects edges to the real PIs they are mapped to. Like this + // equivalence checking can be done. + void remove_virtual_input_nodes() + { + std::sort(virtual_inputs.begin(), virtual_inputs.end(), std::greater()); + for (uint64_t i : virtual_inputs) { + if(i < _storage->nodes.size()) { + uint64_t new_node = i; + for (const auto& pair : map) { + if (pair.first == i) { + new_node = pair.second; + break; + } + } + substitute_node(i, new_node); + _storage->nodes.erase(_storage->nodes.begin() + i); + } + } + + // Clear virtual_inputs after using it + virtual_inputs.clear(); + map.clear(); + } + + protected: + std::vector virtual_inputs; + std::vector> map; +}; /* color_view */ + +} // namespace fiction + +#endif // FICTION_NODE_DUPLICATION_VIEW_HPP diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp new file mode 100644 index 000000000..07d97abac --- /dev/null +++ b/test/networks/virtual_pi_network.cpp @@ -0,0 +1,56 @@ +// +// Created by benjamin on 6/17/24. +// + +#include "catch2/catch_test_macros.hpp" +#include "fiction/networks/virtual_pi_network.hpp" + +using namespace fiction; +//ToDo: Write meaningful test cases +TEST_CASE("Virtual PI view create virtual PI", "[virtual-pi-view]") +{ + technology_network tec{}; + + const auto a = tec.create_pi(); + const auto b = tec.create_pi(); + + virtual_pi_network vpi{tec}; + const auto c = vpi.create_virtual_pi(a); + const auto d = vpi.create_virtual_pi(b); + + const auto f1 = vpi.create_and(a, b); + const auto f2 = vpi.create_and(b, c); + const auto f3 = vpi.create_or(a, d); + + vpi.create_po(f1); + vpi.create_po(f2); + vpi.create_po(f3); + + std::cout << "real tec num_gates: " << vpi.size() << std::endl; + std::cout << "virt tec num_gates: " << vpi.size_virtual() << std::endl; + + vpi.foreach_node([&](const auto& nd) + { + std::cout << "Nd:" << nd << "\n"; + vpi.foreach_fanin(nd, [&](const auto& fi) + { + std::cout << "Fis:" << fi << "\n"; + }); + if (vpi.is_virtual_pi(nd)){ + std::cout << "Is virtual PI \n"; + } + }); + vpi.remove_virtual_input_nodes(); + + vpi.foreach_node([&](const auto& nd) + { + std::cout << "Nd:" << nd << "\n"; + vpi.foreach_fanin(nd, [&](const auto& fi) + { + std::cout << "Fis:" << fi << "\n"; + }); + if (vpi.is_virtual_pi(nd)){ + std::cout << "Is virtual PI \n"; + } + }); +} From 5319bf4366a3c196ccf496f3980f954cb89051ac Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 18 Jun 2024 11:00:47 +0200 Subject: [PATCH 10/84] :art: output iterators adjusted after rmoving virtual PIs. Test cases modified --- .../fiction/networks/virtual_pi_network.hpp | 11 ++- test/networks/virtual_pi_network.cpp | 85 ++++++++++++------- 2 files changed, 64 insertions(+), 32 deletions(-) diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 153f4bc29..2307d2db4 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -127,9 +127,9 @@ class virtual_pi_network : public technology_network void remove_virtual_input_nodes() { std::sort(virtual_inputs.begin(), virtual_inputs.end(), std::greater()); - for (uint64_t i : virtual_inputs) { + for (uint32_t i : virtual_inputs) { if(i < _storage->nodes.size()) { - uint64_t new_node = i; + uint64_t new_node = ( _storage->outputs.begin() + i )->index; for (const auto& pair : map) { if (pair.first == i) { new_node = pair.second; @@ -137,6 +137,11 @@ class virtual_pi_network : public technology_network } } substitute_node(i, new_node); + // The outputs iterators also need to be adjusted with -1 + for ( auto& output : _storage->outputs ) + { + --output.index; + } _storage->nodes.erase(_storage->nodes.begin() + i); } } @@ -147,7 +152,7 @@ class virtual_pi_network : public technology_network } protected: - std::vector virtual_inputs; + std::vector virtual_inputs; std::vector> map; }; /* color_view */ diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index 07d97abac..92c7944c6 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -2,55 +2,82 @@ // Created by benjamin on 6/17/24. // -#include "catch2/catch_test_macros.hpp" -#include "fiction/networks/virtual_pi_network.hpp" +#include + +#include +#include + +#include +#include using namespace fiction; -//ToDo: Write meaningful test cases -TEST_CASE("Virtual PI view create virtual PI", "[virtual-pi-view]") + +TEST_CASE("Copy network and size consistency", "[virtual-pi-view]") { technology_network tec{}; const auto a = tec.create_pi(); const auto b = tec.create_pi(); + const auto f1 = tec.create_and(a, b); + virtual_pi_network vpi{tec}; const auto c = vpi.create_virtual_pi(a); const auto d = vpi.create_virtual_pi(b); + + const auto f2 = vpi.create_and(b, c); + const auto f3 = vpi.create_or(a, d); + + vpi.create_po(f1); + vpi.create_po(f2); + vpi.create_po(f3); + + // virtual_pi_network is a deep copy. THe original network won't be affected by any changes after the copy + CHECK(tec.size() == 5); + // This is the size disregarding virtual PIs. So this would correspond to the size in a normal technology_network + CHECK(vpi.size() == 7); + // This is the size with the virtual PIs + CHECK(vpi.size_virtual() == 9); + vpi.remove_virtual_input_nodes(); + // After removing/remapping the virtual PIs to their real PIs the sizes are equal + CHECK(vpi.size_virtual() == vpi.size()); + CHECK(vpi.size_virtual() == 7); +} + +TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]") +{ + technology_network tec{}; + virtual_pi_network vpi{}; + + const auto a = vpi.create_pi(); + const auto b = vpi.create_pi(); + + const auto a_t = tec.create_pi(); + const auto b_t = tec.create_pi(); + + const auto c = vpi.create_virtual_pi(a); + const auto d = vpi.create_virtual_pi(b); + const auto f1 = vpi.create_and(a, b); const auto f2 = vpi.create_and(b, c); const auto f3 = vpi.create_or(a, d); + const auto f1_t = tec.create_and(a_t, b); + const auto f2_t = tec.create_and(b_t, a_t); + const auto f3_t = tec.create_or(a_t, b_t); + vpi.create_po(f1); vpi.create_po(f2); vpi.create_po(f3); - std::cout << "real tec num_gates: " << vpi.size() << std::endl; - std::cout << "virt tec num_gates: " << vpi.size_virtual() << std::endl; - - vpi.foreach_node([&](const auto& nd) - { - std::cout << "Nd:" << nd << "\n"; - vpi.foreach_fanin(nd, [&](const auto& fi) - { - std::cout << "Fis:" << fi << "\n"; - }); - if (vpi.is_virtual_pi(nd)){ - std::cout << "Is virtual PI \n"; - } - }); + tec.create_po(f1_t); + tec.create_po(f2_t); + tec.create_po(f3_t); + vpi.remove_virtual_input_nodes(); - vpi.foreach_node([&](const auto& nd) - { - std::cout << "Nd:" << nd << "\n"; - vpi.foreach_fanin(nd, [&](const auto& fi) - { - std::cout << "Fis:" << fi << "\n"; - }); - if (vpi.is_virtual_pi(nd)){ - std::cout << "Is virtual PI \n"; - } - }); + mockturtle::equivalence_checking_stats st; + bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); + CHECK(cec_m == 1); } From 93d71c58ff3638b1169075ca154cd7e6120fbcfc Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 18 Jun 2024 13:08:17 +0200 Subject: [PATCH 11/84] :art: redefinition of size() for code consistency --- .../fiction/networks/virtual_pi_network.hpp | 6 +-- test/networks/virtual_pi_network.cpp | 48 +++++++++++++++++-- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 2307d2db4..4aadd0fc6 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -42,12 +42,12 @@ class virtual_pi_network : public technology_network auto size() const { - return static_cast(_storage->nodes.size() - virtual_inputs.size()); + return static_cast(_storage->nodes.size()); } - [[nodiscard]] auto size_virtual() const + [[nodiscard]] auto size_real() const { - return static_cast(_storage->nodes.size()); + return static_cast(_storage->nodes.size() - virtual_inputs.size()); } /*! \brief Creates a new virtual PI */ diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index 92c7944c6..6984ac32d 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -9,6 +9,7 @@ #include #include +#include using namespace fiction; @@ -36,13 +37,13 @@ TEST_CASE("Copy network and size consistency", "[virtual-pi-view]") // virtual_pi_network is a deep copy. THe original network won't be affected by any changes after the copy CHECK(tec.size() == 5); // This is the size disregarding virtual PIs. So this would correspond to the size in a normal technology_network - CHECK(vpi.size() == 7); + CHECK(vpi.size_real() == 7); // This is the size with the virtual PIs - CHECK(vpi.size_virtual() == 9); + CHECK(vpi.size() == 9); vpi.remove_virtual_input_nodes(); // After removing/remapping the virtual PIs to their real PIs the sizes are equal - CHECK(vpi.size_virtual() == vpi.size()); - CHECK(vpi.size_virtual() == 7); + CHECK(vpi.size_real() == vpi.size()); + CHECK(vpi.size() == 7); } TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]") @@ -81,3 +82,42 @@ TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]") bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); CHECK(cec_m == 1); } + +TEST_CASE("Rank View on virtual PIs", "[virtual-rank-view]") +{ + virtual_pi_network vpi{}; + + const auto a = vpi.create_pi(); + const auto b = vpi.create_pi(); + + const auto c = vpi.create_virtual_pi(a); + const auto d = vpi.create_virtual_pi(b); + + const auto f1 = vpi.create_and(a, b); + const auto f2 = vpi.create_and(b, c); + const auto f3 = vpi.create_or(a, d); + + vpi.create_po(f1); + vpi.create_po(f2); + vpi.create_po(f3); + + std::cout << "real tec num_gates: " << vpi.size() << std::endl; + std::cout << "virt tec num_gates: " << vpi.size_real() << std::endl; + + vpi.foreach_node([&](const auto& nd) + { + std::cout << "Nd:" << nd << "\n"; + vpi.foreach_fanin(nd, [&](const auto& fi) + { + std::cout << "Fis:" << fi << "\n"; + }); + if (vpi.is_virtual_pi(nd)){ + std::cout << "Is virtual PI \n"; + } + }); + + //vpi.remove_virtual_input_nodes(); + + mockturtle::rank_view vpi_r(vpi); + +} From cb22aa92877c387051d1795aec83e871df316d0a Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 18 Jun 2024 14:28:42 +0200 Subject: [PATCH 12/84] :art: redefinition of functions. --- .../fiction/networks/virtual_pi_network.hpp | 73 +++++++++++++++++-- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 4aadd0fc6..24a0f85ef 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -61,34 +61,66 @@ class virtual_pi_network : public technology_network return index; } - [[nodiscard]] bool is_virtual_pi(node const& n) const + [[nodiscard]] bool is_pi(node const& n) const + { + return std::find(virtual_inputs.begin(), virtual_inputs.end(), n) != virtual_inputs.end() || + std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); + } + + [[nodiscard]] bool is_pi_virtual(node const& n) const { return std::find(virtual_inputs.begin(), virtual_inputs.end(), n) != virtual_inputs.end(); } - [[nodiscard]] bool is_virtual_ci(node const& n) const + [[nodiscard]] bool is_pi_real(node const& n) const + { + return std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); + } + + [[nodiscard]] bool is_ci(node const& n) const + { + return std::find(virtual_inputs.begin(), virtual_inputs.end(), n) != virtual_inputs.end() || + std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); + } + + [[nodiscard]] bool is_ci_virtual(node const& n) const { return std::find(virtual_inputs.begin(), virtual_inputs.end(), n) != virtual_inputs.end(); } + [[nodiscard]] bool is_ci_real(node const& n) const + { + return std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); + } + + [[nodiscard]] auto num_cis() const + { + return static_cast(_storage->inputs.size() + virtual_inputs.size()); + } + [[nodiscard]] auto num_cis_virtual() const { return static_cast(virtual_inputs.size()); } - [[nodiscard]] auto num_pis_virtual() const + [[nodiscard]] auto num_cis_real() const { - return static_cast(virtual_inputs.size()); + return static_cast(_storage->inputs.size()); } - [[nodiscard]] auto num_cis_all() const + [[nodiscard]] auto num_pis() const { return static_cast(_storage->inputs.size() + virtual_inputs.size()); } - [[nodiscard]] auto num_pis_all() const + [[nodiscard]] auto num_pis_virtual() const + { + return static_cast(virtual_inputs.size()); + } + + [[nodiscard]] auto num_pis_real() const { - return static_cast(_storage->inputs.size() + virtual_inputs.size()); + return static_cast(_storage->inputs.size()); } [[nodiscard]] auto get_real_pi(const node& v_pi) const @@ -101,13 +133,38 @@ class virtual_pi_network : public technology_network throw std::runtime_error("Error: node is not a virtual pi"); } - // exclude virtual_inputs + template + void foreach_pi( Fn&& fn ) const + { + mockturtle::detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); + mockturtle::detail::foreach_element(virtual_inputs.begin(), virtual_inputs.end(), fn); + } + + template + void foreach_pi_real( Fn&& fn ) const + { + mockturtle::detail::foreach_element( _storage->inputs.begin(), _storage->inputs.end(), fn ); + } + template void foreach_pi_virtual(Fn&& fn) const { mockturtle::detail::foreach_element(virtual_inputs.begin(), virtual_inputs.end(), fn); } + template + void foreach_ci( Fn&& fn ) const + { + mockturtle::detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); + mockturtle::detail::foreach_element(virtual_inputs.begin(), virtual_inputs.end(), fn); + } + + template + void foreach_ci_real( Fn&& fn ) const + { + mockturtle::detail::foreach_element( _storage->inputs.begin(), _storage->inputs.end(), fn ); + } + template void foreach_ci_virtual(Fn&& fn) const { From 2e8251743a88e48c5d586db56778c052ac4a97da Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 19 Jun 2024 09:57:07 +0200 Subject: [PATCH 13/84] :heavy_plus_sign: added extended_rank_view.cpp and extended_rank_view.cpp. --- .../networks/views/extended_rank_view.hpp | 62 +++++++++++++++ test/networks/views/extended_rank_view.cpp | 19 +++++ test/networks/virtual_pi_network.cpp | 78 +++++++++++++++---- 3 files changed, 144 insertions(+), 15 deletions(-) create mode 100644 include/fiction/networks/views/extended_rank_view.hpp create mode 100644 test/networks/views/extended_rank_view.cpp diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp new file mode 100644 index 000000000..174173e9e --- /dev/null +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -0,0 +1,62 @@ +// +// Created by benjamin on 6/18/24. +// + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifndef FICTION_VIRTUAL_RANK_VIEW_HPP +#define FICTION_VIRTUAL_RANK_VIEW_HPP + +// this rank view can assign specific ranks to nodes in one level +// to check validity of the rank view you can use check_rank_validity() + +// add the trait that is added in the virtual rank view +template && mockturtle::has_at_rank_position_v && + mockturtle::has_swap_v && mockturtle::has_width_v && + mockturtle::has_foreach_node_in_rank_v && mockturtle::has_foreach_gate_in_rank_v> +class extended_rank_view +{}; + +/*ToDo: Reverse true and false and implement the traits for the new implemented functions + * remove_virtual_input_nodes has to be modified so that it is deleting also the nodes out of the ranks + * -> this impacts the behaviour of foreach_node etc. + * include a new function, which allows to just assign a rank to a node + * include a function which tests for validity of ranks. meaning that there is a increasing order of ranks in each level + * -> this is good to verify if the ranks are still valid after deleting the virtual nodes + * */ +template +class extended_rank_view : public mockturtle::rank_view +{ + public: + extended_rank_view(Ntk const& ntk) : mockturtle::rank_view(ntk) {} +}; + +template +class extended_rank_view : public mockturtle::rank_view +{ + public: + using node = typename Ntk::node; + extended_rank_view(Ntk const& ntk) : mockturtle::rank_view(ntk) {} + + void modify_rank(node const& n, uint32_t new_rank) { + + } +}; + +//deduction guide +template +extended_rank_view( T const& ) -> extended_rank_view; + +#endif // FICTION_VIRTUAL_RANK_VIEW_HPP diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp new file mode 100644 index 000000000..86ddfca06 --- /dev/null +++ b/test/networks/views/extended_rank_view.cpp @@ -0,0 +1,19 @@ +// +// Created by benjamin on 6/18/24. +// + +#include + +#include +#include +#include + +#include + +using namespace fiction; + +TEST_CASE("Check Traits", "[virtual-rank-view]") +{ + CHECK(!has_create_virtual_pi_v); + CHECK(has_create_virtual_pi_v); +} diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index 6984ac32d..04131e4e9 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -23,9 +23,8 @@ TEST_CASE("Copy network and size consistency", "[virtual-pi-view]") const auto f1 = tec.create_and(a, b); virtual_pi_network vpi{tec}; - const auto c = vpi.create_virtual_pi(a); - const auto d = vpi.create_virtual_pi(b); - + const auto c = vpi.create_virtual_pi(a); + const auto d = vpi.create_virtual_pi(b); const auto f2 = vpi.create_and(b, c); const auto f3 = vpi.create_or(a, d); @@ -104,20 +103,69 @@ TEST_CASE("Rank View on virtual PIs", "[virtual-rank-view]") std::cout << "real tec num_gates: " << vpi.size() << std::endl; std::cout << "virt tec num_gates: " << vpi.size_real() << std::endl; - vpi.foreach_node([&](const auto& nd) - { - std::cout << "Nd:" << nd << "\n"; - vpi.foreach_fanin(nd, [&](const auto& fi) - { - std::cout << "Fis:" << fi << "\n"; - }); - if (vpi.is_virtual_pi(nd)){ - std::cout << "Is virtual PI \n"; - } - }); + /*vpi.foreach_node( + [&](const auto& nd) + { + std::cout << "Nd:" << nd << "\n"; + vpi.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); + if (vpi.is_virtual_pi(nd)) + { + std::cout << "Is virtual PI \n"; + } + });*/ - //vpi.remove_virtual_input_nodes(); + // vpi.remove_virtual_input_nodes(); mockturtle::rank_view vpi_r(vpi); + /* vpi_r.foreach_pi([&](const auto& nd) { + std::cout << "Nd:" << nd << "\n"; + auto rnk = vpi_r.rank_position(nd); + auto lvl = vpi_r.level(nd); + std::cout << "Level: " << lvl << "\n"; + std::cout << "Rank: " << rnk << "\n"; + });*/ + std::cout << "r pis: " < Date: Wed, 19 Jun 2024 14:35:47 +0200 Subject: [PATCH 14/84] :art: extended_rank_view is a rank_view with additional modify_rank and check_validity functions --- .../networks/views/extended_rank_view.hpp | 398 +++++++++++++++++- .../node_duplication_planarization.cpp | 52 +++ test/networks/views/extended_rank_view.cpp | 56 ++- 3 files changed, 483 insertions(+), 23 deletions(-) diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index 174173e9e..6b8574e2e 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include @@ -20,43 +19,402 @@ // this rank view can assign specific ranks to nodes in one level // to check validity of the rank view you can use check_rank_validity() - -// add the trait that is added in the virtual rank view -template && mockturtle::has_at_rank_position_v && mockturtle::has_swap_v && mockturtle::has_width_v && mockturtle::has_foreach_node_in_rank_v && mockturtle::has_foreach_gate_in_rank_v> class extended_rank_view {}; -/*ToDo: Reverse true and false and implement the traits for the new implemented functions - * remove_virtual_input_nodes has to be modified so that it is deleting also the nodes out of the ranks - * -> this impacts the behaviour of foreach_node etc. - * include a new function, which allows to just assign a rank to a node - * include a function which tests for validity of ranks. meaning that there is a increasing order of ranks in each level - * -> this is good to verify if the ranks are still valid after deleting the virtual nodes - * */ template -class extended_rank_view : public mockturtle::rank_view +class extended_rank_view : public mockturtle::depth_view { public: - extended_rank_view(Ntk const& ntk) : mockturtle::rank_view(ntk) {} + extended_rank_view(Ntk const& ntk) : mockturtle::depth_view(ntk) {} }; template -class extended_rank_view : public mockturtle::rank_view +class extended_rank_view : public mockturtle::depth_view { public: - using node = typename Ntk::node; - extended_rank_view(Ntk const& ntk) : mockturtle::rank_view(ntk) {} + static constexpr bool is_topologically_sorted = true; + using storage = typename Ntk::storage; + using node = typename Ntk::node; + using signal = typename Ntk::signal; + + explicit extended_rank_view() : mockturtle::depth_view(), rank_pos{*this}, ranks{}, max_rank_width{0} + { + static_assert(mockturtle::is_network_type_v, "Ntk is not a network type"); + static_assert(mockturtle::has_foreach_node_v, "Ntk does not implement the foreach_node method"); + static_assert(mockturtle::has_get_node_v, "Ntk does not implement the get_node method"); + static_assert(mockturtle::has_num_pis_v, "Ntk does not implement the num_pis method"); + static_assert(mockturtle::has_is_ci_v, "Ntk does not implement the is_ci method"); + static_assert(mockturtle::has_is_constant_v, "Ntk does not implement the is_constant method"); + + add_event = Ntk::events().register_add_event([this](auto const& n) { on_add(n); }); + } + + /*! \brief Standard constructor. + * + * \param ntk Base network + */ + explicit extended_rank_view(Ntk const& ntk) : + mockturtle::depth_view{ntk}, + rank_pos{ntk}, + ranks{this->depth() + 1}, + max_rank_width{0} + { + static_assert(mockturtle::is_network_type_v, "Ntk is not a network type"); + static_assert(mockturtle::has_foreach_node_v, "Ntk does not implement the foreach_node method"); + static_assert(mockturtle::has_get_node_v, "Ntk does not implement the get_node method"); + static_assert(mockturtle::has_num_pis_v, "Ntk does not implement the num_pis method"); + static_assert(mockturtle::has_is_ci_v, "Ntk does not implement the is_ci method"); + static_assert(mockturtle::has_is_constant_v, "Ntk does not implement the is_constant method"); + + init_ranks(); + + add_event = Ntk::events().register_add_event([this](auto const& n) { on_add(n); }); + } + /*! + * \brief Overloaded constructor with ranks specification. + * + * This constructor is similar to the standard one, with the addition of specifying initial node ranks within the + * network. + * + * \param ntk Base network + * \param ranks A vector of vectors containing nodes, each sub-vector represents a particular rank, and the nodes + * within it. + */ + explicit extended_rank_view(Ntk const& ntk, std::vector> ranks) : + mockturtle::depth_view{ntk}, + rank_pos{ntk}, + ranks{this->depth() + 1}, + max_rank_width{0} + { + static_assert(mockturtle::is_network_type_v, "Ntk is not a network type"); + static_assert(mockturtle::has_foreach_node_v, "Ntk does not implement the foreach_node method"); + static_assert(mockturtle::has_get_node_v, "Ntk does not implement the get_node method"); + static_assert(mockturtle::has_num_pis_v, "Ntk does not implement the num_pis method"); + static_assert(mockturtle::has_is_ci_v, "Ntk does not implement the is_ci method"); + static_assert(mockturtle::has_is_constant_v, "Ntk does not implement the is_constant method"); + + init_ranks(ranks); + + add_event = Ntk::events().register_add_event([this](auto const& n) { on_add(n); }); + } + + /*! \brief Copy constructor. */ + extended_rank_view(extended_rank_view const& other) : + mockturtle::depth_view(other), + rank_pos{other.rank_pos}, + ranks{other.ranks}, + max_rank_width{other.max_rank_width} + { + add_event = Ntk::events().register_add_event([this](auto const& n) { on_add(n); }); + } + + extended_rank_view& operator=(extended_rank_view const& other) + { + /* delete the event of this network */ + Ntk::events().release_add_event(add_event); - void modify_rank(node const& n, uint32_t new_rank) { + /* update the base class */ + this->_storage = other._storage; + this->_events = other._events; + /* copy */ + rank_pos = other.rank_pos; + ranks = other.ranks; + max_rank_width = other.max_rank_width; + + /* register new event in the other network */ + add_event = Ntk::events().register_add_event([this](auto const& n) { on_add(n); }); + + return *this; + } + + ~extended_rank_view() + { + Ntk::events().release_add_event(add_event); + } + /** + * \brief Returns the rank position of a node. + * + * @param n Node to get the rank position of. + * @return Rank position of node `n`. + */ + uint32_t rank_position(node const& n) const noexcept + { + assert(!this->is_constant(n) && "node must not be constant"); + + return rank_pos[n]; + } + + bool check_validity() const noexcept + { + for (size_t i = 0; i < ranks.size(); ++i) + { + const auto& rank = ranks[i]; + uint32_t expected_rank_pos = 0; + for (const auto& n : rank) + { + // Check if the level is different from the rank level + if (this->level(n) != i) + { + return false; + } + // Check if the rank_pos is not in ascending order + if(rank_pos[n] != expected_rank_pos) + { + return false; + } + ++expected_rank_pos; // Increment the expected rank_pos + } + } + return true; + } + + /** + * \brief Modifies the rank by updating the nodes at the specified level with the given nodes. + * + * This function replaces the nodes at the specified level with the given nodes and updates the rank positions + * accordingly. + * + * \param level The level at which to modify the rank. + * \param nodes The new set of nodes for the specified level. + */ + void modify_rank(uint32_t const level, std::vector& nodes) + { + auto& rank = ranks[level]; + rank = nodes; + std::for_each(rank.cbegin(), rank.cend(), [this, i = 0u](auto const& n) mutable { rank_pos[n] = i++; }); } + /** + * \brief Returns the node at a certain rank position. + * + * @param level Level in the network, i.e., rank to get the node from. + * @param pos Position in the rank to get the node from. + * @return Node at position `pos` in rank `level`. + */ + node at_rank_position(uint32_t const level, uint32_t const pos) const noexcept + { + assert(level < ranks.size() && "level must be less than the number of ranks"); + assert(pos < ranks[level].size() && "pos must be less than the number of nodes in rank"); + + return ranks[level][pos]; + } + /** + * \brief Returns the width of the widest rank in the network. + * + * @return Width of the widest rank in the network. + */ + uint32_t width() const noexcept + { + return max_rank_width; + } + /** + * \brief Swaps the positions of two nodes in the same rank. + * + * @param n1 First node to swap. + * @param n2 Second node to swap. + */ + void swap(node const& n1, node const& n2) noexcept + { + assert(this->level(n1) == this->level(n2) && "nodes must be in the same rank"); + + auto& pos1 = rank_pos[n1]; + auto& pos2 = rank_pos[n2]; + + std::swap(ranks[this->level(n1)][pos1], ranks[this->level(n2)][pos2]); + std::swap(pos1, pos2); + } + /** + * \brief Sorts the given rank according to a comparator. + * + * @tparam Cmp Functor type that compares two nodes. It needs to fulfill the requirements of `Compare` (named C++ + * requirement). + * @param level The level of the rank to sort. + * @param cmp The comparator to use. + */ + template + void sort_rank(uint32_t const level, Cmp const& cmp) + { + // level must be less than the number of ranks + if (level < ranks.size()) + { + auto& rank = ranks[level]; + + std::sort(rank.begin(), rank.end(), cmp); + std::for_each(rank.cbegin(), rank.cend(), [this, i = 0u](auto const& n) mutable { rank_pos[n] = i++; }); + } + } + /** + * \brief Applies a given function to each node in the rank level in order. + * + * @tparam Fn Functor type. + * @param level The rank to apply fn to. + * @param fn The function to apply. + */ + template + void foreach_node_in_rank(uint32_t const level, Fn&& fn) const + { + // level must be less than the number of ranks + if (level < ranks.size()) + { + auto const& rank = ranks[level]; + + mockturtle::detail::foreach_element(rank.cbegin(), rank.cend(), std::forward(fn)); + } + } + /** + * \brief Applies a given function to each node in rank order. + * + * This function overrides the `foreach_node` method of the base class. + * + * @tparam Fn Functor type. + * @param fn The function to apply. + */ + template + void foreach_node(Fn&& fn) const + { + for (auto l = 0; l < ranks.size(); ++l) + { + foreach_node_in_rank(l, std::forward(fn)); + } + } + /** + * \brief Applies a given function to each gate in the rank level in order. + * + * @tparam Fn Functor type. + * @param level The rank to apply fn to. + * @param fn The function to apply. + */ + template + void foreach_gate_in_rank(uint32_t const level, Fn&& fn) const + { + // level must be less than the number of ranks + if (level < ranks.size()) + { + auto const& rank = ranks[level]; + + mockturtle::detail::foreach_element_if( + rank.cbegin(), rank.cend(), [this](auto const& n) { return !this->is_ci(n); }, std::forward(fn)); + } + } + /** + * \brief Applies a given function to each gate in rank order. + * + * This function overrides the `foreach_gate` method of the base class. + * + * @tparam Fn Functor type. + * @param fn The function to apply. + */ + template + void foreach_gate(Fn&& fn) const + { + for (auto l = 0; l < ranks.size(); ++l) + { + foreach_gate_in_rank(l, std::forward(fn)); + } + } + /** + * \brief Applies a given function to each PI in rank order. + * + * This function overrides the `foreach_pi` method of the base class. + * + * @tparam Fn Functor type. + * @param fn The function to apply. + */ + template + void foreach_pi(Fn&& fn) const + { + std::vector pis{}; + pis.reserve(this->num_pis()); + + mockturtle::depth_view::foreach_pi([&pis](auto const& pi) { pis.push_back(pi); }); + std::sort(pis.begin(), pis.end(), + [this](auto const& n1, auto const& n2) { return rank_pos[n1] < rank_pos[n2]; }); + mockturtle::detail::foreach_element(pis.cbegin(), pis.cend(), std::forward(fn)); + } + /** + * Overrides the base class method to also call the add_event on create_pi(). + * + * @note This can (and in fact will) lead to issues if Ntk already calls add_event functions on create_pi()! + * + * @return Newly created PI signal. + */ + signal create_pi() + { + auto const n = mockturtle::depth_view::create_pi(); + this->resize_levels(); + on_add(this->get_node(n)); + return n; + } + + private: + mockturtle::node_map rank_pos; + std::vector> ranks; + uint32_t max_rank_width; + + std::shared_ptr::add_event_type> add_event; + + void insert_in_rank(node const& n) noexcept + { + auto& rank = ranks[this->level(n)]; + rank_pos[n] = rank.size(); + rank.push_back(n); + max_rank_width = std::max(max_rank_width, static_cast(rank.size())); + } + + void on_add(node const& n) noexcept + { + if (this->level(n) >= ranks.size()) + { + // add sufficient ranks to store the new node + ranks.insert(ranks.end(), this->level(n) - ranks.size() + 1, {}); + } + rank_pos.resize(); + + insert_in_rank(n); + } + + void init_ranks() noexcept + { + mockturtle::depth_view::foreach_node( + [this](auto const& n) + { + if (!this->is_constant(n)) + { + insert_in_rank(n); + } + }); + } + + void insert_in_rank(node const& n, size_t rank_level) noexcept + { + auto &rank = ranks[rank_level]; + rank_pos[n] = rank.size(); + rank.push_back(n); + max_rank_width = std::max(max_rank_width, static_cast(rank.size())); + } + + void init_ranks(std::vector> const& input_ranks) noexcept + { + for(size_t i = 0; i < input_ranks.size(); ++i){ + auto const& rank_nodes = input_ranks[i]; + for(auto const& n : rank_nodes) + { + if (!this->is_constant(n)) + { + insert_in_rank(n, i); + } + } + } + } + }; -//deduction guide -template -extended_rank_view( T const& ) -> extended_rank_view; +template +extended_rank_view(T const&) -> extended_rank_view; #endif // FICTION_VIRTUAL_RANK_VIEW_HPP diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index 87dce738a..8b679932b 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -6,6 +6,7 @@ #include "utils/blueprints/network_blueprints.hpp" #include "utils/equivalence_checking_utils.hpp" +#include #include #include @@ -66,3 +67,54 @@ TEST_CASE("Multi Level test", "[node-duplication-planarization]") CHECK(1 == 1); } + +// Implement reverse balancing function. Also it should propagate PIs all to the last level +TEST_CASE("Balancing Test", "[node-duplication-planarization]") +{ + technology_network tec{}; + + CHECK(mockturtle::has_clear_visited_v); + CHECK(mockturtle::has_visited_v); + CHECK(mockturtle::has_set_visited_v); + + const auto x1 = tec.create_pi(); + const auto x2 = tec.create_pi(); + const auto x3 = tec.create_pi(); + const auto x4 = tec.create_pi(); + const auto x5 = tec.create_pi(); + const auto f1 = tec.create_not(x2); + const auto f2 = tec.create_nary_and({x1, x2, x3, x4}); + const auto f3 = tec.create_nary_and({x3, x4, x5}); + tec.create_po(f1); + tec.create_po(f2); + tec.create_po(f3); + + auto blc = is_balanced(tec); + std::cout << "Balanced: " << blc << "\n"; + + auto tec_b = network_balancing(tec); + blc = is_balanced(tec_b); + std::cout << "Balanced: " << blc << "\n"; + + const auto vpi_r = mockturtle::rank_view(tec_b); + vpi_r.foreach_node([&](const auto& nd) { + std::cout << "Nd:" << nd << "\n"; + if (vpi_r.is_inv(nd)) + { + std::cout << "is not" << "\n"; + } + if (vpi_r.is_buf(nd)) + { + std::cout << "is buf" << "\n"; + } + vpi_r.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); + auto rnk = vpi_r.rank_position(nd); + auto lvl = vpi_r.level(nd); + std::cout << "Level: " << lvl << "\n"; + std::cout << "Rank: " << rnk << "\n"; + }); + + const auto planarized_maj = node_duplication_planarization(tec); + + CHECK(1 == 1); +} diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index 86ddfca06..069030f49 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -4,6 +4,8 @@ #include +#include "fiction/algorithms/network_transformation/network_balancing.hpp" + #include #include #include @@ -12,8 +14,56 @@ using namespace fiction; -TEST_CASE("Check Traits", "[virtual-rank-view]") +TEST_CASE("Check modify ranks", "[extended-rank-view]") { - CHECK(!has_create_virtual_pi_v); - CHECK(has_create_virtual_pi_v); + technology_network tec{}; + + CHECK(mockturtle::has_clear_visited_v); + CHECK(mockturtle::has_visited_v); + CHECK(mockturtle::has_set_visited_v); + + const auto x1 = tec.create_pi(); + const auto x2 = tec.create_pi(); + const auto x3 = tec.create_pi(); + const auto x4 = tec.create_pi(); + const auto x5 = tec.create_pi(); + const auto f1 = tec.create_not(x2); + const auto f2 = tec.create_nary_and({x1, x2, x3, x4}); + const auto f3 = tec.create_nary_and({x3, x4, x5}); + tec.create_po(f1); + tec.create_po(f2); + tec.create_po(f3); + + auto blc = is_balanced(tec); + std::cout << "Balanced: " << blc << "\n"; + + auto tec_b = network_balancing(tec); + blc = is_balanced(tec_b); + std::cout << "Balanced: " << blc << "\n"; + + auto vpi_r = extended_rank_view(tec_b); + + std::vector nodes = {13, 10}; + vpi_r.modify_rank(2, nodes); + + vpi_r.foreach_node([&](const auto& nd) { + std::cout << "Nd:" << nd << "\n"; + /*if (vpi_r.is_inv(nd)) + { + std::cout << "is not" << "\n"; + } + if (vpi_r.is_buf(nd)) + { + std::cout << "is buf" << "\n"; + } + vpi_r.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; });*/ + auto rnk = vpi_r.rank_position(nd); + auto lvl = vpi_r.level(nd); + std::cout << "Level: " << lvl << "\n"; + std::cout << "Rank: " << rnk << "\n"; + }); + + std::cout << "Valid: " << vpi_r.check_validity() << std::endl; + + CHECK(1 == 1); } From 85bf4b454f60496f9bb1d7ead0dff4e129bb97c8 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 9 Jul 2024 08:49:00 +0200 Subject: [PATCH 15/84] :art: remove_virtual_input_nodes fixed. Take care of input and output iterators. --- .../fiction/networks/virtual_pi_network.hpp | 24 ++- test/networks/views/extended_rank_view.cpp | 12 +- test/networks/virtual_pi_network.cpp | 184 +++++++++++++++++- 3 files changed, 212 insertions(+), 8 deletions(-) diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 24a0f85ef..557c263d8 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -186,7 +186,7 @@ class virtual_pi_network : public technology_network std::sort(virtual_inputs.begin(), virtual_inputs.end(), std::greater()); for (uint32_t i : virtual_inputs) { if(i < _storage->nodes.size()) { - uint64_t new_node = ( _storage->outputs.begin() + i )->index; + uint64_t new_node = 0; // = ( _storage->outputs.begin() + i )->index for (const auto& pair : map) { if (pair.first == i) { new_node = pair.second; @@ -194,7 +194,27 @@ class virtual_pi_network : public technology_network } } substitute_node(i, new_node); - // The outputs iterators also need to be adjusted with -1 + // Adjust inputs + for ( auto& input : _storage->inputs ) + { + if (input > i) + { + --input; + } + } + // Adjust nodes vector + for ( auto j = 0u; j < _storage->nodes.size(); ++j ) + { + auto& n = _storage->nodes[j]; + for ( auto& child : n.children ) + { + if (child.data > i) + { + --child.data; + } + } + } + // Adjust outputs for ( auto& output : _storage->outputs ) { --output.index; diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index 069030f49..d551348dc 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -10,6 +10,7 @@ #include #include +#include #include using namespace fiction; @@ -37,16 +38,19 @@ TEST_CASE("Check modify ranks", "[extended-rank-view]") auto blc = is_balanced(tec); std::cout << "Balanced: " << blc << "\n"; - auto tec_b = network_balancing(tec); - blc = is_balanced(tec_b); + network_balancing_params ps; + ps.unify_outputs = true; + + auto tec_balanced = network_balancing(tec, ps); + blc = is_balanced(tec_balanced); std::cout << "Balanced: " << blc << "\n"; - auto vpi_r = extended_rank_view(tec_b); + auto vpi_r = extended_rank_view(tec_balanced); std::vector nodes = {13, 10}; vpi_r.modify_rank(2, nodes); - vpi_r.foreach_node([&](const auto& nd) { + vpi_r.foreach_po([&](const auto& nd) { std::cout << "Nd:" << nd << "\n"; /*if (vpi_r.is_inv(nd)) { diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index 04131e4e9..f2b9f1163 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -75,8 +75,60 @@ TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]") tec.create_po(f2_t); tec.create_po(f3_t); + vpi.foreach_node( + [&](const auto& nd) + { + std::cout << "Nd:" << nd << "\n"; + if (vpi.is_pi_real(nd)) + { + std::cout << "is pi real" << "\n"; + } + if (vpi.is_pi_virtual(nd)) + { + std::cout << "is pi virtual" << "\n"; + } + if (vpi.is_inv(nd)) + { + std::cout << "is not" << "\n"; + } + if (vpi.is_buf(nd)) + { + std::cout << "is buf" << "\n"; + } + if (vpi.is_po(nd)) + { + std::cout << "is po" << "\n"; + } + }); + vpi.remove_virtual_input_nodes(); + vpi.foreach_node( + [&](const auto& nd) + { + std::cout << "Nd:" << nd << "\n"; + if (vpi.is_pi_real(nd)) + { + std::cout << "is pi real" << "\n"; + } + if (vpi.is_pi_virtual(nd)) + { + std::cout << "is pi virtual" << "\n"; + } + if (vpi.is_inv(nd)) + { + std::cout << "is not" << "\n"; + } + if (vpi.is_buf(nd)) + { + std::cout << "is buf" << "\n"; + } + if (vpi.is_po(nd)) + { + std::cout << "is po" << "\n"; + } + }); + mockturtle::equivalence_checking_stats st; bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); CHECK(cec_m == 1); @@ -139,8 +191,8 @@ TEST_CASE("Rank View on virtual PIs", "[virtual-rank-view]") vpi_r.remove_virtual_input_nodes(); - std::cout << "r pis: " <(tec, vpi), {}, &st); + CHECK(cec_m == 1); +} From 85dab93dfa557f75fc2777a7a1add008bb3d02c0 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 9 Jul 2024 08:49:41 +0200 Subject: [PATCH 16/84] :heavy_plus_sign: network creation added. Only 1-ary and 2-ary functions compatible atm --- .../node_duplication_planarization.hpp | 289 ++++++++++++++++-- .../node_duplication_planarization.cpp | 75 ++++- 2 files changed, 338 insertions(+), 26 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index f366d6ba0..db9483f7f 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -6,6 +6,9 @@ #define FICTION_NODE_DUPLICATION_PLANARIZATION_HPP #include "fiction/algorithms/network_transformation/fanout_substitution.hpp" +#include "fiction/algorithms/network_transformation/network_balancing.hpp" +#include "fiction/networks/views/extended_rank_view.hpp" +#include "fiction/networks/virtual_pi_network.hpp" #include "fiction/traits.hpp" #include @@ -71,6 +74,210 @@ struct node_duplication_params namespace detail { +template +std::pair>, NtkSrc>> +initialize_copy_network_v(NtkSrc const& src) +{ + static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); + static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); + + static_assert(mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method"); + static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method"); + static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method"); + static_assert(mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi method"); + + mockturtle::node_map>, NtkSrc> old2new(src); + NtkDest dest; + + // Please modify next lines as per your requirements + + old2new[src.get_constant(false)].push_back(dest.get_constant(false)); + if (src.get_node(src.get_constant(true)) != src.get_node(src.get_constant(false))) + { + old2new[src.get_constant(true)].push_back(dest.get_constant(true)); + } + src.foreach_pi([&](auto const& n) { old2new[n].push_back(dest.create_pi()); }); + return {dest, old2new}; +} + +template +virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector>>& ntk_lvls) +{ + std::vector>> ntk_lvls_new; + std::unordered_map, bool> node_status; + // node_status[node] + ntk_lvls_new.resize(ntk_lvls.size()); + + auto init_v = initialize_copy_network_v(ntk); + auto& ntk_dest_v = init_v.first; + auto& old2new_v = init_v.second; + + const auto gather_fanin_signals = [&](const auto& n, const auto& lvl, size_t& edge_it) + { + std::vector children{}; + const auto edge_it_int = edge_it; + int first_fi_edge_it = -1; + + ntk.foreach_fanin(n, + [&](const auto& f) + { + const auto fn = ntk.get_node(f); + auto tgt_signal_v = old2new_v[fn]; + + // lvl[edge_it] gives the current iterator at where the edge can be connected + // to get the right signal, all nodes at old2new[n] need to be viewed + // match lvl[edge_it] against áll entries in old2new[n], then try lvl[edge_it+1] then try + // lvl[edge_it+2] + + assert(edge_it_int < lvl.size()); + + for (const auto& possible_node : tgt_signal_v) + { + for (size_t i = 0; i < 3; i++) + { + if (edge_it_int + i < lvl.size() && lvl[edge_it_int + i] == possible_node) + { + if (first_fi_edge_it != -1) + { + assert(edge_it_int + i == first_fi_edge_it + 1 || + edge_it_int + i == first_fi_edge_it - 1); + } + children.emplace_back(possible_node); + first_fi_edge_it = static_cast(edge_it_int + i); + if (edge_it_int + i > edge_it) + { + edge_it = edge_it_int + i; + } + break; + } + } + if (first_fi_edge_it != -1) + { + break; + } + } + + /*std::cout << n <<'\n';*/ + /*children.emplace_back(ntk.is_complemented(f) ? ntk_dest_v.create_not(tgt_signal) : + tgt_signal);*/ + }); + + return children; + }; + + // auto view = extended_rank_view(ntk_dest); + size_t edge_it = 0; + for (size_t i = ntk_lvls.size(); i-- > 0;) + { + /*if (i == 1) + { + std::cout << "POs" << + }*/ + edge_it = 0; + auto& lvl = ntk_lvls[i]; + auto& lvl_new = ntk_lvls_new[i]; + for (const auto& nd : lvl) + { + if (ntk.is_pi(nd)) + { + if (node_status[nd]) + { + const auto& new_node = ntk_dest_v.create_virtual_pi(nd); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + } + else + { + lvl_new.push_back(nd); + node_status[nd] = true; + } + } + else + { + auto children = gather_fanin_signals(nd, ntk_lvls_new[i + 1], edge_it); + + if (ntk.is_and(nd)) + { + const auto& new_node = ntk_dest_v.create_and(children[0], children[1]); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + /*if (i == 0) + { + ntk_dest_v.create_po(new_node); + }*/ + continue; + } + if (ntk.is_or(nd)) + { + const auto& new_node = ntk_dest_v.create_or(children[0], children[1]); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + continue; + } + if (ntk.is_xor(nd)) + { + const auto& new_node = ntk_dest_v.create_xor(children[0], children[1]); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + continue; + } + // ToDo:TEST 3-input functions + /*if (ntk.is_maj(nd)) + { + const auto& new_node = ntk_dest_v.create_maj(children[0], children[1], children[2]); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + continue; + }*/ + if (ntk.is_buf(nd)) + { + const auto& new_node = ntk_dest_v.create_buf(children[0]); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + continue; + } + if (ntk.is_inv(nd)) + { + const auto& new_node = ntk_dest_v.create_not(children[0]); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + continue; + } + } + } + } + + ntk.foreach_po( + [&ntk, &ntk_dest_v, &old2new_v](const auto& po) + { + const auto tgt_signal_v = old2new_v[ntk.get_node(po)]; + // POs dont get duplicated since the algorithm starts at the POs and duplicates other nodes according to + // their order + assert(tgt_signal_v.size() == 1); + const auto tgt_signal = tgt_signal_v[0]; + + const auto tgt_po = ntk.is_complemented(po) ? ntk_dest_v.create_not(tgt_signal) : tgt_signal; + + ntk_dest_v.create_po(tgt_po); + }); + + /*ntk_dest_v.foreach_pi([&](const auto& pi) + { + std::cout << "PI: " << pi << '\n'; + }); + ntk_dest_v.foreach_pi_real([&](const auto& pi) + { + std::cout << "PI real: " << pi << '\n'; + }); + ntk_dest_v.foreach_pi_virtual([&](const auto& pi) + { + std::cout << "PI virtual: " << pi << '\n'; + });*/ + + return ntk_dest_v; +} + template struct node_pair { @@ -133,9 +340,7 @@ template class node_duplication_planarization_impl { public: - node_duplication_planarization_impl(const Ntk& src, const node_duplication_params p) : - ntk(mockturtle::rank_view(src)) - {} + node_duplication_planarization_impl(const Ntk& src, const node_duplication_params p) : ntk(src) {} void compute_slice_delays(mockturtle::node nd, const bool border_pis) { @@ -184,11 +389,12 @@ class node_duplication_planarization_impl } } - for (const auto& node_pair : combinations) + // Debug output + /*for (const auto& node_pair : combinations) { std::cout << "Fanin Pair: (" << node_pair.pair.first << ", " << node_pair.pair.second << "), Delay: " << node_pair.delay << std::endl; - } + }*/ cur_lvl_pairs.push_back(combinations); } @@ -211,7 +417,7 @@ class node_duplication_planarization_impl if (minimum_it != combinations.end()) { const auto& min_combination = *minimum_it; - std::cout << "Minimum delay: " << min_combination.delay << std::endl; + // std::cout << "Minimum delay: " << min_combination.delay << std::endl; // Insert the terminal node insert_if_unique(min_combination.pair.second, next_level); @@ -246,7 +452,7 @@ class node_duplication_planarization_impl } } - void check_final_level(std::vector>& v_next_level, bool& f_final_level ) + void check_final_level(std::vector>& v_next_level, bool& f_final_level) { for (const auto& nd : v_next_level) { @@ -258,7 +464,8 @@ class node_duplication_planarization_impl } } - mockturtle::rank_view run() + //mockturtle::rank_view run() + virtual_pi_network run() { const bool border_pis = true; // ToDo: Determine the PO order @@ -270,14 +477,14 @@ class node_duplication_planarization_impl [this, &v_level](auto po) { // Recalculate the levels to start from the pos - std::cout << ntk.level(po) << std::endl; - ntk.set_level(po, ntk.depth()); + // std::cout << ntk.level(po) << std::endl; + // ntk.set_level(po, ntk.depth()); cur_fis.clear(); compute_slice_delays(po, border_pis); v_level.push_back(po); }); - int level = ntk.depth(); - std::cout << "push lvl: " << level << std::endl; + // int level = ntk.depth(); + // std::cout << "push lvl: " << level << std::endl; ntk_lvls.push_back(v_level); v_level.clear(); @@ -291,8 +498,8 @@ class node_duplication_planarization_impl // Process all other levels while (!v_level.empty() && !f_final_level) { - level--; - std::cout << "push lvl: " << level << std::endl; + // level--; + // std::cout << "push lvl: " << level << std::endl; // Push the level to the network ntk_lvls.push_back(v_level); cur_lvl_pairs.clear(); @@ -314,17 +521,49 @@ class node_duplication_planarization_impl if (f_final_level) { - std::cout << "push lvl: " << level - 1 << std::endl; + // std::cout << "push lvl: " << level - 1 << '\n'; ntk_lvls.push_back(v_level); } - std::cout << "width: " << ntk.width() << std::endl; - std::cout << "depth: " << ntk.depth() << std::endl; - return ntk; + // std::cout << "width: " << ntk.width() << std::endl; + // std::cout << "depth: " << ntk.depth() << std::endl; + + // Debug output for nodes in lvl + /*std::cout << "Here:" << '\n'; + for (size_t i = 0; i < ntk_lvls.size(); ++i) { + std::cout << "Level: " << i << '\n'; + for (auto n : ntk_lvls[i]) + { + std::cout << "Node: " << n << '\n'; + ntk.foreach_fanin(n, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); + } + }*/ + + /* ntk.foreach_node([&](const auto& nd) { + std::cout << "Nd:" << nd << "\n"; + *//*if (ntk.is_inv(nd)) + { + std::cout << "is not" << "\n"; + } + if (ntk.is_buf(nd)) + { + std::cout << "is buf" << "\n"; + } + ntk.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; });*//* + auto rnk = ntk.rank_position(nd); + auto lvl = ntk.level(nd); + std::cout << "Level: " << lvl << "\n"; + std::cout << "Rank: " << rnk << "\n"; + });*/ + + // create virtual pi network + auto new_ntk = create_virt_pi_ntk_from_lvls(ntk, ntk_lvls); + + return new_ntk;//mockturtle::rank_view(ntk); } private: - mockturtle::rank_view ntk; + Ntk ntk; std::vector>> cur_lvl_pairs; std::vector> cur_fis; std::vector>> ntk_lvls; @@ -341,7 +580,8 @@ class node_duplication_planarization_impl * shortest x-y paths at each level of the graph. */ template -mockturtle::rank_view node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) +//mockturtle::rank_view node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) +virtual_pi_network node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) { static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); @@ -363,13 +603,18 @@ mockturtle::rank_view node_duplication_planarization(const NtkSrc& ntk_ throw high_degree_fanin_exception(); }*/ - auto t_ntk = convert_network(ntk_src); + if (!is_balanced(ntk_src)) + { + throw std::runtime_error("Combinations are empty. There might be a dangling node"); + } + + // auto t_ntk = convert_network(ntk_src); /*if (!is_fanout_substituted(t_ntk)) { t_ntk = fanout_substitution(t_ntk); // Apply fanout substitution if needed }*/ - detail::node_duplication_planarization_impl p{t_ntk, ps}; + detail::node_duplication_planarization_impl p{ntk_src, ps}; auto result = p.run(); diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index 8b679932b..ff42b3a61 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -84,7 +84,7 @@ TEST_CASE("Balancing Test", "[node-duplication-planarization]") const auto x5 = tec.create_pi(); const auto f1 = tec.create_not(x2); const auto f2 = tec.create_nary_and({x1, x2, x3, x4}); - const auto f3 = tec.create_nary_and({x3, x4, x5}); + const auto f3 = tec.create_nary_or({x3, x4, x5}); tec.create_po(f1); tec.create_po(f2); tec.create_po(f3); @@ -92,12 +92,15 @@ TEST_CASE("Balancing Test", "[node-duplication-planarization]") auto blc = is_balanced(tec); std::cout << "Balanced: " << blc << "\n"; - auto tec_b = network_balancing(tec); + network_balancing_params ps; + ps.unify_outputs = true; + + auto tec_b = network_balancing(tec, ps); blc = is_balanced(tec_b); std::cout << "Balanced: " << blc << "\n"; const auto vpi_r = mockturtle::rank_view(tec_b); - vpi_r.foreach_node([&](const auto& nd) { + /*vpi_r.foreach_node([&](const auto& nd) { std::cout << "Nd:" << nd << "\n"; if (vpi_r.is_inv(nd)) { @@ -112,9 +115,73 @@ TEST_CASE("Balancing Test", "[node-duplication-planarization]") auto lvl = vpi_r.level(nd); std::cout << "Level: " << lvl << "\n"; std::cout << "Rank: " << rnk << "\n"; + });*/ + + auto planarized_maj = node_duplication_planarization(tec_b); + + planarized_maj.foreach_node([&](const auto& nd) { + std::cout << "Nd:" << nd << "\n"; + if (planarized_maj.is_pi_real(nd)) + { + std::cout << "is pi real" << "\n"; + } + if (planarized_maj.is_pi_virtual(nd)) + { + std::cout << "is pi virtual" << "\n"; + } + if (planarized_maj.is_inv(nd)) + { + std::cout << "is not" << "\n"; + } + if (planarized_maj.is_buf(nd)) + { + std::cout << "is buf" << "\n"; + } + if (planarized_maj.is_and(nd)) + { + std::cout << "is and" << "\n"; + } + if (planarized_maj.is_po(nd)) + { + std::cout << "is po" << "\n"; + } + planarized_maj.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); }); - const auto planarized_maj = node_duplication_planarization(tec); + planarized_maj.remove_virtual_input_nodes(); + + planarized_maj.foreach_node([&](const auto& nd) { + std::cout << "Nd:" << nd << "\n"; + if (planarized_maj.is_pi_real(nd)) + { + std::cout << "is pi real" << "\n"; + } + if (planarized_maj.is_pi_virtual(nd)) + { + std::cout << "is pi virtual" << "\n"; + } + if (planarized_maj.is_inv(nd)) + { + std::cout << "is not" << "\n"; + } + if (planarized_maj.is_buf(nd)) + { + std::cout << "is buf" << "\n"; + } + if (planarized_maj.is_and(nd)) + { + std::cout << "is and" << "\n"; + } + if (planarized_maj.is_po(nd)) + { + std::cout << "is po" << "\n"; + } + planarized_maj.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); + }); + + mockturtle::equivalence_checking_stats st; + bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); + CHECK(cec_m == 1); CHECK(1 == 1); } From 4e5b9ba6a192510c305b8ce32ff5dd450c228d98 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 9 Jul 2024 17:30:03 +0200 Subject: [PATCH 17/84] :art: code cleaned and test case added --- .../node_duplication_planarization.hpp | 98 +++++-------------- .../node_duplication_planarization.cpp | 45 ++++++++- 2 files changed, 69 insertions(+), 74 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index db9483f7f..cb67f25a5 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -113,6 +113,20 @@ virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector children{}; @@ -157,12 +171,7 @@ virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector 0;) { - /*if (i == 1) - { - std::cout << "POs" << - }*/ edge_it = 0; auto& lvl = ntk_lvls[i]; auto& lvl_new = ntk_lvls_new[i]; @@ -202,10 +207,6 @@ virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector run() + // mockturtle::rank_view run() virtual_pi_network run() { const bool border_pis = true; @@ -477,14 +465,10 @@ class node_duplication_planarization_impl [this, &v_level](auto po) { // Recalculate the levels to start from the pos - // std::cout << ntk.level(po) << std::endl; - // ntk.set_level(po, ntk.depth()); cur_fis.clear(); compute_slice_delays(po, border_pis); v_level.push_back(po); }); - // int level = ntk.depth(); - // std::cout << "push lvl: " << level << std::endl; ntk_lvls.push_back(v_level); v_level.clear(); @@ -498,19 +482,17 @@ class node_duplication_planarization_impl // Process all other levels while (!v_level.empty() && !f_final_level) { - // level--; - // std::cout << "push lvl: " << level << std::endl; // Push the level to the network ntk_lvls.push_back(v_level); cur_lvl_pairs.clear(); - // We need to create a new vector to store the nodes of the next level + // Store the nodes of the next level for (const auto& cur_node : v_level) { cur_fis.clear(); - // There is one slice in the H-Graph per node in the level + // There is one slice in the H-Graph for each node in the level compute_slice_delays(cur_node, border_pis); } - // Clear before starting computations on the enxt level + // Clear before starting computations on the next level v_level.clear(); // Compute the next level compute_node_order_next_level(v_level); @@ -518,48 +500,16 @@ class node_duplication_planarization_impl f_final_level = true; check_final_level(v_level, f_final_level); } - + // Push the final level (PIs) if (f_final_level) { - // std::cout << "push lvl: " << level - 1 << '\n'; ntk_lvls.push_back(v_level); } - // std::cout << "width: " << ntk.width() << std::endl; - // std::cout << "depth: " << ntk.depth() << std::endl; - - // Debug output for nodes in lvl - /*std::cout << "Here:" << '\n'; - for (size_t i = 0; i < ntk_lvls.size(); ++i) { - std::cout << "Level: " << i << '\n'; - for (auto n : ntk_lvls[i]) - { - std::cout << "Node: " << n << '\n'; - ntk.foreach_fanin(n, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); - } - }*/ - - /* ntk.foreach_node([&](const auto& nd) { - std::cout << "Nd:" << nd << "\n"; - *//*if (ntk.is_inv(nd)) - { - std::cout << "is not" << "\n"; - } - if (ntk.is_buf(nd)) - { - std::cout << "is buf" << "\n"; - } - ntk.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; });*//* - auto rnk = ntk.rank_position(nd); - auto lvl = ntk.level(nd); - std::cout << "Level: " << lvl << "\n"; - std::cout << "Rank: " << rnk << "\n"; - });*/ - // create virtual pi network auto new_ntk = create_virt_pi_ntk_from_lvls(ntk, ntk_lvls); - return new_ntk;//mockturtle::rank_view(ntk); + return new_ntk; // mockturtle::rank_view(ntk); } private: @@ -580,7 +530,7 @@ class node_duplication_planarization_impl * shortest x-y paths at each level of the graph. */ template -//mockturtle::rank_view node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) +// mockturtle::rank_view node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) virtual_pi_network node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) { static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); @@ -618,6 +568,8 @@ virtual_pi_network node_duplication_planarization(const NtkSrc& ntk_src, node_du auto result = p.run(); + // ToDo: Check for planarity + return result; } diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index ff42b3a61..a01739822 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -69,7 +69,7 @@ TEST_CASE("Multi Level test", "[node-duplication-planarization]") } // Implement reverse balancing function. Also it should propagate PIs all to the last level -TEST_CASE("Balancing Test", "[node-duplication-planarization]") +TEST_CASE("2-ary Balancing Test", "[node-duplication-planarization]") { technology_network tec{}; @@ -185,3 +185,46 @@ TEST_CASE("Balancing Test", "[node-duplication-planarization]") CHECK(1 == 1); } + +TEST_CASE("3-ary Balancing Test", "[node-duplication-planarization]") +{ + technology_network tec{}; + + CHECK(mockturtle::has_clear_visited_v); + CHECK(mockturtle::has_visited_v); + CHECK(mockturtle::has_set_visited_v); + + const auto x1 = tec.create_pi(); + const auto x2 = tec.create_pi(); + const auto x3 = tec.create_pi(); + const auto x4 = tec.create_pi(); + const auto x5 = tec.create_pi(); + const auto f1 = tec.create_not(x2); + const auto f2 = tec.create_nary_and({x1, x2, x3, x4}); + const auto f3 = tec.create_nary_or({x3, x4, x5}); + const auto f4 = tec.create_maj(x1, x2, f3); + tec.create_po(f1); + tec.create_po(f2); + tec.create_po(f3); + tec.create_po(f4); + + auto blc = is_balanced(tec); + + network_balancing_params ps; + ps.unify_outputs = true; + + auto tec_b = network_balancing(tec, ps); + blc = is_balanced(tec_b); + + const auto vpi_r = mockturtle::rank_view(tec_b); + + auto planarized_maj = node_duplication_planarization(tec_b); + + planarized_maj.remove_virtual_input_nodes(); + + mockturtle::equivalence_checking_stats st; + bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); + CHECK(cec_m == 1); + + CHECK(1 == 1); +} From 6f4c78e3c516c04b210708f7db335d4720ae4cf3 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 15 Jul 2024 17:13:17 +0200 Subject: [PATCH 18/84] :art: changed virt_pi storage to shared_ptr and handle node deletion for equivalence checking inside the extended rank view. --- .../node_duplication_planarization.hpp | 15 ++-- .../networks/views/extended_rank_view.hpp | 36 +++++++-- .../fiction/networks/virtual_pi_network.hpp | 44 +++++------ test/networks/views/extended_rank_view.cpp | 54 ++++++++++++- test/networks/virtual_pi_network.cpp | 78 ------------------- 5 files changed, 112 insertions(+), 115 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index cb67f25a5..334ab9293 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -102,7 +102,7 @@ initialize_copy_network_v(NtkSrc const& src) } template -virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector>>& ntk_lvls) +extended_rank_view create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector>>& ntk_lvls) { std::vector>> ntk_lvls_new; std::unordered_map, bool> node_status; @@ -262,8 +262,14 @@ virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector(ntk_dest_v); - return ntk_dest_v; + /*for (size_t i = 0; i < ntk_lvls_new.size(); i++) + { + ntk_dest_r.modify_rank(i, ntk_lvls_new[i]); + }*/ + + return ntk_dest_r; } template @@ -453,7 +459,7 @@ class node_duplication_planarization_impl } // mockturtle::rank_view run() - virtual_pi_network run() + extended_rank_view run() { const bool border_pis = true; // ToDo: Determine the PO order @@ -530,8 +536,7 @@ class node_duplication_planarization_impl * shortest x-y paths at each level of the graph. */ template -// mockturtle::rank_view node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) -virtual_pi_network node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) +extended_rank_view node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) { static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index 6b8574e2e..663559a53 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -2,6 +2,8 @@ // Created by benjamin on 6/18/24. // +#include + #include #include #include @@ -150,12 +152,32 @@ class extended_rank_view : public mockturtle::depth_view return rank_pos[n]; } + // This function has the only purpose to enable an equivalence checking of this network + template + typename std::enable_if::value>::type remove_virtual_input_nodes() + { + fiction::virtual_pi_network::remove_virtual_input_nodes(); + rank_pos.reset(); // Clear the node_map + // Clear each vector in ranks + for (auto& rank : ranks) + { + rank.clear(); + } + // Finally, clear the ranks vector itself + // ranks.clear(); + + // Reset max_rank_width + max_rank_width = 0; + this->init_ranks(); + std::cout << "remove() called\n"; + } + bool check_validity() const noexcept { for (size_t i = 0; i < ranks.size(); ++i) { - const auto& rank = ranks[i]; - uint32_t expected_rank_pos = 0; + const auto& rank = ranks[i]; + uint32_t expected_rank_pos = 0; for (const auto& n : rank) { // Check if the level is different from the rank level @@ -164,7 +186,7 @@ class extended_rank_view : public mockturtle::depth_view return false; } // Check if the rank_pos is not in ascending order - if(rank_pos[n] != expected_rank_pos) + if (rank_pos[n] != expected_rank_pos) { return false; } @@ -392,7 +414,7 @@ class extended_rank_view : public mockturtle::depth_view void insert_in_rank(node const& n, size_t rank_level) noexcept { - auto &rank = ranks[rank_level]; + auto& rank = ranks[rank_level]; rank_pos[n] = rank.size(); rank.push_back(n); max_rank_width = std::max(max_rank_width, static_cast(rank.size())); @@ -400,9 +422,10 @@ class extended_rank_view : public mockturtle::depth_view void init_ranks(std::vector> const& input_ranks) noexcept { - for(size_t i = 0; i < input_ranks.size(); ++i){ + for (size_t i = 0; i < input_ranks.size(); ++i) + { auto const& rank_nodes = input_ranks[i]; - for(auto const& n : rank_nodes) + for (auto const& n : rank_nodes) { if (!this->is_constant(n)) { @@ -411,7 +434,6 @@ class extended_rank_view : public mockturtle::depth_view } } } - }; template diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 557c263d8..c09f6faf1 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -19,7 +19,7 @@ namespace fiction /*!\brief Manager view for virtual PIs * * Virtual PIs are mapping of a "virtual" PI onto a "real" PI in the network. - * With virtual PIs PI-duplications are handled. + * Virtual PIs handle PI-duplications. */ class virtual_pi_network : public technology_network { @@ -28,16 +28,16 @@ class virtual_pi_network : public technology_network using signal = typename technology_network::signal; public: - explicit virtual_pi_network() = default; + explicit virtual_pi_network() : virtual_inputs(std::make_shared>()) {} - explicit virtual_pi_network(const technology_network& other) + explicit virtual_pi_network(const technology_network& other) : virtual_inputs(std::make_shared>()) { _storage = std::make_shared(*(other._storage)); // create deep copy of storage } auto num_gates() const { - return static_cast(_storage->nodes.size() - virtual_inputs.size() - _storage->inputs.size() - 2); + return static_cast(_storage->nodes.size() - virtual_inputs->size() - _storage->inputs.size() - 2); } auto size() const @@ -47,7 +47,7 @@ class virtual_pi_network : public technology_network [[nodiscard]] auto size_real() const { - return static_cast(_storage->nodes.size() - virtual_inputs.size()); + return static_cast(_storage->nodes.size() - virtual_inputs->size()); } /*! \brief Creates a new virtual PI */ @@ -55,7 +55,7 @@ class virtual_pi_network : public technology_network { const auto index = _storage->nodes.size(); _storage->nodes.emplace_back(); - virtual_inputs.emplace_back(index); + virtual_inputs->emplace_back(index); _storage->nodes[index].data[1].h1 = 2; map.emplace_back(index, real_pi); return index; @@ -63,13 +63,13 @@ class virtual_pi_network : public technology_network [[nodiscard]] bool is_pi(node const& n) const { - return std::find(virtual_inputs.begin(), virtual_inputs.end(), n) != virtual_inputs.end() || + return std::find(virtual_inputs->begin(), virtual_inputs->end(), n) != virtual_inputs->end() || std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); } [[nodiscard]] bool is_pi_virtual(node const& n) const { - return std::find(virtual_inputs.begin(), virtual_inputs.end(), n) != virtual_inputs.end(); + return std::find(virtual_inputs->begin(), virtual_inputs->end(), n) != virtual_inputs->end(); } [[nodiscard]] bool is_pi_real(node const& n) const @@ -79,13 +79,13 @@ class virtual_pi_network : public technology_network [[nodiscard]] bool is_ci(node const& n) const { - return std::find(virtual_inputs.begin(), virtual_inputs.end(), n) != virtual_inputs.end() || + return std::find(virtual_inputs->begin(), virtual_inputs->end(), n) != virtual_inputs->end() || std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); } [[nodiscard]] bool is_ci_virtual(node const& n) const { - return std::find(virtual_inputs.begin(), virtual_inputs.end(), n) != virtual_inputs.end(); + return std::find(virtual_inputs->begin(), virtual_inputs->end(), n) != virtual_inputs->end(); } [[nodiscard]] bool is_ci_real(node const& n) const @@ -95,12 +95,12 @@ class virtual_pi_network : public technology_network [[nodiscard]] auto num_cis() const { - return static_cast(_storage->inputs.size() + virtual_inputs.size()); + return static_cast(_storage->inputs.size() + virtual_inputs->size()); } [[nodiscard]] auto num_cis_virtual() const { - return static_cast(virtual_inputs.size()); + return static_cast(virtual_inputs->size()); } [[nodiscard]] auto num_cis_real() const @@ -110,12 +110,12 @@ class virtual_pi_network : public technology_network [[nodiscard]] auto num_pis() const { - return static_cast(_storage->inputs.size() + virtual_inputs.size()); + return static_cast(_storage->inputs.size() + virtual_inputs->size()); } [[nodiscard]] auto num_pis_virtual() const { - return static_cast(virtual_inputs.size()); + return static_cast(virtual_inputs->size()); } [[nodiscard]] auto num_pis_real() const @@ -137,7 +137,7 @@ class virtual_pi_network : public technology_network void foreach_pi( Fn&& fn ) const { mockturtle::detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); - mockturtle::detail::foreach_element(virtual_inputs.begin(), virtual_inputs.end(), fn); + mockturtle::detail::foreach_element(virtual_inputs->begin(), virtual_inputs->end(), fn); } template @@ -149,14 +149,14 @@ class virtual_pi_network : public technology_network template void foreach_pi_virtual(Fn&& fn) const { - mockturtle::detail::foreach_element(virtual_inputs.begin(), virtual_inputs.end(), fn); + mockturtle::detail::foreach_element(virtual_inputs->begin(), virtual_inputs->end(), fn); } template void foreach_ci( Fn&& fn ) const { mockturtle::detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); - mockturtle::detail::foreach_element(virtual_inputs.begin(), virtual_inputs.end(), fn); + mockturtle::detail::foreach_element(virtual_inputs->begin(), virtual_inputs->end(), fn); } template @@ -168,7 +168,7 @@ class virtual_pi_network : public technology_network template void foreach_ci_virtual(Fn&& fn) const { - mockturtle::detail::foreach_element(virtual_inputs.begin(), virtual_inputs.end(), fn); + mockturtle::detail::foreach_element(virtual_inputs->begin(), virtual_inputs->end(), fn); } template @@ -183,8 +183,8 @@ class virtual_pi_network : public technology_network // equivalence checking can be done. void remove_virtual_input_nodes() { - std::sort(virtual_inputs.begin(), virtual_inputs.end(), std::greater()); - for (uint32_t i : virtual_inputs) { + std::sort(virtual_inputs->begin(), virtual_inputs->end(), std::greater()); + for (uint32_t i : *virtual_inputs) { if(i < _storage->nodes.size()) { uint64_t new_node = 0; // = ( _storage->outputs.begin() + i )->index for (const auto& pair : map) { @@ -224,12 +224,12 @@ class virtual_pi_network : public technology_network } // Clear virtual_inputs after using it - virtual_inputs.clear(); + virtual_inputs->clear(); map.clear(); } protected: - std::vector virtual_inputs; + std::shared_ptr> virtual_inputs; std::vector> map; }; /* color_view */ diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index d551348dc..e20b2294b 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -4,13 +4,13 @@ #include -#include "fiction/algorithms/network_transformation/network_balancing.hpp" - +#include #include #include #include -#include +#include +#include #include using namespace fiction; @@ -71,3 +71,51 @@ TEST_CASE("Check modify ranks", "[extended-rank-view]") CHECK(1 == 1); } + +TEST_CASE("Check equivalence checking", "[extended-rank-view]") +{ + technology_network tec{}; + virtual_pi_network vpi{}; + + const auto a = vpi.create_pi(); + const auto b = vpi.create_pi(); + + const auto a_t = tec.create_pi(); + const auto b_t = tec.create_pi(); + + const auto c = vpi.create_virtual_pi(a); + const auto d = vpi.create_virtual_pi(b); + + const auto f1 = vpi.create_and(a, b); + const auto f2 = vpi.create_and(b, c); + const auto f3 = vpi.create_or(a, d); + + const auto f1_t = tec.create_and(a_t, b); + const auto f2_t = tec.create_and(b_t, a_t); + const auto f3_t = tec.create_or(a_t, b_t); + + vpi.create_po(f1); + vpi.create_po(f2); + vpi.create_po(f3); + + tec.create_po(f1_t); + tec.create_po(f2_t); + tec.create_po(f3_t); + + network_balancing_params ps; + ps.unify_outputs = true; + + auto vpi_r = extended_rank_view(vpi); + + std::cout << "Num Cis" << vpi_r.num_cis() << std::endl; + + vpi_r.remove_virtual_input_nodes(); + + std::cout << "Num Cis" << vpi_r.num_cis() << std::endl; + + mockturtle::equivalence_checking_stats st; + bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); + CHECK(cec_m == 1); + + CHECK(1 == 1); +} diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index f2b9f1163..c884d0dd0 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -265,86 +265,8 @@ TEST_CASE("Remove PIs and check equivalence second", "[virtual-pi-view]") vpi.create_po(f13); vpi.create_po(f14); - /*vpi.foreach_node( - [&](const auto& nd) - { - std::cout << "Nd:" << nd << "\n"; - if (vpi.is_pi_real(nd)) - { - std::cout << "is pi real" << "\n"; - } - if (vpi.is_pi_virtual(nd)) - { - std::cout << "is pi virtual" << "\n"; - } - if (vpi.is_inv(nd)) - { - std::cout << "is not" << "\n"; - } - if (vpi.is_buf(nd)) - { - std::cout << "is buf" << "\n"; - } - if (vpi.is_po(nd)) - { - std::cout << "is po" << "\n"; - } - vpi.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); - - });*/ - vpi.remove_virtual_input_nodes(); - /*tec.foreach_node( - [&](const auto& nd) - { - std::cout << "Nd:" << nd << "\n"; - if (tec.is_pi(nd)) - { - std::cout << "is pi" << "\n"; - } - if (tec.is_inv(nd)) - { - std::cout << "is not" << "\n"; - } - if (tec.is_buf(nd)) - { - std::cout << "is buf" << "\n"; - } - if (tec.is_po(nd)) - { - std::cout << "is po" << "\n"; - } - vpi.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); - }); - - vpi.foreach_node( - [&](const auto& nd) - { - std::cout << "Nd:" << nd << "\n"; - if (vpi.is_pi_real(nd)) - { - std::cout << "is pi real" << "\n"; - } - if (vpi.is_pi_virtual(nd)) - { - std::cout << "is pi virtual" << "\n"; - } - if (vpi.is_inv(nd)) - { - std::cout << "is not" << "\n"; - } - if (vpi.is_buf(nd)) - { - std::cout << "is buf" << "\n"; - } - if (vpi.is_po(nd)) - { - std::cout << "is po" << "\n"; - } - vpi.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); - });*/ - mockturtle::equivalence_checking_stats st; bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); CHECK(cec_m == 1); From eade5322f5477b0d589afb84eac2f964b9650661 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 15 Jul 2024 17:53:15 +0200 Subject: [PATCH 19/84] :art: cleaned and documented virtual_pi_network files --- .../fiction/networks/virtual_pi_network.hpp | 289 ++++++++++++++++-- test/networks/virtual_pi_network.cpp | 147 +-------- 2 files changed, 269 insertions(+), 167 deletions(-) diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index c09f6faf1..a2aa7c302 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -28,29 +28,71 @@ class virtual_pi_network : public technology_network using signal = typename technology_network::signal; public: + /** + * A default constructor for the `virtual_pi_network` class. + * + * This constructor initializes `virtual_inputs` with a shared pointer to an empty + * std::vector of uint32_t. + */ explicit virtual_pi_network() : virtual_inputs(std::make_shared>()) {} - explicit virtual_pi_network(const technology_network& other) : virtual_inputs(std::make_shared>()) + /** + * A parameterized constructor for the `virtual_pi_network` class. + * + * This constructor creates a `virtual_pi_network` using the `other` `technology_network` + * and initializes `virtual_inputs` with a shared pointer to an empty std::vector of uint32_t. + * + * @param other A `technology_network` object to create an instance of `virtual_pi_network`. + */ + explicit virtual_pi_network(const technology_network& other) : + virtual_inputs(std::make_shared>()) { _storage = std::make_shared(*(other._storage)); // create deep copy of storage } + /** + * @brief Reimplementation of num_gates(). Retrieves the number of gates in the virtual_pi_network. + * + * @return The number of gates in the virtual_pi_network. + */ auto num_gates() const { return static_cast(_storage->nodes.size() - virtual_inputs->size() - _storage->inputs.size() - 2); } + /** + * @brief Reimplementation of size(). Get the size of the virtual_pi_network. + * + * @return The size of the virtual_pi_network as a uint32_t. + */ auto size() const { return static_cast(_storage->nodes.size()); } + /** + * \brief Calculate the real size of the virtual_pi_network. + * + * This function calculates the real size of the virtual_pi_network by subtracting the size of the virtual_inputs + * vector from the size of the _storage->nodes vector. + * + * \return The real size of the virtual_pi_network as a uint32_t. + */ [[nodiscard]] auto size_real() const { return static_cast(_storage->nodes.size() - virtual_inputs->size()); } - /*! \brief Creates a new virtual PI */ + /** + * @brief Create a virtual PI mapping to a real PI. + * + * This function creates a virtual PI mapping to a real PI in the network. It adds a new node to the + * `_storage->nodes` vector and inserts the index of the new node into the `virtual _inputs` vector. It also updates + * the data of the new node. + * + * @param real_pi The node representing the real PI in the network. + * @return The index of the newly created virtual PI. + */ signal create_virtual_pi(const node& real_pi) { const auto index = _storage->nodes.size(); @@ -61,68 +103,175 @@ class virtual_pi_network : public technology_network return index; } + /** + * @brief Reimplementation of is_pi(). Check if a given node is a primary input (PI) in the virtual_pi_network. + * + * A node is considered a PI if it exists in the virtual_inputs vector or the inputs vector of the _storage object. + * + * @param n The node to check. + * @return True if the node is a PI, false otherwise. + */ [[nodiscard]] bool is_pi(node const& n) const { return std::find(virtual_inputs->begin(), virtual_inputs->end(), n) != virtual_inputs->end() || std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); } + /** + * @brief Check if a given node is a virtual primary input (PI) in the virtual_pi_network. + * + * A node is considered a virtual PI if it exists in the virtual_inputs vector of the virtual_pi_network. + * + * @param n The node to check. + * @return True if the node is a virtual PI, false otherwise. + */ [[nodiscard]] bool is_pi_virtual(node const& n) const { return std::find(virtual_inputs->begin(), virtual_inputs->end(), n) != virtual_inputs->end(); } + /** + * @brief Check if a given node is a real primary input (PI) in the virtual_pi_network. + * + * A node is considered a real PI if it exists in the inputs vector of the `_storage` object. + * + * @param n The node to check. + * @return True if the node is a real PI, false otherwise. + */ [[nodiscard]] bool is_pi_real(node const& n) const { return std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); } + /** + * Check if a node is a const input in the virtual_pi_network. + * + * A node is considered a const input if it exists in the virtual_inputs vector or the inputs vector of the _storage + * object. + * + * @param n The node to check. + * @return True if the node is a const input, false otherwise. + */ [[nodiscard]] bool is_ci(node const& n) const { return std::find(virtual_inputs->begin(), virtual_inputs->end(), n) != virtual_inputs->end() || std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); } + /** + * @brief Check if a given node is a virtual constant input (CI) in the virtual_pi_network. + * + * A node is considered a virtual CI if it exists in the virtual_inputs vector. + * + * @param n The node to check. + * @return True if the node is a virtual CI, false otherwise. + */ [[nodiscard]] bool is_ci_virtual(node const& n) const { return std::find(virtual_inputs->begin(), virtual_inputs->end(), n) != virtual_inputs->end(); } + /** + * @brief Check if a given node is a real combinatorial input (CI) in the virtual_pi_network. + * + * A node is considered a real CI if it exists in the inputs vector of the `_storage` object. + * + * @param n The node to check. + * @return True if the node is a real CI, false otherwise. + */ [[nodiscard]] bool is_ci_real(node const& n) const { return std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); } + /** + * @brief Retrieve the number of combinatorial inputs (CIs) in the virtual_pi_network. + * + * The num_cis() function returns the total number of CIs in the virtual_pi_network. + * It includes both virtual constant inputs and real constant inputs. + * + * @return The number of CIs as a uint32_t. + */ [[nodiscard]] auto num_cis() const { return static_cast(_storage->inputs.size() + virtual_inputs->size()); } + /** + * @brief Get the number of virtual combinatorial inputs (CIs) in the virtual_pi_network. + * + * The num_cis_virtual() function returns the total number of virtual CIs in the virtual_pi_network. + * Virtual constant inputs are those which exist in the virtual_inputs vector. + * + * @return The number of virtual CIs as a uint32_t. + */ [[nodiscard]] auto num_cis_virtual() const { return static_cast(virtual_inputs->size()); } + /** + * @brief Get the number of real constant inputs (CIs) in the virtual_pi_network. + * + * The num_cis_real() function returns the total number of real CIs in the virtual_pi_network. + * Real constant inputs are those which exist in the inputs vector of the `_storage` object. + * + * @return The number of real CIs as a uint32_t. + */ [[nodiscard]] auto num_cis_real() const { return static_cast(_storage->inputs.size()); } + /** + * @brief Reimplementation of num_pis(). Get the number of primary inputs (PIs) in the virtual_pi_network. + * + * The num_pis() function returns the total number of PIs in the virtual_pi_network. + * It includes both virtual PIs and real PIs. + * + * @return The number of PIs as a uint32_t. + */ [[nodiscard]] auto num_pis() const { return static_cast(_storage->inputs.size() + virtual_inputs->size()); } + /** + * @brief Get the number of virtual primary inputs (PIs) in the virtual_pi_network. + * + * The num_pis_virtual() function returns the total number of virtual PIs in the virtual_pi_network. + * Virtual PIs are those which exist in the virtual_inputs vector. + * + * @return The number of virtual PIs as a uint32_t. + */ [[nodiscard]] auto num_pis_virtual() const { return static_cast(virtual_inputs->size()); } + /** + * @brief Retrieve the number of real primary inputs (PIs) in the virtual_pi_network. + * + * The num_pis_real() function returns the total number of real PIs in the virtual_pi_network. + * Real PIs are those which exist in the inputs vector of the `_storage` object. + * + * @return The number of real PIs as a uint32_t. + */ [[nodiscard]] auto num_pis_real() const { return static_cast(_storage->inputs.size()); } + /** + * @brief Retrieve the real PI mapped to the given virtual PI. + * + * This function searches for the given virtual PI in the mapping table and returns the corresponding real PI. + * It throws a std::runtime_error if the virtual PI is not found in the mapping table. + * + * @param v_pi The virtual PI to find the corresponding real PI for. + * @return The real PI mapped to the virtual PI. + * @throws std::runtime_error If the virtual PI is not found in the mapping table. + */ [[nodiscard]] auto get_real_pi(const node& v_pi) const { auto it = std::find_if(map.begin(), map.end(), [v_pi](const auto& pair) { return pair.first == v_pi; }); @@ -133,44 +282,114 @@ class virtual_pi_network : public technology_network throw std::runtime_error("Error: node is not a virtual pi"); } - template - void foreach_pi( Fn&& fn ) const + /** + * @brief Reimplementation of foreach_pi(). Apply a given function to each primary input in the virtual_pi_network. + * + * This function iterates over all primary inputs in the virtual_pi_network and applies the given function to each + * primary input. + * + * @tparam Fn The type of function to apply to each primary input. + * @param fn The function to apply to each primary input. + */ + template + void foreach_pi(Fn&& fn) const { mockturtle::detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); mockturtle::detail::foreach_element(virtual_inputs->begin(), virtual_inputs->end(), fn); } - template - void foreach_pi_real( Fn&& fn ) const + /** + * @brief Iterates over the primary inputs of the circuit and applies a given + * function. + * + * This function iterates over the primary inputs of the circuit and applies a + * given function to each primary input. + * + * @tparam Fn The type of the function. + * @param fn The function to be applied to each primary input. + */ + template + void foreach_pi_real(Fn&& fn) const { - mockturtle::detail::foreach_element( _storage->inputs.begin(), _storage->inputs.end(), fn ); + mockturtle::detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); } + /** + * @brief Applies a given function to each element in a container. + * + * This function applies the provided function to each element in the container `Fn`. The container must support + * iteration using `begin()` and `end()` methods. + * + * @tparam Fn The container type. + * @param fn The function to apply to each element. + * + * @see mockturtle::detail::foreach_element + */ template void foreach_pi_virtual(Fn&& fn) const { mockturtle::detail::foreach_element(virtual_inputs->begin(), virtual_inputs->end(), fn); } - template - void foreach_ci( Fn&& fn ) const + /** + * @brief Applies a function to each combinatorial input. + * + * This function applies the given function to each input stored in the circuit. + * It also applies the function to each virtual input. + * The data types of the function passed to this function must be compatible + * with the data types stored in the inputs and virtual_inputs of the circuit. + * + * @tparam Fn The type of the function to apply to each input. + * @param fn The function to apply to each input. + */ + template + void foreach_ci(Fn&& fn) const { mockturtle::detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); mockturtle::detail::foreach_element(virtual_inputs->begin(), virtual_inputs->end(), fn); } - template - void foreach_ci_real( Fn&& fn ) const + /** + * @brief Applies a given function to each input element in the circuit + * + * This function iterates over each input element in the circuit and applies + * the given function to it. + * + * @tparam Fn The type of the function to be applied + * @param fn The function to be applied + */ + template + void foreach_ci_real(Fn&& fn) const { - mockturtle::detail::foreach_element( _storage->inputs.begin(), _storage->inputs.end(), fn ); + mockturtle::detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); } + /** + * @brief Executes a given function for each element in a container of virtual inputs. + * + * This function iterates over every element in the container of virtual inputs, and + * invokes the provided callable object on each element. + * + * @tparam Fn Type of the callable object. + * @param fn The callable object to be invoked on each element. + * + * @note The provided callable object must accept a single argument of the same type as + * the elements in the container. + */ template void foreach_ci_virtual(Fn&& fn) const { mockturtle::detail::foreach_element(virtual_inputs->begin(), virtual_inputs->end(), fn); } + /** + * @brief Applies a function to each gate in the circuit. + * + * This function iterates over each gate in the circuit, excluding the constants. + * + * @tparam Fn The type of the function. + * @param fn The function to apply to each gate. + */ template void foreach_gate(Fn&& fn) const { @@ -179,34 +398,48 @@ class virtual_pi_network : public technology_network r.begin(), r.end(), [this](auto n) { return (!is_ci(n) && !is_virtual_ci(n)); }, fn); } - // This function removed the virtual PIs and connects edges to the real PIs they are mapped to. Like this - // equivalence checking can be done. + /** + * @brief Removes virtual input nodes from the storage. This enables equivalence checking. + * + * This function removes virtual input nodes from the storage by performing the following steps: + * 1. Sorts the virtual input nodes in descending order. + * 2. For each virtual input node, finds the corresponding real_pi index mapped to it from the map. + * 3. Substitute the virtual input node with the new node index, which corresponds to the real_pi. + * 4. Adjusts the inputs, nodes vector, and outputs. + * 5. Erases the virtual input node from the nodes vector. + * + * After removing the virtual input nodes, this function clears the virtual_inputs and map containers. + */ void remove_virtual_input_nodes() { std::sort(virtual_inputs->begin(), virtual_inputs->end(), std::greater()); - for (uint32_t i : *virtual_inputs) { - if(i < _storage->nodes.size()) { - uint64_t new_node = 0; // = ( _storage->outputs.begin() + i )->index - for (const auto& pair : map) { - if (pair.first == i) { + for (uint32_t i : *virtual_inputs) + { + if (i < _storage->nodes.size()) + { + uint64_t new_node = 0; // = ( _storage->outputs.begin() + i )->index + for (const auto& pair : map) + { + if (pair.first == i) + { new_node = pair.second; break; } } substitute_node(i, new_node); // Adjust inputs - for ( auto& input : _storage->inputs ) + for (auto& input : _storage->inputs) { if (input > i) { --input; } } - // Adjust nodes vector - for ( auto j = 0u; j < _storage->nodes.size(); ++j ) + // Adjust nodes vector in the technology_network _storage + for (auto j = 0u; j < _storage->nodes.size(); ++j) { auto& n = _storage->nodes[j]; - for ( auto& child : n.children ) + for (auto& child : n.children) { if (child.data > i) { @@ -215,7 +448,7 @@ class virtual_pi_network : public technology_network } } // Adjust outputs - for ( auto& output : _storage->outputs ) + for (auto& output : _storage->outputs) { --output.index; } @@ -229,7 +462,13 @@ class virtual_pi_network : public technology_network } protected: - std::shared_ptr> virtual_inputs; + /* + * Shared pointer vector storage for virtual_inputs. + * */ + std::shared_ptr> virtual_inputs; + /* + * Map from virtual_pis to real_pis. + * */ std::vector> map; }; /* color_view */ diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index c884d0dd0..822001dcc 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -23,6 +23,7 @@ TEST_CASE("Copy network and size consistency", "[virtual-pi-view]") const auto f1 = tec.create_and(a, b); virtual_pi_network vpi{tec}; + const auto c = vpi.create_virtual_pi(a); const auto d = vpi.create_virtual_pi(b); @@ -75,153 +76,15 @@ TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]") tec.create_po(f2_t); tec.create_po(f3_t); - vpi.foreach_node( - [&](const auto& nd) - { - std::cout << "Nd:" << nd << "\n"; - if (vpi.is_pi_real(nd)) - { - std::cout << "is pi real" << "\n"; - } - if (vpi.is_pi_virtual(nd)) - { - std::cout << "is pi virtual" << "\n"; - } - if (vpi.is_inv(nd)) - { - std::cout << "is not" << "\n"; - } - if (vpi.is_buf(nd)) - { - std::cout << "is buf" << "\n"; - } - if (vpi.is_po(nd)) - { - std::cout << "is po" << "\n"; - } - }); - vpi.remove_virtual_input_nodes(); - - vpi.foreach_node( - [&](const auto& nd) - { - std::cout << "Nd:" << nd << "\n"; - if (vpi.is_pi_real(nd)) - { - std::cout << "is pi real" << "\n"; - } - if (vpi.is_pi_virtual(nd)) - { - std::cout << "is pi virtual" << "\n"; - } - if (vpi.is_inv(nd)) - { - std::cout << "is not" << "\n"; - } - if (vpi.is_buf(nd)) - { - std::cout << "is buf" << "\n"; - } - if (vpi.is_po(nd)) - { - std::cout << "is po" << "\n"; - } - }); + CHECK(vpi.size_real() == vpi.size()); + CHECK(vpi.size() == tec.size()); mockturtle::equivalence_checking_stats st; bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); CHECK(cec_m == 1); } -TEST_CASE("Rank View on virtual PIs", "[virtual-rank-view]") -{ - virtual_pi_network vpi{}; - - const auto a = vpi.create_pi(); - const auto b = vpi.create_pi(); - - const auto c = vpi.create_virtual_pi(a); - const auto d = vpi.create_virtual_pi(b); - - const auto f1 = vpi.create_and(a, b); - const auto f2 = vpi.create_and(b, c); - const auto f3 = vpi.create_or(a, d); - - vpi.create_po(f1); - vpi.create_po(f2); - vpi.create_po(f3); - - std::cout << "real tec num_gates: " << vpi.size() << std::endl; - std::cout << "virt tec num_gates: " << vpi.size_real() << std::endl; - - /*vpi.foreach_node( - [&](const auto& nd) - { - std::cout << "Nd:" << nd << "\n"; - vpi.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); - if (vpi.is_virtual_pi(nd)) - { - std::cout << "Is virtual PI \n"; - } - });*/ - - // vpi.remove_virtual_input_nodes(); - - mockturtle::rank_view vpi_r(vpi); - /* vpi_r.foreach_pi([&](const auto& nd) { - std::cout << "Nd:" << nd << "\n"; - auto rnk = vpi_r.rank_position(nd); - auto lvl = vpi_r.level(nd); - std::cout << "Level: " << lvl << "\n"; - std::cout << "Rank: " << rnk << "\n"; - });*/ - std::cout << "r pis: " <(tec, vpi), {}, &st); From 326d6a4f33076c86100ee05405bcfb1c0771e97f Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 16 Jul 2024 12:36:41 +0200 Subject: [PATCH 20/84] :art: cleaned and documented extended_rank_view files --- .../networks/views/extended_rank_view.hpp | 137 +++++++++++++++++- test/networks/views/extended_rank_view.cpp | 84 ++++++++++- test/networks/virtual_pi_network.cpp | 2 +- 3 files changed, 211 insertions(+), 12 deletions(-) diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index 663559a53..e0b4b0b8e 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -21,6 +21,12 @@ // this rank view can assign specific ranks to nodes in one level // to check validity of the rank view you can use check_rank_validity() +/** + * @class extended_rank_view. Extends the mockturtle::rank_view + * + * Provides a view with node ranks for given networks. It adds some functionalities to modify ranks. + * + */ template && mockturtle::has_at_rank_position_v && mockturtle::has_swap_v && mockturtle::has_width_v && @@ -28,6 +34,12 @@ template class extended_rank_view : public mockturtle::depth_view { @@ -35,6 +47,12 @@ class extended_rank_view : public mockturtle::depth_view extended_rank_view(Ntk const& ntk) : mockturtle::depth_view(ntk) {} }; +/** + * @class extended_rank_view (specialization) + * + * A derived class from depth_view. + * + */ template class extended_rank_view : public mockturtle::depth_view { @@ -44,6 +62,11 @@ class extended_rank_view : public mockturtle::depth_view using node = typename Ntk::node; using signal = typename Ntk::signal; + /** + * @class extended_rank_view (specialization) + * + * Can assign specific ranks. + */ explicit extended_rank_view() : mockturtle::depth_view(), rank_pos{*this}, ranks{}, max_rank_width{0} { static_assert(mockturtle::is_network_type_v, "Ntk is not a network type"); @@ -56,9 +79,15 @@ class extended_rank_view : public mockturtle::depth_view add_event = Ntk::events().register_add_event([this](auto const& n) { on_add(n); }); } - /*! \brief Standard constructor. + /** + * @class extended_rank_view * - * \param ntk Base network + * @brief A derived class from depth_view that represents a network with ranks assigned to nodes. + * + * This class provides functionality to assign and modify ranks for nodes in a network. It also provides methods to + * access and manipulate nodes based on their rank position. + * + * @tparam Ntk Network type */ explicit extended_rank_view(Ntk const& ntk) : mockturtle::depth_view{ntk}, @@ -105,7 +134,15 @@ class extended_rank_view : public mockturtle::depth_view add_event = Ntk::events().register_add_event([this](auto const& n) { on_add(n); }); } - /*! \brief Copy constructor. */ + /** + * @brief Copy constructor for extended_rank_view + * + * This constructor creates a new extended_rank_view object by copying the content of another object of the same + * type. + * + * @tparam Ntk Network type + * @param other The extended_rank_view object to be copied + */ extended_rank_view(extended_rank_view const& other) : mockturtle::depth_view(other), rank_pos{other.rank_pos}, @@ -115,6 +152,17 @@ class extended_rank_view : public mockturtle::depth_view add_event = Ntk::events().register_add_event([this](auto const& n) { on_add(n); }); } + /** + * @brief Assigns the content of another `extended_rank_view` object to this object. + * + * This assignment operator replaces the content of this object with the content of another `extended_rank_view` + * object. It first releases the add event of this network, then updates the base class with the storage and events + * of the other object. It then copies the rank position, ranks, and max rank width from the other object. Finally, + * it registers a new add event in the other network and returns a reference to this object. + * + * @param other The `extended_rank_view` object to be assigned to this object. + * @return Reference to this object. + */ extended_rank_view& operator=(extended_rank_view const& other) { /* delete the event of this network */ @@ -135,6 +183,11 @@ class extended_rank_view : public mockturtle::depth_view return *this; } + /** + * @brief Destructor for extended_rank_view. + * + * This destructor releases the add event associated with the extended_rank_view object. + */ ~extended_rank_view() { Ntk::events().release_add_event(add_event); @@ -152,7 +205,20 @@ class extended_rank_view : public mockturtle::depth_view return rank_pos[n]; } - // This function has the only purpose to enable an equivalence checking of this network + /** + * @brief Remove virtual input nodes from the network. + * + * This function removes all virtual input nodes from the network. It first calls the base class function + * `remove_virtual_input_nodes()` to remove the virtual input nodes. Then, it resets the `rank_pos` node map, clears + * each vector in the `ranks` vector, and resets the `max_rank_width` to 0. Finally, it initializes the ranks again + * by calling the `init_ranks()` function and prints a message indicating that the `remove()` function was called. + * + * This function is used to enable equivalence checking with the network. + * + * Note: This function should only be used for network types that are the same as `fiction::virtual_pi_network`. + * + * @tparam U The network type. + */ template typename std::enable_if::value>::type remove_virtual_input_nodes() { @@ -172,6 +238,16 @@ class extended_rank_view : public mockturtle::depth_view std::cout << "remove() called\n"; } + /** + * @brief Checks the validity of the ranks and rank positions in the extended_rank_view class. + * + * This function checks if the ranks and rank positions are valid in the extended_rank_view class. It iterates over + *each rank and checks if the level of each node matches the rank level . It also checks if the rank positions are + *in ascending order for each rank. If any inconsistency is found, the function returns false. Otherwise, it returns + *true, indicating that the ranks and rank positions are valid. + * + * @return True if the ranks and rank positions are valid, false otherwise. + */ bool check_validity() const noexcept { for (size_t i = 0; i < ranks.size(); ++i) @@ -380,6 +456,13 @@ class extended_rank_view : public mockturtle::depth_view std::shared_ptr::add_event_type> add_event; + /** + * @brief Inserts a node into the rank. + * + * This function inserts a node into the rank and updates the rank position, ranks, and max rank width accordingly. + * + * @param n The node to insert into the rank. + */ void insert_in_rank(node const& n) noexcept { auto& rank = ranks[this->level(n)]; @@ -388,6 +471,10 @@ class extended_rank_view : public mockturtle::depth_view max_rank_width = std::max(max_rank_width, static_cast(rank.size())); } + /** + * Adds a new node to the skip list. + * @param n The node to be added. + */ void on_add(node const& n) noexcept { if (this->level(n) >= ranks.size()) @@ -400,6 +487,14 @@ class extended_rank_view : public mockturtle::depth_view insert_in_rank(n); } + /** + * @brief Initializes the ranks for the given network. + * + * This function initializes the ranks for the given network. It traverses the nodes in the network using a + * depth-first search and inserts each non-constant node into the rank. + * + * This function is noexcept. + */ void init_ranks() noexcept { mockturtle::depth_view::foreach_node( @@ -412,14 +507,39 @@ class extended_rank_view : public mockturtle::depth_view }); } + /** + * @brief Inserts a node into the rank list at the specified rank level. + * @param n The node to insert. + * @param rank_level The rank level at which to insert the node. + * @note This function modifies the rank list by adding the node at the specified rank level. + * @note This function updates the rank position and the maximum rank width. + * @warning This function assumes that the node n is a valid node. + * @warning This function assumes that the rank list and rank positions have been initialized before calling this + * function. + * + * @see ranks, rank_pos, max_rank_width + */ void insert_in_rank(node const& n, size_t rank_level) noexcept { + if (rank_level >= ranks.size()) + { + throw std::out_of_range("Rank level is out of range"); + } auto& rank = ranks[rank_level]; rank_pos[n] = rank.size(); rank.push_back(n); max_rank_width = std::max(max_rank_width, static_cast(rank.size())); } + /** + * @brief Initializes the ranks with the given vector of nodes. + * + * This function takes in a 2D vector of nodes and initializes the ranks accordingly. + * Each node in the input ranks is inserted into its corresponding rank, unless it is a constant node. + * + * @param input_ranks The input vector of ranks. + * @return void + */ void init_ranks(std::vector> const& input_ranks) noexcept { for (size_t i = 0; i < input_ranks.size(); ++i) @@ -436,6 +556,15 @@ class extended_rank_view : public mockturtle::depth_view } }; +/** + * @brief Deduction guide for `extended_rank_view' + * + * This template helps to deduce the type argument `T` for the + * `extended_rank_view` class when constructed with an argument of type `T`. + * + * @tparam T Network type deduced from the construction context of + * `extended_rank_view`. + */ template extended_rank_view(T const&) -> extended_rank_view; diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index e20b2294b..383768641 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -3,6 +3,7 @@ // #include +#include #include #include @@ -11,10 +12,53 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include using namespace fiction; +TEMPLATE_TEST_CASE( "traits", "[extended_rank_view]", mockturtle::aig_network, mockturtle::mig_network, mockturtle::xag_network, mockturtle::xmg_network, mockturtle::klut_network, mockturtle::cover_network, mockturtle::buffered_aig_network, mockturtle::buffered_mig_network, mockturtle::crossed_klut_network, mockturtle::buffered_crossed_klut_network ) +{ + CHECK( mockturtle::is_network_type_v ); + CHECK( !mockturtle::has_rank_position_v ); + CHECK( !mockturtle::has_at_rank_position_v ); + CHECK( !mockturtle::has_width_v ); + CHECK( !mockturtle::has_sort_rank_v ); + CHECK( !mockturtle::has_foreach_node_in_rank_v ); + CHECK( !mockturtle::has_foreach_gate_in_rank_v ); + CHECK( !mockturtle::is_topologically_sorted_v ); + + using rank_ntk = extended_rank_view; + + CHECK( mockturtle::is_network_type_v ); + CHECK( mockturtle::has_rank_position_v ); + CHECK( mockturtle::has_at_rank_position_v ); + CHECK( mockturtle::has_width_v ); + CHECK( mockturtle::has_sort_rank_v ); + CHECK( mockturtle::has_foreach_node_in_rank_v ); + CHECK( mockturtle::has_foreach_gate_in_rank_v ); + CHECK( mockturtle::is_topologically_sorted_v ); + + using rank_rank_ntk = extended_rank_view; + + CHECK( mockturtle::is_network_type_v ); + CHECK( mockturtle::has_rank_position_v ); + CHECK( mockturtle::has_at_rank_position_v ); + CHECK( mockturtle::has_width_v ); + CHECK( mockturtle::has_sort_rank_v ); + CHECK( mockturtle::has_foreach_node_in_rank_v ); + CHECK( mockturtle::has_foreach_gate_in_rank_v ); + CHECK( mockturtle::is_topologically_sorted_v ); +} + TEST_CASE("Check modify ranks", "[extended-rank-view]") { technology_network tec{}; @@ -72,7 +116,39 @@ TEST_CASE("Check modify ranks", "[extended-rank-view]") CHECK(1 == 1); } -TEST_CASE("Check equivalence checking", "[extended-rank-view]") +TEMPLATE_TEST_CASE( "Check equivalence checking", "[extended_rank_view]", mockturtle::aig_network, mockturtle::mig_network, mockturtle::xag_network, mockturtle::xmg_network, mockturtle::klut_network, mockturtle::buffered_aig_network, mockturtle::buffered_mig_network, mockturtle::crossed_klut_network, mockturtle::buffered_crossed_klut_network ) +{ + TestType ntk{}; + + const auto a = ntk.create_pi(); + const auto b = ntk.create_pi(); + + const auto a_t = ntk.create_pi(); + const auto b_t = ntk.create_pi(); + + const auto f1 = ntk.create_and(a, b); + + const auto f1_t = ntk.create_and(a_t, b); + const auto f2_t = ntk.create_and(b_t, a_t); + const auto f3_t = ntk.create_or(a_t, b_t); + + ntk.create_po(f1); + + ntk.create_po(f1_t); + ntk.create_po(f2_t); + ntk.create_po(f3_t); + + network_balancing_params ps; + ps.unify_outputs = true; + + auto ntk_r = extended_rank_view(ntk); + + mockturtle::equivalence_checking_stats st; + bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(ntk, ntk_r), {}, &st); + CHECK(cec_m == 1); +} + +TEST_CASE("Check equivalence checking for virtual PIs", "[extended-rank-view]") { technology_network tec{}; virtual_pi_network vpi{}; @@ -107,15 +183,9 @@ TEST_CASE("Check equivalence checking", "[extended-rank-view]") auto vpi_r = extended_rank_view(vpi); - std::cout << "Num Cis" << vpi_r.num_cis() << std::endl; - vpi_r.remove_virtual_input_nodes(); - std::cout << "Num Cis" << vpi_r.num_cis() << std::endl; - mockturtle::equivalence_checking_stats st; bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); CHECK(cec_m == 1); - - CHECK(1 == 1); } diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index 822001dcc..e4e54fadb 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -128,7 +128,7 @@ TEST_CASE("Remove PIs and check equivalence second", "[virtual-pi-view]") vpi.remove_virtual_input_nodes(); CHECK(vpi.size_real() == vpi.size()); - CHECK(vpi.size() - 2 == tec.size()); // the -2 is bdue to the buffers + CHECK(vpi.size() - 2 == tec.size()); // the -2 is due to the buffers mockturtle::equivalence_checking_stats st; bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); From d2b1a575836c6ebc21c0b852a02600a20906a1e9 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 16 Jul 2024 15:40:04 +0200 Subject: [PATCH 21/84] :art: small adjustments to enable extended_rank_view --- .../node_duplication_planarization.hpp | 12 +++++++----- .../fiction/networks/views/extended_rank_view.hpp | 1 - .../node_duplication_planarization.cpp | 11 +++++++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 334ab9293..4a47377a0 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -102,7 +102,7 @@ initialize_copy_network_v(NtkSrc const& src) } template -extended_rank_view create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector>>& ntk_lvls) +virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector>>& ntk_lvls) { std::vector>> ntk_lvls_new; std::unordered_map, bool> node_status; @@ -262,14 +262,14 @@ extended_rank_view create_virt_pi_ntk_from_lvls(Ntk& ntk, st ntk_dest_v.create_po(tgt_po); }); - auto ntk_dest_r = extended_rank_view(ntk_dest_v); + //auto ntk_dest_r = mockturtle::rank_view(ntk_dest_v); /*for (size_t i = 0; i < ntk_lvls_new.size(); i++) { ntk_dest_r.modify_rank(i, ntk_lvls_new[i]); }*/ - return ntk_dest_r; + return ntk_dest_v; } template @@ -459,7 +459,7 @@ class node_duplication_planarization_impl } // mockturtle::rank_view run() - extended_rank_view run() + virtual_pi_network run() { const bool border_pis = true; // ToDo: Determine the PO order @@ -571,7 +571,9 @@ extended_rank_view node_duplication_planarization(const NtkS detail::node_duplication_planarization_impl p{ntk_src, ps}; - auto result = p.run(); + auto result_ntk = p.run(); + + auto result = extended_rank_view(result_ntk); // ToDo: Check for planarity diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index e0b4b0b8e..18172fd22 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -235,7 +235,6 @@ class extended_rank_view : public mockturtle::depth_view // Reset max_rank_width max_rank_width = 0; this->init_ranks(); - std::cout << "remove() called\n"; } /** diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index a01739822..427001d1c 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -11,6 +11,9 @@ #include #include +#include +#include + using namespace fiction; TEST_CASE("First test", "[node-duplication-planarization]") @@ -148,7 +151,8 @@ TEST_CASE("2-ary Balancing Test", "[node-duplication-planarization]") planarized_maj.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); }); - planarized_maj.remove_virtual_input_nodes(); + // The test takes long due to the rank_pos.reset() function + planarized_maj.remove_virtual_input_nodes(); planarized_maj.foreach_node([&](const auto& nd) { std::cout << "Nd:" << nd << "\n"; @@ -220,11 +224,10 @@ TEST_CASE("3-ary Balancing Test", "[node-duplication-planarization]") auto planarized_maj = node_duplication_planarization(tec_b); - planarized_maj.remove_virtual_input_nodes(); + // The test takes long due to the rank_pos.reset() function + planarized_maj.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); CHECK(cec_m == 1); - - CHECK(1 == 1); } From db6a668a73cc4256138eef5588e50b997885dad3 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 16 Jul 2024 17:46:01 +0200 Subject: [PATCH 22/84] :art: rank computation added --- .../node_duplication_planarization.hpp | 28 +++++-------------- .../networks/views/extended_rank_view.hpp | 3 ++ 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 4a47377a0..648a4f774 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -102,9 +102,8 @@ initialize_copy_network_v(NtkSrc const& src) } template -virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector>>& ntk_lvls) +virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector>>& ntk_lvls, std::vector>>& ntk_lvls_new) { - std::vector>> ntk_lvls_new; std::unordered_map, bool> node_status; // node_status[node] ntk_lvls_new.resize(ntk_lvls.size()); @@ -175,7 +174,6 @@ virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector 0;) { @@ -262,13 +260,6 @@ virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector(ntk_dest_v); - - /*for (size_t i = 0; i < ntk_lvls_new.size(); i++) - { - ntk_dest_r.modify_rank(i, ntk_lvls_new[i]); - }*/ - return ntk_dest_v; } @@ -383,13 +374,6 @@ class node_duplication_planarization_impl } } - // Debug output - /*for (const auto& node_pair : combinations) - { - std::cout << "Fanin Pair: (" << node_pair.pair.first << ", " << node_pair.pair.second - << "), Delay: " << node_pair.delay << std::endl; - }*/ - cur_lvl_pairs.push_back(combinations); } @@ -459,7 +443,7 @@ class node_duplication_planarization_impl } // mockturtle::rank_view run() - virtual_pi_network run() + virtual_pi_network run(std::vector>>& ntk_lvls_new) { const bool border_pis = true; // ToDo: Determine the PO order @@ -513,7 +497,7 @@ class node_duplication_planarization_impl } // create virtual pi network - auto new_ntk = create_virt_pi_ntk_from_lvls(ntk, ntk_lvls); + auto new_ntk = create_virt_pi_ntk_from_lvls(ntk, ntk_lvls, ntk_lvls_new); return new_ntk; // mockturtle::rank_view(ntk); } @@ -571,9 +555,11 @@ extended_rank_view node_duplication_planarization(const NtkS detail::node_duplication_planarization_impl p{ntk_src, ps}; - auto result_ntk = p.run(); + std::vector>> ntk_lvls_new; + + auto result_ntk = p.run(ntk_lvls_new); - auto result = extended_rank_view(result_ntk); + auto result = extended_rank_view(result_ntk, ntk_lvls_new); // ToDo: Check for planarity diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index 18172fd22..4e63dc6c2 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -567,4 +567,7 @@ class extended_rank_view : public mockturtle::depth_view template extended_rank_view(T const&) -> extended_rank_view; +template +extended_rank_view(T const&, std::vector>) -> extended_rank_view; + #endif // FICTION_VIRTUAL_RANK_VIEW_HPP From e94b47907349598104a308239c65a9bd32d9e304 Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 17 Jul 2024 12:30:32 +0200 Subject: [PATCH 23/84] :heavy_plus_sign: planarity check added. The check requires a balanced network and also a rank_view. --- .../algorithms/properties/check_planarity.hpp | 80 +++++++++++++ .../algorithms/properties/check_planarity.cpp | 105 ++++++++++++++++++ 2 files changed, 185 insertions(+) create mode 100644 include/fiction/algorithms/properties/check_planarity.hpp create mode 100644 test/algorithms/properties/check_planarity.cpp diff --git a/include/fiction/algorithms/properties/check_planarity.hpp b/include/fiction/algorithms/properties/check_planarity.hpp new file mode 100644 index 000000000..d7faa6bd6 --- /dev/null +++ b/include/fiction/algorithms/properties/check_planarity.hpp @@ -0,0 +1,80 @@ +// +// Created by benjamin on 7/17/24. +// + +#ifndef FICTION_CHECK_PLANARITY_HPP +#define FICTION_CHECK_PLANARITY_HPP + +#include "fiction/algorithms/network_transformation/network_balancing.hpp" + +#include + +namespace fiction +{ + +template +class check_planarity_impl +{ + public: + check_planarity_impl(const Ntk& ntk) : ntk(ntk) {} + + bool run() + { + bool return_false = false; + for (uint32_t r = 1; r < ntk.depth() + 1; r++) + { + uint32_t bound = 0; + ntk.foreach_node_in_rank(r, + [this, &bound, &return_false](const auto& n) + { + uint32_t new_bound = bound; + ntk.foreach_fanin(n, + [this, &bound, &new_bound, &return_false](const auto& fi) + { + const auto fi_n = ntk.get_node(fi); + if (ntk.rank_position(fi_n) < bound) + { + return_false = true; + } + new_bound = std::max(new_bound, ntk.rank_position(fi_n)); + }); + if (return_false) + return; + bound = new_bound; + }); + if (return_false) + return false; + } + return true; + } + + private: + Ntk ntk; +}; + +template +bool check_planarity(Ntk& ntk) +{ + static_assert(mockturtle::has_rank_position_v, "Ntk does not have rank position trait"); + static_assert(mockturtle::has_at_rank_position_v, "Ntk does not have at rank position trait"); + static_assert(mockturtle::has_swap_v, "Ntk does not have swap trait"); + static_assert(mockturtle::has_width_v, "Ntk does not have width trait"); + static_assert(mockturtle::has_foreach_node_in_rank_v, "Ntk does not have foreach node in rank trait"); + static_assert(mockturtle::has_foreach_gate_in_rank_v, "Ntk does not have foreach gate in rank trait"); + + if (!is_balanced(ntk)) + { + // ToDo: Instead drag this to the implementation and insert buffers so that they divide multi-level edges + throw std::runtime_error("Network must be balanced"); + } + + check_planarity_impl p{ntk}; + + auto result = p.run(); + + return result; +} + +} // namespace fiction + +#endif // FICTION_CHECK_PLANARITY_HPP diff --git a/test/algorithms/properties/check_planarity.cpp b/test/algorithms/properties/check_planarity.cpp new file mode 100644 index 000000000..bb380f376 --- /dev/null +++ b/test/algorithms/properties/check_planarity.cpp @@ -0,0 +1,105 @@ +// +// Created by benjamin on 7/17/24. +// + +#include +#include +#include +#include + +#include + +using namespace fiction; + +TEST_CASE("Check planarity aig", "[check-planarity]") +{ + mockturtle::aig_network aig{}; + + CHECK(mockturtle::has_clear_visited_v); + CHECK(mockturtle::has_visited_v); + CHECK(mockturtle::has_set_visited_v); + + const auto x1 = aig.create_pi(); + const auto x2 = aig.create_pi(); + const auto x3 = aig.create_pi(); + + const auto f1 = aig.create_and(x1, x2); + const auto f2 = aig.create_and(x2, x3); + + aig.create_po(f1); + aig.create_po(f2); + + extended_rank_view tec_r(aig); + + std::vector nodes_rank0{1, 2, 3}; + std::vector nodes_rank1{4, 5}; + + tec_r.modify_rank(0, nodes_rank0); + tec_r.modify_rank(0, nodes_rank0); + + bool planar = check_planarity(tec_r); + + CHECK(planar == 1); +} + +TEST_CASE("Check planarity technology network", "[check-planarity]") +{ + technology_network tec{}; + + CHECK(mockturtle::has_clear_visited_v); + CHECK(mockturtle::has_visited_v); + CHECK(mockturtle::has_set_visited_v); + + const auto x1 = tec.create_pi(); + const auto x2 = tec.create_pi(); + const auto x3 = tec.create_pi(); + + const auto f1 = tec.create_and(x1, x2); + const auto f2 = tec.create_and(x2, x3); + + tec.create_po(f1); + tec.create_po(f2); + + extended_rank_view tec_r(tec); + + std::vector nodes_rank0{2, 3, 4}; + std::vector nodes_rank1{5, 6}; + + tec_r.modify_rank(0, nodes_rank0); + tec_r.modify_rank(0, nodes_rank0); + + bool planar = check_planarity(tec_r); + + CHECK(planar == 1); +} + +TEST_CASE("Check non-planarity technology network", "[check-planarity]") +{ + technology_network tec{}; + + CHECK(mockturtle::has_clear_visited_v); + CHECK(mockturtle::has_visited_v); + CHECK(mockturtle::has_set_visited_v); + + const auto x1 = tec.create_pi(); + const auto x2 = tec.create_pi(); + const auto x3 = tec.create_pi(); + + const auto f1 = tec.create_and(x1, x3); + const auto f2 = tec.create_and(x2, x3); + + tec.create_po(f1); + tec.create_po(f2); + + extended_rank_view tec_r(tec); + + std::vector nodes_rank0{2, 3, 4}; + std::vector nodes_rank1{5, 6}; + + tec_r.modify_rank(0, nodes_rank0); + tec_r.modify_rank(0, nodes_rank0); + + bool planar = check_planarity(tec_r); + + CHECK(planar == 0); +} From 1b77a89f1743aec2999debe4d01ba6c80798171a Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 17 Jul 2024 16:25:37 +0200 Subject: [PATCH 24/84] :art: bugs with gather_fanin_signals removed. Documentation updated. --- .../node_duplication_planarization.hpp | 306 ++++++++++++------ .../node_duplication_planarization.cpp | 176 +++------- 2 files changed, 246 insertions(+), 236 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 648a4f774..294bd5d27 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -7,6 +7,7 @@ #include "fiction/algorithms/network_transformation/fanout_substitution.hpp" #include "fiction/algorithms/network_transformation/network_balancing.hpp" +#include "fiction/algorithms/properties/check_planarity.hpp" #include "fiction/networks/views/extended_rank_view.hpp" #include "fiction/networks/virtual_pi_network.hpp" #include "fiction/traits.hpp" @@ -19,6 +20,7 @@ #include #include #include +#include #include #include @@ -29,51 +31,39 @@ namespace fiction { -/*template -class RankViewNtk : public Ntk { - public: - using Ntk::Ntk; // Inherit constructors - - RankViewNtk(const Ntk& ntk): Ntk(mockturtle::rank_view(ntk)) {} // Convert from Ntk -};*/ - /** * Parameters for the fanout substitution algorithm. */ struct node_duplication_params { - /** - * Breadth-first vs. depth-first fanout-tree substitution strategies. - */ - enum substitution_strategy - { - /** - * Breadth-first substitution. Creates balanced fanout trees. - */ - BREADTH, - /** - * Depth-first substitution. Creates fanout trees with one deep branch. - */ - DEPTH - }; - - /** - * Substitution strategy of high-degree fanout networks (depth-first vs. breadth-first). - */ - substitution_strategy strategy = BREADTH; - /** - * Maximum output degree of each fan-out node. - */ - uint32_t degree = 2ul; - /** - * Maximum number of outputs any gate is allowed to have before substitution applies. - */ - uint32_t threshold = 1ul; + /* + * The output order determines the starting layer for this algorithm. If this option is turned off, the output order + * remains the same as in the provided network. If it is turned on, the outputs are ordered randomly. + * */ + bool random_output_order = false; }; namespace detail { +/** + * @brief A variant of the mockturtle::initialize_copy_network. It maps old nodes not only to a single node, but to + * multiple or duplicated nodes. + * + * @tparam NtkDest Type of the destination network + * @tparam NtkSrc Type of the source network + * @param src The source network + * + * @return A pair of the destination network and a node map from the source to the destination network. + * + * @pre NtkDest and NtkSrc must be network types (satisfy is_network_type_v). + * @pre NtkDest and NtkSrc must implement the methods get_constant, get_node, create_pi and foreach_pi (satisfy + * has_get_constant_v, has_get_node_v, has_create_pi_v and has_foreach_pi_v). + * + * @post A map (old2new) is created where old nodes from source network are mapped to new nodes in destination network. + * @post A destination network is created with the same structure as the source network. + * + */ template std::pair>, NtkSrc>> initialize_copy_network_v(NtkSrc const& src) @@ -90,8 +80,6 @@ initialize_copy_network_v(NtkSrc const& src) mockturtle::node_map>, NtkSrc> old2new(src); NtkDest dest; - // Please modify next lines as per your requirements - old2new[src.get_constant(false)].push_back(dest.get_constant(false)); if (src.get_node(src.get_constant(true)) != src.get_node(src.get_constant(false))) { @@ -102,10 +90,10 @@ initialize_copy_network_v(NtkSrc const& src) } template -virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector>>& ntk_lvls, std::vector>>& ntk_lvls_new) +virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector>>& ntk_lvls, + std::vector>>& ntk_lvls_new) { std::unordered_map, bool> node_status; - // node_status[node] ntk_lvls_new.resize(ntk_lvls.size()); auto init_v = initialize_copy_network_v(ntk); @@ -147,14 +135,18 @@ virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector(edge_it_int + i); @@ -165,10 +157,6 @@ virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector struct node_pair { + /** + * Defines the beginning and end of the fanin-edged node + */ std::pair, mockturtle::node> pair; - std::vector> middle_nodes; - std::shared_ptr> fanin_pair; - uint64_t delay; - // constructor + /** + * Contains the nodes between the fanin-edges node; cannot be connected to any other node + */ + std::vector> middle_nodes; + + /** + * Shared pointer to another instance of node_pair detailing fanin-edge alignment + */ + std::shared_ptr> fanin_pair; + + /** + * Specifies the delay value for the node + */ + uint64_t delay; + + /** + * @brief node_pair constructor + * + * @param node1 The first node of the fanin-edged node + * @param node2 The second node of the fanin-edged node + * @param delayValue The delay value for the node + */ node_pair(mockturtle::node node1, mockturtle::node node2, uint64_t delayValue) : pair(node1, node2), delay(delayValue) {} }; +/** + * @brief Calculates pairs of nodes from a given vector of nodes. + * + * This function takes a vector of nodes and returns a vector of node pairs. Each node pair consists of two nodes from + * the input vector and an optional vector of middle nodes. The delay of each node pair is initialized to infinity. + * + * @tparam Ntk The network type. + * @param nodes The vector of nodes. + * @return The vector of node pairs. + */ template std::vector> calculate_pairs(const std::vector>& nodes) { @@ -325,26 +359,44 @@ template class node_duplication_planarization_impl { public: - node_duplication_planarization_impl(const Ntk& src, const node_duplication_params p) : ntk(src) {} + node_duplication_planarization_impl(const Ntk& src, const node_duplication_params p) : ntk(src), ps{p} {} + /** + * @brief Computes the delay in a given slice (each possible order of node_pairs) of an H-graph + * + * @param nd Node in the H-graph + * @param border_pis A boolean indicating whether the input PIs (Primary Inputs) should be propagated to the next + * level + * + * This function iterates over the fanins of the given node and computes the delay for all possible orders + * of these nodes that form a node_pair. The delay computation depends on the node's connections and position + * within the graph. If there is a connection between two node_pairs, the delay is incremented by 1. If not, + * the delay is incremented by 2. Default delay for the first node is 1. If a node_pair doesn't have a connection + * and its delay (when increased by two) is less than the existing delay, then this node_pair's delay is updated. + * + * The processed node_pairs are pushed back to the 'lvl_pairs' data member for subsequent delay calculations. + * + * @throws std::runtime_error if no combinations (possible node_pairs) are found, which might suggest a dangling + * node + */ void compute_slice_delays(mockturtle::node nd, const bool border_pis) { // Pis need to be propagated into the next level, since they have to be connected without crossings if (ntk.is_pi(nd) && border_pis) { - cur_fis.push_back(nd); + fis.push_back(nd); } - ntk.foreach_fanin(nd, [this](auto fi) { cur_fis.push_back(fi); }); + ntk.foreach_fanin(nd, [this](auto fi) { fis.push_back(fi); }); // Compute the combinations in one slice - auto combinations = calculate_pairs(cur_fis); + auto combinations = calculate_pairs(fis); if (combinations.empty()) { throw std::runtime_error("Combinations are empty. There might be a dangling node"); } std::vector> combinations_last; - if (!cur_lvl_pairs.empty()) + if (!lvl_pairs.empty()) { - combinations_last = cur_lvl_pairs.back(); + combinations_last = lvl_pairs.back(); for (auto& node_pair_cur : combinations) { for (auto& node_pair_last : combinations_last) @@ -374,9 +426,19 @@ class node_duplication_planarization_impl } } - cur_lvl_pairs.push_back(combinations); + lvl_pairs.push_back(combinations); } + /** + * @brief Inserts a node into a vector if it is unique + * + * This function inserts a node into a vector only if the vector is empty or the node is not equal to the first + * element of the vector. If the vector is not empty and the node is equal to the first element, it does nothing. + * + * @tparam Ntk The network type + * @param node The node to be inserted + * @param vec The vector to insert the node into + */ void insert_if_unique(mockturtle::node node, std::vector>& vec) { if (vec.empty() || vec.front() != node) @@ -385,9 +447,18 @@ class node_duplication_planarization_impl } } + /** + * @brief Computes the order of nodes in the next level based on delay + * + * @param next_level The vector to store the nodes in the next level + * + * This function computes the order of nodes in the next level based on their delay in the H-graph of the level. It + * selects the path with the least delay from the current level pairs and follows it via fanin relations. The nodes + * are inserted into the next level vector in the order they are encountered. + */ void compute_node_order_next_level(std::vector>& next_level) { - const auto& combinations = cur_lvl_pairs.back(); + const auto& combinations = lvl_pairs.back(); // select the path with the least delay and follow it via fanin relations auto minimum_it = std::min_element(combinations.begin(), combinations.end(), @@ -395,7 +466,6 @@ class node_duplication_planarization_impl if (minimum_it != combinations.end()) { const auto& min_combination = *minimum_it; - // std::cout << "Minimum delay: " << min_combination.delay << std::endl; // Insert the terminal node insert_if_unique(min_combination.pair.second, next_level); @@ -430,6 +500,15 @@ class node_duplication_planarization_impl } } + /** + * @brief Checks if the given vector of nodes contains any non-primary inputs. + * + * This function iterates through each node in the vector and checks if it is a primary input. + * If a non-primary input is found, the `f_final_level` parameter is set to false and the loop is exited. + * + * @param v_next_level The vector of nodes to be checked + * @param f_final_level A reference to a boolean indicating if the vector contains only primary inputs + */ void check_final_level(std::vector>& v_next_level, bool& f_final_level) { for (const auto& nd : v_next_level) @@ -442,27 +521,37 @@ class node_duplication_planarization_impl } } - // mockturtle::rank_view run() virtual_pi_network run(std::vector>>& ntk_lvls_new) { const bool border_pis = true; - // ToDo: Determine the PO order - /*static std::mt19937 generator(std::random_device{}()); - std::uniform_int_distribution distribution(0, ntk.rank_width(r) - 1);*/ - std::vector> v_level; // save the nodes of the next level + + std::vector pos; + ntk.foreach_po([&pos](auto po) { pos.push_back(po); }); + // Randomize the PO order + if (ps.random_output_order) + { + // Generate a random engine + std::random_device rd; + std::mt19937 g(rd()); + // Shuffle the pos vector + std::shuffle(pos.begin(), pos.end(), g); + } + + // save the nodes of the next level + std::vector> v_level; // Process the first level - ntk.foreach_po( - [this, &v_level](auto po) - { - // Recalculate the levels to start from the pos - cur_fis.clear(); - compute_slice_delays(po, border_pis); - v_level.push_back(po); - }); + for (const auto& po : pos) + { + // Recalculate the levels to start from the pos + fis.clear(); + compute_slice_delays(po, border_pis); + v_level.push_back(po); + } + ntk_lvls.push_back(v_level); v_level.clear(); - // ToDo: try to push PIs to the beginning or end of he vector, since they have to be propagated with buffers + // Try to push PIs to the beginning or end of the vector, since they have to be propagated with buffers // until the last levels this should only happen if border_pis == true compute_node_order_next_level(v_level); @@ -474,11 +563,11 @@ class node_duplication_planarization_impl { // Push the level to the network ntk_lvls.push_back(v_level); - cur_lvl_pairs.clear(); + lvl_pairs.clear(); // Store the nodes of the next level for (const auto& cur_node : v_level) { - cur_fis.clear(); + fis.clear(); // There is one slice in the H-Graph for each node in the level compute_slice_delays(cur_node, border_pis); } @@ -503,24 +592,52 @@ class node_duplication_planarization_impl } private: - Ntk ntk; - std::vector>> cur_lvl_pairs; - std::vector> cur_fis; + /* + * The input network. + */ + Ntk ntk; + /* + * The currently node_pairs used in the current level. + */ + std::vector>> lvl_pairs; + /* + * The fanin nodes. + */ + std::vector> fis; + /* + * The network stored as levels. + */ std::vector>> ntk_lvls; + /* + * The stats of the node_duplication class. + */ + node_duplication_params ps; }; } // namespace detail /** - * ToDo: Description - * This implementation utilizes an H-Graph to capture all edge relations between two layers of a graph. - * The Node Duplication Crossing Minimization (NDCE) problem is addressed by finding the shortest x-y path on the - * H-Graph. Note that this minimization is valid only under a specific order at the primary output (PO) level. The - * algorithm traverses from primary outputs (POs) to primary inputs (PIs), constructing the H-Graph and computing the - * shortest x-y paths at each level of the graph. + * @brief Implements a planarization mechanism for Mockturtle networks using a H-Graph strategy and node duplication. + * + * @tparam NtkDest Destination network type + * @tparam NtkSrc Source network type + * @param ntk_src Source network to be utilized for the planarization + * @param ps Node duplication parameters used in the computation + * + * The planarization achieved by this function solves the Node Duplication Crossing Minimization (NDCE) problem by + * finding the shortest x-y path in the H-graph for every level in the network. The function constructs an H-graph that + * captures edge relations between two levels within the graph and computes the shortest x-y paths on the H-graph. The + * graph is traversed from Primary Outputs (POs) towards Primary Inputs (PIs). + * + * @return A view of the planarized virtual_pi_network created in the format of extended_rank_view + * + * @throws std::runtime_error if input network not balanced, if no node combinations are found or if + * the created network is non-planar + * */ template -extended_rank_view node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) +extended_rank_view node_duplication_planarization(const NtkSrc& ntk_src, + node_duplication_params ps = {}) { static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); @@ -536,32 +653,25 @@ extended_rank_view node_duplication_planarization(const NtkS static_assert(mockturtle::has_foreach_fanin_v, "NtkDest does not implement the foreach_fanin function"); static_assert(mockturtle::has_foreach_po_v, "NtkDest does not implement the foreach_po function"); - // check for input degree - /*if (has_high_degree_fanin_nodes(ntk_src, 2)) - { - throw high_degree_fanin_exception(); - }*/ - if (!is_balanced(ntk_src)) { throw std::runtime_error("Combinations are empty. There might be a dangling node"); } - // auto t_ntk = convert_network(ntk_src); - - /*if (!is_fanout_substituted(t_ntk)) { - t_ntk = fanout_substitution(t_ntk); // Apply fanout substitution if needed - }*/ - detail::node_duplication_planarization_impl p{ntk_src, ps}; std::vector>> ntk_lvls_new; auto result_ntk = p.run(ntk_lvls_new); + std::reverse(ntk_lvls_new.begin(), ntk_lvls_new.end()); + auto result = extended_rank_view(result_ntk, ntk_lvls_new); - // ToDo: Check for planarity + if (!check_planarity(result)) + { + throw std::runtime_error("Error: Network should be planar"); + } return result; } diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index 427001d1c..364ee7b9f 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -16,35 +16,8 @@ using namespace fiction; -TEST_CASE("First test", "[node-duplication-planarization]") -{ - technology_network tec{}; - - CHECK(mockturtle::has_clear_visited_v); - CHECK(mockturtle::has_visited_v); - CHECK(mockturtle::has_set_visited_v); - - const auto x1 = tec.create_pi(); - const auto x2 = tec.create_pi(); - const auto x3 = tec.create_pi(); - - const auto f1 = tec.create_and(x1, x2); - const auto f2 = tec.create_and(x1, x2); - const auto f3 = tec.create_and(x2, x3); - const auto f4 = tec.create_not(x3); - tec.create_po(f1); - tec.create_po(f2); - tec.create_po(f3); - tec.create_po(f4); - - // auto maj = blueprints::maj1_network(); - - const auto planarized_maj = node_duplication_planarization(tec); - - CHECK(1 == 1); -} - -TEST_CASE("Multi Level test", "[node-duplication-planarization]") +// Implement reverse balancing function. Also it should propagate PIs all to the last level +TEST_CASE("2-ary Test", "[node-duplication-planarization]") { technology_network tec{}; @@ -59,20 +32,29 @@ TEST_CASE("Multi Level test", "[node-duplication-planarization]") const auto x5 = tec.create_pi(); const auto f1 = tec.create_not(x2); const auto f2 = tec.create_nary_and({x1, x2, x3, x4}); - const auto f3 = tec.create_nary_and({x3, x4, x5}); + const auto f3 = tec.create_nary_or({x3, x4, x5}); tec.create_po(f1); tec.create_po(f2); tec.create_po(f3); - // auto maj = blueprints::maj1_network(); + network_balancing_params ps; + ps.unify_outputs = true; - const auto planarized_maj = node_duplication_planarization(tec); + auto tec_b = network_balancing(tec, ps); + + const auto vpi_r = mockturtle::rank_view(tec_b); - CHECK(1 == 1); + auto planarized_maj = node_duplication_planarization(tec_b); + + // The test takes long due to the rank_pos.reset() function + planarized_maj.remove_virtual_input_nodes(); + + mockturtle::equivalence_checking_stats st; + bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); + CHECK(cec_m == 1); } -// Implement reverse balancing function. Also it should propagate PIs all to the last level -TEST_CASE("2-ary Balancing Test", "[node-duplication-planarization]") +TEST_CASE("3-ary Test", "[node-duplication-planarization]") { technology_network tec{}; @@ -88,146 +70,64 @@ TEST_CASE("2-ary Balancing Test", "[node-duplication-planarization]") const auto f1 = tec.create_not(x2); const auto f2 = tec.create_nary_and({x1, x2, x3, x4}); const auto f3 = tec.create_nary_or({x3, x4, x5}); + const auto f4 = tec.create_maj(x1, x2, f3); tec.create_po(f1); tec.create_po(f2); tec.create_po(f3); - - auto blc = is_balanced(tec); - std::cout << "Balanced: " << blc << "\n"; + tec.create_po(f4); network_balancing_params ps; ps.unify_outputs = true; auto tec_b = network_balancing(tec, ps); - blc = is_balanced(tec_b); - std::cout << "Balanced: " << blc << "\n"; const auto vpi_r = mockturtle::rank_view(tec_b); - /*vpi_r.foreach_node([&](const auto& nd) { - std::cout << "Nd:" << nd << "\n"; - if (vpi_r.is_inv(nd)) - { - std::cout << "is not" << "\n"; - } - if (vpi_r.is_buf(nd)) - { - std::cout << "is buf" << "\n"; - } - vpi_r.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); - auto rnk = vpi_r.rank_position(nd); - auto lvl = vpi_r.level(nd); - std::cout << "Level: " << lvl << "\n"; - std::cout << "Rank: " << rnk << "\n"; - });*/ auto planarized_maj = node_duplication_planarization(tec_b); - planarized_maj.foreach_node([&](const auto& nd) { - std::cout << "Nd:" << nd << "\n"; - if (planarized_maj.is_pi_real(nd)) - { - std::cout << "is pi real" << "\n"; - } - if (planarized_maj.is_pi_virtual(nd)) - { - std::cout << "is pi virtual" << "\n"; - } - if (planarized_maj.is_inv(nd)) - { - std::cout << "is not" << "\n"; - } - if (planarized_maj.is_buf(nd)) - { - std::cout << "is buf" << "\n"; - } - if (planarized_maj.is_and(nd)) - { - std::cout << "is and" << "\n"; - } - if (planarized_maj.is_po(nd)) - { - std::cout << "is po" << "\n"; - } - planarized_maj.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); - }); - // The test takes long due to the rank_pos.reset() function planarized_maj.remove_virtual_input_nodes(); - planarized_maj.foreach_node([&](const auto& nd) { - std::cout << "Nd:" << nd << "\n"; - if (planarized_maj.is_pi_real(nd)) - { - std::cout << "is pi real" << "\n"; - } - if (planarized_maj.is_pi_virtual(nd)) - { - std::cout << "is pi virtual" << "\n"; - } - if (planarized_maj.is_inv(nd)) - { - std::cout << "is not" << "\n"; - } - if (planarized_maj.is_buf(nd)) - { - std::cout << "is buf" << "\n"; - } - if (planarized_maj.is_and(nd)) - { - std::cout << "is and" << "\n"; - } - if (planarized_maj.is_po(nd)) - { - std::cout << "is po" << "\n"; - } - planarized_maj.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; }); - }); - mockturtle::equivalence_checking_stats st; bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); CHECK(cec_m == 1); - - CHECK(1 == 1); } -TEST_CASE("3-ary Balancing Test", "[node-duplication-planarization]") +TEST_CASE("Aig Test", "[node-duplication-planarization]") { - technology_network tec{}; + mockturtle::aig_network aig{}; CHECK(mockturtle::has_clear_visited_v); CHECK(mockturtle::has_visited_v); CHECK(mockturtle::has_set_visited_v); - const auto x1 = tec.create_pi(); - const auto x2 = tec.create_pi(); - const auto x3 = tec.create_pi(); - const auto x4 = tec.create_pi(); - const auto x5 = tec.create_pi(); - const auto f1 = tec.create_not(x2); - const auto f2 = tec.create_nary_and({x1, x2, x3, x4}); - const auto f3 = tec.create_nary_or({x3, x4, x5}); - const auto f4 = tec.create_maj(x1, x2, f3); - tec.create_po(f1); - tec.create_po(f2); - tec.create_po(f3); - tec.create_po(f4); - - auto blc = is_balanced(tec); + const auto x1 = aig.create_pi(); + const auto x2 = aig.create_pi(); + const auto x3 = aig.create_pi(); + const auto x4 = aig.create_pi(); + const auto x5 = aig.create_pi(); + const auto f1 = aig.create_not(x2); + const auto f2 = aig.create_nary_and({x1, x2, x3, x4}); + const auto f3 = aig.create_nary_or({x3, x4, x5}); + const auto f4 = aig.create_maj(x1, x2, f3); + aig.create_po(f1); + aig.create_po(f2); + aig.create_po(f3); + aig.create_po(f4); network_balancing_params ps; ps.unify_outputs = true; - auto tec_b = network_balancing(tec, ps); - blc = is_balanced(tec_b); + auto aig_b = network_balancing(aig, ps); - const auto vpi_r = mockturtle::rank_view(tec_b); + const auto vpi_r = mockturtle::rank_view(aig_b); - auto planarized_maj = node_duplication_planarization(tec_b); + auto planarized_maj = node_duplication_planarization(aig_b); // The test takes long due to the rank_pos.reset() function planarized_maj.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; - bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); + bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(aig, planarized_maj), {}, &st); CHECK(cec_m == 1); } From 0e2f63d83ab40faa2737be25810bf175181fc074 Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 17 Jul 2024 16:50:25 +0200 Subject: [PATCH 25/84] :art: create_virtualPi_network from levels moved to virtual_pi_network.hpp as constructor. --- .../node_duplication_planarization.hpp | 207 +------------- .../fiction/networks/virtual_pi_network.hpp | 254 ++++++++++++++++-- 2 files changed, 236 insertions(+), 225 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 294bd5d27..1e61ec49e 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -46,211 +46,6 @@ struct node_duplication_params namespace detail { -/** - * @brief A variant of the mockturtle::initialize_copy_network. It maps old nodes not only to a single node, but to - * multiple or duplicated nodes. - * - * @tparam NtkDest Type of the destination network - * @tparam NtkSrc Type of the source network - * @param src The source network - * - * @return A pair of the destination network and a node map from the source to the destination network. - * - * @pre NtkDest and NtkSrc must be network types (satisfy is_network_type_v). - * @pre NtkDest and NtkSrc must implement the methods get_constant, get_node, create_pi and foreach_pi (satisfy - * has_get_constant_v, has_get_node_v, has_create_pi_v and has_foreach_pi_v). - * - * @post A map (old2new) is created where old nodes from source network are mapped to new nodes in destination network. - * @post A destination network is created with the same structure as the source network. - * - */ -template -std::pair>, NtkSrc>> -initialize_copy_network_v(NtkSrc const& src) -{ - static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); - static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); - - static_assert(mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method"); - static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method"); - static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method"); - static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method"); - static_assert(mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi method"); - - mockturtle::node_map>, NtkSrc> old2new(src); - NtkDest dest; - - old2new[src.get_constant(false)].push_back(dest.get_constant(false)); - if (src.get_node(src.get_constant(true)) != src.get_node(src.get_constant(false))) - { - old2new[src.get_constant(true)].push_back(dest.get_constant(true)); - } - src.foreach_pi([&](auto const& n) { old2new[n].push_back(dest.create_pi()); }); - return {dest, old2new}; -} - -template -virtual_pi_network create_virt_pi_ntk_from_lvls(Ntk& ntk, std::vector>>& ntk_lvls, - std::vector>>& ntk_lvls_new) -{ - std::unordered_map, bool> node_status; - ntk_lvls_new.resize(ntk_lvls.size()); - - auto init_v = initialize_copy_network_v(ntk); - auto& ntk_dest_v = init_v.first; - auto& old2new_v = init_v.second; - - /** - * The function gather_fanin_signals collects the fanin data for node n from the original ntk. - * For each node n there are the possible fanin candidates old2new_v[fn], which are the original node and all the - * nodes which are duplicates of this node. - * - * lvl[edge_it] gives the current iterator at where the edge can be connected. To get the right signal, - * all nodes at old2new[n] need to be viewed. Match lvl[edge_it] against all entries in old2new[n], - * then try lvl[edge_it+1] then try lvl[edge_it+2]. - * - * @param n Variable to process. - * @param lvl Level to process. - * @param edge_it Iterator for edge. - * @return Vector of fanins in the virtual_pi_network connected to the processed node. - */ - const auto gather_fanin_signals = [&](const auto& n, const auto& lvl, size_t& edge_it) - { - std::vector children{}; - const auto edge_it_int = edge_it; - int first_fi_edge_it = -1; - - ntk.foreach_fanin(n, - [&](const auto& f) - { - const auto fn = ntk.get_node(f); - auto tgt_signal_v = old2new_v[fn]; - - // lvl[edge_it] gives the current iterator at where the edge can be connected - // to get the right signal, all nodes at old2new[n] need to be viewed - // match lvl[edge_it] against áll entries in old2new[n], then try lvl[edge_it+1] then try - // lvl[edge_it+2] - - assert(edge_it_int < lvl.size()); - - for (const auto& possible_node : tgt_signal_v) - { - auto it = ntk.is_maj(n) ? 4 : 3; - for (size_t i = 0; i < it; i++) - { - if (edge_it_int + i < lvl.size() && lvl[edge_it_int + i] == possible_node) - { - if (first_fi_edge_it != -1) - { - if (!ntk.is_maj(n)) - { - assert(edge_it_int + i == first_fi_edge_it + 1 || - edge_it_int + i == first_fi_edge_it - 1); - } - } - children.emplace_back(possible_node); - first_fi_edge_it = static_cast(edge_it_int + i); - if (edge_it_int + i > edge_it) - { - edge_it = edge_it_int + i; - } - break; - } - } - } - }); - return children; - }; - - size_t edge_it = 0; - for (size_t i = ntk_lvls.size(); i-- > 0;) - { - edge_it = 0; - auto& lvl = ntk_lvls[i]; - auto& lvl_new = ntk_lvls_new[i]; - for (const auto& nd : lvl) - { - if (ntk.is_pi(nd)) - { - if (node_status[nd]) - { - const auto& new_node = ntk_dest_v.create_virtual_pi(nd); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - } - else - { - lvl_new.push_back(nd); - node_status[nd] = true; - } - } - else - { - auto children = gather_fanin_signals(nd, ntk_lvls_new[i + 1], edge_it); - - if (ntk.is_and(nd)) - { - const auto& new_node = ntk_dest_v.create_and(children[0], children[1]); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - continue; - } - if (ntk.is_or(nd)) - { - const auto& new_node = ntk_dest_v.create_or(children[0], children[1]); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - continue; - } - if (ntk.is_xor(nd)) - { - const auto& new_node = ntk_dest_v.create_xor(children[0], children[1]); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - continue; - } - if (ntk.is_maj(nd)) - { - const auto& new_node = ntk_dest_v.create_maj(children[0], children[1], children[2]); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - continue; - } - if (ntk.is_buf(nd)) - { - const auto& new_node = ntk_dest_v.create_buf(children[0]); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - continue; - } - if (ntk.is_inv(nd)) - { - const auto& new_node = ntk_dest_v.create_not(children[0]); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - continue; - } - } - } - } - - ntk.foreach_po( - [&ntk, &ntk_dest_v, &old2new_v](const auto& po) - { - const auto tgt_signal_v = old2new_v[ntk.get_node(po)]; - // POs dont get duplicated since the algorithm starts at the POs and duplicates other nodes according to - // their order - assert(tgt_signal_v.size() == 1); - const auto tgt_signal = tgt_signal_v[0]; - - const auto tgt_po = ntk.is_complemented(po) ? ntk_dest_v.create_not(tgt_signal) : tgt_signal; - - ntk_dest_v.create_po(tgt_po); - }); - - return ntk_dest_v; -} - /** * @brief A structure representing a pair of nodes in an H-graph * @@ -586,7 +381,7 @@ class node_duplication_planarization_impl } // create virtual pi network - auto new_ntk = create_virt_pi_ntk_from_lvls(ntk, ntk_lvls, ntk_lvls_new); + auto new_ntk = virtual_pi_network(ntk, ntk_lvls, ntk_lvls_new); return new_ntk; // mockturtle::rank_view(ntk); } diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index a2aa7c302..ca1ee79c4 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -50,6 +50,222 @@ class virtual_pi_network : public technology_network _storage = std::make_shared(*(other._storage)); // create deep copy of storage } + /** + * @brief A variant of the mockturtle::initialize_copy_network. It maps old nodes not only to a single node, but to + * multiple or duplicated nodes. + * + * @tparam NtkDest Type of the destination network + * @tparam NtkSrc Type of the source network + * @param src The source network + * + * @return A pair of the destination network and a node map from the source to the destination network. + * + * @pre NtkDest and NtkSrc must be network types (satisfy is_network_type_v). + * @pre NtkDest and NtkSrc must implement the methods get_constant, get_node, create_pi and foreach_pi (satisfy + * has_get_constant_v, has_get_node_v, has_create_pi_v and has_foreach_pi_v). + * + * @post A map (old2new) is created where old nodes from source network are mapped to new nodes in destination + * network. + * @post A destination network is created with the same structure as the source network. + * + */ + template + std::pair>, NtkSrc>> + initialize_copy_network_v(NtkSrc const& src) + { + static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); + static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); + + static_assert(mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method"); + static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method"); + static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method"); + static_assert(mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi method"); + + mockturtle::node_map>, NtkSrc> old2new(src); + NtkDest dest; + + old2new[src.get_constant(false)].push_back(dest.get_constant(false)); + if (src.get_node(src.get_constant(true)) != src.get_node(src.get_constant(false))) + { + old2new[src.get_constant(true)].push_back(dest.get_constant(true)); + } + src.foreach_pi([&](auto const& n) { old2new[n].push_back(dest.create_pi()); }); + return {dest, old2new}; + } + + /** + * @brief Special constructor to construct a virtual_pi_network from any other network type. + * + * @tparam Ntk Network type + * @param ntk Source network to be utilized for the creation of the virtual_pi_network + * @param ntk_lvls Levels of nodes in the source network + * @param ntk_lvls_new Levels of newly created nodes in the virtual_pi_network + * + * This constructor creates a virtual_pi_network by using the nodes from the original network stored in ntk_lvls. + * It handles duplicated nodes and stores them with their newly created nodes in ntk_lvls_new. + * If the duplicated nodes are PIs (Primary Inputs), virtual PIs are created and the original PI is stored in a map. + * To manage the connections between nodes, this also uses an auxiliary function gather_fanin_signals, that + * collects the fanin data for a node and matches them in the virtual_pi_network. + * + */ + template + explicit virtual_pi_network(Ntk& ntk, std::vector>>& ntk_lvls, + std::vector>>& ntk_lvls_new) + { + std::unordered_map, bool> node_status; + ntk_lvls_new.resize(ntk_lvls.size()); + + auto init_v = initialize_copy_network_v(ntk); + auto& ntk_dest_v = init_v.first; + auto& old2new_v = init_v.second; + + /** + * The function gather_fanin_signals collects the fanin data for node n from the original ntk. + * For each node n there are the possible fanin candidates old2new_v[fn], which are the original node and all + * the nodes which are duplicates of this node. + * + * lvl[edge_it] gives the current iterator at where the edge can be connected. To get the right signal, + * all nodes at old2new[n] need to be viewed. Match lvl[edge_it] against all entries in old2new[n], + * then try lvl[edge_it+1] then try lvl[edge_it+2]. + * + * @param n Variable to process. + * @param lvl Level to process. + * @param edge_it Iterator for edge. + * @return Vector of fanins in the virtual_pi_network connected to the processed node. + */ + const auto gather_fanin_signals = [&](const auto& n, const auto& lvl, size_t& edge_it) + { + std::vector children{}; + const auto edge_it_int = edge_it; + int first_fi_edge_it = -1; + + ntk.foreach_fanin(n, + [&](const auto& f) + { + const auto fn = ntk.get_node(f); + auto tgt_signal_v = old2new_v[fn]; + + assert(edge_it_int < lvl.size()); + + for (const auto& possible_node : tgt_signal_v) + { + auto it = ntk.is_maj(n) ? 4 : 3; + for (size_t i = 0; i < it; i++) + { + if (edge_it_int + i < lvl.size() && lvl[edge_it_int + i] == possible_node) + { + if (first_fi_edge_it != -1) + { + if (!ntk.is_maj(n)) + { + assert(edge_it_int + i == first_fi_edge_it + 1 || + edge_it_int + i == first_fi_edge_it - 1); + } + } + children.emplace_back(possible_node); + first_fi_edge_it = static_cast(edge_it_int + i); + if (edge_it_int + i > edge_it) + { + edge_it = edge_it_int + i; + } + break; + } + } + } + }); + return children; + }; + + size_t edge_it = 0; + for (size_t i = ntk_lvls.size(); i-- > 0;) + { + edge_it = 0; + auto& lvl = ntk_lvls[i]; + auto& lvl_new = ntk_lvls_new[i]; + for (const auto& nd : lvl) + { + if (ntk.is_pi(nd)) + { + if (node_status[nd]) + { + const auto& new_node = ntk_dest_v.create_virtual_pi(nd); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + } + else + { + lvl_new.push_back(nd); + node_status[nd] = true; + } + } + else + { + auto children = gather_fanin_signals(nd, ntk_lvls_new[i + 1], edge_it); + + if (ntk.is_and(nd)) + { + const auto& new_node = ntk_dest_v.create_and(children[0], children[1]); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + continue; + } + if (ntk.is_or(nd)) + { + const auto& new_node = ntk_dest_v.create_or(children[0], children[1]); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + continue; + } + if (ntk.is_xor(nd)) + { + const auto& new_node = ntk_dest_v.create_xor(children[0], children[1]); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + continue; + } + if (ntk.is_maj(nd)) + { + const auto& new_node = ntk_dest_v.create_maj(children[0], children[1], children[2]); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + continue; + } + if (ntk.is_buf(nd)) + { + const auto& new_node = ntk_dest_v.create_buf(children[0]); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + continue; + } + if (ntk.is_inv(nd)) + { + const auto& new_node = ntk_dest_v.create_not(children[0]); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + continue; + } + } + } + } + + ntk.foreach_po( + [&ntk, &ntk_dest_v, &old2new_v](const auto& po) + { + const auto tgt_signal_v = old2new_v[ntk.get_node(po)]; + // POs dont get duplicated since the algorithm starts at the POs and duplicates other nodes according to + // their order + assert(tgt_signal_v.size() == 1); + const auto tgt_signal = tgt_signal_v[0]; + + const auto tgt_po = ntk.is_complemented(po) ? ntk_dest_v.create_not(tgt_signal) : tgt_signal; + + ntk_dest_v.create_po(tgt_po); + }); + + *this = ntk_dest_v; + } + /** * @brief Reimplementation of num_gates(). Retrieves the number of gates in the virtual_pi_network. * @@ -383,13 +599,13 @@ class virtual_pi_network : public technology_network } /** - * @brief Applies a function to each gate in the circuit. - * - * This function iterates over each gate in the circuit, excluding the constants. - * - * @tparam Fn The type of the function. - * @param fn The function to apply to each gate. - */ + * @brief Applies a function to each gate in the circuit. + * + * This function iterates over each gate in the circuit, excluding the constants. + * + * @tparam Fn The type of the function. + * @param fn The function to apply to each gate. + */ template void foreach_gate(Fn&& fn) const { @@ -399,17 +615,17 @@ class virtual_pi_network : public technology_network } /** - * @brief Removes virtual input nodes from the storage. This enables equivalence checking. - * - * This function removes virtual input nodes from the storage by performing the following steps: - * 1. Sorts the virtual input nodes in descending order. - * 2. For each virtual input node, finds the corresponding real_pi index mapped to it from the map. - * 3. Substitute the virtual input node with the new node index, which corresponds to the real_pi. - * 4. Adjusts the inputs, nodes vector, and outputs. - * 5. Erases the virtual input node from the nodes vector. - * - * After removing the virtual input nodes, this function clears the virtual_inputs and map containers. - */ + * @brief Removes virtual input nodes from the storage. This enables equivalence checking. + * + * This function removes virtual input nodes from the storage by performing the following steps: + * 1. Sorts the virtual input nodes in descending order. + * 2. For each virtual input node, finds the corresponding real_pi index mapped to it from the map. + * 3. Substitute the virtual input node with the new node index, which corresponds to the real_pi. + * 4. Adjusts the inputs, nodes vector, and outputs. + * 5. Erases the virtual input node from the nodes vector. + * + * After removing the virtual input nodes, this function clears the virtual_inputs and map containers. + */ void remove_virtual_input_nodes() { std::sort(virtual_inputs->begin(), virtual_inputs->end(), std::greater()); @@ -465,7 +681,7 @@ class virtual_pi_network : public technology_network /* * Shared pointer vector storage for virtual_inputs. * */ - std::shared_ptr> virtual_inputs; + std::shared_ptr> virtual_inputs; /* * Map from virtual_pis to real_pis. * */ From 0d5dc5578cc794264ac4877b158aec357e654831 Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 17 Jul 2024 17:12:00 +0200 Subject: [PATCH 26/84] :art: updated documentation check_planarity.hpp --- .../algorithms/properties/check_planarity.hpp | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/include/fiction/algorithms/properties/check_planarity.hpp b/include/fiction/algorithms/properties/check_planarity.hpp index d7faa6bd6..17af548b9 100644 --- a/include/fiction/algorithms/properties/check_planarity.hpp +++ b/include/fiction/algorithms/properties/check_planarity.hpp @@ -18,6 +18,17 @@ class check_planarity_impl public: check_planarity_impl(const Ntk& ntk) : ntk(ntk) {} + /** + * @brief Checks if a given network is planar. + * + * This function checks if the network represented by the variable `ntk` is planar. + * The network is planar if for any edge with starting point m and end point n there is never another edge with + * starting point m_ > m and ending point n_ < n or vice versa. When iterating through the ranks of one level the + * end points ar always increasing. Therefore only the starting points need to be checked. Therefore the highest + * connected starting point in the fanin gives a border m_max for every next edge. + * + * @return `true` if the network is planar, `false` otherwise. + */ bool run() { bool return_false = false; @@ -28,7 +39,7 @@ class check_planarity_impl [this, &bound, &return_false](const auto& n) { uint32_t new_bound = bound; - ntk.foreach_fanin(n, + ntk.foreach_fanin(n, [this, &bound, &new_bound, &return_false](const auto& fi) { const auto fi_n = ntk.get_node(fi); @@ -52,6 +63,17 @@ class check_planarity_impl Ntk ntk; }; +/** + * Checks if a logic network is planar. + * + * If the network is not balanced, an exception is thrown. To balance the network, insert buffers to divide multi-level + * edges. + * + * @tparam Ntk Logic network type. + * @param ntk The logic network to check for planarity. + * @return `true` if the network is planar, `false` otherwise. + * @throw std::runtime_error if the network is not balanced. + */ template bool check_planarity(Ntk& ntk) { @@ -64,7 +86,6 @@ bool check_planarity(Ntk& ntk) if (!is_balanced(ntk)) { - // ToDo: Instead drag this to the implementation and insert buffers so that they divide multi-level edges throw std::runtime_error("Network must be balanced"); } From afd38fb772f2ac0f824c3421365c48e2df34984a Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 17 Jul 2024 17:46:09 +0200 Subject: [PATCH 27/84] :art: small adjustments --- .../node_duplication_planarization.hpp | 6 ++-- .../networks/views/extended_rank_view.hpp | 12 ++++++-- .../fiction/networks/virtual_pi_network.hpp | 8 +++--- .../node_duplication_planarization.cpp | 5 ++-- test/networks/views/extended_rank_view.cpp | 28 ++----------------- test/networks/virtual_pi_network.cpp | 2 +- 6 files changed, 23 insertions(+), 38 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 1e61ec49e..0bd751ccc 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -174,7 +174,7 @@ class node_duplication_planarization_impl * @throws std::runtime_error if no combinations (possible node_pairs) are found, which might suggest a dangling * node */ - void compute_slice_delays(mockturtle::node nd, const bool border_pis) + void compute_slice_delays(const mockturtle::node& nd, const bool border_pis) { // Pis need to be propagated into the next level, since they have to be connected without crossings if (ntk.is_pi(nd) && border_pis) @@ -234,7 +234,7 @@ class node_duplication_planarization_impl * @param node The node to be inserted * @param vec The vector to insert the node into */ - void insert_if_unique(mockturtle::node node, std::vector>& vec) + void insert_if_unique(const mockturtle::node& node, std::vector>& vec) { if (vec.empty() || vec.front() != node) { @@ -304,7 +304,7 @@ class node_duplication_planarization_impl * @param v_next_level The vector of nodes to be checked * @param f_final_level A reference to a boolean indicating if the vector contains only primary inputs */ - void check_final_level(std::vector>& v_next_level, bool& f_final_level) + void check_final_level(const std::vector>& v_next_level, bool& f_final_level) { for (const auto& nd : v_next_level) { diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index 4e63dc6c2..1a176b93c 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -436,8 +436,6 @@ class extended_rank_view : public mockturtle::depth_view /** * Overrides the base class method to also call the add_event on create_pi(). * - * @note This can (and in fact will) lead to issues if Ntk already calls add_event functions on create_pi()! - * * @return Newly created PI signal. */ signal create_pi() @@ -567,6 +565,16 @@ class extended_rank_view : public mockturtle::depth_view template extended_rank_view(T const&) -> extended_rank_view; +/** + * @brief Deduction guide for `extended_rank_view` with two constructor arguments + * + * This template helps to deduce the type argument `T` for the + * `extended_rank_view` class when constructed with two arguments: a network of type `T`, + * and a `vector` of `vector` containing network nodes. + * + * @tparam T Network type deduced from the construction context of + * `extended_rank_view`. + */ template extended_rank_view(T const&, std::vector>) -> extended_rank_view; diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index ca1ee79c4..c5ab5291d 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -95,7 +95,7 @@ class virtual_pi_network : public technology_network } /** - * @brief Special constructor to construct a virtual_pi_network from any other network type. + * @brief Special constructor to construct a planar virtual_pi_network from any other network type with given ranks. * * @tparam Ntk Network type * @param ntk Source network to be utilized for the creation of the virtual_pi_network @@ -111,7 +111,7 @@ class virtual_pi_network : public technology_network */ template explicit virtual_pi_network(Ntk& ntk, std::vector>>& ntk_lvls, - std::vector>>& ntk_lvls_new) + std::vector>>& ntk_lvls_new) { std::unordered_map, bool> node_status; ntk_lvls_new.resize(ntk_lvls.size()); @@ -253,8 +253,8 @@ class virtual_pi_network : public technology_network [&ntk, &ntk_dest_v, &old2new_v](const auto& po) { const auto tgt_signal_v = old2new_v[ntk.get_node(po)]; - // POs dont get duplicated since the algorithm starts at the POs and duplicates other nodes according to - // their order + // POs do not get duplicated since the algorithm starts at the POs and duplicates other nodes according + // to their order assert(tgt_signal_v.size() == 1); const auto tgt_signal = tgt_signal_v[0]; diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index 364ee7b9f..78386bd92 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -16,8 +16,7 @@ using namespace fiction; -// Implement reverse balancing function. Also it should propagate PIs all to the last level -TEST_CASE("2-ary Test", "[node-duplication-planarization]") +TEST_CASE("2-ary nodes Test", "[node-duplication-planarization]") { technology_network tec{}; @@ -54,7 +53,7 @@ TEST_CASE("2-ary Test", "[node-duplication-planarization]") CHECK(cec_m == 1); } -TEST_CASE("3-ary Test", "[node-duplication-planarization]") +TEST_CASE("3-ary nodes Test", "[node-duplication-planarization]") { technology_network tec{}; diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index 383768641..c3704c2fa 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -79,41 +79,17 @@ TEST_CASE("Check modify ranks", "[extended-rank-view]") tec.create_po(f2); tec.create_po(f3); - auto blc = is_balanced(tec); - std::cout << "Balanced: " << blc << "\n"; - network_balancing_params ps; ps.unify_outputs = true; auto tec_balanced = network_balancing(tec, ps); - blc = is_balanced(tec_balanced); - std::cout << "Balanced: " << blc << "\n"; auto vpi_r = extended_rank_view(tec_balanced); std::vector nodes = {13, 10}; vpi_r.modify_rank(2, nodes); - vpi_r.foreach_po([&](const auto& nd) { - std::cout << "Nd:" << nd << "\n"; - /*if (vpi_r.is_inv(nd)) - { - std::cout << "is not" << "\n"; - } - if (vpi_r.is_buf(nd)) - { - std::cout << "is buf" << "\n"; - } - vpi_r.foreach_fanin(nd, [&](const auto& fi) { std::cout << "Fis:" << fi << "\n"; });*/ - auto rnk = vpi_r.rank_position(nd); - auto lvl = vpi_r.level(nd); - std::cout << "Level: " << lvl << "\n"; - std::cout << "Rank: " << rnk << "\n"; - }); - - std::cout << "Valid: " << vpi_r.check_validity() << std::endl; - - CHECK(1 == 1); + CHECK(vpi_r.check_validity() == 1); } TEMPLATE_TEST_CASE( "Check equivalence checking", "[extended_rank_view]", mockturtle::aig_network, mockturtle::mig_network, mockturtle::xag_network, mockturtle::xmg_network, mockturtle::klut_network, mockturtle::buffered_aig_network, mockturtle::buffered_mig_network, mockturtle::crossed_klut_network, mockturtle::buffered_crossed_klut_network ) @@ -146,6 +122,7 @@ TEMPLATE_TEST_CASE( "Check equivalence checking", "[extended_rank_view]", mocktu mockturtle::equivalence_checking_stats st; bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(ntk, ntk_r), {}, &st); CHECK(cec_m == 1); + CHECK(ntk_r.check_validity() == 1); } TEST_CASE("Check equivalence checking for virtual PIs", "[extended-rank-view]") @@ -188,4 +165,5 @@ TEST_CASE("Check equivalence checking for virtual PIs", "[extended-rank-view]") mockturtle::equivalence_checking_stats st; bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); CHECK(cec_m == 1); + CHECK(vpi_r.check_validity() == 1); } diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index e4e54fadb..179b2e6cc 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -85,7 +85,7 @@ TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]") CHECK(cec_m == 1); } -TEST_CASE("Remove PIs and check equivalence second", "[virtual-pi-view]") +TEST_CASE("Remove PIs and check equivalence copy constructor", "[virtual-pi-view]") { technology_network tec{}; From c22d3c37cc4dadcf9e0cca6ffad0a0602f85ccb9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 15:51:38 +0000 Subject: [PATCH 28/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../node_duplication_planarization.cpp | 14 +++-- .../algorithms/properties/check_planarity.cpp | 5 +- test/networks/views/extended_rank_view.cpp | 60 ++++++++++--------- test/networks/virtual_pi_network.cpp | 12 ++-- 4 files changed, 51 insertions(+), 40 deletions(-) diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index 78386bd92..32299151d 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -6,10 +6,11 @@ #include "utils/blueprints/network_blueprints.hpp" #include "utils/equivalence_checking_utils.hpp" -#include -#include #include +#include + +#include #include #include @@ -49,7 +50,8 @@ TEST_CASE("2-ary nodes Test", "[node-duplication-planarization]") planarized_maj.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; - bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); + bool cec_m = + *mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); CHECK(cec_m == 1); } @@ -88,7 +90,8 @@ TEST_CASE("3-ary nodes Test", "[node-duplication-planarization]") planarized_maj.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; - bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); + bool cec_m = + *mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); CHECK(cec_m == 1); } @@ -127,6 +130,7 @@ TEST_CASE("Aig Test", "[node-duplication-planarization]") planarized_maj.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; - bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(aig, planarized_maj), {}, &st); + bool cec_m = + *mockturtle::equivalence_checking(*mockturtle::miter(aig, planarized_maj), {}, &st); CHECK(cec_m == 1); } diff --git a/test/algorithms/properties/check_planarity.cpp b/test/algorithms/properties/check_planarity.cpp index bb380f376..59f2cea04 100644 --- a/test/algorithms/properties/check_planarity.cpp +++ b/test/algorithms/properties/check_planarity.cpp @@ -2,12 +2,13 @@ // Created by benjamin on 7/17/24. // +#include + #include #include #include -#include -#include +#include using namespace fiction; diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index c3704c2fa..e640d946d 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -2,8 +2,8 @@ // Created by benjamin on 6/18/24. // -#include #include +#include #include #include @@ -25,38 +25,41 @@ using namespace fiction; -TEMPLATE_TEST_CASE( "traits", "[extended_rank_view]", mockturtle::aig_network, mockturtle::mig_network, mockturtle::xag_network, mockturtle::xmg_network, mockturtle::klut_network, mockturtle::cover_network, mockturtle::buffered_aig_network, mockturtle::buffered_mig_network, mockturtle::crossed_klut_network, mockturtle::buffered_crossed_klut_network ) +TEMPLATE_TEST_CASE("traits", "[extended_rank_view]", mockturtle::aig_network, mockturtle::mig_network, + mockturtle::xag_network, mockturtle::xmg_network, mockturtle::klut_network, + mockturtle::cover_network, mockturtle::buffered_aig_network, mockturtle::buffered_mig_network, + mockturtle::crossed_klut_network, mockturtle::buffered_crossed_klut_network) { - CHECK( mockturtle::is_network_type_v ); - CHECK( !mockturtle::has_rank_position_v ); - CHECK( !mockturtle::has_at_rank_position_v ); - CHECK( !mockturtle::has_width_v ); - CHECK( !mockturtle::has_sort_rank_v ); - CHECK( !mockturtle::has_foreach_node_in_rank_v ); - CHECK( !mockturtle::has_foreach_gate_in_rank_v ); - CHECK( !mockturtle::is_topologically_sorted_v ); + CHECK(mockturtle::is_network_type_v); + CHECK(!mockturtle::has_rank_position_v); + CHECK(!mockturtle::has_at_rank_position_v); + CHECK(!mockturtle::has_width_v); + CHECK(!mockturtle::has_sort_rank_v); + CHECK(!mockturtle::has_foreach_node_in_rank_v); + CHECK(!mockturtle::has_foreach_gate_in_rank_v); + CHECK(!mockturtle::is_topologically_sorted_v); using rank_ntk = extended_rank_view; - CHECK( mockturtle::is_network_type_v ); - CHECK( mockturtle::has_rank_position_v ); - CHECK( mockturtle::has_at_rank_position_v ); - CHECK( mockturtle::has_width_v ); - CHECK( mockturtle::has_sort_rank_v ); - CHECK( mockturtle::has_foreach_node_in_rank_v ); - CHECK( mockturtle::has_foreach_gate_in_rank_v ); - CHECK( mockturtle::is_topologically_sorted_v ); + CHECK(mockturtle::is_network_type_v); + CHECK(mockturtle::has_rank_position_v); + CHECK(mockturtle::has_at_rank_position_v); + CHECK(mockturtle::has_width_v); + CHECK(mockturtle::has_sort_rank_v); + CHECK(mockturtle::has_foreach_node_in_rank_v); + CHECK(mockturtle::has_foreach_gate_in_rank_v); + CHECK(mockturtle::is_topologically_sorted_v); using rank_rank_ntk = extended_rank_view; - CHECK( mockturtle::is_network_type_v ); - CHECK( mockturtle::has_rank_position_v ); - CHECK( mockturtle::has_at_rank_position_v ); - CHECK( mockturtle::has_width_v ); - CHECK( mockturtle::has_sort_rank_v ); - CHECK( mockturtle::has_foreach_node_in_rank_v ); - CHECK( mockturtle::has_foreach_gate_in_rank_v ); - CHECK( mockturtle::is_topologically_sorted_v ); + CHECK(mockturtle::is_network_type_v); + CHECK(mockturtle::has_rank_position_v); + CHECK(mockturtle::has_at_rank_position_v); + CHECK(mockturtle::has_width_v); + CHECK(mockturtle::has_sort_rank_v); + CHECK(mockturtle::has_foreach_node_in_rank_v); + CHECK(mockturtle::has_foreach_gate_in_rank_v); + CHECK(mockturtle::is_topologically_sorted_v); } TEST_CASE("Check modify ranks", "[extended-rank-view]") @@ -92,7 +95,10 @@ TEST_CASE("Check modify ranks", "[extended-rank-view]") CHECK(vpi_r.check_validity() == 1); } -TEMPLATE_TEST_CASE( "Check equivalence checking", "[extended_rank_view]", mockturtle::aig_network, mockturtle::mig_network, mockturtle::xag_network, mockturtle::xmg_network, mockturtle::klut_network, mockturtle::buffered_aig_network, mockturtle::buffered_mig_network, mockturtle::crossed_klut_network, mockturtle::buffered_crossed_klut_network ) +TEMPLATE_TEST_CASE("Check equivalence checking", "[extended_rank_view]", mockturtle::aig_network, + mockturtle::mig_network, mockturtle::xag_network, mockturtle::xmg_network, mockturtle::klut_network, + mockturtle::buffered_aig_network, mockturtle::buffered_mig_network, mockturtle::crossed_klut_network, + mockturtle::buffered_crossed_klut_network) { TestType ntk{}; diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index 179b2e6cc..04689091b 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -24,8 +24,8 @@ TEST_CASE("Copy network and size consistency", "[virtual-pi-view]") virtual_pi_network vpi{tec}; - const auto c = vpi.create_virtual_pi(a); - const auto d = vpi.create_virtual_pi(b); + const auto c = vpi.create_virtual_pi(a); + const auto d = vpi.create_virtual_pi(b); const auto f2 = vpi.create_and(b, c); const auto f3 = vpi.create_or(a, d); @@ -112,9 +112,9 @@ TEST_CASE("Remove PIs and check equivalence copy constructor", "[virtual-pi-view const auto e = vpi.create_pi(); - const auto f7 = vpi.create_not(b); - const auto f8 = vpi.create_and(a, b); - const auto f9 = vpi.create_and(c, d); + const auto f7 = vpi.create_not(b); + const auto f8 = vpi.create_and(a, b); + const auto f9 = vpi.create_and(c, d); const auto f10 = vpi.create_buf(c); const auto f11 = vpi.create_and(d_v, e); @@ -128,7 +128,7 @@ TEST_CASE("Remove PIs and check equivalence copy constructor", "[virtual-pi-view vpi.remove_virtual_input_nodes(); CHECK(vpi.size_real() == vpi.size()); - CHECK(vpi.size() - 2 == tec.size()); // the -2 is due to the buffers + CHECK(vpi.size() - 2 == tec.size()); // the -2 is due to the buffers mockturtle::equivalence_checking_stats st; bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); From 345071863710f5804d856ad3a2e958040dd1a144 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 30 Jul 2024 17:46:44 +0200 Subject: [PATCH 29/84] :art: check_planarity.hpp spaw trait removed, since const ntk doesnt need this trait. revised all files for costness, includes, comments, docstrings, etc. --- .../node_duplication_planarization.hpp | 23 +++-- .../algorithms/properties/check_planarity.hpp | 33 ++++--- .../networks/views/extended_rank_view.hpp | 15 +-- .../fiction/networks/virtual_pi_network.hpp | 98 +++++++++++-------- .../node_duplication_planarization.cpp | 26 ++--- .../algorithms/properties/check_planarity.cpp | 26 ++--- test/networks/views/extended_rank_view.cpp | 17 ++-- test/networks/virtual_pi_network.cpp | 10 +- 8 files changed, 139 insertions(+), 109 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 0bd751ccc..b9d7f166c 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -1,11 +1,10 @@ // -// Created by benjamin on 6/11/24. +// Created by benjamin on 11.06.24. // #ifndef FICTION_NODE_DUPLICATION_PLANARIZATION_HPP #define FICTION_NODE_DUPLICATION_PLANARIZATION_HPP -#include "fiction/algorithms/network_transformation/fanout_substitution.hpp" #include "fiction/algorithms/network_transformation/network_balancing.hpp" #include "fiction/algorithms/properties/check_planarity.hpp" #include "fiction/networks/views/extended_rank_view.hpp" @@ -32,14 +31,14 @@ namespace fiction { /** - * Parameters for the fanout substitution algorithm. + * Parameters for the node duplication algorithm. */ struct node_duplication_params { - /* + /** * The output order determines the starting layer for this algorithm. If this option is turned off, the output order * remains the same as in the provided network. If it is turned on, the outputs are ordered randomly. - * */ + */ bool random_output_order = false; }; @@ -390,7 +389,7 @@ class node_duplication_planarization_impl /* * The input network. */ - Ntk ntk; + const Ntk ntk; /* * The currently node_pairs used in the current level. */ @@ -412,7 +411,7 @@ class node_duplication_planarization_impl } // namespace detail /** - * @brief Implements a planarization mechanism for Mockturtle networks using a H-Graph strategy and node duplication. + * @brief Implements a planarization mechanism for networks using a H-Graph strategy for node duplication. * * @tparam NtkDest Destination network type * @tparam NtkSrc Source network type @@ -420,9 +419,11 @@ class node_duplication_planarization_impl * @param ps Node duplication parameters used in the computation * * The planarization achieved by this function solves the Node Duplication Crossing Minimization (NDCE) problem by - * finding the shortest x-y path in the H-graph for every level in the network. The function constructs an H-graph that - * captures edge relations between two levels within the graph and computes the shortest x-y paths on the H-graph. The - * graph is traversed from Primary Outputs (POs) towards Primary Inputs (PIs). + * finding the shortest x-y path in the H-graph for every level in the network. An H-graph describes edge relations + * between two levels in a network, with one level assumed as fixed, starting at the Primary Outputs (POs). By finding + * the shortest path from the source (x) to the sink (y) in this H-graph, an optimal solution for the NDCE problem is + * found. The function constructs an H-graph that captures edge relations between two levels within the graph and + * computes the shortest x-y paths on the H-graph, traversing from the POs towards the Primary Inputs (PIs). * * @return A view of the planarized virtual_pi_network created in the format of extended_rank_view * @@ -443,8 +444,6 @@ extended_rank_view node_duplication_planarization(const NtkS static_assert(mockturtle::has_create_po_v, "NtkDest does not implement the create_po function"); static_assert(mockturtle::has_create_buf_v, "NtkDest does not implement the create_buf function"); static_assert(mockturtle::has_clone_node_v, "NtkDest does not implement the clone_node function"); - static_assert(mockturtle::has_fanout_size_v, "NtkDest does not implement the fanout_size function"); - static_assert(mockturtle::has_foreach_gate_v, "NtkDest does not implement the foreach_gate function"); static_assert(mockturtle::has_foreach_fanin_v, "NtkDest does not implement the foreach_fanin function"); static_assert(mockturtle::has_foreach_po_v, "NtkDest does not implement the foreach_po function"); diff --git a/include/fiction/algorithms/properties/check_planarity.hpp b/include/fiction/algorithms/properties/check_planarity.hpp index 17af548b9..ba277f324 100644 --- a/include/fiction/algorithms/properties/check_planarity.hpp +++ b/include/fiction/algorithms/properties/check_planarity.hpp @@ -1,5 +1,5 @@ // -// Created by benjamin on 7/17/24. +// Created by benjamin on 17.07.24. // #ifndef FICTION_CHECK_PLANARITY_HPP @@ -7,6 +7,10 @@ #include "fiction/algorithms/network_transformation/network_balancing.hpp" +#include + +#include +#include #include namespace fiction @@ -22,10 +26,10 @@ class check_planarity_impl * @brief Checks if a given network is planar. * * This function checks if the network represented by the variable `ntk` is planar. - * The network is planar if for any edge with starting point m and end point n there is never another edge with - * starting point m_ > m and ending point n_ < n or vice versa. When iterating through the ranks of one level the - * end points ar always increasing. Therefore only the starting points need to be checked. Therefore the highest - * connected starting point in the fanin gives a border m_max for every next edge. + * The network is planar if for any edge with starting point m and endpoint n (represented by the node ranks), there + * is never another edge with starting point m_ > m and endpoint n_ < n, or vice versa. When iterating through + * the ranks of one level, the endpoints are always increasing. Therefore, only the starting points need to be + * checked. Thus, the highest connected starting point in the fan-in gives a border m_max for every subsequent edge. * * @return `true` if the network is planar, `false` otherwise. */ @@ -60,11 +64,11 @@ class check_planarity_impl } private: - Ntk ntk; + const Ntk ntk; }; /** - * Checks if a logic network is planar. + * Checks if a logic network is planar. To perform this check, the network must have ranks assigned. * * If the network is not balanced, an exception is thrown. To balance the network, insert buffers to divide multi-level * edges. @@ -75,14 +79,13 @@ class check_planarity_impl * @throw std::runtime_error if the network is not balanced. */ template -bool check_planarity(Ntk& ntk) +bool check_planarity(const Ntk& ntk) { - static_assert(mockturtle::has_rank_position_v, "Ntk does not have rank position trait"); - static_assert(mockturtle::has_at_rank_position_v, "Ntk does not have at rank position trait"); - static_assert(mockturtle::has_swap_v, "Ntk does not have swap trait"); - static_assert(mockturtle::has_width_v, "Ntk does not have width trait"); - static_assert(mockturtle::has_foreach_node_in_rank_v, "Ntk does not have foreach node in rank trait"); - static_assert(mockturtle::has_foreach_gate_in_rank_v, "Ntk does not have foreach gate in rank trait"); + static_assert(mockturtle::has_get_node_v, "Ntk does not have get_node trait"); + static_assert(mockturtle::has_foreach_fanin_v, "Ntk does not have foreach_fanin trait"); + static_assert(mockturtle::has_depth_v, "Ntk does not have depth trait"); + static_assert(mockturtle::has_rank_position_v, "Ntk does not have rank_position trait"); + static_assert(mockturtle::has_foreach_node_in_rank_v, "Ntk does not have foreach_node_in_rank trait"); if (!is_balanced(ntk)) { @@ -91,7 +94,7 @@ bool check_planarity(Ntk& ntk) check_planarity_impl p{ntk}; - auto result = p.run(); + const auto result = p.run(); return result; } diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index 1a176b93c..27bb6cb16 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -1,8 +1,8 @@ // -// Created by benjamin on 6/18/24. +// Created by benjamin on 18.06.24. // -#include +#include "fiction/networks/virtual_pi_network.hpp" #include #include @@ -12,19 +12,20 @@ #include #include #include -#include +#include #include #include #ifndef FICTION_VIRTUAL_RANK_VIEW_HPP #define FICTION_VIRTUAL_RANK_VIEW_HPP -// this rank view can assign specific ranks to nodes in one level -// to check validity of the rank view you can use check_rank_validity() /** * @class extended_rank_view. Extends the mockturtle::rank_view * - * Provides a view with node ranks for given networks. It adds some functionalities to modify ranks. + * Provides a view with node ranks for given networks. It adds functionalities to modify ranks. Most importantly, the + * new `init_ranks()` function allows an array of nodes to be provided, which sets the levels and ranks of the nodes in + * the network. Additionally, the `modify_rank()` function allows a vector to be passed to a rank, assigning the ranks at + * this level. * */ template : public mockturtle::depth_view * \param level The level at which to modify the rank. * \param nodes The new set of nodes for the specified level. */ - void modify_rank(uint32_t const level, std::vector& nodes) + void modify_rank(uint32_t const level, const std::vector& nodes) { auto& rank = ranks[level]; rank = nodes; diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index c5ab5291d..41b469825 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -1,25 +1,37 @@ // -// Created by benjamin on 6/14/24. +// Created by benjamin on 14.06.24. // -#ifndef FICTION_NODE_DUPLICATION_VIEW_HPP -#define FICTION_NODE_DUPLICATION_VIEW_HPP +#ifndef FICTION_VIRTUAL_PI_NETWORK_HPP +#define FICTION_VIRTUAL_PI_NETWORK_HPP -#include "fiction/algorithms/network_transformation/network_conversion.hpp" +#include "fiction/types.hpp" +#include "fiction/networks/technology_network.hpp" -#include -// #include #include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include namespace fiction { -/*!\brief Manager view for virtual PIs +/*!\brief Network with additional "virtual" PIs. * - * Virtual PIs are mapping of a "virtual" PI onto a "real" PI in the network. - * Virtual PIs handle PI-duplications. + * "Virtual" PIs (Primary Inputs) are used to manage the duplication of PIs in the network. Each "real" PI can have + * an arbitrary number of "virtual" PIs, which are copies of the original "real" PI. + * A "virtual" PI can be created by duplicating a "real" PI. + * To keep track of this relationship, there is a mapping of each "virtual" PI to its corresponding "real" PI in the + * network. */ class virtual_pi_network : public technology_network { @@ -78,9 +90,15 @@ class virtual_pi_network : public technology_network static_assert(mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method"); static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method"); + static_assert(mockturtle::has_is_pi_v, "NtkDest does not implement the is_pi method"); + static_assert(mockturtle::has_create_not_v, "NtkDest does not implement the create_not method"); static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method"); static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method"); static_assert(mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi method"); + static_assert(mockturtle::has_foreach_po_v, "NtkSrc does not implement the foreach_po method"); + static_assert(mockturtle::has_is_complemented_v, + "NtkSrc does not implement the is_complemented method"); + static_assert(mockturtle::has_foreach_fanin_v, "NtkSrc does not implement the foreach_fanin method"); mockturtle::node_map>, NtkSrc> old2new(src); NtkDest dest; @@ -150,7 +168,7 @@ class virtual_pi_network : public technology_network for (const auto& possible_node : tgt_signal_v) { - auto it = ntk.is_maj(n) ? 4 : 3; + const auto it = ntk.is_maj(n) ? 4 : 3; for (size_t i = 0; i < it; i++) { if (edge_it_int + i < lvl.size() && lvl[edge_it_int + i] == possible_node) @@ -180,9 +198,9 @@ class virtual_pi_network : public technology_network size_t edge_it = 0; for (size_t i = ntk_lvls.size(); i-- > 0;) { - edge_it = 0; - auto& lvl = ntk_lvls[i]; - auto& lvl_new = ntk_lvls_new[i]; + edge_it = 0; + const auto& lvl = ntk_lvls[i]; + auto& lvl_new = ntk_lvls_new[i]; for (const auto& nd : lvl) { if (ntk.is_pi(nd)) @@ -201,7 +219,7 @@ class virtual_pi_network : public technology_network } else { - auto children = gather_fanin_signals(nd, ntk_lvls_new[i + 1], edge_it); + const auto children = gather_fanin_signals(nd, ntk_lvls_new[i + 1], edge_it); if (ntk.is_and(nd)) { @@ -329,8 +347,8 @@ class virtual_pi_network : public technology_network */ [[nodiscard]] bool is_pi(node const& n) const { - return std::find(virtual_inputs->begin(), virtual_inputs->end(), n) != virtual_inputs->end() || - std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); + return std::find(virtual_inputs->cbegin(), virtual_inputs->cend(), n) != virtual_inputs->cend() || + std::find(_storage->inputs.cbegin(), _storage->inputs.cend(), n) != _storage->inputs.cend(); } /** @@ -343,7 +361,7 @@ class virtual_pi_network : public technology_network */ [[nodiscard]] bool is_pi_virtual(node const& n) const { - return std::find(virtual_inputs->begin(), virtual_inputs->end(), n) != virtual_inputs->end(); + return std::find(virtual_inputs->cbegin(), virtual_inputs->cend(), n) != virtual_inputs->cend(); } /** @@ -356,7 +374,7 @@ class virtual_pi_network : public technology_network */ [[nodiscard]] bool is_pi_real(node const& n) const { - return std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); + return std::find(_storage->inputs.cbegin(), _storage->inputs.cend(), n) != _storage->inputs.cend(); } /** @@ -370,8 +388,8 @@ class virtual_pi_network : public technology_network */ [[nodiscard]] bool is_ci(node const& n) const { - return std::find(virtual_inputs->begin(), virtual_inputs->end(), n) != virtual_inputs->end() || - std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); + return std::find(virtual_inputs->cbegin(), virtual_inputs->cend(), n) != virtual_inputs->cend() || + std::find(_storage->inputs.cbegin(), _storage->inputs.cend(), n) != _storage->inputs.cend(); } /** @@ -384,7 +402,7 @@ class virtual_pi_network : public technology_network */ [[nodiscard]] bool is_ci_virtual(node const& n) const { - return std::find(virtual_inputs->begin(), virtual_inputs->end(), n) != virtual_inputs->end(); + return std::find(virtual_inputs->cbegin(), virtual_inputs->cend(), n) != virtual_inputs->cend(); } /** @@ -397,7 +415,7 @@ class virtual_pi_network : public technology_network */ [[nodiscard]] bool is_ci_real(node const& n) const { - return std::find(_storage->inputs.begin(), _storage->inputs.end(), n) != _storage->inputs.end(); + return std::find(_storage->inputs.cbegin(), _storage->inputs.cend(), n) != _storage->inputs.cend(); } /** @@ -490,7 +508,7 @@ class virtual_pi_network : public technology_network */ [[nodiscard]] auto get_real_pi(const node& v_pi) const { - auto it = std::find_if(map.begin(), map.end(), [v_pi](const auto& pair) { return pair.first == v_pi; }); + auto it = std::find_if(map.cbegin(), map.cend(), [v_pi](const auto& pair) { return pair.first == v_pi; }); if (it != map.end()) return it->second; @@ -510,8 +528,8 @@ class virtual_pi_network : public technology_network template void foreach_pi(Fn&& fn) const { - mockturtle::detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); - mockturtle::detail::foreach_element(virtual_inputs->begin(), virtual_inputs->end(), fn); + mockturtle::detail::foreach_element(_storage->inputs.cbegin(), _storage->inputs.cend(), fn); + mockturtle::detail::foreach_element(virtual_inputs->cbegin(), virtual_inputs->cend(), fn); } /** @@ -527,14 +545,14 @@ class virtual_pi_network : public technology_network template void foreach_pi_real(Fn&& fn) const { - mockturtle::detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); + mockturtle::detail::foreach_element(_storage->inputs.cbegin(), _storage->inputs.cend(), fn); } /** * @brief Applies a given function to each element in a container. * * This function applies the provided function to each element in the container `Fn`. The container must support - * iteration using `begin()` and `end()` methods. + * iteration using `cbegin()` and `cend()` methods. * * @tparam Fn The container type. * @param fn The function to apply to each element. @@ -544,7 +562,7 @@ class virtual_pi_network : public technology_network template void foreach_pi_virtual(Fn&& fn) const { - mockturtle::detail::foreach_element(virtual_inputs->begin(), virtual_inputs->end(), fn); + mockturtle::detail::foreach_element(virtual_inputs->cbegin(), virtual_inputs->cend(), fn); } /** @@ -561,8 +579,8 @@ class virtual_pi_network : public technology_network template void foreach_ci(Fn&& fn) const { - mockturtle::detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); - mockturtle::detail::foreach_element(virtual_inputs->begin(), virtual_inputs->end(), fn); + mockturtle::detail::foreach_element(_storage->inputs.cbegin(), _storage->inputs.cend(), fn); + mockturtle::detail::foreach_element(virtual_inputs->cbegin(), virtual_inputs->cend(), fn); } /** @@ -577,7 +595,7 @@ class virtual_pi_network : public technology_network template void foreach_ci_real(Fn&& fn) const { - mockturtle::detail::foreach_element(_storage->inputs.begin(), _storage->inputs.end(), fn); + mockturtle::detail::foreach_element(_storage->inputs.cbegin(), _storage->inputs.cend(), fn); } /** @@ -595,7 +613,7 @@ class virtual_pi_network : public technology_network template void foreach_ci_virtual(Fn&& fn) const { - mockturtle::detail::foreach_element(virtual_inputs->begin(), virtual_inputs->end(), fn); + mockturtle::detail::foreach_element(virtual_inputs->cbegin(), virtual_inputs->cend(), fn); } /** @@ -633,7 +651,7 @@ class virtual_pi_network : public technology_network { if (i < _storage->nodes.size()) { - uint64_t new_node = 0; // = ( _storage->outputs.begin() + i )->index + uint64_t new_node = 0; for (const auto& pair : map) { if (pair.first == i) @@ -668,7 +686,7 @@ class virtual_pi_network : public technology_network { --output.index; } - _storage->nodes.erase(_storage->nodes.begin() + i); + _storage->nodes.erase(_storage->nodes.cbegin() + i); } } @@ -678,16 +696,16 @@ class virtual_pi_network : public technology_network } protected: - /* + /** * Shared pointer vector storage for virtual_inputs. - * */ + */ std::shared_ptr> virtual_inputs; - /* + /** * Map from virtual_pis to real_pis. - * */ + */ std::vector> map; -}; /* color_view */ +}; } // namespace fiction -#endif // FICTION_NODE_DUPLICATION_VIEW_HPP +#endif // FICTION_VIRTUAL_PI_NETWORK_HPP diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index 32299151d..7f249b24b 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -1,5 +1,5 @@ // -// Created by benjamin on 6/11/24. +// Created by benjamin on 11.06.24. // #include @@ -12,9 +12,6 @@ #include -#include -#include - using namespace fiction; TEST_CASE("2-ary nodes Test", "[node-duplication-planarization]") @@ -40,7 +37,7 @@ TEST_CASE("2-ary nodes Test", "[node-duplication-planarization]") network_balancing_params ps; ps.unify_outputs = true; - auto tec_b = network_balancing(tec, ps); + const auto tec_b = network_balancing(tec, ps); const auto vpi_r = mockturtle::rank_view(tec_b); @@ -50,8 +47,9 @@ TEST_CASE("2-ary nodes Test", "[node-duplication-planarization]") planarized_maj.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; - bool cec_m = - *mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); + const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); + REQUIRE(maybe_cec_m.has_value()); + const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); } @@ -80,7 +78,7 @@ TEST_CASE("3-ary nodes Test", "[node-duplication-planarization]") network_balancing_params ps; ps.unify_outputs = true; - auto tec_b = network_balancing(tec, ps); + const auto tec_b = network_balancing(tec, ps); const auto vpi_r = mockturtle::rank_view(tec_b); @@ -90,8 +88,9 @@ TEST_CASE("3-ary nodes Test", "[node-duplication-planarization]") planarized_maj.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; - bool cec_m = - *mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); + const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); + REQUIRE(maybe_cec_m.has_value()); + const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); } @@ -120,7 +119,7 @@ TEST_CASE("Aig Test", "[node-duplication-planarization]") network_balancing_params ps; ps.unify_outputs = true; - auto aig_b = network_balancing(aig, ps); + const auto aig_b = network_balancing(aig, ps); const auto vpi_r = mockturtle::rank_view(aig_b); @@ -130,7 +129,8 @@ TEST_CASE("Aig Test", "[node-duplication-planarization]") planarized_maj.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; - bool cec_m = - *mockturtle::equivalence_checking(*mockturtle::miter(aig, planarized_maj), {}, &st); + const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(aig, planarized_maj), {}, &st); + REQUIRE(maybe_cec_m.has_value()); + const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); } diff --git a/test/algorithms/properties/check_planarity.cpp b/test/algorithms/properties/check_planarity.cpp index 59f2cea04..caa5c9f6e 100644 --- a/test/algorithms/properties/check_planarity.cpp +++ b/test/algorithms/properties/check_planarity.cpp @@ -1,5 +1,5 @@ // -// Created by benjamin on 7/17/24. +// Created by benjamin on 17.07.24. // #include @@ -8,8 +8,6 @@ #include #include -#include - using namespace fiction; TEST_CASE("Check planarity aig", "[check-planarity]") @@ -27,18 +25,22 @@ TEST_CASE("Check planarity aig", "[check-planarity]") const auto f1 = aig.create_and(x1, x2); const auto f2 = aig.create_and(x2, x3); + const auto x4 = aig.create_pi(); + const auto x5 = aig.create_not(x4); + aig.create_po(f1); aig.create_po(f2); + aig.create_po(x5); extended_rank_view tec_r(aig); - std::vector nodes_rank0{1, 2, 3}; - std::vector nodes_rank1{4, 5}; + const std::vector nodes_rank0{1, 2, 3}; + const std::vector nodes_rank1{4, 5}; tec_r.modify_rank(0, nodes_rank0); tec_r.modify_rank(0, nodes_rank0); - bool planar = check_planarity(tec_r); + const bool planar = check_planarity(tec_r); CHECK(planar == 1); } @@ -63,13 +65,13 @@ TEST_CASE("Check planarity technology network", "[check-planarity]") extended_rank_view tec_r(tec); - std::vector nodes_rank0{2, 3, 4}; - std::vector nodes_rank1{5, 6}; + const std::vector nodes_rank0{2, 3, 4}; + const std::vector nodes_rank1{5, 6}; tec_r.modify_rank(0, nodes_rank0); tec_r.modify_rank(0, nodes_rank0); - bool planar = check_planarity(tec_r); + const bool planar = check_planarity(tec_r); CHECK(planar == 1); } @@ -94,13 +96,13 @@ TEST_CASE("Check non-planarity technology network", "[check-planarity]") extended_rank_view tec_r(tec); - std::vector nodes_rank0{2, 3, 4}; - std::vector nodes_rank1{5, 6}; + const std::vector nodes_rank0{2, 3, 4}; + const std::vector nodes_rank1{5, 6}; tec_r.modify_rank(0, nodes_rank0); tec_r.modify_rank(0, nodes_rank0); - bool planar = check_planarity(tec_r); + const bool planar = check_planarity(tec_r); CHECK(planar == 0); } diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index e640d946d..7065ab861 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -1,9 +1,8 @@ // -// Created by benjamin on 6/18/24. +// Created by benjamin on 18.06.24. // #include -#include #include #include @@ -85,11 +84,11 @@ TEST_CASE("Check modify ranks", "[extended-rank-view]") network_balancing_params ps; ps.unify_outputs = true; - auto tec_balanced = network_balancing(tec, ps); + const auto tec_balanced = network_balancing(tec, ps); auto vpi_r = extended_rank_view(tec_balanced); - std::vector nodes = {13, 10}; + const std::vector nodes = {13, 10}; vpi_r.modify_rank(2, nodes); CHECK(vpi_r.check_validity() == 1); @@ -123,10 +122,12 @@ TEMPLATE_TEST_CASE("Check equivalence checking", "[extended_rank_view]", mocktur network_balancing_params ps; ps.unify_outputs = true; - auto ntk_r = extended_rank_view(ntk); + const auto ntk_r = extended_rank_view(ntk); mockturtle::equivalence_checking_stats st; - bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(ntk, ntk_r), {}, &st); + const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(ntk, ntk_r), {}, &st); + REQUIRE(maybe_cec_m.has_value()); + const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); CHECK(ntk_r.check_validity() == 1); } @@ -169,7 +170,9 @@ TEST_CASE("Check equivalence checking for virtual PIs", "[extended-rank-view]") vpi_r.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; - bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); + const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi_r), {}, &st); + REQUIRE(maybe_cec_m.has_value()); + const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); CHECK(vpi_r.check_validity() == 1); } diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index 04689091b..e67bae1c9 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -1,5 +1,5 @@ // -// Created by benjamin on 6/17/24. +// Created by benjamin on 14.06.24. // #include @@ -81,7 +81,9 @@ TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]") CHECK(vpi.size() == tec.size()); mockturtle::equivalence_checking_stats st; - bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); + const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); + REQUIRE(maybe_cec_m.has_value()); + const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); } @@ -131,6 +133,8 @@ TEST_CASE("Remove PIs and check equivalence copy constructor", "[virtual-pi-view CHECK(vpi.size() - 2 == tec.size()); // the -2 is due to the buffers mockturtle::equivalence_checking_stats st; - bool cec_m = *mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); + const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); + REQUIRE(maybe_cec_m.has_value()); + const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); } From 08d6212400c7389fb2f17c1311427199b28f46de Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 30 Jul 2024 15:47:27 +0000 Subject: [PATCH 30/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/fiction/networks/views/extended_rank_view.hpp | 4 ++-- include/fiction/networks/virtual_pi_network.hpp | 4 ++-- .../node_duplication_planarization.cpp | 9 ++++++--- test/networks/views/extended_rank_view.cpp | 6 ++++-- test/networks/virtual_pi_network.cpp | 6 ++++-- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index 27bb6cb16..23b2aa992 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -24,8 +24,8 @@ * * Provides a view with node ranks for given networks. It adds functionalities to modify ranks. Most importantly, the * new `init_ranks()` function allows an array of nodes to be provided, which sets the levels and ranks of the nodes in - * the network. Additionally, the `modify_rank()` function allows a vector to be passed to a rank, assigning the ranks at - * this level. + * the network. Additionally, the `modify_rank()` function allows a vector to be passed to a rank, assigning the ranks + * at this level. * */ template #include @@ -16,8 +16,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index 7f249b24b..c61df2b16 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -47,7 +47,8 @@ TEST_CASE("2-ary nodes Test", "[node-duplication-planarization]") planarized_maj.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); + const auto maybe_cec_m = + mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); REQUIRE(maybe_cec_m.has_value()); const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); @@ -88,7 +89,8 @@ TEST_CASE("3-ary nodes Test", "[node-duplication-planarization]") planarized_maj.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); + const auto maybe_cec_m = + mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); REQUIRE(maybe_cec_m.has_value()); const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); @@ -129,7 +131,8 @@ TEST_CASE("Aig Test", "[node-duplication-planarization]") planarized_maj.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(aig, planarized_maj), {}, &st); + const auto maybe_cec_m = + mockturtle::equivalence_checking(*mockturtle::miter(aig, planarized_maj), {}, &st); REQUIRE(maybe_cec_m.has_value()); const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index 7065ab861..ed28034cb 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -125,7 +125,8 @@ TEMPLATE_TEST_CASE("Check equivalence checking", "[extended_rank_view]", mocktur const auto ntk_r = extended_rank_view(ntk); mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(ntk, ntk_r), {}, &st); + const auto maybe_cec_m = + mockturtle::equivalence_checking(*mockturtle::miter(ntk, ntk_r), {}, &st); REQUIRE(maybe_cec_m.has_value()); const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); @@ -170,7 +171,8 @@ TEST_CASE("Check equivalence checking for virtual PIs", "[extended-rank-view]") vpi_r.remove_virtual_input_nodes(); mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi_r), {}, &st); + const auto maybe_cec_m = + mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi_r), {}, &st); REQUIRE(maybe_cec_m.has_value()); const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index e67bae1c9..983033200 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -81,7 +81,8 @@ TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]") CHECK(vpi.size() == tec.size()); mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); + const auto maybe_cec_m = + mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); REQUIRE(maybe_cec_m.has_value()); const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); @@ -133,7 +134,8 @@ TEST_CASE("Remove PIs and check equivalence copy constructor", "[virtual-pi-view CHECK(vpi.size() - 2 == tec.size()); // the -2 is due to the buffers mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); + const auto maybe_cec_m = + mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); REQUIRE(maybe_cec_m.has_value()); const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); From 20da9f73345ee3fcd9d2657859eea35a2ab31561 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 30 Jul 2024 15:48:19 +0000 Subject: [PATCH 31/84] :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions --- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 279 ++++++++++++++++++ 1 file changed, 279 insertions(+) diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index 022f146b1..f1ebb717a 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -23,6 +23,37 @@ #endif +static const char *__doc_extended_rank_view = +R"doc(@class extended_rank_view (specialization) + +A derived class from depth_view.)doc"; + +static const char *__doc_extended_rank_view_2 = +R"doc(Deduction guide for `extended_rank_view' + +This template helps to deduce the type argument `T` for the +`extended_rank_view` class when constructed with an argument of type +`T`. + +Template parameter ``T``: + Network type deduced from the construction context of + `extended_rank_view`.)doc"; + +static const char *__doc_extended_rank_view_3 = +R"doc(Deduction guide for `extended_rank_view` with two constructor +arguments + +This template helps to deduce the type argument `T` for the +`extended_rank_view` class when constructed with two arguments: a +network of type `T`, and a `vector` of `vector` containing network +nodes. + +Template parameter ``T``: + Network type deduced from the construction context of + `extended_rank_view`.)doc"; + +static const char *__doc_extended_rank_view_extended_rank_view = R"doc()doc"; + static const char *__doc_fiction_a_star = R"doc(The A* path finding algorithm for shortest loop-less paths between a given source and target coordinate in a layout. This function @@ -1886,6 +1917,46 @@ Parameter ``cs``: Returns: Integer representing the SiDB's charge state.)doc"; +static const char *__doc_fiction_check_planarity = +R"doc(Checks if a logic network is planar. To perform this check, the +network must have ranks assigned. + +If the network is not balanced, an exception is thrown. To balance the +network, insert buffers to divide multi-level edges. + +Template parameter ``Ntk``: + Logic network type. + +Parameter ``ntk``: + The logic network to check for planarity. + +Returns: + `true` if the network is planar, `false` otherwise. + +Throws: + std::runtime_error if the network is not balanced.)doc"; + +static const char *__doc_fiction_check_planarity_impl = R"doc()doc"; + +static const char *__doc_fiction_check_planarity_impl_check_planarity_impl = R"doc()doc"; + +static const char *__doc_fiction_check_planarity_impl_ntk = R"doc()doc"; + +static const char *__doc_fiction_check_planarity_impl_run = +R"doc(Checks if a given network is planar. + +This function checks if the network represented by the variable `ntk` +is planar. The network is planar if for any edge with starting point m +and endpoint n (represented by the node ranks), there is never another +edge with starting point m_ > m and endpoint n_ < n, or vice versa. +When iterating through the ranks of one level, the endpoints are +always increasing. Therefore, only the starting points need to be +checked. Thus, the highest connected starting point in the fan-in +gives a border m_max for every subsequent edge. + +Returns: + `true` if the network is planar, `false` otherwise.)doc"; + static const char *__doc_fiction_check_simulation_results_for_equivalence = R"doc(This function compares two SiDB simulation results for equivalence. Two results are considered equivalent if they have the same number of @@ -3772,6 +3843,23 @@ Parameter ``to_delete``: Returns: A 2D vector representing the calculated offset matrix.)doc"; +static const char *__doc_fiction_detail_calculate_pairs = +R"doc(Calculates pairs of nodes from a given vector of nodes. + +This function takes a vector of nodes and returns a vector of node +pairs. Each node pair consists of two nodes from the input vector and +an optional vector of middle nodes. The delay of each node pair is +initialized to infinity. + +Template parameter ``Ntk``: + The network type. + +Parameter ``nodes``: + The vector of nodes. + +Returns: + The vector of node pairs.)doc"; + static const char *__doc_fiction_detail_color_routing_impl = R"doc()doc"; static const char *__doc_fiction_detail_color_routing_impl_color_routing_impl = R"doc()doc"; @@ -5717,6 +5805,125 @@ static const char *__doc_fiction_detail_network_balancing_impl_ps = R"doc()doc"; static const char *__doc_fiction_detail_network_balancing_impl_run = R"doc()doc"; +static const char *__doc_fiction_detail_node_duplication_planarization_impl = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_check_final_level = +R"doc(Checks if the given vector of nodes contains any non-primary inputs. + +This function iterates through each node in the vector and checks if +it is a primary input. If a non-primary input is found, the +`f_final_level` parameter is set to false and the loop is exited. + +Parameter ``v_next_level``: + The vector of nodes to be checked + +Parameter ``f_final_level``: + A reference to a boolean indicating if the vector contains only + primary inputs)doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_compute_node_order_next_level = +R"doc(Computes the order of nodes in the next level based on delay + +Parameter ``next_level``: + The vector to store the nodes in the next level + +This function computes the order of nodes in the next level based on +their delay in the H-graph of the level. It selects the path with the +least delay from the current level pairs and follows it via fanin +relations. The nodes are inserted into the next level vector in the +order they are encountered.)doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_compute_slice_delays = +R"doc(Computes the delay in a given slice (each possible order of +node_pairs) of an H-graph + +Parameter ``nd``: + Node in the H-graph + +Parameter ``border_pis``: + A boolean indicating whether the input PIs (Primary Inputs) should + be propagated to the next level + +This function iterates over the fanins of the given node and computes +the delay for all possible orders of these nodes that form a +node_pair. The delay computation depends on the node's connections and +position within the graph. If there is a connection between two +node_pairs, the delay is incremented by 1. If not, the delay is +incremented by 2. Default delay for the first node is 1. If a +node_pair doesn't have a connection and its delay (when increased by +two) is less than the existing delay, then this node_pair's delay is +updated. + +The processed node_pairs are pushed back to the 'lvl_pairs' data +member for subsequent delay calculations. + +Throws: + std::runtime_error if no combinations (possible node_pairs) are + found, which might suggest a dangling node)doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_insert_if_unique = +R"doc(Inserts a node into a vector if it is unique + +This function inserts a node into a vector only if the vector is empty +or the node is not equal to the first element of the vector. If the +vector is not empty and the node is equal to the first element, it +does nothing. + +Template parameter ``Ntk``: + The network type + +Parameter ``node``: + The node to be inserted + +Parameter ``vec``: + The vector to insert the node into)doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_lvl_pairs = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_node_duplication_planarization_impl = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_ntk = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_ps = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_run = R"doc()doc"; + +static const char *__doc_fiction_detail_node_pair = +R"doc(A structure representing a pair of nodes in an H-graph + +Template parameter ``Ntk``: + Network type for the nodes in the pair + +The nodes stored in this struct describe the fanin-edges of a node in +an H-graph. A node pair object holds two nodes, which are saved in the +member 'pair'. These two outer nodes are connected through zero or +more 'middle_nodes'. The fanin order starts with the first node in +'pair', then proceeds through the 'middle_nodes', and ends with the +second node in 'pair'. The order of 'middle_nodes' is arbitrary as +they cannot be further connected to any other nodes. For the +planarization, only the nodes inside the 'pair' are relevant. + +@note The edges connecting to the nodes in 'pair' effectively block +the 'middle_nodes'.)doc"; + +static const char *__doc_fiction_detail_node_pair_delay = R"doc(Specifies the delay value for the node)doc"; + +static const char *__doc_fiction_detail_node_pair_fanin_pair = +R"doc(Shared pointer to another instance of node_pair detailing fanin-edge +alignment)doc"; + +static const char *__doc_fiction_detail_node_pair_node_pair = +R"doc(node_pair constructor + +Parameter ``node1``: + The first node of the fanin-edged node + +Parameter ``node2``: + The second node of the fanin-edged node + +Parameter ``delayValue``: + The delay value for the node)doc"; + static const char *__doc_fiction_detail_operational_domain_impl = R"doc()doc"; static const char *__doc_fiction_detail_operational_domain_impl_contour_tracing = @@ -11731,6 +11938,49 @@ Parameter ``file``: Parameter ``rfun``: The actual parsing function.)doc"; +static const char *__doc_fiction_node_duplication_params = R"doc(Parameters for the node duplication algorithm.)doc"; + +static const char *__doc_fiction_node_duplication_params_random_output_order = +R"doc(The output order determines the starting layer for this algorithm. If +this option is turned off, the output order remains the same as in the +provided network. If it is turned on, the outputs are ordered +randomly.)doc"; + +static const char *__doc_fiction_node_duplication_planarization = +R"doc(Implements a planarization mechanism for networks using a H-Graph +strategy for node duplication. + +Template parameter ``NtkDest``: + Destination network type + +Template parameter ``NtkSrc``: + Source network type + +Parameter ``ntk_src``: + Source network to be utilized for the planarization + +Parameter ``ps``: + Node duplication parameters used in the computation + +The planarization achieved by this function solves the Node +Duplication Crossing Minimization (NDCE) problem by finding the +shortest x-y path in the H-graph for every level in the network. An +H-graph describes edge relations between two levels in a network, with +one level assumed as fixed, starting at the Primary Outputs (POs). By +finding the shortest path from the source (x) to the sink (y) in this +H-graph, an optimal solution for the NDCE problem is found. The +function constructs an H-graph that captures edge relations between +two levels within the graph and computes the shortest x-y paths on the +H-graph, traversing from the POs towards the Primary Inputs (PIs). + +Returns: + A view of the planarized virtual_pi_network created in the format + of extended_rank_view + +Throws: + std::runtime_error if input network not balanced, if no node + combinations are found or if the created network is non-planar)doc"; + static const char *__doc_fiction_normalize_layout_coordinates = R"doc(A new layout is constructed and returned that is equivalent to the given cell-level layout. However, its coordinates are normalized, @@ -15449,6 +15699,35 @@ static const char *__doc_fiction_vertical_shift_cartesian = R"doc(\verbatim +-------+ | | | +-------+ | | | +-------+ | | | +-------+ \endverbatim)doc"; +static const char *__doc_fiction_virtual_pi_network = +R"doc(!Network with additional "virtual" PIs. + +"Virtual" PIs (Primary Inputs) are used to manage the duplication of +PIs in the network. Each "real" PI can have an arbitrary number of +"virtual" PIs, which are copies of the original "real" PI. A "virtual" +PI can be created by duplicating a "real" PI. To keep track of this +relationship, there is a mapping of each "virtual" PI to its +corresponding "real" PI in the network.)doc"; + +static const char *__doc_fiction_virtual_pi_network_map = R"doc(Map from virtual_pis to real_pis.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network = +R"doc(A default constructor for the `virtual_pi_network` class. + +This constructor initializes `virtual_inputs` with a shared pointer to +an empty std::vector of uint32_t.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_2 = +R"doc(A parameterized constructor for the `virtual_pi_network` class. + +This constructor creates a `virtual_pi_network` using the `other` +`technology_network` and initializes `virtual_inputs` with a shared +pointer to an empty std::vector of uint32_t. + +Parameter ``other``: + A `technology_network` object to create an instance of + `virtual_pi_network`.)doc"; + static const char *__doc_fiction_volume = R"doc(Computes the volume of a given coordinate assuming its origin is (0, 0, 0). Calculates :math:`(|x| + 1) \cdot (|y| + 1) \cdot (|z| + 1)` by From 7e501a61004636bb9a2e43cc95b5147ab84bc30b Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 31 Jul 2024 16:11:48 +0200 Subject: [PATCH 32/84] :heavy_plus_sign: refactored virtual_pi_network.hpp and added virtual_miter.hpp for equivalence checking --- .../algorithms/verification/virtual_miter.hpp | 117 ++++++++ .../fiction/networks/virtual_pi_network.hpp | 263 ++++-------------- include/fiction/traits.hpp | 27 ++ test/networks/virtual_pi_network.cpp | 113 ++++++-- 4 files changed, 290 insertions(+), 230 deletions(-) create mode 100644 include/fiction/algorithms/verification/virtual_miter.hpp diff --git a/include/fiction/algorithms/verification/virtual_miter.hpp b/include/fiction/algorithms/verification/virtual_miter.hpp new file mode 100644 index 000000000..46b993d68 --- /dev/null +++ b/include/fiction/algorithms/verification/virtual_miter.hpp @@ -0,0 +1,117 @@ +// +// Created by benjamin on 7/31/24. +// + +#ifndef FICTION_VIRTUAL_MITER_HPP +#define FICTION_VIRTUAL_MITER_HPP + +#include +#include + +#include +#include + +#include "fiction/networks/virtual_pi_network.hpp" + +namespace fiction +{ + +/*! \brief Creates a combinational miter from two networks. + * + * This method combines two networks that have the same number of primary + * inputs and the same number of primary outputs into a miter. The miter + * has the same number of inputs and one primary output. This output is the + * OR of XORs of all primary output pairs. In other words, the miter outputs + * 1 for all input assignments in which the two input networks differ. + * + * All networks may have different types. The method returns an optional, which + * is `nullopt`, whenever the two input networks don't match in their number of + * primary inputs and primary outputs. + */ +template +std::optional miter( NtkSource1 const& ntk1, NtkSource2 const& ntk2 ) +{ + static_assert( mockturtle::is_network_type_v, "NtkSource1 is not a network type" ); + static_assert( mockturtle::is_network_type_v, "NtkSource2 is not a network type" ); + static_assert( mockturtle::is_network_type_v, "NtkDest is not a network type" ); + + static_assert( mockturtle::has_num_pis_v, "NtkSource1 does not implement the num_pis method" ); + static_assert( mockturtle::has_num_pos_v, "NtkSource1 does not implement the num_pos method" ); + static_assert( mockturtle::has_num_pis_v, "NtkSource2 does not implement the num_pis method" ); + static_assert( mockturtle::has_num_pos_v, "NtkSource2 does not implement the num_pos method" ); + static_assert( mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method" ); + static_assert( mockturtle::has_create_po_v, "NtkDest does not implement the create_po method" ); + static_assert( mockturtle::has_create_xor_v, "NtkDest does not implement the create_xor method" ); + static_assert( mockturtle::has_create_nary_or_v, "NtkDest does not implement the create_nary_or method" ); + + auto num_pis1 = ntk1.num_pis(); + auto num_pis2 = ntk2.num_pis(); + if constexpr (has_num_real_pis_v) + { + num_pis1 = ntk1.num_real_pis(); + } + if constexpr (has_num_real_pis_v) + { + num_pis2 = ntk2.num_real_pis(); + } + /* both networks must have same number of inputs and outputs */ + if ( ( num_pis1 != num_pis2 ) || ( ntk1.num_pos() != ntk2.num_pos() ) ) + { + return std::nullopt; + } + + /* create primary inputs */ + NtkDest dest; + std::vector> pis; + for ( auto i = 0u; i < num_pis1; ++i ) + { + pis.push_back( dest.create_pi() ); + } + + std::shared_ptr ntk1_copy; + if constexpr (has_remove_virtual_input_nodes_v) { + ntk1_copy = std::make_shared(ntk1); + ntk1_copy->remove_virtual_input_nodes(); + } + else { + ntk1_copy = std::make_shared(ntk1); // You may need const_cast here to remove the constness + } + + std::shared_ptr ntk2_copy; + if constexpr (has_remove_virtual_input_nodes_v) { + ntk2_copy = std::make_shared(ntk2); + ntk2_copy->remove_virtual_input_nodes(); + } + else { + ntk2_copy = std::make_shared(ntk2); // You may need const_cast here to remove the constness + } + + /* copy networks */ + const auto pos1 = mockturtle::cleanup_dangling( *ntk1_copy, dest, pis.begin(), pis.end() ); + const auto pos2 = mockturtle::cleanup_dangling( *ntk2_copy, dest, pis.begin(), pis.end() ); + + if constexpr ( mockturtle::has_EXODC_interface_v ) + { + ntk1_copy->build_oe_miter( dest, pos1, pos2 ); + return dest; + } + if constexpr ( mockturtle::has_EXODC_interface_v ) + { + ntk2_copy->build_oe_miter( dest, pos1, pos2 ); + return dest; + } + + /* create XOR of output pairs */ + std::vector> xor_outputs; + std::transform( pos1.begin(), pos1.end(), pos2.begin(), std::back_inserter( xor_outputs ), + [&]( auto const& o1, auto const& o2 ) { return dest.create_xor( o1, o2 ); } ); + + /* create big OR of XOR gates */ + dest.create_po( dest.create_nary_or( xor_outputs ) ); + + return dest; +} + +} // namespace mockturtle + +#endif // FICTION_VIRTUAL_MITER_HPP diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 6eb284f66..39b38864b 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -5,18 +5,18 @@ #ifndef FICTION_VIRTUAL_PI_NETWORK_HPP #define FICTION_VIRTUAL_PI_NETWORK_HPP -#include "fiction/networks/technology_network.hpp" #include "fiction/types.hpp" #include -#include #include +#include #include #include #include #include #include +#include #include #include #include @@ -33,11 +33,13 @@ namespace fiction * To keep track of this relationship, there is a mapping of each "virtual" PI to its corresponding "real" PI in the * network. */ -class virtual_pi_network : public technology_network +template +class virtual_pi_network : public Ntk { public: - using node = typename technology_network::node; - using signal = typename technology_network::signal; + using storage = typename Ntk::storage; + using node = typename Ntk::node; + using signal = typename Ntk::signal; public: /** @@ -46,20 +48,18 @@ class virtual_pi_network : public technology_network * This constructor initializes `virtual_inputs` with a shared pointer to an empty * std::vector of uint32_t. */ - explicit virtual_pi_network() : virtual_inputs(std::make_shared>()) {} + explicit virtual_pi_network() : virtual_inputs(std::make_shared>()) {} /** - * A parameterized constructor for the `virtual_pi_network` class. - * - * This constructor creates a `virtual_pi_network` using the `other` `technology_network` - * and initializes `virtual_inputs` with a shared pointer to an empty std::vector of uint32_t. + * A default constructor for the `virtual_pi_network` class. * - * @param other A `technology_network` object to create an instance of `virtual_pi_network`. + * This constructor initializes `virtual_inputs` with a shared pointer to an empty + * std::vector of uint32_t. */ - explicit virtual_pi_network(const technology_network& other) : - virtual_inputs(std::make_shared>()) + explicit virtual_pi_network(const Ntk& ntk) : + Ntk(ntk.clone()), + virtual_inputs(std::make_shared>()) { - _storage = std::make_shared(*(other._storage)); // create deep copy of storage } /** @@ -127,7 +127,6 @@ class virtual_pi_network : public technology_network * collects the fanin data for a node and matches them in the virtual_pi_network. * */ - template explicit virtual_pi_network(Ntk& ntk, std::vector>>& ntk_lvls, std::vector>>& ntk_lvls_new) { @@ -284,26 +283,6 @@ class virtual_pi_network : public technology_network *this = ntk_dest_v; } - /** - * @brief Reimplementation of num_gates(). Retrieves the number of gates in the virtual_pi_network. - * - * @return The number of gates in the virtual_pi_network. - */ - auto num_gates() const - { - return static_cast(_storage->nodes.size() - virtual_inputs->size() - _storage->inputs.size() - 2); - } - - /** - * @brief Reimplementation of size(). Get the size of the virtual_pi_network. - * - * @return The size of the virtual_pi_network as a uint32_t. - */ - auto size() const - { - return static_cast(_storage->nodes.size()); - } - /** * \brief Calculate the real size of the virtual_pi_network. * @@ -312,9 +291,9 @@ class virtual_pi_network : public technology_network * * \return The real size of the virtual_pi_network as a uint32_t. */ - [[nodiscard]] auto size_real() const + [[nodiscard]] auto real_size() const { - return static_cast(_storage->nodes.size() - virtual_inputs->size()); + return static_cast(Ntk::size() - virtual_inputs->size()); } /** @@ -327,28 +306,12 @@ class virtual_pi_network : public technology_network * @param real_pi The node representing the real PI in the network. * @return The index of the newly created virtual PI. */ - signal create_virtual_pi(const node& real_pi) + signal create_virtual_pi(const signal& real_pi) { - const auto index = _storage->nodes.size(); - _storage->nodes.emplace_back(); - virtual_inputs->emplace_back(index); - _storage->nodes[index].data[1].h1 = 2; - map.emplace_back(index, real_pi); - return index; - } - - /** - * @brief Reimplementation of is_pi(). Check if a given node is a primary input (PI) in the virtual_pi_network. - * - * A node is considered a PI if it exists in the virtual_inputs vector or the inputs vector of the _storage object. - * - * @param n The node to check. - * @return True if the node is a PI, false otherwise. - */ - [[nodiscard]] bool is_pi(node const& n) const - { - return std::find(virtual_inputs->cbegin(), virtual_inputs->cend(), n) != virtual_inputs->cend() || - std::find(_storage->inputs.cbegin(), _storage->inputs.cend(), n) != _storage->inputs.cend(); + signal s = Ntk::create_pi(); + virtual_inputs->emplace_back(s); + map.emplace_back(s, real_pi); + return s; } /** @@ -359,7 +322,7 @@ class virtual_pi_network : public technology_network * @param n The node to check. * @return True if the node is a virtual PI, false otherwise. */ - [[nodiscard]] bool is_pi_virtual(node const& n) const + [[nodiscard]] bool is_virtual_pi(node const& n) const { return std::find(virtual_inputs->cbegin(), virtual_inputs->cend(), n) != virtual_inputs->cend(); } @@ -372,24 +335,9 @@ class virtual_pi_network : public technology_network * @param n The node to check. * @return True if the node is a real PI, false otherwise. */ - [[nodiscard]] bool is_pi_real(node const& n) const + [[nodiscard]] bool is_real_pi(node const& n) const { - return std::find(_storage->inputs.cbegin(), _storage->inputs.cend(), n) != _storage->inputs.cend(); - } - - /** - * Check if a node is a const input in the virtual_pi_network. - * - * A node is considered a const input if it exists in the virtual_inputs vector or the inputs vector of the _storage - * object. - * - * @param n The node to check. - * @return True if the node is a const input, false otherwise. - */ - [[nodiscard]] bool is_ci(node const& n) const - { - return std::find(virtual_inputs->cbegin(), virtual_inputs->cend(), n) != virtual_inputs->cend() || - std::find(_storage->inputs.cbegin(), _storage->inputs.cend(), n) != _storage->inputs.cend(); + return (Ntk::is_pi(n) && !is_virtual_pi(n)); } /** @@ -400,7 +348,7 @@ class virtual_pi_network : public technology_network * @param n The node to check. * @return True if the node is a virtual CI, false otherwise. */ - [[nodiscard]] bool is_ci_virtual(node const& n) const + [[nodiscard]] bool is_virtual_ci(node const& n) const { return std::find(virtual_inputs->cbegin(), virtual_inputs->cend(), n) != virtual_inputs->cend(); } @@ -413,22 +361,9 @@ class virtual_pi_network : public technology_network * @param n The node to check. * @return True if the node is a real CI, false otherwise. */ - [[nodiscard]] bool is_ci_real(node const& n) const - { - return std::find(_storage->inputs.cbegin(), _storage->inputs.cend(), n) != _storage->inputs.cend(); - } - - /** - * @brief Retrieve the number of combinatorial inputs (CIs) in the virtual_pi_network. - * - * The num_cis() function returns the total number of CIs in the virtual_pi_network. - * It includes both virtual constant inputs and real constant inputs. - * - * @return The number of CIs as a uint32_t. - */ - [[nodiscard]] auto num_cis() const + [[nodiscard]] bool is_real_ci(node const& n) const { - return static_cast(_storage->inputs.size() + virtual_inputs->size()); + return (Ntk::is_ci(n) && !is_virtual_ci(n)); } /** @@ -439,7 +374,7 @@ class virtual_pi_network : public technology_network * * @return The number of virtual CIs as a uint32_t. */ - [[nodiscard]] auto num_cis_virtual() const + [[nodiscard]] auto num_virtual_cis() const { return static_cast(virtual_inputs->size()); } @@ -452,22 +387,9 @@ class virtual_pi_network : public technology_network * * @return The number of real CIs as a uint32_t. */ - [[nodiscard]] auto num_cis_real() const - { - return static_cast(_storage->inputs.size()); - } - - /** - * @brief Reimplementation of num_pis(). Get the number of primary inputs (PIs) in the virtual_pi_network. - * - * The num_pis() function returns the total number of PIs in the virtual_pi_network. - * It includes both virtual PIs and real PIs. - * - * @return The number of PIs as a uint32_t. - */ - [[nodiscard]] auto num_pis() const + [[nodiscard]] auto num_real_cis() const { - return static_cast(_storage->inputs.size() + virtual_inputs->size()); + return static_cast(Ntk::num_cis()-num_virtual_cis()); } /** @@ -478,7 +400,7 @@ class virtual_pi_network : public technology_network * * @return The number of virtual PIs as a uint32_t. */ - [[nodiscard]] auto num_pis_virtual() const + [[nodiscard]] auto num_virtual_pis() const { return static_cast(virtual_inputs->size()); } @@ -491,9 +413,9 @@ class virtual_pi_network : public technology_network * * @return The number of real PIs as a uint32_t. */ - [[nodiscard]] auto num_pis_real() const + [[nodiscard]] auto num_real_pis() const { - return static_cast(_storage->inputs.size()); + return static_cast(Ntk::num_pis()-num_virtual_pis()); } /** @@ -516,22 +438,6 @@ class virtual_pi_network : public technology_network throw std::runtime_error("Error: node is not a virtual pi"); } - /** - * @brief Reimplementation of foreach_pi(). Apply a given function to each primary input in the virtual_pi_network. - * - * This function iterates over all primary inputs in the virtual_pi_network and applies the given function to each - * primary input. - * - * @tparam Fn The type of function to apply to each primary input. - * @param fn The function to apply to each primary input. - */ - template - void foreach_pi(Fn&& fn) const - { - mockturtle::detail::foreach_element(_storage->inputs.cbegin(), _storage->inputs.cend(), fn); - mockturtle::detail::foreach_element(virtual_inputs->cbegin(), virtual_inputs->cend(), fn); - } - /** * @brief Iterates over the primary inputs of the circuit and applies a given * function. @@ -543,9 +449,13 @@ class virtual_pi_network : public technology_network * @param fn The function to be applied to each primary input. */ template - void foreach_pi_real(Fn&& fn) const + void foreach_real_pi(Fn&& fn) { - mockturtle::detail::foreach_element(_storage->inputs.cbegin(), _storage->inputs.cend(), fn); + static_cast(this)->foreach_pi([&](const auto& i){ + if (!is_virtual_pi(i)) { + std::forward(fn)(i); + } + }); } /** @@ -560,29 +470,11 @@ class virtual_pi_network : public technology_network * @see mockturtle::detail::foreach_element */ template - void foreach_pi_virtual(Fn&& fn) const + void foreach_virtual_pi(Fn&& fn) const { mockturtle::detail::foreach_element(virtual_inputs->cbegin(), virtual_inputs->cend(), fn); } - /** - * @brief Applies a function to each combinatorial input. - * - * This function applies the given function to each input stored in the circuit. - * It also applies the function to each virtual input. - * The data types of the function passed to this function must be compatible - * with the data types stored in the inputs and virtual_inputs of the circuit. - * - * @tparam Fn The type of the function to apply to each input. - * @param fn The function to apply to each input. - */ - template - void foreach_ci(Fn&& fn) const - { - mockturtle::detail::foreach_element(_storage->inputs.cbegin(), _storage->inputs.cend(), fn); - mockturtle::detail::foreach_element(virtual_inputs->cbegin(), virtual_inputs->cend(), fn); - } - /** * @brief Applies a given function to each input element in the circuit * @@ -593,9 +485,13 @@ class virtual_pi_network : public technology_network * @param fn The function to be applied */ template - void foreach_ci_real(Fn&& fn) const + void foreach_real_ci(Fn&& fn) { - mockturtle::detail::foreach_element(_storage->inputs.cbegin(), _storage->inputs.cend(), fn); + static_cast(this)->foreach_ci([&](const auto& i){ + if (!is_virtual_ci(i)) { + std::forward(fn)(i); + } + }); } /** @@ -611,27 +507,11 @@ class virtual_pi_network : public technology_network * the elements in the container. */ template - void foreach_ci_virtual(Fn&& fn) const + void foreach_virtual_ci(Fn&& fn) const { mockturtle::detail::foreach_element(virtual_inputs->cbegin(), virtual_inputs->cend(), fn); } - /** - * @brief Applies a function to each gate in the circuit. - * - * This function iterates over each gate in the circuit, excluding the constants. - * - * @tparam Fn The type of the function. - * @param fn The function to apply to each gate. - */ - template - void foreach_gate(Fn&& fn) const - { - auto r = mockturtle::range(2u, _storage->nodes.size()); /* start from 2 to avoid constants */ - mockturtle::detail::foreach_element_if( - r.begin(), r.end(), [this](auto n) { return (!is_ci(n) && !is_virtual_ci(n)); }, fn); - } - /** * @brief Removes virtual input nodes from the storage. This enables equivalence checking. * @@ -646,50 +526,13 @@ class virtual_pi_network : public technology_network */ void remove_virtual_input_nodes() { - std::sort(virtual_inputs->begin(), virtual_inputs->end(), std::greater()); - for (uint32_t i : *virtual_inputs) + for (const auto &map_item : map) { - if (i < _storage->nodes.size()) - { - uint64_t new_node = 0; - for (const auto& pair : map) - { - if (pair.first == i) - { - new_node = pair.second; - break; - } - } - substitute_node(i, new_node); - // Adjust inputs - for (auto& input : _storage->inputs) - { - if (input > i) - { - --input; - } - } - // Adjust nodes vector in the technology_network _storage - for (auto j = 0u; j < _storage->nodes.size(); ++j) - { - auto& n = _storage->nodes[j]; - for (auto& child : n.children) - { - if (child.data > i) - { - --child.data; - } - } - } - // Adjust outputs - for (auto& output : _storage->outputs) - { - --output.index; - } - _storage->nodes.erase(_storage->nodes.cbegin() + i); - } + Ntk::substitute_node(Ntk::get_node(map_item.first), map_item.second); } + *this = mockturtle::cleanup_dangling(*this, 1); + // Clear virtual_inputs after using it virtual_inputs->clear(); map.clear(); @@ -699,11 +542,11 @@ class virtual_pi_network : public technology_network /** * Shared pointer vector storage for virtual_inputs. */ - std::shared_ptr> virtual_inputs; + std::shared_ptr> virtual_inputs; /** * Map from virtual_pis to real_pis. */ - std::vector> map; + std::vector> map; }; } // namespace fiction diff --git a/include/fiction/traits.hpp b/include/fiction/traits.hpp index deea30ad5..59274c4fe 100644 --- a/include/fiction/traits.hpp +++ b/include/fiction/traits.hpp @@ -1228,6 +1228,33 @@ template inline constexpr bool has_is_and_xor_v = has_is_and_xor::value; #pragma endregion +#pragma region has_num_real_pis +template +struct has_num_real_pis : std::false_type +{}; + +template +struct has_num_real_pis().num_real_pis())>> + : std::true_type +{}; + +template +inline constexpr bool has_num_real_pis_v = has_num_real_pis::value; +#pragma endregion + +#pragma region has_remove_virtual_input_nodes +template +struct has_remove_virtual_input_nodes : std::false_type +{}; + +template +struct has_remove_virtual_input_nodes().remove_virtual_input_nodes())>> + : std::true_type +{}; + +template +inline constexpr bool has_remove_virtual_input_nodes_v = has_remove_virtual_input_nodes::value; +#pragma endregion } // namespace fiction #endif // FICTION_TRAITS_HPP diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index 983033200..d17a4538c 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -3,17 +3,19 @@ // #include +#include +#include #include #include #include -#include -#include +#include +#include using namespace fiction; -TEST_CASE("Copy network and size consistency", "[virtual-pi-view]") +TEST_CASE("Copy technology network and size consistency", "[virtual-pi-view]") { technology_network tec{}; @@ -37,19 +39,53 @@ TEST_CASE("Copy network and size consistency", "[virtual-pi-view]") // virtual_pi_network is a deep copy. THe original network won't be affected by any changes after the copy CHECK(tec.size() == 5); // This is the size disregarding virtual PIs. So this would correspond to the size in a normal technology_network - CHECK(vpi.size_real() == 7); + CHECK(vpi.real_size() == 7); // This is the size with the virtual PIs CHECK(vpi.size() == 9); vpi.remove_virtual_input_nodes(); // After removing/remapping the virtual PIs to their real PIs the sizes are equal - CHECK(vpi.size_real() == vpi.size()); + CHECK(vpi.real_size() == vpi.size()); CHECK(vpi.size() == 7); } -TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]") +TEMPLATE_TEST_CASE("Copy networks and size consistency", "[virtual-pi-view]", mockturtle::aig_network, + mockturtle::xag_network) { - technology_network tec{}; - virtual_pi_network vpi{}; + TestType ntk{}; + + const auto a = ntk.create_pi(); + const auto b = ntk.create_pi(); + + const auto f1 = ntk.create_and(a, b); + + virtual_pi_network vpi{ntk}; + + const auto c = vpi.create_virtual_pi(a); + const auto d = vpi.create_virtual_pi(b); + + const auto f2 = vpi.create_and(b, c); + const auto f3 = vpi.create_or(a, d); + + vpi.create_po(f1); + vpi.create_po(f2); + vpi.create_po(f3); + + // virtual_pi_network is a deep copy. THe original network won't be affected by any changes after the copy + CHECK(ntk.size() == 4); + // This is the size disregarding virtual PIs. So this would correspond to the size in a normal technology_network + CHECK(vpi.real_size() == 6); + // This is the size with the virtual PIs + CHECK(vpi.size() == 8); + vpi.remove_virtual_input_nodes(); + // After removing/remapping the virtual PIs to their real PIs the sizes are equal + CHECK(vpi.real_size() == vpi.size()); + CHECK(vpi.size() == 6); +} + +TEST_CASE("Remove PIs from technology network and check equivalence", "[virtual-pi-view]") +{ + technology_network tec{}; + virtual_pi_network vpi{}; const auto a = vpi.create_pi(); const auto b = vpi.create_pi(); @@ -77,18 +113,57 @@ TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]") tec.create_po(f3_t); vpi.remove_virtual_input_nodes(); - CHECK(vpi.size_real() == vpi.size()); + CHECK(vpi.real_size() == vpi.size()); + CHECK(vpi.size() == tec.size()); + + mockturtle::equivalence_checking_stats st; + const auto maybe_cec_m = mockturtle::equivalence_checking(*fiction::miter(tec, vpi), {}, &st); + REQUIRE(maybe_cec_m.has_value()); + CHECK(*maybe_cec_m == 1); +} + +TEMPLATE_TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]", mockturtle::aig_network, + mockturtle::xag_network) +{ + TestType tec{}; + virtual_pi_network vpi{}; + + const auto a = vpi.create_pi(); + const auto b = vpi.create_pi(); + + const auto a_t = tec.create_pi(); + const auto b_t = tec.create_pi(); + + const auto c = vpi.create_virtual_pi(a); + const auto d = vpi.create_virtual_pi(b); + + const auto f1 = vpi.create_and(a, b); + const auto f2 = vpi.create_and(b, c); + const auto f3 = vpi.create_and(a, d); + + const auto f1_t = tec.create_and(a_t, b); + const auto f2_t = tec.create_and(b_t, a_t); + const auto f3_t = tec.create_and(a_t, b_t); + + vpi.create_po(f1); + vpi.create_po(f2); + vpi.create_po(f3); + + tec.create_po(f1_t); + tec.create_po(f2_t); + tec.create_po(f3_t); + + vpi.remove_virtual_input_nodes(); + CHECK(vpi.real_size() == vpi.size()); CHECK(vpi.size() == tec.size()); mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = - mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); + const auto maybe_cec_m = mockturtle::equivalence_checking(*fiction::miter(tec, vpi), {}, &st); REQUIRE(maybe_cec_m.has_value()); - const bool cec_m = *maybe_cec_m; - CHECK(cec_m == 1); + CHECK(*maybe_cec_m == 1); } -TEST_CASE("Remove PIs and check equivalence copy constructor", "[virtual-pi-view]") +TEST_CASE("Remove PIs and check equivalence with different sizes", "[virtual-pi-view]") { technology_network tec{}; @@ -104,7 +179,7 @@ TEST_CASE("Remove PIs and check equivalence copy constructor", "[virtual-pi-view tec.create_po(f2); tec.create_po(f3); - virtual_pi_network vpi{}; + virtual_pi_network vpi{}; const auto a = vpi.create_pi(); const auto b = vpi.create_pi(); @@ -130,13 +205,11 @@ TEST_CASE("Remove PIs and check equivalence copy constructor", "[virtual-pi-view vpi.create_po(f14); vpi.remove_virtual_input_nodes(); - CHECK(vpi.size_real() == vpi.size()); + CHECK(vpi.real_size() == vpi.size()); CHECK(vpi.size() - 2 == tec.size()); // the -2 is due to the buffers mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = - mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi), {}, &st); + const auto maybe_cec_m = mockturtle::equivalence_checking(*fiction::miter(tec, vpi), {}, &st); REQUIRE(maybe_cec_m.has_value()); - const bool cec_m = *maybe_cec_m; - CHECK(cec_m == 1); + CHECK(*maybe_cec_m == 1); } From a2cab373b58660f3b9e2df7e651bd256b9259bbb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 14:12:46 +0000 Subject: [PATCH 33/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../algorithms/verification/virtual_miter.hpp | 80 ++++++++++--------- .../fiction/networks/virtual_pi_network.hpp | 39 +++++---- include/fiction/traits.hpp | 3 +- test/networks/virtual_pi_network.cpp | 2 +- 4 files changed, 66 insertions(+), 58 deletions(-) diff --git a/include/fiction/algorithms/verification/virtual_miter.hpp b/include/fiction/algorithms/verification/virtual_miter.hpp index 46b993d68..3ec3c253a 100644 --- a/include/fiction/algorithms/verification/virtual_miter.hpp +++ b/include/fiction/algorithms/verification/virtual_miter.hpp @@ -5,13 +5,13 @@ #ifndef FICTION_VIRTUAL_MITER_HPP #define FICTION_VIRTUAL_MITER_HPP -#include -#include +#include "fiction/networks/virtual_pi_network.hpp" -#include #include +#include -#include "fiction/networks/virtual_pi_network.hpp" +#include +#include namespace fiction { @@ -28,21 +28,21 @@ namespace fiction * is `nullopt`, whenever the two input networks don't match in their number of * primary inputs and primary outputs. */ -template -std::optional miter( NtkSource1 const& ntk1, NtkSource2 const& ntk2 ) +template +std::optional miter(NtkSource1 const& ntk1, NtkSource2 const& ntk2) { - static_assert( mockturtle::is_network_type_v, "NtkSource1 is not a network type" ); - static_assert( mockturtle::is_network_type_v, "NtkSource2 is not a network type" ); - static_assert( mockturtle::is_network_type_v, "NtkDest is not a network type" ); - - static_assert( mockturtle::has_num_pis_v, "NtkSource1 does not implement the num_pis method" ); - static_assert( mockturtle::has_num_pos_v, "NtkSource1 does not implement the num_pos method" ); - static_assert( mockturtle::has_num_pis_v, "NtkSource2 does not implement the num_pis method" ); - static_assert( mockturtle::has_num_pos_v, "NtkSource2 does not implement the num_pos method" ); - static_assert( mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method" ); - static_assert( mockturtle::has_create_po_v, "NtkDest does not implement the create_po method" ); - static_assert( mockturtle::has_create_xor_v, "NtkDest does not implement the create_xor method" ); - static_assert( mockturtle::has_create_nary_or_v, "NtkDest does not implement the create_nary_or method" ); + static_assert(mockturtle::is_network_type_v, "NtkSource1 is not a network type"); + static_assert(mockturtle::is_network_type_v, "NtkSource2 is not a network type"); + static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); + + static_assert(mockturtle::has_num_pis_v, "NtkSource1 does not implement the num_pis method"); + static_assert(mockturtle::has_num_pos_v, "NtkSource1 does not implement the num_pos method"); + static_assert(mockturtle::has_num_pis_v, "NtkSource2 does not implement the num_pis method"); + static_assert(mockturtle::has_num_pos_v, "NtkSource2 does not implement the num_pos method"); + static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method"); + static_assert(mockturtle::has_create_po_v, "NtkDest does not implement the create_po method"); + static_assert(mockturtle::has_create_xor_v, "NtkDest does not implement the create_xor method"); + static_assert(mockturtle::has_create_nary_or_v, "NtkDest does not implement the create_nary_or method"); auto num_pis1 = ntk1.num_pis(); auto num_pis2 = ntk2.num_pis(); @@ -55,63 +55,67 @@ std::optional miter( NtkSource1 const& ntk1, NtkSource2 const& ntk2 ) num_pis2 = ntk2.num_real_pis(); } /* both networks must have same number of inputs and outputs */ - if ( ( num_pis1 != num_pis2 ) || ( ntk1.num_pos() != ntk2.num_pos() ) ) + if ((num_pis1 != num_pis2) || (ntk1.num_pos() != ntk2.num_pos())) { return std::nullopt; } /* create primary inputs */ - NtkDest dest; + NtkDest dest; std::vector> pis; - for ( auto i = 0u; i < num_pis1; ++i ) + for (auto i = 0u; i < num_pis1; ++i) { - pis.push_back( dest.create_pi() ); + pis.push_back(dest.create_pi()); } std::shared_ptr ntk1_copy; - if constexpr (has_remove_virtual_input_nodes_v) { + if constexpr (has_remove_virtual_input_nodes_v) + { ntk1_copy = std::make_shared(ntk1); ntk1_copy->remove_virtual_input_nodes(); } - else { - ntk1_copy = std::make_shared(ntk1); // You may need const_cast here to remove the constness + else + { + ntk1_copy = std::make_shared(ntk1); // You may need const_cast here to remove the constness } std::shared_ptr ntk2_copy; - if constexpr (has_remove_virtual_input_nodes_v) { + if constexpr (has_remove_virtual_input_nodes_v) + { ntk2_copy = std::make_shared(ntk2); ntk2_copy->remove_virtual_input_nodes(); } - else { - ntk2_copy = std::make_shared(ntk2); // You may need const_cast here to remove the constness + else + { + ntk2_copy = std::make_shared(ntk2); // You may need const_cast here to remove the constness } /* copy networks */ - const auto pos1 = mockturtle::cleanup_dangling( *ntk1_copy, dest, pis.begin(), pis.end() ); - const auto pos2 = mockturtle::cleanup_dangling( *ntk2_copy, dest, pis.begin(), pis.end() ); + const auto pos1 = mockturtle::cleanup_dangling(*ntk1_copy, dest, pis.begin(), pis.end()); + const auto pos2 = mockturtle::cleanup_dangling(*ntk2_copy, dest, pis.begin(), pis.end()); - if constexpr ( mockturtle::has_EXODC_interface_v ) + if constexpr (mockturtle::has_EXODC_interface_v) { - ntk1_copy->build_oe_miter( dest, pos1, pos2 ); + ntk1_copy->build_oe_miter(dest, pos1, pos2); return dest; } - if constexpr ( mockturtle::has_EXODC_interface_v ) + if constexpr (mockturtle::has_EXODC_interface_v) { - ntk2_copy->build_oe_miter( dest, pos1, pos2 ); + ntk2_copy->build_oe_miter(dest, pos1, pos2); return dest; } /* create XOR of output pairs */ std::vector> xor_outputs; - std::transform( pos1.begin(), pos1.end(), pos2.begin(), std::back_inserter( xor_outputs ), - [&]( auto const& o1, auto const& o2 ) { return dest.create_xor( o1, o2 ); } ); + std::transform(pos1.begin(), pos1.end(), pos2.begin(), std::back_inserter(xor_outputs), + [&](auto const& o1, auto const& o2) { return dest.create_xor(o1, o2); }); /* create big OR of XOR gates */ - dest.create_po( dest.create_nary_or( xor_outputs ) ); + dest.create_po(dest.create_nary_or(xor_outputs)); return dest; } -} // namespace mockturtle +} // namespace fiction #endif // FICTION_VIRTUAL_MITER_HPP diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 39b38864b..438463549 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -7,17 +7,17 @@ #include "fiction/types.hpp" +#include #include #include -#include #include #include #include #include #include -#include #include +#include #include #include #include @@ -59,8 +59,7 @@ class virtual_pi_network : public Ntk explicit virtual_pi_network(const Ntk& ntk) : Ntk(ntk.clone()), virtual_inputs(std::make_shared>()) - { - } + {} /** * @brief A variant of the mockturtle::initialize_copy_network. It maps old nodes not only to a single node, but to @@ -389,7 +388,7 @@ class virtual_pi_network : public Ntk */ [[nodiscard]] auto num_real_cis() const { - return static_cast(Ntk::num_cis()-num_virtual_cis()); + return static_cast(Ntk::num_cis() - num_virtual_cis()); } /** @@ -415,7 +414,7 @@ class virtual_pi_network : public Ntk */ [[nodiscard]] auto num_real_pis() const { - return static_cast(Ntk::num_pis()-num_virtual_pis()); + return static_cast(Ntk::num_pis() - num_virtual_pis()); } /** @@ -451,11 +450,14 @@ class virtual_pi_network : public Ntk template void foreach_real_pi(Fn&& fn) { - static_cast(this)->foreach_pi([&](const auto& i){ - if (!is_virtual_pi(i)) { - std::forward(fn)(i); - } - }); + static_cast(this)->foreach_pi( + [&](const auto& i) + { + if (!is_virtual_pi(i)) + { + std::forward(fn)(i); + } + }); } /** @@ -487,11 +489,14 @@ class virtual_pi_network : public Ntk template void foreach_real_ci(Fn&& fn) { - static_cast(this)->foreach_ci([&](const auto& i){ - if (!is_virtual_ci(i)) { - std::forward(fn)(i); - } - }); + static_cast(this)->foreach_ci( + [&](const auto& i) + { + if (!is_virtual_ci(i)) + { + std::forward(fn)(i); + } + }); } /** @@ -526,7 +531,7 @@ class virtual_pi_network : public Ntk */ void remove_virtual_input_nodes() { - for (const auto &map_item : map) + for (const auto& map_item : map) { Ntk::substitute_node(Ntk::get_node(map_item.first), map_item.second); } diff --git a/include/fiction/traits.hpp b/include/fiction/traits.hpp index 59274c4fe..125b3d753 100644 --- a/include/fiction/traits.hpp +++ b/include/fiction/traits.hpp @@ -1234,8 +1234,7 @@ struct has_num_real_pis : std::false_type {}; template -struct has_num_real_pis().num_real_pis())>> - : std::true_type +struct has_num_real_pis().num_real_pis())>> : std::true_type {}; template diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index d17a4538c..48ea06eb4 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -2,8 +2,8 @@ // Created by benjamin on 14.06.24. // -#include #include +#include #include #include From 7d94449eb72ea956444dec7c94da7eccf5e1c803 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 31 Jul 2024 14:14:01 +0000 Subject: [PATCH 34/84] :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions --- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index f1ebb717a..f71bd4250 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -10378,10 +10378,14 @@ static const char *__doc_fiction_has_north_east = R"doc()doc"; static const char *__doc_fiction_has_north_west = R"doc()doc"; +static const char *__doc_fiction_has_num_real_pis = R"doc()doc"; + static const char *__doc_fiction_has_ordinal_operations = R"doc()doc"; static const char *__doc_fiction_has_post_layout_optimization = R"doc()doc"; +static const char *__doc_fiction_has_remove_virtual_input_nodes = R"doc()doc"; + static const char *__doc_fiction_has_set_layout_name = R"doc()doc"; static const char *__doc_fiction_has_south = R"doc()doc"; @@ -11854,6 +11858,20 @@ static const char *__doc_fiction_missing_sidb_position_exception_missing_sidb_po static const char *__doc_fiction_missing_sidb_position_exception_where = R"doc()doc"; +static const char *__doc_fiction_miter = +R"doc(! Creates a combinational miter from two networks. + +This method combines two networks that have the same number of primary +inputs and the same number of primary outputs into a miter. The miter +has the same number of inputs and one primary output. This output is +the OR of XORs of all primary output pairs. In other words, the miter +outputs 1 for all input assignments in which the two input networks +differ. + +All networks may have different types. The method returns an optional, +which is `nullopt`, whenever the two input networks don't match in +their number of primary inputs and primary outputs.)doc"; + static const char *__doc_fiction_network_balancing = R"doc(Balances a logic network with buffer nodes that compute the identity function. For this purpose, `create_buf` is utilized. Therefore, @@ -15718,15 +15736,10 @@ This constructor initializes `virtual_inputs` with a shared pointer to an empty std::vector of uint32_t.)doc"; static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_2 = -R"doc(A parameterized constructor for the `virtual_pi_network` class. - -This constructor creates a `virtual_pi_network` using the `other` -`technology_network` and initializes `virtual_inputs` with a shared -pointer to an empty std::vector of uint32_t. +R"doc(A default constructor for the `virtual_pi_network` class. -Parameter ``other``: - A `technology_network` object to create an instance of - `virtual_pi_network`.)doc"; +This constructor initializes `virtual_inputs` with a shared pointer to +an empty std::vector of uint32_t.)doc"; static const char *__doc_fiction_volume = R"doc(Computes the volume of a given coordinate assuming its origin is (0, From 58ae758edc4037aa924c15b3c26cbe8cba243642 Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 31 Jul 2024 17:24:10 +0200 Subject: [PATCH 35/84] :art: consistency --- .../fiction/networks/virtual_pi_network.hpp | 278 ++++++++---------- 1 file changed, 120 insertions(+), 158 deletions(-) diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 39b38864b..871553692 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -7,25 +7,40 @@ #include "fiction/types.hpp" +#include #include #include -#include #include #include #include #include #include -#include #include +#include #include #include #include +#include + namespace fiction { -/*!\brief Network with additional "virtual" PIs. +template +struct virtual_storage +{ + /** + * Shared pointer vector storage for virtual_inputs. + */ + std::vector virtual_inputs; + /** + * Map from virtual_pis to real_pis. + */ + phmap::parallel_flat_hash_map map_virt_to_real_pi; +}; + +/* Network with additional "virtual" PIs. * * "Virtual" PIs (Primary Inputs) are used to manage the duplication of PIs in the network. Each "real" PI can have * an arbitrary number of "virtual" PIs, which are copies of the original "real" PI. @@ -43,47 +58,42 @@ class virtual_pi_network : public Ntk public: /** - * A default constructor for the `virtual_pi_network` class. - * - * This constructor initializes `virtual_inputs` with a shared pointer to an empty - * std::vector of uint32_t. + * Default constructor for the `virtual_pi_network` class. + * Initializes `_storage` as a shared pointer. */ - explicit virtual_pi_network() : virtual_inputs(std::make_shared>()) {} + explicit virtual_pi_network() : _storage(std::make_shared>()) {} /** - * A default constructor for the `virtual_pi_network` class. + * Copy constructor for the `virtual_pi_network` class. + * Given a network `ntk`, constructs a new `virtual_pi_network` as a clone of `ntk`. + * Initializes `_storage` as a shared pointer. * - * This constructor initializes `virtual_inputs` with a shared pointer to an empty - * std::vector of uint32_t. + * @param ntk The network to clone into this object. */ - explicit virtual_pi_network(const Ntk& ntk) : - Ntk(ntk.clone()), - virtual_inputs(std::make_shared>()) - { - } + explicit virtual_pi_network(const Ntk& ntk) : Ntk(ntk.clone()), _storage(std::make_shared>()) + {} /** - * @brief A variant of the mockturtle::initialize_copy_network. It maps old nodes not only to a single node, but to - * multiple or duplicated nodes. - * - * @tparam NtkDest Type of the destination network - * @tparam NtkSrc Type of the source network - * @param src The source network + * Variant of the mockturtle::initialize_copy_network. This function helps with creating new networks from old + * networks. In the original version `old2new` is used to map nodes from the old network to nodes in the new network + * in a one to one relation.This variant allows old nodes not only to a single node, but to multiple nodes. * - * @return A pair of the destination network and a node map from the source to the destination network. - * - * @pre NtkDest and NtkSrc must be network types (satisfy is_network_type_v). - * @pre NtkDest and NtkSrc must implement the methods get_constant, get_node, create_pi and foreach_pi (satisfy + * NtkDest and NtkSrc must be network types (satisfy is_network_type_v). + * NtkDest and NtkSrc must implement the methods get_constant, get_node, create_pi and foreach_pi (satisfy * has_get_constant_v, has_get_node_v, has_create_pi_v and has_foreach_pi_v). * - * @post A map (old2new) is created where old nodes from source network are mapped to new nodes in destination - * network. - * @post A destination network is created with the same structure as the source network. + * A map (old2new) is created where old nodes from source network are mapped to new nodes in destination network. + * A destination network is created with the same structure as the source network. + * + * @tparam NtkDest Type of the destination network. + * @tparam NtkSrc Type of the source network. + * @param src The source network. * + * @return A pair of the destination network and a node map from the source to the destination network. */ template std::pair>, NtkSrc>> - initialize_copy_network_v(NtkSrc const& src) + initialize_copy_network_virtual(NtkSrc const& src) { static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); @@ -113,19 +123,18 @@ class virtual_pi_network : public Ntk } /** - * @brief Special constructor to construct a planar virtual_pi_network from any other network type with given ranks. + * Special constructor to construct a planar virtual_pi_network from any other network type with given ranks. * - * @tparam Ntk Network type - * @param ntk Source network to be utilized for the creation of the virtual_pi_network - * @param ntk_lvls Levels of nodes in the source network - * @param ntk_lvls_new Levels of newly created nodes in the virtual_pi_network + * @tparam Ntk Network type. + * @param ntk Source network to be utilized for the creation of the virtual_pi_network. + * @param ntk_lvls Levels of nodes in the source network. + * @param ntk_lvls_new Levels of newly created nodes in the virtual_pi_network. * * This constructor creates a virtual_pi_network by using the nodes from the original network stored in ntk_lvls. * It handles duplicated nodes and stores them with their newly created nodes in ntk_lvls_new. * If the duplicated nodes are PIs (Primary Inputs), virtual PIs are created and the original PI is stored in a map. * To manage the connections between nodes, this also uses an auxiliary function gather_fanin_signals, that * collects the fanin data for a node and matches them in the virtual_pi_network. - * */ explicit virtual_pi_network(Ntk& ntk, std::vector>>& ntk_lvls, std::vector>>& ntk_lvls_new) @@ -133,7 +142,7 @@ class virtual_pi_network : public Ntk std::unordered_map, bool> node_status; ntk_lvls_new.resize(ntk_lvls.size()); - auto init_v = initialize_copy_network_v(ntk); + auto init_v = initialize_copy_network_virtual(ntk); auto& ntk_dest_v = init_v.first; auto& old2new_v = init_v.second; @@ -151,7 +160,7 @@ class virtual_pi_network : public Ntk * @param edge_it Iterator for edge. * @return Vector of fanins in the virtual_pi_network connected to the processed node. */ - const auto gather_fanin_signals = [&](const auto& n, const auto& lvl, size_t& edge_it) + const auto gather_fanin_signals = [&](const auto& n, const auto& lvl, std::size_t& edge_it) { std::vector children{}; const auto edge_it_int = edge_it; @@ -168,7 +177,7 @@ class virtual_pi_network : public Ntk for (const auto& possible_node : tgt_signal_v) { const auto it = ntk.is_maj(n) ? 4 : 3; - for (size_t i = 0; i < it; i++) + for (std::size_t i = 0; i < it; i++) { if (edge_it_int + i < lvl.size() && lvl[edge_it_int + i] == possible_node) { @@ -194,8 +203,8 @@ class virtual_pi_network : public Ntk return children; }; - size_t edge_it = 0; - for (size_t i = ntk_lvls.size(); i-- > 0;) + std::size_t edge_it = 0; + for (std::size_t i = ntk_lvls.size(); i-- > 0;) { edge_it = 0; const auto& lvl = ntk_lvls[i]; @@ -272,7 +281,7 @@ class virtual_pi_network : public Ntk const auto tgt_signal_v = old2new_v[ntk.get_node(po)]; // POs do not get duplicated since the algorithm starts at the POs and duplicates other nodes according // to their order - assert(tgt_signal_v.size() == 1); + assert(tgt_signal_v.size() == 1 && "Multiple nodes mapped to PO"); const auto tgt_signal = tgt_signal_v[0]; const auto tgt_po = ntk.is_complemented(po) ? ntk_dest_v.create_not(tgt_signal) : tgt_signal; @@ -284,53 +293,48 @@ class virtual_pi_network : public Ntk } /** - * \brief Calculate the real size of the virtual_pi_network. + * Calculate the real size of the virtual_pi_network. * - * This function calculates the real size of the virtual_pi_network by subtracting the size of the virtual_inputs - * vector from the size of the _storage->nodes vector. + * The real size of the network is considered the size without virtual PIs. * - * \return The real size of the virtual_pi_network as a uint32_t. + * @return The real size of the virtual_pi_network as a uint32_t. */ [[nodiscard]] auto real_size() const { - return static_cast(Ntk::size() - virtual_inputs->size()); + return static_cast(Ntk::size() - _storage->virtual_inputs.size()); } /** - * @brief Create a virtual PI mapping to a real PI. + * Create a virtual PI, which is a mapping to a real PI. * - * This function creates a virtual PI mapping to a real PI in the network. It adds a new node to the - * `_storage->nodes` vector and inserts the index of the new node into the `virtual _inputs` vector. It also updates - * the data of the new node. + * This function creates a virtual PI mapping to a real PI in the network. It adds a PI to the underlying network, + * but marks it as virtual and stores a mapping to a real PI. * * @param real_pi The node representing the real PI in the network. - * @return The index of the newly created virtual PI. + * @return The signal of the newly created virtual PI. */ signal create_virtual_pi(const signal& real_pi) { signal s = Ntk::create_pi(); - virtual_inputs->emplace_back(s); - map.emplace_back(s, real_pi); + _storage->virtual_inputs.emplace_back(s); + _storage->map_virt_to_real_pi.insert({s, real_pi}); return s; } /** - * @brief Check if a given node is a virtual primary input (PI) in the virtual_pi_network. - * - * A node is considered a virtual PI if it exists in the virtual_inputs vector of the virtual_pi_network. + * Check if a given node is a virtual PI in the virtual_pi_network. * * @param n The node to check. * @return True if the node is a virtual PI, false otherwise. */ [[nodiscard]] bool is_virtual_pi(node const& n) const { - return std::find(virtual_inputs->cbegin(), virtual_inputs->cend(), n) != virtual_inputs->cend(); + return std::find(_storage->virtual_inputs.cbegin(), _storage->virtual_inputs.cend(), n) != + _storage->virtual_inputs.cend(); } /** - * @brief Check if a given node is a real primary input (PI) in the virtual_pi_network. - * - * A node is considered a real PI if it exists in the inputs vector of the `_storage` object. + * Check if a given node is a real PI in the virtual_pi_network. * * @param n The node to check. * @return True if the node is a real PI, false otherwise. @@ -341,22 +345,19 @@ class virtual_pi_network : public Ntk } /** - * @brief Check if a given node is a virtual constant input (CI) in the virtual_pi_network. - * - * A node is considered a virtual CI if it exists in the virtual_inputs vector. + * Check if a given node is a virtual CI in the virtual_pi_network. * * @param n The node to check. * @return True if the node is a virtual CI, false otherwise. */ [[nodiscard]] bool is_virtual_ci(node const& n) const { - return std::find(virtual_inputs->cbegin(), virtual_inputs->cend(), n) != virtual_inputs->cend(); + return std::find(_storage->virtual_inputs.cbegin(), _storage->virtual_inputs.cend(), n) != + _storage->virtual_inputs.cend(); } /** - * @brief Check if a given node is a real combinatorial input (CI) in the virtual_pi_network. - * - * A node is considered a real CI if it exists in the inputs vector of the `_storage` object. + * Check if a given node is a real CI in the virtual_pi_network. * * @param n The node to check. * @return True if the node is a real CI, false otherwise. @@ -367,83 +368,61 @@ class virtual_pi_network : public Ntk } /** - * @brief Get the number of virtual combinatorial inputs (CIs) in the virtual_pi_network. - * - * The num_cis_virtual() function returns the total number of virtual CIs in the virtual_pi_network. - * Virtual constant inputs are those which exist in the virtual_inputs vector. + * Get the number of virtual CIs in the virtual_pi_network. * * @return The number of virtual CIs as a uint32_t. */ [[nodiscard]] auto num_virtual_cis() const { - return static_cast(virtual_inputs->size()); + return static_cast(_storage->virtual_inputs.size()); } /** - * @brief Get the number of real constant inputs (CIs) in the virtual_pi_network. - * - * The num_cis_real() function returns the total number of real CIs in the virtual_pi_network. - * Real constant inputs are those which exist in the inputs vector of the `_storage` object. + * Get the number of real CIs in the virtual_pi_network. * * @return The number of real CIs as a uint32_t. */ [[nodiscard]] auto num_real_cis() const { - return static_cast(Ntk::num_cis()-num_virtual_cis()); + return static_cast(Ntk::num_cis() - num_virtual_cis()); } /** - * @brief Get the number of virtual primary inputs (PIs) in the virtual_pi_network. - * - * The num_pis_virtual() function returns the total number of virtual PIs in the virtual_pi_network. - * Virtual PIs are those which exist in the virtual_inputs vector. + * Get the number of virtual PIs in the virtual_pi_network. * * @return The number of virtual PIs as a uint32_t. */ [[nodiscard]] auto num_virtual_pis() const { - return static_cast(virtual_inputs->size()); + return static_cast(_storage->virtual_inputs.size()); } /** - * @brief Retrieve the number of real primary inputs (PIs) in the virtual_pi_network. - * - * The num_pis_real() function returns the total number of real PIs in the virtual_pi_network. - * Real PIs are those which exist in the inputs vector of the `_storage` object. + * Get the number of real PIs in the virtual_pi_network. * * @return The number of real PIs as a uint32_t. */ [[nodiscard]] auto num_real_pis() const { - return static_cast(Ntk::num_pis()-num_virtual_pis()); + return static_cast(Ntk::num_pis() - num_virtual_pis()); } /** - * @brief Retrieve the real PI mapped to the given virtual PI. - * - * This function searches for the given virtual PI in the mapping table and returns the corresponding real PI. - * It throws a std::runtime_error if the virtual PI is not found in the mapping table. - * - * @param v_pi The virtual PI to find the corresponding real PI for. - * @return The real PI mapped to the virtual PI. - * @throws std::runtime_error If the virtual PI is not found in the mapping table. + * Get the real PI associated with a virtual PI node. + * @param v_pi The virtual pi node to retrieve the real pi for. + * @return The real pi associated with the virtual pi node. */ [[nodiscard]] auto get_real_pi(const node& v_pi) const { - auto it = std::find_if(map.cbegin(), map.cend(), [v_pi](const auto& pair) { return pair.first == v_pi; }); + auto it = _storage->map_virt_to_real_pi.find(v_pi); - if (it != map.end()) - return it->second; + assert(it != _storage->map_virt_to_real_pi.end() && "Error: node is not a virtual pi"); - throw std::runtime_error("Error: node is not a virtual pi"); + return it->second; } /** - * @brief Iterates over the primary inputs of the circuit and applies a given - * function. - * - * This function iterates over the primary inputs of the circuit and applies a - * given function to each primary input. + * Iterates over the real PIs of the circuit and applies a given function. * * @tparam Fn The type of the function. * @param fn The function to be applied to each primary input. @@ -451,82 +430,69 @@ class virtual_pi_network : public Ntk template void foreach_real_pi(Fn&& fn) { - static_cast(this)->foreach_pi([&](const auto& i){ - if (!is_virtual_pi(i)) { - std::forward(fn)(i); - } - }); + static_cast(this)->foreach_pi( + [&](const auto& i) + { + if (!is_virtual_pi(i)) + { + std::forward(fn)(i); + } + }); } /** - * @brief Applies a given function to each element in a container. - * - * This function applies the provided function to each element in the container `Fn`. The container must support - * iteration using `cbegin()` and `cend()` methods. + * Iterates over the virtual PIs of the circuit and applies a given function. * - * @tparam Fn The container type. - * @param fn The function to apply to each element. - * - * @see mockturtle::detail::foreach_element + * @tparam Fn The type of the function. + * @param fn The function to be applied to each primary input. */ template void foreach_virtual_pi(Fn&& fn) const { - mockturtle::detail::foreach_element(virtual_inputs->cbegin(), virtual_inputs->cend(), fn); + mockturtle::detail::foreach_element(_storage->virtual_inputs.cbegin(), _storage->virtual_inputs.cend(), fn); } /** - * @brief Applies a given function to each input element in the circuit + * Iterates over the virtual CIs of the circuit and applies a given function. * - * This function iterates over each input element in the circuit and applies - * the given function to it. - * - * @tparam Fn The type of the function to be applied - * @param fn The function to be applied + * @tparam Fn The type of the function to be applied. + * @param fn The function to be applied. */ template void foreach_real_ci(Fn&& fn) { - static_cast(this)->foreach_ci([&](const auto& i){ - if (!is_virtual_ci(i)) { - std::forward(fn)(i); - } - }); + static_cast(this)->foreach_ci( + [&](const auto& i) + { + if (!is_virtual_ci(i)) + { + std::forward(fn)(i); + } + }); } /** - * @brief Executes a given function for each element in a container of virtual inputs. - * - * This function iterates over every element in the container of virtual inputs, and - * invokes the provided callable object on each element. - * - * @tparam Fn Type of the callable object. - * @param fn The callable object to be invoked on each element. + * Iterates over the virtual CIs of the circuit and applies a given function. * - * @note The provided callable object must accept a single argument of the same type as - * the elements in the container. + * @tparam Fn The type of the function. + * @param fn The function to be applied to each primary input. */ template void foreach_virtual_ci(Fn&& fn) const { - mockturtle::detail::foreach_element(virtual_inputs->cbegin(), virtual_inputs->cend(), fn); + mockturtle::detail::foreach_element(_storage->virtual_inputs.cbegin(), _storage->virtual_inputs.cend(), fn); } /** - * @brief Removes virtual input nodes from the storage. This enables equivalence checking. + * Removes virtual input nodes from the virtual_pi_network. * - * This function removes virtual input nodes from the storage by performing the following steps: - * 1. Sorts the virtual input nodes in descending order. - * 2. For each virtual input node, finds the corresponding real_pi index mapped to it from the map. - * 3. Substitute the virtual input node with the new node index, which corresponds to the real_pi. - * 4. Adjusts the inputs, nodes vector, and outputs. - * 5. Erases the virtual input node from the nodes vector. - * - * After removing the virtual input nodes, this function clears the virtual_inputs and map containers. + * This function removes the virtual input nodes from the network by substituting them with their corresponding + * real input nodes. It then performs a cleanup to remove any dangling PIs.. + * Finally, it clears the virtual_inputs and map_virt_to_real_pi data structures in the _storage object. */ void remove_virtual_input_nodes() { - for (const auto &map_item : map) + for (const auto& map_item : _storage->map_virt_to_real_pi) { Ntk::substitute_node(Ntk::get_node(map_item.first), map_item.second); } @@ -534,19 +500,15 @@ class virtual_pi_network : public Ntk *this = mockturtle::cleanup_dangling(*this, 1); // Clear virtual_inputs after using it - virtual_inputs->clear(); - map.clear(); + _storage->virtual_inputs.clear(); + _storage->map_virt_to_real_pi.clear(); } protected: /** - * Shared pointer vector storage for virtual_inputs. - */ - std::shared_ptr> virtual_inputs; - /** - * Map from virtual_pis to real_pis. + * Shared pointer if the virtual PI storage. */ - std::vector> map; + std::shared_ptr> _storage; }; } // namespace fiction From d619670761fc12c3856b273aa1f6ae8a03e25ecf Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 31 Jul 2024 15:25:57 +0000 Subject: [PATCH 36/84] :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions --- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index f71bd4250..1b25d426b 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -15717,29 +15717,25 @@ static const char *__doc_fiction_vertical_shift_cartesian = R"doc(\verbatim +-------+ | | | +-------+ | | | +-------+ | | | +-------+ \endverbatim)doc"; -static const char *__doc_fiction_virtual_pi_network = -R"doc(!Network with additional "virtual" PIs. +static const char *__doc_fiction_virtual_pi_network = R"doc()doc"; -"Virtual" PIs (Primary Inputs) are used to manage the duplication of -PIs in the network. Each "real" PI can have an arbitrary number of -"virtual" PIs, which are copies of the original "real" PI. A "virtual" -PI can be created by duplicating a "real" PI. To keep track of this -relationship, there is a mapping of each "virtual" PI to its -corresponding "real" PI in the network.)doc"; +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network = +R"doc(Default constructor for the `virtual_pi_network` class. Initializes +`_storage` as a shared pointer.)doc"; -static const char *__doc_fiction_virtual_pi_network_map = R"doc(Map from virtual_pis to real_pis.)doc"; +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_2 = +R"doc(Copy constructor for the `virtual_pi_network` class. Given a network +`ntk`, constructs a new `virtual_pi_network` as a clone of `ntk`. +Initializes `_storage` as a shared pointer. -static const char *__doc_fiction_virtual_pi_network_virtual_pi_network = -R"doc(A default constructor for the `virtual_pi_network` class. +Parameter ``ntk``: + The network to clone into this object.)doc"; -This constructor initializes `virtual_inputs` with a shared pointer to -an empty std::vector of uint32_t.)doc"; +static const char *__doc_fiction_virtual_storage = R"doc()doc"; -static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_2 = -R"doc(A default constructor for the `virtual_pi_network` class. +static const char *__doc_fiction_virtual_storage_map_virt_to_real_pi = R"doc(Map from virtual_pis to real_pis.)doc"; -This constructor initializes `virtual_inputs` with a shared pointer to -an empty std::vector of uint32_t.)doc"; +static const char *__doc_fiction_virtual_storage_virtual_inputs = R"doc(Shared pointer vector storage for virtual_inputs.)doc"; static const char *__doc_fiction_volume = R"doc(Computes the volume of a given coordinate assuming its origin is (0, From a5706406414af66c75c79f9eca2a49a54c7597df Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 31 Jul 2024 17:32:50 +0200 Subject: [PATCH 37/84] :art: consistency --- include/fiction/networks/virtual_pi_network.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 871553692..3b7bc9151 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -322,7 +322,7 @@ class virtual_pi_network : public Ntk } /** - * Check if a given node is a virtual PI in the virtual_pi_network. + * Check if a given node is a virtual PI. Virtual PIs are created with create_virtual_pi(). * * @param n The node to check. * @return True if the node is a virtual PI, false otherwise. @@ -334,7 +334,7 @@ class virtual_pi_network : public Ntk } /** - * Check if a given node is a real PI in the virtual_pi_network. + * Check if a given node is a real PI. Real PIs are created with create_pi(). * * @param n The node to check. * @return True if the node is a real PI, false otherwise. From ca2cc5abd264ddc99446bc8519bc3e302a65dd6d Mon Sep 17 00:00:00 2001 From: benjamin Date: Thu, 1 Aug 2024 13:31:55 +0200 Subject: [PATCH 38/84] :art: Updated extended_rank_view --- .../networks/views/extended_rank_view.hpp | 205 ++++++++---------- test/networks/views/extended_rank_view.cpp | 9 +- 2 files changed, 89 insertions(+), 125 deletions(-) diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index 23b2aa992..7630d261f 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -24,9 +24,21 @@ * * Provides a view with node ranks for given networks. It adds functionalities to modify ranks. Most importantly, the * new `init_ranks()` function allows an array of nodes to be provided, which sets the levels and ranks of the nodes in - * the network. Additionally, the `modify_rank()` function allows a vector to be passed to a rank, assigning the ranks - * at this level. + * the network. Additionally, the `modify_rank()` function allows to pass a vector to assign the ranks of nodes in one + * specific level. * + * This class template is specialized depending on whether the provided network has a rank interface or not. The rank + * interface is detected using the type traits defined in mockturtle. Specifically, + * - has_rank_position_v + * - has_at_rank_position_v + * - has_swap_v + * - has_width_v + * - has_foreach_node_in_rank_v + * - has_foreach_gate_in_rank_v + * + * @tparam Ntk - The network type. + * @tparam has_rank_interface - Boolean flag checked compile-time, determines if the provided Ntk supports the rank + * interface */ template && mockturtle::has_at_rank_position_v && @@ -36,10 +48,11 @@ class extended_rank_view {}; /** - * @class extended_rank_view (specialization) + * @class extended_rank_view * - * A derived class from depth_view. + * If already a rank_interface exists only the depth_view constructor gets called. * + * @tparam Ntk - The network type. */ template class extended_rank_view : public mockturtle::depth_view @@ -49,10 +62,11 @@ class extended_rank_view : public mockturtle::depth_view }; /** - * @class extended_rank_view (specialization) + * @class extended_rank_view * - * A derived class from depth_view. + * If no rank_interface exists, inherits from mockturtle::depth_view and initializes ranks for the network. * + * @tparam Ntk - The network type. */ template class extended_rank_view : public mockturtle::depth_view @@ -64,9 +78,9 @@ class extended_rank_view : public mockturtle::depth_view using signal = typename Ntk::signal; /** - * @class extended_rank_view (specialization) - * - * Can assign specific ranks. + * Default constructor. + * Constructs an empty extended_rank_view object, initializes base class and class variables, and verifies that the + * Network Type (Ntk) needs to support certain methods. */ explicit extended_rank_view() : mockturtle::depth_view(), rank_pos{*this}, ranks{}, max_rank_width{0} { @@ -81,14 +95,11 @@ class extended_rank_view : public mockturtle::depth_view } /** - * @class extended_rank_view - * - * @brief A derived class from depth_view that represents a network with ranks assigned to nodes. - * - * This class provides functionality to assign and modify ranks for nodes in a network. It also provides methods to - * access and manipulate nodes based on their rank position. + * Constructs an extended_rank_view from an existing network. + * Calls the base class constructor with the provided network, initializes class members, and registers network + * events. Also, it ensures that the Network Type (Ntk) needs to support certain methods. * - * @tparam Ntk Network type + * @param ntk - Reference to the network. */ explicit extended_rank_view(Ntk const& ntk) : mockturtle::depth_view{ntk}, @@ -107,17 +118,14 @@ class extended_rank_view : public mockturtle::depth_view add_event = Ntk::events().register_add_event([this](auto const& n) { on_add(n); }); } - /*! - * \brief Overloaded constructor with ranks specification. - * - * This constructor is similar to the standard one, with the addition of specifying initial node ranks within the - * network. + + /** + * Constructs an extended_rank_view from an existing network and a specific initial rank configuration. * - * \param ntk Base network - * \param ranks A vector of vectors containing nodes, each sub-vector represents a particular rank, and the nodes - * within it. + * @param ntk - Reference to the network. + * @param ranks - A vector of vectors specifying initial ranks for the nodes within the network. */ - explicit extended_rank_view(Ntk const& ntk, std::vector> ranks) : + explicit extended_rank_view(Ntk const& ntk, const std::vector>& ranks) : mockturtle::depth_view{ntk}, rank_pos{ntk}, ranks{this->depth() + 1}, @@ -136,17 +144,13 @@ class extended_rank_view : public mockturtle::depth_view } /** - * @brief Copy constructor for extended_rank_view + * Copy constructor creates a new extended_rank_view by copying the content of another extended_rank_view. * - * This constructor creates a new extended_rank_view object by copying the content of another object of the same - * type. - * - * @tparam Ntk Network type - * @param other The extended_rank_view object to be copied + * @param other - The other extended_rank_view object to be copied. */ extended_rank_view(extended_rank_view const& other) : mockturtle::depth_view(other), - rank_pos{other.rank_pos}, + rank_pos{other}, ranks{other.ranks}, max_rank_width{other.max_rank_width} { @@ -154,15 +158,10 @@ class extended_rank_view : public mockturtle::depth_view } /** - * @brief Assigns the content of another `extended_rank_view` object to this object. - * - * This assignment operator replaces the content of this object with the content of another `extended_rank_view` - * object. It first releases the add event of this network, then updates the base class with the storage and events - * of the other object. It then copies the rank position, ranks, and max rank width from the other object. Finally, - * it registers a new add event in the other network and returns a reference to this object. + * Overloaded assignment operator for copying `extended_rank_view` content of another `extended_rank_view` object. * - * @param other The `extended_rank_view` object to be assigned to this object. - * @return Reference to this object. + * @param other - The source `extended_rank_view` object whose contents are being copied. + * @return A reference to the current object, enabling chain assignments. */ extended_rank_view& operator=(extended_rank_view const& other) { @@ -185,16 +184,14 @@ class extended_rank_view : public mockturtle::depth_view } /** - * @brief Destructor for extended_rank_view. - * - * This destructor releases the add event associated with the extended_rank_view object. + * Destructor for extended_rank_view. */ ~extended_rank_view() { Ntk::events().release_add_event(add_event); } /** - * \brief Returns the rank position of a node. + * Returns the rank position of a node. * * @param n Node to get the rank position of. * @return Rank position of node `n`. @@ -206,24 +203,20 @@ class extended_rank_view : public mockturtle::depth_view return rank_pos[n]; } - /** - * @brief Remove virtual input nodes from the network. - * - * This function removes all virtual input nodes from the network. It first calls the base class function - * `remove_virtual_input_nodes()` to remove the virtual input nodes. Then, it resets the `rank_pos` node map, clears - * each vector in the `ranks` vector, and resets the `max_rank_width` to 0. Finally, it initializes the ranks again - * by calling the `init_ranks()` function and prints a message indicating that the `remove()` function was called. - * - * This function is used to enable equivalence checking with the network. + /* + * Removes all virtual input nodes from the network. * - * Note: This function should only be used for network types that are the same as `fiction::virtual_pi_network`. - * - * @tparam U The network type. + * The purpose of this function is to facilitate network equivalence checking. This function is primarily + * intended for network types that resemble `fiction::virtual_pi_network`. */ - template - typename std::enable_if::value>::type remove_virtual_input_nodes() + // template + // typename std::enable_if>::type remove_virtual_input_nodes() + void remove_virtual_input_nodes() { - fiction::virtual_pi_network::remove_virtual_input_nodes(); + if constexpr (fiction::has_remove_virtual_input_nodes_v) + { + Ntk::remove_virtual_input_nodes(); + } rank_pos.reset(); // Clear the node_map // Clear each vector in ranks for (auto& rank : ranks) @@ -239,18 +232,13 @@ class extended_rank_view : public mockturtle::depth_view } /** - * @brief Checks the validity of the ranks and rank positions in the extended_rank_view class. + * Verifies the validity of ranks and rank positions within the extended_rank_view context. * - * This function checks if the ranks and rank positions are valid in the extended_rank_view class. It iterates over - *each rank and checks if the level of each node matches the rank level . It also checks if the rank positions are - *in ascending order for each rank. If any inconsistency is found, the function returns false. Otherwise, it returns - *true, indicating that the ranks and rank positions are valid. - * - * @return True if the ranks and rank positions are valid, false otherwise. + * @return A boolean indicating whether the ranks and rank positions are valid (true) or not (false). */ bool check_validity() const noexcept { - for (size_t i = 0; i < ranks.size(); ++i) + for (std::size_t i = 0; i < ranks.size(); ++i) { const auto& rank = ranks[i]; uint32_t expected_rank_pos = 0; @@ -273,13 +261,10 @@ class extended_rank_view : public mockturtle::depth_view } /** - * \brief Modifies the rank by updating the nodes at the specified level with the given nodes. - * - * This function replaces the nodes at the specified level with the given nodes and updates the rank positions - * accordingly. + * Updates the nodes and associated rank positions for a specific level within the rank. * - * \param level The level at which to modify the rank. - * \param nodes The new set of nodes for the specified level. + * @param level Level at which to replace nodes. + * @param nodes The new nodes to be set at the given level. */ void modify_rank(uint32_t const level, const std::vector& nodes) { @@ -287,12 +272,13 @@ class extended_rank_view : public mockturtle::depth_view rank = nodes; std::for_each(rank.cbegin(), rank.cend(), [this, i = 0u](auto const& n) mutable { rank_pos[n] = i++; }); } + /** - * \brief Returns the node at a certain rank position. + * Fetches a node at a specific rank position * - * @param level Level in the network, i.e., rank to get the node from. - * @param pos Position in the rank to get the node from. - * @return Node at position `pos` in rank `level`. + * @param level The level in the network, from which the node is to be fetched. + * @param pos The position within the rank from which to obtain the node. + * @return The node that resides at the `pos` in the `level`. */ node at_rank_position(uint32_t const level, uint32_t const pos) const noexcept { @@ -302,7 +288,7 @@ class extended_rank_view : public mockturtle::depth_view return ranks[level][pos]; } /** - * \brief Returns the width of the widest rank in the network. + * Returns the width of the widest rank in the network. * * @return Width of the widest rank in the network. */ @@ -311,7 +297,7 @@ class extended_rank_view : public mockturtle::depth_view return max_rank_width; } /** - * \brief Swaps the positions of two nodes in the same rank. + * Swaps the positions of two nodes in the same rank. * * @param n1 First node to swap. * @param n2 Second node to swap. @@ -327,7 +313,7 @@ class extended_rank_view : public mockturtle::depth_view std::swap(pos1, pos2); } /** - * \brief Sorts the given rank according to a comparator. + * Sorts the given rank according to a comparator. * * @tparam Cmp Functor type that compares two nodes. It needs to fulfill the requirements of `Compare` (named C++ * requirement). @@ -347,7 +333,7 @@ class extended_rank_view : public mockturtle::depth_view } } /** - * \brief Applies a given function to each node in the rank level in order. + * Applies a given function to each node in the rank level in order. * * @tparam Fn Functor type. * @param level The rank to apply fn to. @@ -365,7 +351,7 @@ class extended_rank_view : public mockturtle::depth_view } } /** - * \brief Applies a given function to each node in rank order. + * Applies a given function to each node in rank order. * * This function overrides the `foreach_node` method of the base class. * @@ -381,7 +367,7 @@ class extended_rank_view : public mockturtle::depth_view } } /** - * \brief Applies a given function to each gate in the rank level in order. + * Applies a given function to each gate in the rank level in order. * * @tparam Fn Functor type. * @param level The rank to apply fn to. @@ -400,7 +386,7 @@ class extended_rank_view : public mockturtle::depth_view } } /** - * \brief Applies a given function to each gate in rank order. + * Applies a given function to each gate in rank order. * * This function overrides the `foreach_gate` method of the base class. * @@ -416,7 +402,7 @@ class extended_rank_view : public mockturtle::depth_view } } /** - * \brief Applies a given function to each PI in rank order. + * Applies a given function to each PI in rank order. * * This function overrides the `foreach_pi` method of the base class. * @@ -455,9 +441,7 @@ class extended_rank_view : public mockturtle::depth_view std::shared_ptr::add_event_type> add_event; /** - * @brief Inserts a node into the rank. - * - * This function inserts a node into the rank and updates the rank position, ranks, and max rank width accordingly. + * Inserts a node into the rank and updates the rank position, ranks, and max rank width accordingly. * * @param n The node to insert into the rank. */ @@ -471,6 +455,7 @@ class extended_rank_view : public mockturtle::depth_view /** * Adds a new node to the skip list. + * * @param n The node to be added. */ void on_add(node const& n) noexcept @@ -486,10 +471,8 @@ class extended_rank_view : public mockturtle::depth_view } /** - * @brief Initializes the ranks for the given network. - * - * This function initializes the ranks for the given network. It traverses the nodes in the network using a - * depth-first search and inserts each non-constant node into the rank. + * Initializes the ranks for the given network. It traverses the nodes in the network using a depth-first search and + * inserts each non-constant node into the rank. * * This function is noexcept. */ @@ -506,18 +489,12 @@ class extended_rank_view : public mockturtle::depth_view } /** - * @brief Inserts a node into the rank list at the specified rank level. - * @param n The node to insert. - * @param rank_level The rank level at which to insert the node. - * @note This function modifies the rank list by adding the node at the specified rank level. - * @note This function updates the rank position and the maximum rank width. - * @warning This function assumes that the node n is a valid node. - * @warning This function assumes that the rank list and rank positions have been initialized before calling this - * function. + * Implements a node into the rank list at the given rank level. * - * @see ranks, rank_pos, max_rank_width + * @param n The node to be inserted. + * @param rank_level The level at which the node should be inserted in the rank. */ - void insert_in_rank(node const& n, size_t rank_level) noexcept + void insert_in_rank(node const& n, std::size_t rank_level) noexcept { if (rank_level >= ranks.size()) { @@ -530,17 +507,14 @@ class extended_rank_view : public mockturtle::depth_view } /** - * @brief Initializes the ranks with the given vector of nodes. - * - * This function takes in a 2D vector of nodes and initializes the ranks accordingly. - * Each node in the input ranks is inserted into its corresponding rank, unless it is a constant node. + * Initializes the ranks with the given array of nodes. * * @param input_ranks The input vector of ranks. * @return void */ void init_ranks(std::vector> const& input_ranks) noexcept { - for (size_t i = 0; i < input_ranks.size(); ++i) + for (std::size_t i = 0; i < input_ranks.size(); ++i) { auto const& rank_nodes = input_ranks[i]; for (auto const& n : rank_nodes) @@ -555,26 +529,17 @@ class extended_rank_view : public mockturtle::depth_view }; /** - * @brief Deduction guide for `extended_rank_view' - * - * This template helps to deduce the type argument `T` for the - * `extended_rank_view` class when constructed with an argument of type `T`. + * Deduction guide for `extended_rank_view' * - * @tparam T Network type deduced from the construction context of - * `extended_rank_view`. + * @tparam T Network type deduced from the construction context of `extended_rank_view`. */ template extended_rank_view(T const&) -> extended_rank_view; /** - * @brief Deduction guide for `extended_rank_view` with two constructor arguments - * - * This template helps to deduce the type argument `T` for the - * `extended_rank_view` class when constructed with two arguments: a network of type `T`, - * and a `vector` of `vector` containing network nodes. + * Deduction guide for `extended_rank_view` with two constructor arguments * - * @tparam T Network type deduced from the construction context of - * `extended_rank_view`. + * @tparam T Network type deduced from the construction context of `extended_rank_view`. */ template extended_rank_view(T const&, std::vector>) -> extended_rank_view; diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index ed28034cb..1deed794a 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -3,11 +3,13 @@ // #include +#include #include #include #include #include +#include #include #include @@ -20,7 +22,6 @@ #include #include #include -#include using namespace fiction; @@ -136,7 +137,7 @@ TEMPLATE_TEST_CASE("Check equivalence checking", "[extended_rank_view]", mocktur TEST_CASE("Check equivalence checking for virtual PIs", "[extended-rank-view]") { technology_network tec{}; - virtual_pi_network vpi{}; + virtual_pi_network vpi{}; const auto a = vpi.create_pi(); const auto b = vpi.create_pi(); @@ -168,11 +169,9 @@ TEST_CASE("Check equivalence checking for virtual PIs", "[extended-rank-view]") auto vpi_r = extended_rank_view(vpi); - vpi_r.remove_virtual_input_nodes(); - mockturtle::equivalence_checking_stats st; const auto maybe_cec_m = - mockturtle::equivalence_checking(*mockturtle::miter(tec, vpi_r), {}, &st); + mockturtle::equivalence_checking(*fiction::miter(tec, vpi_r), {}, &st); REQUIRE(maybe_cec_m.has_value()); const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); From 566ed78b2824e95941d32a11bfb0ae5068513187 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 1 Aug 2024 11:32:50 +0000 Subject: [PATCH 39/84] :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions --- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index 1b25d426b..34df6c1e5 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -24,17 +24,17 @@ static const char *__doc_extended_rank_view = -R"doc(@class extended_rank_view (specialization) +R"doc(@class extended_rank_view -A derived class from depth_view.)doc"; +If already a rank_interface exists only the depth_view constructor +gets called. + +Template parameter ``Ntk``: + - The network type.)doc"; static const char *__doc_extended_rank_view_2 = R"doc(Deduction guide for `extended_rank_view' -This template helps to deduce the type argument `T` for the -`extended_rank_view` class when constructed with an argument of type -`T`. - Template parameter ``T``: Network type deduced from the construction context of `extended_rank_view`.)doc"; @@ -43,11 +43,6 @@ static const char *__doc_extended_rank_view_3 = R"doc(Deduction guide for `extended_rank_view` with two constructor arguments -This template helps to deduce the type argument `T` for the -`extended_rank_view` class when constructed with two arguments: a -network of type `T`, and a `vector` of `vector` containing network -nodes. - Template parameter ``T``: Network type deduced from the construction context of `extended_rank_view`.)doc"; From 42dd596f720f883bf01c6bcfe561c1724be3a98d Mon Sep 17 00:00:00 2001 From: benjamin Date: Thu, 1 Aug 2024 14:16:48 +0200 Subject: [PATCH 40/84] :art: Updated node_duplication_planarization --- .../node_duplication_planarization.hpp | 25 ++++----- .../node_duplication_planarization.cpp | 54 ++++++------------- 2 files changed, 25 insertions(+), 54 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index b9d7f166c..c6238d019 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -315,7 +315,7 @@ class node_duplication_planarization_impl } } - virtual_pi_network run(std::vector>>& ntk_lvls_new) + virtual_pi_network run(std::vector>>& ntk_lvls_new) { const bool border_pis = true; @@ -389,7 +389,7 @@ class node_duplication_planarization_impl /* * The input network. */ - const Ntk ntk; + Ntk ntk; /* * The currently node_pairs used in the current level. */ @@ -431,30 +431,23 @@ class node_duplication_planarization_impl * the created network is non-planar * */ -template -extended_rank_view node_duplication_planarization(const NtkSrc& ntk_src, - node_duplication_params ps = {}) +template +extended_rank_view> +node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) { static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); - static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); - static_assert(mockturtle::has_is_constant_v, "NtkSrc does not implement the is_constant function"); - static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi function"); - static_assert(mockturtle::has_create_not_v, "NtkDest does not implement the create_not function"); - static_assert(mockturtle::has_create_po_v, "NtkDest does not implement the create_po function"); - static_assert(mockturtle::has_create_buf_v, "NtkDest does not implement the create_buf function"); - static_assert(mockturtle::has_clone_node_v, "NtkDest does not implement the clone_node function"); - static_assert(mockturtle::has_foreach_fanin_v, "NtkDest does not implement the foreach_fanin function"); - static_assert(mockturtle::has_foreach_po_v, "NtkDest does not implement the foreach_po function"); + // check the network to be a technology network (is there a better check/trait?) + static_assert(mockturtle::has_create_le_v, "T must be of type const ExpectedType"); if (!is_balanced(ntk_src)) { throw std::runtime_error("Combinations are empty. There might be a dangling node"); } - detail::node_duplication_planarization_impl p{ntk_src, ps}; + detail::node_duplication_planarization_impl p{ntk_src, ps}; - std::vector>> ntk_lvls_new; + std::vector>> ntk_lvls_new; auto result_ntk = p.run(ntk_lvls_new); diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index c61df2b16..1ca0fb2d6 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -4,13 +4,15 @@ #include +#include "fiction/algorithms/network_transformation/network_balancing.hpp" #include "utils/blueprints/network_blueprints.hpp" -#include "utils/equivalence_checking_utils.hpp" #include +#include #include -#include +#include +#include using namespace fiction; @@ -18,10 +20,6 @@ TEST_CASE("2-ary nodes Test", "[node-duplication-planarization]") { technology_network tec{}; - CHECK(mockturtle::has_clear_visited_v); - CHECK(mockturtle::has_visited_v); - CHECK(mockturtle::has_set_visited_v); - const auto x1 = tec.create_pi(); const auto x2 = tec.create_pi(); const auto x3 = tec.create_pi(); @@ -43,25 +41,17 @@ TEST_CASE("2-ary nodes Test", "[node-duplication-planarization]") auto planarized_maj = node_duplication_planarization(tec_b); - // The test takes long due to the rank_pos.reset() function - planarized_maj.remove_virtual_input_nodes(); - mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = - mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); - REQUIRE(maybe_cec_m.has_value()); - const bool cec_m = *maybe_cec_m; - CHECK(cec_m == 1); + const auto cec_m = + mockturtle::equivalence_checking(*fiction::miter(tec, planarized_maj), {}, &st); + REQUIRE(cec_m.has_value()); + CHECK(*cec_m == 1); } TEST_CASE("3-ary nodes Test", "[node-duplication-planarization]") { technology_network tec{}; - CHECK(mockturtle::has_clear_visited_v); - CHECK(mockturtle::has_visited_v); - CHECK(mockturtle::has_set_visited_v); - const auto x1 = tec.create_pi(); const auto x2 = tec.create_pi(); const auto x3 = tec.create_pi(); @@ -85,25 +75,17 @@ TEST_CASE("3-ary nodes Test", "[node-duplication-planarization]") auto planarized_maj = node_duplication_planarization(tec_b); - // The test takes long due to the rank_pos.reset() function - planarized_maj.remove_virtual_input_nodes(); - mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = - mockturtle::equivalence_checking(*mockturtle::miter(tec, planarized_maj), {}, &st); - REQUIRE(maybe_cec_m.has_value()); - const bool cec_m = *maybe_cec_m; - CHECK(cec_m == 1); + const auto cec_m = + mockturtle::equivalence_checking(*fiction::miter(tec, planarized_maj), {}, &st); + REQUIRE(cec_m.has_value()); + CHECK(*cec_m == 1); } TEST_CASE("Aig Test", "[node-duplication-planarization]") { mockturtle::aig_network aig{}; - CHECK(mockturtle::has_clear_visited_v); - CHECK(mockturtle::has_visited_v); - CHECK(mockturtle::has_set_visited_v); - const auto x1 = aig.create_pi(); const auto x2 = aig.create_pi(); const auto x3 = aig.create_pi(); @@ -127,13 +109,9 @@ TEST_CASE("Aig Test", "[node-duplication-planarization]") auto planarized_maj = node_duplication_planarization(aig_b); - // The test takes long due to the rank_pos.reset() function - planarized_maj.remove_virtual_input_nodes(); - mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = - mockturtle::equivalence_checking(*mockturtle::miter(aig, planarized_maj), {}, &st); - REQUIRE(maybe_cec_m.has_value()); - const bool cec_m = *maybe_cec_m; - CHECK(cec_m == 1); + const auto cec_m = + mockturtle::equivalence_checking(*fiction::miter(aig, planarized_maj), {}, &st); + REQUIRE(cec_m.has_value()); + CHECK(*cec_m == 1); } From d786f433de84d50c565eaec5f6b7bde763af6f97 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 12:17:49 +0000 Subject: [PATCH 41/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/networks/views/extended_rank_view.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index 1deed794a..3b9e12b8e 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -6,10 +6,10 @@ #include #include +#include #include #include #include -#include #include #include @@ -136,7 +136,7 @@ TEMPLATE_TEST_CASE("Check equivalence checking", "[extended_rank_view]", mocktur TEST_CASE("Check equivalence checking for virtual PIs", "[extended-rank-view]") { - technology_network tec{}; + technology_network tec{}; virtual_pi_network vpi{}; const auto a = vpi.create_pi(); @@ -170,8 +170,7 @@ TEST_CASE("Check equivalence checking for virtual PIs", "[extended-rank-view]") auto vpi_r = extended_rank_view(vpi); mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = - mockturtle::equivalence_checking(*fiction::miter(tec, vpi_r), {}, &st); + const auto maybe_cec_m = mockturtle::equivalence_checking(*fiction::miter(tec, vpi_r), {}, &st); REQUIRE(maybe_cec_m.has_value()); const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); From 699d4eed4dc98414e3260b9a8fa94101fa7f09ee Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 13 Aug 2024 10:50:57 +0200 Subject: [PATCH 42/84] :heavy_plus_sign: added function rank_width to extended_rank_view.hpp --- include/fiction/networks/views/extended_rank_view.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index 7630d261f..3a31333e7 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -296,6 +296,16 @@ class extended_rank_view : public mockturtle::depth_view { return max_rank_width; } + /** + * Returns the width of the rank. + * + * @return Width of the rank. + */ + uint32_t rank_width(uint32_t const level) noexcept + { + auto& rank = ranks[level]; + return rank.size(); + } /** * Swaps the positions of two nodes in the same rank. * From 4f3aab7a53723417888d03273df85b477318cf47 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:36:40 +0000 Subject: [PATCH 43/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/fiction/networks/views/extended_rank_view.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index 3a31333e7..7d58e618c 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -303,7 +303,7 @@ class extended_rank_view : public mockturtle::depth_view */ uint32_t rank_width(uint32_t const level) noexcept { - auto& rank = ranks[level]; + auto& rank = ranks[level]; return rank.size(); } /** From e431e21282542ec42bcc0d0a07c23c23d35badbc Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 20 Aug 2024 16:05:57 +0000 Subject: [PATCH 44/84] :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions --- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 283 ++++++++++++++++++ 1 file changed, 283 insertions(+) diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index 4189a3ee5..237cfbd5c 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -23,6 +23,32 @@ #endif +static const char *__doc_extended_rank_view = +R"doc(@class extended_rank_view + +If already a rank_interface exists only the depth_view constructor +gets called. + +Template parameter ``Ntk``: + - The network type.)doc"; + +static const char *__doc_extended_rank_view_2 = +R"doc(Deduction guide for `extended_rank_view' + +Template parameter ``T``: + Network type deduced from the construction context of + `extended_rank_view`.)doc"; + +static const char *__doc_extended_rank_view_3 = +R"doc(Deduction guide for `extended_rank_view` with two constructor +arguments + +Template parameter ``T``: + Network type deduced from the construction context of + `extended_rank_view`.)doc"; + +static const char *__doc_extended_rank_view_extended_rank_view = R"doc()doc"; + static const char *__doc_fiction_a_star = R"doc(The A* path finding algorithm for shortest loop-less paths between a given source and target coordinate in a layout. This function @@ -1938,6 +1964,46 @@ Parameter ``cs``: Returns: Integer representing the SiDB's charge state.)doc"; +static const char *__doc_fiction_check_planarity = +R"doc(Checks if a logic network is planar. To perform this check, the +network must have ranks assigned. + +If the network is not balanced, an exception is thrown. To balance the +network, insert buffers to divide multi-level edges. + +Template parameter ``Ntk``: + Logic network type. + +Parameter ``ntk``: + The logic network to check for planarity. + +Returns: + `true` if the network is planar, `false` otherwise. + +Throws: + std::runtime_error if the network is not balanced.)doc"; + +static const char *__doc_fiction_check_planarity_impl = R"doc()doc"; + +static const char *__doc_fiction_check_planarity_impl_check_planarity_impl = R"doc()doc"; + +static const char *__doc_fiction_check_planarity_impl_ntk = R"doc()doc"; + +static const char *__doc_fiction_check_planarity_impl_run = +R"doc(Checks if a given network is planar. + +This function checks if the network represented by the variable `ntk` +is planar. The network is planar if for any edge with starting point m +and endpoint n (represented by the node ranks), there is never another +edge with starting point m_ > m and endpoint n_ < n, or vice versa. +When iterating through the ranks of one level, the endpoints are +always increasing. Therefore, only the starting points need to be +checked. Thus, the highest connected starting point in the fan-in +gives a border m_max for every subsequent edge. + +Returns: + `true` if the network is planar, `false` otherwise.)doc"; + static const char *__doc_fiction_check_simulation_results_for_equivalence = R"doc(This function compares two SiDB simulation results for equivalence. Two results are considered equivalent if they have the same number of @@ -3904,6 +3970,23 @@ Parameter ``to_delete``: Returns: A 2D vector representing the calculated offset matrix.)doc"; +static const char *__doc_fiction_detail_calculate_pairs = +R"doc(Calculates pairs of nodes from a given vector of nodes. + +This function takes a vector of nodes and returns a vector of node +pairs. Each node pair consists of two nodes from the input vector and +an optional vector of middle nodes. The delay of each node pair is +initialized to infinity. + +Template parameter ``Ntk``: + The network type. + +Parameter ``nodes``: + The vector of nodes. + +Returns: + The vector of node pairs.)doc"; + static const char *__doc_fiction_detail_color_routing_impl = R"doc()doc"; static const char *__doc_fiction_detail_color_routing_impl_color_routing_impl = R"doc()doc"; @@ -6318,6 +6401,125 @@ static const char *__doc_fiction_detail_new_gate_location_NONE = R"doc(Do not ch static const char *__doc_fiction_detail_new_gate_location_SRC = R"doc(Check if the source tile is empty.)doc"; +static const char *__doc_fiction_detail_node_duplication_planarization_impl = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_check_final_level = +R"doc(Checks if the given vector of nodes contains any non-primary inputs. + +This function iterates through each node in the vector and checks if +it is a primary input. If a non-primary input is found, the +`f_final_level` parameter is set to false and the loop is exited. + +Parameter ``v_next_level``: + The vector of nodes to be checked + +Parameter ``f_final_level``: + A reference to a boolean indicating if the vector contains only + primary inputs)doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_compute_node_order_next_level = +R"doc(Computes the order of nodes in the next level based on delay + +Parameter ``next_level``: + The vector to store the nodes in the next level + +This function computes the order of nodes in the next level based on +their delay in the H-graph of the level. It selects the path with the +least delay from the current level pairs and follows it via fanin +relations. The nodes are inserted into the next level vector in the +order they are encountered.)doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_compute_slice_delays = +R"doc(Computes the delay in a given slice (each possible order of +node_pairs) of an H-graph + +Parameter ``nd``: + Node in the H-graph + +Parameter ``border_pis``: + A boolean indicating whether the input PIs (Primary Inputs) should + be propagated to the next level + +This function iterates over the fanins of the given node and computes +the delay for all possible orders of these nodes that form a +node_pair. The delay computation depends on the node's connections and +position within the graph. If there is a connection between two +node_pairs, the delay is incremented by 1. If not, the delay is +incremented by 2. Default delay for the first node is 1. If a +node_pair doesn't have a connection and its delay (when increased by +two) is less than the existing delay, then this node_pair's delay is +updated. + +The processed node_pairs are pushed back to the 'lvl_pairs' data +member for subsequent delay calculations. + +Throws: + std::runtime_error if no combinations (possible node_pairs) are + found, which might suggest a dangling node)doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_insert_if_unique = +R"doc(Inserts a node into a vector if it is unique + +This function inserts a node into a vector only if the vector is empty +or the node is not equal to the first element of the vector. If the +vector is not empty and the node is equal to the first element, it +does nothing. + +Template parameter ``Ntk``: + The network type + +Parameter ``node``: + The node to be inserted + +Parameter ``vec``: + The vector to insert the node into)doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_lvl_pairs = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_node_duplication_planarization_impl = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_ntk = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_ps = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_run = R"doc()doc"; + +static const char *__doc_fiction_detail_node_pair = +R"doc(A structure representing a pair of nodes in an H-graph + +Template parameter ``Ntk``: + Network type for the nodes in the pair + +The nodes stored in this struct describe the fanin-edges of a node in +an H-graph. A node pair object holds two nodes, which are saved in the +member 'pair'. These two outer nodes are connected through zero or +more 'middle_nodes'. The fanin order starts with the first node in +'pair', then proceeds through the 'middle_nodes', and ends with the +second node in 'pair'. The order of 'middle_nodes' is arbitrary as +they cannot be further connected to any other nodes. For the +planarization, only the nodes inside the 'pair' are relevant. + +@note The edges connecting to the nodes in 'pair' effectively block +the 'middle_nodes'.)doc"; + +static const char *__doc_fiction_detail_node_pair_delay = R"doc(Specifies the delay value for the node)doc"; + +static const char *__doc_fiction_detail_node_pair_fanin_pair = +R"doc(Shared pointer to another instance of node_pair detailing fanin-edge +alignment)doc"; + +static const char *__doc_fiction_detail_node_pair_node_pair = +R"doc(node_pair constructor + +Parameter ``node1``: + The first node of the fanin-edged node + +Parameter ``node2``: + The second node of the fanin-edged node + +Parameter ``delayValue``: + The delay value for the node)doc"; + static const char *__doc_fiction_detail_on_the_fly_circuit_design_impl = R"doc()doc"; static const char *__doc_fiction_detail_on_the_fly_circuit_design_impl_design_circuit_on_defective_surface = R"doc()doc"; @@ -11225,10 +11427,14 @@ static const char *__doc_fiction_has_north_east = R"doc()doc"; static const char *__doc_fiction_has_north_west = R"doc()doc"; +static const char *__doc_fiction_has_num_real_pis = R"doc()doc"; + static const char *__doc_fiction_has_ordinal_operations = R"doc()doc"; static const char *__doc_fiction_has_post_layout_optimization = R"doc()doc"; +static const char *__doc_fiction_has_remove_virtual_input_nodes = R"doc()doc"; + static const char *__doc_fiction_has_set_layout_name = R"doc()doc"; static const char *__doc_fiction_has_south = R"doc()doc"; @@ -12735,6 +12941,20 @@ static const char *__doc_fiction_missing_sidb_position_exception_missing_sidb_po static const char *__doc_fiction_missing_sidb_position_exception_where = R"doc()doc"; +static const char *__doc_fiction_miter = +R"doc(! Creates a combinational miter from two networks. + +This method combines two networks that have the same number of primary +inputs and the same number of primary outputs into a miter. The miter +has the same number of inputs and one primary output. This output is +the OR of XORs of all primary output pairs. In other words, the miter +outputs 1 for all input assignments in which the two input networks +differ. + +All networks may have different types. The method returns an optional, +which is `nullopt`, whenever the two input networks don't match in +their number of primary inputs and primary outputs.)doc"; + static const char *__doc_fiction_network_balancing = R"doc(Balances a logic network with buffer nodes that compute the identity function. For this purpose, `create_buf` is utilized. Therefore, @@ -12819,6 +13039,49 @@ Parameter ``file``: Parameter ``rfun``: The actual parsing function.)doc"; +static const char *__doc_fiction_node_duplication_params = R"doc(Parameters for the node duplication algorithm.)doc"; + +static const char *__doc_fiction_node_duplication_params_random_output_order = +R"doc(The output order determines the starting layer for this algorithm. If +this option is turned off, the output order remains the same as in the +provided network. If it is turned on, the outputs are ordered +randomly.)doc"; + +static const char *__doc_fiction_node_duplication_planarization = +R"doc(Implements a planarization mechanism for networks using a H-Graph +strategy for node duplication. + +Template parameter ``NtkDest``: + Destination network type + +Template parameter ``NtkSrc``: + Source network type + +Parameter ``ntk_src``: + Source network to be utilized for the planarization + +Parameter ``ps``: + Node duplication parameters used in the computation + +The planarization achieved by this function solves the Node +Duplication Crossing Minimization (NDCE) problem by finding the +shortest x-y path in the H-graph for every level in the network. An +H-graph describes edge relations between two levels in a network, with +one level assumed as fixed, starting at the Primary Outputs (POs). By +finding the shortest path from the source (x) to the sink (y) in this +H-graph, an optimal solution for the NDCE problem is found. The +function constructs an H-graph that captures edge relations between +two levels within the graph and computes the shortest x-y paths on the +H-graph, traversing from the POs towards the Primary Inputs (PIs). + +Returns: + A view of the planarized virtual_pi_network created in the format + of extended_rank_view + +Throws: + std::runtime_error if input network not balanced, if no node + combinations are found or if the created network is non-planar)doc"; + static const char *__doc_fiction_normalize_layout_coordinates = R"doc(A new layout is constructed and returned that is equivalent to the given cell-level layout. However, its coordinates are normalized, @@ -16886,6 +17149,26 @@ static const char *__doc_fiction_vertical_shift_cartesian = R"doc(\verbatim +-------+ | | | +-------+ | | | +-------+ | | | +-------+ \endverbatim)doc"; +static const char *__doc_fiction_virtual_pi_network = R"doc()doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network = +R"doc(Default constructor for the `virtual_pi_network` class. Initializes +`_storage` as a shared pointer.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_2 = +R"doc(Copy constructor for the `virtual_pi_network` class. Given a network +`ntk`, constructs a new `virtual_pi_network` as a clone of `ntk`. +Initializes `_storage` as a shared pointer. + +Parameter ``ntk``: + The network to clone into this object.)doc"; + +static const char *__doc_fiction_virtual_storage = R"doc()doc"; + +static const char *__doc_fiction_virtual_storage_map_virt_to_real_pi = R"doc(Map from virtual_pis to real_pis.)doc"; + +static const char *__doc_fiction_virtual_storage_virtual_inputs = R"doc(Shared pointer vector storage for virtual_inputs.)doc"; + static const char *__doc_fiction_volume = R"doc(Computes the volume of a given coordinate assuming its origin is (0, 0, 0). Calculates :math:`(|x| + 1) \cdot (|y| + 1) \cdot (|z| + 1)` by From 01035ec0f84c9679e657aceb9dca75d50cd32178 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 20 Aug 2024 19:09:04 +0200 Subject: [PATCH 45/84] :art: bug fixed --- .../fiction/networks/virtual_pi_network.hpp | 4 +++ .../node_duplication_planarization.cpp | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 3b7bc9151..7a81f6cdf 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -177,6 +177,10 @@ class virtual_pi_network : public Ntk for (const auto& possible_node : tgt_signal_v) { const auto it = ntk.is_maj(n) ? 4 : 3; + if (ntk.fanin_size(n) == children.size()) + { + break; + } for (std::size_t i = 0; i < it; i++) { if (edge_it_int + i < lvl.size() && lvl[edge_it_int + i] == possible_node) diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index 1ca0fb2d6..a157b55f0 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -115,3 +115,30 @@ TEST_CASE("Aig Test", "[node-duplication-planarization]") REQUIRE(cec_m.has_value()); CHECK(*cec_m == 1); } + +TEST_CASE("Aig Test 2", "[node-duplication-planarization]") +{ + technology_network aig{}; + + const auto x1 = aig.create_pi(); + const auto x2 = aig.create_pi(); + const auto f1 = aig.create_and(x1, x2); + const auto f2 = aig.create_or(x1, x2); + aig.create_po(f1); + aig.create_po(f2); + + network_balancing_params ps; + ps.unify_outputs = true; + + const auto aig_b = network_balancing(aig, ps); + + const auto vpi_r = mockturtle::rank_view(aig_b); + + auto planarized_maj = node_duplication_planarization(aig_b); + + mockturtle::equivalence_checking_stats st; + const auto cec_m = + mockturtle::equivalence_checking(*fiction::miter(aig, planarized_maj), {}, &st); + REQUIRE(cec_m.has_value()); + CHECK(*cec_m == 1); +} From a1cabbe7a3f5734376db391af34562ba31447a83 Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 21 Aug 2024 10:39:43 +0200 Subject: [PATCH 46/84] :art: multi_output bug fixed --- .../node_duplication_planarization.hpp | 11 ++++++- .../node_duplication_planarization.cpp | 30 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index c6238d019..9a04e083d 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -319,8 +319,17 @@ class node_duplication_planarization_impl { const bool border_pis = true; + std::unordered_map po_counts; + + ntk.foreach_po([&po_counts](auto po) { + po_counts[po]++; + }); + std::vector pos; - ntk.foreach_po([&pos](auto po) { pos.push_back(po); }); + for(const auto& kv : po_counts) { + pos.push_back(kv.first); + } + // Randomize the PO order if (ps.random_output_order) { diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index a157b55f0..4fda94719 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -142,3 +142,33 @@ TEST_CASE("Aig Test 2", "[node-duplication-planarization]") REQUIRE(cec_m.has_value()); CHECK(*cec_m == 1); } + +TEST_CASE("Multi output network", "[node-duplication-planarization]") +{ + mockturtle::aig_network aig{}; + + const auto x1 = aig.create_pi(); + const auto x2 = aig.create_pi(); + + const auto a1 = aig.create_and(x1, x2); + + aig.create_po(a1); + aig.create_po(a1); + /*aig.create_po(a1); + aig.create_po(a1);*/ + + network_balancing_params ps; + ps.unify_outputs = true; + + const auto aig_b = network_balancing(aig, ps); + + const auto vpi_r = mockturtle::rank_view(aig_b); + + auto planarized_maj = node_duplication_planarization(aig_b); + + mockturtle::equivalence_checking_stats st; + const auto cec_m = + mockturtle::equivalence_checking(*fiction::miter(aig, planarized_maj), {}, &st); + REQUIRE(cec_m.has_value()); + CHECK(*cec_m == 1); +} From ac979e030067d0e81a6987d6255520c53ec95cc8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2024 08:40:01 +0000 Subject: [PATCH 47/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../node_duplication_planarization.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 9a04e083d..b4e7f5f6d 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -321,12 +321,11 @@ class node_duplication_planarization_impl std::unordered_map po_counts; - ntk.foreach_po([&po_counts](auto po) { - po_counts[po]++; - }); + ntk.foreach_po([&po_counts](auto po) { po_counts[po]++; }); std::vector pos; - for(const auto& kv : po_counts) { + for (const auto& kv : po_counts) + { pos.push_back(kv.first); } From de1343a08bddf5dc9bac1353130db5a3657f86d7 Mon Sep 17 00:00:00 2001 From: benjamin Date: Sat, 24 Aug 2024 15:05:06 +0200 Subject: [PATCH 48/84] :art: removed unnecessary functions and updated documentation --- .../networks/views/extended_rank_view.hpp | 104 +++++++----------- test/networks/views/extended_rank_view.cpp | 7 +- 2 files changed, 41 insertions(+), 70 deletions(-) diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index 7d58e618c..ba7c00b29 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -2,7 +2,8 @@ // Created by benjamin on 18.06.24. // -#include "fiction/networks/virtual_pi_network.hpp" +#ifndef FICTION_EXTENDED_RANK_VIEW_HPP +#define FICTION_EXTENDED_RANK_VIEW_HPP #include #include @@ -16,9 +17,8 @@ #include #include -#ifndef FICTION_VIRTUAL_RANK_VIEW_HPP -#define FICTION_VIRTUAL_RANK_VIEW_HPP - +namespace fiction +{ /** * @class extended_rank_view. Extends the mockturtle::rank_view * @@ -36,8 +36,8 @@ * - has_foreach_node_in_rank_v * - has_foreach_gate_in_rank_v * - * @tparam Ntk - The network type. - * @tparam has_rank_interface - Boolean flag checked compile-time, determines if the provided Ntk supports the rank + * @tparam Ntk The network type. + * @tparam has_rank_interface Boolean flag checked compile-time, determines if the provided Ntk supports the rank * interface */ template class extended_rank_view : public mockturtle::depth_view { public: - extended_rank_view(Ntk const& ntk) : mockturtle::depth_view(ntk) {} + extended_rank_view(const Ntk& ntk) : mockturtle::depth_view(ntk) {} }; /** @@ -66,7 +66,7 @@ class extended_rank_view : public mockturtle::depth_view * * If no rank_interface exists, inherits from mockturtle::depth_view and initializes ranks for the network. * - * @tparam Ntk - The network type. + * @tparam Ntk The network type. */ template class extended_rank_view : public mockturtle::depth_view @@ -99,9 +99,9 @@ class extended_rank_view : public mockturtle::depth_view * Calls the base class constructor with the provided network, initializes class members, and registers network * events. Also, it ensures that the Network Type (Ntk) needs to support certain methods. * - * @param ntk - Reference to the network. + * @param ntk Reference to the network. */ - explicit extended_rank_view(Ntk const& ntk) : + explicit extended_rank_view(const Ntk& ntk) : mockturtle::depth_view{ntk}, rank_pos{ntk}, ranks{this->depth() + 1}, @@ -122,10 +122,10 @@ class extended_rank_view : public mockturtle::depth_view /** * Constructs an extended_rank_view from an existing network and a specific initial rank configuration. * - * @param ntk - Reference to the network. - * @param ranks - A vector of vectors specifying initial ranks for the nodes within the network. + * @param ntk Reference to the network. + * @param ranks A vector of vectors specifying initial ranks for the nodes within the network. */ - explicit extended_rank_view(Ntk const& ntk, const std::vector>& ranks) : + explicit extended_rank_view(const Ntk& ntk, const std::vector>& ranks) : mockturtle::depth_view{ntk}, rank_pos{ntk}, ranks{this->depth() + 1}, @@ -146,11 +146,11 @@ class extended_rank_view : public mockturtle::depth_view /** * Copy constructor creates a new extended_rank_view by copying the content of another extended_rank_view. * - * @param other - The other extended_rank_view object to be copied. + * @param other The other extended_rank_view object to be copied. */ - extended_rank_view(extended_rank_view const& other) : + extended_rank_view(const extended_rank_view& other) : mockturtle::depth_view(other), - rank_pos{other}, + rank_pos{other.rank_pos}, ranks{other.ranks}, max_rank_width{other.max_rank_width} { @@ -160,10 +160,10 @@ class extended_rank_view : public mockturtle::depth_view /** * Overloaded assignment operator for copying `extended_rank_view` content of another `extended_rank_view` object. * - * @param other - The source `extended_rank_view` object whose contents are being copied. + * @param other The source `extended_rank_view` object whose contents are being copied. * @return A reference to the current object, enabling chain assignments. */ - extended_rank_view& operator=(extended_rank_view const& other) + extended_rank_view& operator=(const extended_rank_view& other) { /* delete the event of this network */ Ntk::events().release_add_event(add_event); @@ -196,41 +196,13 @@ class extended_rank_view : public mockturtle::depth_view * @param n Node to get the rank position of. * @return Rank position of node `n`. */ - uint32_t rank_position(node const& n) const noexcept + uint32_t rank_position(const node& n) const noexcept { assert(!this->is_constant(n) && "node must not be constant"); return rank_pos[n]; } - /* - * Removes all virtual input nodes from the network. - * - * The purpose of this function is to facilitate network equivalence checking. This function is primarily - * intended for network types that resemble `fiction::virtual_pi_network`. - */ - // template - // typename std::enable_if>::type remove_virtual_input_nodes() - void remove_virtual_input_nodes() - { - if constexpr (fiction::has_remove_virtual_input_nodes_v) - { - Ntk::remove_virtual_input_nodes(); - } - rank_pos.reset(); // Clear the node_map - // Clear each vector in ranks - for (auto& rank : ranks) - { - rank.clear(); - } - // Finally, clear the ranks vector itself - // ranks.clear(); - - // Reset max_rank_width - max_rank_width = 0; - this->init_ranks(); - } - /** * Verifies the validity of ranks and rank positions within the extended_rank_view context. * @@ -266,7 +238,7 @@ class extended_rank_view : public mockturtle::depth_view * @param level Level at which to replace nodes. * @param nodes The new nodes to be set at the given level. */ - void modify_rank(uint32_t const level, const std::vector& nodes) + void modify_rank(const uint32_t level, const std::vector& nodes) { auto& rank = ranks[level]; rank = nodes; @@ -280,7 +252,7 @@ class extended_rank_view : public mockturtle::depth_view * @param pos The position within the rank from which to obtain the node. * @return The node that resides at the `pos` in the `level`. */ - node at_rank_position(uint32_t const level, uint32_t const pos) const noexcept + [[nodiscard]] node at_rank_position(const uint32_t level, const uint32_t pos) const noexcept { assert(level < ranks.size() && "level must be less than the number of ranks"); assert(pos < ranks[level].size() && "pos must be less than the number of nodes in rank"); @@ -301,7 +273,7 @@ class extended_rank_view : public mockturtle::depth_view * * @return Width of the rank. */ - uint32_t rank_width(uint32_t const level) noexcept + uint32_t rank_width(const uint32_t level) noexcept { auto& rank = ranks[level]; return rank.size(); @@ -312,7 +284,7 @@ class extended_rank_view : public mockturtle::depth_view * @param n1 First node to swap. * @param n2 Second node to swap. */ - void swap(node const& n1, node const& n2) noexcept + void swap(const node& n1, const node& n2) noexcept { assert(this->level(n1) == this->level(n2) && "nodes must be in the same rank"); @@ -331,7 +303,7 @@ class extended_rank_view : public mockturtle::depth_view * @param cmp The comparator to use. */ template - void sort_rank(uint32_t const level, Cmp const& cmp) + void sort_rank(const uint32_t level, const Cmp& cmp) { // level must be less than the number of ranks if (level < ranks.size()) @@ -350,7 +322,7 @@ class extended_rank_view : public mockturtle::depth_view * @param fn The function to apply. */ template - void foreach_node_in_rank(uint32_t const level, Fn&& fn) const + void foreach_node_in_rank(const uint32_t level, Fn&& fn) const { // level must be less than the number of ranks if (level < ranks.size()) @@ -384,7 +356,7 @@ class extended_rank_view : public mockturtle::depth_view * @param fn The function to apply. */ template - void foreach_gate_in_rank(uint32_t const level, Fn&& fn) const + void foreach_gate_in_rank(const uint32_t level, Fn&& fn) const { // level must be less than the number of ranks if (level < ranks.size()) @@ -455,7 +427,7 @@ class extended_rank_view : public mockturtle::depth_view * * @param n The node to insert into the rank. */ - void insert_in_rank(node const& n) noexcept + void insert_in_rank(const node& n) { auto& rank = ranks[this->level(n)]; rank_pos[n] = rank.size(); @@ -468,7 +440,7 @@ class extended_rank_view : public mockturtle::depth_view * * @param n The node to be added. */ - void on_add(node const& n) noexcept + void on_add(const node& n) noexcept { if (this->level(n) >= ranks.size()) { @@ -504,12 +476,9 @@ class extended_rank_view : public mockturtle::depth_view * @param n The node to be inserted. * @param rank_level The level at which the node should be inserted in the rank. */ - void insert_in_rank(node const& n, std::size_t rank_level) noexcept + void insert_in_rank(const node& n, std::size_t rank_level) { - if (rank_level >= ranks.size()) - { - throw std::out_of_range("Rank level is out of range"); - } + assert(rank_level < ranks.size()); auto& rank = ranks[rank_level]; rank_pos[n] = rank.size(); rank.push_back(n); @@ -520,9 +489,8 @@ class extended_rank_view : public mockturtle::depth_view * Initializes the ranks with the given array of nodes. * * @param input_ranks The input vector of ranks. - * @return void */ - void init_ranks(std::vector> const& input_ranks) noexcept + void init_ranks(const std::vector>& input_ranks) { for (std::size_t i = 0; i < input_ranks.size(); ++i) { @@ -544,7 +512,7 @@ class extended_rank_view : public mockturtle::depth_view * @tparam T Network type deduced from the construction context of `extended_rank_view`. */ template -extended_rank_view(T const&) -> extended_rank_view; +extended_rank_view(const T&) -> extended_rank_view; /** * Deduction guide for `extended_rank_view` with two constructor arguments @@ -552,6 +520,8 @@ extended_rank_view(T const&) -> extended_rank_view; * @tparam T Network type deduced from the construction context of `extended_rank_view`. */ template -extended_rank_view(T const&, std::vector>) -> extended_rank_view; +extended_rank_view(const T&, std::vector>) -> extended_rank_view; + +} // namespace fiction -#endif // FICTION_VIRTUAL_RANK_VIEW_HPP +#endif // FICTION_EXTENDED_RANK_VIEW_HPP diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index 3b9e12b8e..d1171519f 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -23,6 +22,8 @@ #include #include +#include + using namespace fiction; TEMPLATE_TEST_CASE("traits", "[extended_rank_view]", mockturtle::aig_network, mockturtle::mig_network, @@ -127,7 +128,7 @@ TEMPLATE_TEST_CASE("Check equivalence checking", "[extended_rank_view]", mocktur mockturtle::equivalence_checking_stats st; const auto maybe_cec_m = - mockturtle::equivalence_checking(*mockturtle::miter(ntk, ntk_r), {}, &st); + mockturtle::equivalence_checking(*fiction::virtual_miter(ntk, ntk_r), {}, &st); REQUIRE(maybe_cec_m.has_value()); const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); @@ -170,7 +171,7 @@ TEST_CASE("Check equivalence checking for virtual PIs", "[extended-rank-view]") auto vpi_r = extended_rank_view(vpi); mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = mockturtle::equivalence_checking(*fiction::miter(tec, vpi_r), {}, &st); + const auto maybe_cec_m = mockturtle::equivalence_checking(*fiction::virtual_miter(tec, vpi_r), {}, &st); REQUIRE(maybe_cec_m.has_value()); const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); From de97080609da11742d7ebd25a729f112620fcd0b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 24 Aug 2024 13:05:32 +0000 Subject: [PATCH 49/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/networks/views/extended_rank_view.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index d1171519f..a71a49f1d 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -171,7 +171,8 @@ TEST_CASE("Check equivalence checking for virtual PIs", "[extended-rank-view]") auto vpi_r = extended_rank_view(vpi); mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = mockturtle::equivalence_checking(*fiction::virtual_miter(tec, vpi_r), {}, &st); + const auto maybe_cec_m = + mockturtle::equivalence_checking(*fiction::virtual_miter(tec, vpi_r), {}, &st); REQUIRE(maybe_cec_m.has_value()); const bool cec_m = *maybe_cec_m; CHECK(cec_m == 1); From 2080f605bc39ee5ff63b407a143544fccec15ebb Mon Sep 17 00:00:00 2001 From: benjamin Date: Sat, 24 Aug 2024 16:29:03 +0200 Subject: [PATCH 50/84] :art: updated files for consistency --- .../node_duplication_planarization.hpp | 184 ++++++++---------- include/fiction/traits.hpp | 43 ++++ .../node_duplication_planarization.cpp | 30 +-- 3 files changed, 142 insertions(+), 115 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index b4e7f5f6d..232f02184 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -9,17 +9,17 @@ #include "fiction/algorithms/properties/check_planarity.hpp" #include "fiction/networks/views/extended_rank_view.hpp" #include "fiction/networks/virtual_pi_network.hpp" -#include "fiction/traits.hpp" #include -#include #include +#include #include -#include -#include -#include +#include +#include +#include #include +#include #include #include @@ -33,7 +33,7 @@ namespace fiction /** * Parameters for the node duplication algorithm. */ -struct node_duplication_params +struct node_duplication_planarization_params { /** * The output order determines the starting layer for this algorithm. If this option is turned off, the output order @@ -46,9 +46,7 @@ namespace detail { /** - * @brief A structure representing a pair of nodes in an H-graph - * - * @tparam Ntk Network type for the nodes in the pair + * A structure representing a pair of nodes in an H-graph. * * The nodes stored in this struct describe the fanin-edges of a node in an H-graph. * A node pair object holds two nodes, which are saved in the member 'pair'. @@ -57,37 +55,33 @@ namespace detail * second node in 'pair'. The order of 'middle_nodes' is arbitrary as they cannot be further connected to any other * nodes. For the planarization, only the nodes inside the 'pair' are relevant. * - * - * @note The edges connecting to the nodes in 'pair' effectively block the 'middle_nodes'. + * @tparam Ntk Network type for the nodes in the pair. */ template struct node_pair { /** - * Defines the beginning and end of the fanin-edged node + * Defines the beginning and end of the fanin-edged node. */ std::pair, mockturtle::node> pair; /** - * Contains the nodes between the fanin-edges node; cannot be connected to any other node + * Contains the nodes between the fanin-edges node; cannot be connected to any other node. */ std::vector> middle_nodes; - /** - * Shared pointer to another instance of node_pair detailing fanin-edge alignment + * Shared pointer to another instance of node_pair detailing fanin-edge alignment. */ std::shared_ptr> fanin_pair; - /** - * Specifies the delay value for the node + * Specifies the delay value for the node. */ uint64_t delay; - /** - * @brief node_pair constructor + * Standard constructor. * - * @param node1 The first node of the fanin-edged node - * @param node2 The second node of the fanin-edged node - * @param delayValue The delay value for the node + * @param node1 The first node of the fanin-edged node. + * @param node2 The second node of the fanin-edged node. + * @param delayValue The delay value for the node. */ node_pair(mockturtle::node node1, mockturtle::node node2, uint64_t delayValue) : pair(node1, node2), @@ -96,7 +90,7 @@ struct node_pair }; /** - * @brief Calculates pairs of nodes from a given vector of nodes. + * Calculates pairs of nodes from a given vector of nodes. * * This function takes a vector of nodes and returns a vector of node pairs. Each node pair consists of two nodes from * the input vector and an optional vector of middle nodes. The delay of each node pair is initialized to infinity. @@ -106,27 +100,27 @@ struct node_pair * @return The vector of node pairs. */ template -std::vector> calculate_pairs(const std::vector>& nodes) +[[nodiscard]] std::vector> calculate_pairs(const std::vector>& nodes) noexcept { - std::vector> pairwise_combinations; - std::vector> middle_nodes; + std::vector> pairwise_combinations{}; + pairwise_combinations.reserve(nodes.size() * (nodes.size() - 1)); if (nodes.size() == 1) { - node_pair pair = {nodes[0], nodes[0], std::numeric_limits::max()}; // Initialize delay to inf + const node_pair pair = {nodes[0], nodes[0], std::numeric_limits::max()}; // Initialize delay to inf pairwise_combinations.push_back(pair); return pairwise_combinations; } - for (auto it1 = nodes.begin(); it1 != nodes.end(); ++it1) + for (auto it1 = nodes.cbegin(); it1 != nodes.cend(); ++it1) { - for (auto it2 = it1 + 1; it2 != nodes.end(); ++it2) + for (auto it2 = it1 + 1; it2 != nodes.cend(); ++it2) { - // Clear middle_nodes before the next pair - middle_nodes.clear(); + std::vector> middle_nodes{}; + middle_nodes.reserve(nodes.size() - 2); // fill middle_nodes with non-pair members - for (auto it = nodes.begin(); it != nodes.end(); ++it) + for (auto it = nodes.cbegin(); it != nodes.cend(); ++it) { if (it != it1 && it != it2) { @@ -153,14 +147,11 @@ template class node_duplication_planarization_impl { public: - node_duplication_planarization_impl(const Ntk& src, const node_duplication_params p) : ntk(src), ps{p} {} + node_duplication_planarization_impl(const Ntk& src, const node_duplication_planarization_params& p) : ntk(src), ps{p} + {} /** - * @brief Computes the delay in a given slice (each possible order of node_pairs) of an H-graph - * - * @param nd Node in the H-graph - * @param border_pis A boolean indicating whether the input PIs (Primary Inputs) should be propagated to the next - * level + * Computes the delay in a given slice (each possible order of node_pairs) of an H-graph. * * This function iterates over the fanins of the given node and computes the delay for all possible orders * of these nodes that form a node_pair. The delay computation depends on the node's connections and position @@ -170,8 +161,9 @@ class node_duplication_planarization_impl * * The processed node_pairs are pushed back to the 'lvl_pairs' data member for subsequent delay calculations. * - * @throws std::runtime_error if no combinations (possible node_pairs) are found, which might suggest a dangling - * node + * @param nd Node in the H-graph. + * @param border_pis A boolean indicating whether the input PIs (Primary Inputs) should be propagated to the next + * level. */ void compute_slice_delays(const mockturtle::node& nd, const bool border_pis) { @@ -183,14 +175,13 @@ class node_duplication_planarization_impl ntk.foreach_fanin(nd, [this](auto fi) { fis.push_back(fi); }); // Compute the combinations in one slice auto combinations = calculate_pairs(fis); - if (combinations.empty()) - { - throw std::runtime_error("Combinations are empty. There might be a dangling node"); - } + assert(!combinations.empty() && "Combinations are empty. There might be a dangling node"); std::vector> combinations_last; + if (!lvl_pairs.empty()) { combinations_last = lvl_pairs.back(); + for (auto& node_pair_cur : combinations) { for (auto& node_pair_last : combinations_last) @@ -224,16 +215,15 @@ class node_duplication_planarization_impl } /** - * @brief Inserts a node into a vector if it is unique + * Inserts a node into a vector if it is unique. * * This function inserts a node into a vector only if the vector is empty or the node is not equal to the first * element of the vector. If the vector is not empty and the node is equal to the first element, it does nothing. * - * @tparam Ntk The network type - * @param node The node to be inserted - * @param vec The vector to insert the node into + * @param node The node to be inserted. + * @param vec The vector to insert the node into. */ - void insert_if_unique(const mockturtle::node& node, std::vector>& vec) + void insert_if_not_first(const mockturtle::node& node, std::vector>& vec) { if (vec.empty() || vec.front() != node) { @@ -242,52 +232,52 @@ class node_duplication_planarization_impl } /** - * @brief Computes the order of nodes in the next level based on delay - * - * @param next_level The vector to store the nodes in the next level + * Computes the order of nodes in the next level based on delay * * This function computes the order of nodes in the next level based on their delay in the H-graph of the level. It * selects the path with the least delay from the current level pairs and follows it via fanin relations. The nodes * are inserted into the next level vector in the order they are encountered. + * + * @param next_level The vector to store the nodes in the next level. */ void compute_node_order_next_level(std::vector>& next_level) { const auto& combinations = lvl_pairs.back(); // select the path with the least delay and follow it via fanin relations - auto minimum_it = - std::min_element(combinations.begin(), combinations.end(), + const auto minimum_it = + std::min_element(combinations.cbegin(), combinations.cend(), [](const node_pair& a, const node_pair& b) { return a.delay < b.delay; }); - if (minimum_it != combinations.end()) + if (minimum_it != combinations.cend()) { const auto& min_combination = *minimum_it; // Insert the terminal node - insert_if_unique(min_combination.pair.second, next_level); + insert_if_not_first(min_combination.pair.second, next_level); // insert middle_nodes for (const auto& node : min_combination.middle_nodes) { - insert_if_unique(node, next_level); + insert_if_not_first(node, next_level); } // Insert the first node - insert_if_unique(min_combination.pair.first, next_level); + insert_if_not_first(min_combination.pair.first, next_level); - std::shared_ptr> fanin_combination = minimum_it->fanin_pair; + auto fanin_combination = minimum_it->fanin_pair; while (fanin_combination) { // Insert the terminal node - insert_if_unique(fanin_combination->pair.second, next_level); + insert_if_not_first(fanin_combination->pair.second, next_level); // Insert middle_nodes for (const auto& node : fanin_combination->middle_nodes) { - insert_if_unique(node, next_level); + insert_if_not_first(node, next_level); } // insert the first node - insert_if_unique(fanin_combination->pair.first, next_level); + insert_if_not_first(fanin_combination->pair.first, next_level); fanin_combination = fanin_combination->fanin_pair; } @@ -295,35 +285,36 @@ class node_duplication_planarization_impl } /** - * @brief Checks if the given vector of nodes contains any non-primary inputs. + * Checks if the given vector of nodes contains any non-primary inputs. * * This function iterates through each node in the vector and checks if it is a primary input. * If a non-primary input is found, the `f_final_level` parameter is set to false and the loop is exited. * - * @param v_next_level The vector of nodes to be checked - * @param f_final_level A reference to a boolean indicating if the vector contains only primary inputs + * @param v_next_level The vector of nodes to be checked. */ - void check_final_level(const std::vector>& v_next_level, bool& f_final_level) + [[nodiscard]] bool check_final_level(const std::vector>& v_next_level) { for (const auto& nd : v_next_level) { if (!ntk.is_pi(nd)) { - f_final_level = false; - break; + return false; } } + return true; } - virtual_pi_network run(std::vector>>& ntk_lvls_new) + [[nodiscard]] virtual_pi_network run(std::vector>>& ntk_lvls_new) { + // ToDO: implement border_pis (if there is a choice ush pis to the borders (first or last rank)) const bool border_pis = true; std::unordered_map po_counts; ntk.foreach_po([&po_counts](auto po) { po_counts[po]++; }); - std::vector pos; + std::vector pos{}; + pos.reserve(ntk.num_pos()); for (const auto& kv : po_counts) { pos.push_back(kv.first); @@ -333,14 +324,14 @@ class node_duplication_planarization_impl if (ps.random_output_order) { // Generate a random engine - std::random_device rd; - std::mt19937 g(rd()); + static std::mt19937_64 generator(std::random_device{}()); // Shuffle the pos vector - std::shuffle(pos.begin(), pos.end(), g); + std::shuffle(pos.begin(), pos.end(), generator); } // save the nodes of the next level - std::vector> v_level; + std::vector> v_level{}; + v_level.reserve(pos.size()); // Process the first level for (const auto& po : pos) { @@ -357,8 +348,7 @@ class node_duplication_planarization_impl // until the last levels this should only happen if border_pis == true compute_node_order_next_level(v_level); - bool f_final_level = true; - check_final_level(v_level, f_final_level); + bool f_final_level = check_final_level(v_level); // Process all other levels while (!v_level.empty() && !f_final_level) @@ -378,8 +368,7 @@ class node_duplication_planarization_impl // Compute the next level compute_node_order_next_level(v_level); // Check if we are at the final level - f_final_level = true; - check_final_level(v_level, f_final_level); + f_final_level = check_final_level(v_level); } // Push the final level (PIs) if (f_final_level) @@ -388,43 +377,36 @@ class node_duplication_planarization_impl } // create virtual pi network - auto new_ntk = virtual_pi_network(ntk, ntk_lvls, ntk_lvls_new); - - return new_ntk; // mockturtle::rank_view(ntk); + return virtual_pi_network(ntk, ntk_lvls, ntk_lvls_new); } private: /* * The input network. */ - Ntk ntk; + Ntk ntk{}; /* * The currently node_pairs used in the current level. */ - std::vector>> lvl_pairs; + std::vector>> lvl_pairs{}; /* * The fanin nodes. */ - std::vector> fis; + std::vector> fis{}; /* * The network stored as levels. */ - std::vector>> ntk_lvls; + std::vector>> ntk_lvls{}; /* * The stats of the node_duplication class. */ - node_duplication_params ps; + node_duplication_planarization_params ps{}; }; } // namespace detail /** - * @brief Implements a planarization mechanism for networks using a H-Graph strategy for node duplication. - * - * @tparam NtkDest Destination network type - * @tparam NtkSrc Source network type - * @param ntk_src Source network to be utilized for the planarization - * @param ps Node duplication parameters used in the computation + * Implements a planarization mechanism for networks using a H-Graph strategy for node duplication. * * The planarization achieved by this function solves the Node Duplication Crossing Minimization (NDCE) problem by * finding the shortest x-y path in the H-graph for every level in the network. An H-graph describes edge relations @@ -433,25 +415,27 @@ class node_duplication_planarization_impl * found. The function constructs an H-graph that captures edge relations between two levels within the graph and * computes the shortest x-y paths on the H-graph, traversing from the POs towards the Primary Inputs (PIs). * - * @return A view of the planarized virtual_pi_network created in the format of extended_rank_view + * @return A view of the planarized virtual_pi_network created in the format of extended_rank_view. + * + * @tparam NtkDest Destination network type. + * @tparam NtkSrc Source network type. + * @param ntk_src Source network to be utilized for the planarization. + * @param ps Node duplication parameters used in the computation. * * @throws std::runtime_error if input network not balanced, if no node combinations are found or if - * the created network is non-planar + * the created network is non-planar. * */ template -extended_rank_view> -node_duplication_planarization(const NtkSrc& ntk_src, node_duplication_params ps = {}) +[[nodiscard]] extended_rank_view> +node_duplication_planarization(const NtkSrc& ntk_src, const node_duplication_planarization_params& ps = {}) { static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); // check the network to be a technology network (is there a better check/trait?) static_assert(mockturtle::has_create_le_v, "T must be of type const ExpectedType"); - if (!is_balanced(ntk_src)) - { - throw std::runtime_error("Combinations are empty. There might be a dangling node"); - } + assert (is_balanced(ntk_src) && "Networks have to be balanced for this duplication"); detail::node_duplication_planarization_impl p{ntk_src, ps}; diff --git a/include/fiction/traits.hpp b/include/fiction/traits.hpp index 7feed90be..a7c8cb00f 100644 --- a/include/fiction/traits.hpp +++ b/include/fiction/traits.hpp @@ -1297,6 +1297,49 @@ template inline constexpr bool has_num_real_pis_v = has_num_real_pis::value; #pragma endregion +#pragma region has_num_virtual_pis +template +struct has_num_virtual_pis : std::false_type +{}; + +template +struct has_num_virtual_pis().num_virtual_pis())>> : std::true_type +{}; + +template +inline constexpr bool has_num_virtual_pis_v = has_num_virtual_pis::value; +#pragma endregion + +#pragma region has_foreach_pi +template +struct has_foreach_real_pi : std::false_type +{ +}; + +template +struct has_foreach_real_pi().foreach_real_pi( std::declval, uint32_t )>() ) )>> : std::true_type +{ +}; + +template +inline constexpr bool has_foreach_real_pi_v = has_foreach_real_pi::value; +#pragma endregion + +#pragma region has_index_to_node +template +struct has_get_real_pi : std::false_type +{ +}; + +template +struct has_get_real_pi().get_real_pi( mockturtle::node() ) )>> : std::true_type +{ +}; + +template +inline constexpr bool has_get_real_pi_v = has_get_real_pi::value; +#pragma endregion + #pragma region has_remove_virtual_input_nodes template struct has_remove_virtual_input_nodes : std::false_type diff --git a/test/algorithms/network_transformation/node_duplication_planarization.cpp b/test/algorithms/network_transformation/node_duplication_planarization.cpp index 4fda94719..a9aefbad9 100644 --- a/test/algorithms/network_transformation/node_duplication_planarization.cpp +++ b/test/algorithms/network_transformation/node_duplication_planarization.cpp @@ -5,18 +5,18 @@ #include #include "fiction/algorithms/network_transformation/network_balancing.hpp" -#include "utils/blueprints/network_blueprints.hpp" #include #include #include #include -#include +#include +#include using namespace fiction; -TEST_CASE("2-ary nodes Test", "[node-duplication-planarization]") +TEST_CASE("Planarize technology ntk", "[node-duplication-planarization]") { technology_network tec{}; @@ -43,12 +43,12 @@ TEST_CASE("2-ary nodes Test", "[node-duplication-planarization]") mockturtle::equivalence_checking_stats st; const auto cec_m = - mockturtle::equivalence_checking(*fiction::miter(tec, planarized_maj), {}, &st); + mockturtle::equivalence_checking(*fiction::virtual_miter(tec, planarized_maj), {}, &st); REQUIRE(cec_m.has_value()); CHECK(*cec_m == 1); } -TEST_CASE("3-ary nodes Test", "[node-duplication-planarization]") +TEST_CASE("Planarize ntk with 3-ary node", "[node-duplication-planarization]") { technology_network tec{}; @@ -77,12 +77,12 @@ TEST_CASE("3-ary nodes Test", "[node-duplication-planarization]") mockturtle::equivalence_checking_stats st; const auto cec_m = - mockturtle::equivalence_checking(*fiction::miter(tec, planarized_maj), {}, &st); + mockturtle::equivalence_checking(*fiction::virtual_miter(tec, planarized_maj), {}, &st); REQUIRE(cec_m.has_value()); CHECK(*cec_m == 1); } -TEST_CASE("Aig Test", "[node-duplication-planarization]") +TEST_CASE("Buffer AIG and planarize technology_network", "[node-duplication-planarization]") { mockturtle::aig_network aig{}; @@ -111,14 +111,14 @@ TEST_CASE("Aig Test", "[node-duplication-planarization]") mockturtle::equivalence_checking_stats st; const auto cec_m = - mockturtle::equivalence_checking(*fiction::miter(aig, planarized_maj), {}, &st); + mockturtle::equivalence_checking(*fiction::virtual_miter(aig, planarized_maj), {}, &st); REQUIRE(cec_m.has_value()); CHECK(*cec_m == 1); } -TEST_CASE("Aig Test 2", "[node-duplication-planarization]") +TEST_CASE("Buffer AIG and planarize technology_network 2", "[node-duplication-planarization]") { - technology_network aig{}; + mockturtle::aig_network aig{}; const auto x1 = aig.create_pi(); const auto x2 = aig.create_pi(); @@ -138,12 +138,12 @@ TEST_CASE("Aig Test 2", "[node-duplication-planarization]") mockturtle::equivalence_checking_stats st; const auto cec_m = - mockturtle::equivalence_checking(*fiction::miter(aig, planarized_maj), {}, &st); + mockturtle::equivalence_checking(*fiction::virtual_miter(aig, planarized_maj), {}, &st); REQUIRE(cec_m.has_value()); CHECK(*cec_m == 1); } -TEST_CASE("Multi output network", "[node-duplication-planarization]") +TEST_CASE("Planarize multi output network", "[node-duplication-planarization]") { mockturtle::aig_network aig{}; @@ -154,8 +154,8 @@ TEST_CASE("Multi output network", "[node-duplication-planarization]") aig.create_po(a1); aig.create_po(a1); - /*aig.create_po(a1); - aig.create_po(a1);*/ + aig.create_po(a1); + aig.create_po(a1); network_balancing_params ps; ps.unify_outputs = true; @@ -168,7 +168,7 @@ TEST_CASE("Multi output network", "[node-duplication-planarization]") mockturtle::equivalence_checking_stats st; const auto cec_m = - mockturtle::equivalence_checking(*fiction::miter(aig, planarized_maj), {}, &st); + mockturtle::equivalence_checking(*fiction::virtual_miter(aig, planarized_maj), {}, &st); REQUIRE(cec_m.has_value()); CHECK(*cec_m == 1); } From f722484e96f6b9be8963010cf884ce39f9794f84 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:29:25 +0000 Subject: [PATCH 51/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../node_duplication_planarization.hpp | 13 ++++---- include/fiction/traits.hpp | 30 +++++++++---------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 232f02184..aef5ed551 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -15,9 +15,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -102,12 +102,13 @@ struct node_pair template [[nodiscard]] std::vector> calculate_pairs(const std::vector>& nodes) noexcept { - std::vector> pairwise_combinations{}; + std::vector> pairwise_combinations{}; pairwise_combinations.reserve(nodes.size() * (nodes.size() - 1)); if (nodes.size() == 1) { - const node_pair pair = {nodes[0], nodes[0], std::numeric_limits::max()}; // Initialize delay to inf + const node_pair pair = {nodes[0], nodes[0], + std::numeric_limits::max()}; // Initialize delay to inf pairwise_combinations.push_back(pair); return pairwise_combinations; } @@ -147,7 +148,9 @@ template class node_duplication_planarization_impl { public: - node_duplication_planarization_impl(const Ntk& src, const node_duplication_planarization_params& p) : ntk(src), ps{p} + node_duplication_planarization_impl(const Ntk& src, const node_duplication_planarization_params& p) : + ntk(src), + ps{p} {} /** @@ -435,7 +438,7 @@ node_duplication_planarization(const NtkSrc& ntk_src, const node_duplication_pla // check the network to be a technology network (is there a better check/trait?) static_assert(mockturtle::has_create_le_v, "T must be of type const ExpectedType"); - assert (is_balanced(ntk_src) && "Networks have to be balanced for this duplication"); + assert(is_balanced(ntk_src) && "Networks have to be balanced for this duplication"); detail::node_duplication_planarization_impl p{ntk_src, ps}; diff --git a/include/fiction/traits.hpp b/include/fiction/traits.hpp index a7c8cb00f..c539ab777 100644 --- a/include/fiction/traits.hpp +++ b/include/fiction/traits.hpp @@ -1311,32 +1311,30 @@ inline constexpr bool has_num_virtual_pis_v = has_num_virtual_pis::value; #pragma endregion #pragma region has_foreach_pi -template +template struct has_foreach_real_pi : std::false_type -{ -}; +{}; -template -struct has_foreach_real_pi().foreach_real_pi( std::declval, uint32_t )>() ) )>> : std::true_type -{ -}; +template +struct has_foreach_real_pi().foreach_real_pi( + std::declval, uint32_t)>()))>> : std::true_type +{}; -template +template inline constexpr bool has_foreach_real_pi_v = has_foreach_real_pi::value; #pragma endregion #pragma region has_index_to_node -template +template struct has_get_real_pi : std::false_type -{ -}; +{}; -template -struct has_get_real_pi().get_real_pi( mockturtle::node() ) )>> : std::true_type -{ -}; +template +struct has_get_real_pi().get_real_pi(mockturtle::node()))>> + : std::true_type +{}; -template +template inline constexpr bool has_get_real_pi_v = has_get_real_pi::value; #pragma endregion From 3926c47e856235a3432d3247ce63b34bc198cf25 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sat, 24 Aug 2024 14:30:09 +0000 Subject: [PATCH 52/84] :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions --- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 166 +++++++++--------- 1 file changed, 79 insertions(+), 87 deletions(-) diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index 237cfbd5c..54b3e83cd 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -23,32 +23,6 @@ #endif -static const char *__doc_extended_rank_view = -R"doc(@class extended_rank_view - -If already a rank_interface exists only the depth_view constructor -gets called. - -Template parameter ``Ntk``: - - The network type.)doc"; - -static const char *__doc_extended_rank_view_2 = -R"doc(Deduction guide for `extended_rank_view' - -Template parameter ``T``: - Network type deduced from the construction context of - `extended_rank_view`.)doc"; - -static const char *__doc_extended_rank_view_3 = -R"doc(Deduction guide for `extended_rank_view` with two constructor -arguments - -Template parameter ``T``: - Network type deduced from the construction context of - `extended_rank_view`.)doc"; - -static const char *__doc_extended_rank_view_extended_rank_view = R"doc()doc"; - static const char *__doc_fiction_a_star = R"doc(The A* path finding algorithm for shortest loop-less paths between a given source and target coordinate in a layout. This function @@ -6411,34 +6385,23 @@ it is a primary input. If a non-primary input is found, the `f_final_level` parameter is set to false and the loop is exited. Parameter ``v_next_level``: - The vector of nodes to be checked - -Parameter ``f_final_level``: - A reference to a boolean indicating if the vector contains only - primary inputs)doc"; + The vector of nodes to be checked.)doc"; static const char *__doc_fiction_detail_node_duplication_planarization_impl_compute_node_order_next_level = R"doc(Computes the order of nodes in the next level based on delay -Parameter ``next_level``: - The vector to store the nodes in the next level - This function computes the order of nodes in the next level based on their delay in the H-graph of the level. It selects the path with the least delay from the current level pairs and follows it via fanin relations. The nodes are inserted into the next level vector in the -order they are encountered.)doc"; +order they are encountered. + +Parameter ``next_level``: + The vector to store the nodes in the next level.)doc"; static const char *__doc_fiction_detail_node_duplication_planarization_impl_compute_slice_delays = R"doc(Computes the delay in a given slice (each possible order of -node_pairs) of an H-graph - -Parameter ``nd``: - Node in the H-graph - -Parameter ``border_pis``: - A boolean indicating whether the input PIs (Primary Inputs) should - be propagated to the next level +node_pairs) of an H-graph. This function iterates over the fanins of the given node and computes the delay for all possible orders of these nodes that form a @@ -6453,26 +6416,26 @@ updated. The processed node_pairs are pushed back to the 'lvl_pairs' data member for subsequent delay calculations. -Throws: - std::runtime_error if no combinations (possible node_pairs) are - found, which might suggest a dangling node)doc"; +Parameter ``nd``: + Node in the H-graph. + +Parameter ``border_pis``: + A boolean indicating whether the input PIs (Primary Inputs) should + be propagated to the next level.)doc"; -static const char *__doc_fiction_detail_node_duplication_planarization_impl_insert_if_unique = -R"doc(Inserts a node into a vector if it is unique +static const char *__doc_fiction_detail_node_duplication_planarization_impl_insert_if_not_first = +R"doc(Inserts a node into a vector if it is unique. This function inserts a node into a vector only if the vector is empty or the node is not equal to the first element of the vector. If the vector is not empty and the node is equal to the first element, it does nothing. -Template parameter ``Ntk``: - The network type - Parameter ``node``: - The node to be inserted + The node to be inserted. Parameter ``vec``: - The vector to insert the node into)doc"; + The vector to insert the node into.)doc"; static const char *__doc_fiction_detail_node_duplication_planarization_impl_lvl_pairs = R"doc()doc"; @@ -6485,10 +6448,7 @@ static const char *__doc_fiction_detail_node_duplication_planarization_impl_ps = static const char *__doc_fiction_detail_node_duplication_planarization_impl_run = R"doc()doc"; static const char *__doc_fiction_detail_node_pair = -R"doc(A structure representing a pair of nodes in an H-graph - -Template parameter ``Ntk``: - Network type for the nodes in the pair +R"doc(A structure representing a pair of nodes in an H-graph. The nodes stored in this struct describe the fanin-edges of a node in an H-graph. A node pair object holds two nodes, which are saved in the @@ -6499,26 +6459,26 @@ second node in 'pair'. The order of 'middle_nodes' is arbitrary as they cannot be further connected to any other nodes. For the planarization, only the nodes inside the 'pair' are relevant. -@note The edges connecting to the nodes in 'pair' effectively block -the 'middle_nodes'.)doc"; +Template parameter ``Ntk``: + Network type for the nodes in the pair.)doc"; -static const char *__doc_fiction_detail_node_pair_delay = R"doc(Specifies the delay value for the node)doc"; +static const char *__doc_fiction_detail_node_pair_delay = R"doc(Specifies the delay value for the node.)doc"; static const char *__doc_fiction_detail_node_pair_fanin_pair = R"doc(Shared pointer to another instance of node_pair detailing fanin-edge -alignment)doc"; +alignment.)doc"; static const char *__doc_fiction_detail_node_pair_node_pair = -R"doc(node_pair constructor +R"doc(Standard constructor. Parameter ``node1``: - The first node of the fanin-edged node + The first node of the fanin-edged node. Parameter ``node2``: - The second node of the fanin-edged node + The second node of the fanin-edged node. Parameter ``delayValue``: - The delay value for the node)doc"; + The delay value for the node.)doc"; static const char *__doc_fiction_detail_on_the_fly_circuit_design_impl = R"doc()doc"; @@ -9103,6 +9063,32 @@ R"doc(*QuickExact* is also an exact simulation engine that requires exponential runtime, but it scales a lot better than ExGS due to its effective search-space pruning.)doc"; +static const char *__doc_fiction_extended_rank_view = +R"doc(@class extended_rank_view + +If already a rank_interface exists only the depth_view constructor +gets called. + +Template parameter ``Ntk``: + The network type.)doc"; + +static const char *__doc_fiction_extended_rank_view_2 = +R"doc(Deduction guide for `extended_rank_view' + +Template parameter ``T``: + Network type deduced from the construction context of + `extended_rank_view`.)doc"; + +static const char *__doc_fiction_extended_rank_view_3 = +R"doc(Deduction guide for `extended_rank_view` with two constructor +arguments + +Template parameter ``T``: + Network type deduced from the construction context of + `extended_rank_view`.)doc"; + +static const char *__doc_fiction_extended_rank_view_extended_rank_view = R"doc()doc"; + static const char *__doc_fiction_extract_routing_objectives = R"doc(Extracts all routing objectives from the given layout. To this end, all routing paths in the layout are traversed, starting at each PI. @@ -11319,6 +11305,8 @@ static const char *__doc_fiction_has_foreach_incoming_clocked_zone = R"doc()doc" static const char *__doc_fiction_has_foreach_outgoing_clocked_zone = R"doc()doc"; +static const char *__doc_fiction_has_foreach_real_pi = R"doc()doc"; + static const char *__doc_fiction_has_foreach_sidb_defect = R"doc()doc"; static const char *__doc_fiction_has_foreach_tile = R"doc()doc"; @@ -11331,6 +11319,8 @@ static const char *__doc_fiction_has_get_gate_ports = R"doc()doc"; static const char *__doc_fiction_has_get_layout_name = R"doc()doc"; +static const char *__doc_fiction_has_get_real_pi = R"doc()doc"; + static const char *__doc_fiction_has_get_sidb_defect = R"doc()doc"; static const char *__doc_fiction_has_high_degree_fanin_nodes = @@ -11429,6 +11419,8 @@ static const char *__doc_fiction_has_north_west = R"doc()doc"; static const char *__doc_fiction_has_num_real_pis = R"doc()doc"; +static const char *__doc_fiction_has_num_virtual_pis = R"doc()doc"; + static const char *__doc_fiction_has_ordinal_operations = R"doc()doc"; static const char *__doc_fiction_has_post_layout_optimization = R"doc()doc"; @@ -13039,30 +13031,10 @@ Parameter ``file``: Parameter ``rfun``: The actual parsing function.)doc"; -static const char *__doc_fiction_node_duplication_params = R"doc(Parameters for the node duplication algorithm.)doc"; - -static const char *__doc_fiction_node_duplication_params_random_output_order = -R"doc(The output order determines the starting layer for this algorithm. If -this option is turned off, the output order remains the same as in the -provided network. If it is turned on, the outputs are ordered -randomly.)doc"; - static const char *__doc_fiction_node_duplication_planarization = R"doc(Implements a planarization mechanism for networks using a H-Graph strategy for node duplication. -Template parameter ``NtkDest``: - Destination network type - -Template parameter ``NtkSrc``: - Source network type - -Parameter ``ntk_src``: - Source network to be utilized for the planarization - -Parameter ``ps``: - Node duplication parameters used in the computation - The planarization achieved by this function solves the Node Duplication Crossing Minimization (NDCE) problem by finding the shortest x-y path in the H-graph for every level in the network. An @@ -13076,11 +13048,31 @@ H-graph, traversing from the POs towards the Primary Inputs (PIs). Returns: A view of the planarized virtual_pi_network created in the format - of extended_rank_view + of extended_rank_view. + +Template parameter ``NtkDest``: + Destination network type. + +Template parameter ``NtkSrc``: + Source network type. + +Parameter ``ntk_src``: + Source network to be utilized for the planarization. + +Parameter ``ps``: + Node duplication parameters used in the computation. Throws: std::runtime_error if input network not balanced, if no node - combinations are found or if the created network is non-planar)doc"; + combinations are found or if the created network is non-planar.)doc"; + +static const char *__doc_fiction_node_duplication_planarization_params = R"doc(Parameters for the node duplication algorithm.)doc"; + +static const char *__doc_fiction_node_duplication_planarization_params_random_output_order = +R"doc(The output order determines the starting layer for this algorithm. If +this option is turned off, the output order remains the same as in the +provided network. If it is turned on, the outputs are ordered +randomly.)doc"; static const char *__doc_fiction_normalize_layout_coordinates = R"doc(A new layout is constructed and returned that is equivalent to the From 2094073c61dfd265189232fd570141e857d1ad72 Mon Sep 17 00:00:00 2001 From: benjamin Date: Sat, 24 Aug 2024 18:21:19 +0200 Subject: [PATCH 53/84] :art: updated files for consistency --- .../algorithms/properties/check_planarity.hpp | 49 ++- .../algorithms/verification/virtual_miter.hpp | 71 ++-- .../fiction/networks/virtual_pi_network.hpp | 306 ++++++++++++++++-- .../algorithms/properties/check_planarity.cpp | 3 + test/networks/virtual_pi_network.cpp | 64 ++-- 5 files changed, 385 insertions(+), 108 deletions(-) diff --git a/include/fiction/algorithms/properties/check_planarity.hpp b/include/fiction/algorithms/properties/check_planarity.hpp index ba277f324..1ab130f73 100644 --- a/include/fiction/algorithms/properties/check_planarity.hpp +++ b/include/fiction/algorithms/properties/check_planarity.hpp @@ -23,16 +23,19 @@ class check_planarity_impl check_planarity_impl(const Ntk& ntk) : ntk(ntk) {} /** - * @brief Checks if a given network is planar. + * Checks if a given network is planar. * * This function checks if the network represented by the variable `ntk` is planar. - * The network is planar if for any edge with starting point m and endpoint n (represented by the node ranks), there - * is never another edge with starting point m_ > m and endpoint n_ < n, or vice versa. When iterating through - * the ranks of one level, the endpoints are always increasing. Therefore, only the starting points need to be - * checked. Thus, the highest connected starting point in the fan-in gives a border m_max for every subsequent edge. + * The network is planar if, for any edge with starting point \f$m\f$ and endpoint \f$n\f$ + * (represented by the node ranks), there is never another edge with starting point + * \f$m' > m\f$ and endpoint \f$n' < n\f$, or vice versa. When iterating through the + * ranks of one level, the endpoints are always increasing. Therefore, only the starting + * points need to be checked. Thus, the highest connected starting point in the fan-in + * gives a border \f$m_{\text{max}}\f$ for every subsequent edge. * * @return `true` if the network is planar, `false` otherwise. */ + bool run() { bool return_false = false; @@ -50,15 +53,23 @@ class check_planarity_impl if (ntk.rank_position(fi_n) < bound) { return_false = true; + return false; // stop iterating } + new_bound = std::max(new_bound, ntk.rank_position(fi_n)); + + return true; // keep iterating }); if (return_false) + { return; + } bound = new_bound; }); if (return_false) + { return false; + } } return true; } @@ -68,29 +79,33 @@ class check_planarity_impl }; /** - * Checks if a logic network is planar. To perform this check, the network must have ranks assigned. + * Checks if a logic network is planar for a network that is path balanced and has ranks assigned. * * If the network is not balanced, an exception is thrown. To balance the network, insert buffers to divide multi-level * edges. * + * It checks if the network represented by the variable `ntk` is planar. + * The network is planar if, for any edge with starting point \f$m\f$ and endpoint \f$n\f$ (represented by the node + * ranks), there is never another edge with starting point \f$m' > m\f$ and endpoint \f$n' < n\f$, or vice versa. When + * iterating through the ranks of one level, the endpoints are always increasing. Therefore, only the starting points + * need to be checked. Thus, the highest connected starting point in the fan-in gives a border \f$m_{\text{max}}\f$ for + * every subsequent edge. + * * @tparam Ntk Logic network type. * @param ntk The logic network to check for planarity. * @return `true` if the network is planar, `false` otherwise. - * @throw std::runtime_error if the network is not balanced. */ template -bool check_planarity(const Ntk& ntk) +[[nodiscard]] bool check_planarity(const Ntk& ntk) { - static_assert(mockturtle::has_get_node_v, "Ntk does not have get_node trait"); - static_assert(mockturtle::has_foreach_fanin_v, "Ntk does not have foreach_fanin trait"); - static_assert(mockturtle::has_depth_v, "Ntk does not have depth trait"); - static_assert(mockturtle::has_rank_position_v, "Ntk does not have rank_position trait"); - static_assert(mockturtle::has_foreach_node_in_rank_v, "Ntk does not have foreach_node_in_rank trait"); + static_assert(mockturtle::has_get_node_v, "Ntk does not implement the get_node function"); + static_assert(mockturtle::has_foreach_fanin_v, "Ntk does not implement the foreach_fanin function"); + static_assert(mockturtle::has_depth_v, "Ntk does not implement the depth function"); + static_assert(mockturtle::has_rank_position_v, "Ntk does not implement the rank_position function"); + static_assert(mockturtle::has_foreach_node_in_rank_v, + "Ntk does not implement the foreach_node_in_rank function"); - if (!is_balanced(ntk)) - { - throw std::runtime_error("Network must be balanced"); - } + assert(is_balanced(ntk) && "Network must be balanced"); check_planarity_impl p{ntk}; diff --git a/include/fiction/algorithms/verification/virtual_miter.hpp b/include/fiction/algorithms/verification/virtual_miter.hpp index 3ec3c253a..bda8dc92c 100644 --- a/include/fiction/algorithms/verification/virtual_miter.hpp +++ b/include/fiction/algorithms/verification/virtual_miter.hpp @@ -16,6 +16,14 @@ namespace fiction { +template +auto handle_virtual_pis(const Ntk& network) { + if constexpr (has_num_virtual_pis_v) + return delete_virtual_pis(network); + else + return network; +} + /*! \brief Creates a combinational miter from two networks. * * This method combines two networks that have the same number of primary @@ -29,7 +37,7 @@ namespace fiction * primary inputs and primary outputs. */ template -std::optional miter(NtkSource1 const& ntk1, NtkSource2 const& ntk2) +std::optional virtual_miter(NtkSource1 const& ntk1_in, NtkSource2 const& ntk2_in) { static_assert(mockturtle::is_network_type_v, "NtkSource1 is not a network type"); static_assert(mockturtle::is_network_type_v, "NtkSource2 is not a network type"); @@ -44,74 +52,45 @@ std::optional miter(NtkSource1 const& ntk1, NtkSource2 const& ntk2) static_assert(mockturtle::has_create_xor_v, "NtkDest does not implement the create_xor method"); static_assert(mockturtle::has_create_nary_or_v, "NtkDest does not implement the create_nary_or method"); - auto num_pis1 = ntk1.num_pis(); - auto num_pis2 = ntk2.num_pis(); - if constexpr (has_num_real_pis_v) - { - num_pis1 = ntk1.num_real_pis(); - } - if constexpr (has_num_real_pis_v) - { - num_pis2 = ntk2.num_real_pis(); - } + auto ntk1 = handle_virtual_pis(ntk1_in); + auto ntk2 = handle_virtual_pis(ntk2_in); + /* both networks must have same number of inputs and outputs */ - if ((num_pis1 != num_pis2) || (ntk1.num_pos() != ntk2.num_pos())) + if ( ( ntk1.num_pis() != ntk2.num_pis() ) || ( ntk1.num_pos() != ntk2.num_pos() ) ) { return std::nullopt; } /* create primary inputs */ - NtkDest dest; + NtkDest dest; std::vector> pis; - for (auto i = 0u; i < num_pis1; ++i) - { - pis.push_back(dest.create_pi()); - } - - std::shared_ptr ntk1_copy; - if constexpr (has_remove_virtual_input_nodes_v) - { - ntk1_copy = std::make_shared(ntk1); - ntk1_copy->remove_virtual_input_nodes(); - } - else - { - ntk1_copy = std::make_shared(ntk1); // You may need const_cast here to remove the constness - } - - std::shared_ptr ntk2_copy; - if constexpr (has_remove_virtual_input_nodes_v) - { - ntk2_copy = std::make_shared(ntk2); - ntk2_copy->remove_virtual_input_nodes(); - } - else + for ( auto i = 0u; i < ntk1.num_pis(); ++i ) { - ntk2_copy = std::make_shared(ntk2); // You may need const_cast here to remove the constness + pis.push_back( dest.create_pi() ); } /* copy networks */ - const auto pos1 = mockturtle::cleanup_dangling(*ntk1_copy, dest, pis.begin(), pis.end()); - const auto pos2 = mockturtle::cleanup_dangling(*ntk2_copy, dest, pis.begin(), pis.end()); + const auto pos1 = cleanup_dangling( ntk1, dest, pis.begin(), pis.end() ); + const auto pos2 = cleanup_dangling( ntk2, dest, pis.begin(), pis.end() ); - if constexpr (mockturtle::has_EXODC_interface_v) + if constexpr ( mockturtle::has_EXODC_interface_v ) { - ntk1_copy->build_oe_miter(dest, pos1, pos2); + ntk1.build_oe_miter( dest, pos1, pos2 ); return dest; } - if constexpr (mockturtle::has_EXODC_interface_v) + if constexpr ( mockturtle::has_EXODC_interface_v ) { - ntk2_copy->build_oe_miter(dest, pos1, pos2); + ntk2.build_oe_miter( dest, pos1, pos2 ); return dest; } /* create XOR of output pairs */ std::vector> xor_outputs; - std::transform(pos1.begin(), pos1.end(), pos2.begin(), std::back_inserter(xor_outputs), - [&](auto const& o1, auto const& o2) { return dest.create_xor(o1, o2); }); + std::transform( pos1.begin(), pos1.end(), pos2.begin(), std::back_inserter( xor_outputs ), + [&]( auto const& o1, auto const& o2 ) { return dest.create_xor( o1, o2 ); } ); /* create big OR of XOR gates */ - dest.create_po(dest.create_nary_or(xor_outputs)); + dest.create_po( dest.create_nary_or( xor_outputs ) ); return dest; } diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 7a81f6cdf..90f71b96d 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -6,6 +6,7 @@ #define FICTION_VIRTUAL_PI_NETWORK_HPP #include "fiction/types.hpp" +#include "fiction/utils/name_utils.hpp" #include #include @@ -33,11 +34,11 @@ struct virtual_storage /** * Shared pointer vector storage for virtual_inputs. */ - std::vector virtual_inputs; + std::vector virtual_inputs; /** * Map from virtual_pis to real_pis. */ - phmap::parallel_flat_hash_map map_virt_to_real_pi; + phmap::parallel_flat_hash_map map_virt_to_real_pi; }; /* Network with additional "virtual" PIs. @@ -61,18 +62,43 @@ class virtual_pi_network : public Ntk * Default constructor for the `virtual_pi_network` class. * Initializes `_storage` as a shared pointer. */ - explicit virtual_pi_network() : _storage(std::make_shared>()) {} + virtual_pi_network() : Ntk(), v_storage(std::make_shared>()) {} /** * Copy constructor for the `virtual_pi_network` class. - * Given a network `ntk`, constructs a new `virtual_pi_network` as a clone of `ntk`. - * Initializes `_storage` as a shared pointer. + */ + explicit virtual_pi_network(std::shared_ptr s) : + Ntk(std::move(s)), + v_storage(std::make_shared>()) + {} + + /** + * Constructor for the `virtual_pi_network` class that takes a network as input. + * Unlike other network types a virtual_pi_network can be created on top of any network. + * It initializes the base class `Ntk` with a clone of the provided network and creates a shared pointer + * to a `virtual_storage` object. * - * @param ntk The network to clone into this object. + * @tparam Ntk Network type. + * @param ntk Input network. */ - explicit virtual_pi_network(const Ntk& ntk) : Ntk(ntk.clone()), _storage(std::make_shared>()) + explicit virtual_pi_network(const Ntk& ntk) : Ntk(ntk.clone()), v_storage(std::make_shared>()) {} + explicit virtual_pi_network(const Ntk& ntk, std::shared_ptr> s) : Ntk(ntk), v_storage(std::move(s)) + {} + + /** + * Clones the virtual_pi_network object. + */ + [[nodiscard]] virtual_pi_network clone() const + { + return virtual_pi_network( + // Clone the network + Ntk::clone(), + // Create a new shared_ptr to virtual_storage using a copy of the current _storage + std::make_shared>(*v_storage)); + } + /** * Variant of the mockturtle::initialize_copy_network. This function helps with creating new networks from old * networks. In the original version `old2new` is used to map nodes from the old network to nodes in the new network @@ -305,7 +331,7 @@ class virtual_pi_network : public Ntk */ [[nodiscard]] auto real_size() const { - return static_cast(Ntk::size() - _storage->virtual_inputs.size()); + return static_cast(Ntk::size() - v_storage->virtual_inputs.size()); } /** @@ -320,8 +346,8 @@ class virtual_pi_network : public Ntk signal create_virtual_pi(const signal& real_pi) { signal s = Ntk::create_pi(); - _storage->virtual_inputs.emplace_back(s); - _storage->map_virt_to_real_pi.insert({s, real_pi}); + v_storage->virtual_inputs.emplace_back(Ntk::get_node(s)); + v_storage->map_virt_to_real_pi.insert({Ntk::get_node(s), Ntk::get_node(real_pi)}); return s; } @@ -333,8 +359,8 @@ class virtual_pi_network : public Ntk */ [[nodiscard]] bool is_virtual_pi(node const& n) const { - return std::find(_storage->virtual_inputs.cbegin(), _storage->virtual_inputs.cend(), n) != - _storage->virtual_inputs.cend(); + return std::find(v_storage->virtual_inputs.cbegin(), v_storage->virtual_inputs.cend(), n) != + v_storage->virtual_inputs.cend(); } /** @@ -356,8 +382,8 @@ class virtual_pi_network : public Ntk */ [[nodiscard]] bool is_virtual_ci(node const& n) const { - return std::find(_storage->virtual_inputs.cbegin(), _storage->virtual_inputs.cend(), n) != - _storage->virtual_inputs.cend(); + return std::find(v_storage->virtual_inputs.cbegin(), v_storage->virtual_inputs.cend(), n) != + v_storage->virtual_inputs.cend(); } /** @@ -378,7 +404,7 @@ class virtual_pi_network : public Ntk */ [[nodiscard]] auto num_virtual_cis() const { - return static_cast(_storage->virtual_inputs.size()); + return static_cast(v_storage->virtual_inputs.size()); } /** @@ -398,7 +424,7 @@ class virtual_pi_network : public Ntk */ [[nodiscard]] auto num_virtual_pis() const { - return static_cast(_storage->virtual_inputs.size()); + return static_cast(v_storage->virtual_inputs.size()); } /** @@ -418,9 +444,9 @@ class virtual_pi_network : public Ntk */ [[nodiscard]] auto get_real_pi(const node& v_pi) const { - auto it = _storage->map_virt_to_real_pi.find(v_pi); + auto it = v_storage->map_virt_to_real_pi.find(v_pi); - assert(it != _storage->map_virt_to_real_pi.end() && "Error: node is not a virtual pi"); + assert(it != v_storage->map_virt_to_real_pi.end() && "Error: node is not a virtual pi"); return it->second; } @@ -453,7 +479,7 @@ class virtual_pi_network : public Ntk template void foreach_virtual_pi(Fn&& fn) const { - mockturtle::detail::foreach_element(_storage->virtual_inputs.cbegin(), _storage->virtual_inputs.cend(), fn); + mockturtle::detail::foreach_element(v_storage->virtual_inputs.cbegin(), v_storage->virtual_inputs.cend(), fn); } /** @@ -484,7 +510,7 @@ class virtual_pi_network : public Ntk template void foreach_virtual_ci(Fn&& fn) const { - mockturtle::detail::foreach_element(_storage->virtual_inputs.cbegin(), _storage->virtual_inputs.cend(), fn); + mockturtle::detail::foreach_element(v_storage->virtual_inputs.cbegin(), v_storage->virtual_inputs.cend(), fn); } /** @@ -494,27 +520,253 @@ class virtual_pi_network : public Ntk * real input nodes. It then performs a cleanup to remove any dangling PIs.. * Finally, it clears the virtual_inputs and map_virt_to_real_pi data structures in the _storage object. */ - void remove_virtual_input_nodes() + /*void remove_virtual_input_nodes() { - for (const auto& map_item : _storage->map_virt_to_real_pi) + for (const auto& map_item : v_storage->map_virt_to_real_pi) { - Ntk::substitute_node(Ntk::get_node(map_item.first), map_item.second); + Ntk::substitute_node(map_item.first, map_item.second); } *this = mockturtle::cleanup_dangling(*this, 1); // Clear virtual_inputs after using it - _storage->virtual_inputs.clear(); - _storage->map_virt_to_real_pi.clear(); - } + v_storage->virtual_inputs.clear(); + v_storage->map_virt_to_real_pi.clear(); + }*/ protected: /** * Shared pointer if the virtual PI storage. */ - std::shared_ptr> _storage; + std::shared_ptr> v_storage; }; +namespace detail +{ + +template +std::pair, Ntk>> initialize_copy_virtual_pi_network( Ntk& src ) +{ + static_assert( mockturtle::is_network_type_v, "NtkDest is not a network type" ); + static_assert( mockturtle::is_network_type_v, "NtkSrc is not a network type" ); + + static_assert( mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method" ); + static_assert( mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method" ); + static_assert( mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method" ); + static_assert( mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method" ); + static_assert( has_foreach_real_pi_v, "NtkSrc does not implement the foreach_pi method" ); + + mockturtle::node_map, Ntk> old2new( src ); + Ntk dest; + old2new[src.get_constant( false )] = dest.get_constant( false ); + if ( src.get_node( src.get_constant( true ) ) != src.get_node( src.get_constant( false ) ) ) + { + old2new[src.get_constant( true )] = dest.get_constant( true ); + } + src.foreach_real_pi( [&]( auto const& n ) { + old2new[n] = dest.create_pi(); + } ); + return { dest, old2new }; +} + +template +class delete_virtual_pis_impl +{ + public: + explicit delete_virtual_pis_impl(const Ntk& ntk_src) : ntk{ntk_src}, ntk_topo{ntk_src} {} + + // if ntk is not a virtual_pi_network just return the network + + // auto run() -> decltype(this->ntk.clone()) + auto run() -> decltype(std::declval().clone()) + { + auto init = initialize_copy_virtual_pi_network(ntk); + auto& ntk_dest_ref = init.first; + auto ntk_dest = ntk_dest_ref.clone(); + auto& old2new = init.second; + + // ntk_dest.create_and(2, 3); + + const auto gather_fanin_signals = [this, &ntk_dest, &old2new](const auto& n) + { + std::vector children{}; + + ntk.foreach_fanin(n, + [this, &ntk_dest, &old2new, &children](const auto& f) + { + auto fn = ntk.get_node(f); + + if (ntk.is_virtual_pi(fn)) + { + fn = ntk.get_real_pi(fn); + } + auto tgt_signal = old2new[fn]; + + children.emplace_back(ntk.is_complemented(f) ? ntk_dest.create_not(tgt_signal) : + tgt_signal); + }); + + return children; + }; + +#if (PROGRESS_BARS) + // initialize a progress bar + mockturtle::progress_bar bar{static_cast(ntk.num_gates()), "[i] network conversion: |{0}|"}; +#endif + + ntk_topo.foreach_gate( + [&, this](const auto& g, [[maybe_unused]] auto i) + { + auto children = gather_fanin_signals(g); + +#if (PROGRESS_BARS) + // update progress + bar(i); +#endif + + if constexpr (mockturtle::has_is_and_v && mockturtle::has_create_and_v) + { + if (ntk.is_and(g)) + { + old2new[g] = ntk_dest.create_and(children[0], children[1]); + return true; + } + } + if constexpr (mockturtle::has_is_or_v && mockturtle::has_create_or_v) + { + if (ntk.is_or(g)) + { + old2new[g] = ntk_dest.create_or(children[0], children[1]); + return true; + } + } + if constexpr (mockturtle::has_is_xor_v && mockturtle::has_create_xor_v) + { + if (ntk.is_xor(g)) + { + old2new[g] = ntk_dest.create_xor(children[0], children[1]); + return true; + } + } + if constexpr (mockturtle::has_is_maj_v && mockturtle::has_create_maj_v) + { + if (ntk.is_maj(g)) + { + old2new[g] = ntk_dest.create_maj(children[0], children[1], children[2]); + return true; + } + } + if constexpr (mockturtle::has_is_nary_and_v && mockturtle::has_create_nary_and_v) + { + if (ntk.is_nary_and(g)) + { + old2new[g] = ntk_dest.create_nary_and(children); + return true; + } + } + if constexpr (mockturtle::has_is_nary_or_v && mockturtle::has_create_nary_or_v) + { + if (ntk.is_nary_or(g)) + { + old2new[g] = ntk_dest.create_nary_or(children); + return true; + } + } + if constexpr (mockturtle::has_is_nary_xor_v && mockturtle::has_create_nary_xor_v) + { + if (ntk.is_nary_xor(g)) + { + old2new[g] = ntk_dest.create_nary_xor(children); + return true; + } + } + if constexpr (fiction::has_is_buf_v && mockturtle::has_create_buf_v) + { + if (ntk.is_buf(g)) + { + old2new[g] = ntk_dest.create_buf(children[0]); + return true; + } + } + if constexpr (mockturtle::has_node_function_v && mockturtle::has_create_node_v) + { + old2new[g] = ntk_dest.create_node(children, ntk.node_function(g)); + return true; + } + + return true; + }); + + ntk.foreach_po( + [this, &ntk_dest, &old2new](const auto& po) + { + const auto tgt_signal = old2new[ntk.get_node(po)]; + const auto tgt_po = ntk.is_complemented(po) ? ntk_dest.create_not(tgt_signal) : tgt_signal; + + ntk_dest.create_po(tgt_po); + }); + + // restore signal names if applicable + fiction::restore_names(ntk, ntk_dest, old2new); + + return ntk_dest; // ntk_dest + } + + private: + using TopoNtkSrc = mockturtle::topo_view; + TopoNtkSrc ntk_topo; + Ntk ntk; +}; +} // namespace detail + +/** + * Deletes virtual primary inputs from a network. This can mainly be used for equivalence checking. + * If the network does not have any virtual PIs stored, the network is returned. + * + * @tparam Ntk The type of network. + * @param ntk The input network. + * @return The resulting network after virtual primary inputs are deleted. + */ +template +auto delete_virtual_pis(const Ntk& ntk) -> decltype(std::declval().clone()) +{ + static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); + static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); + + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node function"); + static_assert(mockturtle::has_is_complemented_v, "NtkSrc does not implement the is_complemented function"); + static_assert(mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi function"); + static_assert(has_get_real_pi_v, "NtkSrc does not implement the has_get_real_pi function"); + static_assert(has_num_real_pis_v, "NtkSrc does not implement the has_get_real_pi function"); + static_assert(mockturtle::has_foreach_gate_v, "NtkSrc does not implement the foreach_gate function"); + static_assert(mockturtle::has_foreach_po_v, "NtkSrc does not implement the foreach_po function"); + static_assert(mockturtle::has_foreach_fanin_v, "NtkSrc does not implement the foreach_fanin function"); + + static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant function"); + static_assert(mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant function"); + + static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi function"); + static_assert(mockturtle::has_create_po_v, "NtkDest does not implement the create_po function"); + static_assert(mockturtle::has_create_not_v, "NtkDest does not implement the create_not function"); + static_assert(mockturtle::has_create_and_v, "NtkDest does not implement the create_and function"); + static_assert(mockturtle::has_create_or_v, "NtkDest does not implement the create_or function"); + static_assert(mockturtle::has_create_xor_v, "NtkDest does not implement the create_xor function"); + static_assert(mockturtle::has_create_maj_v, "NtkDest does not implement the create_maj function"); + + assert(ntk.is_combinational() && "Network has to be combinational"); + + if(ntk.num_virtual_pis() == 0) + { + return ntk; + } + + detail::delete_virtual_pis_impl p{ntk}; + + auto result = p.run(); + + return result; +} + } // namespace fiction #endif // FICTION_VIRTUAL_PI_NETWORK_HPP diff --git a/test/algorithms/properties/check_planarity.cpp b/test/algorithms/properties/check_planarity.cpp index caa5c9f6e..7ebb2897a 100644 --- a/test/algorithms/properties/check_planarity.cpp +++ b/test/algorithms/properties/check_planarity.cpp @@ -7,6 +7,9 @@ #include #include #include +#include +#include +#include using namespace fiction; diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index 48ea06eb4..63f8c0e26 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -5,13 +5,18 @@ #include #include +#include "fiction/algorithms/network_transformation/network_conversion.hpp" +#include + #include #include #include #include +#include #include #include +#include using namespace fiction; @@ -42,10 +47,11 @@ TEST_CASE("Copy technology network and size consistency", "[virtual-pi-view]") CHECK(vpi.real_size() == 7); // This is the size with the virtual PIs CHECK(vpi.size() == 9); - vpi.remove_virtual_input_nodes(); + const auto non_vpi = delete_virtual_pis(vpi); // After removing/remapping the virtual PIs to their real PIs the sizes are equal - CHECK(vpi.real_size() == vpi.size()); - CHECK(vpi.size() == 7); + CHECK(non_vpi.real_size() == non_vpi.size()); + CHECK(non_vpi.size() == vpi.size() - vpi.num_virtual_pis()); + CHECK(non_vpi.size() == 7); } TEMPLATE_TEST_CASE("Copy networks and size consistency", "[virtual-pi-view]", mockturtle::aig_network, @@ -76,10 +82,12 @@ TEMPLATE_TEST_CASE("Copy networks and size consistency", "[virtual-pi-view]", mo CHECK(vpi.real_size() == 6); // This is the size with the virtual PIs CHECK(vpi.size() == 8); - vpi.remove_virtual_input_nodes(); + const auto non_vpi = delete_virtual_pis(vpi); // After removing/remapping the virtual PIs to their real PIs the sizes are equal - CHECK(vpi.real_size() == vpi.size()); - CHECK(vpi.size() == 6); + // Minus one, since AIG nodes get hashed when creating the new AIG + CHECK(non_vpi.real_size() == non_vpi.size() - 1); + CHECK(non_vpi.size() == vpi.size() - vpi.num_virtual_pis() - 1); + CHECK(non_vpi.size() == 6 - 1); } TEST_CASE("Remove PIs from technology network and check equivalence", "[virtual-pi-view]") @@ -112,12 +120,26 @@ TEST_CASE("Remove PIs from technology network and check equivalence", "[virtual- tec.create_po(f2_t); tec.create_po(f3_t); - vpi.remove_virtual_input_nodes(); - CHECK(vpi.real_size() == vpi.size()); - CHECK(vpi.size() == tec.size()); + auto vvv = vpi.clone(); + + auto ntk_r = extended_rank_view(vpi); + + /*auto init = mockturtle::initialize_copy_network >(ntk_r); + auto& ntk_dest = init.first; + auto& old2new = init.second; + auto nw = ntk_dest.clone(); + auto xx = nw.create_and(2, 3);*/ + + // auto non_vpi_r = delete_virtual_pis(ntk_r); + + // auto z = convert_network>(ntk_r); + + /*CHECK(non_vpi_r.real_size() == non_vpi_r.size()); + CHECK(non_vpi_r.size() == vpi.size() - vpi.num_virtual_pis());*/ mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = mockturtle::equivalence_checking(*fiction::miter(tec, vpi), {}, &st); + const auto maybe_cec_m = + mockturtle::equivalence_checking(*fiction::virtual_miter(tec, ntk_r), {}, &st); REQUIRE(maybe_cec_m.has_value()); CHECK(*maybe_cec_m == 1); } @@ -153,12 +175,18 @@ TEMPLATE_TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]", mock tec.create_po(f2_t); tec.create_po(f3_t); - vpi.remove_virtual_input_nodes(); - CHECK(vpi.real_size() == vpi.size()); - CHECK(vpi.size() == tec.size()); + const auto n_pi = vpi.get_real_pi(3); + + auto non_virt = delete_virtual_pis(vpi); + CHECK(non_virt.size() == + vpi.size() - vpi.num_virtual_pis() - 2); // When creating the AIG, the nodes will be hashed. Since all AND + // nodes are the same, only one node will be created. + + CHECK(non_virt.real_size() == non_virt.size()); mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = mockturtle::equivalence_checking(*fiction::miter(tec, vpi), {}, &st); + const auto maybe_cec_m = + mockturtle::equivalence_checking(*mockturtle::miter(tec, non_virt), {}, &st); REQUIRE(maybe_cec_m.has_value()); CHECK(*maybe_cec_m == 1); } @@ -204,12 +232,12 @@ TEST_CASE("Remove PIs and check equivalence with different sizes", "[virtual-pi- vpi.create_po(f13); vpi.create_po(f14); - vpi.remove_virtual_input_nodes(); - CHECK(vpi.real_size() == vpi.size()); - CHECK(vpi.size() - 2 == tec.size()); // the -2 is due to the buffers + auto non_virt = delete_virtual_pis(vpi); + CHECK(non_virt.size() == vpi.size() - vpi.num_virtual_pis()); mockturtle::equivalence_checking_stats st; - const auto maybe_cec_m = mockturtle::equivalence_checking(*fiction::miter(tec, vpi), {}, &st); + const auto maybe_cec_m = + mockturtle::equivalence_checking(*mockturtle::miter(tec, non_virt), {}, &st); REQUIRE(maybe_cec_m.has_value()); CHECK(*maybe_cec_m == 1); } From 0c9798994092df054e96e9c94da4c2acb1a9ef0d Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sat, 24 Aug 2024 16:22:12 +0000 Subject: [PATCH 54/84] :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions --- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 99 +++++++++++++------ 1 file changed, 67 insertions(+), 32 deletions(-) diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index 54b3e83cd..edd15fecd 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -1939,12 +1939,22 @@ Parameter ``cs``: Integer representing the SiDB's charge state.)doc"; static const char *__doc_fiction_check_planarity = -R"doc(Checks if a logic network is planar. To perform this check, the -network must have ranks assigned. +R"doc(Checks if a logic network is planar for a network that is path +balanced and has ranks assigned. If the network is not balanced, an exception is thrown. To balance the network, insert buffers to divide multi-level edges. +It checks if the network represented by the variable `ntk` is planar. +The network is planar if, for any edge with starting point :math:`m` +and endpoint :math:`n` (represented by the node ranks), there is never +another edge with starting point :math:`m' > m` and endpoint :math:`n' +< n`, or vice versa. When iterating through the ranks of one level, +the endpoints are always increasing. Therefore, only the starting +points need to be checked. Thus, the highest connected starting point +in the fan-in gives a border :math:`m_{\text{max}}` for every +subsequent edge. + Template parameter ``Ntk``: Logic network type. @@ -1952,10 +1962,7 @@ Parameter ``ntk``: The logic network to check for planarity. Returns: - `true` if the network is planar, `false` otherwise. - -Throws: - std::runtime_error if the network is not balanced.)doc"; + `true` if the network is planar, `false` otherwise.)doc"; static const char *__doc_fiction_check_planarity_impl = R"doc()doc"; @@ -1967,13 +1974,14 @@ static const char *__doc_fiction_check_planarity_impl_run = R"doc(Checks if a given network is planar. This function checks if the network represented by the variable `ntk` -is planar. The network is planar if for any edge with starting point m -and endpoint n (represented by the node ranks), there is never another -edge with starting point m_ > m and endpoint n_ < n, or vice versa. -When iterating through the ranks of one level, the endpoints are -always increasing. Therefore, only the starting points need to be -checked. Thus, the highest connected starting point in the fan-in -gives a border m_max for every subsequent edge. +is planar. The network is planar if, for any edge with starting point +:math:`m` and endpoint :math:`n` (represented by the node ranks), +there is never another edge with starting point :math:`m' > m` and +endpoint :math:`n' < n`, or vice versa. When iterating through the +ranks of one level, the endpoints are always increasing. Therefore, +only the starting points need to be checked. Thus, the highest +connected starting point in the fan-in gives a border +:math:`m_{\text{max}}` for every subsequent edge. Returns: `true` if the network is planar, `false` otherwise.)doc"; @@ -3366,6 +3374,20 @@ Parameter ``neutral_defect_spacing_overwrite``: A pair of uint16_t values representing the number of horizontal and vertical SiDBs affected by the given defect type.)doc"; +static const char *__doc_fiction_delete_virtual_pis = +R"doc(Deletes virtual primary inputs from a network. This can mainly be used +for equivalence checking. If the network does not have any virtual PIs +stored, the network is returned. + +Template parameter ``Ntk``: + The type of network. + +Parameter ``ntk``: + The input network. + +Returns: + The resulting network after virtual primary inputs are deleted.)doc"; + static const char *__doc_fiction_dependent_cell_mode = R"doc(An enumeration of modes for the dependent cell.)doc"; static const char *__doc_fiction_dependent_cell_mode_FIXED = @@ -11273,6 +11295,8 @@ Parameter ``m``: static const char *__doc_fiction_gray_code_iterator_start_number = R"doc(Start number of the iteration.)doc"; +static const char *__doc_fiction_handle_virtual_pis = R"doc()doc"; + static const char *__doc_fiction_has_above = R"doc()doc"; static const char *__doc_fiction_has_assign_charge_state = R"doc()doc"; @@ -12933,20 +12957,6 @@ static const char *__doc_fiction_missing_sidb_position_exception_missing_sidb_po static const char *__doc_fiction_missing_sidb_position_exception_where = R"doc()doc"; -static const char *__doc_fiction_miter = -R"doc(! Creates a combinational miter from two networks. - -This method combines two networks that have the same number of primary -inputs and the same number of primary outputs into a miter. The miter -has the same number of inputs and one primary output. This output is -the OR of XORs of all primary output pairs. In other words, the miter -outputs 1 for all input assignments in which the two input networks -differ. - -All networks may have different types. The method returns an optional, -which is `nullopt`, whenever the two input networks don't match in -their number of primary inputs and primary outputs.)doc"; - static const char *__doc_fiction_network_balancing = R"doc(Balances a logic network with buffer nodes that compute the identity function. For this purpose, `create_buf` is utilized. Therefore, @@ -17141,19 +17151,44 @@ static const char *__doc_fiction_vertical_shift_cartesian = R"doc(\verbatim +-------+ | | | +-------+ | | | +-------+ | | | +-------+ \endverbatim)doc"; +static const char *__doc_fiction_virtual_miter = +R"doc(! Creates a combinational miter from two networks. + +This method combines two networks that have the same number of primary +inputs and the same number of primary outputs into a miter. The miter +has the same number of inputs and one primary output. This output is +the OR of XORs of all primary output pairs. In other words, the miter +outputs 1 for all input assignments in which the two input networks +differ. + +All networks may have different types. The method returns an optional, +which is `nullopt`, whenever the two input networks don't match in +their number of primary inputs and primary outputs.)doc"; + static const char *__doc_fiction_virtual_pi_network = R"doc()doc"; +static const char *__doc_fiction_virtual_pi_network_clone = R"doc(Clones the virtual_pi_network object.)doc"; + static const char *__doc_fiction_virtual_pi_network_virtual_pi_network = R"doc(Default constructor for the `virtual_pi_network` class. Initializes `_storage` as a shared pointer.)doc"; -static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_2 = -R"doc(Copy constructor for the `virtual_pi_network` class. Given a network -`ntk`, constructs a new `virtual_pi_network` as a clone of `ntk`. -Initializes `_storage` as a shared pointer. +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_2 = R"doc(Copy constructor for the `virtual_pi_network` class.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_3 = +R"doc(Constructor for the `virtual_pi_network` class that takes a network as +input. Unlike other network types a virtual_pi_network can be created +on top of any network. It initializes the base class `Ntk` with a +clone of the provided network and creates a shared pointer to a +`virtual_storage` object. + +Template parameter ``Ntk``: + Network type. Parameter ``ntk``: - The network to clone into this object.)doc"; + Input network.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_4 = R"doc()doc"; static const char *__doc_fiction_virtual_storage = R"doc()doc"; From 7721cc51b8856c405f6959a7130bacae5fde0616 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 26 Aug 2024 08:17:51 +0200 Subject: [PATCH 55/84] :heavy_plus sign: updated documentation and added test --- .../algorithms/verification/virtual_miter.hpp | 57 +++++++++--------- .../algorithms/verification/virtual_miter.cpp | 58 +++++++++++++++++++ 2 files changed, 89 insertions(+), 26 deletions(-) create mode 100644 test/algorithms/verification/virtual_miter.cpp diff --git a/include/fiction/algorithms/verification/virtual_miter.hpp b/include/fiction/algorithms/verification/virtual_miter.hpp index bda8dc92c..2061a8aaf 100644 --- a/include/fiction/algorithms/verification/virtual_miter.hpp +++ b/include/fiction/algorithms/verification/virtual_miter.hpp @@ -7,37 +7,42 @@ #include "fiction/networks/virtual_pi_network.hpp" -#include #include #include #include +#include namespace fiction { template -auto handle_virtual_pis(const Ntk& network) { +auto handle_virtual_pis(const Ntk& network) +{ if constexpr (has_num_virtual_pis_v) + { return delete_virtual_pis(network); + } else + { return network; + } } -/*! \brief Creates a combinational miter from two networks. +/** + * This method combines two networks to a combinational miter like a mockturtle::miter. Additionally, either of the + * input networks can be a network with virtual inputs, which are duplicated PIs. In this case + * the duplicated PIs are deleted and all edges connecting to them are remapped on their originating PI. * - * This method combines two networks that have the same number of primary - * inputs and the same number of primary outputs into a miter. The miter - * has the same number of inputs and one primary output. This output is the - * OR of XORs of all primary output pairs. In other words, the miter outputs - * 1 for all input assignments in which the two input networks differ. + * Therefore, the miter has the same number of inputs and one primary output. This output is the OR of XORs of all + * primary output pairs. In other words, the miter outputs 1 for all input assignments in which the two input networks + * differ. * - * All networks may have different types. The method returns an optional, which - * is `nullopt`, whenever the two input networks don't match in their number of - * primary inputs and primary outputs. + * All networks may have different types. The method returns an optional, which is `nullopt`, whenever the two input + * networks don't match in their number of primary inputs and primary outputs. */ -template -std::optional virtual_miter(NtkSource1 const& ntk1_in, NtkSource2 const& ntk2_in) +template +std::optional virtual_miter(const NtkSource1& ntk1_in, const NtkSource2& ntk2_in) { static_assert(mockturtle::is_network_type_v, "NtkSource1 is not a network type"); static_assert(mockturtle::is_network_type_v, "NtkSource2 is not a network type"); @@ -56,41 +61,41 @@ std::optional virtual_miter(NtkSource1 const& ntk1_in, NtkSource2 const auto ntk2 = handle_virtual_pis(ntk2_in); /* both networks must have same number of inputs and outputs */ - if ( ( ntk1.num_pis() != ntk2.num_pis() ) || ( ntk1.num_pos() != ntk2.num_pos() ) ) + if ((ntk1.num_pis() != ntk2.num_pis()) || (ntk1.num_pos() != ntk2.num_pos())) { return std::nullopt; } /* create primary inputs */ - NtkDest dest; + NtkDest dest; std::vector> pis; - for ( auto i = 0u; i < ntk1.num_pis(); ++i ) + for (auto i = 0u; i < ntk1.num_pis(); ++i) { - pis.push_back( dest.create_pi() ); + pis.push_back(dest.create_pi()); } /* copy networks */ - const auto pos1 = cleanup_dangling( ntk1, dest, pis.begin(), pis.end() ); - const auto pos2 = cleanup_dangling( ntk2, dest, pis.begin(), pis.end() ); + const auto pos1 = cleanup_dangling(ntk1, dest, pis.begin(), pis.end()); + const auto pos2 = cleanup_dangling(ntk2, dest, pis.begin(), pis.end()); - if constexpr ( mockturtle::has_EXODC_interface_v ) + if constexpr (mockturtle::has_EXODC_interface_v) { - ntk1.build_oe_miter( dest, pos1, pos2 ); + ntk1.build_oe_miter(dest, pos1, pos2); return dest; } - if constexpr ( mockturtle::has_EXODC_interface_v ) + if constexpr (mockturtle::has_EXODC_interface_v) { - ntk2.build_oe_miter( dest, pos1, pos2 ); + ntk2.build_oe_miter(dest, pos1, pos2); return dest; } /* create XOR of output pairs */ std::vector> xor_outputs; - std::transform( pos1.begin(), pos1.end(), pos2.begin(), std::back_inserter( xor_outputs ), - [&]( auto const& o1, auto const& o2 ) { return dest.create_xor( o1, o2 ); } ); + std::transform(pos1.begin(), pos1.end(), pos2.begin(), std::back_inserter(xor_outputs), + [&](auto const& o1, auto const& o2) { return dest.create_xor(o1, o2); }); /* create big OR of XOR gates */ - dest.create_po( dest.create_nary_or( xor_outputs ) ); + dest.create_po(dest.create_nary_or(xor_outputs)); return dest; } diff --git a/test/algorithms/verification/virtual_miter.cpp b/test/algorithms/verification/virtual_miter.cpp new file mode 100644 index 000000000..3d1a276ec --- /dev/null +++ b/test/algorithms/verification/virtual_miter.cpp @@ -0,0 +1,58 @@ +// +// Created by benjamin on 8/26/24. +// + +#include + +#include +#include +#include + +#include + +using namespace fiction; + +TEST_CASE("Miter network positions", "[virtual-miter]") +{ + technology_network tec{}; + const auto x1 = tec.create_pi(); + const auto x2 = tec.create_pi(); + const auto a1 = tec.create_and(x1, x2); + const auto o1 = tec.create_or(x1, x2); + tec.create_po(a1); + tec.create_po(o1); + + virtual_pi_network vpi_ntk_1{}; + const auto x1_v = vpi_ntk_1.create_pi(); + const auto x2_v = vpi_ntk_1.create_pi(); + const auto v1 = vpi_ntk_1.create_virtual_pi(x1_v); + const auto a1_v = vpi_ntk_1.create_and(x1_v, x2_v); + const auto o1_v = vpi_ntk_1.create_or(v1, x2_v); + vpi_ntk_1.create_po(a1_v); + vpi_ntk_1.create_po(o1_v); + + virtual_pi_network vpi_ntk_2{}; + const auto x1_v2 = vpi_ntk_2.create_pi(); + const auto x2_v2 = vpi_ntk_2.create_pi(); + const auto v1_2 = vpi_ntk_2.create_virtual_pi(x1_v2); + const auto a1_v2 = vpi_ntk_2.create_and(v1_2, x2_v2); + const auto o1_v2 = vpi_ntk_2.create_or(x1_v2, x2_v2); + vpi_ntk_2.create_po(a1_v2); + vpi_ntk_2.create_po(o1_v2); + + mockturtle::equivalence_checking_stats st; + auto maybe_cec_m = + mockturtle::equivalence_checking(*fiction::virtual_miter(vpi_ntk_1, tec), {}, &st); + REQUIRE(maybe_cec_m.has_value()); + CHECK(*maybe_cec_m == 1); + + maybe_cec_m = + mockturtle::equivalence_checking(*fiction::virtual_miter(tec, vpi_ntk_2), {}, &st); + REQUIRE(maybe_cec_m.has_value()); + CHECK(*maybe_cec_m == 1); + + maybe_cec_m = + mockturtle::equivalence_checking(*fiction::virtual_miter(vpi_ntk_1, vpi_ntk_2), {}, &st); + REQUIRE(maybe_cec_m.has_value()); + CHECK(*maybe_cec_m == 1); +} \ No newline at end of file From e444977054856bd91517669c95a15110abdd7dc6 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 26 Aug 2024 06:18:57 +0000 Subject: [PATCH 56/84] :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions --- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index edd15fecd..027cb6c1b 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -17152,14 +17152,16 @@ R"doc(\verbatim +-------+ | | | +-------+ | | | +-------+ | | | +-------+ \endverbatim)doc"; static const char *__doc_fiction_virtual_miter = -R"doc(! Creates a combinational miter from two networks. - -This method combines two networks that have the same number of primary -inputs and the same number of primary outputs into a miter. The miter -has the same number of inputs and one primary output. This output is -the OR of XORs of all primary output pairs. In other words, the miter -outputs 1 for all input assignments in which the two input networks -differ. +R"doc(This method combines two networks to a combinational miter like a +mockturtle::miter. Additionally, either of the input networks can be a +network with virtual inputs, which are duplicated PIs. In this case +the duplicated PIs are deleted and all edges connecting to them are +remapped on their originating PI. + +Therefore, the miter has the same number of inputs and one primary +output. This output is the OR of XORs of all primary output pairs. In +other words, the miter outputs 1 for all input assignments in which +the two input networks differ. All networks may have different types. The method returns an optional, which is `nullopt`, whenever the two input networks don't match in From 5cda15e0e780862bffbe03462881dc148d80d586 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 26 Aug 2024 09:11:57 +0200 Subject: [PATCH 57/84] :art: updated readability and documentation --- .../algorithms/properties/check_planarity.hpp | 2 +- .../fiction/networks/virtual_pi_network.hpp | 50 +++++++++---------- test/networks/virtual_pi_network.cpp | 25 ++-------- 3 files changed, 27 insertions(+), 50 deletions(-) diff --git a/include/fiction/algorithms/properties/check_planarity.hpp b/include/fiction/algorithms/properties/check_planarity.hpp index 1ab130f73..a6b988f60 100644 --- a/include/fiction/algorithms/properties/check_planarity.hpp +++ b/include/fiction/algorithms/properties/check_planarity.hpp @@ -10,8 +10,8 @@ #include #include +#include #include -#include namespace fiction { diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 90f71b96d..dfffa182e 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -534,7 +535,7 @@ class virtual_pi_network : public Ntk v_storage->map_virt_to_real_pi.clear(); }*/ - protected: + private: /** * Shared pointer if the virtual PI storage. */ @@ -575,18 +576,15 @@ class delete_virtual_pis_impl public: explicit delete_virtual_pis_impl(const Ntk& ntk_src) : ntk{ntk_src}, ntk_topo{ntk_src} {} - // if ntk is not a virtual_pi_network just return the network - // auto run() -> decltype(this->ntk.clone()) auto run() -> decltype(std::declval().clone()) { auto init = initialize_copy_virtual_pi_network(ntk); auto& ntk_dest_ref = init.first; + // cloning resolves runtime issues with rank_views, but might return a different network type. auto ntk_dest = ntk_dest_ref.clone(); auto& old2new = init.second; - // ntk_dest.create_and(2, 3); - const auto gather_fanin_signals = [this, &ntk_dest, &old2new](const auto& n) { std::vector children{}; @@ -730,28 +728,26 @@ class delete_virtual_pis_impl template auto delete_virtual_pis(const Ntk& ntk) -> decltype(std::declval().clone()) { - static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); - static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); - - static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node function"); - static_assert(mockturtle::has_is_complemented_v, "NtkSrc does not implement the is_complemented function"); - static_assert(mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi function"); - static_assert(has_get_real_pi_v, "NtkSrc does not implement the has_get_real_pi function"); - static_assert(has_num_real_pis_v, "NtkSrc does not implement the has_get_real_pi function"); - static_assert(mockturtle::has_foreach_gate_v, "NtkSrc does not implement the foreach_gate function"); - static_assert(mockturtle::has_foreach_po_v, "NtkSrc does not implement the foreach_po function"); - static_assert(mockturtle::has_foreach_fanin_v, "NtkSrc does not implement the foreach_fanin function"); - - static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant function"); - static_assert(mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant function"); - - static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi function"); - static_assert(mockturtle::has_create_po_v, "NtkDest does not implement the create_po function"); - static_assert(mockturtle::has_create_not_v, "NtkDest does not implement the create_not function"); - static_assert(mockturtle::has_create_and_v, "NtkDest does not implement the create_and function"); - static_assert(mockturtle::has_create_or_v, "NtkDest does not implement the create_or function"); - static_assert(mockturtle::has_create_xor_v, "NtkDest does not implement the create_xor function"); - static_assert(mockturtle::has_create_maj_v, "NtkDest does not implement the create_maj function"); + static_assert(mockturtle::is_network_type_v, "Ntk is not a network type"); + + static_assert(mockturtle::has_get_node_v, "Ntk does not implement the get_node function"); + static_assert(mockturtle::has_is_complemented_v, "Ntk does not implement the is_complemented function"); + static_assert(mockturtle::has_foreach_pi_v, "Ntk does not implement the foreach_pi function"); + static_assert(has_get_real_pi_v, "Ntk does not implement the has_get_real_pi function"); + static_assert(has_num_real_pis_v, "Ntk does not implement the has_num_real_pis function"); + static_assert(mockturtle::has_foreach_gate_v, "Ntk does not implement the foreach_gate function"); + static_assert(mockturtle::has_foreach_po_v, "Ntk does not implement the foreach_po function"); + static_assert(mockturtle::has_foreach_fanin_v, "Ntk does not implement the foreach_fanin function"); + + static_assert(mockturtle::has_get_constant_v, "Ntk does not implement the get_constant function"); + + static_assert(mockturtle::has_create_pi_v, "Ntk does not implement the create_pi function"); + static_assert(mockturtle::has_create_po_v, "Ntk does not implement the create_po function"); + static_assert(mockturtle::has_create_not_v, "Ntk does not implement the create_not function"); + static_assert(mockturtle::has_create_and_v, "Ntk does not implement the create_and function"); + static_assert(mockturtle::has_create_or_v, "Ntk does not implement the create_or function"); + static_assert(mockturtle::has_create_xor_v, "Ntk does not implement the create_xor function"); + static_assert(mockturtle::has_create_maj_v, "Ntk does not implement the create_maj function"); assert(ntk.is_combinational() && "Network has to be combinational"); diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index 63f8c0e26..2a3d18bb3 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -5,7 +5,6 @@ #include #include -#include "fiction/algorithms/network_transformation/network_conversion.hpp" #include #include @@ -16,7 +15,6 @@ #include #include #include -#include using namespace fiction; @@ -84,13 +82,13 @@ TEMPLATE_TEST_CASE("Copy networks and size consistency", "[virtual-pi-view]", mo CHECK(vpi.size() == 8); const auto non_vpi = delete_virtual_pis(vpi); // After removing/remapping the virtual PIs to their real PIs the sizes are equal + CHECK(non_vpi.real_size() == non_vpi.size()); // Minus one, since AIG nodes get hashed when creating the new AIG - CHECK(non_vpi.real_size() == non_vpi.size() - 1); CHECK(non_vpi.size() == vpi.size() - vpi.num_virtual_pis() - 1); - CHECK(non_vpi.size() == 6 - 1); + CHECK(non_vpi.size() == 5); } -TEST_CASE("Remove PIs from technology network and check equivalence", "[virtual-pi-view]") +TEST_CASE("Check equivalence of an extended_rank view", "[virtual-pi-view]") { technology_network tec{}; virtual_pi_network vpi{}; @@ -120,23 +118,8 @@ TEST_CASE("Remove PIs from technology network and check equivalence", "[virtual- tec.create_po(f2_t); tec.create_po(f3_t); - auto vvv = vpi.clone(); - auto ntk_r = extended_rank_view(vpi); - /*auto init = mockturtle::initialize_copy_network >(ntk_r); - auto& ntk_dest = init.first; - auto& old2new = init.second; - auto nw = ntk_dest.clone(); - auto xx = nw.create_and(2, 3);*/ - - // auto non_vpi_r = delete_virtual_pis(ntk_r); - - // auto z = convert_network>(ntk_r); - - /*CHECK(non_vpi_r.real_size() == non_vpi_r.size()); - CHECK(non_vpi_r.size() == vpi.size() - vpi.num_virtual_pis());*/ - mockturtle::equivalence_checking_stats st; const auto maybe_cec_m = mockturtle::equivalence_checking(*fiction::virtual_miter(tec, ntk_r), {}, &st); @@ -175,8 +158,6 @@ TEMPLATE_TEST_CASE("Remove PIs and check equivalence", "[virtual-pi-view]", mock tec.create_po(f2_t); tec.create_po(f3_t); - const auto n_pi = vpi.get_real_pi(3); - auto non_virt = delete_virtual_pis(vpi); CHECK(non_virt.size() == vpi.size() - vpi.num_virtual_pis() - 2); // When creating the AIG, the nodes will be hashed. Since all AND From 3e24f3cb75a459572f931366eaf05efc5a28bc26 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 26 Aug 2024 12:28:53 +0200 Subject: [PATCH 58/84] :heavy_plus sign: added experiments legalization.cpp. Fixed bug for the virtual_pi generation needed for planarization. --- experiments/legalization/legalization.cpp | 90 +++++++++++++++++++ .../algorithms/properties/check_planarity.hpp | 2 +- .../fiction/networks/virtual_pi_network.hpp | 69 +++++++------- 3 files changed, 127 insertions(+), 34 deletions(-) create mode 100644 experiments/legalization/legalization.cpp diff --git a/experiments/legalization/legalization.cpp b/experiments/legalization/legalization.cpp new file mode 100644 index 000000000..4612bf7ce --- /dev/null +++ b/experiments/legalization/legalization.cpp @@ -0,0 +1,90 @@ +// +// Created by benjamin on 8/26/24. +// + +#include "experiments.hpp" +#include "fiction/algorithms/network_transformation/fanout_substitution.hpp" +#include "fiction/algorithms/properties/check_planarity.hpp" +#include "fiction/utils/debug/network_writer.hpp" +#include "fiction_experiments.hpp" + +#include +#include +#include // scalable heuristic for physical design +#include // wiring reduction algorithm +#include // critical path and throughput calculations +#include // SAT-based equivalence checking +#include +#include +#include // read networks from files +#include +#include + +#include +#include // output formatting +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +template +Ntk read_ntk(const std::string& name) +{ + fmt::print("[i] processing {}\n", name); + + std::ostringstream os{}; + + fiction::network_reader reader{fiction_experiments::benchmark_path(name), os}; + + const auto nets = reader.get_networks(); + + return *nets.front(); +} + +int main() // NOLINT +{ + experiments::experiment wiring_reduction_exp{ + "planarization", "benchmark", "inputs", "outputs", "initial nodes", "nodes_after", "is_planar", "equivalent"}; + + static constexpr const uint64_t bench_select = + (fiction_experiments::trindade16 | fiction_experiments::fontes18) & ~fiction_experiments::clpl; + // static constexpr const uint64_t bench_select = (fiction_experiments::one_bit_add_maj); + + for (const auto& benchmark : fiction_experiments::all_benchmarks(bench_select)) + { + const auto benchmark_network = read_ntk(benchmark); + + fiction::network_balancing_params ps; + ps.unify_outputs = true; + + const auto _b = fiction::network_balancing( + fiction::fanout_substitution(benchmark_network), ps); + + const auto planarized_b = fiction::node_duplication_planarization(_b); + + const auto is_planar = fiction::check_planarity(planarized_b); + + // fiction::debug::write_dot_network(_b); + + // check equivalence + mockturtle::equivalence_checking_stats st; + const auto cec_m = mockturtle::equivalence_checking( + *fiction::virtual_miter(benchmark_network, planarized_b), {}, &st); + assert(cec_m.has_value()); + + // log results + wiring_reduction_exp(benchmark, benchmark_network.num_pis(), benchmark_network.num_pos(), + benchmark_network.num_gates(), _b.num_gates(), is_planar, static_cast(cec_m)); + + wiring_reduction_exp.save(); + wiring_reduction_exp.table(); + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/include/fiction/algorithms/properties/check_planarity.hpp b/include/fiction/algorithms/properties/check_planarity.hpp index a6b988f60..4c510e25f 100644 --- a/include/fiction/algorithms/properties/check_planarity.hpp +++ b/include/fiction/algorithms/properties/check_planarity.hpp @@ -20,7 +20,7 @@ template class check_planarity_impl { public: - check_planarity_impl(const Ntk& ntk) : ntk(ntk) {} + explicit check_planarity_impl(const Ntk& ntk) : ntk(ntk) {} /** * Checks if a given network is planar. diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index dfffa182e..1aae87802 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -5,10 +5,8 @@ #ifndef FICTION_VIRTUAL_PI_NETWORK_HPP #define FICTION_VIRTUAL_PI_NETWORK_HPP -#include "fiction/types.hpp" #include "fiction/utils/name_utils.hpp" -#include #include #include #include @@ -18,8 +16,6 @@ #include #include #include -#include -#include #include #include #include @@ -85,7 +81,9 @@ class virtual_pi_network : public Ntk explicit virtual_pi_network(const Ntk& ntk) : Ntk(ntk.clone()), v_storage(std::make_shared>()) {} - explicit virtual_pi_network(const Ntk& ntk, std::shared_ptr> s) : Ntk(ntk), v_storage(std::move(s)) + explicit virtual_pi_network(const Ntk& ntk, std::shared_ptr> s) : + Ntk(ntk), + v_storage(std::move(s)) {} /** @@ -201,16 +199,18 @@ class virtual_pi_network : public Ntk assert(edge_it_int < lvl.size()); + bool break_loop = false; for (const auto& possible_node : tgt_signal_v) { - const auto it = ntk.is_maj(n) ? 4 : 3; + const auto it = ntk.fanin_size(n) + 1; if (ntk.fanin_size(n) == children.size()) { break; } for (std::size_t i = 0; i < it; i++) { - if (edge_it_int + i < lvl.size() && lvl[edge_it_int + i] == possible_node) + if (edge_it_int + i < lvl.size() && lvl[edge_it_int + i] == possible_node && + ntk_dest_v.fanout_size(possible_node) < 2) { if (first_fi_edge_it != -1) { @@ -226,9 +226,14 @@ class virtual_pi_network : public Ntk { edge_it = edge_it_int + i; } + break_loop = true; break; } } + if (break_loop) + { + break; + } } }); return children; @@ -545,29 +550,27 @@ class virtual_pi_network : public Ntk namespace detail { -template -std::pair, Ntk>> initialize_copy_virtual_pi_network( Ntk& src ) +template +std::pair, Ntk>> initialize_copy_virtual_pi_network(Ntk& src) { - static_assert( mockturtle::is_network_type_v, "NtkDest is not a network type" ); - static_assert( mockturtle::is_network_type_v, "NtkSrc is not a network type" ); - - static_assert( mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method" ); - static_assert( mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method" ); - static_assert( mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method" ); - static_assert( mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method" ); - static_assert( has_foreach_real_pi_v, "NtkSrc does not implement the foreach_pi method" ); - - mockturtle::node_map, Ntk> old2new( src ); - Ntk dest; - old2new[src.get_constant( false )] = dest.get_constant( false ); - if ( src.get_node( src.get_constant( true ) ) != src.get_node( src.get_constant( false ) ) ) + static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); + static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); + + static_assert(mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method"); + static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method"); + static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method"); + static_assert(has_foreach_real_pi_v, "NtkSrc does not implement the foreach_pi method"); + + mockturtle::node_map, Ntk> old2new(src); + Ntk dest; + old2new[src.get_constant(false)] = dest.get_constant(false); + if (src.get_node(src.get_constant(true)) != src.get_node(src.get_constant(false))) { - old2new[src.get_constant( true )] = dest.get_constant( true ); + old2new[src.get_constant(true)] = dest.get_constant(true); } - src.foreach_real_pi( [&]( auto const& n ) { - old2new[n] = dest.create_pi(); - } ); - return { dest, old2new }; + src.foreach_real_pi([&](auto const& n) { old2new[n] = dest.create_pi(); }); + return {dest, old2new}; } template @@ -579,10 +582,10 @@ class delete_virtual_pis_impl // auto run() -> decltype(this->ntk.clone()) auto run() -> decltype(std::declval().clone()) { - auto init = initialize_copy_virtual_pi_network(ntk); + auto init = initialize_copy_virtual_pi_network(ntk); auto& ntk_dest_ref = init.first; // cloning resolves runtime issues with rank_views, but might return a different network type. - auto ntk_dest = ntk_dest_ref.clone(); + auto ntk_dest = ntk_dest_ref.clone(); auto& old2new = init.second; const auto gather_fanin_signals = [this, &ntk_dest, &old2new](const auto& n) @@ -592,7 +595,7 @@ class delete_virtual_pis_impl ntk.foreach_fanin(n, [this, &ntk_dest, &old2new, &children](const auto& f) { - auto fn = ntk.get_node(f); + auto fn = ntk.get_node(f); if (ntk.is_virtual_pi(fn)) { @@ -707,13 +710,13 @@ class delete_virtual_pis_impl // restore signal names if applicable fiction::restore_names(ntk, ntk_dest, old2new); - return ntk_dest; // ntk_dest + return ntk_dest; // ntk_dest } private: using TopoNtkSrc = mockturtle::topo_view; TopoNtkSrc ntk_topo; - Ntk ntk; + Ntk ntk; }; } // namespace detail @@ -751,7 +754,7 @@ auto delete_virtual_pis(const Ntk& ntk) -> decltype(std::declval().clone()) assert(ntk.is_combinational() && "Network has to be combinational"); - if(ntk.num_virtual_pis() == 0) + if (ntk.num_virtual_pis() == 0) { return ntk; } From ce44c8510d7cc38832210965884a0d7d448dc04d Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 26 Aug 2024 15:52:47 +0200 Subject: [PATCH 59/84] :art: override foreach_ci in extended_rank_view.hpp --- .../networks/views/extended_rank_view.hpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index ba7c00b29..6cd00e019 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -402,6 +402,25 @@ class extended_rank_view : public mockturtle::depth_view [this](auto const& n1, auto const& n2) { return rank_pos[n1] < rank_pos[n2]; }); mockturtle::detail::foreach_element(pis.cbegin(), pis.cend(), std::forward(fn)); } + /** + * Applies a given function to each CI in rank order. + * + * This function overrides the `foreach_ci` method of the base class. + * + * @tparam Fn Functor type. + * @param fn The function to apply. + */ + template + void foreach_ci(Fn&& fn) const + { + std::vector pis{}; + pis.reserve(this->num_pis()); + + mockturtle::depth_view::foreach_ci([&pis](auto const& pi) { pis.push_back(pi); }); + std::sort(pis.begin(), pis.end(), + [this](auto const& n1, auto const& n2) { return rank_pos[n1] < rank_pos[n2]; }); + mockturtle::detail::foreach_element(pis.cbegin(), pis.cend(), std::forward(fn)); + } /** * Overrides the base class method to also call the add_event on create_pi(). * From e835f3061111b0a03913a0ca1f44fd37f9a3b948 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 26 Aug 2024 18:54:31 +0200 Subject: [PATCH 60/84] :art: included size bounds for networks. For to big networks `calculate_pairs` gets a segmentation fault due to its size --- experiments/legalization/legalization.cpp | 25 +++++++++++++++- .../node_duplication_planarization.hpp | 30 +++++++++++++++++-- .../algorithms/properties/check_planarity.hpp | 17 ++++++----- 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/experiments/legalization/legalization.cpp b/experiments/legalization/legalization.cpp index 4612bf7ce..ff893d324 100644 --- a/experiments/legalization/legalization.cpp +++ b/experiments/legalization/legalization.cpp @@ -53,7 +53,8 @@ int main() // NOLINT "planarization", "benchmark", "inputs", "outputs", "initial nodes", "nodes_after", "is_planar", "equivalent"}; static constexpr const uint64_t bench_select = - (fiction_experiments::trindade16 | fiction_experiments::fontes18) & ~fiction_experiments::clpl; + (fiction_experiments::epfl) & //fiction_experiments::iscas85 & ~ + ~fiction_experiments::clpl; // fiction_experiments::trindade16 | fiction_experiments::fontes18 | fiction_experiments::epfl | fiction_experiments::iscas85 // static constexpr const uint64_t bench_select = (fiction_experiments::one_bit_add_maj); for (const auto& benchmark : fiction_experiments::all_benchmarks(bench_select)) @@ -63,6 +64,28 @@ int main() // NOLINT fiction::network_balancing_params ps; ps.unify_outputs = true; + if (benchmark_network.num_gates() > 2500) + { + std::cout << "the number of gates is too high\n"; + continue; + } + + bool cont = false; + benchmark_network.foreach_pi( + [&benchmark_network, &cont](auto pi) + { + if (benchmark_network.is_po(pi)) + { + cont = true; + std::cout << "Pi is Po\n"; + + } + }); + if(cont) + { + continue; + } + const auto _b = fiction::network_balancing( fiction::fanout_substitution(benchmark_network), ps); diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index aef5ed551..aec1db7d1 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -175,7 +175,17 @@ class node_duplication_planarization_impl { fis.push_back(nd); } - ntk.foreach_fanin(nd, [this](auto fi) { fis.push_back(fi); }); + + ntk.foreach_fanin(nd, + [this](auto fi) + { + if (!ntk.is_constant(fi)) + { + fis.push_back(fi); + } + }); + + assert(!fis.size() == 0 && "Node is a buffered PI that is a PO"); // Compute the combinations in one slice auto combinations = calculate_pairs(fis); assert(!combinations.empty() && "Combinations are empty. There might be a dangling node"); @@ -307,7 +317,8 @@ class node_duplication_planarization_impl return true; } - [[nodiscard]] virtual_pi_network run(std::vector>>& ntk_lvls_new) + [[nodiscard]] std::optional> + run(std::vector>>& ntk_lvls_new) { // ToDO: implement border_pis (if there is a choice ush pis to the borders (first or last rank)) const bool border_pis = true; @@ -353,9 +364,15 @@ class node_duplication_planarization_impl bool f_final_level = check_final_level(v_level); + int lvl_it = 0; // Process all other levels while (!v_level.empty() && !f_final_level) { + // ToDo: Fix segmentation fault + if (v_level.size() > 25000) + { + return std::nullopt; + } // Push the level to the network ntk_lvls.push_back(v_level); lvl_pairs.clear(); @@ -372,6 +389,7 @@ class node_duplication_planarization_impl compute_node_order_next_level(v_level); // Check if we are at the final level f_final_level = check_final_level(v_level); + ++lvl_it; } // Push the final level (PIs) if (f_final_level) @@ -446,9 +464,15 @@ node_duplication_planarization(const NtkSrc& ntk_src, const node_duplication_pla auto result_ntk = p.run(ntk_lvls_new); + if (!result_ntk) + { + std::cout << "The network is to wide to be processed by the planarization algorithm" << std::endl; + return extended_rank_view>(virtual_pi_network(ntk_src)); + } + std::reverse(ntk_lvls_new.begin(), ntk_lvls_new.end()); - auto result = extended_rank_view(result_ntk, ntk_lvls_new); + auto result = extended_rank_view(*result_ntk, ntk_lvls_new); if (!check_planarity(result)) { diff --git a/include/fiction/algorithms/properties/check_planarity.hpp b/include/fiction/algorithms/properties/check_planarity.hpp index 4c510e25f..97398237f 100644 --- a/include/fiction/algorithms/properties/check_planarity.hpp +++ b/include/fiction/algorithms/properties/check_planarity.hpp @@ -47,17 +47,20 @@ class check_planarity_impl { uint32_t new_bound = bound; ntk.foreach_fanin(n, - [this, &bound, &new_bound, &return_false](const auto& fi) + [this, &n, &bound, &new_bound, &return_false](const auto& fi) { const auto fi_n = ntk.get_node(fi); - if (ntk.rank_position(fi_n) < bound) + if (!ntk.is_constant(fi_n)) { - return_false = true; - return false; // stop iterating + if (ntk.rank_position(fi_n) < bound) + { + return_false = true; + return false; // stop iterating + } + + new_bound = + std::max(new_bound, ntk.rank_position(fi_n)); } - - new_bound = std::max(new_bound, ntk.rank_position(fi_n)); - return true; // keep iterating }); if (return_false) From 7acc1326da2d40ece562e0f7311149d69dfaa9b7 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 27 Aug 2024 18:10:00 +0200 Subject: [PATCH 61/84] :art: switched from shared_pointers to raw pointers and fixed the segmentation fault. Error: For big networks not the depth/view/rank_view needs to long to be created. (Therefore the size guards are still left in) --- .../node_duplication_planarization.hpp | 16 ++++++++-------- include/fiction/networks/virtual_pi_network.hpp | 2 ++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index aec1db7d1..d066f0eda 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -71,7 +71,7 @@ struct node_pair /** * Shared pointer to another instance of node_pair detailing fanin-edge alignment. */ - std::shared_ptr> fanin_pair; + node_pair* fanin_pair; /** * Specifies the delay value for the node. */ @@ -85,7 +85,8 @@ struct node_pair */ node_pair(mockturtle::node node1, mockturtle::node node2, uint64_t delayValue) : pair(node1, node2), - delay(delayValue) + delay(delayValue), + fanin_pair(nullptr) {} }; @@ -189,27 +190,26 @@ class node_duplication_planarization_impl // Compute the combinations in one slice auto combinations = calculate_pairs(fis); assert(!combinations.empty() && "Combinations are empty. There might be a dangling node"); - std::vector> combinations_last; if (!lvl_pairs.empty()) { - combinations_last = lvl_pairs.back(); + std::vector>* combinations_last = &lvl_pairs.back(); for (auto& node_pair_cur : combinations) { - for (auto& node_pair_last : combinations_last) + for (auto& node_pair_last : *combinations_last) { // If there is a connection between the two node pairs the delay is calculated like this if ((node_pair_cur.pair.first == node_pair_last.pair.second && node_pair_last.delay + 1 < node_pair_cur.delay)) { - node_pair_cur.fanin_pair = std::make_shared>(node_pair_last); + node_pair_cur.fanin_pair = &node_pair_last; node_pair_cur.delay = node_pair_last.delay + 1; } // If there is no connection between the two node pairs the delay is calculated like this else if (node_pair_last.delay + 2 < node_pair_cur.delay) { - node_pair_cur.fanin_pair = std::make_shared>(node_pair_last); + node_pair_cur.fanin_pair = &node_pair_last; node_pair_cur.delay = node_pair_last.delay + 2; } } @@ -368,7 +368,7 @@ class node_duplication_planarization_impl // Process all other levels while (!v_level.empty() && !f_final_level) { - // ToDo: Fix segmentation fault + // ToDo: Fix the creation of the depth_view/rank_view if (v_level.size() > 25000) { return std::nullopt; diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 1aae87802..69201718b 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -264,6 +264,8 @@ class virtual_pi_network : public Ntk else { const auto children = gather_fanin_signals(nd, ntk_lvls_new[i + 1], edge_it); + // std::cout << "Node: " << nd << std::endl; + assert(!children.empty() && "The node has to have children"); if (ntk.is_and(nd)) { From e9bfba97b314b60e052e4e3badc0e5e6db733854 Mon Sep 17 00:00:00 2001 From: benjamin Date: Wed, 28 Aug 2024 09:51:01 +0200 Subject: [PATCH 62/84] :art: added ortho to experiment --- experiments/legalization/legalization.cpp | 35 ++++++++++++++++++----- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/experiments/legalization/legalization.cpp b/experiments/legalization/legalization.cpp index ff893d324..a6f907d78 100644 --- a/experiments/legalization/legalization.cpp +++ b/experiments/legalization/legalization.cpp @@ -49,12 +49,12 @@ Ntk read_ntk(const std::string& name) int main() // NOLINT { - experiments::experiment wiring_reduction_exp{ - "planarization", "benchmark", "inputs", "outputs", "initial nodes", "nodes_after", "is_planar", "equivalent"}; + experiments::experiment wiring_reduction_exp{ + "planarization", "benchmark", "inputs", "outputs", "initial nodes", "nodes_after", "is_planar", "equivalent(ntk)", "equivalent(lyt)"}; static constexpr const uint64_t bench_select = - (fiction_experiments::epfl) & //fiction_experiments::iscas85 & ~ - ~fiction_experiments::clpl; // fiction_experiments::trindade16 | fiction_experiments::fontes18 | fiction_experiments::epfl | fiction_experiments::iscas85 + (fiction_experiments::par_gen); //fiction_experiments::iscas85 & ~ + // fiction_experiments::trindade16 | fiction_experiments::fontes18 | fiction_experiments::epfl | fiction_experiments::iscas85 // static constexpr const uint64_t bench_select = (fiction_experiments::one_bit_add_maj); for (const auto& benchmark : fiction_experiments::all_benchmarks(bench_select)) @@ -64,7 +64,7 @@ int main() // NOLINT fiction::network_balancing_params ps; ps.unify_outputs = true; - if (benchmark_network.num_gates() > 2500) + if (benchmark_network.num_gates() > 3000) { std::cout << "the number of gates is too high\n"; continue; @@ -93,7 +93,28 @@ int main() // NOLINT const auto is_planar = fiction::check_planarity(planarized_b); - // fiction::debug::write_dot_network(_b); + auto name = mockturtle::names_view(planarized_b); + + fiction::restore_names(benchmark_network, name); + + using gate_lyt = + fiction::gate_level_layout>>>; + + fiction::orthogonal_physical_design_stats stats{}; + using gate_layout = fiction::gate_level_layout>>>; + auto layout = fiction::orthogonal(name, {}, &stats); + + fiction::equivalence_checking_stats eq_s_ortho{}; + // check equivalence + const auto eq_stats_ortho = + fiction::equivalence_checking(planarized_b, layout, &eq_s_ortho); + + const std::string eq_result_ortho = eq_stats_ortho == fiction::eq_type::STRONG ? "STRONG" : + eq_stats_ortho == fiction::eq_type::WEAK ? "WEAK" : + "NO"; + + /*fiction::debug::write_dot_layout(layout); + fiction::debug::write_dot_network(_b);*/ // check equivalence mockturtle::equivalence_checking_stats st; @@ -103,7 +124,7 @@ int main() // NOLINT // log results wiring_reduction_exp(benchmark, benchmark_network.num_pis(), benchmark_network.num_pos(), - benchmark_network.num_gates(), _b.num_gates(), is_planar, static_cast(cec_m)); + benchmark_network.num_gates(), _b.num_gates(), is_planar, static_cast(cec_m), eq_result_ortho); wiring_reduction_exp.save(); wiring_reduction_exp.table(); From 3b56eb8d147b1a2a0e9ddc4ae9790521f967f13e Mon Sep 17 00:00:00 2001 From: benjamin Date: Thu, 19 Sep 2024 16:04:15 +0200 Subject: [PATCH 63/84] :art: merged main --- libs/Catch2 | 2 +- libs/json | 2 +- libs/mockturtle | 2 +- libs/parallel-hashmap | 2 +- libs/pybind11 | 2 +- libs/tinyxml2 | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/Catch2 b/libs/Catch2 index bc63412e2..fa306fc85 160000 --- a/libs/Catch2 +++ b/libs/Catch2 @@ -1 +1 @@ -Subproject commit bc63412e2a3b3e39e178ea75953522f78b840aa7 +Subproject commit fa306fc85eca7cc68a5362c503019fa823cbe411 diff --git a/libs/json b/libs/json index b36f4c477..960b763ec 160000 --- a/libs/json +++ b/libs/json @@ -1 +1 @@ -Subproject commit b36f4c477c40356a0ae1204b567cca3c2a57d201 +Subproject commit 960b763ecd144f156d05ec61f577b04107290137 diff --git a/libs/mockturtle b/libs/mockturtle index e55e2bbbe..924c277bc 160000 --- a/libs/mockturtle +++ b/libs/mockturtle @@ -1 +1 @@ -Subproject commit e55e2bbbef4648d311b97ae0907380190ebe8a29 +Subproject commit 924c277bc01900c9dc6d56fb6f2f4d100cab0806 diff --git a/libs/parallel-hashmap b/libs/parallel-hashmap index 63acc3336..8a889d369 160000 --- a/libs/parallel-hashmap +++ b/libs/parallel-hashmap @@ -1 +1 @@ -Subproject commit 63acc3336f941c6f324c88eb9ee4ce623a460cd5 +Subproject commit 8a889d3699b3c09ade435641fb034427f3fd12b6 diff --git a/libs/pybind11 b/libs/pybind11 index ef5a9560b..a1d00916b 160000 --- a/libs/pybind11 +++ b/libs/pybind11 @@ -1 +1 @@ -Subproject commit ef5a9560bb03efcac588888a825b7c7a0b8266cc +Subproject commit a1d00916b26b187e583f3bce39cd59c3b0652c32 diff --git a/libs/tinyxml2 b/libs/tinyxml2 index 374292e9b..8a519a556 160000 --- a/libs/tinyxml2 +++ b/libs/tinyxml2 @@ -1 +1 @@ -Subproject commit 374292e9ba1549460f35d70411daba8b82bb2add +Subproject commit 8a519a556afecb3e717a4797615a8bfa49cae10a From a4276591e3b9f93ea9d41fdbae9487e0f3629b0e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:04:33 +0000 Subject: [PATCH 64/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- experiments/legalization/legalization.cpp | 26 ++++++++++--------- .../algorithms/properties/check_planarity.cpp | 6 +++-- .../algorithms/verification/virtual_miter.cpp | 2 +- test/networks/virtual_pi_network.cpp | 5 ++-- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/experiments/legalization/legalization.cpp b/experiments/legalization/legalization.cpp index a6f907d78..3ea62e5f9 100644 --- a/experiments/legalization/legalization.cpp +++ b/experiments/legalization/legalization.cpp @@ -49,12 +49,13 @@ Ntk read_ntk(const std::string& name) int main() // NOLINT { - experiments::experiment wiring_reduction_exp{ - "planarization", "benchmark", "inputs", "outputs", "initial nodes", "nodes_after", "is_planar", "equivalent(ntk)", "equivalent(lyt)"}; + experiments::experiment + wiring_reduction_exp{"planarization", "benchmark", "inputs", "outputs", "initial nodes", + "nodes_after", "is_planar", "equivalent(ntk)", "equivalent(lyt)"}; - static constexpr const uint64_t bench_select = - (fiction_experiments::par_gen); //fiction_experiments::iscas85 & ~ - // fiction_experiments::trindade16 | fiction_experiments::fontes18 | fiction_experiments::epfl | fiction_experiments::iscas85 + static constexpr const uint64_t bench_select = (fiction_experiments::par_gen); // fiction_experiments::iscas85 & ~ + // fiction_experiments::trindade16 | fiction_experiments::fontes18 | fiction_experiments::epfl | + // fiction_experiments::iscas85 // static constexpr const uint64_t bench_select = (fiction_experiments::one_bit_add_maj); for (const auto& benchmark : fiction_experiments::all_benchmarks(bench_select)) @@ -78,10 +79,9 @@ int main() // NOLINT { cont = true; std::cout << "Pi is Po\n"; - } }); - if(cont) + if (cont) { continue; } @@ -97,11 +97,12 @@ int main() // NOLINT fiction::restore_names(benchmark_network, name); - using gate_lyt = - fiction::gate_level_layout>>>; + using gate_lyt = fiction::gate_level_layout< + fiction::clocked_layout>>>; fiction::orthogonal_physical_design_stats stats{}; - using gate_layout = fiction::gate_level_layout>>>; + using gate_layout = fiction::gate_level_layout< + fiction::clocked_layout>>>; auto layout = fiction::orthogonal(name, {}, &stats); fiction::equivalence_checking_stats eq_s_ortho{}; @@ -124,11 +125,12 @@ int main() // NOLINT // log results wiring_reduction_exp(benchmark, benchmark_network.num_pis(), benchmark_network.num_pos(), - benchmark_network.num_gates(), _b.num_gates(), is_planar, static_cast(cec_m), eq_result_ortho); + benchmark_network.num_gates(), _b.num_gates(), is_planar, static_cast(cec_m), + eq_result_ortho); wiring_reduction_exp.save(); wiring_reduction_exp.table(); } return EXIT_SUCCESS; -} \ No newline at end of file +} diff --git a/test/algorithms/properties/check_planarity.cpp b/test/algorithms/properties/check_planarity.cpp index 7ebb2897a..a0ca81141 100644 --- a/test/algorithms/properties/check_planarity.cpp +++ b/test/algorithms/properties/check_planarity.cpp @@ -7,9 +7,11 @@ #include #include #include -#include -#include + #include +#include + +#include using namespace fiction; diff --git a/test/algorithms/verification/virtual_miter.cpp b/test/algorithms/verification/virtual_miter.cpp index 3d1a276ec..ec6d5bc7a 100644 --- a/test/algorithms/verification/virtual_miter.cpp +++ b/test/algorithms/verification/virtual_miter.cpp @@ -55,4 +55,4 @@ TEST_CASE("Miter network positions", "[virtual-miter]") mockturtle::equivalence_checking(*fiction::virtual_miter(vpi_ntk_1, vpi_ntk_2), {}, &st); REQUIRE(maybe_cec_m.has_value()); CHECK(*maybe_cec_m == 1); -} \ No newline at end of file +} diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index 2a3d18bb3..a7c9600a2 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -5,10 +5,9 @@ #include #include -#include - #include #include +#include #include #include @@ -118,7 +117,7 @@ TEST_CASE("Check equivalence of an extended_rank view", "[virtual-pi-view]") tec.create_po(f2_t); tec.create_po(f3_t); - auto ntk_r = extended_rank_view(vpi); + auto ntk_r = extended_rank_view(vpi); mockturtle::equivalence_checking_stats st; const auto maybe_cec_m = From 853e2d724f08340e7cd5915968325990b53d48b5 Mon Sep 17 00:00:00 2001 From: benjamin Date: Thu, 19 Sep 2024 16:30:38 +0200 Subject: [PATCH 65/84] :art: bug fixes and small changes --- experiments/legalization/legalization.cpp | 273 ++++++++++++++++-- .../node_duplication_planarization.hpp | 72 +++-- .../networks/views/extended_rank_view.hpp | 1 + .../fiction/networks/virtual_pi_network.hpp | 1 + .../algorithms/properties/check_planarity.cpp | 6 +- .../algorithms/verification/virtual_miter.cpp | 2 +- test/networks/views/extended_rank_view.cpp | 2 +- test/networks/virtual_pi_network.cpp | 5 +- 8 files changed, 298 insertions(+), 64 deletions(-) diff --git a/experiments/legalization/legalization.cpp b/experiments/legalization/legalization.cpp index 3ea62e5f9..19de33457 100644 --- a/experiments/legalization/legalization.cpp +++ b/experiments/legalization/legalization.cpp @@ -49,27 +49,190 @@ Ntk read_ntk(const std::string& name) int main() // NOLINT { - experiments::experiment - wiring_reduction_exp{"planarization", "benchmark", "inputs", "outputs", "initial nodes", - "nodes_after", "is_planar", "equivalent(ntk)", "equivalent(lyt)"}; + experiments::experiment + wiring_reduction_exp{"planarization", "benchmark", "inputs", "virt_inputs", + "outputs", "initial nodes", "nodes buffered", "nodes planarized", + "is_planar", "equivalent(ntk)", "equivalent(lyt)"}; - static constexpr const uint64_t bench_select = (fiction_experiments::par_gen); // fiction_experiments::iscas85 & ~ - // fiction_experiments::trindade16 | fiction_experiments::fontes18 | fiction_experiments::epfl | - // fiction_experiments::iscas85 - // static constexpr const uint64_t bench_select = (fiction_experiments::one_bit_add_maj); - - for (const auto& benchmark : fiction_experiments::all_benchmarks(bench_select)) + int x = 0; + for (const auto& entry : + std::filesystem::directory_iterator("/home/benjamin/Documents/Repositories/working/fiction/benchmarks/IWLS93")) { - const auto benchmark_network = read_ntk(benchmark); + fmt::print("[i] processing {}\n", entry.path().filename().string()); + + /*if ( "sqrt8ml.v" != entry.path().filename().string()) + { + continue; + }*/ + /*if ( "C1355.v" != entry.path().filename().string()) + { + continue; + }*/ + if ( "C432.v" == entry.path().filename().string()) + { + continue; + } + if ( "ex4p.v" == entry.path().filename().string()) + { + continue; + } + if ( "apex1.v" == entry.path().filename().string()) + { + continue; + } + + std::ostringstream os{}; + + fiction::network_reader reader{entry.path().string(), os}; + + const auto nets = reader.get_networks(); + + auto benchmark_network = *nets.front(); + + bool cont = false; + benchmark_network.foreach_pi( + [&benchmark_network, &cont](auto pi) + { + if (benchmark_network.is_po(pi)) + { + cont = true; + // std::cout << "Pi is Po\n"; + } + }); + if (cont) + { + continue; + } + + // fiction::debug::write_dot_network(benchmark_network); + + // std::cout << benchmark_network.num_gates() << std::endl; fiction::network_balancing_params ps; ps.unify_outputs = true; - if (benchmark_network.num_gates() > 3000) + const auto _b = fiction::network_balancing( + fiction::fanout_substitution(benchmark_network), ps); + + // happens with exp4.v + /*const auto fc = fanins(_b, 9213); + + std::cout << "Node 9213: " << fc.fanin_nodes.size() << std::endl; + std::cout << "Node 9213: " << _b.is_buf(9213) << std::endl;*/ + + // happens with apex1.v + /*const auto fc = fanins(_b, 8771); + + std::cout << "Node 9213: " << fc.fanin_nodes.size() << std::endl; + std::cout << "Node 9213: " << _b.is_buf(8771) << std::endl;*/ + + // std::cout << _b.num_gates() << std::endl; + + // fiction::debug::write_dot_network(_b); + + if (_b.size() > 10000) + { + /*wiring_reduction_exp(entry.path().filename().string(), benchmark_network.num_pis(), 0, + benchmark_network.num_pos(), benchmark_network.num_gates(), _b.num_gates(), + _b.num_gates(), 0, 0, 0); + wiring_reduction_exp.save(); + wiring_reduction_exp.table(); + std::cout << ++x << "\n";*/ + continue; + } + + const auto planarized_b = fiction::node_duplication_planarization(_b); + const auto is_planar = fiction::check_planarity(planarized_b); + if (planarized_b.size() > 20000) { - std::cout << "the number of gates is too high\n"; continue; } + mockturtle::equivalence_checking_stats st; + const auto cec_m = mockturtle::equivalence_checking( + *fiction::virtual_miter(benchmark_network, planarized_b), {}, &st); + assert(cec_m.has_value()); + std::cout << cec_m.value() << std::endl; + + using gate_lyt = fiction::gate_level_layout< + fiction::clocked_layout>>>; + + fiction::orthogonal_physical_design_stats stats{}; + using gate_layout = fiction::gate_level_layout< + fiction::clocked_layout>>>; + auto layout = fiction::orthogonal(planarized_b, {}, &stats); + + fiction::gate_level_drv_params ps_d{}; + fiction::gate_level_drv_stats st_d{}; + + fiction::gate_level_drvs(layout, ps_d, &st_d); + + const auto miter = mockturtle::miter(planarized_b, layout); + bool eq; + if (miter) + { + mockturtle::equivalence_checking_stats st; + + const auto ce = mockturtle::equivalence_checking(*miter, {}, &st); + eq = ce.value(); + } + wiring_reduction_exp(entry.path().filename().string(), benchmark_network.num_pis(), + planarized_b.num_virtual_pis(), benchmark_network.num_pos(), benchmark_network.num_gates(), + _b.num_gates(), planarized_b.num_gates(), is_planar, cec_m.value(), eq); + wiring_reduction_exp.save(); + wiring_reduction_exp.table(); + std::cout << ++x << "\n"; + } + + /*fiction::technology_network tec; + const auto pi0 = tec.create_pi(); + const auto pi1 = tec.create_pi(); + const auto pi2 = tec.create_pi(); + const auto pi3 = tec.create_pi(); + const auto pi4 = tec.create_pi(); + + const auto a0 = tec.create_and(pi0, pi1); + const auto o0 = tec.create_or(pi0, pi1); + const auto a1 = tec.create_and(pi3, pi4); + const auto o1 = tec.create_or(pi3, pi4); + + const auto a2 = tec.create_and(o0, pi2); + const auto a3 = tec.create_and(o1, pi2); + const auto a4 = tec.create_and(a2, a3); + + tec.create_po(a0); + tec.create_po(a4); + tec.create_po(a1); + + fiction::network_balancing_params ps; + ps.unify_outputs = true; + + const auto _b = fiction::network_balancing( + fiction::fanout_substitution(tec), ps); + + + const auto _b_topo = mockturtle::topo_view(_b); + const auto _b_rank = mockturtle::rank_view(_b); + + fiction::node_duplication_planarization_params dps; + dps.random_output_order = false; + + const auto planarized_b = fiction::node_duplication_planarization(_b, dps); + + fiction::debug::write_dot_network(tec, "tec_test"); + fiction::debug::write_dot_network(_b, "t_b"); + fiction::debug::write_dot_network(planarized_b, "network_b");*/ + + static constexpr const uint64_t bench_select = (fiction_experiments::fontes18); // fiction_experiments::iscas85 & ~ + // fiction_experiments::trindade16 | fiction_experiments::fontes18 | fiction_experiments::epfl | + // fiction_experiments::iscas85 static constexpr const uint64_t bench_select = + for (const auto& benchmark : fiction_experiments::all_benchmarks(bench_select)) + { + continue; + const auto benchmark_network = read_ntk(benchmark); + + fiction::network_balancing_params ps; + ps.unify_outputs = true; bool cont = false; benchmark_network.foreach_pi( @@ -79,9 +242,10 @@ int main() // NOLINT { cont = true; std::cout << "Pi is Po\n"; + } }); - if (cont) + if(cont) { continue; } @@ -89,48 +253,93 @@ int main() // NOLINT const auto _b = fiction::network_balancing( fiction::fanout_substitution(benchmark_network), ps); + if (_b.size() > 15000) + { + /*wiring_reduction_exp(benchmark, benchmark_network.num_pis(), 0, benchmark_network.num_pos(), + benchmark_network.num_gates(), _b.num_gates(), _b.num_gates(), 0, 0, "TEST"); + wiring_reduction_exp.save(); + wiring_reduction_exp.table();*/ + continue; + } + const auto planarized_b = fiction::node_duplication_planarization(_b); const auto is_planar = fiction::check_planarity(planarized_b); + if (planarized_b.size() > 30000) + { + wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), benchmark_network.num_pos(), + benchmark_network.num_gates(), _b.num_gates(), planarized_b.num_gates(), is_planar, 0, 0); + wiring_reduction_exp.save(); + wiring_reduction_exp.table(); + continue; + } + + // check equivalence + mockturtle::equivalence_checking_stats st; + const auto cec_m = mockturtle::equivalence_checking( + *fiction::virtual_miter(benchmark_network, planarized_b), {}, &st); + assert(cec_m.has_value()); + auto name = mockturtle::names_view(planarized_b); fiction::restore_names(benchmark_network, name); - using gate_lyt = fiction::gate_level_layout< - fiction::clocked_layout>>>; + using gate_lyt = + fiction::gate_level_layout>>>; fiction::orthogonal_physical_design_stats stats{}; - using gate_layout = fiction::gate_level_layout< - fiction::clocked_layout>>>; - auto layout = fiction::orthogonal(name, {}, &stats); + using gate_layout = fiction::gate_level_layout>>>; + auto start = std::chrono::high_resolution_clock::now(); + auto layout = fiction::orthogonal(planarized_b, {}, &stats); + auto stop = std::chrono::high_resolution_clock::now(); - fiction::equivalence_checking_stats eq_s_ortho{}; + std::chrono::duration elapsed = stop - start; + + std::cout << "Time elapsed: " << elapsed.count() << " s\n"; + + std::cout << "X size : " << stats.x_size << "\n"; + std::cout << "Y size : " << stats.y_size << "\n"; + + std::cout << "PO benchmark : " << benchmark_network.num_pos() << "\n"; + std::cout << "PO planarized : " << planarized_b.num_pos() << "\n"; + std::cout << "PO layout : " << layout.num_pos() << "\n"; + + fiction::gate_level_drv_params ps_d{}; + fiction::gate_level_drv_stats st_d{}; + + fiction::gate_level_drvs(layout, ps_d, &st_d); + + /*fiction::equivalence_checking_stats eq_s_ortho{}; // check equivalence const auto eq_stats_ortho = fiction::equivalence_checking(planarized_b, layout, &eq_s_ortho); - + std::cout << "eq_checking gone\n"; const std::string eq_result_ortho = eq_stats_ortho == fiction::eq_type::STRONG ? "STRONG" : eq_stats_ortho == fiction::eq_type::WEAK ? "WEAK" : - "NO"; + "NO";*/ + + const auto miter = mockturtle::miter(planarized_b, layout); + bool eq; + if (miter) + { + mockturtle::equivalence_checking_stats st; - /*fiction::debug::write_dot_layout(layout); - fiction::debug::write_dot_network(_b);*/ + const auto ce = mockturtle::equivalence_checking(*miter, {}, &st); + eq = ce.value(); + } - // check equivalence - mockturtle::equivalence_checking_stats st; - const auto cec_m = mockturtle::equivalence_checking( - *fiction::virtual_miter(benchmark_network, planarized_b), {}, &st); - assert(cec_m.has_value()); + // fiction::debug::write_dot_layout(layout); + /*fiction::debug::write_dot_network(_b, "ntk_b"); + fiction::debug::write_dot_network(planarized_b, "ntk_p");*/ // log results - wiring_reduction_exp(benchmark, benchmark_network.num_pis(), benchmark_network.num_pos(), - benchmark_network.num_gates(), _b.num_gates(), is_planar, static_cast(cec_m), - eq_result_ortho); + wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), benchmark_network.num_pos(), + benchmark_network.num_gates(), _b.num_gates(), planarized_b.num_gates(), is_planar, cec_m.value(), eq); wiring_reduction_exp.save(); wiring_reduction_exp.table(); } return EXIT_SUCCESS; -} +} \ No newline at end of file diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index d066f0eda..42bd40ea4 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -5,7 +5,6 @@ #ifndef FICTION_NODE_DUPLICATION_PLANARIZATION_HPP #define FICTION_NODE_DUPLICATION_PLANARIZATION_HPP -#include "fiction/algorithms/network_transformation/network_balancing.hpp" #include "fiction/algorithms/properties/check_planarity.hpp" #include "fiction/networks/views/extended_rank_view.hpp" #include "fiction/networks/virtual_pi_network.hpp" @@ -17,9 +16,7 @@ #include #include #include -#include #include -#include #include #include @@ -212,6 +209,29 @@ class node_duplication_planarization_impl node_pair_cur.fanin_pair = &node_pair_last; node_pair_cur.delay = node_pair_last.delay + 2; } + else if (node_pair_last.delay + 2 == node_pair_cur.delay) + { + // ToDo: If order doesnt matter, decide on a minimal crossing view (implement mincross.c from + // graphviz) + + // this solves equal paths, if they are connected in the next layer via a fanout + const auto fc0 = fanins(ntk, node_pair_last.pair.first); + if (node_pair_last.fanin_pair != nullptr) + { + const auto fc1 = fanins(ntk, node_pair_last.fanin_pair->pair.second); + for (const auto f0 : fc0.fanin_nodes) + { + for (const auto f1 : fc1.fanin_nodes) + { + if (f0 == f1) + { + node_pair_cur.fanin_pair = &node_pair_last; + break; + } + } + } + } + } } } } @@ -236,11 +256,25 @@ class node_duplication_planarization_impl * @param node The node to be inserted. * @param vec The vector to insert the node into. */ - void insert_if_not_first(const mockturtle::node& node, std::vector>& vec) + void insert_if_not_first(const mockturtle::node& node, std::vector>& vec, + int& saturated_fanout_flag, int position) { if (vec.empty() || vec.front() != node) { vec.insert(vec.begin(), node); + saturated_fanout_flag = 0; + } + else if (position == 0) + { + if (saturated_fanout_flag == 1) + { + vec.insert(vec.begin(), node); + saturated_fanout_flag = 0; + } + else + { + saturated_fanout_flag = 1; + } } } @@ -255,7 +289,8 @@ class node_duplication_planarization_impl */ void compute_node_order_next_level(std::vector>& next_level) { - const auto& combinations = lvl_pairs.back(); + int saturated_fanout_flag = 0; + const auto& combinations = lvl_pairs.back(); // select the path with the least delay and follow it via fanin relations const auto minimum_it = std::min_element(combinations.cbegin(), combinations.cend(), @@ -265,32 +300,32 @@ class node_duplication_planarization_impl const auto& min_combination = *minimum_it; // Insert the terminal node - insert_if_not_first(min_combination.pair.second, next_level); + insert_if_not_first(min_combination.pair.second, next_level, saturated_fanout_flag, 0); // insert middle_nodes for (const auto& node : min_combination.middle_nodes) { - insert_if_not_first(node, next_level); + insert_if_not_first(node, next_level, saturated_fanout_flag, 1); } // Insert the first node - insert_if_not_first(min_combination.pair.first, next_level); + insert_if_not_first(min_combination.pair.first, next_level, saturated_fanout_flag, 1); auto fanin_combination = minimum_it->fanin_pair; while (fanin_combination) { // Insert the terminal node - insert_if_not_first(fanin_combination->pair.second, next_level); + insert_if_not_first(fanin_combination->pair.second, next_level, saturated_fanout_flag, 0); // Insert middle_nodes for (const auto& node : fanin_combination->middle_nodes) { - insert_if_not_first(node, next_level); + insert_if_not_first(node, next_level, saturated_fanout_flag, 1); } // insert the first node - insert_if_not_first(fanin_combination->pair.first, next_level); + insert_if_not_first(fanin_combination->pair.first, next_level, saturated_fanout_flag, 1); fanin_combination = fanin_combination->fanin_pair; } @@ -323,16 +358,10 @@ class node_duplication_planarization_impl // ToDO: implement border_pis (if there is a choice ush pis to the borders (first or last rank)) const bool border_pis = true; - std::unordered_map po_counts; - - ntk.foreach_po([&po_counts](auto po) { po_counts[po]++; }); - std::vector pos{}; pos.reserve(ntk.num_pos()); - for (const auto& kv : po_counts) - { - pos.push_back(kv.first); - } + + ntk.foreach_po([&pos](auto po) { pos.push_back(po); }); // Randomize the PO order if (ps.random_output_order) @@ -368,11 +397,6 @@ class node_duplication_planarization_impl // Process all other levels while (!v_level.empty() && !f_final_level) { - // ToDo: Fix the creation of the depth_view/rank_view - if (v_level.size() > 25000) - { - return std::nullopt; - } // Push the level to the network ntk_lvls.push_back(v_level); lvl_pairs.clear(); diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index 6cd00e019..d49114ca6 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -241,6 +241,7 @@ class extended_rank_view : public mockturtle::depth_view void modify_rank(const uint32_t level, const std::vector& nodes) { auto& rank = ranks[level]; + assert(rank.size() == nodes.size()); rank = nodes; std::for_each(rank.cbegin(), rank.cend(), [this, i = 0u](auto const& n) mutable { rank_pos[n] = i++; }); } diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 69201718b..1bbfcd78f 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -309,6 +309,7 @@ class virtual_pi_network : public Ntk old2new_v[nd].push_back(new_node); continue; } + assert(false); } } } diff --git a/test/algorithms/properties/check_planarity.cpp b/test/algorithms/properties/check_planarity.cpp index a0ca81141..7ebb2897a 100644 --- a/test/algorithms/properties/check_planarity.cpp +++ b/test/algorithms/properties/check_planarity.cpp @@ -7,11 +7,9 @@ #include #include #include - -#include -#include - #include +#include +#include using namespace fiction; diff --git a/test/algorithms/verification/virtual_miter.cpp b/test/algorithms/verification/virtual_miter.cpp index ec6d5bc7a..3d1a276ec 100644 --- a/test/algorithms/verification/virtual_miter.cpp +++ b/test/algorithms/verification/virtual_miter.cpp @@ -55,4 +55,4 @@ TEST_CASE("Miter network positions", "[virtual-miter]") mockturtle::equivalence_checking(*fiction::virtual_miter(vpi_ntk_1, vpi_ntk_2), {}, &st); REQUIRE(maybe_cec_m.has_value()); CHECK(*maybe_cec_m == 1); -} +} \ No newline at end of file diff --git a/test/networks/views/extended_rank_view.cpp b/test/networks/views/extended_rank_view.cpp index a71a49f1d..945db2a4a 100644 --- a/test/networks/views/extended_rank_view.cpp +++ b/test/networks/views/extended_rank_view.cpp @@ -90,7 +90,7 @@ TEST_CASE("Check modify ranks", "[extended-rank-view]") auto vpi_r = extended_rank_view(tec_balanced); - const std::vector nodes = {13, 10}; + const std::vector nodes = {13, 10, 14}; vpi_r.modify_rank(2, nodes); CHECK(vpi_r.check_validity() == 1); diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index a7c9600a2..2a3d18bb3 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -5,9 +5,10 @@ #include #include +#include + #include #include -#include #include #include @@ -117,7 +118,7 @@ TEST_CASE("Check equivalence of an extended_rank view", "[virtual-pi-view]") tec.create_po(f2_t); tec.create_po(f3_t); - auto ntk_r = extended_rank_view(vpi); + auto ntk_r = extended_rank_view(vpi); mockturtle::equivalence_checking_stats st; const auto maybe_cec_m = From bb3195ad746e565a0783f8d44859bfbfd638d1f9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:31:32 +0000 Subject: [PATCH 66/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- experiments/legalization/legalization.cpp | 45 ++++++++++--------- .../networks/views/extended_rank_view.hpp | 2 +- .../algorithms/properties/check_planarity.cpp | 6 ++- .../algorithms/verification/virtual_miter.cpp | 2 +- test/networks/virtual_pi_network.cpp | 5 +-- 5 files changed, 31 insertions(+), 29 deletions(-) diff --git a/experiments/legalization/legalization.cpp b/experiments/legalization/legalization.cpp index 19de33457..19e5a4231 100644 --- a/experiments/legalization/legalization.cpp +++ b/experiments/legalization/legalization.cpp @@ -49,8 +49,7 @@ Ntk read_ntk(const std::string& name) int main() // NOLINT { - experiments::experiment + experiments::experiment wiring_reduction_exp{"planarization", "benchmark", "inputs", "virt_inputs", "outputs", "initial nodes", "nodes buffered", "nodes planarized", "is_planar", "equivalent(ntk)", "equivalent(lyt)"}; @@ -69,15 +68,15 @@ int main() // NOLINT { continue; }*/ - if ( "C432.v" == entry.path().filename().string()) + if ("C432.v" == entry.path().filename().string()) { continue; } - if ( "ex4p.v" == entry.path().filename().string()) + if ("ex4p.v" == entry.path().filename().string()) { continue; } - if ( "apex1.v" == entry.path().filename().string()) + if ("apex1.v" == entry.path().filename().string()) { continue; } @@ -143,7 +142,7 @@ int main() // NOLINT } const auto planarized_b = fiction::node_duplication_planarization(_b); - const auto is_planar = fiction::check_planarity(planarized_b); + const auto is_planar = fiction::check_planarity(planarized_b); if (planarized_b.size() > 20000) { continue; @@ -168,13 +167,13 @@ int main() // NOLINT fiction::gate_level_drvs(layout, ps_d, &st_d); const auto miter = mockturtle::miter(planarized_b, layout); - bool eq; + bool eq; if (miter) { mockturtle::equivalence_checking_stats st; const auto ce = mockturtle::equivalence_checking(*miter, {}, &st); - eq = ce.value(); + eq = ce.value(); } wiring_reduction_exp(entry.path().filename().string(), benchmark_network.num_pis(), planarized_b.num_virtual_pis(), benchmark_network.num_pos(), benchmark_network.num_gates(), @@ -242,10 +241,9 @@ int main() // NOLINT { cont = true; std::cout << "Pi is Po\n"; - } }); - if(cont) + if (cont) { continue; } @@ -268,8 +266,9 @@ int main() // NOLINT if (planarized_b.size() > 30000) { - wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), benchmark_network.num_pos(), - benchmark_network.num_gates(), _b.num_gates(), planarized_b.num_gates(), is_planar, 0, 0); + wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), + benchmark_network.num_pos(), benchmark_network.num_gates(), _b.num_gates(), + planarized_b.num_gates(), is_planar, 0, 0); wiring_reduction_exp.save(); wiring_reduction_exp.table(); continue; @@ -285,14 +284,15 @@ int main() // NOLINT fiction::restore_names(benchmark_network, name); - using gate_lyt = - fiction::gate_level_layout>>>; + using gate_lyt = fiction::gate_level_layout< + fiction::clocked_layout>>>; fiction::orthogonal_physical_design_stats stats{}; - using gate_layout = fiction::gate_level_layout>>>; - auto start = std::chrono::high_resolution_clock::now(); + using gate_layout = fiction::gate_level_layout< + fiction::clocked_layout>>>; + auto start = std::chrono::high_resolution_clock::now(); auto layout = fiction::orthogonal(planarized_b, {}, &stats); - auto stop = std::chrono::high_resolution_clock::now(); + auto stop = std::chrono::high_resolution_clock::now(); std::chrono::duration elapsed = stop - start; @@ -320,13 +320,13 @@ int main() // NOLINT "NO";*/ const auto miter = mockturtle::miter(planarized_b, layout); - bool eq; + bool eq; if (miter) { mockturtle::equivalence_checking_stats st; const auto ce = mockturtle::equivalence_checking(*miter, {}, &st); - eq = ce.value(); + eq = ce.value(); } // fiction::debug::write_dot_layout(layout); @@ -334,12 +334,13 @@ int main() // NOLINT fiction::debug::write_dot_network(planarized_b, "ntk_p");*/ // log results - wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), benchmark_network.num_pos(), - benchmark_network.num_gates(), _b.num_gates(), planarized_b.num_gates(), is_planar, cec_m.value(), eq); + wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), + benchmark_network.num_pos(), benchmark_network.num_gates(), _b.num_gates(), + planarized_b.num_gates(), is_planar, cec_m.value(), eq); wiring_reduction_exp.save(); wiring_reduction_exp.table(); } return EXIT_SUCCESS; -} \ No newline at end of file +} diff --git a/include/fiction/networks/views/extended_rank_view.hpp b/include/fiction/networks/views/extended_rank_view.hpp index d49114ca6..9a85ad48e 100644 --- a/include/fiction/networks/views/extended_rank_view.hpp +++ b/include/fiction/networks/views/extended_rank_view.hpp @@ -242,7 +242,7 @@ class extended_rank_view : public mockturtle::depth_view { auto& rank = ranks[level]; assert(rank.size() == nodes.size()); - rank = nodes; + rank = nodes; std::for_each(rank.cbegin(), rank.cend(), [this, i = 0u](auto const& n) mutable { rank_pos[n] = i++; }); } diff --git a/test/algorithms/properties/check_planarity.cpp b/test/algorithms/properties/check_planarity.cpp index 7ebb2897a..a0ca81141 100644 --- a/test/algorithms/properties/check_planarity.cpp +++ b/test/algorithms/properties/check_planarity.cpp @@ -7,9 +7,11 @@ #include #include #include -#include -#include + #include +#include + +#include using namespace fiction; diff --git a/test/algorithms/verification/virtual_miter.cpp b/test/algorithms/verification/virtual_miter.cpp index 3d1a276ec..ec6d5bc7a 100644 --- a/test/algorithms/verification/virtual_miter.cpp +++ b/test/algorithms/verification/virtual_miter.cpp @@ -55,4 +55,4 @@ TEST_CASE("Miter network positions", "[virtual-miter]") mockturtle::equivalence_checking(*fiction::virtual_miter(vpi_ntk_1, vpi_ntk_2), {}, &st); REQUIRE(maybe_cec_m.has_value()); CHECK(*maybe_cec_m == 1); -} \ No newline at end of file +} diff --git a/test/networks/virtual_pi_network.cpp b/test/networks/virtual_pi_network.cpp index 2a3d18bb3..a7c9600a2 100644 --- a/test/networks/virtual_pi_network.cpp +++ b/test/networks/virtual_pi_network.cpp @@ -5,10 +5,9 @@ #include #include -#include - #include #include +#include #include #include @@ -118,7 +117,7 @@ TEST_CASE("Check equivalence of an extended_rank view", "[virtual-pi-view]") tec.create_po(f2_t); tec.create_po(f3_t); - auto ntk_r = extended_rank_view(vpi); + auto ntk_r = extended_rank_view(vpi); mockturtle::equivalence_checking_stats st; const auto maybe_cec_m = From 89bb7b2ec3b51b357a1c3d7904b02fb590824d9f Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 19 Sep 2024 15:01:39 +0000 Subject: [PATCH 67/84] :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions --- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 312 ++++++++++++++++++ 1 file changed, 312 insertions(+) diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index beb224e23..13b955238 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -2059,6 +2059,54 @@ Template parameter ``Dist``: static const char *__doc_fiction_chebyshev_distance_functor_chebyshev_distance_functor = R"doc()doc"; +static const char *__doc_fiction_check_planarity = +R"doc(Checks if a logic network is planar for a network that is path +balanced and has ranks assigned. + +If the network is not balanced, an exception is thrown. To balance the +network, insert buffers to divide multi-level edges. + +It checks if the network represented by the variable `ntk` is planar. +The network is planar if, for any edge with starting point :math:`m` +and endpoint :math:`n` (represented by the node ranks), there is never +another edge with starting point :math:`m' > m` and endpoint :math:`n' +< n`, or vice versa. When iterating through the ranks of one level, +the endpoints are always increasing. Therefore, only the starting +points need to be checked. Thus, the highest connected starting point +in the fan-in gives a border :math:`m_{\text{max}}` for every +subsequent edge. + +Template parameter ``Ntk``: + Logic network type. + +Parameter ``ntk``: + The logic network to check for planarity. + +Returns: + `true` if the network is planar, `false` otherwise.)doc"; + +static const char *__doc_fiction_check_planarity_impl = R"doc()doc"; + +static const char *__doc_fiction_check_planarity_impl_check_planarity_impl = R"doc()doc"; + +static const char *__doc_fiction_check_planarity_impl_ntk = R"doc()doc"; + +static const char *__doc_fiction_check_planarity_impl_run = +R"doc(Checks if a given network is planar. + +This function checks if the network represented by the variable `ntk` +is planar. The network is planar if, for any edge with starting point +:math:`m` and endpoint :math:`n` (represented by the node ranks), +there is never another edge with starting point :math:`m' > m` and +endpoint :math:`n' < n`, or vice versa. When iterating through the +ranks of one level, the endpoints are always increasing. Therefore, +only the starting points need to be checked. Thus, the highest +connected starting point in the fan-in gives a border +:math:`m_{\text{max}}` for every subsequent edge. + +Returns: + `true` if the network is planar, `false` otherwise.)doc"; + static const char *__doc_fiction_check_simulation_results_for_equivalence = R"doc(This function compares two SiDB simulation results for equivalence. Two results are considered equivalent if they have the same number of @@ -3445,6 +3493,20 @@ Parameter ``neutral_defect_spacing_overwrite``: A pair of uint16_t values representing the number of horizontal and vertical SiDBs affected by the given defect type.)doc"; +static const char *__doc_fiction_delete_virtual_pis = +R"doc(Deletes virtual primary inputs from a network. This can mainly be used +for equivalence checking. If the network does not have any virtual PIs +stored, the network is returned. + +Template parameter ``Ntk``: + The type of network. + +Parameter ``ntk``: + The input network. + +Returns: + The resulting network after virtual primary inputs are deleted.)doc"; + static const char *__doc_fiction_dependent_cell_mode = R"doc(An enumeration of modes for the dependent cell.)doc"; static const char *__doc_fiction_dependent_cell_mode_FIXED = @@ -4019,6 +4081,23 @@ Parameter ``to_delete``: Returns: A 2D vector representing the calculated offset matrix.)doc"; +static const char *__doc_fiction_detail_calculate_pairs = +R"doc(Calculates pairs of nodes from a given vector of nodes. + +This function takes a vector of nodes and returns a vector of node +pairs. Each node pair consists of two nodes from the input vector and +an optional vector of middle nodes. The delay of each node pair is +initialized to infinity. + +Template parameter ``Ntk``: + The network type. + +Parameter ``nodes``: + The vector of nodes. + +Returns: + The vector of node pairs.)doc"; + static const char *__doc_fiction_detail_color_routing_impl = R"doc()doc"; static const char *__doc_fiction_detail_color_routing_impl_color_routing_impl = R"doc()doc"; @@ -6558,6 +6637,111 @@ static const char *__doc_fiction_detail_new_gate_location_NONE = R"doc(Do not ch static const char *__doc_fiction_detail_new_gate_location_SRC = R"doc(Check if the source tile is empty.)doc"; +static const char *__doc_fiction_detail_node_duplication_planarization_impl = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_check_final_level = +R"doc(Checks if the given vector of nodes contains any non-primary inputs. + +This function iterates through each node in the vector and checks if +it is a primary input. If a non-primary input is found, the +`f_final_level` parameter is set to false and the loop is exited. + +Parameter ``v_next_level``: + The vector of nodes to be checked.)doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_compute_node_order_next_level = +R"doc(Computes the order of nodes in the next level based on delay + +This function computes the order of nodes in the next level based on +their delay in the H-graph of the level. It selects the path with the +least delay from the current level pairs and follows it via fanin +relations. The nodes are inserted into the next level vector in the +order they are encountered. + +Parameter ``next_level``: + The vector to store the nodes in the next level.)doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_compute_slice_delays = +R"doc(Computes the delay in a given slice (each possible order of +node_pairs) of an H-graph. + +This function iterates over the fanins of the given node and computes +the delay for all possible orders of these nodes that form a +node_pair. The delay computation depends on the node's connections and +position within the graph. If there is a connection between two +node_pairs, the delay is incremented by 1. If not, the delay is +incremented by 2. Default delay for the first node is 1. If a +node_pair doesn't have a connection and its delay (when increased by +two) is less than the existing delay, then this node_pair's delay is +updated. + +The processed node_pairs are pushed back to the 'lvl_pairs' data +member for subsequent delay calculations. + +Parameter ``nd``: + Node in the H-graph. + +Parameter ``border_pis``: + A boolean indicating whether the input PIs (Primary Inputs) should + be propagated to the next level.)doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_insert_if_not_first = +R"doc(Inserts a node into a vector if it is unique. + +This function inserts a node into a vector only if the vector is empty +or the node is not equal to the first element of the vector. If the +vector is not empty and the node is equal to the first element, it +does nothing. + +Parameter ``node``: + The node to be inserted. + +Parameter ``vec``: + The vector to insert the node into.)doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_lvl_pairs = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_node_duplication_planarization_impl = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_ntk = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_ps = R"doc()doc"; + +static const char *__doc_fiction_detail_node_duplication_planarization_impl_run = R"doc()doc"; + +static const char *__doc_fiction_detail_node_pair = +R"doc(A structure representing a pair of nodes in an H-graph. + +The nodes stored in this struct describe the fanin-edges of a node in +an H-graph. A node pair object holds two nodes, which are saved in the +member 'pair'. These two outer nodes are connected through zero or +more 'middle_nodes'. The fanin order starts with the first node in +'pair', then proceeds through the 'middle_nodes', and ends with the +second node in 'pair'. The order of 'middle_nodes' is arbitrary as +they cannot be further connected to any other nodes. For the +planarization, only the nodes inside the 'pair' are relevant. + +Template parameter ``Ntk``: + Network type for the nodes in the pair.)doc"; + +static const char *__doc_fiction_detail_node_pair_delay = R"doc(Specifies the delay value for the node.)doc"; + +static const char *__doc_fiction_detail_node_pair_fanin_pair = +R"doc(Shared pointer to another instance of node_pair detailing fanin-edge +alignment.)doc"; + +static const char *__doc_fiction_detail_node_pair_node_pair = +R"doc(Standard constructor. + +Parameter ``node1``: + The first node of the fanin-edged node. + +Parameter ``node2``: + The second node of the fanin-edged node. + +Parameter ``delayValue``: + The delay value for the node.)doc"; + static const char *__doc_fiction_detail_on_the_fly_circuit_design_impl = R"doc()doc"; static const char *__doc_fiction_detail_on_the_fly_circuit_design_impl_design_circuit_on_defective_surface = R"doc()doc"; @@ -9178,6 +9362,32 @@ Parameter ``ps``: Returns: sidb_simulation_result is returned with all results.)doc"; +static const char *__doc_fiction_extended_rank_view = +R"doc(@class extended_rank_view + +If already a rank_interface exists only the depth_view constructor +gets called. + +Template parameter ``Ntk``: + The network type.)doc"; + +static const char *__doc_fiction_extended_rank_view_2 = +R"doc(Deduction guide for `extended_rank_view' + +Template parameter ``T``: + Network type deduced from the construction context of + `extended_rank_view`.)doc"; + +static const char *__doc_fiction_extended_rank_view_3 = +R"doc(Deduction guide for `extended_rank_view` with two constructor +arguments + +Template parameter ``T``: + Network type deduced from the construction context of + `extended_rank_view`.)doc"; + +static const char *__doc_fiction_extended_rank_view_extended_rank_view = R"doc()doc"; + static const char *__doc_fiction_extract_routing_objectives = R"doc(Extracts all routing objectives from the given layout. To this end, all routing paths in the layout are traversed, starting at each PI. @@ -11401,6 +11611,8 @@ Parameter ``m``: static const char *__doc_fiction_gray_code_iterator_start_number = R"doc(Start number of the iteration.)doc"; +static const char *__doc_fiction_handle_virtual_pis = R"doc()doc"; + static const char *__doc_fiction_has_above = R"doc()doc"; static const char *__doc_fiction_has_assign_charge_state = R"doc()doc"; @@ -11433,6 +11645,8 @@ static const char *__doc_fiction_has_foreach_incoming_clocked_zone = R"doc()doc" static const char *__doc_fiction_has_foreach_outgoing_clocked_zone = R"doc()doc"; +static const char *__doc_fiction_has_foreach_real_pi = R"doc()doc"; + static const char *__doc_fiction_has_foreach_sidb_defect = R"doc()doc"; static const char *__doc_fiction_has_foreach_tile = R"doc()doc"; @@ -11445,6 +11659,8 @@ static const char *__doc_fiction_has_get_gate_ports = R"doc()doc"; static const char *__doc_fiction_has_get_layout_name = R"doc()doc"; +static const char *__doc_fiction_has_get_real_pi = R"doc()doc"; + static const char *__doc_fiction_has_get_sidb_defect = R"doc()doc"; static const char *__doc_fiction_has_high_degree_fanin_nodes = @@ -11541,10 +11757,16 @@ static const char *__doc_fiction_has_north_east = R"doc()doc"; static const char *__doc_fiction_has_north_west = R"doc()doc"; +static const char *__doc_fiction_has_num_real_pis = R"doc()doc"; + +static const char *__doc_fiction_has_num_virtual_pis = R"doc()doc"; + static const char *__doc_fiction_has_ordinal_operations = R"doc()doc"; static const char *__doc_fiction_has_post_layout_optimization = R"doc()doc"; +static const char *__doc_fiction_has_remove_virtual_input_nodes = R"doc()doc"; + static const char *__doc_fiction_has_set_layout_name = R"doc()doc"; static const char *__doc_fiction_has_south = R"doc()doc"; @@ -13135,6 +13357,49 @@ Parameter ``file``: Parameter ``rfun``: The actual parsing function.)doc"; +static const char *__doc_fiction_node_duplication_planarization = +R"doc(Implements a planarization mechanism for networks using a H-Graph +strategy for node duplication. + +The planarization achieved by this function solves the Node +Duplication Crossing Minimization (NDCE) problem by finding the +shortest x-y path in the H-graph for every level in the network. An +H-graph describes edge relations between two levels in a network, with +one level assumed as fixed, starting at the Primary Outputs (POs). By +finding the shortest path from the source (x) to the sink (y) in this +H-graph, an optimal solution for the NDCE problem is found. The +function constructs an H-graph that captures edge relations between +two levels within the graph and computes the shortest x-y paths on the +H-graph, traversing from the POs towards the Primary Inputs (PIs). + +Returns: + A view of the planarized virtual_pi_network created in the format + of extended_rank_view. + +Template parameter ``NtkDest``: + Destination network type. + +Template parameter ``NtkSrc``: + Source network type. + +Parameter ``ntk_src``: + Source network to be utilized for the planarization. + +Parameter ``ps``: + Node duplication parameters used in the computation. + +Throws: + std::runtime_error if input network not balanced, if no node + combinations are found or if the created network is non-planar.)doc"; + +static const char *__doc_fiction_node_duplication_planarization_params = R"doc(Parameters for the node duplication algorithm.)doc"; + +static const char *__doc_fiction_node_duplication_planarization_params_random_output_order = +R"doc(The output order determines the starting layer for this algorithm. If +this option is turned off, the output order remains the same as in the +provided network. If it is turned on, the outputs are ordered +randomly.)doc"; + static const char *__doc_fiction_normalize_layout_coordinates = R"doc(A new layout is constructed and returned that is equivalent to the given cell-level layout. However, its coordinates are normalized, @@ -17294,6 +17559,53 @@ static const char *__doc_fiction_vertical_shift_cartesian = R"doc(\verbatim +-------+ | | | +-------+ | | | +-------+ | | | +-------+ \endverbatim)doc"; +static const char *__doc_fiction_virtual_miter = +R"doc(This method combines two networks to a combinational miter like a +mockturtle::miter. Additionally, either of the input networks can be a +network with virtual inputs, which are duplicated PIs. In this case +the duplicated PIs are deleted and all edges connecting to them are +remapped on their originating PI. + +Therefore, the miter has the same number of inputs and one primary +output. This output is the OR of XORs of all primary output pairs. In +other words, the miter outputs 1 for all input assignments in which +the two input networks differ. + +All networks may have different types. The method returns an optional, +which is `nullopt`, whenever the two input networks don't match in +their number of primary inputs and primary outputs.)doc"; + +static const char *__doc_fiction_virtual_pi_network = R"doc()doc"; + +static const char *__doc_fiction_virtual_pi_network_clone = R"doc(Clones the virtual_pi_network object.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network = +R"doc(Default constructor for the `virtual_pi_network` class. Initializes +`_storage` as a shared pointer.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_2 = R"doc(Copy constructor for the `virtual_pi_network` class.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_3 = +R"doc(Constructor for the `virtual_pi_network` class that takes a network as +input. Unlike other network types a virtual_pi_network can be created +on top of any network. It initializes the base class `Ntk` with a +clone of the provided network and creates a shared pointer to a +`virtual_storage` object. + +Template parameter ``Ntk``: + Network type. + +Parameter ``ntk``: + Input network.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_4 = R"doc()doc"; + +static const char *__doc_fiction_virtual_storage = R"doc()doc"; + +static const char *__doc_fiction_virtual_storage_map_virt_to_real_pi = R"doc(Map from virtual_pis to real_pis.)doc"; + +static const char *__doc_fiction_virtual_storage_virtual_inputs = R"doc(Shared pointer vector storage for virtual_inputs.)doc"; + static const char *__doc_fiction_volume = R"doc(Computes the volume of a given coordinate assuming its origin is (0, 0, 0). Calculates :math:`(|x| + 1) \cdot (|y| + 1) \cdot (|z| + 1)` by From cbfbd6fb904e8f69c773fb88f6a990570170719d Mon Sep 17 00:00:00 2001 From: benjamin Date: Fri, 20 Sep 2024 10:18:52 +0200 Subject: [PATCH 68/84] :art: bugfix: reverted changes for pos in node_duplication_legalization --- experiments/legalization/legalization.cpp | 51 +++++++++---------- .../node_duplication_planarization.hpp | 10 +++- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/experiments/legalization/legalization.cpp b/experiments/legalization/legalization.cpp index 19e5a4231..7f45f3ecb 100644 --- a/experiments/legalization/legalization.cpp +++ b/experiments/legalization/legalization.cpp @@ -49,7 +49,8 @@ Ntk read_ntk(const std::string& name) int main() // NOLINT { - experiments::experiment + experiments::experiment wiring_reduction_exp{"planarization", "benchmark", "inputs", "virt_inputs", "outputs", "initial nodes", "nodes buffered", "nodes planarized", "is_planar", "equivalent(ntk)", "equivalent(lyt)"}; @@ -58,6 +59,7 @@ int main() // NOLINT for (const auto& entry : std::filesystem::directory_iterator("/home/benjamin/Documents/Repositories/working/fiction/benchmarks/IWLS93")) { + continue; fmt::print("[i] processing {}\n", entry.path().filename().string()); /*if ( "sqrt8ml.v" != entry.path().filename().string()) @@ -68,15 +70,15 @@ int main() // NOLINT { continue; }*/ - if ("C432.v" == entry.path().filename().string()) + if ( "C432.v" == entry.path().filename().string()) { continue; } - if ("ex4p.v" == entry.path().filename().string()) + if ( "ex4p.v" == entry.path().filename().string()) { continue; } - if ("apex1.v" == entry.path().filename().string()) + if ( "apex1.v" == entry.path().filename().string()) { continue; } @@ -142,7 +144,7 @@ int main() // NOLINT } const auto planarized_b = fiction::node_duplication_planarization(_b); - const auto is_planar = fiction::check_planarity(planarized_b); + const auto is_planar = fiction::check_planarity(planarized_b); if (planarized_b.size() > 20000) { continue; @@ -167,13 +169,13 @@ int main() // NOLINT fiction::gate_level_drvs(layout, ps_d, &st_d); const auto miter = mockturtle::miter(planarized_b, layout); - bool eq; + bool eq; if (miter) { mockturtle::equivalence_checking_stats st; const auto ce = mockturtle::equivalence_checking(*miter, {}, &st); - eq = ce.value(); + eq = ce.value(); } wiring_reduction_exp(entry.path().filename().string(), benchmark_network.num_pis(), planarized_b.num_virtual_pis(), benchmark_network.num_pos(), benchmark_network.num_gates(), @@ -222,12 +224,11 @@ int main() // NOLINT fiction::debug::write_dot_network(_b, "t_b"); fiction::debug::write_dot_network(planarized_b, "network_b");*/ - static constexpr const uint64_t bench_select = (fiction_experiments::fontes18); // fiction_experiments::iscas85 & ~ + static constexpr const uint64_t bench_select = (fiction_experiments::iscas85); // fiction_experiments::iscas85 & ~ // fiction_experiments::trindade16 | fiction_experiments::fontes18 | fiction_experiments::epfl | // fiction_experiments::iscas85 static constexpr const uint64_t bench_select = for (const auto& benchmark : fiction_experiments::all_benchmarks(bench_select)) { - continue; const auto benchmark_network = read_ntk(benchmark); fiction::network_balancing_params ps; @@ -241,9 +242,10 @@ int main() // NOLINT { cont = true; std::cout << "Pi is Po\n"; + } }); - if (cont) + if(cont) { continue; } @@ -251,7 +253,7 @@ int main() // NOLINT const auto _b = fiction::network_balancing( fiction::fanout_substitution(benchmark_network), ps); - if (_b.size() > 15000) + if (_b.size() > 10000) { /*wiring_reduction_exp(benchmark, benchmark_network.num_pis(), 0, benchmark_network.num_pos(), benchmark_network.num_gates(), _b.num_gates(), _b.num_gates(), 0, 0, "TEST"); @@ -264,11 +266,10 @@ int main() // NOLINT const auto is_planar = fiction::check_planarity(planarized_b); - if (planarized_b.size() > 30000) + if (planarized_b.size() > 20000) { - wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), - benchmark_network.num_pos(), benchmark_network.num_gates(), _b.num_gates(), - planarized_b.num_gates(), is_planar, 0, 0); + wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), benchmark_network.num_pos(), + benchmark_network.num_gates(), _b.num_gates(), planarized_b.num_gates(), is_planar, 0, 0); wiring_reduction_exp.save(); wiring_reduction_exp.table(); continue; @@ -284,15 +285,14 @@ int main() // NOLINT fiction::restore_names(benchmark_network, name); - using gate_lyt = fiction::gate_level_layout< - fiction::clocked_layout>>>; + using gate_lyt = + fiction::gate_level_layout>>>; fiction::orthogonal_physical_design_stats stats{}; - using gate_layout = fiction::gate_level_layout< - fiction::clocked_layout>>>; - auto start = std::chrono::high_resolution_clock::now(); + using gate_layout = fiction::gate_level_layout>>>; + auto start = std::chrono::high_resolution_clock::now(); auto layout = fiction::orthogonal(planarized_b, {}, &stats); - auto stop = std::chrono::high_resolution_clock::now(); + auto stop = std::chrono::high_resolution_clock::now(); std::chrono::duration elapsed = stop - start; @@ -320,13 +320,13 @@ int main() // NOLINT "NO";*/ const auto miter = mockturtle::miter(planarized_b, layout); - bool eq; + bool eq; if (miter) { mockturtle::equivalence_checking_stats st; const auto ce = mockturtle::equivalence_checking(*miter, {}, &st); - eq = ce.value(); + eq = ce.value(); } // fiction::debug::write_dot_layout(layout); @@ -334,9 +334,8 @@ int main() // NOLINT fiction::debug::write_dot_network(planarized_b, "ntk_p");*/ // log results - wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), - benchmark_network.num_pos(), benchmark_network.num_gates(), _b.num_gates(), - planarized_b.num_gates(), is_planar, cec_m.value(), eq); + wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), benchmark_network.num_pos(), + benchmark_network.num_gates(), _b.num_gates(), planarized_b.num_gates(), is_planar, cec_m.value(), eq); wiring_reduction_exp.save(); wiring_reduction_exp.table(); diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 42bd40ea4..0a0ddeaf2 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -16,7 +16,9 @@ #include #include #include +#include #include +#include #include #include @@ -358,10 +360,14 @@ class node_duplication_planarization_impl // ToDO: implement border_pis (if there is a choice ush pis to the borders (first or last rank)) const bool border_pis = true; + std::unordered_map po_counts; + ntk.foreach_po([&po_counts](auto po) { po_counts[po]++; }); std::vector pos{}; pos.reserve(ntk.num_pos()); - - ntk.foreach_po([&pos](auto po) { pos.push_back(po); }); + for (const auto& kv : po_counts) + { + pos.push_back(kv.first); + } // Randomize the PO order if (ps.random_output_order) From ac0ff0f1c5ddecc346ed67075ca0a7e27dbfb8a4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 08:19:10 +0000 Subject: [PATCH 69/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- experiments/legalization/legalization.cpp | 43 ++++++++++++----------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/experiments/legalization/legalization.cpp b/experiments/legalization/legalization.cpp index 7f45f3ecb..0f8664d13 100644 --- a/experiments/legalization/legalization.cpp +++ b/experiments/legalization/legalization.cpp @@ -49,8 +49,7 @@ Ntk read_ntk(const std::string& name) int main() // NOLINT { - experiments::experiment + experiments::experiment wiring_reduction_exp{"planarization", "benchmark", "inputs", "virt_inputs", "outputs", "initial nodes", "nodes buffered", "nodes planarized", "is_planar", "equivalent(ntk)", "equivalent(lyt)"}; @@ -70,15 +69,15 @@ int main() // NOLINT { continue; }*/ - if ( "C432.v" == entry.path().filename().string()) + if ("C432.v" == entry.path().filename().string()) { continue; } - if ( "ex4p.v" == entry.path().filename().string()) + if ("ex4p.v" == entry.path().filename().string()) { continue; } - if ( "apex1.v" == entry.path().filename().string()) + if ("apex1.v" == entry.path().filename().string()) { continue; } @@ -144,7 +143,7 @@ int main() // NOLINT } const auto planarized_b = fiction::node_duplication_planarization(_b); - const auto is_planar = fiction::check_planarity(planarized_b); + const auto is_planar = fiction::check_planarity(planarized_b); if (planarized_b.size() > 20000) { continue; @@ -169,13 +168,13 @@ int main() // NOLINT fiction::gate_level_drvs(layout, ps_d, &st_d); const auto miter = mockturtle::miter(planarized_b, layout); - bool eq; + bool eq; if (miter) { mockturtle::equivalence_checking_stats st; const auto ce = mockturtle::equivalence_checking(*miter, {}, &st); - eq = ce.value(); + eq = ce.value(); } wiring_reduction_exp(entry.path().filename().string(), benchmark_network.num_pis(), planarized_b.num_virtual_pis(), benchmark_network.num_pos(), benchmark_network.num_gates(), @@ -242,10 +241,9 @@ int main() // NOLINT { cont = true; std::cout << "Pi is Po\n"; - } }); - if(cont) + if (cont) { continue; } @@ -268,8 +266,9 @@ int main() // NOLINT if (planarized_b.size() > 20000) { - wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), benchmark_network.num_pos(), - benchmark_network.num_gates(), _b.num_gates(), planarized_b.num_gates(), is_planar, 0, 0); + wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), + benchmark_network.num_pos(), benchmark_network.num_gates(), _b.num_gates(), + planarized_b.num_gates(), is_planar, 0, 0); wiring_reduction_exp.save(); wiring_reduction_exp.table(); continue; @@ -285,14 +284,15 @@ int main() // NOLINT fiction::restore_names(benchmark_network, name); - using gate_lyt = - fiction::gate_level_layout>>>; + using gate_lyt = fiction::gate_level_layout< + fiction::clocked_layout>>>; fiction::orthogonal_physical_design_stats stats{}; - using gate_layout = fiction::gate_level_layout>>>; - auto start = std::chrono::high_resolution_clock::now(); + using gate_layout = fiction::gate_level_layout< + fiction::clocked_layout>>>; + auto start = std::chrono::high_resolution_clock::now(); auto layout = fiction::orthogonal(planarized_b, {}, &stats); - auto stop = std::chrono::high_resolution_clock::now(); + auto stop = std::chrono::high_resolution_clock::now(); std::chrono::duration elapsed = stop - start; @@ -320,13 +320,13 @@ int main() // NOLINT "NO";*/ const auto miter = mockturtle::miter(planarized_b, layout); - bool eq; + bool eq; if (miter) { mockturtle::equivalence_checking_stats st; const auto ce = mockturtle::equivalence_checking(*miter, {}, &st); - eq = ce.value(); + eq = ce.value(); } // fiction::debug::write_dot_layout(layout); @@ -334,8 +334,9 @@ int main() // NOLINT fiction::debug::write_dot_network(planarized_b, "ntk_p");*/ // log results - wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), benchmark_network.num_pos(), - benchmark_network.num_gates(), _b.num_gates(), planarized_b.num_gates(), is_planar, cec_m.value(), eq); + wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), + benchmark_network.num_pos(), benchmark_network.num_gates(), _b.num_gates(), + planarized_b.num_gates(), is_planar, cec_m.value(), eq); wiring_reduction_exp.save(); wiring_reduction_exp.table(); From 0c7e3baefb661b55bdd1db6a47f4febb12c514bb Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 23 Sep 2024 11:03:35 +0200 Subject: [PATCH 70/84] :art: refactored po collection in node_duplication_planarization.hpp --- .../node_duplication_planarization.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 0a0ddeaf2..ff547e5e8 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -360,14 +360,14 @@ class node_duplication_planarization_impl // ToDO: implement border_pis (if there is a choice ush pis to the borders (first or last rank)) const bool border_pis = true; - std::unordered_map po_counts; - ntk.foreach_po([&po_counts](auto po) { po_counts[po]++; }); - std::vector pos{}; + std::vector> pos{}; pos.reserve(ntk.num_pos()); - for (const auto& kv : po_counts) - { - pos.push_back(kv.first); - } + ntk.foreach_po([&pos](auto po) + { + if(std::find(pos.begin(), pos.end(), po) == pos.end()) { + pos.push_back(po); + } + }); // Randomize the PO order if (ps.random_output_order) From ad00cf4be9cd86f2b16a17cb6626c7882f96ffcb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 09:04:06 +0000 Subject: [PATCH 71/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../node_duplication_planarization.hpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index ff547e5e8..bd3111fb3 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -362,12 +362,14 @@ class node_duplication_planarization_impl std::vector> pos{}; pos.reserve(ntk.num_pos()); - ntk.foreach_po([&pos](auto po) - { - if(std::find(pos.begin(), pos.end(), po) == pos.end()) { - pos.push_back(po); - } - }); + ntk.foreach_po( + [&pos](auto po) + { + if (std::find(pos.begin(), pos.end(), po) == pos.end()) + { + pos.push_back(po); + } + }); // Randomize the PO order if (ps.random_output_order) From 28513585aab70ecafafe405ae5f33b1be409f3f0 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 23 Sep 2024 11:36:55 +0200 Subject: [PATCH 72/84] :art: fixed tests in check_planarity.cpp --- test/algorithms/properties/check_planarity.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/algorithms/properties/check_planarity.cpp b/test/algorithms/properties/check_planarity.cpp index a0ca81141..9bd9aa551 100644 --- a/test/algorithms/properties/check_planarity.cpp +++ b/test/algorithms/properties/check_planarity.cpp @@ -39,11 +39,11 @@ TEST_CASE("Check planarity aig", "[check-planarity]") extended_rank_view tec_r(aig); - const std::vector nodes_rank0{1, 2, 3}; + const std::vector nodes_rank0{1, 2, 3, 6}; const std::vector nodes_rank1{4, 5}; tec_r.modify_rank(0, nodes_rank0); - tec_r.modify_rank(0, nodes_rank0); + tec_r.modify_rank(1, nodes_rank1); const bool planar = check_planarity(tec_r); @@ -74,7 +74,7 @@ TEST_CASE("Check planarity technology network", "[check-planarity]") const std::vector nodes_rank1{5, 6}; tec_r.modify_rank(0, nodes_rank0); - tec_r.modify_rank(0, nodes_rank0); + tec_r.modify_rank(1, nodes_rank1); const bool planar = check_planarity(tec_r); @@ -105,7 +105,7 @@ TEST_CASE("Check non-planarity technology network", "[check-planarity]") const std::vector nodes_rank1{5, 6}; tec_r.modify_rank(0, nodes_rank0); - tec_r.modify_rank(0, nodes_rank0); + tec_r.modify_rank(1, nodes_rank1); const bool planar = check_planarity(tec_r); From 9f4f59ce3525b0e672591f1882da8170097b1d61 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 23 Sep 2024 13:00:23 +0200 Subject: [PATCH 73/84] :art: placed virtual_pi creation for duplicated nodes into node_duplication_planarization.hpp. The function has no use in any other context (so far). --- .../node_duplication_planarization.hpp | 199 ++++++++++++++- .../fiction/networks/virtual_pi_network.hpp | 233 ------------------ 2 files changed, 198 insertions(+), 234 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index bd3111fb3..220bb406b 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -89,6 +89,203 @@ struct node_pair {} }; +/** + * Variant of the mockturtle::initialize_copy_network. This function helps with creating new networks from old + * networks. In the mockturtle/original version `old2new` is used to map nodes from the old network to nodes in the new + * network in a one to one relation. This variant allows old nodes to map to multiple nodes in order to represent + * relations to dulicated nodes. + + * A map (old2new) is created where old nodes from source network are mapped to new nodes in destination network. + * A destination network is created as a virtual_pi_network. + * + * @tparam NtkSrc Type of the source network. + * @param src The source network. + * + * @return A pair of the destination network and a node map from the source to the destination network. + */ +template +std::pair, + mockturtle::node_map>>, NtkSrc>> +initialize_copy_network_virtual(NtkSrc const& src) +{ + static_assert(mockturtle::is_network_type_v>, "NtkDest is not a network type"); + static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); + + static_assert(mockturtle::has_get_constant_v>, + "NtkDest does not implement the get_constant method"); + static_assert(mockturtle::has_create_pi_v>, + "NtkDest does not implement the create_pi method"); + static_assert(mockturtle::has_is_pi_v>, "NtkDest does not implement the is_pi method"); + static_assert(mockturtle::has_create_not_v>, + "NtkDest does not implement the create_not method"); + static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method"); + static_assert(mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi method"); + static_assert(mockturtle::has_foreach_po_v, "NtkSrc does not implement the foreach_po method"); + static_assert(mockturtle::has_is_complemented_v, "NtkSrc does not implement the is_complemented method"); + static_assert(mockturtle::has_foreach_fanin_v, "NtkSrc does not implement the foreach_fanin method"); + + mockturtle::node_map>>, NtkSrc> old2new(src); + virtual_pi_network dest; + + old2new[src.get_constant(false)].push_back(dest.get_constant(false)); + if (src.get_node(src.get_constant(true)) != src.get_node(src.get_constant(false))) + { + old2new[src.get_constant(true)].push_back(dest.get_constant(true)); + } + src.foreach_pi([&](auto const& n) { old2new[n].push_back(dest.create_pi()); }); + return {dest, old2new}; +} + +/** + * Constructs a planar `virtual_pi_network` based on the `ntk_lvls` array, which holds the ranks of the duplicated nodes + * for each level in the new network. This function creates new nodes for the duplicated ones and restores their fanin + * relations using the `gather_fanin_signals` function. + * + * For duplicated PIs (Primary Inputs), virtual PIs are created, and the original PI is stored in a map. + * + * The auxiliary function `gather_fanin_signals` collects fanin data for a node and matches it in the + * `virtual_pi_network`. + * + * Example: For a level (2, 3, 2, 4, 2), new nodes are created for duplications (e.g., 2) and stored in the `old2new_v` + * node_map. This map is used by `gather_fanin_signals` to establish the correct fanin relations. + * + * @tparam Ntk Network type. + * @param ntk Source network to be utilized for the creation of the virtual_pi_network. + * @param ntk_lvls Levels of nodes in the source network. + * @param ntk_lvls_new Levels of newly created nodes in the virtual_pi_network. + */ +template +virtual_pi_network +create_virtual_pi_ntk_from_duplicated_nodes(Ntk& ntk, std::vector>>& ntk_lvls, + std::vector>>& ntk_lvls_new) +{ + std::unordered_map, bool> node_status; + ntk_lvls_new.resize(ntk_lvls.size()); + + auto init_v = initialize_copy_network_virtual(ntk); + auto& ntk_dest_v = init_v.first; + auto& old2new_v = init_v.second; + + /** + * The function gather_fanin_signals collects the fanin data for node n from the original ntk. + * For each node n there are the possible fanin candidates old2new_v[fn], which are the original node and all + * the nodes which are duplicates of this node. + * + * lvl[edge_it] gives the current iterator at where the edge can be connected. To get the right signal, + * all nodes at old2new[n] need to be viewed. Match lvl[edge_it] against all entries in old2new[n], + * then try lvl[edge_it+1] then try lvl[edge_it+2]. + * + * @param n Variable to process. + * @param lvl Level to process. + * @param edge_it Iterator for edge. + * @return Vector of fanins in the virtual_pi_network connected to the processed node. + */ + const auto gather_fanin_signals = [&](const auto& n, const auto& lvl, std::size_t& edge_it) + { + std::vector children{}; + const auto edge_it_int = edge_it; + int first_fi_edge_it = -1; + + ntk.foreach_fanin(n, + [&](const auto& f) + { + const auto fn = ntk.get_node(f); + auto tgt_signal_v = old2new_v[fn]; + + assert(edge_it_int < lvl.size()); + + bool break_loop = false; + for (const auto& possible_node : tgt_signal_v) + { + const auto it = ntk.fanin_size(n) + 1; + if (ntk.fanin_size(n) == children.size()) + { + break; + } + for (std::size_t i = 0; i < it; i++) + { + if (edge_it_int + i < lvl.size() && lvl[edge_it_int + i] == possible_node && + ntk_dest_v.fanout_size(possible_node) < 2) + { + if (first_fi_edge_it != -1) + { + if (!ntk.is_maj(n)) + { + assert(edge_it_int + i == first_fi_edge_it + 1 || + edge_it_int + i == first_fi_edge_it - 1); + } + } + children.emplace_back(possible_node); + first_fi_edge_it = static_cast(edge_it_int + i); + if (edge_it_int + i > edge_it) + { + edge_it = edge_it_int + i; + } + break_loop = true; + break; + } + } + if (break_loop) + { + break; + } + } + }); + return children; + }; + + std::size_t edge_it = 0; + for (std::size_t i = ntk_lvls.size(); i-- > 0;) + { + edge_it = 0; + const auto& lvl = ntk_lvls[i]; + auto& lvl_new = ntk_lvls_new[i]; + for (const auto& nd : lvl) + { + if (ntk.is_pi(nd)) + { + if (node_status[nd]) + { + const auto& new_node = ntk_dest_v.create_virtual_pi(nd); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + } + else + { + lvl_new.push_back(nd); + node_status[nd] = true; + } + } + else + { + const auto children = gather_fanin_signals(nd, ntk_lvls_new[i + 1], edge_it); + assert(!children.empty() && "The node has to have children"); + + const auto& new_node = ntk_dest_v.create_node(children, ntk.node_function(nd)); + lvl_new.push_back(new_node); + old2new_v[nd].push_back(new_node); + } + } + } + + ntk.foreach_po( + [&ntk, &ntk_dest_v, &old2new_v](const auto& po) + { + const auto tgt_signal_v = old2new_v[ntk.get_node(po)]; + // POs do not get duplicated since the algorithm starts at the POs and duplicates other nodes according + // to their order + assert(tgt_signal_v.size() == 1 && "Multiple nodes mapped to PO"); + const auto tgt_signal = tgt_signal_v[0]; + + const auto tgt_po = ntk.is_complemented(po) ? ntk_dest_v.create_not(tgt_signal) : tgt_signal; + + ntk_dest_v.create_po(tgt_po); + }); + + return ntk_dest_v; +} + /** * Calculates pairs of nodes from a given vector of nodes. * @@ -430,7 +627,7 @@ class node_duplication_planarization_impl } // create virtual pi network - return virtual_pi_network(ntk, ntk_lvls, ntk_lvls_new); + return create_virtual_pi_ntk_from_duplicated_nodes(ntk, ntk_lvls, ntk_lvls_new); } private: diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 1bbfcd78f..66f508c27 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -98,239 +98,6 @@ class virtual_pi_network : public Ntk std::make_shared>(*v_storage)); } - /** - * Variant of the mockturtle::initialize_copy_network. This function helps with creating new networks from old - * networks. In the original version `old2new` is used to map nodes from the old network to nodes in the new network - * in a one to one relation.This variant allows old nodes not only to a single node, but to multiple nodes. - * - * NtkDest and NtkSrc must be network types (satisfy is_network_type_v). - * NtkDest and NtkSrc must implement the methods get_constant, get_node, create_pi and foreach_pi (satisfy - * has_get_constant_v, has_get_node_v, has_create_pi_v and has_foreach_pi_v). - * - * A map (old2new) is created where old nodes from source network are mapped to new nodes in destination network. - * A destination network is created with the same structure as the source network. - * - * @tparam NtkDest Type of the destination network. - * @tparam NtkSrc Type of the source network. - * @param src The source network. - * - * @return A pair of the destination network and a node map from the source to the destination network. - */ - template - std::pair>, NtkSrc>> - initialize_copy_network_virtual(NtkSrc const& src) - { - static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); - static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); - - static_assert(mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method"); - static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method"); - static_assert(mockturtle::has_is_pi_v, "NtkDest does not implement the is_pi method"); - static_assert(mockturtle::has_create_not_v, "NtkDest does not implement the create_not method"); - static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method"); - static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method"); - static_assert(mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi method"); - static_assert(mockturtle::has_foreach_po_v, "NtkSrc does not implement the foreach_po method"); - static_assert(mockturtle::has_is_complemented_v, - "NtkSrc does not implement the is_complemented method"); - static_assert(mockturtle::has_foreach_fanin_v, "NtkSrc does not implement the foreach_fanin method"); - - mockturtle::node_map>, NtkSrc> old2new(src); - NtkDest dest; - - old2new[src.get_constant(false)].push_back(dest.get_constant(false)); - if (src.get_node(src.get_constant(true)) != src.get_node(src.get_constant(false))) - { - old2new[src.get_constant(true)].push_back(dest.get_constant(true)); - } - src.foreach_pi([&](auto const& n) { old2new[n].push_back(dest.create_pi()); }); - return {dest, old2new}; - } - - /** - * Special constructor to construct a planar virtual_pi_network from any other network type with given ranks. - * - * @tparam Ntk Network type. - * @param ntk Source network to be utilized for the creation of the virtual_pi_network. - * @param ntk_lvls Levels of nodes in the source network. - * @param ntk_lvls_new Levels of newly created nodes in the virtual_pi_network. - * - * This constructor creates a virtual_pi_network by using the nodes from the original network stored in ntk_lvls. - * It handles duplicated nodes and stores them with their newly created nodes in ntk_lvls_new. - * If the duplicated nodes are PIs (Primary Inputs), virtual PIs are created and the original PI is stored in a map. - * To manage the connections between nodes, this also uses an auxiliary function gather_fanin_signals, that - * collects the fanin data for a node and matches them in the virtual_pi_network. - */ - explicit virtual_pi_network(Ntk& ntk, std::vector>>& ntk_lvls, - std::vector>>& ntk_lvls_new) - { - std::unordered_map, bool> node_status; - ntk_lvls_new.resize(ntk_lvls.size()); - - auto init_v = initialize_copy_network_virtual(ntk); - auto& ntk_dest_v = init_v.first; - auto& old2new_v = init_v.second; - - /** - * The function gather_fanin_signals collects the fanin data for node n from the original ntk. - * For each node n there are the possible fanin candidates old2new_v[fn], which are the original node and all - * the nodes which are duplicates of this node. - * - * lvl[edge_it] gives the current iterator at where the edge can be connected. To get the right signal, - * all nodes at old2new[n] need to be viewed. Match lvl[edge_it] against all entries in old2new[n], - * then try lvl[edge_it+1] then try lvl[edge_it+2]. - * - * @param n Variable to process. - * @param lvl Level to process. - * @param edge_it Iterator for edge. - * @return Vector of fanins in the virtual_pi_network connected to the processed node. - */ - const auto gather_fanin_signals = [&](const auto& n, const auto& lvl, std::size_t& edge_it) - { - std::vector children{}; - const auto edge_it_int = edge_it; - int first_fi_edge_it = -1; - - ntk.foreach_fanin(n, - [&](const auto& f) - { - const auto fn = ntk.get_node(f); - auto tgt_signal_v = old2new_v[fn]; - - assert(edge_it_int < lvl.size()); - - bool break_loop = false; - for (const auto& possible_node : tgt_signal_v) - { - const auto it = ntk.fanin_size(n) + 1; - if (ntk.fanin_size(n) == children.size()) - { - break; - } - for (std::size_t i = 0; i < it; i++) - { - if (edge_it_int + i < lvl.size() && lvl[edge_it_int + i] == possible_node && - ntk_dest_v.fanout_size(possible_node) < 2) - { - if (first_fi_edge_it != -1) - { - if (!ntk.is_maj(n)) - { - assert(edge_it_int + i == first_fi_edge_it + 1 || - edge_it_int + i == first_fi_edge_it - 1); - } - } - children.emplace_back(possible_node); - first_fi_edge_it = static_cast(edge_it_int + i); - if (edge_it_int + i > edge_it) - { - edge_it = edge_it_int + i; - } - break_loop = true; - break; - } - } - if (break_loop) - { - break; - } - } - }); - return children; - }; - - std::size_t edge_it = 0; - for (std::size_t i = ntk_lvls.size(); i-- > 0;) - { - edge_it = 0; - const auto& lvl = ntk_lvls[i]; - auto& lvl_new = ntk_lvls_new[i]; - for (const auto& nd : lvl) - { - if (ntk.is_pi(nd)) - { - if (node_status[nd]) - { - const auto& new_node = ntk_dest_v.create_virtual_pi(nd); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - } - else - { - lvl_new.push_back(nd); - node_status[nd] = true; - } - } - else - { - const auto children = gather_fanin_signals(nd, ntk_lvls_new[i + 1], edge_it); - // std::cout << "Node: " << nd << std::endl; - assert(!children.empty() && "The node has to have children"); - - if (ntk.is_and(nd)) - { - const auto& new_node = ntk_dest_v.create_and(children[0], children[1]); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - continue; - } - if (ntk.is_or(nd)) - { - const auto& new_node = ntk_dest_v.create_or(children[0], children[1]); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - continue; - } - if (ntk.is_xor(nd)) - { - const auto& new_node = ntk_dest_v.create_xor(children[0], children[1]); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - continue; - } - if (ntk.is_maj(nd)) - { - const auto& new_node = ntk_dest_v.create_maj(children[0], children[1], children[2]); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - continue; - } - if (ntk.is_buf(nd)) - { - const auto& new_node = ntk_dest_v.create_buf(children[0]); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - continue; - } - if (ntk.is_inv(nd)) - { - const auto& new_node = ntk_dest_v.create_not(children[0]); - lvl_new.push_back(new_node); - old2new_v[nd].push_back(new_node); - continue; - } - assert(false); - } - } - } - - ntk.foreach_po( - [&ntk, &ntk_dest_v, &old2new_v](const auto& po) - { - const auto tgt_signal_v = old2new_v[ntk.get_node(po)]; - // POs do not get duplicated since the algorithm starts at the POs and duplicates other nodes according - // to their order - assert(tgt_signal_v.size() == 1 && "Multiple nodes mapped to PO"); - const auto tgt_signal = tgt_signal_v[0]; - - const auto tgt_po = ntk.is_complemented(po) ? ntk_dest_v.create_not(tgt_signal) : tgt_signal; - - ntk_dest_v.create_po(tgt_po); - }); - - *this = ntk_dest_v; - } - /** * Calculate the real size of the virtual_pi_network. * From 832136231388e5092d10ff68d64930d6f4b4ec44 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 23 Sep 2024 11:01:12 +0000 Subject: [PATCH 74/84] :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions --- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 224 +++++++++++------- 1 file changed, 135 insertions(+), 89 deletions(-) diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index 23eeb8d21..a73e9980d 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -4125,23 +4125,6 @@ Parameter ``to_delete``: Returns: A 2D vector representing the calculated offset matrix.)doc"; -static const char *__doc_fiction_detail_calculate_pairs = -R"doc(Calculates pairs of nodes from a given vector of nodes. - -This function takes a vector of nodes and returns a vector of node -pairs. Each node pair consists of two nodes from the input vector and -an optional vector of middle nodes. The delay of each node pair is -initialized to infinity. - -Template parameter ``Ntk``: - The network type. - -Parameter ``nodes``: - The vector of nodes. - -Returns: - The vector of node pairs.)doc"; - static const char *__doc_fiction_detail_color_routing_impl = R"doc()doc"; static const char *__doc_fiction_detail_color_routing_impl_color_routing_impl = R"doc()doc"; @@ -6681,78 +6664,6 @@ static const char *__doc_fiction_detail_new_gate_location_NONE = R"doc(Do not ch static const char *__doc_fiction_detail_new_gate_location_SRC = R"doc(Check if the source tile is empty.)doc"; -static const char *__doc_fiction_detail_node_duplication_planarization_impl = R"doc()doc"; - -static const char *__doc_fiction_detail_node_duplication_planarization_impl_check_final_level = -R"doc(Checks if the given vector of nodes contains any non-primary inputs. - -This function iterates through each node in the vector and checks if -it is a primary input. If a non-primary input is found, the -`f_final_level` parameter is set to false and the loop is exited. - -Parameter ``v_next_level``: - The vector of nodes to be checked.)doc"; - -static const char *__doc_fiction_detail_node_duplication_planarization_impl_compute_node_order_next_level = -R"doc(Computes the order of nodes in the next level based on delay - -This function computes the order of nodes in the next level based on -their delay in the H-graph of the level. It selects the path with the -least delay from the current level pairs and follows it via fanin -relations. The nodes are inserted into the next level vector in the -order they are encountered. - -Parameter ``next_level``: - The vector to store the nodes in the next level.)doc"; - -static const char *__doc_fiction_detail_node_duplication_planarization_impl_compute_slice_delays = -R"doc(Computes the delay in a given slice (each possible order of -node_pairs) of an H-graph. - -This function iterates over the fanins of the given node and computes -the delay for all possible orders of these nodes that form a -node_pair. The delay computation depends on the node's connections and -position within the graph. If there is a connection between two -node_pairs, the delay is incremented by 1. If not, the delay is -incremented by 2. Default delay for the first node is 1. If a -node_pair doesn't have a connection and its delay (when increased by -two) is less than the existing delay, then this node_pair's delay is -updated. - -The processed node_pairs are pushed back to the 'lvl_pairs' data -member for subsequent delay calculations. - -Parameter ``nd``: - Node in the H-graph. - -Parameter ``border_pis``: - A boolean indicating whether the input PIs (Primary Inputs) should - be propagated to the next level.)doc"; - -static const char *__doc_fiction_detail_node_duplication_planarization_impl_insert_if_not_first = -R"doc(Inserts a node into a vector if it is unique. - -This function inserts a node into a vector only if the vector is empty -or the node is not equal to the first element of the vector. If the -vector is not empty and the node is equal to the first element, it -does nothing. - -Parameter ``node``: - The node to be inserted. - -Parameter ``vec``: - The vector to insert the node into.)doc"; - -static const char *__doc_fiction_detail_node_duplication_planarization_impl_lvl_pairs = R"doc()doc"; - -static const char *__doc_fiction_detail_node_duplication_planarization_impl_node_duplication_planarization_impl = R"doc()doc"; - -static const char *__doc_fiction_detail_node_duplication_planarization_impl_ntk = R"doc()doc"; - -static const char *__doc_fiction_detail_node_duplication_planarization_impl_ps = R"doc()doc"; - -static const char *__doc_fiction_detail_node_duplication_planarization_impl_run = R"doc()doc"; - static const char *__doc_fiction_detail_node_pair = R"doc(A structure representing a pair of nodes in an H-graph. @@ -17630,6 +17541,141 @@ static const char *__doc_fiction_virtual_pi_network = R"doc()doc"; static const char *__doc_fiction_virtual_pi_network_clone = R"doc(Clones the virtual_pi_network object.)doc"; +static const char *__doc_fiction_virtual_pi_network_create_virtual_pi = +R"doc(Create a virtual PI, which is a mapping to a real PI. + +This function creates a virtual PI mapping to a real PI in the +network. It adds a PI to the underlying network, but marks it as +virtual and stores a mapping to a real PI. + +Parameter ``real_pi``: + The node representing the real PI in the network. + +Returns: + The signal of the newly created virtual PI.)doc"; + +static const char *__doc_fiction_virtual_pi_network_foreach_real_ci = +R"doc(Iterates over the virtual CIs of the circuit and applies a given +function. + +Template parameter ``Fn``: + The type of the function to be applied. + +Parameter ``fn``: + The function to be applied.)doc"; + +static const char *__doc_fiction_virtual_pi_network_foreach_real_pi = +R"doc(Iterates over the real PIs of the circuit and applies a given +function. + +Template parameter ``Fn``: + The type of the function. + +Parameter ``fn``: + The function to be applied to each primary input.)doc"; + +static const char *__doc_fiction_virtual_pi_network_foreach_virtual_ci = +R"doc(Iterates over the virtual CIs of the circuit and applies a given +function. + +Template parameter ``Fn``: + The type of the function. + +Parameter ``fn``: + The function to be applied to each primary input.)doc"; + +static const char *__doc_fiction_virtual_pi_network_foreach_virtual_pi = +R"doc(Iterates over the virtual PIs of the circuit and applies a given +function. + +Template parameter ``Fn``: + The type of the function. + +Parameter ``fn``: + The function to be applied to each primary input.)doc"; + +static const char *__doc_fiction_virtual_pi_network_get_real_pi = +R"doc(Get the real PI associated with a virtual PI node. + +Parameter ``v_pi``: + The virtual pi node to retrieve the real pi for. + +Returns: + The real pi associated with the virtual pi node.)doc"; + +static const char *__doc_fiction_virtual_pi_network_is_real_ci = +R"doc(Check if a given node is a real CI in the virtual_pi_network. + +Parameter ``n``: + The node to check. + +Returns: + True if the node is a real CI, false otherwise.)doc"; + +static const char *__doc_fiction_virtual_pi_network_is_real_pi = +R"doc(Check if a given node is a real PI. Real PIs are created with +create_pi(). + +Parameter ``n``: + The node to check. + +Returns: + True if the node is a real PI, false otherwise.)doc"; + +static const char *__doc_fiction_virtual_pi_network_is_virtual_ci = +R"doc(Check if a given node is a virtual CI in the virtual_pi_network. + +Parameter ``n``: + The node to check. + +Returns: + True if the node is a virtual CI, false otherwise.)doc"; + +static const char *__doc_fiction_virtual_pi_network_is_virtual_pi = +R"doc(Check if a given node is a virtual PI. Virtual PIs are created with +create_virtual_pi(). + +Parameter ``n``: + The node to check. + +Returns: + True if the node is a virtual PI, false otherwise.)doc"; + +static const char *__doc_fiction_virtual_pi_network_num_real_cis = +R"doc(Get the number of real CIs in the virtual_pi_network. + +Returns: + The number of real CIs as a uint32_t.)doc"; + +static const char *__doc_fiction_virtual_pi_network_num_real_pis = +R"doc(Get the number of real PIs in the virtual_pi_network. + +Returns: + The number of real PIs as a uint32_t.)doc"; + +static const char *__doc_fiction_virtual_pi_network_num_virtual_cis = +R"doc(Get the number of virtual CIs in the virtual_pi_network. + +Returns: + The number of virtual CIs as a uint32_t.)doc"; + +static const char *__doc_fiction_virtual_pi_network_num_virtual_pis = +R"doc(Get the number of virtual PIs in the virtual_pi_network. + +Returns: + The number of virtual PIs as a uint32_t.)doc"; + +static const char *__doc_fiction_virtual_pi_network_real_size = +R"doc(Calculate the real size of the virtual_pi_network. + +The real size of the network is considered the size without virtual +PIs. + +Returns: + The real size of the virtual_pi_network as a uint32_t.)doc"; + +static const char *__doc_fiction_virtual_pi_network_v_storage = R"doc(Shared pointer if the virtual PI storage.)doc"; + static const char *__doc_fiction_virtual_pi_network_virtual_pi_network = R"doc(Default constructor for the `virtual_pi_network` class. Initializes `_storage` as a shared pointer.)doc"; From accd04fc47c26ab2476280b22eb1cbf3618c1640 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 23 Sep 2024 18:12:12 +0200 Subject: [PATCH 75/84] :art: cleaned up some code --- .../node_duplication_planarization.hpp | 112 ++++++------- .../fiction/networks/virtual_pi_network.hpp | 153 ++++++++++-------- 2 files changed, 146 insertions(+), 119 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 220bb406b..b65f09390 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -38,7 +38,19 @@ struct node_duplication_planarization_params * The output order determines the starting layer for this algorithm. If this option is turned off, the output order * remains the same as in the provided network. If it is turned on, the outputs are ordered randomly. */ - bool random_output_order = false; + enum class output_order : uint8_t + { + /** + * Keep the PO order from the input network. + */ + KEEP_PO_ORDER, + /** + * Randomize the PO order. + */ + RANDOM_PO_ORDER + }; + // bool random_output_order = false; + output_order po_order = output_order::KEEP_PO_ORDER; }; namespace detail @@ -184,8 +196,12 @@ create_virtual_pi_ntk_from_duplicated_nodes(Ntk& ntk, std::vector children{}; - const auto edge_it_int = edge_it; - int first_fi_edge_it = -1; + const auto edge_it_int = edge_it; + +#ifndef NDEBUG + // Useful Debug parameter to check that fanins need to be adjacent. + int64_t first_fi_edge_it = -1; +#endif ntk.foreach_fanin(n, [&](const auto& f) @@ -193,7 +209,7 @@ create_virtual_pi_ntk_from_duplicated_nodes(Ntk& ntk, std::vector(edge_it_int + i); +#endif + children.emplace_back(possible_node); if (edge_it_int + i > edge_it) { edge_it = edge_it_int + i; @@ -365,10 +383,10 @@ class node_duplication_planarization_impl * @param border_pis A boolean indicating whether the input PIs (Primary Inputs) should be propagated to the next * level. */ - void compute_slice_delays(const mockturtle::node& nd, const bool border_pis) + void compute_slice_delays(const mockturtle::node& nd) { // Pis need to be propagated into the next level, since they have to be connected without crossings - if (ntk.is_pi(nd) && border_pis) + if (ntk.is_pi(nd)) { fis.push_back(nd); } @@ -449,8 +467,10 @@ class node_duplication_planarization_impl /** * Inserts a node into a vector if it is unique. * - * This function inserts a node into a vector only if the vector is empty or the node is not equal to the first + * `This function inserts a node into a vector only if the vector is empty or the node is not equal to the first * element of the vector. If the vector is not empty and the node is equal to the first element, it does nothing. + * An exception occurs if the node was skipped on the previous insertion attempt due to `vec.front() != node`; in + * that case, the node will be inserted this time. * * @param node The node to be inserted. * @param vec The vector to insert the node into. @@ -478,18 +498,17 @@ class node_duplication_planarization_impl } /** - * Computes the order of nodes in the next level based on delay + * Computes the order of nodes in the next level based on the shortest path (delay) in the H-graph of the level. * * This function computes the order of nodes in the next level based on their delay in the H-graph of the level. It * selects the path with the least delay from the current level pairs and follows it via fanin relations. The nodes * are inserted into the next level vector in the order they are encountered. - * - * @param next_level The vector to store the nodes in the next level. */ - void compute_node_order_next_level(std::vector>& next_level) + std::vector> compute_node_order() { - int saturated_fanout_flag = 0; - const auto& combinations = lvl_pairs.back(); + std::vector> next_level; + int saturated_fanout_flag = 0; + const auto& combinations = lvl_pairs.back(); // select the path with the least delay and follow it via fanin relations const auto minimum_it = std::min_element(combinations.cbegin(), combinations.cend(), @@ -529,6 +548,7 @@ class node_duplication_planarization_impl fanin_combination = fanin_combination->fanin_pair; } } + return next_level; } /** @@ -551,17 +571,15 @@ class node_duplication_planarization_impl return true; } - [[nodiscard]] std::optional> + [[nodiscard]] extended_rank_view> run(std::vector>>& ntk_lvls_new) { - // ToDO: implement border_pis (if there is a choice ush pis to the borders (first or last rank)) - const bool border_pis = true; - std::vector> pos{}; pos.reserve(ntk.num_pos()); ntk.foreach_po( - [&pos](auto po) + [this, &pos](const auto n) { + const auto po = ntk.get_node(n); if (std::find(pos.begin(), pos.end(), po) == pos.end()) { pos.push_back(po); @@ -569,7 +587,7 @@ class node_duplication_planarization_impl }); // Randomize the PO order - if (ps.random_output_order) + if (ps.po_order == node_duplication_planarization_params::output_order::RANDOM_PO_ORDER) { // Generate a random engine static std::mt19937_64 generator(std::random_device{}()); @@ -585,20 +603,17 @@ class node_duplication_planarization_impl { // Recalculate the levels to start from the pos fis.clear(); - compute_slice_delays(po, border_pis); + compute_slice_delays(po); v_level.push_back(po); } ntk_lvls.push_back(v_level); v_level.clear(); - // Try to push PIs to the beginning or end of the vector, since they have to be propagated with buffers - // until the last levels this should only happen if border_pis == true - compute_node_order_next_level(v_level); + v_level = compute_node_order(); bool f_final_level = check_final_level(v_level); - int lvl_it = 0; // Process all other levels while (!v_level.empty() && !f_final_level) { @@ -610,15 +625,14 @@ class node_duplication_planarization_impl { fis.clear(); // There is one slice in the H-Graph for each node in the level - compute_slice_delays(cur_node, border_pis); + compute_slice_delays(cur_node); } // Clear before starting computations on the next level v_level.clear(); // Compute the next level - compute_node_order_next_level(v_level); + v_level = compute_node_order(); // Check if we are at the final level f_final_level = check_final_level(v_level); - ++lvl_it; } // Push the final level (PIs) if (f_final_level) @@ -627,7 +641,11 @@ class node_duplication_planarization_impl } // create virtual pi network - return create_virtual_pi_ntk_from_duplicated_nodes(ntk, ntk_lvls, ntk_lvls_new); + const auto virtual_ntk = create_virtual_pi_ntk_from_duplicated_nodes(ntk, ntk_lvls, ntk_lvls_new); + // the ntk_levels were created in reverse order + std::reverse(ntk_lvls_new.begin(), ntk_lvls_new.end()); + // assign the ranks in the virtual network based on ntk_lvls_new + return extended_rank_view(virtual_ntk, ntk_lvls_new); } private: @@ -661,9 +679,9 @@ class node_duplication_planarization_impl * The planarization achieved by this function solves the Node Duplication Crossing Minimization (NDCE) problem by * finding the shortest x-y path in the H-graph for every level in the network. An H-graph describes edge relations * between two levels in a network, with one level assumed as fixed, starting at the Primary Outputs (POs). By finding - * the shortest path from the source (x) to the sink (y) in this H-graph, an optimal solution for the NDCE problem is - * found. The function constructs an H-graph that captures edge relations between two levels within the graph and - * computes the shortest x-y paths on the H-graph, traversing from the POs towards the Primary Inputs (PIs). + * the shortest path from the source (x) to the sink (y) in this H-graph, an optimal solution for the NDCE problem for + * each level is found. The function constructs an H-graph that captures edge relations between two levels within the + * graph and computes the shortest x-y paths on the H-graph, traversing from the POs towards the Primary Inputs (PIs). * * @return A view of the planarized virtual_pi_network created in the format of extended_rank_view. * @@ -671,42 +689,24 @@ class node_duplication_planarization_impl * @tparam NtkSrc Source network type. * @param ntk_src Source network to be utilized for the planarization. * @param ps Node duplication parameters used in the computation. - * - * @throws std::runtime_error if input network not balanced, if no node combinations are found or if - * the created network is non-planar. - * */ template -[[nodiscard]] extended_rank_view> +[[nodiscard]] extended_rank_view> node_duplication_planarization(const NtkSrc& ntk_src, const node_duplication_planarization_params& ps = {}) { static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); - - // check the network to be a technology network (is there a better check/trait?) - static_assert(mockturtle::has_create_le_v, "T must be of type const ExpectedType"); + // ToDo: This might also be implemented, so that it works for all Ntk types + static_assert(mockturtle::has_create_node_v, "NtkSrc does not implement the create_node function"); assert(is_balanced(ntk_src) && "Networks have to be balanced for this duplication"); detail::node_duplication_planarization_impl p{ntk_src, ps}; - std::vector>> ntk_lvls_new; - - auto result_ntk = p.run(ntk_lvls_new); + std::vector>> ntk_lvls_new; - if (!result_ntk) - { - std::cout << "The network is to wide to be processed by the planarization algorithm" << std::endl; - return extended_rank_view>(virtual_pi_network(ntk_src)); - } + auto result = p.run(ntk_lvls_new); - std::reverse(ntk_lvls_new.begin(), ntk_lvls_new.end()); - - auto result = extended_rank_view(*result_ntk, ntk_lvls_new); - - if (!check_planarity(result)) - { - throw std::runtime_error("Error: Network should be planar"); - } + assert(check_planarity(result) && "Planarization failed: Network should be planar"); return result; } diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index 66f508c27..c475ff1d0 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -24,20 +23,6 @@ namespace fiction { - -template -struct virtual_storage -{ - /** - * Shared pointer vector storage for virtual_inputs. - */ - std::vector virtual_inputs; - /** - * Map from virtual_pis to real_pis. - */ - phmap::parallel_flat_hash_map map_virt_to_real_pi; -}; - /* Network with additional "virtual" PIs. * * "Virtual" PIs (Primary Inputs) are used to manage the duplication of PIs in the network. Each "real" PI can have @@ -45,6 +30,8 @@ struct virtual_storage * A "virtual" PI can be created by duplicating a "real" PI. * To keep track of this relationship, there is a mapping of each "virtual" PI to its corresponding "real" PI in the * network. + * + * @tparam Ntk Network type. */ template class virtual_pi_network : public Ntk @@ -54,37 +41,77 @@ class virtual_pi_network : public Ntk using node = typename Ntk::node; using signal = typename Ntk::signal; - public: + struct virtual_storage + { + /** + * Vector storing virtual_inputs. + */ + std::vector virtual_inputs{}; + /** + * Map from virtual_pis to real_pis. + */ + phmap::parallel_flat_hash_map map_virt_to_real_pi{}; + }; + + using v_strg = std::shared_ptr; + /** * Default constructor for the `virtual_pi_network` class. - * Initializes `_storage` as a shared pointer. + * Initializes `v_storage` as a shared pointer. */ - virtual_pi_network() : Ntk(), v_storage(std::make_shared>()) {} + virtual_pi_network() : Ntk(), v_storage(std::make_shared()) + { + static_assert(mockturtle::has_create_pi_v, "NtkSrc does not implement the create_pi function"); + static_assert(mockturtle::has_clone_v, "NtkSrc does not implement the clone function"); + static_assert(mockturtle::has_size_v, "NtkSrc does not implement the size function"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node function"); + static_assert(mockturtle::has_is_pi_v, "NtkSrc does not implement the is_pi function"); + static_assert(mockturtle::has_is_ci_v, "NtkSrc does not implement the is_ci function"); + static_assert(mockturtle::has_num_pis_v, "NtkSrc does not implement the num_pis function"); + static_assert(mockturtle::has_num_cis_v, "NtkSrc does not implement the num_cis function"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node function"); + } /** - * Copy constructor for the `virtual_pi_network` class. + * Constructor for the `virtual_pi_network` class that takes a network as input. It adds the functionalities of + * the `virtual_pi_network` class on top of the network. + * + * @tparam Ntk Network type. + * @param ntk Input network. */ - explicit virtual_pi_network(std::shared_ptr s) : - Ntk(std::move(s)), - v_storage(std::make_shared>()) - {} + explicit virtual_pi_network(const Ntk& ntk) : Ntk(ntk.clone()), v_storage(std::make_shared()) + { + static_assert(mockturtle::has_create_pi_v, "NtkSrc does not implement the create_pi function"); + static_assert(mockturtle::has_clone_v, "NtkSrc does not implement the clone function"); + static_assert(mockturtle::has_size_v, "NtkSrc does not implement the size function"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node function"); + static_assert(mockturtle::has_is_pi_v, "NtkSrc does not implement the is_pi function"); + static_assert(mockturtle::has_is_ci_v, "NtkSrc does not implement the is_ci function"); + static_assert(mockturtle::has_num_pis_v, "NtkSrc does not implement the num_pis function"); + static_assert(mockturtle::has_num_cis_v, "NtkSrc does not implement the num_cis function"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node function"); + } /** - * Constructor for the `virtual_pi_network` class that takes a network as input. - * Unlike other network types a virtual_pi_network can be created on top of any network. - * It initializes the base class `Ntk` with a clone of the provided network and creates a shared pointer - * to a `virtual_storage` object. + * Constructor for the `virtual_pi_network` class that takes a network and a shared pointer to a `virtual_storage` + * object. THis is used for cloning. * * @tparam Ntk Network type. * @param ntk Input network. + * @param s Shared pointer to the `virtual_storage` object to be used by this `virtual_pi_network`. */ - explicit virtual_pi_network(const Ntk& ntk) : Ntk(ntk.clone()), v_storage(std::make_shared>()) - {} - - explicit virtual_pi_network(const Ntk& ntk, std::shared_ptr> s) : - Ntk(ntk), - v_storage(std::move(s)) - {} + explicit virtual_pi_network(const Ntk& ntk, std::shared_ptr s) : Ntk(ntk), v_storage(std::move(s)) + { + static_assert(mockturtle::has_create_pi_v, "NtkSrc does not implement the create_pi function"); + static_assert(mockturtle::has_clone_v, "NtkSrc does not implement the clone function"); + static_assert(mockturtle::has_size_v, "NtkSrc does not implement the size function"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node function"); + static_assert(mockturtle::has_is_pi_v, "NtkSrc does not implement the is_pi function"); + static_assert(mockturtle::has_is_ci_v, "NtkSrc does not implement the is_ci function"); + static_assert(mockturtle::has_num_pis_v, "NtkSrc does not implement the num_pis function"); + static_assert(mockturtle::has_num_cis_v, "NtkSrc does not implement the num_cis function"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node function"); + } /** * Clones the virtual_pi_network object. @@ -95,7 +122,7 @@ class virtual_pi_network : public Ntk // Clone the network Ntk::clone(), // Create a new shared_ptr to virtual_storage using a copy of the current _storage - std::make_shared>(*v_storage)); + std::make_shared(*v_storage)); } /** @@ -121,7 +148,7 @@ class virtual_pi_network : public Ntk */ signal create_virtual_pi(const signal& real_pi) { - signal s = Ntk::create_pi(); + const signal s = Ntk::create_pi(); v_storage->virtual_inputs.emplace_back(Ntk::get_node(s)); v_storage->map_virt_to_real_pi.insert({Ntk::get_node(s), Ntk::get_node(real_pi)}); return s; @@ -220,7 +247,7 @@ class virtual_pi_network : public Ntk */ [[nodiscard]] auto get_real_pi(const node& v_pi) const { - auto it = v_storage->map_virt_to_real_pi.find(v_pi); + const auto it = v_storage->map_virt_to_real_pi.find(v_pi); assert(it != v_storage->map_virt_to_real_pi.end() && "Error: node is not a virtual pi"); @@ -312,37 +339,14 @@ class virtual_pi_network : public Ntk private: /** - * Shared pointer if the virtual PI storage. + * Shared pointer of the virtual PI storage. */ - std::shared_ptr> v_storage; + v_strg v_storage; }; namespace detail { -template -std::pair, Ntk>> initialize_copy_virtual_pi_network(Ntk& src) -{ - static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); - static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); - - static_assert(mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method"); - static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method"); - static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method"); - static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method"); - static_assert(has_foreach_real_pi_v, "NtkSrc does not implement the foreach_pi method"); - - mockturtle::node_map, Ntk> old2new(src); - Ntk dest; - old2new[src.get_constant(false)] = dest.get_constant(false); - if (src.get_node(src.get_constant(true)) != src.get_node(src.get_constant(false))) - { - old2new[src.get_constant(true)] = dest.get_constant(true); - } - src.foreach_real_pi([&](auto const& n) { old2new[n] = dest.create_pi(); }); - return {dest, old2new}; -} - template class delete_virtual_pis_impl { @@ -485,8 +489,31 @@ class delete_virtual_pis_impl private: using TopoNtkSrc = mockturtle::topo_view; - TopoNtkSrc ntk_topo; Ntk ntk; + TopoNtkSrc ntk_topo; + + [[nodiscard]] std::pair, Ntk>> + initialize_copy_virtual_pi_network(Ntk& src) + { + static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); + static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); + + static_assert(mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method"); + static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method"); + static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method"); + static_assert(has_foreach_real_pi_v, "NtkSrc does not implement the foreach_pi method"); + + mockturtle::node_map, Ntk> old2new(src); + Ntk dest; + old2new[src.get_constant(false)] = dest.get_constant(false); + if (src.get_node(src.get_constant(true)) != src.get_node(src.get_constant(false))) + { + old2new[src.get_constant(true)] = dest.get_constant(true); + } + src.foreach_real_pi([&](auto const& n) { old2new[n] = dest.create_pi(); }); + return {dest, old2new}; + } }; } // namespace detail From c838deeb15e823313296ddbc79df4b0bcd4c2e8a Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 23 Sep 2024 16:13:04 +0000 Subject: [PATCH 76/84] :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions --- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 68 ++++++++++++------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index a73e9980d..288323f4e 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -4376,6 +4376,16 @@ Parameter ``bdl_iterator``: static const char *__doc_fiction_detail_critical_temperature_impl_stats = R"doc(Statistics.)doc"; +static const char *__doc_fiction_detail_delete_virtual_pis_impl = R"doc()doc"; + +static const char *__doc_fiction_detail_delete_virtual_pis_impl_delete_virtual_pis_impl = R"doc()doc"; + +static const char *__doc_fiction_detail_delete_virtual_pis_impl_ntk = R"doc()doc"; + +static const char *__doc_fiction_detail_delete_virtual_pis_impl_ntk_topo = R"doc()doc"; + +static const char *__doc_fiction_detail_delete_virtual_pis_impl_run = R"doc()doc"; + static const char *__doc_fiction_detail_delete_wires = R"doc(This function deletes wires from the provided `wiring_reduction_layout` based on the specified coordinates and @@ -13327,10 +13337,11 @@ shortest x-y path in the H-graph for every level in the network. An H-graph describes edge relations between two levels in a network, with one level assumed as fixed, starting at the Primary Outputs (POs). By finding the shortest path from the source (x) to the sink (y) in this -H-graph, an optimal solution for the NDCE problem is found. The -function constructs an H-graph that captures edge relations between -two levels within the graph and computes the shortest x-y paths on the -H-graph, traversing from the POs towards the Primary Inputs (PIs). +H-graph, an optimal solution for the NDCE problem for each level is +found. The function constructs an H-graph that captures edge relations +between two levels within the graph and computes the shortest x-y +paths on the H-graph, traversing from the POs towards the Primary +Inputs (PIs). Returns: A view of the planarized virtual_pi_network created in the format @@ -13346,20 +13357,22 @@ Parameter ``ntk_src``: Source network to be utilized for the planarization. Parameter ``ps``: - Node duplication parameters used in the computation. - -Throws: - std::runtime_error if input network not balanced, if no node - combinations are found or if the created network is non-planar.)doc"; + Node duplication parameters used in the computation.)doc"; static const char *__doc_fiction_node_duplication_planarization_params = R"doc(Parameters for the node duplication algorithm.)doc"; -static const char *__doc_fiction_node_duplication_planarization_params_random_output_order = +static const char *__doc_fiction_node_duplication_planarization_params_output_order = R"doc(The output order determines the starting layer for this algorithm. If this option is turned off, the output order remains the same as in the provided network. If it is turned on, the outputs are ordered randomly.)doc"; +static const char *__doc_fiction_node_duplication_planarization_params_output_order_KEEP_PO_ORDER = R"doc(Keep the PO order from the input network.)doc"; + +static const char *__doc_fiction_node_duplication_planarization_params_output_order_RANDOM_PO_ORDER = R"doc(Randomize the PO order.)doc"; + +static const char *__doc_fiction_node_duplication_planarization_params_po_order = R"doc()doc"; + static const char *__doc_fiction_normalize_layout_coordinates = R"doc(A new layout is constructed and returned that is equivalent to the given cell-level layout. However, its coordinates are normalized, @@ -17674,20 +17687,16 @@ PIs. Returns: The real size of the virtual_pi_network as a uint32_t.)doc"; -static const char *__doc_fiction_virtual_pi_network_v_storage = R"doc(Shared pointer if the virtual PI storage.)doc"; +static const char *__doc_fiction_virtual_pi_network_v_storage = R"doc(Shared pointer of the virtual PI storage.)doc"; static const char *__doc_fiction_virtual_pi_network_virtual_pi_network = R"doc(Default constructor for the `virtual_pi_network` class. Initializes -`_storage` as a shared pointer.)doc"; - -static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_2 = R"doc(Copy constructor for the `virtual_pi_network` class.)doc"; +`v_storage` as a shared pointer.)doc"; -static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_3 = +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_2 = R"doc(Constructor for the `virtual_pi_network` class that takes a network as -input. Unlike other network types a virtual_pi_network can be created -on top of any network. It initializes the base class `Ntk` with a -clone of the provided network and creates a shared pointer to a -`virtual_storage` object. +input. It adds the functionalities of the `virtual_pi_network` class +on top of the network. Template parameter ``Ntk``: Network type. @@ -17695,13 +17704,26 @@ Template parameter ``Ntk``: Parameter ``ntk``: Input network.)doc"; -static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_4 = R"doc()doc"; +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_3 = +R"doc(Constructor for the `virtual_pi_network` class that takes a network +and a shared pointer to a `virtual_storage` object. THis is used for +cloning. + +Template parameter ``Ntk``: + Network type. + +Parameter ``ntk``: + Input network. + +Parameter ``s``: + Shared pointer to the `virtual_storage` object to be used by this + `virtual_pi_network`.)doc"; -static const char *__doc_fiction_virtual_storage = R"doc()doc"; +static const char *__doc_fiction_virtual_pi_network_virtual_storage = R"doc()doc"; -static const char *__doc_fiction_virtual_storage_map_virt_to_real_pi = R"doc(Map from virtual_pis to real_pis.)doc"; +static const char *__doc_fiction_virtual_pi_network_virtual_storage_map_virt_to_real_pi = R"doc(Map from virtual_pis to real_pis.)doc"; -static const char *__doc_fiction_virtual_storage_virtual_inputs = R"doc(Shared pointer vector storage for virtual_inputs.)doc"; +static const char *__doc_fiction_virtual_pi_network_virtual_storage_virtual_inputs = R"doc(Vector storing virtual_inputs.)doc"; static const char *__doc_fiction_volume = R"doc(Computes the volume of a given coordinate assuming its origin is (0, From 42510ce2f2662fd2dd167fcf3f0962d725b9d51c Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 24 Sep 2024 15:11:15 +0200 Subject: [PATCH 77/84] :heavy_plus_sign: buffer_removal added. --- .../network_transformation/buffer_removal.hpp | 310 ++++++++++++++++++ .../fiction/networks/virtual_pi_network.hpp | 4 +- .../network_transformation/buffer_removal.cpp | 103 ++++++ 3 files changed, 415 insertions(+), 2 deletions(-) create mode 100644 include/fiction/algorithms/network_transformation/buffer_removal.hpp create mode 100644 test/algorithms/network_transformation/buffer_removal.cpp diff --git a/include/fiction/algorithms/network_transformation/buffer_removal.hpp b/include/fiction/algorithms/network_transformation/buffer_removal.hpp new file mode 100644 index 000000000..ec31ef251 --- /dev/null +++ b/include/fiction/algorithms/network_transformation/buffer_removal.hpp @@ -0,0 +1,310 @@ +// +// Created by benjamin on 9/24/24. +// + +#ifndef FICTION_BUFFER_REMOVAL_HPP +#define FICTION_BUFFER_REMOVAL_HPP + +#include "fiction/traits.hpp" +#include "fiction/utils/name_utils.hpp" + +#include +#include +#include + +#include +#include +#include + +#if (PROGRESS_BARS) +#include +#endif + +namespace fiction +{ + +template +std::pair, NtkSrc>> initialize_copy_network_v( NtkSrc const& src ) +{ + static_assert( mockturtle::is_network_type_v, "NtkDest is not a network type" ); + static_assert( mockturtle::is_network_type_v, "NtkSrc is not a network type" ); + + static_assert( mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method" ); + static_assert( mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method" ); + static_assert( mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method" ); + static_assert( mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method" ); + static_assert( mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi method" ); + + mockturtle::node_map, NtkSrc> old2new( src ); + NtkDest dest; + old2new[src.get_constant( false )] = dest.get_constant( false ); + if ( src.get_node( src.get_constant( true ) ) != src.get_node( src.get_constant( false ) ) ) + { + old2new[src.get_constant( true )] = dest.get_constant( true ); + } + if constexpr (fiction::has_foreach_real_pi_v) + { + src.foreach_real_pi( [&]( auto const& n ) { + old2new[n] = dest.create_pi(); + } ); + src.foreach_virtual_pi( [&]( auto const& n ) { + old2new[n] = dest.create_virtual_pi(src.get_real_pi(n)); + } ); + } + else + { + src.foreach_pi( [&]( auto const& n ) { + old2new[n] = dest.create_pi(); + } ); + } + + + return { dest, old2new }; +} + +namespace detail +{ + +template +class remove_buffer_impl +{ + public: + using signal = typename Ntk::signal; + using node = typename Ntk::node; + using TopoNtkSrc = mockturtle::topo_view; + + explicit remove_buffer_impl(const Ntk& ntk_src) : ntk{ntk_src} {} + + signal skip_buffer_chain_rec(node n, signal s, mockturtle::node_map& old2new) + { + // Buffer only have one fan-in && make sure it is not a fan-out node + if (ntk.is_buf(n) && ntk.fanout_size(n) == 1) + { + const auto fc = fanins(ntk, n); + assert(fc.fanin_nodes.size() == 1 && "Error: Node is not a buffer -> check the conditions for this path"); + const auto fn = fc.fanin_nodes[0]; + const auto tgt_signal = old2new[fn]; + + // Recursive call: Traverse upstream if the fanin node is also a buffer + return skip_buffer_chain_rec(fn, tgt_signal, old2new); + } + + // If the node 'n' is not a buffer, return the current signal 's' + return s; + } + + Ntk run() + { + auto init = fiction::initialize_copy_network_v(ntk); + auto& ntk_dest = init.first; + auto& old2new = init.second; + + const auto gather_fanin_signals = [this, &ntk_dest, &old2new](const auto& n) + { + std::vector children{}; + + ntk.foreach_fanin(n, + [this, &ntk_dest, &old2new, &children](const auto& f) + { + const auto fn = ntk.get_node(f); + const auto tgt_signal = old2new[fn]; + + // skip buffer chains + const auto tgt_signal_wo_buf = skip_buffer_chain_rec(fn, tgt_signal, old2new); + + children.emplace_back(ntk.is_complemented(f) ? + ntk_dest.create_not(tgt_signal_wo_buf) : + tgt_signal_wo_buf); + }); + + return children; + }; + +#if (PROGRESS_BARS) + // initialize a progress bar + mockturtle::progress_bar bar{static_cast(ntk.num_gates()), "[i] network conversion: |{0}|"}; +#endif + + ntk.foreach_gate( + [&, this](const auto& g, [[maybe_unused]] auto i) + { + // skip buffer nodes + if (ntk.is_buf(g) && ntk.fanout_size(g) == 1) + { + return true; + } + + auto children = gather_fanin_signals(g); + +#if (PROGRESS_BARS) + // update progress + bar(i); +#endif + + if constexpr (mockturtle::has_is_and_v && mockturtle::has_create_and_v) + { + if (ntk.is_and(g)) + { + old2new[g] = ntk_dest.create_and(children[0], children[1]); + return true; + } + } + if constexpr (mockturtle::has_is_or_v && mockturtle::has_create_or_v) + { + if (ntk.is_or(g)) + { + old2new[g] = ntk_dest.create_or(children[0], children[1]); + return true; + } + } + if constexpr (mockturtle::has_is_xor_v && mockturtle::has_create_xor_v) + { + if (ntk.is_xor(g)) + { + old2new[g] = ntk_dest.create_xor(children[0], children[1]); + return true; + } + } + if constexpr (mockturtle::has_is_maj_v && mockturtle::has_create_maj_v) + { + if (ntk.is_maj(g)) + { + old2new[g] = ntk_dest.create_maj(children[0], children[1], children[2]); + return true; + } + } + if constexpr (mockturtle::has_is_nary_and_v && mockturtle::has_create_nary_and_v) + { + if (ntk.is_nary_and(g)) + { + old2new[g] = ntk_dest.create_nary_and(children); + return true; + } + } + if constexpr (mockturtle::has_is_nary_or_v && mockturtle::has_create_nary_or_v) + { + if (ntk.is_nary_or(g)) + { + old2new[g] = ntk_dest.create_nary_or(children); + return true; + } + } + if constexpr (mockturtle::has_is_nary_xor_v && mockturtle::has_create_nary_xor_v) + { + if (ntk.is_nary_xor(g)) + { + old2new[g] = ntk_dest.create_nary_xor(children); + return true; + } + } + if constexpr (fiction::has_is_buf_v && mockturtle::has_create_buf_v) + { + if (ntk.is_buf(g)) + { + old2new[g] = ntk_dest.create_buf(children[0]); + return true; + } + } + if constexpr (mockturtle::has_node_function_v && mockturtle::has_create_node_v) + { + old2new[g] = ntk_dest.create_node(children, ntk.node_function(g)); + return true; + } + assert(false); + return true; + }); + + ntk.foreach_po( + [this, &ntk_dest, &old2new](const auto& po) + { + const auto tgt_signal = old2new[ntk.get_node(po)]; + + // skip buffer chains + const auto tgt_signal_wo_buf = skip_buffer_chain_rec(ntk.get_node(po), tgt_signal, old2new); + + const auto tgt_po = + ntk.is_complemented(po) ? ntk_dest.create_not(tgt_signal_wo_buf) : tgt_signal_wo_buf; + + ntk_dest.create_po(tgt_po); + }); + + // restore signal names if applicable + fiction::restore_names(ntk, ntk_dest, old2new); + + return ntk_dest; + } + + private: + Ntk ntk; +}; +} // namespace detail + +template +bool constains_buffer(Ntk ntk) +{ + bool has_buf = false; + ntk.foreach_gate( + [&ntk, &has_buf](const auto& g) + { + if (ntk.is_buf(g)) + { + has_buf = true; + } + }); + return has_buf; +} + +/** + * Converts a logic network into an equivalent one of another type. Thereby, this function is very similar to + * `mockturtle::cleanup_dangling`. However, it supports real buffer nodes used for fanouts and path balancing in + * fiction. + * + * @note If `NtkDest` and `NtkSrc` are of the same type, this function returns `ntk` cleaned using + * `mockturtle::cleanup_dangling`. + * + * @tparam NtkDest Type of the returned logic network. + * @tparam NtkSrc Type of the input logic network. + * @param ntk The input logic network. + * @return A logic network of type `NtkDest` that is logically equivalent to `ntk`. + */ +template +Ntk remove_buffer(const Ntk& ntk) +{ + static_assert(mockturtle::is_network_type_v, "Ntk is not a network type"); + + static_assert(mockturtle::has_is_buf_v, "Ntk does not implement the is_buf function"); + static_assert(mockturtle::has_get_node_v, "Ntk does not implement the get_node function"); + static_assert(mockturtle::has_is_complemented_v, "Ntk does not implement the is_complemented function"); + static_assert(mockturtle::has_foreach_pi_v, "Ntk does not implement the foreach_pi function"); + static_assert(mockturtle::has_foreach_gate_v, "Ntk does not implement the foreach_gate function"); + static_assert(mockturtle::has_foreach_po_v, "Ntk does not implement the foreach_po function"); + static_assert(mockturtle::has_foreach_fanin_v, "Ntk does not implement the foreach_fanin function"); + + static_assert(mockturtle::has_get_constant_v, "Ntk does not implement the get_constant function"); + + static_assert(mockturtle::has_create_pi_v, "Ntk does not implement the create_pi function"); + static_assert(mockturtle::has_create_po_v, "Ntk does not implement the create_po function"); + static_assert(mockturtle::has_create_not_v, "Ntk does not implement the create_not function"); + static_assert(mockturtle::has_create_and_v, "Ntk does not implement the create_and function"); + static_assert(mockturtle::has_create_or_v, "Ntk does not implement the create_or function"); + static_assert(mockturtle::has_create_xor_v, "Ntk does not implement the create_xor function"); + static_assert(mockturtle::has_create_maj_v, "Ntk does not implement the create_maj function"); + // TODO handle ci/ro/etc... + + assert(ntk.is_combinational() && "Network has to be combinational"); + + if (!constains_buffer(ntk)) + { + return ntk; + } + + detail::remove_buffer_impl p{ntk}; + + auto result = p.run(); + + return result; +} + +} // namespace fiction + +#endif // FICTION_BUFFER_REMOVAL_HPP diff --git a/include/fiction/networks/virtual_pi_network.hpp b/include/fiction/networks/virtual_pi_network.hpp index c475ff1d0..73feca15c 100644 --- a/include/fiction/networks/virtual_pi_network.hpp +++ b/include/fiction/networks/virtual_pi_network.hpp @@ -261,9 +261,9 @@ class virtual_pi_network : public Ntk * @param fn The function to be applied to each primary input. */ template - void foreach_real_pi(Fn&& fn) + void foreach_real_pi(Fn&& fn) const { - static_cast(this)->foreach_pi( + static_cast(this)->foreach_pi( [&](const auto& i) { if (!is_virtual_pi(i)) diff --git a/test/algorithms/network_transformation/buffer_removal.cpp b/test/algorithms/network_transformation/buffer_removal.cpp new file mode 100644 index 000000000..ff2efc27c --- /dev/null +++ b/test/algorithms/network_transformation/buffer_removal.cpp @@ -0,0 +1,103 @@ +// +// Created by benjamin on 9/24/24. +// + +#include + +#include "fiction/algorithms/network_transformation/fanout_substitution.hpp" +#include "fiction/algorithms/network_transformation/network_balancing.hpp" +#include "fiction/algorithms/network_transformation/node_duplication_planarization.hpp" +#include "fiction/algorithms/verification/virtual_miter.hpp" +#include "fiction/networks/technology_network.hpp" +#include "fiction/utils/debug/network_writer.hpp" + +#include + +#include +#include + +using namespace fiction; + +TEST_CASE("Remove one buffer", "[buffer-removal]") +{ + technology_network tec{}; + const auto p0 = tec.create_pi(); + const auto p1 = tec.create_pi(); + const auto b0 = tec.create_buf(p0); + const auto a0 = tec.create_and(b0, p1); + tec.create_po(a0); + + const auto removed = remove_buffer(tec); + + mockturtle::equivalence_checking_stats st; + const auto cec_m = mockturtle::equivalence_checking(*mockturtle::miter(tec, removed), {}, &st); + REQUIRE(cec_m.has_value()); + CHECK(cec_m.value() == 1); + + CHECK(tec.num_gates() == removed.num_gates() + 1); +} + +TEST_CASE("Remove one buffer chain", "[buffer-removal]") +{ + technology_network tec{}; + const auto p0 = tec.create_pi(); + const auto p1 = tec.create_pi(); + const auto b0 = tec.create_buf(p0); + const auto b1 = tec.create_buf(b0); + const auto b2 = tec.create_buf(b1); + const auto a0 = tec.create_and(b2, p1); + tec.create_po(a0); + + const auto removed = remove_buffer(tec); + + mockturtle::equivalence_checking_stats st; + const auto cec_m = mockturtle::equivalence_checking(*mockturtle::miter(tec, removed), {}, &st); + REQUIRE(cec_m.has_value()); + CHECK(cec_m.value() == 1); + + CHECK(tec.num_gates() == removed.num_gates() + 3); +} + +TEST_CASE("Remove multiple buffers", "[buffer-removal]") +{ + fiction::technology_network tec; + const auto pi0 = tec.create_pi(); + const auto pi1 = tec.create_pi(); + const auto pi2 = tec.create_pi(); + const auto pi3 = tec.create_pi(); + const auto pi4 = tec.create_pi(); + + const auto a0 = tec.create_and(pi0, pi1); + const auto o0 = tec.create_or(pi0, pi1); + const auto a1 = tec.create_and(pi3, pi4); + const auto o1 = tec.create_or(pi3, pi4); + + const auto a2 = tec.create_and(o0, pi2); + const auto a3 = tec.create_and(o1, pi2); + const auto a4 = tec.create_and(a2, a3); + + tec.create_po(a0); + tec.create_po(a4); + tec.create_po(a1); + + fiction::network_balancing_params ps; + ps.unify_outputs = true; + + const auto _b = fiction::network_balancing( + fiction::fanout_substitution(tec), ps); + + fiction::node_duplication_planarization_params dps; + dps.po_order = fiction::node_duplication_planarization_params::output_order::KEEP_PO_ORDER; + + auto planarized_b = fiction::node_duplication_planarization(_b, dps); + // clone to get rid of the extended_rank_view + auto planar = planarized_b.clone(); + // remove the buffer nodes + auto removed = remove_buffer(planar); + + mockturtle::equivalence_checking_stats st; + const auto cec_m = + mockturtle::equivalence_checking(*fiction::virtual_miter(tec, removed), {}, &st); + REQUIRE(cec_m.has_value()); + CHECK(cec_m.value() == 1); +} From 60f4038caf7e3b5790fa79f5f35be547ed674e8a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 13:11:40 +0000 Subject: [PATCH 78/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network_transformation/buffer_removal.hpp | 48 ++++++++----------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/buffer_removal.hpp b/include/fiction/algorithms/network_transformation/buffer_removal.hpp index ec31ef251..5a8c0acc7 100644 --- a/include/fiction/algorithms/network_transformation/buffer_removal.hpp +++ b/include/fiction/algorithms/network_transformation/buffer_removal.hpp @@ -23,43 +23,37 @@ namespace fiction { -template -std::pair, NtkSrc>> initialize_copy_network_v( NtkSrc const& src ) +template +std::pair, NtkSrc>> +initialize_copy_network_v(NtkSrc const& src) { - static_assert( mockturtle::is_network_type_v, "NtkDest is not a network type" ); - static_assert( mockturtle::is_network_type_v, "NtkSrc is not a network type" ); - - static_assert( mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method" ); - static_assert( mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method" ); - static_assert( mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method" ); - static_assert( mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method" ); - static_assert( mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi method" ); - - mockturtle::node_map, NtkSrc> old2new( src ); - NtkDest dest; - old2new[src.get_constant( false )] = dest.get_constant( false ); - if ( src.get_node( src.get_constant( true ) ) != src.get_node( src.get_constant( false ) ) ) + static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); + static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); + + static_assert(mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method"); + static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method"); + static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method"); + static_assert(mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi method"); + + mockturtle::node_map, NtkSrc> old2new(src); + NtkDest dest; + old2new[src.get_constant(false)] = dest.get_constant(false); + if (src.get_node(src.get_constant(true)) != src.get_node(src.get_constant(false))) { - old2new[src.get_constant( true )] = dest.get_constant( true ); + old2new[src.get_constant(true)] = dest.get_constant(true); } if constexpr (fiction::has_foreach_real_pi_v) { - src.foreach_real_pi( [&]( auto const& n ) { - old2new[n] = dest.create_pi(); - } ); - src.foreach_virtual_pi( [&]( auto const& n ) { - old2new[n] = dest.create_virtual_pi(src.get_real_pi(n)); - } ); + src.foreach_real_pi([&](auto const& n) { old2new[n] = dest.create_pi(); }); + src.foreach_virtual_pi([&](auto const& n) { old2new[n] = dest.create_virtual_pi(src.get_real_pi(n)); }); } else { - src.foreach_pi( [&]( auto const& n ) { - old2new[n] = dest.create_pi(); - } ); + src.foreach_pi([&](auto const& n) { old2new[n] = dest.create_pi(); }); } - - return { dest, old2new }; + return {dest, old2new}; } namespace detail From b7a6229438ffad165a56ea4c972858c863c27249 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 24 Sep 2024 15:23:54 +0200 Subject: [PATCH 79/84] :art: added docstrings --- .../network_transformation/buffer_removal.hpp | 84 ++++++++++--------- .../network_transformation/buffer_removal.cpp | 1 - 2 files changed, 46 insertions(+), 39 deletions(-) diff --git a/include/fiction/algorithms/network_transformation/buffer_removal.hpp b/include/fiction/algorithms/network_transformation/buffer_removal.hpp index ec31ef251..76b172a99 100644 --- a/include/fiction/algorithms/network_transformation/buffer_removal.hpp +++ b/include/fiction/algorithms/network_transformation/buffer_removal.hpp @@ -23,43 +23,46 @@ namespace fiction { -template -std::pair, NtkSrc>> initialize_copy_network_v( NtkSrc const& src ) +/** + * Initializes a copy of the source network like in mockturtle::initialize_copy_network. Additionally, this modification + * supports virtual PIs created via `virtual_pi_network. + * + * @tparam NtkDest The type of the destination network. + * @tparam NtkSrc The type of the source network. + * @param src The source network to be copied. + * @return A pair of the destination network and the node map. + */ +template +std::pair, NtkSrc>> +initialize_copy_network_v(NtkSrc const& src) { - static_assert( mockturtle::is_network_type_v, "NtkDest is not a network type" ); - static_assert( mockturtle::is_network_type_v, "NtkSrc is not a network type" ); - - static_assert( mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method" ); - static_assert( mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method" ); - static_assert( mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method" ); - static_assert( mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method" ); - static_assert( mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi method" ); - - mockturtle::node_map, NtkSrc> old2new( src ); - NtkDest dest; - old2new[src.get_constant( false )] = dest.get_constant( false ); - if ( src.get_node( src.get_constant( true ) ) != src.get_node( src.get_constant( false ) ) ) + static_assert(mockturtle::is_network_type_v, "NtkDest is not a network type"); + static_assert(mockturtle::is_network_type_v, "NtkSrc is not a network type"); + + static_assert(mockturtle::has_get_constant_v, "NtkDest does not implement the get_constant method"); + static_assert(mockturtle::has_create_pi_v, "NtkDest does not implement the create_pi method"); + static_assert(mockturtle::has_get_constant_v, "NtkSrc does not implement the get_constant method"); + static_assert(mockturtle::has_get_node_v, "NtkSrc does not implement the get_node method"); + static_assert(mockturtle::has_foreach_pi_v, "NtkSrc does not implement the foreach_pi method"); + + mockturtle::node_map, NtkSrc> old2new(src); + NtkDest dest; + old2new[src.get_constant(false)] = dest.get_constant(false); + if (src.get_node(src.get_constant(true)) != src.get_node(src.get_constant(false))) { - old2new[src.get_constant( true )] = dest.get_constant( true ); + old2new[src.get_constant(true)] = dest.get_constant(true); } if constexpr (fiction::has_foreach_real_pi_v) { - src.foreach_real_pi( [&]( auto const& n ) { - old2new[n] = dest.create_pi(); - } ); - src.foreach_virtual_pi( [&]( auto const& n ) { - old2new[n] = dest.create_virtual_pi(src.get_real_pi(n)); - } ); + src.foreach_real_pi([&](auto const& n) { old2new[n] = dest.create_pi(); }); + src.foreach_virtual_pi([&](auto const& n) { old2new[n] = dest.create_virtual_pi(src.get_real_pi(n)); }); } else { - src.foreach_pi( [&]( auto const& n ) { - old2new[n] = dest.create_pi(); - } ); + src.foreach_pi([&](auto const& n) { old2new[n] = dest.create_pi(); }); } - - return { dest, old2new }; + return {dest, old2new}; } namespace detail @@ -85,7 +88,7 @@ class remove_buffer_impl const auto fn = fc.fanin_nodes[0]; const auto tgt_signal = old2new[fn]; - // Recursive call: Traverse upstream if the fanin node is also a buffer + // Recursive call: Traverse if the fanin node is also a buffer return skip_buffer_chain_rec(fn, tgt_signal, old2new); } @@ -133,7 +136,7 @@ class remove_buffer_impl { return true; } - + // the rest of the code is taken from `fiction::convert_network`. auto children = gather_fanin_signals(g); #if (PROGRESS_BARS) @@ -239,6 +242,13 @@ class remove_buffer_impl }; } // namespace detail +/** + * Checks if a given logic network contains a buffer gate. + * + * @tparam Ntk The type of the logic network. + * @param ntk The logic network. + * @return true if the network contains a buffer gate, false otherwise. + */ template bool constains_buffer(Ntk ntk) { @@ -255,17 +265,15 @@ bool constains_buffer(Ntk ntk) } /** - * Converts a logic network into an equivalent one of another type. Thereby, this function is very similar to - * `mockturtle::cleanup_dangling`. However, it supports real buffer nodes used for fanouts and path balancing in - * fiction. + * Removes buffer nodes in a network. The idea is the same as in mockturtle::remove_buffer_chains()`, but node deletion + * is not supported for `buffered_klut_networks`, and therefore, an approach similar to `fiction::convert_network` is + * chosen. * - * @note If `NtkDest` and `NtkSrc` are of the same type, this function returns `ntk` cleaned using - * `mockturtle::cleanup_dangling`. + * @note Fanout nodes are also flagged with `is_buf` in fiction, but not removed by this class. * - * @tparam NtkDest Type of the returned logic network. - * @tparam NtkSrc Type of the input logic network. - * @param ntk The input logic network. - * @return A logic network of type `NtkDest` that is logically equivalent to `ntk`. + * @tparam Ntk The network type. + * @param ntk The original network. + * @return The network with buffers removed. */ template Ntk remove_buffer(const Ntk& ntk) diff --git a/test/algorithms/network_transformation/buffer_removal.cpp b/test/algorithms/network_transformation/buffer_removal.cpp index ff2efc27c..c111f41d8 100644 --- a/test/algorithms/network_transformation/buffer_removal.cpp +++ b/test/algorithms/network_transformation/buffer_removal.cpp @@ -9,7 +9,6 @@ #include "fiction/algorithms/network_transformation/node_duplication_planarization.hpp" #include "fiction/algorithms/verification/virtual_miter.hpp" #include "fiction/networks/technology_network.hpp" -#include "fiction/utils/debug/network_writer.hpp" #include From f5e0e490bd5800206a243f54bbe327a72888e2b5 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 14 Oct 2024 11:52:56 +0200 Subject: [PATCH 80/84] :art: renamed files --- experiments/legalization/legalization.cpp | 2 +- .../node_duplication_planarization.hpp | 2 +- .../{check_planarity.hpp => check_planarity_balanced.hpp} | 6 +++--- .../{check_planarity.cpp => check_planarity_balanced.cpp} | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename include/fiction/algorithms/properties/{check_planarity.hpp => check_planarity_balanced.hpp} (97%) rename test/algorithms/properties/{check_planarity.cpp => check_planarity_balanced.cpp} (97%) diff --git a/experiments/legalization/legalization.cpp b/experiments/legalization/legalization.cpp index 0f8664d13..ddf6cea39 100644 --- a/experiments/legalization/legalization.cpp +++ b/experiments/legalization/legalization.cpp @@ -4,7 +4,7 @@ #include "experiments.hpp" #include "fiction/algorithms/network_transformation/fanout_substitution.hpp" -#include "fiction/algorithms/properties/check_planarity.hpp" +#include "fiction/algorithms/properties/check_planarity_balanced.hpp" #include "fiction/utils/debug/network_writer.hpp" #include "fiction_experiments.hpp" diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index b65f09390..513ac3150 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -5,7 +5,7 @@ #ifndef FICTION_NODE_DUPLICATION_PLANARIZATION_HPP #define FICTION_NODE_DUPLICATION_PLANARIZATION_HPP -#include "fiction/algorithms/properties/check_planarity.hpp" +#include "fiction/algorithms/properties/check_planarity_balanced.hpp" #include "fiction/networks/views/extended_rank_view.hpp" #include "fiction/networks/virtual_pi_network.hpp" diff --git a/include/fiction/algorithms/properties/check_planarity.hpp b/include/fiction/algorithms/properties/check_planarity_balanced.hpp similarity index 97% rename from include/fiction/algorithms/properties/check_planarity.hpp rename to include/fiction/algorithms/properties/check_planarity_balanced.hpp index 97398237f..6a4da0a84 100644 --- a/include/fiction/algorithms/properties/check_planarity.hpp +++ b/include/fiction/algorithms/properties/check_planarity_balanced.hpp @@ -2,8 +2,8 @@ // Created by benjamin on 17.07.24. // -#ifndef FICTION_CHECK_PLANARITY_HPP -#define FICTION_CHECK_PLANARITY_HPP +#ifndef FICTION_CHECK_PLANARITY_BALANCED_HPP +#define FICTION_CHECK_PLANARITY_BALANCED_HPP #include "fiction/algorithms/network_transformation/network_balancing.hpp" @@ -119,4 +119,4 @@ template } // namespace fiction -#endif // FICTION_CHECK_PLANARITY_HPP +#endif // FICTION_CHECK_PLANARITY_BALANCED_HPP diff --git a/test/algorithms/properties/check_planarity.cpp b/test/algorithms/properties/check_planarity_balanced.cpp similarity index 97% rename from test/algorithms/properties/check_planarity.cpp rename to test/algorithms/properties/check_planarity_balanced.cpp index 9bd9aa551..0bc7bda89 100644 --- a/test/algorithms/properties/check_planarity.cpp +++ b/test/algorithms/properties/check_planarity_balanced.cpp @@ -4,7 +4,7 @@ #include -#include +#include #include #include From ede1ff05f15661a8555b4a7c071f9a5f68c69af3 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 14 Oct 2024 12:52:31 +0200 Subject: [PATCH 81/84] :art: experiments_file_cleaned --- experiments/legalization/legalization.cpp | 190 +++--------------- .../node_duplication_planarization.hpp | 8 +- libs/Catch2 | 2 +- libs/json | 2 +- libs/mockturtle | 2 +- libs/parallel-hashmap | 2 +- libs/pybind11 | 2 +- libs/tinyxml2 | 2 +- 8 files changed, 38 insertions(+), 172 deletions(-) diff --git a/experiments/legalization/legalization.cpp b/experiments/legalization/legalization.cpp index ddf6cea39..59bf40c77 100644 --- a/experiments/legalization/legalization.cpp +++ b/experiments/legalization/legalization.cpp @@ -5,31 +5,30 @@ #include "experiments.hpp" #include "fiction/algorithms/network_transformation/fanout_substitution.hpp" #include "fiction/algorithms/properties/check_planarity_balanced.hpp" -#include "fiction/utils/debug/network_writer.hpp" +#include "fiction/layouts/clocked_layout.hpp" +#include "fiction/layouts/cartesian_layout.hpp" +#include "fiction/layouts/tile_based_layout.hpp" +#include "fiction/layouts/gate_level_layout.hpp" +#include "fiction/layouts/coordinates.hpp" #include "fiction_experiments.hpp" #include #include -#include // scalable heuristic for physical design -#include // wiring reduction algorithm -#include // critical path and throughput calculations -#include // SAT-based equivalence checking +#include // scalable heuristic for physical design +#include #include -#include #include // read networks from files #include #include #include -#include // output formatting #include -#include -#include -#include +#include +#include #include #include -#include +#include #include #include @@ -49,12 +48,11 @@ Ntk read_ntk(const std::string& name) int main() // NOLINT { - experiments::experiment + experiments::experiment wiring_reduction_exp{"planarization", "benchmark", "inputs", "virt_inputs", "outputs", "initial nodes", "nodes buffered", "nodes planarized", "is_planar", "equivalent(ntk)", "equivalent(lyt)"}; - int x = 0; for (const auto& entry : std::filesystem::directory_iterator("/home/benjamin/Documents/Repositories/working/fiction/benchmarks/IWLS93")) { @@ -90,29 +88,10 @@ int main() // NOLINT auto benchmark_network = *nets.front(); - bool cont = false; - benchmark_network.foreach_pi( - [&benchmark_network, &cont](auto pi) - { - if (benchmark_network.is_po(pi)) - { - cont = true; - // std::cout << "Pi is Po\n"; - } - }); - if (cont) - { - continue; - } - - // fiction::debug::write_dot_network(benchmark_network); - - // std::cout << benchmark_network.num_gates() << std::endl; - fiction::network_balancing_params ps; ps.unify_outputs = true; - const auto _b = fiction::network_balancing( + const auto b = fiction::network_balancing( fiction::fanout_substitution(benchmark_network), ps); // happens with exp4.v @@ -127,22 +106,12 @@ int main() // NOLINT std::cout << "Node 9213: " << fc.fanin_nodes.size() << std::endl; std::cout << "Node 9213: " << _b.is_buf(8771) << std::endl;*/ - // std::cout << _b.num_gates() << std::endl; - - // fiction::debug::write_dot_network(_b); - - if (_b.size() > 10000) + if (b.size() > 10000) { - /*wiring_reduction_exp(entry.path().filename().string(), benchmark_network.num_pis(), 0, - benchmark_network.num_pos(), benchmark_network.num_gates(), _b.num_gates(), - _b.num_gates(), 0, 0, 0); - wiring_reduction_exp.save(); - wiring_reduction_exp.table(); - std::cout << ++x << "\n";*/ continue; } - const auto planarized_b = fiction::node_duplication_planarization(_b); + const auto planarized_b = fiction::node_duplication_planarization(b); const auto is_planar = fiction::check_planarity(planarized_b); if (planarized_b.size() > 20000) { @@ -152,80 +121,34 @@ int main() // NOLINT const auto cec_m = mockturtle::equivalence_checking( *fiction::virtual_miter(benchmark_network, planarized_b), {}, &st); assert(cec_m.has_value()); - std::cout << cec_m.value() << std::endl; - - using gate_lyt = fiction::gate_level_layout< - fiction::clocked_layout>>>; fiction::orthogonal_physical_design_stats stats{}; using gate_layout = fiction::gate_level_layout< fiction::clocked_layout>>>; auto layout = fiction::orthogonal(planarized_b, {}, &stats); - fiction::gate_level_drv_params ps_d{}; + const fiction::gate_level_drv_params ps_d{}; fiction::gate_level_drv_stats st_d{}; fiction::gate_level_drvs(layout, ps_d, &st_d); const auto miter = mockturtle::miter(planarized_b, layout); - bool eq; + bool eq = false; if (miter) { - mockturtle::equivalence_checking_stats st; + mockturtle::equivalence_checking_stats st_o; - const auto ce = mockturtle::equivalence_checking(*miter, {}, &st); + const auto ce = mockturtle::equivalence_checking(*miter, {}, &st_o); eq = ce.value(); } wiring_reduction_exp(entry.path().filename().string(), benchmark_network.num_pis(), planarized_b.num_virtual_pis(), benchmark_network.num_pos(), benchmark_network.num_gates(), - _b.num_gates(), planarized_b.num_gates(), is_planar, cec_m.value(), eq); + b.num_gates(), planarized_b.num_gates(), is_planar, cec_m.value(), eq); wiring_reduction_exp.save(); wiring_reduction_exp.table(); - std::cout << ++x << "\n"; } - /*fiction::technology_network tec; - const auto pi0 = tec.create_pi(); - const auto pi1 = tec.create_pi(); - const auto pi2 = tec.create_pi(); - const auto pi3 = tec.create_pi(); - const auto pi4 = tec.create_pi(); - - const auto a0 = tec.create_and(pi0, pi1); - const auto o0 = tec.create_or(pi0, pi1); - const auto a1 = tec.create_and(pi3, pi4); - const auto o1 = tec.create_or(pi3, pi4); - - const auto a2 = tec.create_and(o0, pi2); - const auto a3 = tec.create_and(o1, pi2); - const auto a4 = tec.create_and(a2, a3); - - tec.create_po(a0); - tec.create_po(a4); - tec.create_po(a1); - - fiction::network_balancing_params ps; - ps.unify_outputs = true; - - const auto _b = fiction::network_balancing( - fiction::fanout_substitution(tec), ps); - - - const auto _b_topo = mockturtle::topo_view(_b); - const auto _b_rank = mockturtle::rank_view(_b); - - fiction::node_duplication_planarization_params dps; - dps.random_output_order = false; - - const auto planarized_b = fiction::node_duplication_planarization(_b, dps); - - fiction::debug::write_dot_network(tec, "tec_test"); - fiction::debug::write_dot_network(_b, "t_b"); - fiction::debug::write_dot_network(planarized_b, "network_b");*/ - - static constexpr const uint64_t bench_select = (fiction_experiments::iscas85); // fiction_experiments::iscas85 & ~ - // fiction_experiments::trindade16 | fiction_experiments::fontes18 | fiction_experiments::epfl | - // fiction_experiments::iscas85 static constexpr const uint64_t bench_select = + static constexpr const std::uint64_t bench_select = (fiction_experiments::trindade16 | fiction_experiments::fontes18); for (const auto& benchmark : fiction_experiments::all_benchmarks(bench_select)) { const auto benchmark_network = read_ntk(benchmark); @@ -233,42 +156,18 @@ int main() // NOLINT fiction::network_balancing_params ps; ps.unify_outputs = true; - bool cont = false; - benchmark_network.foreach_pi( - [&benchmark_network, &cont](auto pi) - { - if (benchmark_network.is_po(pi)) - { - cont = true; - std::cout << "Pi is Po\n"; - } - }); - if (cont) - { - continue; - } - - const auto _b = fiction::network_balancing( + const auto b = fiction::network_balancing( fiction::fanout_substitution(benchmark_network), ps); - if (_b.size() > 10000) - { - /*wiring_reduction_exp(benchmark, benchmark_network.num_pis(), 0, benchmark_network.num_pos(), - benchmark_network.num_gates(), _b.num_gates(), _b.num_gates(), 0, 0, "TEST"); - wiring_reduction_exp.save(); - wiring_reduction_exp.table();*/ - continue; - } - - const auto planarized_b = fiction::node_duplication_planarization(_b); + const auto planarized_b = fiction::node_duplication_planarization(b); const auto is_planar = fiction::check_planarity(planarized_b); if (planarized_b.size() > 20000) { wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), - benchmark_network.num_pos(), benchmark_network.num_gates(), _b.num_gates(), - planarized_b.num_gates(), is_planar, 0, 0); + benchmark_network.num_pos(), benchmark_network.num_gates(), b.num_gates(), + planarized_b.num_gates(), is_planar, false, false); wiring_reduction_exp.save(); wiring_reduction_exp.table(); continue; @@ -280,62 +179,29 @@ int main() // NOLINT *fiction::virtual_miter(benchmark_network, planarized_b), {}, &st); assert(cec_m.has_value()); - auto name = mockturtle::names_view(planarized_b); - - fiction::restore_names(benchmark_network, name); - - using gate_lyt = fiction::gate_level_layout< - fiction::clocked_layout>>>; - fiction::orthogonal_physical_design_stats stats{}; using gate_layout = fiction::gate_level_layout< fiction::clocked_layout>>>; - auto start = std::chrono::high_resolution_clock::now(); auto layout = fiction::orthogonal(planarized_b, {}, &stats); - auto stop = std::chrono::high_resolution_clock::now(); - - std::chrono::duration elapsed = stop - start; - - std::cout << "Time elapsed: " << elapsed.count() << " s\n"; - - std::cout << "X size : " << stats.x_size << "\n"; - std::cout << "Y size : " << stats.y_size << "\n"; - - std::cout << "PO benchmark : " << benchmark_network.num_pos() << "\n"; - std::cout << "PO planarized : " << planarized_b.num_pos() << "\n"; - std::cout << "PO layout : " << layout.num_pos() << "\n"; fiction::gate_level_drv_params ps_d{}; fiction::gate_level_drv_stats st_d{}; fiction::gate_level_drvs(layout, ps_d, &st_d); - /*fiction::equivalence_checking_stats eq_s_ortho{}; - // check equivalence - const auto eq_stats_ortho = - fiction::equivalence_checking(planarized_b, layout, &eq_s_ortho); - std::cout << "eq_checking gone\n"; - const std::string eq_result_ortho = eq_stats_ortho == fiction::eq_type::STRONG ? "STRONG" : - eq_stats_ortho == fiction::eq_type::WEAK ? "WEAK" : - "NO";*/ - const auto miter = mockturtle::miter(planarized_b, layout); - bool eq; + bool eq = false; if (miter) { - mockturtle::equivalence_checking_stats st; + mockturtle::equivalence_checking_stats st_o; - const auto ce = mockturtle::equivalence_checking(*miter, {}, &st); + const auto ce = mockturtle::equivalence_checking(*miter, {}, &st_o); eq = ce.value(); } - // fiction::debug::write_dot_layout(layout); - /*fiction::debug::write_dot_network(_b, "ntk_b"); - fiction::debug::write_dot_network(planarized_b, "ntk_p");*/ - // log results wiring_reduction_exp(benchmark, benchmark_network.num_pis(), planarized_b.num_virtual_pis(), - benchmark_network.num_pos(), benchmark_network.num_gates(), _b.num_gates(), + benchmark_network.num_pos(), benchmark_network.num_gates(), b.num_gates(), planarized_b.num_gates(), is_planar, cec_m.value(), eq); wiring_reduction_exp.save(); diff --git a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp index 513ac3150..1dc50ee07 100644 --- a/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp +++ b/include/fiction/algorithms/network_transformation/node_duplication_planarization.hpp @@ -5,18 +5,18 @@ #ifndef FICTION_NODE_DUPLICATION_PLANARIZATION_HPP #define FICTION_NODE_DUPLICATION_PLANARIZATION_HPP -#include "fiction/algorithms/properties/check_planarity_balanced.hpp" #include "fiction/networks/views/extended_rank_view.hpp" #include "fiction/networks/virtual_pi_network.hpp" #include +#include #include #include #include +#include #include #include -#include #include #include #include @@ -94,9 +94,9 @@ struct node_pair * @param node2 The second node of the fanin-edged node. * @param delayValue The delay value for the node. */ - node_pair(mockturtle::node node1, mockturtle::node node2, uint64_t delayValue) : + node_pair(mockturtle::node node1, mockturtle::node node2, uint64_t delay_value) : pair(node1, node2), - delay(delayValue), + delay(delay_value), fanin_pair(nullptr) {} }; diff --git a/libs/Catch2 b/libs/Catch2 index fa306fc85..bc63412e2 160000 --- a/libs/Catch2 +++ b/libs/Catch2 @@ -1 +1 @@ -Subproject commit fa306fc85eca7cc68a5362c503019fa823cbe411 +Subproject commit bc63412e2a3b3e39e178ea75953522f78b840aa7 diff --git a/libs/json b/libs/json index 960b763ec..b36f4c477 160000 --- a/libs/json +++ b/libs/json @@ -1 +1 @@ -Subproject commit 960b763ecd144f156d05ec61f577b04107290137 +Subproject commit b36f4c477c40356a0ae1204b567cca3c2a57d201 diff --git a/libs/mockturtle b/libs/mockturtle index 924c277bc..e55e2bbbe 160000 --- a/libs/mockturtle +++ b/libs/mockturtle @@ -1 +1 @@ -Subproject commit 924c277bc01900c9dc6d56fb6f2f4d100cab0806 +Subproject commit e55e2bbbef4648d311b97ae0907380190ebe8a29 diff --git a/libs/parallel-hashmap b/libs/parallel-hashmap index 8a889d369..63acc3336 160000 --- a/libs/parallel-hashmap +++ b/libs/parallel-hashmap @@ -1 +1 @@ -Subproject commit 8a889d3699b3c09ade435641fb034427f3fd12b6 +Subproject commit 63acc3336f941c6f324c88eb9ee4ce623a460cd5 diff --git a/libs/pybind11 b/libs/pybind11 index a1d00916b..ef5a9560b 160000 --- a/libs/pybind11 +++ b/libs/pybind11 @@ -1 +1 @@ -Subproject commit a1d00916b26b187e583f3bce39cd59c3b0652c32 +Subproject commit ef5a9560bb03efcac588888a825b7c7a0b8266cc diff --git a/libs/tinyxml2 b/libs/tinyxml2 index 8a519a556..374292e9b 160000 --- a/libs/tinyxml2 +++ b/libs/tinyxml2 @@ -1 +1 @@ -Subproject commit 8a519a556afecb3e717a4797615a8bfa49cae10a +Subproject commit 374292e9ba1549460f35d70411daba8b82bb2add From 089be08e2f1c91d397ae1779c197b5bd8954b5b6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:53:40 +0000 Subject: [PATCH 82/84] =?UTF-8?q?=F0=9F=8E=A8=20Incorporated=20pre-commit?= =?UTF-8?q?=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- experiments/legalization/legalization.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/experiments/legalization/legalization.cpp b/experiments/legalization/legalization.cpp index 59bf40c77..394ce1243 100644 --- a/experiments/legalization/legalization.cpp +++ b/experiments/legalization/legalization.cpp @@ -5,11 +5,11 @@ #include "experiments.hpp" #include "fiction/algorithms/network_transformation/fanout_substitution.hpp" #include "fiction/algorithms/properties/check_planarity_balanced.hpp" -#include "fiction/layouts/clocked_layout.hpp" #include "fiction/layouts/cartesian_layout.hpp" -#include "fiction/layouts/tile_based_layout.hpp" -#include "fiction/layouts/gate_level_layout.hpp" +#include "fiction/layouts/clocked_layout.hpp" #include "fiction/layouts/coordinates.hpp" +#include "fiction/layouts/gate_level_layout.hpp" +#include "fiction/layouts/tile_based_layout.hpp" #include "fiction_experiments.hpp" #include @@ -48,7 +48,8 @@ Ntk read_ntk(const std::string& name) int main() // NOLINT { - experiments::experiment + experiments::experiment wiring_reduction_exp{"planarization", "benchmark", "inputs", "virt_inputs", "outputs", "initial nodes", "nodes buffered", "nodes planarized", "is_planar", "equivalent(ntk)", "equivalent(lyt)"}; @@ -128,12 +129,12 @@ int main() // NOLINT auto layout = fiction::orthogonal(planarized_b, {}, &stats); const fiction::gate_level_drv_params ps_d{}; - fiction::gate_level_drv_stats st_d{}; + fiction::gate_level_drv_stats st_d{}; fiction::gate_level_drvs(layout, ps_d, &st_d); const auto miter = mockturtle::miter(planarized_b, layout); - bool eq = false; + bool eq = false; if (miter) { mockturtle::equivalence_checking_stats st_o; @@ -148,7 +149,8 @@ int main() // NOLINT wiring_reduction_exp.table(); } - static constexpr const std::uint64_t bench_select = (fiction_experiments::trindade16 | fiction_experiments::fontes18); + static constexpr const std::uint64_t bench_select = + (fiction_experiments::trindade16 | fiction_experiments::fontes18); for (const auto& benchmark : fiction_experiments::all_benchmarks(bench_select)) { const auto benchmark_network = read_ntk(benchmark); @@ -190,7 +192,7 @@ int main() // NOLINT fiction::gate_level_drvs(layout, ps_d, &st_d); const auto miter = mockturtle::miter(planarized_b, layout); - bool eq = false; + bool eq = false; if (miter) { mockturtle::equivalence_checking_stats st_o; From b4df1c6432157c2a5576b0b6554ee992bc20e6c7 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 15 Oct 2024 15:18:09 +0200 Subject: [PATCH 83/84] submodules checked --- libs/Catch2 | 2 +- libs/parallel-hashmap | 2 +- libs/pybind11 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/Catch2 b/libs/Catch2 index bc63412e2..fa43b7742 160000 --- a/libs/Catch2 +++ b/libs/Catch2 @@ -1 +1 @@ -Subproject commit bc63412e2a3b3e39e178ea75953522f78b840aa7 +Subproject commit fa43b77429ba76c462b1898d6cd2f2d7a9416b14 diff --git a/libs/parallel-hashmap b/libs/parallel-hashmap index 63acc3336..60acfa469 160000 --- a/libs/parallel-hashmap +++ b/libs/parallel-hashmap @@ -1 +1 @@ -Subproject commit 63acc3336f941c6f324c88eb9ee4ce623a460cd5 +Subproject commit 60acfa4690303eeefde355175eaaad57c65a113d diff --git a/libs/pybind11 b/libs/pybind11 index ef5a9560b..7e418f492 160000 --- a/libs/pybind11 +++ b/libs/pybind11 @@ -1 +1 @@ -Subproject commit ef5a9560bb03efcac588888a825b7c7a0b8266cc +Subproject commit 7e418f49243bb7d13fa92cf2634af1eeac386465 From df3b9f859e896f0e8f92fc331ba534c6994a6308 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 3 Dec 2024 14:05:38 +0000 Subject: [PATCH 84/84] :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions --- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 380 ++++++++++++++++++ 1 file changed, 380 insertions(+) diff --git a/bindings/mnt/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/mnt/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index 2f8cdd768..21f42df17 100644 --- a/bindings/mnt/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/mnt/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -2347,6 +2347,54 @@ Template parameter ``Dist``: static const char *__doc_fiction_chebyshev_distance_functor_chebyshev_distance_functor = R"doc()doc"; +static const char *__doc_fiction_check_planarity = +R"doc(Checks if a logic network is planar for a network that is path +balanced and has ranks assigned. + +If the network is not balanced, an exception is thrown. To balance the +network, insert buffers to divide multi-level edges. + +It checks if the network represented by the variable `ntk` is planar. +The network is planar if, for any edge with starting point :math:`m` +and endpoint :math:`n` (represented by the node ranks), there is never +another edge with starting point :math:`m' > m` and endpoint :math:`n' +< n`, or vice versa. When iterating through the ranks of one level, +the endpoints are always increasing. Therefore, only the starting +points need to be checked. Thus, the highest connected starting point +in the fan-in gives a border :math:`m_{\text{max}}` for every +subsequent edge. + +Template parameter ``Ntk``: + Logic network type. + +Parameter ``ntk``: + The logic network to check for planarity. + +Returns: + `true` if the network is planar, `false` otherwise.)doc"; + +static const char *__doc_fiction_check_planarity_impl = R"doc()doc"; + +static const char *__doc_fiction_check_planarity_impl_check_planarity_impl = R"doc()doc"; + +static const char *__doc_fiction_check_planarity_impl_ntk = R"doc()doc"; + +static const char *__doc_fiction_check_planarity_impl_run = +R"doc(Checks if a given network is planar. + +This function checks if the network represented by the variable `ntk` +is planar. The network is planar if, for any edge with starting point +:math:`m` and endpoint :math:`n` (represented by the node ranks), +there is never another edge with starting point :math:`m' > m` and +endpoint :math:`n' < n`, or vice versa. When iterating through the +ranks of one level, the endpoints are always increasing. Therefore, +only the starting points need to be checked. Thus, the highest +connected starting point in the fan-in gives a border +:math:`m_{\text{max}}` for every subsequent edge. + +Returns: + `true` if the network is planar, `false` otherwise.)doc"; + static const char *__doc_fiction_check_simulation_results_for_equivalence = R"doc(This function compares two SiDB simulation results for equivalence. Two results are considered equivalent if they have the same number of @@ -3761,6 +3809,20 @@ Parameter ``neutral_defect_spacing_overwrite``: A pair of uint16_t values representing the number of horizontal and vertical SiDBs affected by the given defect type.)doc"; +static const char *__doc_fiction_delete_virtual_pis = +R"doc(Deletes virtual primary inputs from a network. This can mainly be used +for equivalence checking. If the network does not have any virtual PIs +stored, the network is returned. + +Template parameter ``Ntk``: + The type of network. + +Parameter ``ntk``: + The input network. + +Returns: + The resulting network after virtual primary inputs are deleted.)doc"; + static const char *__doc_fiction_dependent_cell_mode = R"doc(An enumeration of modes for the dependent cell.)doc"; static const char *__doc_fiction_dependent_cell_mode_FIXED = @@ -4583,6 +4645,16 @@ Parameter ``bdl_iterator``: static const char *__doc_fiction_detail_critical_temperature_impl_stats = R"doc(Statistics.)doc"; +static const char *__doc_fiction_detail_delete_virtual_pis_impl = R"doc()doc"; + +static const char *__doc_fiction_detail_delete_virtual_pis_impl_delete_virtual_pis_impl = R"doc()doc"; + +static const char *__doc_fiction_detail_delete_virtual_pis_impl_ntk = R"doc()doc"; + +static const char *__doc_fiction_detail_delete_virtual_pis_impl_ntk_topo = R"doc()doc"; + +static const char *__doc_fiction_detail_delete_virtual_pis_impl_run = R"doc()doc"; + static const char *__doc_fiction_detail_delete_wires = R"doc(This function deletes wires from the provided `wiring_reduction_layout` based on the specified coordinates and @@ -7214,6 +7286,39 @@ static const char *__doc_fiction_detail_new_gate_location_NONE = R"doc(Do not ch static const char *__doc_fiction_detail_new_gate_location_SRC = R"doc(Check if the source tile is empty.)doc"; +static const char *__doc_fiction_detail_node_pair = +R"doc(A structure representing a pair of nodes in an H-graph. + +The nodes stored in this struct describe the fanin-edges of a node in +an H-graph. A node pair object holds two nodes, which are saved in the +member 'pair'. These two outer nodes are connected through zero or +more 'middle_nodes'. The fanin order starts with the first node in +'pair', then proceeds through the 'middle_nodes', and ends with the +second node in 'pair'. The order of 'middle_nodes' is arbitrary as +they cannot be further connected to any other nodes. For the +planarization, only the nodes inside the 'pair' are relevant. + +Template parameter ``Ntk``: + Network type for the nodes in the pair.)doc"; + +static const char *__doc_fiction_detail_node_pair_delay = R"doc(Specifies the delay value for the node.)doc"; + +static const char *__doc_fiction_detail_node_pair_fanin_pair = +R"doc(Shared pointer to another instance of node_pair detailing fanin-edge +alignment.)doc"; + +static const char *__doc_fiction_detail_node_pair_node_pair = +R"doc(Standard constructor. + +Parameter ``node1``: + The first node of the fanin-edged node. + +Parameter ``node2``: + The second node of the fanin-edged node. + +Parameter ``delayValue``: + The delay value for the node.)doc"; + static const char *__doc_fiction_detail_non_operationality_reason = R"doc(Reason why a layout is non-operational.)doc"; static const char *__doc_fiction_detail_non_operationality_reason_KINKS = R"doc(Kinks induced the layout to become non-operational.)doc"; @@ -10128,6 +10233,32 @@ Parameter ``ps``: Returns: sidb_simulation_result is returned with all results.)doc"; +static const char *__doc_fiction_extended_rank_view = +R"doc(@class extended_rank_view + +If already a rank_interface exists only the depth_view constructor +gets called. + +Template parameter ``Ntk``: + The network type.)doc"; + +static const char *__doc_fiction_extended_rank_view_2 = +R"doc(Deduction guide for `extended_rank_view' + +Template parameter ``T``: + Network type deduced from the construction context of + `extended_rank_view`.)doc"; + +static const char *__doc_fiction_extended_rank_view_3 = +R"doc(Deduction guide for `extended_rank_view` with two constructor +arguments + +Template parameter ``T``: + Network type deduced from the construction context of + `extended_rank_view`.)doc"; + +static const char *__doc_fiction_extended_rank_view_extended_rank_view = R"doc()doc"; + static const char *__doc_fiction_extract_routing_objectives = R"doc(Extracts all routing objectives from the given layout. To this end, all routing paths in the layout are traversed, starting at each PI. @@ -12373,6 +12504,8 @@ Parameter ``m``: static const char *__doc_fiction_gray_code_iterator_start_number = R"doc(Start number of the iteration.)doc"; +static const char *__doc_fiction_handle_virtual_pis = R"doc()doc"; + static const char *__doc_fiction_has_above = R"doc()doc"; static const char *__doc_fiction_has_assign_charge_state = R"doc()doc"; @@ -12405,6 +12538,8 @@ static const char *__doc_fiction_has_foreach_incoming_clocked_zone = R"doc()doc" static const char *__doc_fiction_has_foreach_outgoing_clocked_zone = R"doc()doc"; +static const char *__doc_fiction_has_foreach_real_pi = R"doc()doc"; + static const char *__doc_fiction_has_foreach_sidb_defect = R"doc()doc"; static const char *__doc_fiction_has_foreach_tile = R"doc()doc"; @@ -12417,6 +12552,8 @@ static const char *__doc_fiction_has_get_gate_ports = R"doc()doc"; static const char *__doc_fiction_has_get_layout_name = R"doc()doc"; +static const char *__doc_fiction_has_get_real_pi = R"doc()doc"; + static const char *__doc_fiction_has_get_sidb_defect = R"doc()doc"; static const char *__doc_fiction_has_high_degree_fanin_nodes = @@ -12513,10 +12650,16 @@ static const char *__doc_fiction_has_north_east = R"doc()doc"; static const char *__doc_fiction_has_north_west = R"doc()doc"; +static const char *__doc_fiction_has_num_real_pis = R"doc()doc"; + +static const char *__doc_fiction_has_num_virtual_pis = R"doc()doc"; + static const char *__doc_fiction_has_ordinal_operations = R"doc()doc"; static const char *__doc_fiction_has_post_layout_optimization = R"doc()doc"; +static const char *__doc_fiction_has_remove_virtual_input_nodes = R"doc()doc"; + static const char *__doc_fiction_has_set_layout_name = R"doc()doc"; static const char *__doc_fiction_has_south = R"doc()doc"; @@ -14181,6 +14324,52 @@ Parameter ``file``: Parameter ``rfun``: The actual parsing function.)doc"; +static const char *__doc_fiction_node_duplication_planarization = +R"doc(Implements a planarization mechanism for networks using a H-Graph +strategy for node duplication. + +The planarization achieved by this function solves the Node +Duplication Crossing Minimization (NDCE) problem by finding the +shortest x-y path in the H-graph for every level in the network. An +H-graph describes edge relations between two levels in a network, with +one level assumed as fixed, starting at the Primary Outputs (POs). By +finding the shortest path from the source (x) to the sink (y) in this +H-graph, an optimal solution for the NDCE problem for each level is +found. The function constructs an H-graph that captures edge relations +between two levels within the graph and computes the shortest x-y +paths on the H-graph, traversing from the POs towards the Primary +Inputs (PIs). + +Returns: + A view of the planarized virtual_pi_network created in the format + of extended_rank_view. + +Template parameter ``NtkDest``: + Destination network type. + +Template parameter ``NtkSrc``: + Source network type. + +Parameter ``ntk_src``: + Source network to be utilized for the planarization. + +Parameter ``ps``: + Node duplication parameters used in the computation.)doc"; + +static const char *__doc_fiction_node_duplication_planarization_params = R"doc(Parameters for the node duplication algorithm.)doc"; + +static const char *__doc_fiction_node_duplication_planarization_params_output_order = +R"doc(The output order determines the starting layer for this algorithm. If +this option is turned off, the output order remains the same as in the +provided network. If it is turned on, the outputs are ordered +randomly.)doc"; + +static const char *__doc_fiction_node_duplication_planarization_params_output_order_KEEP_PO_ORDER = R"doc(Keep the PO order from the input network.)doc"; + +static const char *__doc_fiction_node_duplication_planarization_params_output_order_RANDOM_PO_ORDER = R"doc(Randomize the PO order.)doc"; + +static const char *__doc_fiction_node_duplication_planarization_params_po_order = R"doc()doc"; + static const char *__doc_fiction_normalize_layout_coordinates = R"doc(A new layout is constructed and returned that is equivalent to the given cell-level layout. However, its coordinates are normalized, @@ -18405,6 +18594,197 @@ static const char *__doc_fiction_vertical_shift_cartesian = R"doc(\verbatim +-------+ | | | +-------+ | | | +-------+ | | | +-------+ \endverbatim)doc"; +static const char *__doc_fiction_virtual_miter = +R"doc(This method combines two networks to a combinational miter like a +mockturtle::miter. Additionally, either of the input networks can be a +network with virtual inputs, which are duplicated PIs. In this case +the duplicated PIs are deleted and all edges connecting to them are +remapped on their originating PI. + +Therefore, the miter has the same number of inputs and one primary +output. This output is the OR of XORs of all primary output pairs. In +other words, the miter outputs 1 for all input assignments in which +the two input networks differ. + +All networks may have different types. The method returns an optional, +which is `nullopt`, whenever the two input networks don't match in +their number of primary inputs and primary outputs.)doc"; + +static const char *__doc_fiction_virtual_pi_network = R"doc()doc"; + +static const char *__doc_fiction_virtual_pi_network_clone = R"doc(Clones the virtual_pi_network object.)doc"; + +static const char *__doc_fiction_virtual_pi_network_create_virtual_pi = +R"doc(Create a virtual PI, which is a mapping to a real PI. + +This function creates a virtual PI mapping to a real PI in the +network. It adds a PI to the underlying network, but marks it as +virtual and stores a mapping to a real PI. + +Parameter ``real_pi``: + The node representing the real PI in the network. + +Returns: + The signal of the newly created virtual PI.)doc"; + +static const char *__doc_fiction_virtual_pi_network_foreach_real_ci = +R"doc(Iterates over the virtual CIs of the circuit and applies a given +function. + +Template parameter ``Fn``: + The type of the function to be applied. + +Parameter ``fn``: + The function to be applied.)doc"; + +static const char *__doc_fiction_virtual_pi_network_foreach_real_pi = +R"doc(Iterates over the real PIs of the circuit and applies a given +function. + +Template parameter ``Fn``: + The type of the function. + +Parameter ``fn``: + The function to be applied to each primary input.)doc"; + +static const char *__doc_fiction_virtual_pi_network_foreach_virtual_ci = +R"doc(Iterates over the virtual CIs of the circuit and applies a given +function. + +Template parameter ``Fn``: + The type of the function. + +Parameter ``fn``: + The function to be applied to each primary input.)doc"; + +static const char *__doc_fiction_virtual_pi_network_foreach_virtual_pi = +R"doc(Iterates over the virtual PIs of the circuit and applies a given +function. + +Template parameter ``Fn``: + The type of the function. + +Parameter ``fn``: + The function to be applied to each primary input.)doc"; + +static const char *__doc_fiction_virtual_pi_network_get_real_pi = +R"doc(Get the real PI associated with a virtual PI node. + +Parameter ``v_pi``: + The virtual pi node to retrieve the real pi for. + +Returns: + The real pi associated with the virtual pi node.)doc"; + +static const char *__doc_fiction_virtual_pi_network_is_real_ci = +R"doc(Check if a given node is a real CI in the virtual_pi_network. + +Parameter ``n``: + The node to check. + +Returns: + True if the node is a real CI, false otherwise.)doc"; + +static const char *__doc_fiction_virtual_pi_network_is_real_pi = +R"doc(Check if a given node is a real PI. Real PIs are created with +create_pi(). + +Parameter ``n``: + The node to check. + +Returns: + True if the node is a real PI, false otherwise.)doc"; + +static const char *__doc_fiction_virtual_pi_network_is_virtual_ci = +R"doc(Check if a given node is a virtual CI in the virtual_pi_network. + +Parameter ``n``: + The node to check. + +Returns: + True if the node is a virtual CI, false otherwise.)doc"; + +static const char *__doc_fiction_virtual_pi_network_is_virtual_pi = +R"doc(Check if a given node is a virtual PI. Virtual PIs are created with +create_virtual_pi(). + +Parameter ``n``: + The node to check. + +Returns: + True if the node is a virtual PI, false otherwise.)doc"; + +static const char *__doc_fiction_virtual_pi_network_num_real_cis = +R"doc(Get the number of real CIs in the virtual_pi_network. + +Returns: + The number of real CIs as a uint32_t.)doc"; + +static const char *__doc_fiction_virtual_pi_network_num_real_pis = +R"doc(Get the number of real PIs in the virtual_pi_network. + +Returns: + The number of real PIs as a uint32_t.)doc"; + +static const char *__doc_fiction_virtual_pi_network_num_virtual_cis = +R"doc(Get the number of virtual CIs in the virtual_pi_network. + +Returns: + The number of virtual CIs as a uint32_t.)doc"; + +static const char *__doc_fiction_virtual_pi_network_num_virtual_pis = +R"doc(Get the number of virtual PIs in the virtual_pi_network. + +Returns: + The number of virtual PIs as a uint32_t.)doc"; + +static const char *__doc_fiction_virtual_pi_network_real_size = +R"doc(Calculate the real size of the virtual_pi_network. + +The real size of the network is considered the size without virtual +PIs. + +Returns: + The real size of the virtual_pi_network as a uint32_t.)doc"; + +static const char *__doc_fiction_virtual_pi_network_v_storage = R"doc(Shared pointer of the virtual PI storage.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network = +R"doc(Default constructor for the `virtual_pi_network` class. Initializes +`v_storage` as a shared pointer.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_2 = +R"doc(Constructor for the `virtual_pi_network` class that takes a network as +input. It adds the functionalities of the `virtual_pi_network` class +on top of the network. + +Template parameter ``Ntk``: + Network type. + +Parameter ``ntk``: + Input network.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_pi_network_3 = +R"doc(Constructor for the `virtual_pi_network` class that takes a network +and a shared pointer to a `virtual_storage` object. THis is used for +cloning. + +Template parameter ``Ntk``: + Network type. + +Parameter ``ntk``: + Input network. + +Parameter ``s``: + Shared pointer to the `virtual_storage` object to be used by this + `virtual_pi_network`.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_storage = R"doc()doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_storage_map_virt_to_real_pi = R"doc(Map from virtual_pis to real_pis.)doc"; + +static const char *__doc_fiction_virtual_pi_network_virtual_storage_virtual_inputs = R"doc(Vector storing virtual_inputs.)doc"; + static const char *__doc_fiction_volume = R"doc(Computes the volume of a given coordinate assuming its origin is (0, 0, 0). Calculates :math:`(|x| + 1) \cdot (|y| + 1) \cdot (|z| + 1)` by