Development Guide

Ready to contribute to the Quantum Compilation Suite of the MQSS? This guide will help you get started.

Development Environment

  • It is recommended to use a docker container to ensure consistent, stable development environment.

  • The required DockerFile and devcontainer.json are provided in .devcontainer directory. Build and RUN the docker container using the following commands:

docker build -t mqss-pass-dev -f .devcontainer/Dockerfile .
docker run --rm -it \
  -v "$PWD":/workspaces/MQSS-Passes-Suite \
  -w /workspaces/MQSS-Passes-Suite \
  mqss-pass-dev \
  bash

Building the tool

  • The driver script is the MakeFile within the project root.

  • The MakeFile invokes build scripts within scripts/. build_cudaq.sh: Downloads and installs dependencies and configures build for target mqss-cudaq-opt build_catalyst.sh: Downloads and installs dependencies and configures build for target mqss-catalyst-opt setup-env.sh: Sets up a virtual environment and installs python3.11 in it.

  • The ```make`` commands to build the targets remain the same as in the README. Ensure the sequence of commands is followed.

Project structure

The key directory which contains the source code is lib/. Its structure is:

lib/
├── common/
│   ├── include/
│   └─ Passes/
└── mqss-cudaq/
│   ├── CMakeLists.txt
│   ├── cudaq.cpp
│   ├── include/
│   ├── lib/
│   └── cmake/
└── mqss-catalyst/
    ├── CMakeLists.txt
    ├── catalyst.cpp
    ├── include/
    ├── lib/
    └── cmake/
  • The Dialect Agnostic MLIR optimization passes can be found in common/Passes whereas, dialect specific passes can be found in mqss-cudaq/lib/MQSSQuakePasses and mqss-catalyst/lib/MQSScatalystPasses. Currently, passes for either quake or catalyst-quantum dialects are added.

  • All dialect related files can be found in include/IR and lib/IR. Of these, the important ones are the table-gen files (.td) found in include/IR , which comprise the dialect operation definitions.

Testing

  • We use python-lit along-with ninja and FileCheck to perform dialect-level (input: MLIR dialect; output: MLIR dialect) as well as end-to-end (input:c++/python code; output: MLIR dialect) testing. In the end, what is tested for correctness is the output optimized/transformed MLIR dialect.

  • The tests can be found in directories : tests/dialects and tests/code.

  • Dialect-level testing

    1. The input dialect is annotated with the RUN command, for e.g.:

    // RUN: %mqss-catalyst-opt %s --CommonCommutePass=mode=CX-X 2>&1 | FileCheck %s which runs the target/executable mqss-catalyst-opt along-with the pass CommonCommutePass. FileCheck looks for strings to match, specified using the CHECK: keyword, for e.g.

    // CHECK: %out_qubits = quantum.custom "PauliX"() %2 : !quantum.bit
    // CHECK: %out_qubits_0:2 = quantum.custom "CNOT"() %1, %2 : !quantum.bit, !quantum.bit
    

    If an exact match is found in the output dialect, the test succeeds, otherwise the test fails. 2. End-to-End testing In this testing, the input is a c++/python code, which is then translated to the input MLIR dialect. The testing then proceeds as in (1). The emphasis here is on testing the front-end translation pipeline as well as the transformed dialects. A wrapper script mqss-cc is used to invoke the necessary tools to translate the c++/python code to the input quake or catalyst-quantum dialect. If the input code to MLIR dialect translation fails, then the test itself will fail. An example test file performing such a test is shown below:

     // RUN: %mqss-cc %S/../CommuteCNotRxPass.cpp --passes=CommonCommutePass=mode=CX-RX | FileCheck %s
    
     // CHECK: quake.rx (%cst_1) %4 : (f64, !quake.ref) -> ()
     // CHECK-NEXT: quake.x [%1] %2 : (!quake.ref, !quake.ref) -> ()
    

    The test proceeds as follows:

    1. mqss-cc parses the command-line arguments %S/../CommuteCNotRxPass.cpp --passes=CommonCommutePass=mode=CX-RX

    2. Since, a c++ code is the input, it is assumed that the code contains a quantum circuit defined using cudaq .

    3. The c++ to quake dialect translation pipeline is invoked via the tool cudaq-quake

    4. Once the input dialect is generated, mqss-cudaq-opt tool is used to apply MQSS optimization/translation passes defined using the --passes flag.

    5. Finally, the optimized/transformed dialect is emitted which is checked by FileCheck.

Enabling Pass Debug Information

The Pass debug information can be enabled by passing in the flag --debug to the DEBUG_FLAG variable within the MakeFile. Simply remove the flag if no debug information is needed.

Enabling clangd for linting

RUN command : make compile_commands.

  • This creates a symlink from _deps/mqss-cudaq/clang+llvm-16.0.4-aarch64-linux-gnu/bin/clangd to /usr/local/bin/clangd

  • It also creates a file compile_commands.json within build/