{ "cells": [ { "cell_type": "markdown", "id": "37c36b65", "metadata": {}, "source": [ "(sec-tutorial-compiling)=\n", "\n", "# Tutorial: Compiling to Hardware\n", "\n", "```{seealso}\n", "The complete source code of this tutorial can be found in\n", "\n", "{nb-download}`Compiling to Hardware.ipynb`\n", "```\n", "\n", "Compilation allows converting the schedules introduced in {ref}`sec-tutorial-sched-pulse` into a set of instructions that can be executed on the control hardware.\n", "\n", "In this notebook, we will define an example schedule, demonstrate how to compile it, and run it on a virtual hardware setup.\n", "\n", "## Schedule definition\n", "\n", "We start by defining an example schedule." ] }, { "cell_type": "code", "execution_count": 1, "id": "904c6108", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Schedule \"Simple schedule\" containing (2) 2 (unique) operations." ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from quantify_scheduler import ClockResource, Schedule\n", "from quantify_scheduler.operations import SquarePulse\n", "\n", "sched = Schedule(\"Simple schedule\")\n", "sched.add(SquarePulse(amp=0.2, duration=8e-9, port=\"q0:res\", clock=\"q0.ro\"))\n", "sched.add(SquarePulse(amp=0.1, duration=12e-9, port=\"q0:res\", clock=\"q0.ro\"))\n", "\n", "readout_clock = ClockResource(name=\"q0.ro\", freq=7e9)\n", "sched.add_resource(readout_clock)\n", "\n", "sched\n", "\n" ] }, { "cell_type": "markdown", "id": "e9665167", "metadata": {}, "source": [ "## Hardware compilation configuration\n", "\n", "In our example setup, we will use a Qblox Cluster containing an RF control module (QCM-RF). To compile the schedule, we will need to provide the compiler with a dictionary detailing the hardware compilation configuration.\n", "\n", "Please check the documentation on how to properly create such a configuration for the supported backends:\n", "\n", "- {ref}`sec-backend-qblox`\n", "- {ref}`sec-backend-zhinst`\n", "\n", "```{admonition} Creating an example Qblox hardware compilation configuration\n", ":class: dropdown\n", "\n", "Below we create an example hardware configuration dictionary, for the Qblox backend.\n", "In this configuration, we include:\n", "\n", "- The `\"config_type\"`, which points to the specific {class}`~quantify_scheduler.backends.types.common.HardwareCompilationConfig` datastructure for the backend we want to use (the Qblox backend, in this case).\n", "- The description of the setup, including:\n", " - A Cluster containing a QCM-RF module (in the 2nd slot).\n", "- The hardware options we want to use in the compilation.\n", "- The connectivity between the control hardware and the quantum device.\n", "```" ] }, { "cell_type": "code", "execution_count": 2, "id": "becc5810", "metadata": { "mystnb": { "code_prompt_show": "Example hardware configuration" }, "tags": [ "hide-cell" ] }, "outputs": [], "source": [ "hardware_comp_cfg = {\n", " \"config_type\": \"quantify_scheduler.backends.qblox_backend.QbloxHardwareCompilationConfig\",\n", " \"hardware_description\": {\n", " \"cluster0\": {\n", " \"instrument_type\": \"Cluster\",\n", " \"ref\": \"internal\",\n", " \"modules\": {\n", " \"2\": {\n", " \"instrument_type\": \"QCM_RF\"\n", " },\n", " },\n", " },\n", " },\n", " \"hardware_options\": {\n", " \"modulation_frequencies\": {\n", " \"q0:res-q0.ro\": {\"interm_freq\": 50e6},\n", " },\n", " \"mixer_corrections\": {\n", " \"q0:res-q0.ro\": {\n", " \"dc_offset_i\": -0.00552,\n", " \"dc_offset_q\": -0.00556,\n", " \"amp_ratio\": 0.9998,\n", " \"phase_error\": -4.1\n", " }\n", " }\n", " },\n", " \"connectivity\": {\n", " \"graph\": [\n", " (\"cluster0.module2.complex_output_0\", \"q0:res\"),\n", " ]\n", " },\n", "}" ] }, { "cell_type": "markdown", "id": "e3d1c79c", "metadata": {}, "source": [ "(sec-tutorial-compiling-to-hardware-compilation)=\n", "## Compilation\n", "\n", "Now we are ready to proceed to the compilation stage. For each of the control stack's instruments, the compilation generates:\n", "\n", "- The schedule's absolute timing. During the schedule's definition, we didn't assign absolute times to the operations. Instead, only the duration was defined. For the instruments to know how to execute the schedule, the absolute timing of the operations is calculated.\n", "- A set of parameters that are used to properly configure each instrument for the execution of the schedule. These parameters typically don't change during the execution of the schedule.\n", "- A compiled program that contains instructions on what the instrument must do in order for the schedule to be executed.\n", "\n", "We perform the compilation via {func}`~quantify_scheduler.backends.graph_compilation.QuantifyCompiler.compile`.\n", "\n", "We start by setting the directory where the compiled schedule files will be stored, via [set_datadir](https://quantify-os.org/docs/quantify-core/dev/user/concepts.html#data-directory)." ] }, { "cell_type": "code", "execution_count": 3, "id": "548d6c7b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Data will be saved in:\n", "/root/quantify-data\n" ] } ], "source": [ "from quantify_core.data import handling as dh\n", "\n", "dh.set_datadir(dh.default_datadir())\n", "\n" ] }, { "cell_type": "markdown", "id": "ba1158ad", "metadata": {}, "source": [ "Next, we create a device configuration that contains all knowledge of the physical device under test (DUT). To generate it we use the {class}`~quantify_scheduler.device_under_test.quantum_device.QuantumDevice` class.\n", "\n", "The schedule defined at the beginning of this tutorial consists of 2 pulse operations. As such, the hardware compilation configuration must contain the necessary information to execute the schedule. We add the hardware compilation configuration to the `QuantumDevice` object and compile the schedule using this information. We visualize the compiled schedule in a {meth}`pulse diagram <.plot_pulse_diagram>`." ] }, { "cell_type": "code", "execution_count": 4, "id": "ab14e99a", "metadata": {}, "outputs": [ { "data": { "text/html": [ "