From bc971c0173e2f850e676055e43c159d2a2794b97 Mon Sep 17 00:00:00 2001 From: Marcel Walter Date: Mon, 14 Oct 2024 19:08:58 +0200 Subject: [PATCH 1/4] :art: Removed unused includes --- .../include/aigverse/algorithms/equivalence_checking.hpp | 3 --- bindings/aigverse/include/aigverse/algorithms/refactoring.hpp | 2 -- .../aigverse/include/aigverse/algorithms/resubstitution.hpp | 2 -- bindings/aigverse/include/aigverse/io/write_aiger.hpp | 1 - 4 files changed, 8 deletions(-) diff --git a/bindings/aigverse/include/aigverse/algorithms/equivalence_checking.hpp b/bindings/aigverse/include/aigverse/algorithms/equivalence_checking.hpp index 34983f4..f00f3cb 100644 --- a/bindings/aigverse/include/aigverse/algorithms/equivalence_checking.hpp +++ b/bindings/aigverse/include/aigverse/algorithms/equivalence_checking.hpp @@ -5,8 +5,6 @@ #ifndef AIGVERSE_EQUIVALENCE_CHECKING_HPP #define AIGVERSE_EQUIVALENCE_CHECKING_HPP -#include -#include #include #include #include @@ -17,7 +15,6 @@ #include #include #include -#include namespace aigverse { diff --git a/bindings/aigverse/include/aigverse/algorithms/refactoring.hpp b/bindings/aigverse/include/aigverse/algorithms/refactoring.hpp index ad62efc..5aa8ddb 100644 --- a/bindings/aigverse/include/aigverse/algorithms/refactoring.hpp +++ b/bindings/aigverse/include/aigverse/algorithms/refactoring.hpp @@ -5,13 +5,11 @@ #ifndef AIGVERSE_REFACTORING_HPP #define AIGVERSE_REFACTORING_HPP -#include #include #include #include #include #include -#include #include diff --git a/bindings/aigverse/include/aigverse/algorithms/resubstitution.hpp b/bindings/aigverse/include/aigverse/algorithms/resubstitution.hpp index 60c568d..e3fd425 100644 --- a/bindings/aigverse/include/aigverse/algorithms/resubstitution.hpp +++ b/bindings/aigverse/include/aigverse/algorithms/resubstitution.hpp @@ -5,13 +5,11 @@ #ifndef AIGVERSE_RESUBSTITUTION_HPP #define AIGVERSE_RESUBSTITUTION_HPP -#include #include #include #include #include #include -#include #include diff --git a/bindings/aigverse/include/aigverse/io/write_aiger.hpp b/bindings/aigverse/include/aigverse/io/write_aiger.hpp index b08df15..7b96171 100644 --- a/bindings/aigverse/include/aigverse/io/write_aiger.hpp +++ b/bindings/aigverse/include/aigverse/io/write_aiger.hpp @@ -6,7 +6,6 @@ #define AIGVERSE_WRITE_AIGER_HPP #include -#include #include #include #include From 4cd31ab06fbed9b163260d02257390a249a789a5 Mon Sep 17 00:00:00 2001 From: Marcel Walter Date: Mon, 14 Oct 2024 19:33:25 +0200 Subject: [PATCH 2/4] :art: Removed unused includes --- bindings/aigverse/include/aigverse/algorithms/rewriting.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bindings/aigverse/include/aigverse/algorithms/rewriting.hpp b/bindings/aigverse/include/aigverse/algorithms/rewriting.hpp index 8a3de74..ffa4555 100644 --- a/bindings/aigverse/include/aigverse/algorithms/rewriting.hpp +++ b/bindings/aigverse/include/aigverse/algorithms/rewriting.hpp @@ -5,13 +5,10 @@ #ifndef AIGVERSE_REWRITING_HPP #define AIGVERSE_REWRITING_HPP -#include -#include #include #include #include #include -#include #include #include @@ -46,7 +43,8 @@ void rewriting(pybind11::module& m) params.verbose = verbose; params.very_verbose = very_verbose; - mockturtle::xag_npn_resynthesis + const mockturtle::xag_npn_resynthesis aig_npn_resyn_engine{}; ntk = mockturtle::cut_rewriting(ntk, aig_npn_resyn_engine, params); From 99dd7389943dc2f304755c6590d47e764208f5d9 Mon Sep 17 00:00:00 2001 From: Marcel Walter Date: Mon, 14 Oct 2024 19:43:43 +0200 Subject: [PATCH 3/4] :sparkles: Introduce `DepthAig` for level computation --- README.md | 14 +++++ .../aigverse/networks/logic_networks.hpp | 24 +++++--- bindings/aigverse/test/networks/test_aig.py | 55 ++++++++++++++++--- 3 files changed, 79 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 7a1445d..fcd3993 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,20 @@ for fanin in aig.fanins(f_and): print(f"Fanin of {f_and}: {fanin}") ``` +### Depth and Level Computation + +You can compute the depth of the AIG network and the level of each node. Depth information is useful for estimating the +critical path delay of a respective circuit. + +```python +from aigverse import DepthAig + +depth_aig = DepthAig(aig) +print(f"Depth: {depth_aig.num_levels()}") +for node in aig.nodes(): + print(f"Level of {node}: {depth_aig.level(node)}") +``` + ### Logic Optimization You can optimize AIGs using various algorithms. For example, you can perform resubstitution to simplify logic using diff --git a/bindings/aigverse/include/aigverse/networks/logic_networks.hpp b/bindings/aigverse/include/aigverse/networks/logic_networks.hpp index 5fae99e..17c4699 100644 --- a/bindings/aigverse/include/aigverse/networks/logic_networks.hpp +++ b/bindings/aigverse/include/aigverse/networks/logic_networks.hpp @@ -83,13 +83,6 @@ void network(pybind11::module& m, const std::string& network_name) .def("num_pos", &Ntk::num_pos) .def("num_cos", &Ntk::num_cos) - .def("num_levels", - [](const Ntk& ntk) -> uint32_t - { - mockturtle::depth_view depth_ntk{ntk}; - return depth_ntk.depth(); - }) - .def("get_node", &Ntk::get_node, "s"_a) .def("make_signal", &Ntk::make_signal, "n"_a) .def("is_complemented", &Ntk::is_complemented, "s"_a) @@ -220,6 +213,23 @@ void network(pybind11::module& m, const std::string& network_name) "is_nary_or", [](const Ntk& ntk, const mockturtle::node& n) { return ntk.is_nary_or(n); }, "n"_a) ; + + /** + * Depth Network. + */ + using DepthNtk = mockturtle::depth_view; + py::class_(m, fmt::format("Depth{}", network_name).c_str()) + .def(py::init<>()) + .def(py::init(), "ntk"_a) + .def(py::init(), "ntk"_a) + + .def("num_levels", &DepthNtk::depth) + .def("level", &DepthNtk::level, "n"_a) + .def("is_on_critical_path", &DepthNtk::is_on_critical_path, "n"_a) + .def("update_levels", &DepthNtk::update_levels) + .def("create_po", &DepthNtk::create_po, "f"_a) + + ; } } // namespace detail diff --git a/bindings/aigverse/test/networks/test_aig.py b/bindings/aigverse/test/networks/test_aig.py index 5477703..847f1f9 100644 --- a/bindings/aigverse/test/networks/test_aig.py +++ b/bindings/aigverse/test/networks/test_aig.py @@ -290,7 +290,6 @@ def test_aig_structural_properties(self): self.assertTrue(hasattr(aig, 'num_pis')) self.assertTrue(hasattr(aig, 'num_pos')) self.assertTrue(hasattr(aig, 'num_gates')) - self.assertTrue(hasattr(aig, 'num_levels')) self.assertTrue(hasattr(aig, 'fanin_size')) self.assertTrue(hasattr(aig, 'fanout_size')) @@ -298,20 +297,14 @@ def test_aig_structural_properties(self): x1 = aig.create_pi() x2 = aig.create_pi() - self.assertEqual(aig.num_levels(), 0) - # Create AND and OR gates f1 = aig.create_and(x1, x2) f2 = aig.create_or(x1, x2) - self.assertEqual(aig.num_levels(), 0) - # Create primary outputs aig.create_po(f1) aig.create_po(f2) - self.assertEqual(aig.num_levels(), 1) - # Check structural properties self.assertEqual(aig.size(), 5) self.assertEqual(aig.num_pis(), 2) @@ -527,5 +520,53 @@ def test_aig_node_signal_iteration(self): self.assertEqual(mask, 2) +class TestDepthAig(unittest.TestCase): + def test_depth_aig(self): + aig = DepthAig() + + self.assertTrue(hasattr(aig, 'num_levels')) + self.assertTrue(hasattr(aig, 'level')) + self.assertTrue(hasattr(aig, 'is_on_critical_path')) + self.assertTrue(hasattr(aig, 'update_levels')) + self.assertTrue(hasattr(aig, 'create_po')) + + # Create primary inputs + x1 = aig.create_pi() + x2 = aig.create_pi() + x3 = aig.create_pi() + + self.assertEqual(aig.num_levels(), 0) + + # Create AND gates + n4 = aig.create_and(~x1, x2) + n5 = aig.create_and(x1, n4) + n6 = aig.create_and(x3, n5) + n7 = aig.create_and(n4, x2) + n8 = aig.create_and(~n5, ~n7) + n9 = aig.create_and(~n8, n4) + + # Create primary outputs + aig.create_po(n6) + aig.create_po(n9) + + # Check the depth of the AIG + self.assertEqual(aig.num_levels(), 4) + + self.assertEqual(aig.level(aig.get_node(x1)), 0) + self.assertEqual(aig.level(aig.get_node(x2)), 0) + self.assertEqual(aig.level(aig.get_node(x3)), 0) + self.assertEqual(aig.level(aig.get_node(n4)), 1) + self.assertEqual(aig.level(aig.get_node(n5)), 2) + self.assertEqual(aig.level(aig.get_node(n6)), 3) + self.assertEqual(aig.level(aig.get_node(n7)), 2) + self.assertEqual(aig.level(aig.get_node(n8)), 3) + self.assertEqual(aig.level(aig.get_node(n9)), 4) + + # Copy constructor + aig2 = DepthAig(aig) + + self.assertEqual(aig2.num_levels(), 4) + + if __name__ == '__main__': unittest.main() From ce7dd6378b220a50a403cf004b1c9cfe2d644abb Mon Sep 17 00:00:00 2001 From: Marcel Walter Date: Mon, 14 Oct 2024 19:46:10 +0200 Subject: [PATCH 4/4] :bookmark: Bump version to 0.0.9 --- CMakeLists.txt | 2 +- pyproject.toml | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a492667..ebc35b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ set(CMAKE_CXX_EXTENSIONS OFF) # Set the project name and version project( aigverse - VERSION 0.0.8 + VERSION 0.0.9 DESCRIPTION "A Python library for working with logic networks, synthesis, and optimization." HOMEPAGE_URL "https://github.com/marcelwa/aigverse" diff --git a/pyproject.toml b/pyproject.toml index c8950d6..3f97048 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "aigverse" -version = "0.0.8" +version = "0.0.9" description = "A Python library for working with logic networks, synthesis, and optimization." readme = "README.md" authors = [ diff --git a/setup.py b/setup.py index 0f269dd..20b5ec3 100644 --- a/setup.py +++ b/setup.py @@ -83,7 +83,7 @@ def build_extension(self, ext): setup( name='aigverse', - version='0.0.8', + version='0.0.9', author='Marcel Walter', author_email='marcel.walter@tum.de', description='A Python library for working with logic networks, synthesis, and optimization.',