Skip to content

Commit

Permalink
Fix conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
stavros11 committed Jan 23, 2024
2 parents 1889424 + 510e3ca commit 6f85966
Show file tree
Hide file tree
Showing 73 changed files with 945 additions and 1,403 deletions.
45 changes: 45 additions & 0 deletions .github/workflows/capi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Test Qibolab C API
name: C API

on:
push:
workflow_dispatch:

jobs:
tests:
strategy:
matrix:
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Prepare virtual environment
run: |
python -m venv env
- name: Install dependencies
run: |
# build dependencies
pip install cffi
# runtime dependencies
. env/bin/activate
pip install cffi # also a runtime dep
pip install .
- name: Build & install library
working-directory: capi
run: |
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=$(realpath ../env)
cmake --build build
cmake --install build
- name: Build & run example
working-directory: capi/examples
run: |
. ../../env/bin/activate
export PKG_CONFIG_PATH=${VIRTUAL_ENV}/lib/pkgconfig/:${PKG_CONFIG_PATH}:
export LD_LIBRARY_PATH=${VIRTUAL_ENV}/lib/:${LD_LIBRARY_PATH}:
make
./example
6 changes: 0 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,6 @@ platform = create_platform("my_platform")

# Connects to lab instruments using the details specified in the calibration settings.
platform.connect()
# Configures instruments using the loaded calibration settings.
platform.setup()
# Turns on the local oscillators
platform.start()

# Execute a pulse sequence
options = ExecutionParameters(nshots=1000)
Expand All @@ -70,8 +66,6 @@ results = platform.execute_pulse_sequence(sequence, options)
# Print the acquired shots
print(results.samples)

