Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Depth AIG for level computation #23

Merged
merged 6 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading