diff --git a/.github/workflows/nightlyIntegrationTests.yml b/.github/workflows/nightlyIntegrationTests.yml index c785f4c361..d06f277a1a 100644 --- a/.github/workflows/nightlyIntegrationTests.yml +++ b/.github/workflows/nightlyIntegrationTests.yml @@ -13,7 +13,7 @@ jobs: name: Build LLVM runs-on: ubuntu-latest container: - image: ghcr.io/circt/images/circt-integration-test:v3 + image: ghcr.io/circt/images/circt-integration-test:v5 steps: # Clone the CIRCT repo and its submodules. Do shallow clone to save clone # time. @@ -35,12 +35,12 @@ jobs: uses: actions/cache@v2 with: path: llvm - key: ${{ runner.os }}-llvm-sharedlibs-${{ steps.get-llvm-hash.outputs.hash }} + key: ${{ runner.os }}-llvm-sharedlibs-python-${{ steps.get-llvm-hash.outputs.hash }} # Build LLVM if we didn't hit in the cache. - name: Rebuild and Install LLVM if: steps.cache-llvm.outputs.cache-hit != 'true' - run: utils/build-llvm.sh + run: utils/build-llvm.sh build install Release -DMLIR_BINDINGS_PYTHON_ENABLED=ON # Build CIRCT and run its tests using a Docker container with all the # integration testing prerequisite installed. @@ -60,6 +60,9 @@ jobs: cxx: clang++ - cc: gcc cxx: g++ + include: + - build-shared: ON + bindings-python: ON steps: - name: Configure Environment @@ -89,12 +92,12 @@ jobs: uses: actions/cache@v2 with: path: llvm - key: ${{ runner.os }}-llvm-sharedlibs-${{ steps.get-llvm-hash.outputs.hash }} + key: ${{ runner.os }}-llvm-sharedlibs-python-${{ steps.get-llvm-hash.outputs.hash }} # Build LLVM if we didn't hit in the cache. - name: Rebuild and Install LLVM if: steps.cache-llvm.outputs.cache-hit != 'true' - run: utils/build-llvm.sh + run: utils/build-llvm.sh build install Release -DMLIR_BINDINGS_PYTHON_ENABLED=ON # -------- # Build and test CIRCT @@ -107,6 +110,7 @@ jobs: BUILD_ASSERT: ${{ matrix.build-assert }} BUILD_SHARED: ${{ matrix.build-shared }} BUILD_TYPE: ${{ matrix.build-type }} + BINDINGS_PYTHON: ${{matrix.bindings-python}} run: | mkdir build && cd build cmake .. \ @@ -120,7 +124,7 @@ jobs: -DCMAKE_CXX_COMPILER=$CXX \ -DLLVM_EXTERNAL_LIT=`pwd`/../llvm/build/bin/llvm-lit \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCIRCT_BINDINGS_PYTHON_ENABLED=ON \ + -DCIRCT_BINDINGS_PYTHON_ENABLED=$BINDINGS_PYTHON \ -DPYTHON_EXECUTABLE=/usr/bin/python3 - name: Build CIRCT run: | diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md index ad8d9461c3..06824af20c 100644 --- a/docs/GettingStarted.md +++ b/docs/GettingStarted.md @@ -21,6 +21,12 @@ These commands can be used to setup CIRCT project: instructions](https://mlir.llvm.org/getting_started/), including cmake and ninja. +If you plan to use the Python bindings, you should start by reading [the + instructions](https://mlir.llvm.org/docs/Bindings/Python/#building) for building +the MLIR Python bindings, which describe extra dependencies, CMake variables, +and helpful Python development practices. Note the extra CMake variables, which +you will need to specify in step 3) below. + 2) **Check out LLVM and CIRCT repos.** CIRCT contains LLVM as a git submodule. The LLVM repo here includes staged changes to MLIR which may be necessary to support CIRCT. It also represents the version of @@ -85,6 +91,8 @@ To get something that runs fast, use `-DCMAKE_BUILD_TYPE=Release` or you want debug info to go with it. `Release` mode makes a very large difference in performance. +If you plan to use the Python bindings, you should also specify +`-DCIRCT_BINDINGS_PYTHON_ENABLED=ON`. 5) **Optionally configure your environment**: diff --git a/include/circt/Dialect/RTL/RTL.td b/include/circt/Dialect/RTL/RTL.td index e5a7fc47e2..115bc2978f 100644 --- a/include/circt/Dialect/RTL/RTL.td +++ b/include/circt/Dialect/RTL/RTL.td @@ -32,13 +32,13 @@ def RTLDialect : Dialect { let cppNamespace = "::circt::rtl"; } -include "RTLTypes.td" +include "circt/Dialect/RTL/RTLTypes.td" // Base class for the operation in this dialect. class RTLOp traits = []> : Op; -include "RTLAggregates.td" -include "RTLStructure.td" +include "circt/Dialect/RTL/RTLAggregates.td" +include "circt/Dialect/RTL/RTLStructure.td" #endif // RTL_TD diff --git a/integration_test/Bindings/Python/dialects/rtl.py b/integration_test/Bindings/Python/dialects/rtl.py new file mode 100644 index 0000000000..fe91b01539 --- /dev/null +++ b/integration_test/Bindings/Python/dialects/rtl.py @@ -0,0 +1,16 @@ +# REQUIRES: bindings_python +# RUN: %PYTHON% %s | FileCheck %s + +import circt +from circt.dialects import rtl + +from mlir.ir import * + +with Context() as ctx, Location.unknown(): + circt.register_dialects(ctx) + i32 = IntegerType.get_signless(32) + a50 = IntegerAttr.get(i32, 50) + op = rtl.ConstantOp(i32, a50) + + # CHECK: %{{.+}} = rtl.constant 50 : i32 + op.print() diff --git a/lib/Bindings/Python/CIRCTModule.cpp b/lib/Bindings/Python/CIRCTModule.cpp index 610a1e9786..c9eeaf0f27 100644 --- a/lib/Bindings/Python/CIRCTModule.cpp +++ b/lib/Bindings/Python/CIRCTModule.cpp @@ -6,6 +6,27 @@ // //===----------------------------------------------------------------------===// -#include +#include "circt-c/Dialect/RTL.h" +#include "mlir-c/Bindings/Python/Interop.h" +#include "mlir-c/Registration.h" -PYBIND11_MODULE(_circt, m) { m.doc() = "CIRCT Python Native Extension"; } +#include +namespace py = pybind11; + +PYBIND11_MODULE(_circt, m) { + m.doc() = "CIRCT Python Native Extension"; + + m.def( + "register_dialects", + [](py::object capsule) { + // Get the MlirContext capsule from PyMlirContext capsule. + auto wrappedCapsule = capsule.attr(MLIR_PYTHON_CAPI_PTR_ATTR); + MlirContext context = mlirPythonCapsuleToContext(wrappedCapsule.ptr()); + + // Collect CIRCT dialects to register. + MlirDialectHandle rtl = mlirGetDialectHandle__rtl__(); + mlirDialectHandleRegisterDialect(rtl, context); + mlirDialectHandleLoadDialect(rtl, context); + }, + "Register CIRCT dialects on a PyMlirContext."); +} diff --git a/lib/Bindings/Python/CMakeLists.txt b/lib/Bindings/Python/CMakeLists.txt index 7176558b28..93354f3342 100644 --- a/lib/Bindings/Python/CMakeLists.txt +++ b/lib/Bindings/Python/CMakeLists.txt @@ -14,6 +14,8 @@ add_mlir_python_extension(CIRCTBindingsPythonExtension _circt python SOURCES CIRCTModule.cpp + LINK_LIBS + CIRCTCAPIRTL ) add_dependencies(CIRCTBindingsPython CIRCTBindingsPythonExtension) @@ -42,3 +44,11 @@ foreach(PY_SRC_FILE ${PY_SRC_FILES}) "${CMAKE_CURRENT_SOURCE_DIR}/${PY_SRC_FILE}" "${PY_DEST_FILE}" ) endforeach() + +################################################################################ +# Generate dialect-specific bindings. +################################################################################ +add_mlir_dialect_python_bindings(CIRCTBindingsPythonRTLOps + TD_FILE RTLOps.td + DIALECT_NAME rtl) +add_dependencies(CIRCTBindingsPythonSources CIRCTBindingsPythonRTLOps) diff --git a/lib/Bindings/Python/RTLOps.td b/lib/Bindings/Python/RTLOps.td new file mode 100644 index 0000000000..a53cc937fb --- /dev/null +++ b/lib/Bindings/Python/RTLOps.td @@ -0,0 +1,15 @@ +//===-- RTLOps.td - Entry point for RTLOps bindings --------*- tablegen -*-===// +// +// 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_RTL_OPS +#define BINDINGS_PYTHON_RTL_OPS + +include "mlir/Bindings/Python/Attributes.td" +include "circt/Dialect/RTL/RTL.td" + +#endif diff --git a/lib/Bindings/Python/circt/__init__.py b/lib/Bindings/Python/circt/__init__.py index 10ec0804ce..99730e22c4 100644 --- a/lib/Bindings/Python/circt/__init__.py +++ b/lib/Bindings/Python/circt/__init__.py @@ -2,4 +2,5 @@ # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# Simply a wrapper around the extension module of the same name. from _circt import * diff --git a/lib/Bindings/Python/circt/dialects/_ods_common.py b/lib/Bindings/Python/circt/dialects/_ods_common.py new file mode 100644 index 0000000000..2382ed1e3b --- /dev/null +++ b/lib/Bindings/Python/circt/dialects/_ods_common.py @@ -0,0 +1,7 @@ +# 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 + +# Generated tablegen dialects expect to be able to find some symbols from +# the mlir.dialects package. +from mlir.dialects._ods_common import _cext, segmented_accessor, equally_sized_accessor, extend_opview_class, get_default_loc_context diff --git a/lib/Bindings/Python/circt/dialects/rtl.py b/lib/Bindings/Python/circt/dialects/rtl.py new file mode 100644 index 0000000000..2e5d4535a9 --- /dev/null +++ b/lib/Bindings/Python/circt/dialects/rtl.py @@ -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 + +# Generated tablegen dialects end up in the mlir.dialects package for now. +from mlir.dialects._rtl_ops_gen import * diff --git a/utils/build-llvm.sh b/utils/build-llvm.sh index 1791bb2dd7..2b959b477b 100755 --- a/utils/build-llvm.sh +++ b/utils/build-llvm.sh @@ -15,6 +15,7 @@ BUILD_DIR=${1:-"build"} INSTALL_DIR=${2:-"install"} BUILD_TYPE=${3:-"Release"} +EXTRA_ARGS=${@:4} mkdir -p llvm/$BUILD_DIR mkdir -p llvm/$INSTALL_DIR @@ -33,6 +34,7 @@ cmake ../llvm \ -DLLVM_ENABLE_PROJECTS='mlir' \ -DLLVM_INSTALL_UTILS=ON \ -DLLVM_OPTIMIZED_TABLEGEN=ON \ - -DLLVM_TARGETS_TO_BUILD="host" + -DLLVM_TARGETS_TO_BUILD="host" \ + $EXTRA_ARGS cmake --build . --target install -- -j$(nproc) diff --git a/utils/run-docker.sh b/utils/run-docker.sh index 940ee9a7c8..8550d80698 100755 --- a/utils/run-docker.sh +++ b/utils/run-docker.sh @@ -20,7 +20,7 @@ ##===----------------------------------------------------------------------===## CMD=${1:-"./utils/run-tests-docker.sh"} -VER=${2:-"v3"} +VER=${2:-"v5"} REPO_ROOT=$(cd "$(dirname "$BASH_SOURCE[0]")/.." && pwd) cd $REPO_ROOT