diff --git a/CMakeLists.txt b/CMakeLists.txt index f62f9df51e40..b14dd715da9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -514,11 +514,11 @@ option(CIRCT_BINDINGS_PYTHON_ENABLED "Enables CIRCT Python bindings." OFF) if(CIRCT_BINDINGS_PYTHON_ENABLED) message(STATUS "CIRCT Python bindings are enabled.") set(MLIR_DISABLE_CONFIGURE_PYTHON_DEV_PACKAGES 0) - mlir_detect_pybind11_install() + mlir_detect_nanobind_install() # Prime the search like mlir_configure_python_dev_modules find_package(Python3 3.8 COMPONENTS Interpreter Development) find_package(Python3 3.8 COMPONENTS Interpreter Development.Module) - find_package(pybind11 2.10 CONFIG REQUIRED) + find_package(nanobind 2.4.0 CONFIG REQUIRED) else() message(STATUS "CIRCT Python bindings are disabled.") # Lookup python either way as some integration tests use python without the diff --git a/integration_test/Bindings/Python/dialects/esi.py b/integration_test/Bindings/Python/dialects/esi.py index a93223fa0e04..2861022383d8 100644 --- a/integration_test/Bindings/Python/dialects/esi.py +++ b/integration_test/Bindings/Python/dialects/esi.py @@ -31,7 +31,7 @@ assert (not bundle_type.resettable) for bchan in bundle_type.channels: print(bchan) - # CHECK: ('i16chan', , Type(!esi.channel)) + # CHECK: ('i16chan', ChannelDirection.TO, Type(!esi.channel)) print() bundle_type = esi.BundleType.get( diff --git a/lib/Bindings/Python/CIRCTModule.cpp b/lib/Bindings/Python/CIRCTModule.cpp index aa091bdf5ee7..377d39955ee3 100644 --- a/lib/Bindings/Python/CIRCTModule.cpp +++ b/lib/Bindings/Python/CIRCTModule.cpp @@ -1,4 +1,4 @@ -//===- CIRCTModule.cpp - Main pybind module -------------------------------===// +//===- CIRCTModule.cpp - Main nanobind module -----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -35,14 +35,14 @@ #include "mlir-c/Bindings/Python/Interop.h" #include "mlir-c/IR.h" #include "mlir-c/Transforms.h" -#include "mlir/Bindings/Python/PybindAdaptors.h" +#include "mlir/Bindings/Python/NanobindAdaptors.h" #include "llvm-c/ErrorHandling.h" #include "llvm/Support/Signals.h" -#include "PybindUtils.h" -#include -namespace py = pybind11; +#include "NanobindUtils.h" +#include +namespace nb = nanobind; static void registerPasses() { registerArcPasses(); @@ -59,7 +59,7 @@ static void registerPasses() { mlirRegisterTransformsCSE(); } -PYBIND11_MODULE(_circt, m) { +NB_MODULE(_circt, m) { m.doc() = "CIRCT Python Native Extension"; registerPasses(); llvm::sys::PrintStackTraceOnErrorSignal(/*argv=*/""); @@ -67,7 +67,7 @@ PYBIND11_MODULE(_circt, m) { m.def( "register_dialects", - [](py::object capsule) { + [](nb::object capsule) { // Get the MlirContext capsule from PyMlirContext capsule. auto wrappedCapsule = capsule.attr(MLIR_PYTHON_CAPI_PTR_ATTR); MlirContext context = mlirPythonCapsuleToContext(wrappedCapsule.ptr()); @@ -145,9 +145,9 @@ PYBIND11_MODULE(_circt, m) { }, "Register CIRCT dialects on a PyMlirContext."); - m.def("export_verilog", [](MlirModule mod, py::object fileObject) { + m.def("export_verilog", [](MlirModule mod, nb::object fileObject) { circt::python::PyFileAccumulator accum(fileObject, false); - py::gil_scoped_release(); + nb::gil_scoped_release(); mlirExportVerilog(mod, accum.getCallback(), accum.getUserData()); }); @@ -156,26 +156,26 @@ PYBIND11_MODULE(_circt, m) { mlirExportSplitVerilog(mod, cDirectory); }); - py::module esi = m.def_submodule("_esi", "ESI API"); + nb::module_ esi = m.def_submodule("_esi", "ESI API"); circt::python::populateDialectESISubmodule(esi); - py::module msft = m.def_submodule("_msft", "MSFT API"); + nb::module_ msft = m.def_submodule("_msft", "MSFT API"); circt::python::populateDialectMSFTSubmodule(msft); - py::module hw = m.def_submodule("_hw", "HW API"); + nb::module_ hw = m.def_submodule("_hw", "HW API"); circt::python::populateDialectHWSubmodule(hw); - py::module seq = m.def_submodule("_seq", "Seq API"); + nb::module_ seq = m.def_submodule("_seq", "Seq API"); circt::python::populateDialectSeqSubmodule(seq); - py::module om = m.def_submodule("_om", "OM API"); + nb::module_ om = m.def_submodule("_om", "OM API"); circt::python::populateDialectOMSubmodule(om); - py::module rtg = m.def_submodule("_rtg", "RTG API"); + nb::module_ rtg = m.def_submodule("_rtg", "RTG API"); circt::python::populateDialectRTGSubmodule(rtg); - py::module rtgtool = m.def_submodule("_rtgtool", "RTGTool API"); + nb::module_ rtgtool = m.def_submodule("_rtgtool", "RTGTool API"); circt::python::populateDialectRTGToolSubmodule(rtgtool); #ifdef CIRCT_INCLUDE_TESTS - py::module rtgtest = m.def_submodule("_rtgtest", "RTGTest API"); + nb::module_ rtgtest = m.def_submodule("_rtgtest", "RTGTest API"); circt::python::populateDialectRTGTestSubmodule(rtgtest); #endif - py::module sv = m.def_submodule("_sv", "SV API"); + nb::module_ sv = m.def_submodule("_sv", "SV API"); circt::python::populateDialectSVSubmodule(sv); - py::module support = m.def_submodule("_support", "CIRCT support"); + nb::module_ support = m.def_submodule("_support", "CIRCT support"); circt::python::populateSupportSubmodule(support); } diff --git a/lib/Bindings/Python/CIRCTModules.h b/lib/Bindings/Python/CIRCTModules.h index a082a8445e5c..2705543f245b 100644 --- a/lib/Bindings/Python/CIRCTModules.h +++ b/lib/Bindings/Python/CIRCTModules.h @@ -13,23 +13,23 @@ #ifndef CIRCT_BINDINGS_PYTHON_CIRCTMODULES_H #define CIRCT_BINDINGS_PYTHON_CIRCTMODULES_H -#include +#include namespace circt { namespace python { -void populateDialectESISubmodule(pybind11::module &m); -void populateDialectHWSubmodule(pybind11::module &m); -void populateDialectMSFTSubmodule(pybind11::module &m); -void populateDialectOMSubmodule(pybind11::module &m); -void populateDialectRTGSubmodule(pybind11::module &m); -void populateDialectRTGToolSubmodule(pybind11::module &m); +void populateDialectESISubmodule(nanobind::module_ &m); +void populateDialectHWSubmodule(nanobind::module_ &m); +void populateDialectMSFTSubmodule(nanobind::module_ &m); +void populateDialectOMSubmodule(nanobind::module_ &m); +void populateDialectRTGSubmodule(nanobind::module_ &m); +void populateDialectRTGToolSubmodule(nanobind::module_ &m); #ifdef CIRCT_INCLUDE_TESTS -void populateDialectRTGTestSubmodule(pybind11::module &m); +void populateDialectRTGTestSubmodule(nanobind::module_ &m); #endif -void populateDialectSeqSubmodule(pybind11::module &m); -void populateDialectSVSubmodule(pybind11::module &m); -void populateSupportSubmodule(pybind11::module &m); +void populateDialectSeqSubmodule(nanobind::module_ &m); +void populateDialectSVSubmodule(nanobind::module_ &m); +void populateSupportSubmodule(nanobind::module_ &m); } // namespace python } // namespace circt diff --git a/lib/Bindings/Python/CMakeLists.txt b/lib/Bindings/Python/CMakeLists.txt index 54e3a4743223..1d58d2c4689e 100644 --- a/lib/Bindings/Python/CMakeLists.txt +++ b/lib/Bindings/Python/CMakeLists.txt @@ -26,7 +26,7 @@ set(PYTHON_BINDINGS_SOURCES SVModule.cpp # Headers must be included explicitly so they are installed. CIRCTModules.h - PybindUtils.h + NanobindUtils.h ) set(PYTHON_BINDINGS_LINK_LIBS @@ -70,6 +70,8 @@ declare_mlir_python_extension(CIRCTBindingsPythonExtension ${PYTHON_BINDINGS_LINK_LIBS} PRIVATE_LINK_LIBS LLVMSupport + PYTHON_BINDINGS_LIBRARY + nanobind ) add_dependencies(CIRCTBindingsPythonExtension circt-headers) diff --git a/lib/Bindings/Python/ESIModule.cpp b/lib/Bindings/Python/ESIModule.cpp index 92d3111e11c7..2962ec63188b 100644 --- a/lib/Bindings/Python/ESIModule.cpp +++ b/lib/Bindings/Python/ESIModule.cpp @@ -1,4 +1,4 @@ -//===- ESIModule.cpp - ESI API pybind module ------------------------------===// +//===- ESIModule.cpp - ESI API nanobind module ----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -13,17 +13,16 @@ #include "circt-c/Dialect/ESI.h" #include "mlir-c/Bindings/Python/Interop.h" -#include "mlir/Bindings/Python/PybindAdaptors.h" +#include "mlir/Bindings/Python/NanobindAdaptors.h" #include "mlir/CAPI/IR.h" #include "mlir/CAPI/Support.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" -#include "PybindUtils.h" -#include -#include -namespace py = pybind11; +#include "NanobindUtils.h" +#include +namespace nb = nanobind; using namespace circt::esi; @@ -34,18 +33,18 @@ using namespace circt::esi; /// Container for a Python function that will be called to generate a service. class ServiceGenFunc { public: - ServiceGenFunc(py::object genFunc) : genFunc(std::move(genFunc)) {} + ServiceGenFunc(nb::object genFunc) : genFunc(std::move(genFunc)) {} MlirLogicalResult run(MlirOperation reqOp, MlirOperation declOp, MlirOperation recOp) { - py::gil_scoped_acquire acquire; - py::object rc = genFunc(reqOp, declOp, recOp); - return rc.cast() ? mlirLogicalResultSuccess() - : mlirLogicalResultFailure(); + nb::gil_scoped_acquire acquire; + nb::object rc = genFunc(reqOp, declOp, recOp); + return nb::cast(rc) ? mlirLogicalResultSuccess() + : mlirLogicalResultFailure(); } private: - py::object genFunc; + nb::object genFunc; }; // Mapping from unique identifier to python callback. We use std::string @@ -61,7 +60,7 @@ static MlirLogicalResult serviceGenFunc(MlirOperation reqOp, return iter->getSecond().run(reqOp, declOp, recOp); } -void registerServiceGenerator(std::string name, py::object genFunc) { +void registerServiceGenerator(std::string name, nb::object genFunc) { std::string *n = new std::string(name); serviceGenFuncLookup.try_emplace(n, ServiceGenFunc(genFunc)); circtESIRegisterGlobalServiceGenerator(wrap(*n), serviceGenFunc, n); @@ -77,22 +76,22 @@ class PyAppIDIndex { return circtESIAppIDIndexGetChildAppIDsOf(index, op); } - py::object getAppIDPathAttr(MlirOperation fromMod, MlirAttribute appid, + nb::object getAppIDPathAttr(MlirOperation fromMod, MlirAttribute appid, MlirLocation loc) const { MlirAttribute path = circtESIAppIDIndexGetAppIDPath(index, fromMod, appid, loc); if (path.ptr == nullptr) - return py::none(); - return py::cast(path); + return nb::none(); + return nb::cast(path); } private: CirctESIAppIDIndex index; }; -using namespace mlir::python::adaptors; +using namespace mlir::python::nanobind_adaptors; -void circt::python::populateDialectESISubmodule(py::module &m) { +void circt::python::populateDialectESISubmodule(nb::module_ &m) { m.doc() = "ESI Python Native Extension"; ::registerESIPasses(); @@ -104,19 +103,19 @@ void circt::python::populateDialectESISubmodule(py::module &m) { m.def("registerServiceGenerator", registerServiceGenerator, "Register a service generator for a given service name.", - py::arg("impl_type"), py::arg("generator")); + nb::arg("impl_type"), nb::arg("generator")); mlir_type_subclass(m, "ChannelType", circtESITypeIsAChannelType) .def_classmethod( "get", - [](py::object cls, MlirType inner, uint32_t signaling = 0, + [](nb::object cls, MlirType inner, uint32_t signaling = 0, uint64_t dataDelay = 0) { if (circtESITypeIsAChannelType(inner)) return cls(inner); return cls(circtESIChannelTypeGet(inner, signaling, dataDelay)); }, - py::arg("cls"), py::arg("inner"), py::arg("signaling") = 0, - py::arg("dataDelay") = 0) + nb::arg("cls"), nb::arg("inner"), nb::arg("signaling") = 0, + nb::arg("dataDelay") = 0) .def_property_readonly( "inner", [](MlirType self) { return circtESIChannelGetInner(self); }) .def_property_readonly( @@ -129,53 +128,53 @@ void circt::python::populateDialectESISubmodule(py::module &m) { mlir_type_subclass(m, "AnyType", circtESITypeIsAnAnyType) .def_classmethod( "get", - [](py::object cls, MlirContext ctxt) { + [](nb::object cls, MlirContext ctxt) { return cls(circtESIAnyTypeGet(ctxt)); }, - py::arg("self"), py::arg("ctxt") = nullptr); + nb::arg("self"), nb::arg("ctxt") = nullptr); mlir_type_subclass(m, "ListType", circtESITypeIsAListType) .def_classmethod( "get", - [](py::object cls, MlirType inner) { + [](nb::object cls, MlirType inner) { return cls(circtESIListTypeGet(inner)); }, - py::arg("cls"), py::arg("inner")) + nb::arg("cls"), nb::arg("inner")) .def_property_readonly("element_type", [](MlirType self) { return circtESIListTypeGetElementType(self); }); - py::enum_(m, "ChannelDirection") + nb::enum_(m, "ChannelDirection") .value("TO", ChannelDirection::to) .value("FROM", ChannelDirection::from); mlir_type_subclass(m, "BundleType", circtESITypeIsABundleType) .def_classmethod( "get", - [](py::object cls, std::vector channelTuples, + [](nb::object cls, std::vector channelTuples, bool resettable, MlirContext ctxt) { llvm::SmallVector channels( - llvm::map_range(channelTuples, [ctxt](py::tuple t) { - std::string name = py::cast(t[0]); + llvm::map_range(channelTuples, [ctxt](nb::tuple t) { + std::string name = nb::cast(t[0]); return CirctESIBundleTypeBundleChannel{ mlirIdentifierGet(ctxt, mlirStringRefCreate( name.data(), name.length())), - (uint32_t)py::cast(t[1]), - py::cast(t[2])}; + (uint32_t)nb::cast(t[1]), + nb::cast(t[2])}; })); return cls(circtESIBundleTypeGet(ctxt, channels.size(), channels.data(), resettable)); }, - py::arg("cls"), py::arg("channels"), py::arg("resettable"), - py::arg("ctxt") = nullptr) + nb::arg("cls"), nb::arg("channels"), nb::arg("resettable"), + nb::arg("ctxt") = nullptr) .def_property_readonly("resettable", &circtESIBundleTypeGetResettable) .def_property_readonly("channels", [](MlirType bundleType) { - std::vector channels; + std::vector channels; size_t numChannels = circtESIBundleTypeGetNumChannels(bundleType); for (size_t i = 0; i < numChannels; ++i) { CirctESIBundleTypeBundleChannel channel = circtESIBundleTypeGetChannel(bundleType, i); MlirStringRef name = mlirIdentifierStr(channel.name); - channels.push_back(py::make_tuple(py::str(name.data, name.length), + channels.push_back(nb::make_tuple(nb::str(name.data, name.length), (ChannelDirection)channel.direction, channel.channelType)); } @@ -185,56 +184,56 @@ void circt::python::populateDialectESISubmodule(py::module &m) { mlir_attribute_subclass(m, "AppIDAttr", circtESIAttributeIsAnAppIDAttr) .def_classmethod( "get", - [](py::object cls, std::string name, std::optional index, + [](nb::object cls, std::string name, std::optional index, MlirContext ctxt) { if (index.has_value()) return cls(circtESIAppIDAttrGet(ctxt, wrap(name), index.value())); return cls(circtESIAppIDAttrGetNoIdx(ctxt, wrap(name))); }, - "Create an AppID attribute", py::arg("cls"), py::arg("name"), - py::arg("index") = py::none(), py::arg("context") = py::none()) + "Create an AppID attribute", nb::arg("cls"), nb::arg("name"), + nb::arg("index") = nb::none(), nb::arg("context") = nb::none()) .def_property_readonly("name", [](MlirAttribute self) { llvm::StringRef name = unwrap(circtESIAppIDAttrGetName(self)); return std::string(name.data(), name.size()); }) - .def_property_readonly("index", [](MlirAttribute self) -> py::object { + .def_property_readonly("index", [](MlirAttribute self) -> nb::object { uint64_t index; if (circtESIAppIDAttrGetIndex(self, &index)) - return py::cast(index); - return py::none(); + return nb::cast(index); + return nb::none(); }); mlir_attribute_subclass(m, "AppIDPathAttr", circtESIAttributeIsAnAppIDPathAttr) .def_classmethod( "get", - [](py::object cls, MlirAttribute root, + [](nb::object cls, MlirAttribute root, std::vector path, MlirContext ctxt) { return cls( circtESIAppIDAttrPathGet(ctxt, root, path.size(), path.data())); }, - "Create an AppIDPath attribute", py::arg("cls"), py::arg("root"), - py::arg("path"), py::arg("context") = py::none()) + "Create an AppIDPath attribute", nb::arg("cls"), nb::arg("root"), + nb::arg("path"), nb::arg("context") = nb::none()) .def_property_readonly("root", &circtESIAppIDAttrPathGetRoot) .def("__len__", &circtESIAppIDAttrPathGetNumComponents) .def("__getitem__", &circtESIAppIDAttrPathGetComponent); m.def("check_inner_type_match", &circtESICheckInnerTypeMatch, "Check that two types match, allowing for AnyType in 'expected'.", - py::arg("expected"), py::arg("actual")); + nb::arg("expected"), nb::arg("actual")); - py::class_(m, "AppIDIndex") - .def(py::init(), py::arg("root")) + nb::class_(m, "AppIDIndex") + .def(nb::init(), nb::arg("root")) .def("get_child_appids_of", &PyAppIDIndex::getChildAppIDsOf, "Return a dictionary of AppIDAttrs to ArrayAttr of InnerRefAttrs " "containing the relative paths to the leaf of the particular " "AppIDAttr. Argument MUST be HWModuleLike.", - py::arg("mod")) + nb::arg("mod")) .def("get_appid_path", &PyAppIDIndex::getAppIDPathAttr, "Return an array of InnerNameRefAttrs representing the relative " "path to 'appid' from 'fromMod'.", - py::arg("from_mod"), py::arg("appid"), - py::arg("query_site") = py::none()); + nb::arg("from_mod"), nb::arg("appid"), + nb::arg("query_site") = nb::none()); } diff --git a/lib/Bindings/Python/HWModule.cpp b/lib/Bindings/Python/HWModule.cpp index e6b8883066ff..5a98882622fe 100644 --- a/lib/Bindings/Python/HWModule.cpp +++ b/lib/Bindings/Python/HWModule.cpp @@ -1,4 +1,4 @@ -//===- HWModule.cpp - HW API pybind module --------------------------------===// +//===- HWModule.cpp - HW API nanobind module ------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,29 +11,27 @@ #include "circt-c/Dialect/HW.h" #include "mlir-c/BuiltinAttributes.h" -#include "mlir/Bindings/Python/PybindAdaptors.h" +#include "mlir/Bindings/Python/NanobindAdaptors.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" -#include "PybindUtils.h" +#include "NanobindUtils.h" #include "mlir-c/Support.h" -#include -#include -#include -namespace py = pybind11; +#include +namespace nb = nanobind; using namespace circt; -using namespace mlir::python::adaptors; +using namespace mlir::python::nanobind_adaptors; /// Populate the hw python module. -void circt::python::populateDialectHWSubmodule(py::module &m) { +void circt::python::populateDialectHWSubmodule(nb::module_ &m) { m.doc() = "HW dialect Python native extension"; m.def("get_bitwidth", &hwGetBitWidth); mlir_type_subclass(m, "InOutType", hwTypeIsAInOut) .def_classmethod("get", - [](py::object cls, MlirType innerType) { + [](nb::object cls, MlirType innerType) { return cls(hwInOutTypeGet(innerType)); }) .def_property_readonly("element_type", [](MlirType self) { @@ -42,7 +40,7 @@ void circt::python::populateDialectHWSubmodule(py::module &m) { mlir_type_subclass(m, "ArrayType", hwTypeIsAArrayType) .def_classmethod("get", - [](py::object cls, MlirType elementType, intptr_t size) { + [](nb::object cls, MlirType elementType, intptr_t size) { return cls(hwArrayTypeGet(elementType, size)); }) .def_property_readonly( @@ -51,31 +49,31 @@ void circt::python::populateDialectHWSubmodule(py::module &m) { .def_property_readonly( "size", [](MlirType self) { return hwArrayTypeGetSize(self); }); - py::enum_(m, "ModulePortDirection") + nb::enum_(m, "ModulePortDirection") .value("INPUT", HWModulePortDirection::Input) .value("OUTPUT", HWModulePortDirection::Output) .value("INOUT", HWModulePortDirection::InOut) .export_values(); - py::class_(m, "ModulePort") - .def(py::init()); + nb::class_(m, "ModulePort") + .def(nb::init()); mlir_type_subclass(m, "ModuleType", hwTypeIsAModuleType) .def_classmethod( "get", - [](py::object cls, py::list pyModulePorts, MlirContext ctx) { + [](nb::object cls, nb::list pyModulePorts, MlirContext ctx) { std::vector modulePorts; for (auto pyModulePort : pyModulePorts) - modulePorts.push_back(pyModulePort.cast()); + modulePorts.push_back(nb::cast(pyModulePort)); return cls( hwModuleTypeGet(ctx, modulePorts.size(), modulePorts.data())); }, - py::arg("cls"), py::arg("ports"), py::arg("context") = py::none()) + nb::arg("cls"), nb::arg("ports"), nb::arg("context") = nb::none()) .def_property_readonly( "input_types", [](MlirType self) { - py::list inputTypes; + nb::list inputTypes; intptr_t numInputs = hwModuleTypeGetNumInputs(self); for (intptr_t i = 0; i < numInputs; ++i) inputTypes.append(hwModuleTypeGetInputType(self, i)); @@ -95,7 +93,7 @@ void circt::python::populateDialectHWSubmodule(py::module &m) { .def_property_readonly( "output_types", [](MlirType self) { - py::list outputTypes; + nb::list outputTypes; intptr_t numOutputs = hwModuleTypeGetNumOutputs(self); for (intptr_t i = 0; i < numOutputs; ++i) outputTypes.append(hwModuleTypeGetOutputType(self, i)); @@ -114,7 +112,7 @@ void circt::python::populateDialectHWSubmodule(py::module &m) { mlir_type_subclass(m, "ParamIntType", hwTypeIsAIntType) .def_classmethod( "get_from_param", - [](py::object cls, MlirContext ctx, MlirAttribute param) { + [](nb::object cls, MlirContext ctx, MlirAttribute param) { return cls(hwParamIntTypeGet(param)); }) .def_property_readonly("width", [](MlirType self) { @@ -124,7 +122,7 @@ void circt::python::populateDialectHWSubmodule(py::module &m) { mlir_type_subclass(m, "StructType", hwTypeIsAStructType) .def_classmethod( "get", - [](py::object cls, py::list pyFieldInfos) { + [](nb::object cls, nb::list pyFieldInfos) { llvm::SmallVector mlirFieldInfos; MlirContext ctx; @@ -132,10 +130,10 @@ void circt::python::populateDialectHWSubmodule(py::module &m) { // copy them into a temporary vector to give them all new addresses. llvm::SmallVector> names; for (size_t i = 0, e = pyFieldInfos.size(); i < e; ++i) { - auto tuple = pyFieldInfos[i].cast(); - auto type = tuple[1].cast(); + auto tuple = nb::cast(pyFieldInfos[i]); + auto type = nb::cast(tuple[1]); ctx = mlirTypeGetContext(type); - names.emplace_back(tuple[0].cast()); + names.emplace_back(nb::cast(tuple[0])); auto nameStringRef = mlirStringRefCreate(names[i].data(), names[i].size()); mlirFieldInfos.push_back(HWStructFieldInfo{ @@ -156,19 +154,19 @@ void circt::python::populateDialectHWSubmodule(py::module &m) { }) .def("get_fields", [](MlirType self) { intptr_t num_fields = hwStructTypeGetNumFields(self); - py::list fields; + nb::list fields; for (intptr_t i = 0; i < num_fields; ++i) { auto field = hwStructTypeGetFieldNum(self, i); auto fieldName = mlirIdentifierStr(field.name); std::string name(fieldName.data, fieldName.length); - fields.append(py::make_tuple(name, field.type)); + fields.append(nb::make_tuple(name, field.type)); } return fields; }); mlir_type_subclass(m, "TypeAliasType", hwTypeIsATypeAliasType) .def_classmethod("get", - [](py::object cls, std::string scope, std::string name, + [](nb::object cls, std::string scope, std::string name, MlirType innerType) { return cls(hwTypeAliasTypeGet( mlirStringRefCreateFromCString(scope.c_str()), @@ -195,13 +193,13 @@ void circt::python::populateDialectHWSubmodule(py::module &m) { mlir_attribute_subclass(m, "ParamDeclAttr", hwAttrIsAParamDeclAttr) .def_classmethod( "get", - [](py::object cls, std::string name, MlirType type, + [](nb::object cls, std::string name, MlirType type, MlirAttribute value) { return cls(hwParamDeclAttrGet( mlirStringRefCreateFromCString(name.c_str()), type, value)); }) .def_classmethod("get_nodefault", - [](py::object cls, std::string name, MlirType type) { + [](nb::object cls, std::string name, MlirType type) { return cls(hwParamDeclAttrGet( mlirStringRefCreateFromCString(name.c_str()), type, MlirAttribute{nullptr})); @@ -220,7 +218,7 @@ void circt::python::populateDialectHWSubmodule(py::module &m) { mlir_attribute_subclass(m, "ParamDeclRefAttr", hwAttrIsAParamDeclRefAttr) .def_classmethod( "get", - [](py::object cls, MlirContext ctx, std::string name) { + [](nb::object cls, MlirContext ctx, std::string name) { return cls(hwParamDeclRefAttrGet( ctx, mlirStringRefCreateFromCString(name.c_str()))); }) @@ -233,12 +231,12 @@ void circt::python::populateDialectHWSubmodule(py::module &m) { }); mlir_attribute_subclass(m, "ParamVerbatimAttr", hwAttrIsAParamVerbatimAttr) - .def_classmethod("get", [](py::object cls, MlirAttribute text) { + .def_classmethod("get", [](nb::object cls, MlirAttribute text) { return cls(hwParamVerbatimAttrGet(text)); }); mlir_attribute_subclass(m, "OutputFileAttr", hwAttrIsAOutputFileAttr) - .def_classmethod("get_from_filename", [](py::object cls, + .def_classmethod("get_from_filename", [](nb::object cls, MlirAttribute fileName, bool excludeFromFileList, bool includeReplicatedOp) { @@ -248,7 +246,7 @@ void circt::python::populateDialectHWSubmodule(py::module &m) { mlir_attribute_subclass(m, "InnerSymAttr", hwAttrIsAInnerSymAttr) .def_classmethod("get", - [](py::object cls, MlirAttribute symName) { + [](nb::object cls, MlirAttribute symName) { return cls(hwInnerSymAttrGet(symName)); }) .def_property_readonly("symName", [](MlirAttribute self) { @@ -258,7 +256,7 @@ void circt::python::populateDialectHWSubmodule(py::module &m) { mlir_attribute_subclass(m, "InnerRefAttr", hwAttrIsAInnerRefAttr) .def_classmethod( "get", - [](py::object cls, MlirAttribute moduleName, MlirAttribute innerSym) { + [](nb::object cls, MlirAttribute moduleName, MlirAttribute innerSym) { return cls(hwInnerRefAttrGet(moduleName, innerSym)); }) .def_property_readonly( diff --git a/lib/Bindings/Python/MSFTModule.cpp b/lib/Bindings/Python/MSFTModule.cpp index 208bb7579eec..79dd1def4c55 100644 --- a/lib/Bindings/Python/MSFTModule.cpp +++ b/lib/Bindings/Python/MSFTModule.cpp @@ -1,4 +1,4 @@ -//===- MSFTModule.cpp - MSFT API pybind module ----------------------------===// +//===- MSFTModule.cpp - MSFT API nanobind module --------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,22 +11,19 @@ #include "circt-c/Dialect/MSFT.h" #include "circt/Dialect/MSFT/MSFTDialect.h" -#include "mlir/Bindings/Python/PybindAdaptors.h" +#include "mlir/Bindings/Python/NanobindAdaptors.h" #include "mlir/CAPI/IR.h" #include "mlir/CAPI/Support.h" -#include "PybindUtils.h" -#include -#include -#include -namespace py = pybind11; +#include "NanobindUtils.h" +namespace nb = nanobind; // using namespace circt; // using namespace circt::msft; -using namespace mlir::python::adaptors; +using namespace mlir::python::nanobind_adaptors; -static py::handle getPhysLocationAttr(MlirAttribute attr) { - return py::module::import("circt.dialects.msft") +static nb::handle getPhysLocationAttr(MlirAttribute attr) { + return nb::module_::import_("circt.dialects.msft") .attr("PhysLocationAttr")(attr) .release(); } @@ -68,21 +65,22 @@ class PlacementDB { MlirOperation getInstanceAt(MlirAttribute loc) { return circtMSFTPlacementDBGetInstanceAt(db, loc); } - py::handle getNearestFreeInColumn(CirctMSFTPrimitiveType prim, - uint64_t column, uint64_t nearestToY) { + nb::handle getNearestFreeInColumn(PrimitiveType prim, uint64_t column, + uint64_t nearestToY) { + auto cPrim = static_cast(prim); MlirAttribute nearest = circtMSFTPlacementDBGetNearestFreeInColumn( - db, prim, column, nearestToY); + db, cPrim, column, nearestToY); if (!nearest.ptr) - return py::none(); + return nb::none(); return getPhysLocationAttr(nearest); } void walkPlacements( - py::function pycb, - std::tuple bounds, - py::object prim, py::object walkOrder) { + nb::callable pycb, + std::tuple bounds, + nb::object prim, nb::object walkOrder) { - auto handleNone = [](py::object o) { - return o.is_none() ? -1 : o.cast(); + auto handleNone = [](nb::object o) { + return o.is_none() ? -1 : nb::cast(o); }; int64_t cBounds[4] = { handleNone(std::get<0>(bounds)), handleNone(std::get<1>(bounds)), @@ -91,11 +89,11 @@ class PlacementDB { if (prim.is_none()) cPrim = -1; else - cPrim = prim.cast(); + cPrim = nb::cast(prim); CirctMSFTWalkOrder cWalkOrder; if (!walkOrder.is_none()) - cWalkOrder = walkOrder.cast(); + cWalkOrder = nb::cast(walkOrder); else cWalkOrder = CirctMSFTWalkOrder{CirctMSFTDirection::NONE, CirctMSFTDirection::NONE}; @@ -103,8 +101,8 @@ class PlacementDB { circtMSFTPlacementDBWalkPlacements( db, [](MlirAttribute loc, MlirOperation locOp, void *userData) { - py::gil_scoped_acquire gil; - py::function pycb = *((py::function *)(userData)); + nb::gil_scoped_acquire gil; + nb::callable pycb = *((nb::callable *)(userData)); pycb(loc, locOp); }, cBounds, cPrim, cWalkOrder, &pycb); @@ -130,14 +128,13 @@ class PyLocationVecIterator { std::optional dunderNext() { if (nextIndex >= circtMSFTLocationVectorAttrGetNumElements(attr)) { - throw py::stop_iteration(); + throw nb::stop_iteration(); } return getItem(attr, nextIndex++); } - static void bind(py::module &m) { - py::class_(m, "LocationVectorAttrIterator", - py::module_local()) + static void bind(nb::module_ &m) { + nb::class_(m, "LocationVectorAttrIterator") .def("__iter__", &PyLocationVecIterator::dunderIter) .def("__next__", &PyLocationVecIterator::dunderNext); } @@ -148,20 +145,20 @@ class PyLocationVecIterator { }; /// Populate the msft python module. -void circt::python::populateDialectMSFTSubmodule(py::module &m) { +void circt::python::populateDialectMSFTSubmodule(nb::module_ &m) { mlirMSFTRegisterPasses(); m.doc() = "MSFT dialect Python native extension"; m.def("replaceAllUsesWith", &circtMSFTReplaceAllUsesWith); - py::enum_(m, "PrimitiveType") + nb::enum_(m, "PrimitiveType") .value("M20K", PrimitiveType::M20K) .value("DSP", PrimitiveType::DSP) .value("FF", PrimitiveType::FF) .export_values(); - py::enum_(m, "Direction") + nb::enum_(m, "Direction") .value("NONE", CirctMSFTDirection::NONE) .value("ASC", CirctMSFTDirection::ASC) .value("DESC", CirctMSFTDirection::DESC) @@ -171,14 +168,14 @@ void circt::python::populateDialectMSFTSubmodule(py::module &m) { circtMSFTAttributeIsAPhysLocationAttribute) .def_classmethod( "get", - [](py::object cls, PrimitiveType devType, uint64_t x, uint64_t y, + [](nb::object cls, PrimitiveType devType, uint64_t x, uint64_t y, uint64_t num, MlirContext ctxt) { return cls(circtMSFTPhysLocationAttrGet(ctxt, (uint64_t)devType, x, y, num)); }, - "Create a physical location attribute", py::arg(), - py::arg("dev_type"), py::arg("x"), py::arg("y"), py::arg("num"), - py::arg("ctxt") = py::none()) + "Create a physical location attribute", nb::arg(), + nb::arg("dev_type"), nb::arg("x"), nb::arg("y"), nb::arg("num"), + nb::arg("ctxt") = nb::none()) .def_property_readonly( "devtype", [](MlirAttribute self) { @@ -201,21 +198,21 @@ void circt::python::populateDialectMSFTSubmodule(py::module &m) { circtMSFTAttributeIsAPhysicalBoundsAttr) .def_classmethod( "get", - [](py::object cls, uint64_t xMin, uint64_t xMax, uint64_t yMin, + [](nb::object cls, uint64_t xMin, uint64_t xMax, uint64_t yMin, uint64_t yMax, MlirContext ctxt) { auto physicalBounds = circtMSFTPhysicalBoundsAttrGet(ctxt, xMin, xMax, yMin, yMax); return cls(physicalBounds); }, - "Create a PhysicalBounds attribute", py::arg("cls"), py::arg("xMin"), - py::arg("xMax"), py::arg("yMin"), py::arg("yMax"), - py::arg("context") = py::none()); + "Create a PhysicalBounds attribute", nb::arg("cls"), nb::arg("xMin"), + nb::arg("xMax"), nb::arg("yMin"), nb::arg("yMax"), + nb::arg("context") = nb::none()); mlir_attribute_subclass(m, "LocationVectorAttr", circtMSFTAttributeIsALocationVectorAttribute) .def_classmethod( "get", - [](py::object cls, MlirType type, std::vector pylocs, + [](nb::object cls, MlirType type, std::vector pylocs, MlirContext ctxt) { // Get a LocationVector being sensitive to None in the list of // locations. @@ -229,38 +226,38 @@ void circt::python::populateDialectMSFTSubmodule(py::module &m) { return cls(circtMSFTLocationVectorAttrGet(ctxt, type, locs.size(), locs.data())); }, - "Create a LocationVector attribute", py::arg("cls"), py::arg("type"), - py::arg("locs"), py::arg("context") = py::none()) + "Create a LocationVector attribute", nb::arg("cls"), nb::arg("type"), + nb::arg("locs"), nb::arg("context") = nb::none()) .def("reg_type", &circtMSFTLocationVectorAttrGetType) .def("__len__", &circtMSFTLocationVectorAttrGetNumElements) .def("__getitem__", &PyLocationVecIterator::getItem, - "Get the location at the specified position", py::arg("pos")) + "Get the location at the specified position", nb::arg("pos")) .def("__iter__", [](MlirAttribute arr) { return PyLocationVecIterator(arr); }); PyLocationVecIterator::bind(m); - py::class_(m, "PrimitiveDB") - .def(py::init(), py::arg("ctxt") = py::none()) + nb::class_(m, "PrimitiveDB") + .def(nb::init(), nb::arg("ctxt") = nb::none()) .def("add_primitive", &PrimitiveDB::addPrimitive, - "Inform the DB about a new placement.", py::arg("loc_and_prim")) + "Inform the DB about a new placement.", nb::arg("loc_and_prim")) .def("is_valid_location", &PrimitiveDB::isValidLocation, "Query the DB as to whether or not a primitive exists.", - py::arg("loc")); + nb::arg("loc")); - py::class_(m, "PlacementDB") - .def(py::init(), py::arg("top"), - py::arg("seed") = nullptr) + nb::class_(m, "PlacementDB") + .def(nb::init(), nb::arg("top"), + nb::arg("seed") = nullptr) .def("place", &PlacementDB::place, "Place a dynamic instance.", - py::arg("dyn_inst"), py::arg("location"), py::arg("subpath"), - py::arg("src_location") = py::none()) + nb::arg("dyn_inst"), nb::arg("location"), nb::arg("subpath"), + nb::arg("src_location") = nb::none()) .def("remove_placement", &PlacementDB::removePlacement, - "Remove a placement.", py::arg("location")) + "Remove a placement.", nb::arg("location")) .def("move_placement", &PlacementDB::movePlacement, - "Move a placement to another location.", py::arg("old_location"), - py::arg("new_location")) + "Move a placement to another location.", nb::arg("old_location"), + nb::arg("new_location")) .def("get_nearest_free_in_column", &PlacementDB::getNearestFreeInColumn, "Find the nearest free primitive location in column.", - py::arg("prim_type"), py::arg("column"), py::arg("nearest_to_y")) + nb::arg("prim_type"), nb::arg("column"), nb::arg("nearest_to_y")) .def("get_instance_at", &PlacementDB::getInstanceAt, "Get the instance at location. Returns None if nothing exists " "there. Otherwise, returns (path, subpath, op) of the instance " @@ -268,14 +265,14 @@ void circt::python::populateDialectMSFTSubmodule(py::module &m) { .def("walk_placements", &PlacementDB::walkPlacements, "Walk the placements, with possible bounds. Bounds are (xmin, xmax, " "ymin, ymax) with 'None' being unbounded.", - py::arg("callback"), - py::arg("bounds") = - std::make_tuple(py::none(), py::none(), py::none(), py::none()), - py::arg("prim_type") = py::none(), - py::arg("walk_order") = py::none()); + nb::arg("callback"), + nb::arg("bounds") = + std::make_tuple(nb::none(), nb::none(), nb::none(), nb::none()), + nb::arg("prim_type") = nb::none(), + nb::arg("walk_order") = nb::none()); - py::class_(m, "WalkOrder") - .def(py::init(), - py::arg("columns") = CirctMSFTDirection::NONE, - py::arg("rows") = CirctMSFTDirection::NONE); + nb::class_(m, "WalkOrder") + .def(nb::init(), + nb::arg("columns") = CirctMSFTDirection::NONE, + nb::arg("rows") = CirctMSFTDirection::NONE); } diff --git a/lib/Bindings/Python/PybindUtils.h b/lib/Bindings/Python/NanobindUtils.h similarity index 71% rename from lib/Bindings/Python/PybindUtils.h rename to lib/Bindings/Python/NanobindUtils.h index 207b4b7d8276..bd32e87b9a61 100644 --- a/lib/Bindings/Python/PybindUtils.h +++ b/lib/Bindings/Python/NanobindUtils.h @@ -1,4 +1,4 @@ -//===- PybindUtils.h - Utilities for interop with python ------------------===// +//===- NanobindUtils.h - Utilities for interop with python ----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -15,9 +15,7 @@ #include -#include -#include -#include +#include #include "mlir-c/Bindings/Python/Interop.h" #include "mlir-c/IR.h" @@ -25,31 +23,29 @@ #include -namespace py = pybind11; - namespace circt { namespace python { -/// Taken from PybindUtils.h in MLIR. +/// Taken from NanobindUtils.h in MLIR. /// Accumulates into a python file-like object, either writing text (default) /// or binary. class PyFileAccumulator { public: - PyFileAccumulator(pybind11::object fileObject, bool binary) + PyFileAccumulator(nanobind::object fileObject, bool binary) : pyWriteFunction(fileObject.attr("write")), binary(binary) {} void *getUserData() { return this; } MlirStringCallback getCallback() { return [](MlirStringRef part, void *userData) { - pybind11::gil_scoped_acquire(); + nanobind::gil_scoped_acquire(); PyFileAccumulator *accum = static_cast(userData); if (accum->binary) { // Note: Still has to copy and not avoidable with this API. - pybind11::bytes pyBytes(part.data, part.length); + nanobind::bytes pyBytes(part.data, part.length); accum->pyWriteFunction(pyBytes); } else { - pybind11::str pyStr(part.data, + nanobind::str pyStr(part.data, part.length); // Decodes as UTF-8 by default. accum->pyWriteFunction(pyStr); } @@ -57,37 +53,37 @@ class PyFileAccumulator { } private: - pybind11::object pyWriteFunction; + nanobind::object pyWriteFunction; bool binary; }; } // namespace python } // namespace circt -namespace pybind11 { +namespace nanobind { /// Raises a python exception with the given message. /// Correct usage: // throw RaiseValueError(PyExc_ValueError, "Foobar'd"); -inline pybind11::error_already_set raisePyError(PyObject *exc_class, - const char *message) { +inline nanobind::python_error raisePyError(PyObject *exc_class, + const char *message) { PyErr_SetString(exc_class, message); - return pybind11::error_already_set(); + return nanobind::python_error(); } /// Raises a value error with the given message. /// Correct usage: /// throw RaiseValueError("Foobar'd"); -inline pybind11::error_already_set raiseValueError(const char *message) { +inline nanobind::python_error raiseValueError(const char *message) { return raisePyError(PyExc_ValueError, message); } /// Raises a value error with the given message. /// Correct usage: /// throw RaiseValueError(message); -inline pybind11::error_already_set raiseValueError(const std::string &message) { +inline nanobind::python_error raiseValueError(const std::string &message) { return raisePyError(PyExc_ValueError, message.c_str()); } -} // namespace pybind11 +} // namespace nanobind #endif // CIRCT_BINDINGS_PYTHON_PYBINDUTILS_H diff --git a/lib/Bindings/Python/OMModule.cpp b/lib/Bindings/Python/OMModule.cpp index 8f9deb6808c9..5860e6c5cec1 100644 --- a/lib/Bindings/Python/OMModule.cpp +++ b/lib/Bindings/Python/OMModule.cpp @@ -1,4 +1,4 @@ -//===- OMModule.cpp - OM API pybind module --------------------------------===// +//===- OMModule.cpp - OM API nanobind module ------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -12,14 +12,15 @@ #include "mlir-c/BuiltinAttributes.h" #include "mlir-c/BuiltinTypes.h" #include "mlir-c/IR.h" -#include "mlir/Bindings/Python/PybindAdaptors.h" -#include -#include -namespace py = pybind11; +#include "mlir/Bindings/Python/NanobindAdaptors.h" +#include +#include +#include +namespace nb = nanobind; using namespace mlir; using namespace mlir::python; -using namespace mlir::python::adaptors; +using namespace mlir::python::nanobind_adaptors; namespace { @@ -32,11 +33,11 @@ struct Path; /// These are the Python types that are represented by the different primitive /// OMEvaluatorValues as Attributes. -using PythonPrimitive = std::variant; +using PythonPrimitive = std::variant; -/// None is used to by pybind when default initializing a PythonValue. The -/// order of types in the variant matters here, and we want pybind to try +/// None is used to by nanobind when default initializing a PythonValue. The +/// order of types in the variant matters here, and we want nanobind to try /// casting to the Python classes defined in this file first, before /// MlirAttribute and the upstream MLIR type casters. If the MlirAttribute /// is tried first, then we can hit an assert inside the MLIR codebase. @@ -89,14 +90,14 @@ struct Map { Map(OMEvaluatorValue value) : value(value) {} /// Return the keys. - std::vector getKeys() { + std::vector getKeys() { auto attr = omEvaluatorMapGetKeys(value); intptr_t numFieldNames = mlirArrayAttrGetNumElements(attr); - std::vector pyFieldNames; + std::vector pyFieldNames; for (intptr_t i = 0; i < numFieldNames; ++i) { auto name = mlirStringAttrGetValue(mlirArrayAttrGetElement(attr, i)); - pyFieldNames.emplace_back(py::str(name.data, name.length)); + pyFieldNames.emplace_back(nb::str(name.data, name.length)); } return pyFieldNames; @@ -184,8 +185,8 @@ struct Object { return omEvaluatorValueGetLoc(result); } - // Get a field from the Object, using pybind's support for variant to return a - // Python object that is either an Object or Attribute. + // Get a field from the Object, using nanobind's support for variant to return + // a Python object that is either an Object or Attribute. PythonValue getField(const std::string &name) { // Wrap the requested field name in an attribute. MlirContext context = mlirTypeGetContext(omEvaluatorObjectGetType(value)); @@ -247,7 +248,7 @@ struct Evaluator { // implemented in pure Python, so nothing to do here besides throwing an // error to halt execution. if (omEvaluatorObjectIsNull(result)) - throw py::value_error( + throw nb::value_error( "unable to instantiate object, see previous error(s)"); // Return a new Object. @@ -270,13 +271,12 @@ class PyListAttrIterator { MlirAttribute dunderNext() { if (nextIndex >= omListAttrGetNumElements(attr)) - throw py::stop_iteration(); + throw nb::stop_iteration(); return omListAttrGetElement(attr, nextIndex++); } - static void bind(py::module &m) { - py::class_(m, "ListAttributeIterator", - py::module_local()) + static void bind(nb::module_ &m) { + nb::class_(m, "ListAttributeIterator") .def("__iter__", &PyListAttrIterator::dunderIter) .def("__next__", &PyListAttrIterator::dunderNext); } @@ -296,9 +296,9 @@ class PyMapAttrIterator { PyMapAttrIterator &dunderIter() { return *this; } - py::tuple dunderNext() { + nb::tuple dunderNext() { if (nextIndex >= omMapAttrGetNumElements(attr)) - throw py::stop_iteration(); + throw nb::stop_iteration(); MlirIdentifier key = omMapAttrGetElementKey(attr, nextIndex); PythonValue value = @@ -307,11 +307,11 @@ class PyMapAttrIterator { auto keyName = mlirIdentifierStr(key); std::string keyStr(keyName.data, keyName.length); - return py::make_tuple(keyStr, value); + return nb::make_tuple(keyStr, value); } - static void bind(py::module &m) { - py::class_(m, "MapAttributeIterator", py::module_local()) + static void bind(nb::module_ &m) { + nb::class_(m, "MapAttributeIterator") .def("__iter__", &PyMapAttrIterator::dunderIter) .def("__next__", &PyMapAttrIterator::dunderNext); } @@ -331,7 +331,7 @@ PythonValue Tuple::getElement(intptr_t i) { PythonValue Map::dunderGetItemNamed(const std::string &key) { MlirType type = omMapTypeGetKeyType(omEvaluatorMapGetType(value)); if (!omTypeIsAStringType(type)) - throw pybind11::key_error("key is not string"); + throw nanobind::key_error("key is not string"); MlirAttribute attr = mlirStringAttrTypedGet(type, mlirStringRefCreateFromCString(key.c_str())); return dunderGetItemAttr(attr); @@ -340,7 +340,7 @@ PythonValue Map::dunderGetItemNamed(const std::string &key) { PythonValue Map::dunderGetItemIndexed(intptr_t i) { MlirType type = omMapTypeGetKeyType(omEvaluatorMapGetType(value)); if (!mlirTypeIsAInteger(type)) - throw pybind11::key_error("key is not integer"); + throw nanobind::key_error("key is not integer"); MlirAttribute attr = mlirIntegerAttrGet(type, i); return dunderGetItemAttr(attr); } @@ -349,7 +349,7 @@ PythonValue Map::dunderGetItemAttr(MlirAttribute key) { OMEvaluatorValue result = omEvaluatorMapGetElement(value, key); if (omEvaluatorValueIsNull(result)) - throw pybind11::key_error("key not found"); + throw nanobind::key_error("key not found"); return omEvaluatorValueToPythonValue(result); } @@ -368,30 +368,30 @@ Map::dunderGetItem(std::variant key) { static PythonPrimitive omPrimitiveToPythonValue(MlirAttribute attr) { if (omAttrIsAIntegerAttr(attr)) { auto strRef = omIntegerAttrToString(attr); - return py::int_(py::str(strRef.data, strRef.length)); + return nb::int_(nb::str(strRef.data, strRef.length)); } if (mlirAttributeIsAFloat(attr)) { - return py::float_(mlirFloatAttrGetValueDouble(attr)); + return nb::float_(mlirFloatAttrGetValueDouble(attr)); } if (mlirAttributeIsAString(attr)) { auto strRef = mlirStringAttrGetValue(attr); - return py::str(strRef.data, strRef.length); + return nb::str(strRef.data, strRef.length); } // BoolAttr's are IntegerAttr's, check this first. if (mlirAttributeIsABool(attr)) { - return py::bool_(mlirBoolAttrGetValue(attr)); + return nb::bool_(mlirBoolAttrGetValue(attr)); } if (mlirAttributeIsAInteger(attr)) { MlirType type = mlirAttributeGetType(attr); if (mlirTypeIsAIndex(type) || mlirIntegerTypeIsSignless(type)) - return py::int_(mlirIntegerAttrGetValueInt(attr)); + return nb::int_(mlirIntegerAttrGetValueInt(attr)); if (mlirIntegerTypeIsSigned(type)) - return py::int_(mlirIntegerAttrGetValueSInt(attr)); - return py::int_(mlirIntegerAttrGetValueUInt(attr)); + return nb::int_(mlirIntegerAttrGetValueSInt(attr)); + return nb::int_(mlirIntegerAttrGetValueUInt(attr)); } if (omAttrIsAReferenceAttr(attr)) { @@ -399,23 +399,23 @@ static PythonPrimitive omPrimitiveToPythonValue(MlirAttribute attr) { auto moduleStrRef = mlirStringAttrGetValue(hwInnerRefAttrGetModule(innerRef)); auto nameStrRef = mlirStringAttrGetValue(hwInnerRefAttrGetName(innerRef)); - auto moduleStr = py::str(moduleStrRef.data, moduleStrRef.length); - auto nameStr = py::str(nameStrRef.data, nameStrRef.length); - return py::make_tuple(moduleStr, nameStr); + auto moduleStr = nb::str(moduleStrRef.data, moduleStrRef.length); + auto nameStr = nb::str(nameStrRef.data, nameStrRef.length); + return nb::make_tuple(moduleStr, nameStr); } if (omAttrIsAListAttr(attr)) { - py::list results; + nb::list results; for (intptr_t i = 0, e = omListAttrGetNumElements(attr); i < e; ++i) results.append(omPrimitiveToPythonValue(omListAttrGetElement(attr, i))); return results; } if (omAttrIsAMapAttr(attr)) { - py::dict results; + nb::dict results; for (intptr_t i = 0, e = omMapAttrGetNumElements(attr); i < e; ++i) { auto keyStrRef = mlirIdentifierStr(omMapAttrGetElementKey(attr, i)); - auto key = py::str(keyStrRef.data, keyStrRef.length); + auto key = nb::str(keyStrRef.data, keyStrRef.length); auto value = omPrimitiveToPythonValue(omMapAttrGetElementValue(attr, i)); results[key] = value; } @@ -423,7 +423,7 @@ static PythonPrimitive omPrimitiveToPythonValue(MlirAttribute attr) { } mlirAttributeDump(attr); - throw py::type_error("Unexpected OM primitive attribute"); + throw nb::type_error("Unexpected OM primitive attribute"); } // Convert a primitive PythonValue to a generic MLIR Attribute. This is @@ -431,28 +431,28 @@ static PythonPrimitive omPrimitiveToPythonValue(MlirAttribute attr) { // OM dialect. static MlirAttribute omPythonValueToPrimitive(PythonPrimitive value, MlirContext ctx) { - if (auto *intValue = std::get_if(&value)) { + if (auto *intValue = std::get_if(&value)) { auto intType = mlirIntegerTypeGet(ctx, 64); - auto intAttr = mlirIntegerAttrGet(intType, intValue->cast()); + auto intAttr = mlirIntegerAttrGet(intType, nb::cast(*intValue)); return omIntegerAttrGet(intAttr); } - if (auto *attr = std::get_if(&value)) { + if (auto *attr = std::get_if(&value)) { auto floatType = mlirF64TypeGet(ctx); - return mlirFloatAttrDoubleGet(ctx, floatType, attr->cast()); + return mlirFloatAttrDoubleGet(ctx, floatType, nb::cast(*attr)); } - if (auto *attr = std::get_if(&value)) { - auto str = attr->cast(); + if (auto *attr = std::get_if(&value)) { + auto str = nb::cast(*attr); auto strRef = mlirStringRefCreate(str.data(), str.length()); return mlirStringAttrGet(ctx, strRef); } - if (auto *attr = std::get_if(&value)) { - return mlirBoolAttrGet(ctx, attr->cast()); + if (auto *attr = std::get_if(&value)) { + return mlirBoolAttrGet(ctx, nb::cast(*attr)); } - throw py::type_error("Unexpected OM primitive value"); + throw nb::type_error("Unexpected OM primitive value"); } PythonValue omEvaluatorValueToPythonValue(OMEvaluatorValue result) { @@ -460,7 +460,7 @@ PythonValue omEvaluatorValueToPythonValue(OMEvaluatorValue result) { // implemented in pure Python, so nothing to do here besides throwing an // error to halt execution. if (omEvaluatorValueIsNull(result)) - throw py::value_error("unable to get field, see previous error(s)"); + throw nb::value_error("unable to get field, see previous error(s)"); // If the field was an Object, return a new Object. if (omEvaluatorValueIsAObject(result)) @@ -523,58 +523,57 @@ OMEvaluatorValue pythonValueToOMEvaluatorValue(PythonValue result, } // namespace /// Populate the OM Python module. -void circt::python::populateDialectOMSubmodule(py::module &m) { +void circt::python::populateDialectOMSubmodule(nb::module_ &m) { m.doc() = "OM dialect Python native extension"; // Add the Evaluator class definition. - py::class_(m, "Evaluator") - .def(py::init(), py::arg("module")) + nb::class_(m, "Evaluator") + .def(nb::init(), nb::arg("module")) .def("instantiate", &Evaluator::instantiate, "Instantiate an Object", - py::arg("class_name"), py::arg("actual_params")) - .def_property_readonly("module", &Evaluator::getModule, - "The Module the Evaluator is built from"); + nb::arg("class_name"), nb::arg("actual_params")) + .def_prop_ro("module", &Evaluator::getModule, + "The Module the Evaluator is built from"); // Add the List class definition. - py::class_(m, "List") - .def(py::init(), py::arg("list")) + nb::class_(m, "List") + .def(nb::init(), nb::arg("list")) .def("__getitem__", &List::getElement) .def("__len__", &List::getNumElements); - py::class_(m, "Tuple") - .def(py::init(), py::arg("tuple")) + nb::class_(m, "Tuple") + .def(nb::init(), nb::arg("tuple")) .def("__getitem__", &Tuple::getElement) .def("__len__", &Tuple::getNumElements); // Add the Map class definition. - py::class_(m, "Map") - .def(py::init(), py::arg("map")) + nb::class_(m, "Map") + .def(nb::init(), nb::arg("map")) .def("__getitem__", &Map::dunderGetItem) .def("keys", &Map::getKeys) - .def_property_readonly("type", &Map::getType, "The Type of the Map"); + .def_prop_ro("type", &Map::getType, "The Type of the Map"); // Add the BasePath class definition. - py::class_(m, "BasePath") - .def(py::init(), py::arg("basepath")) + nb::class_(m, "BasePath") + .def(nb::init(), nb::arg("basepath")) .def_static("get_empty", &BasePath::getEmpty, - py::arg("context") = py::none()); + nb::arg("context") = nb::none()); // Add the Path class definition. - py::class_(m, "Path") - .def(py::init(), py::arg("path")) + nb::class_(m, "Path") + .def(nb::init(), nb::arg("path")) .def("__str__", &Path::dunderStr); // Add the Object class definition. - py::class_(m, "Object") - .def(py::init(), py::arg("object")) + nb::class_(m, "Object") + .def(nb::init(), nb::arg("object")) .def("__getattr__", &Object::getField, "Get a field from an Object", - py::arg("name")) + nb::arg("name")) .def("get_field_loc", &Object::getFieldLoc, - "Get the location of a field from an Object", py::arg("name")) - .def_property_readonly("field_names", &Object::getFieldNames, - "Get field names from an Object") - .def_property_readonly("type", &Object::getType, "The Type of the Object") - .def_property_readonly("loc", &Object::getLocation, - "The Location of the Object") + "Get the location of a field from an Object", nb::arg("name")) + .def_prop_ro("field_names", &Object::getFieldNames, + "Get field names from an Object") + .def_prop_ro("type", &Object::getType, "The Type of the Object") + .def_prop_ro("loc", &Object::getLocation, "The Location of the Object") .def("__hash__", &Object::getHash, "Get object hash") .def("__eq__", &Object::eq, "Check if two objects are same"); @@ -587,7 +586,7 @@ void circt::python::populateDialectOMSubmodule(py::module &m) { // Add the IntegerAttr definition mlir_attribute_subclass(m, "OMIntegerAttr", omAttrIsAIntegerAttr) .def_classmethod("get", - [](py::object cls, MlirAttribute intVal) { + [](nb::object cls, MlirAttribute intVal) { return cls(omIntegerAttrGet(intVal)); }) .def_property_readonly( diff --git a/lib/Bindings/Python/RTGModule.cpp b/lib/Bindings/Python/RTGModule.cpp index d5729868ab2b..6a601dbea0bb 100644 --- a/lib/Bindings/Python/RTGModule.cpp +++ b/lib/Bindings/Python/RTGModule.cpp @@ -1,4 +1,4 @@ -//===- RTGModule.cpp - RTG API pybind module ------------------------------===// +//===- RTGModule.cpp - RTG API nanobind module ----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -10,56 +10,55 @@ #include "circt-c/Dialect/RTG.h" -#include "mlir/Bindings/Python/PybindAdaptors.h" +#include "mlir/Bindings/Python/NanobindAdaptors.h" -#include -#include -#include -namespace py = pybind11; +#include + +namespace nb = nanobind; using namespace circt; -using namespace mlir::python::adaptors; +using namespace mlir::python::nanobind_adaptors; /// Populate the rtg python module. -void circt::python::populateDialectRTGSubmodule(py::module &m) { +void circt::python::populateDialectRTGSubmodule(nb::module_ &m) { m.doc() = "RTG dialect Python native extension"; mlir_type_subclass(m, "SequenceType", rtgTypeIsASequence) .def_classmethod( "get", - [](py::object cls, MlirContext ctxt) { + [](nb::object cls, MlirContext ctxt) { return cls(rtgSequenceTypeGet(ctxt)); }, - py::arg("self"), py::arg("ctxt") = nullptr); + nb::arg("self"), nb::arg("ctxt") = nullptr); mlir_type_subclass(m, "LabelType", rtgTypeIsALabel) .def_classmethod( "get", - [](py::object cls, MlirContext ctxt) { + [](nb::object cls, MlirContext ctxt) { return cls(rtgLabelTypeGet(ctxt)); }, - py::arg("self"), py::arg("ctxt") = nullptr); + nb::arg("self"), nb::arg("ctxt") = nullptr); mlir_type_subclass(m, "SetType", rtgTypeIsASet) .def_classmethod( "get", - [](py::object cls, MlirType elementType) { + [](nb::object cls, MlirType elementType) { return cls(rtgSetTypeGet(elementType)); }, - py::arg("self"), py::arg("element_type")); + nb::arg("self"), nb::arg("element_type")); mlir_type_subclass(m, "BagType", rtgTypeIsABag) .def_classmethod( "get", - [](py::object cls, MlirType elementType) { + [](nb::object cls, MlirType elementType) { return cls(rtgBagTypeGet(elementType)); }, - py::arg("self"), py::arg("element_type")); + nb::arg("self"), nb::arg("element_type")); mlir_type_subclass(m, "DictType", rtgTypeIsADict) .def_classmethod( "get", - [](py::object cls, MlirContext ctxt, + [](nb::object cls, MlirContext ctxt, const std::vector> &entries) { std::vector names; std::vector types; @@ -70,7 +69,7 @@ void circt::python::populateDialectRTGSubmodule(py::module &m) { return cls( rtgDictTypeGet(ctxt, types.size(), names.data(), types.data())); }, - py::arg("self"), py::arg("ctxt") = nullptr, - py::arg("entries") = + nb::arg("self"), nb::arg("ctxt") = nullptr, + nb::arg("entries") = std::vector>()); } diff --git a/lib/Bindings/Python/RTGTestModule.cpp b/lib/Bindings/Python/RTGTestModule.cpp index 9e69d6ac3491..efe64461aad4 100644 --- a/lib/Bindings/Python/RTGTestModule.cpp +++ b/lib/Bindings/Python/RTGTestModule.cpp @@ -1,4 +1,4 @@ -//===- RTGTestModule.cpp - RTGTest API pybind module ----------------------===// +//===- RTGTestModule.cpp - RTGTest API nanobind module --------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -10,35 +10,33 @@ #include "circt-c/Dialect/RTGTest.h" -#include "mlir/Bindings/Python/PybindAdaptors.h" +#include "mlir/Bindings/Python/NanobindAdaptors.h" -#include -#include -#include -namespace py = pybind11; +#include +namespace nb = nanobind; using namespace circt; -using namespace mlir::python::adaptors; +using namespace mlir::python::nanobind_adaptors; /// Populate the rtgtest python module. -void circt::python::populateDialectRTGTestSubmodule(py::module &m) { +void circt::python::populateDialectRTGTestSubmodule(nb::module_ &m) { m.doc() = "RTGTest dialect Python native extension"; mlir_type_subclass(m, "CPUType", rtgtestTypeIsACPU) .def_classmethod( "get", - [](py::object cls, MlirContext ctxt) { + [](nb::object cls, MlirContext ctxt) { return cls(rtgtestCPUTypeGet(ctxt)); }, - py::arg("self"), py::arg("ctxt") = nullptr); + nb::arg("self"), nb::arg("ctxt") = nullptr); mlir_attribute_subclass(m, "CPUAttr", rtgtestAttrIsACPU) .def_classmethod( "get", - [](py::object cls, unsigned id, MlirContext ctxt) { + [](nb::object cls, unsigned id, MlirContext ctxt) { return cls(rtgtestCPUAttrGet(ctxt, id)); }, - py::arg("self"), py::arg("id"), py::arg("ctxt") = nullptr) + nb::arg("self"), nb::arg("id"), nb::arg("ctxt") = nullptr) .def_property_readonly( "id", [](MlirAttribute self) { return rtgtestCPUAttrGetId(self); }); } diff --git a/lib/Bindings/Python/RTGToolModule.cpp b/lib/Bindings/Python/RTGToolModule.cpp index 06d25c506d80..ffa3bee3d934 100644 --- a/lib/Bindings/Python/RTGToolModule.cpp +++ b/lib/Bindings/Python/RTGToolModule.cpp @@ -1,4 +1,4 @@ -//===- RTGToolModule.cpp - RTG Tool API pybind module ---------------------===// +//===- RTGToolModule.cpp - RTG Tool API nanobind module -------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -10,12 +10,10 @@ #include "circt-c/RtgTool.h" -#include "mlir/Bindings/Python/PybindAdaptors.h" +#include "mlir/Bindings/Python/NanobindAdaptors.h" -#include -#include -#include -namespace py = pybind11; +#include +namespace nb = nanobind; using namespace circt; @@ -75,48 +73,48 @@ class PyRtgToolOptions { } // namespace /// Populate the rtgtool python module. -void circt::python::populateDialectRTGToolSubmodule(py::module &m) { +void circt::python::populateDialectRTGToolSubmodule(nb::module_ &m) { m.doc() = "RTGTool Python native extension"; - py::enum_(m, "OutputFormat") + nb::enum_(m, "OutputFormat") .value("MLIR", CIRCT_RTGTOOL_OUTPUT_FORMAT_MLIR) .value("ELABORATED_MLIR", CIRCT_RTGTOOL_OUTPUT_FORMAT_ELABORATED_MLIR) .value("ASM", CIRCT_RTGTOOL_OUTPUT_FORMAT_ASM); - py::class_(m, "Options") - .def(py::init(m, "Options") + .def(nb::init &, const std::string &>(), - py::arg("seed"), - py::arg("output_format") = CIRCT_RTGTOOL_OUTPUT_FORMAT_ASM, - py::arg("verify_passes") = true, - py::arg("verbose_pass_execution") = false, - py::arg("unsupported_instructions") = std::vector(), - py::arg("unsupported_instructions_file") = "") + nb::arg("seed"), + nb::arg("output_format") = CIRCT_RTGTOOL_OUTPUT_FORMAT_ASM, + nb::arg("verify_passes") = true, + nb::arg("verbose_pass_execution") = false, + nb::arg("unsupported_instructions") = std::vector(), + nb::arg("unsupported_instructions_file") = "") .def("set_output_format", &PyRtgToolOptions::setOutputFormat, - "Specify the output format of the tool", py::arg("format")) + "Specify the output format of the tool", nb::arg("format")) .def("set_seed", &PyRtgToolOptions::setSeed, - "Specify the seed for all RNGs used in the tool", py::arg("seed")) + "Specify the seed for all RNGs used in the tool", nb::arg("seed")) .def("set_verify_passes", &PyRtgToolOptions::setVerifyPasses, "Specify whether the verifiers should be run after each pass", - py::arg("enable")) + nb::arg("enable")) .def("set_verbose_pass_execution", &PyRtgToolOptions::setVerbosePassExecution, "Specify whether passes should run in verbose mode", - py::arg("enable")) + nb::arg("enable")) .def("set_unsupported_instructions", &PyRtgToolOptions::setUnsupportedInstructions, "Set the list of of instructions unsupported by the assembler", - py::arg("instructions")) + nb::arg("instructions")) .def("add_unsupported_instruction", &PyRtgToolOptions::addUnsupportedInstruction, "Add the instruction given by name to the list of instructions not " "supported by the assembler", - py::arg("instruction_name")) + nb::arg("instruction_name")) .def("set_unsupported_instructions_file", &PyRtgToolOptions::setUnsupportedInstructionsFile, "Register a file containing a comma-separated list of instruction " "names which are not supported by the assembler.", - py::arg("filename")); + nb::arg("filename")); m.def("populate_randomizer_pipeline", [](MlirPassManager pm, const PyRtgToolOptions &options) { diff --git a/lib/Bindings/Python/SVModule.cpp b/lib/Bindings/Python/SVModule.cpp index 74b3df2f1d47..c2ff630155b7 100644 --- a/lib/Bindings/Python/SVModule.cpp +++ b/lib/Bindings/Python/SVModule.cpp @@ -1,4 +1,4 @@ -//===- SVModule.cpp - SV API pybind module --------------------------------===// +//===- SVModule.cpp - SV API nanobind module ------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,55 +11,60 @@ #include "circt-c/Dialect/SV.h" #include "mlir-c/Bindings/Python/Interop.h" -#include "mlir/Bindings/Python/PybindAdaptors.h" +#include "mlir/Bindings/Python/NanobindAdaptors.h" #include "mlir/CAPI/IR.h" #include "mlir/CAPI/Support.h" #include "llvm/ADT/SmallVector.h" -#include "PybindUtils.h" -#include -#include -namespace py = pybind11; +#include "NanobindUtils.h" +#include +#include +namespace nb = nanobind; -using namespace mlir::python::adaptors; +using namespace mlir::python::nanobind_adaptors; -void circt::python::populateDialectSVSubmodule(py::module &m) { +void circt::python::populateDialectSVSubmodule(nb::module_ &m) { m.doc() = "SV Python Native Extension"; mlir_attribute_subclass(m, "SVAttributeAttr", svAttrIsASVAttributeAttr) .def_classmethod( "get", - [](py::object cls, std::string name, py::object expressionObj, - bool emitAsComment, MlirContext ctxt) { + [](nb::object cls, std::string name, nb::object expressionObj, + nb::object emitAsCommentObj, MlirContext ctxt) { + // Set emitAsComment from optional boolean flag. + bool emitAsComment = false; + if (!emitAsCommentObj.is_none()) + emitAsComment = nb::cast(emitAsCommentObj); + // Need temporary storage for casted string. std::string expr; MlirStringRef expression = {nullptr, 0}; if (!expressionObj.is_none()) { - expr = expressionObj.cast(); + expr = nb::cast(expressionObj); expression = mlirStringRefCreateFromCString(expr.c_str()); } return cls(svSVAttributeAttrGet( ctxt, mlirStringRefCreateFromCString(name.c_str()), expression, emitAsComment)); }, - "Create a SystemVerilog attribute", py::arg(), py::arg("name"), - py::arg("expression") = py::none(), - py::arg("emit_as_comment") = py::none(), py::arg("ctxt") = py::none()) + "Create a SystemVerilog attribute", nb::arg(), nb::arg("name"), + nb::arg("expression") = nb::none(), + nb::arg("emit_as_comment") = nb::none(), nb::arg("ctxt") = nb::none()) .def_property_readonly("name", [](MlirAttribute self) { MlirStringRef name = svSVAttributeAttrGetName(self); return std::string(name.data, name.length); }) - .def_property_readonly( - "expression", - [](MlirAttribute self) -> py::object { - MlirStringRef name = svSVAttributeAttrGetExpression(self); - if (name.data == nullptr) - return py::none(); - return py::str(std::string(name.data, name.length)); - }) + .def_property_readonly("expression", + [](MlirAttribute self) -> nb::object { + MlirStringRef name = + svSVAttributeAttrGetExpression(self); + if (name.data == nullptr) + return nb::none(); + return nb::str(name.data, name.length); + }) .def_property_readonly("emit_as_comment", [](MlirAttribute self) { return svSVAttributeAttrGetEmitAsComment(self); }); diff --git a/lib/Bindings/Python/SeqModule.cpp b/lib/Bindings/Python/SeqModule.cpp index 3374b193b0da..fb49cbc9bfd0 100644 --- a/lib/Bindings/Python/SeqModule.cpp +++ b/lib/Bindings/Python/SeqModule.cpp @@ -1,4 +1,4 @@ -//===- SeqModule.cpp - Seq API pybind module ------------------------------===// +//===- SeqModule.cpp - Seq API nanobind module ----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -9,34 +9,32 @@ #include "CIRCTModules.h" #include "circt-c/Dialect/Seq.h" -#include "mlir/Bindings/Python/PybindAdaptors.h" +#include "mlir/Bindings/Python/NanobindAdaptors.h" -#include "PybindUtils.h" +#include "NanobindUtils.h" #include "mlir-c/Support.h" -#include -#include -#include +#include -namespace py = pybind11; +namespace nb = nanobind; using namespace circt; -using namespace mlir::python::adaptors; +using namespace mlir::python::nanobind_adaptors; /// Populate the seq python module. -void circt::python::populateDialectSeqSubmodule(py::module &m) { +void circt::python::populateDialectSeqSubmodule(nb::module_ &m) { m.doc() = "Seq dialect Python native extension"; mlir_type_subclass(m, "ClockType", seqTypeIsAClock) .def_classmethod( "get", - [](py::object cls, MlirContext ctx) { + [](nb::object cls, MlirContext ctx) { return cls(seqClockTypeGet(ctx)); }, - py::arg("cls"), py::arg("context") = py::none()); + nb::arg("cls"), nb::arg("context") = nb::none()); mlir_type_subclass(m, "ImmutableType", seqTypeIsAImmutable) .def_classmethod("get", - [](py::object cls, MlirType innerType) { + [](nb::object cls, MlirType innerType) { return cls(seqImmutableTypeGet(innerType)); }) .def_property_readonly("inner_type", [](MlirType self) { diff --git a/lib/Bindings/Python/SupportModule.cpp b/lib/Bindings/Python/SupportModule.cpp index ed159c5aa554..0f56a1547c02 100644 --- a/lib/Bindings/Python/SupportModule.cpp +++ b/lib/Bindings/Python/SupportModule.cpp @@ -1,4 +1,4 @@ -//===- SupportModule.cpp - Support API pybind module ----------------------===// +//===- SupportModule.cpp - Support API nanobind module --------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -8,43 +8,41 @@ #include "CIRCTModules.h" -#include "mlir/Bindings/Python/PybindAdaptors.h" +#include "mlir/Bindings/Python/NanobindAdaptors.h" -#include "PybindUtils.h" +#include "NanobindUtils.h" #include "mlir-c/Support.h" -#include -#include -#include +#include -namespace py = pybind11; +namespace nb = nanobind; using namespace circt; -using namespace mlir::python::adaptors; +using namespace mlir::python::nanobind_adaptors; /// Populate the support python module. -void circt::python::populateSupportSubmodule(py::module &m) { +void circt::python::populateSupportSubmodule(nb::module_ &m) { m.doc() = "CIRCT Python utils"; // Walk with filter. m.def( "_walk_with_filter", [](MlirOperation operation, const std::vector &opNames, - std::function callback, - py::object walkOrderRaw) { + std::function callback, + nb::object walkOrderRaw) { struct UserData { - std::function callback; + std::function callback; bool gotException; std::string exceptionWhat; - py::object exceptionType; + nb::handle exceptionType; std::vector opNames; }; - // As we transition from pybind11 to nanobind, the WalkOrder enum and + // As we transition from nanobind to nanobind, the WalkOrder enum and // automatic casting will be defined as a nanobind enum upstream. Do a - // manual conversion that works with either pybind11 or nanobind for + // manual conversion that works with either nanobind or nanobind for // now. When we're on nanobind in CIRCT, we can go back to automatic // casting. MlirWalkOrder walkOrder; - auto walkOrderRawValue = py::cast(walkOrderRaw.attr("value")); + auto walkOrderRawValue = nb::cast(walkOrderRaw.attr("value")); switch (walkOrderRawValue) { case 0: walkOrder = MlirWalkOrder::MlirWalkPreOrder; @@ -84,15 +82,15 @@ void circt::python::populateSupportSubmodule(py::module &m) { return MlirWalkResult::MlirWalkResultAdvance; try { - // As we transition from pybind11 to nanobind, the WalkResult enum + // As we transition from nanobind to nanobind, the WalkResult enum // and automatic casting will be defined as a nanobind enum - // upstream. Do a manual conversion that works with either pybind11 + // upstream. Do a manual conversion that works with either nanobind // or nanobind for now. When we're on nanobind in CIRCT, we can go // back to automatic casting. MlirWalkResult walkResult; auto walkResultRaw = (calleeUserData->callback)(op); auto walkResultRawValue = - py::cast(walkResultRaw.attr("value")); + nb::cast(walkResultRaw.attr("value")); switch (walkResultRawValue) { case 0: walkResult = MlirWalkResult::MlirWalkResultAdvance; @@ -105,7 +103,7 @@ void circt::python::populateSupportSubmodule(py::module &m) { break; } return walkResult; - } catch (py::error_already_set &e) { + } catch (nb::python_error &e) { calleeUserData->gotException = true; calleeUserData->exceptionWhat = e.what(); calleeUserData->exceptionType = e.type(); @@ -119,6 +117,6 @@ void circt::python::populateSupportSubmodule(py::module &m) { throw std::runtime_error(message); } }, - py::arg("op"), py::arg("op_names"), py::arg("callback"), - py::arg("walk_order")); + nb::arg("op"), nb::arg("op_names"), nb::arg("callback"), + nb::arg("walk_order")); }