# Architecture Overview

This document give a high-level overview of the CUDA-Q codebase. If you want to
familiarize yourself with the code on this repository, this is the document for
you.

## Bird's Eye View

CUDA-Q is first-and-foremost a heterogeneous quantum-classical programming model
in modern C++. The model enables programmers to define typed-callables (implicit
or explicit) that encodes some action to be executed on an available quantum
coprocessor.

To implement this model, this repository provides an MLIR-based compiler. The
compiler maps the C++ abstract syntax tree (AST) generated by Clang to internal
MLIR dialects for quantum and classical computing. These dialects are further
lowered to LLVM adherent to the Quantum Intermediate Representation (QIR)
specification which can be readily lowered to object code.

The quantum-specific dialect put forward by this repository is the Quantum
Kernel Execution (Quake). Quake sits closer to the source language and provides
a memory-semantics model of qubits and operations on those qubits. Quake can
encode runtime-known information, and is therefore a generator of concrete
quantum circuits. Quake also supports a value-semantics model of quantum
computing whereby quantum operations consume qubit values and produce a new
qubit value. Quake is therefore well suited for optimizations and can encode
fully-known, concrete quantum circuits.

We also provide a dialect for classical computing abstractions, specifically
modeling types and operations in C++ required to build Quake functions. This is
the CC dialect.

The dialects for Quake and CC are defined in

[Quake](https://github.com/NVIDIA/cuda-quantum/blob/main/cudaq/include/cudaq/Optimizer/Dialect/Quake/QuakeOps.td)

[CC](https://github.com/NVIDIA/cuda-quantum/blob/main/cudaq/include/cudaq/Optimizer/Dialect/CC/CCOps.td)

We have designed the compiler to be modular, and the compiler workflow itself is
composed of a set of tools (executables) that achieve a specific task.

## Code Map

### `include/cudaq/Frontend/nvqpp`

This folder contains the header files for the AST Bridge. The AST Bridge is
responsible for mapping C++ to Quake MLIR via the Clang abstract syntax tree.
Specifically, `ASTBridge.h` contains a subtype of the
`clang::RecursiveASTVisitor<T>` that enables one to visit the various nodes of
the AST and perform custom actions based on the data in the node. We keep track
of a `RecursiveASTVisitor` which contains an `mlir::ModuleOp` member, which we
build up with Quake and classical MLIR operations.

### `include/cudaq/Optimizer`

This folder contains the header files defining the MLIR dialects and
transformations used by CUDA-Q. The `Dialect` folder contains the tablegen
definitions for Quake and CC. The `CodeGen` folder declares the tablegen
required to define MLIR Passes that lower Quake to code, specifically LLVM IR.
The `Transforms` folder contains the tablegen necessary for transformations on
Quake and CC (e.g. things like lambda lifting, generating extra kernel glue
code, etc.).

### `include/cudaq/Target`

This folder contains the headers for taking Quake to other quantum programming
languages like OpenQASM.

### `lib/Frontend/nvqpp`

This folder contains the implementation code for the `RecursiveASTVisitor` that
maps C++ to Quake. Separate implementation files are defined for translating
Clang `Expr`, `Stmt`, and `Decl` types.

### `lib/Optimizer`

This folder contains the implementation code for the MLIR dialects and
transformations used by the compiler. The structure here is pretty
self-explanatory. The dialect implementation is in the `Dialect` folder (for
Quake and CC). All transformations on the IR are provided in the `Transforms`
folder. Conversions between dialects are in the `Conversion` folder. The passes
that lower MLIR to LLVM IR code are provided in the `CodeGen` folder.

### `lib/Target`

This folder contains the implementation code for mapping Quake to other quantum
programming languages.

### `runtime/common`

This folder contains the code for the `cudaq-common` library. This library is
used by the other runtime libraries and provides the `MeasureCounts`,
`ObserveResult`, `ExecutionContext`, and logging utility types.

### `runtime/nvqir`

This folder contains the code for a library that implements the QIR
specification. `libnvqir` implements the specified QIR QIS and runtime functions
and delegates to an extensible `CircuitSimulator` API. This API is implemented
for CPU-only simulation (OpenMP multi-threaded) and GPU-based simulation via
cuQuantum. Switching the backend simulation capability is a link-time task that
is handled implicitly by `nvq++`.

### `runtime/cudaq`

This folder contains the CUDA-Q runtime library. The headers in this folder
directly implement the CUDA-Q specification, and in doing so, enables the
`nvq++` compiler to generate a full, valid Clang AST that can be processed and
lowered the the MLIR. Moreover, by implementing the specification types and
functions, we are able to use this library to enforce aspects of the
specification at compile time. For example, the specification says that qubits
can not be copied, therefore this runtime library defines the qubit type with a
deleted copy constructor. Any violations of this aspect of the specification
will trigger a standard compiler error. We therefore pick-up existing compiler
diagnostics infrastructures for free.

Specifically, this library provides the `qudit`, `qubit`, `qreg`, and `qspan`
types, the intrinsic quantum operations, and the algorithmic primitives like
`cudaq::sample`, `cudaq::observe`, and `cudaq::evolve`, as well as their
asynchronous versions.

This library defines the `quantum_platform` architecture, enabling CUDA-Q to
target both simulated and physical quantum computing architectures.

### `tools/cudaq-quake`

This folder contains the implementation of the `cudaq-quake` tool. This tool
orchestrates the creation of the `RecursiveASTVisitor` that walks the Clang AST
representation of input source file and outputs a Quake file for all CUDA-Q
kernels in the code. It will also output the classical LLVM IR representation of
the code (with the CUDA-Q runtime headers) with the specification of the
`--emit-llvm-file` flag.

### `tools/cudaq-opt`

This folder contains the implementation of the `cudaq-opt` tool. This tool takes
as input a Quake file, an apply MLIR passes specified by the user as another
command line option (the `--pass-pipeline` flag).

### `tools/quake-translate`

This folder contains the implementation of the `cudaq-translate` tool. This tool
takes as input a Quake file and lowers that representation to QIR or Base
Profile QIR.

### `tools/nvq++`

This folder contains the `nvq++` compiler tool. This tool is a bash script that
orchestrates the workflow necessary to map CUDA-Q C++ to MLIR and ultimately
down to executable code.

The script does the following:

1. Map CUDA-Q C++ kernels to Quake MLIR code via a Clang `ASTConsumer`
2. Register all Quake kernel code with the runtime for quantum IR introspection
3. Rewrite the original CUDA-Q C++ kernel entry-point function to invoke an
   internal runtime kernel launch function which targets the specified
   `quantum_platform`
4. Lower to QIR and link, producing an executable or object code
