Skip to content

Commit

Permalink
Merge pull request #23 from marcelwa/depth-network
Browse files Browse the repository at this point in the history
✨ Depth AIG for level computation
  • Loading branch information
marcelwa authored Oct 14, 2024
2 parents 7821861 + 0ad678d commit 7bd2ef1
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 29 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
#ifndef AIGVERSE_EQUIVALENCE_CHECKING_HPP
#define AIGVERSE_EQUIVALENCE_CHECKING_HPP

#include <fmt/format.h>
#include <lorina/aiger.hpp>
#include <lorina/diagnostics.hpp>
#include <mockturtle/algorithms/equivalence_checking.hpp>
#include <mockturtle/algorithms/miter.hpp>
Expand All @@ -17,7 +15,6 @@
#include <cstdint>
#include <optional>
#include <stdexcept>
#include <string>

namespace aigverse
{
Expand Down
2 changes: 0 additions & 2 deletions bindings/aigverse/include/aigverse/algorithms/refactoring.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@
#ifndef AIGVERSE_REFACTORING_HPP
#define AIGVERSE_REFACTORING_HPP

#include <fmt/format.h>
#include <mockturtle/algorithms/cleanup.hpp>
#include <mockturtle/algorithms/node_resynthesis/sop_factoring.hpp>
#include <mockturtle/algorithms/refactoring.hpp>
#include <mockturtle/networks/aig.hpp>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include <cstdint>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@
#ifndef AIGVERSE_RESUBSTITUTION_HPP
#define AIGVERSE_RESUBSTITUTION_HPP

#include <fmt/format.h>
#include <mockturtle/algorithms/aig_resub.hpp>
#include <mockturtle/algorithms/cleanup.hpp>
#include <mockturtle/algorithms/resubstitution.hpp>
#include <mockturtle/networks/aig.hpp>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include <cstdint>

Expand Down
6 changes: 2 additions & 4 deletions bindings/aigverse/include/aigverse/algorithms/rewriting.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@
#ifndef AIGVERSE_REWRITING_HPP
#define AIGVERSE_REWRITING_HPP

#include <fmt/format.h>
#include <mockturtle/algorithms/cleanup.hpp>
#include <mockturtle/algorithms/cut_rewriting.hpp>
#include <mockturtle/algorithms/node_resynthesis/xag_npn.hpp>
#include <mockturtle/networks/aig.hpp>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include <cstdint>
#include <optional>
Expand Down Expand Up @@ -46,7 +43,8 @@ void rewriting(pybind11::module& m)
params.verbose = verbose;
params.very_verbose = very_verbose;

mockturtle::xag_npn_resynthesis<Ntk, mockturtle::aig_network, mockturtle::xag_npn_db_kind::aig_complete>
const mockturtle::xag_npn_resynthesis<Ntk, mockturtle::aig_network,
mockturtle::xag_npn_db_kind::aig_complete>
aig_npn_resyn_engine{};

ntk = mockturtle::cut_rewriting(ntk, aig_npn_resyn_engine, params);
Expand Down
1 change: 0 additions & 1 deletion bindings/aigverse/include/aigverse/io/write_aiger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#define AIGVERSE_WRITE_AIGER_HPP

#include <fmt/format.h>
#include <lorina/aiger.hpp>
#include <mockturtle/io/write_aiger.hpp>
#include <mockturtle/networks/aig.hpp>
#include <pybind11/pybind11.h>
Expand Down
24 changes: 17 additions & 7 deletions bindings/aigverse/include/aigverse/networks/logic_networks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -220,6 +213,23 @@ void network(pybind11::module& m, const std::string& network_name)
"is_nary_or", [](const Ntk& ntk, const mockturtle::node<Ntk>& n) { return ntk.is_nary_or(n); }, "n"_a)

;

/**
* Depth Network.
*/
using DepthNtk = mockturtle::depth_view<Ntk>;
py::class_<DepthNtk, Ntk>(m, fmt::format("Depth{}", network_name).c_str())
.def(py::init<>())
.def(py::init<const Ntk&>(), "ntk"_a)
.def(py::init<const DepthNtk&>(), "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
Expand Down
55 changes: 48 additions & 7 deletions bindings/aigverse/test/networks/test_aig.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,28 +290,21 @@ 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'))

# Create two primary inputs
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)
Expand Down Expand Up @@ -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()
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.',
Expand Down

0 comments on commit 7bd2ef1

Please sign in to comment.