# Turn off lab instruments
platform.stop()
# Disconnect from the instruments
platform.disconnect()
```
Expand Down
16 changes: 16 additions & 0 deletions capi/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# compiled
*.dylib
*.so
*.dll

CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
38 changes: 38 additions & 0 deletions capi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
cmake_minimum_required (VERSION 3.0.2...3.28.1)

SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")

project(libqibolab)

set(VERSION "\"0.0.1\"")

find_package(Python3 COMPONENTS Interpreter Development)

# running the cffi builder
if (NOT EXISTS ${PROJECT_SOURCE_DIR/src/cqibolab.cc})
execute_process(COMMAND ${Python3_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/build.py WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src)
endif()

include_directories(${Python3_INCLUDE_DIRS})
include_directories(src)
add_library(qibolab SHARED ${PROJECT_SOURCE_DIR}/src/cqibolab.c)
target_link_libraries(qibolab ${Python3_LIBRARIES})

# pkg-config
set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix "${prefix}")
set(includedir "${prefix}/include")
set(extraincludirs "-I${Python3_INCLUDE_DIRS}")
set(libdir "${prefix}/lib")
set(pythonlibs "${Python3_LIBRARIES}")

configure_file(
"${PROJECT_SOURCE_DIR}/src/qibolab.pc.in"
"${PROJECT_SOURCE_DIR}/src/qibolab.pc"
)

install(FILES ${PROJECT_SOURCE_DIR}/src/qibolab.pc DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/src/qibolab DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
install(TARGETS qibolab LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
30 changes: 30 additions & 0 deletions capi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Qibolab C-API
=============

This repository contains a C library to access Qibolab from programming languages different from Python.

## Installation

Make sure you have installed the `qibolab` module in Python, then in order to install proceed with the usual cmake steps:
```bash
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=<your install prefix>
cmake --build build
cmake --install build
```

## Usage

The compiler flags to include this library in your package can be
retrieved with:
```bash
pkg-config qibolab --cflags
pkg-config qibolab --libs
```

If you installed to a non-standard location, you need to set up the `PKG_CONFIG_PATH` and `LD_LIBRARY_PATH`, e.g.:
```bash
export PKG_CONFIG_PATH=${VIRTUAL_ENV}/lib/pkgconfig/:${PKG_CONFIG_PATH}:
export LD_LIBRARY_PATH=${VIRTUAL_ENV}/lib/:${LD_LIBRARY_PATH}:
```

Sample programs using this library are provided in the `capi/examples/` directory.
16 changes: 16 additions & 0 deletions capi/build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Further compilation instructions

## Shared libraries on MacOS

On MacOS the environment variable `LD_LIBRARY_PATH` is replaced by `DYLD_LIBRARY_PATH`.

## Nix vs Clang

Same of what is specified in the [README](./README.md), but to use the GCC compiler,
which is not necessarily the default (e.g. on MacOS), add a suitable CMake flag

```bash
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=<your install prefix> -D CMAKE_CXX_COMPILER=g++
cmake --build build
cmake --install build
```
2 changes: 2 additions & 0 deletions capi/examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# executable
example
12 changes: 12 additions & 0 deletions capi/examples/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Makefile example

CFLAGS=`pkg-config qibolab --cflags`
LIBS=`pkg-config qibolab --libs`

all: example

%: %.c
$(CC) $(CFLAGS) -o $@ $< $(LIBS)

clean:
rm -rf example
25 changes: 25 additions & 0 deletions capi/examples/example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// This file is part of Qibolab
#include <stdio.h>
#include "qibolab/qibolab.h"

int main() {

int* qasm_res = execute_qasm(
"OPENQASM 2.0;" \
"include \"qelib1.inc\";" \
"qreg q[3];" \
"creg a[2];" \
"cx q[0],q[2];" \
"x q[1];" \
"swap q[0],q[1];" \
"cx q[1],q[0];" \
"measure q[0] -> a[0];" \
"measure q[2] -> a[1];",
"dummy", 10);

printf("Samples:\n");
for (int i = 0; i < 2*10; i++)
printf("%d\n", qasm_res[i]);

return 0;
}
3 changes: 3 additions & 0 deletions capi/src/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# generated
cqibolab.c
qibolab.pc
20 changes: 20 additions & 0 deletions capi/src/build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# This file is part of Qibolab
import cffi

ffibuilder = cffi.FFI()

with open("qibolab/qibolab.h") as f:
ffibuilder.embedding_api(f.read())

ffibuilder.set_source(
"cqibolab",
r"""
#include "qibolab/qibolab.h"
""",
source_extension=".c",
)

with open("wrapper.py") as f:
ffibuilder.embedding_init_code(f.read())

ffibuilder.emit_c_code("cqibolab.c")
12 changes: 12 additions & 0 deletions capi/src/qibolab.pc.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
includedir=@includedir@
extraincludirs=@extraincludirs@
libdir=@libdir@
pythonlibs=@pythonlibs@

Name: qibolab
Description: The Qibolab C-API library
Version: @VERSION@
Cflags: -I@includedir@ @extraincludirs@
Libs: -L@libdir@ -lqibolab @pythonlibs@
5 changes: 5 additions & 0 deletions capi/src/qibolab/qibolab.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* Qibolab C API
*/

extern int *execute_qasm(const char *circuit, const char *platform, int nshots);
14 changes: 14 additions & 0 deletions capi/src/wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# This file is part of
from cqibolab import ffi

from qibolab import execute_qasm as py_execute_qasm


@ffi.def_extern()
def execute_qasm(circuit, platform, nshots):
"""Generate samples for a given circuit qasm, platform and number of
shots."""
py_circuit = ffi.string(circuit).decode("utf-8")
py_platform = ffi.string(platform).decode("utf-8")
qasm_res = py_execute_qasm(circuit=py_circuit, platform=py_platform, nshots=nshots)
return ffi.cast("int*", ffi.from_buffer(qasm_res.samples().ravel()))
5 changes: 2 additions & 3 deletions doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ circuits on quantum hardware. Qibolab includes:
1. :ref:`Platform API <main_doc_platform>`: support custom allocation of quantum hardware platforms / lab setup.
2. :ref:`Drivers <main_doc_instruments>`: supports commercial and open-source firmware for hardware control.
3. :ref:`Arbitrary pulse API <main_doc_pulses>`: provide a library of custom pulses for execution through instruments.
4. :ref:`Transpiler <main_doc_transpiler>`: compiles quantum circuits into pulse sequences matching chip topology.
5. :ref:`Quantum Circuit Deployment <tutorials_circuits>`: seamlessly deploys quantum circuit models on
quantum hardware.
4. :ref:`Compiler <main_doc_compiler>`: compiles quantum circuits into pulse sequences.
5. :ref:`Quantum Circuit Deployment <tutorials_circuits>`: seamlessly deploys quantum circuit models on quantum hardware.

Components
----------
Expand Down
20 changes: 7 additions & 13 deletions doc/source/main-documentation/qibolab.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The API reference section provides a description of all the attributes and metho
In the platform, the main methods can be divided in different sections:

- functions save and change qubit parameters (``dump``, ``update``)
- functions to coordinate the instruments (``connect``, ``setup``, ``start``, ``stop``, ``disconnect``)
- functions to coordinate the instruments (``connect``, ``setup``, ``disconnect``)
- functions to execute experiments (``execute_pulse_sequence``, ``execute_pulse_sequences``, ``sweep``)
- functions to initialize gates (``create_RX90_pulse``, ``create_RX_pulse``, ``create_CZ_pulse``, ``create_MZ_pulse``, ``create_qubit_drive_pulse``, ``create_qubit_readout_pulse``, ``create_RX90_drag_pulse``, ``create_RX_drag_pulse``)
- setters and getters of channel/qubit parameters (local oscillator parameters, attenuations, gain and biases)
Expand All @@ -29,13 +29,11 @@ For example, let's first define a platform (that we consider to be a single qubi

platform = create_platform("dummy")

Now we connect and start the instruments (note that we, the user, do not need to know which instruments are connected).
Now we connect to the instruments (note that we, the user, do not need to know which instruments are connected).

.. testcode:: python

platform.connect()
platform.setup()
platform.start()

We can easily print some of the parameters of the channels (similarly we can set those, if needed):

Expand Down Expand Up @@ -93,7 +91,6 @@ Finally, we can stop instruments and close connections.

.. testcode:: python

platform.stop()
platform.disconnect()


Expand Down Expand Up @@ -204,9 +201,9 @@ Note that while channels are defined in a device-independent manner, the port pa
from qibolab.instruments.rfsoc import RFSoC

controller = RFSoC(name="dummy", address="192.168.0.10", port="6000")
channel1 = Channel("my_channel_name_1", port=controller[1])
channel2 = Channel("my_channel_name_2", port=controller[2])
channel3 = Channel("my_channel_name_3", port=controller[3])
channel1 = Channel("my_channel_name_1", port=controller.ports(1))
channel2 = Channel("my_channel_name_2", port=controller.ports(2))
channel3 = Channel("my_channel_name_3", port=controller.ports(3))

Channels are then organized in :class:`qibolab.channels.ChannelMap` to be passed as a single argument to the platform.
Following the tutorial in :doc:`/tutorials/lab`, we can continue the initialization:
Expand Down Expand Up @@ -650,7 +647,7 @@ The shape of the values of an integreted acquisition with 2 sweepers will be:
)
shape = (options.nshots, len(sweeper1.values), len(sweeper2.values))

.. _main_doc_transpiler:
.. _main_doc_compiler:

Transpiler and Compiler
-----------------------
Expand Down Expand Up @@ -707,20 +704,17 @@ Controllers (subclasses of :class:`qibolab.instruments.abstract.Controller`):
- Dummy Instrument: :class:`qibolab.instruments.dummy.DummyInstrument`
- Zurich Instruments: :class:`qibolab.instruments.zhinst.Zurich`
- Quantum Machines: :class:`qibolab.instruments.qm.controller.QMController`
- Qblox: :class:`qibolab.instruments.qblox.cluster.Cluster`
- Qblox: :class:`qibolab.instruments.qblox.controller.QbloxCluster`
- Xilinx RFSoCs: :class:`qibolab.instruments.rfsoc.driver.RFSoC`

Other Instruments (subclasses of :class:`qibolab.instruments.abstract.Instrument`):
- Erasynth++: :class:`qibolab.instruments.erasynth.ERA`
- RohseSchwarz SGS100A: :class:`qibolab.instruments.rohde_schwarz.SGS100A`
- Qutech SPI rack: :class:`qibolab.instruments.qutech.SPI`

Instruments all implement a set of methods:

- connect
- setup
- start
- stop
- disconnect

While the controllers, the main instruments in a typical setup, add other two methods:
Expand Down
Loading

0 comments on commit 6f85966

Please sign in to comment.