[Python] Add Python bindings for AIG dialect (#8646)

This commit adds comprehensive Python bindings for the AIG (And-Inverter Graph) dialect.

The implementation includes an AIG C API header with dialect registration and an AIG C API implementation with pass registration.
It adds an AIG Python dialect TableGen file and Python dialect module. The AIG Python module C++ bindings are implemented using nanobind.

The implementation follows the pattern used by other CIRCT dialects
and enables Python users to work with AIG operations like and_inv through the
circt.dialects.aig module.
This commit is contained in:
Hideto Ueno 2025-07-03 09:04:50 -07:00 committed by GitHub
parent f2e5637ba0
commit 8fbefed670
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 150 additions and 0 deletions

View File

@ -0,0 +1,25 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_C_DIALECT_AIG_H
#define CIRCT_C_DIALECT_AIG_H
#include "mlir-c/IR.h"
#ifdef __cplusplus
extern "C" {
#endif
MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(AIG, aig);
MLIR_CAPI_EXPORTED void registerAIGPasses(void);
#ifdef __cplusplus
}
#endif
#endif // CIRCT_C_DIALECT_AIG_H

View File

@ -0,0 +1,32 @@
# REQUIRES: bindings_python
# RUN: %PYTHON% %s | FileCheck %s
import circt
from circt.dialects import aig, hw
from circt.ir import Context, Location, Module, InsertionPoint, IntegerType
with Context() as ctx, Location.unknown():
circt.register_dialects(ctx)
m = Module.create()
with InsertionPoint(m.body):
# Test basic AIG dialect functionality
i1 = IntegerType.get_signless(1)
# Create a simple hardware module with AIG operations
def build_module(module):
a, b = module.entry_block.arguments
result = aig.and_inv([a, b], [False, True])
hw.OutputOp([result])
hw.HWModuleOp(name="test_aig",
input_ports=[("a", i1), ("b", i1)],
output_ports=[("out", i1)],
body_builder=build_module)
# CHECK-LABEL: AIG dialect registration and basic operations successful!
print("AIG dialect registration and basic operations successful!")
# Test aig.and_inv operation
# CHECK: %{{.*}} = aig.and_inv %a, not %b : i1
print(m)

View File

@ -0,0 +1,25 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "CIRCTModules.h"
#include "circt-c/Dialect/AIG.h"
#include "mlir/Bindings/Python/NanobindAdaptors.h"
#include "NanobindUtils.h"
#include <nanobind/nanobind.h>
namespace nb = nanobind;
using namespace circt;
using namespace mlir::python::nanobind_adaptors;
/// Populate the aig python module.
void circt::python::populateDialectAIGSubmodule(nb::module_ &m) {
m.doc() = "AIG dialect Python native extension";
}

View File

@ -9,6 +9,7 @@
#include "CIRCTModules.h"
#include "circt-c/Conversion.h"
#include "circt-c/Dialect/AIG.h"
#include "circt-c/Dialect/Arc.h"
#include "circt-c/Dialect/Comb.h"
#include "circt-c/Dialect/DC.h"
@ -49,6 +50,7 @@
namespace nb = nanobind;
static void registerPasses() {
registerAIGPasses();
registerArcPasses();
registerCombPasses();
registerDCPasses();
@ -80,6 +82,10 @@ NB_MODULE(_circt, m) {
MlirContext context = mlirPythonCapsuleToContext(wrappedCapsule.ptr());
// Collect CIRCT dialects to register.
MlirDialectHandle aig = mlirGetDialectHandle__aig__();
mlirDialectHandleRegisterDialect(aig, context);
mlirDialectHandleLoadDialect(aig, context);
MlirDialectHandle comb = mlirGetDialectHandle__comb__();
mlirDialectHandleRegisterDialect(comb, context);
mlirDialectHandleLoadDialect(comb, context);
@ -179,6 +185,8 @@ NB_MODULE(_circt, m) {
mlirExportSplitVerilog(mod, cDirectory);
});
nb::module_ aig = m.def_submodule("_aig", "AIG API");
circt::python::populateDialectAIGSubmodule(aig);
nb::module_ esi = m.def_submodule("_esi", "ESI API");
circt::python::populateDialectESISubmodule(esi);
nb::module_ msft = m.def_submodule("_msft", "MSFT API");

View File

@ -18,6 +18,7 @@
namespace circt {
namespace python {
void populateDialectAIGSubmodule(nanobind::module_ &m);
void populateDialectESISubmodule(nanobind::module_ &m);
void populateDialectHWSubmodule(nanobind::module_ &m);
void populateDialectMSFTSubmodule(nanobind::module_ &m);

View File

@ -14,6 +14,7 @@ set(LLVM_OPTIONAL_SOURCES
)
set(PYTHON_BINDINGS_SOURCES
AIGModule.cpp
CIRCTModule.cpp
ESIModule.cpp
HWModule.cpp
@ -30,6 +31,7 @@ set(PYTHON_BINDINGS_SOURCES
)
set(PYTHON_BINDINGS_LINK_LIBS
CIRCTCAPIAIG
CIRCTCAPIArc
CIRCTCAPIComb
CIRCTCAPIConversion
@ -121,6 +123,14 @@ declare_mlir_dialect_python_bindings(
dialects/comb.py
DIALECT_NAME comb)
declare_mlir_dialect_python_bindings(
ADD_TO_PARENT CIRCTBindingsPythonSources.Dialects
ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
TD_FILE dialects/AIGOps.td
SOURCES
dialects/aig.py
DIALECT_NAME aig)
declare_mlir_dialect_python_bindings(
ADD_TO_PARENT CIRCTBindingsPythonSources.Dialects
ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}"

View File

@ -0,0 +1,14 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef BINDINGS_PYTHON_AIG_OPS
#define BINDINGS_PYTHON_AIG_OPS
include "circt/Dialect/AIG/AIG.td"
#endif // BINDINGS_PYTHON_AIG_OPS

View File

@ -0,0 +1,6 @@
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
from ._aig_ops_gen import *
from ._aig_ops_gen import _Dialect

18
lib/CAPI/Dialect/AIG.cpp Normal file
View File

@ -0,0 +1,18 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "circt-c/Dialect/AIG.h"
#include "circt/Dialect/AIG/AIGDialect.h"
#include "circt/Dialect/AIG/AIGPasses.h"
#include "mlir/CAPI/IR.h"
#include "mlir/CAPI/Registration.h"
#include "mlir/CAPI/Support.h"
MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(AIG, aig, circt::aig::AIGDialect)
void registerAIGPasses() { circt::aig::registerPasses(); }

View File

@ -1,5 +1,6 @@
# TODO: Make the check source feature optional as an argument on *_add_library.
set(LLVM_OPTIONAL_SOURCES
AIG.cpp
Arc.cpp
CHIRRTL.cpp
Comb.cpp
@ -26,6 +27,16 @@ set(LLVM_OPTIONAL_SOURCES
Verif.cpp
)
add_circt_public_c_api_library(CIRCTCAPIAIG
AIG.cpp
LINK_LIBS PUBLIC
MLIRCAPIIR
CIRCTAIG
CIRCTAIGAnalysis
CIRCTAIGTransforms
)
add_circt_public_c_api_library(CIRCTCAPIArc
Arc.cpp