{ "cells": [ { "cell_type": "markdown", "id": "2c60202a", "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": "730e7731", "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 Schedule\n", "from quantify_scheduler.operations.pulse_library import SquarePulse\n", "from quantify_scheduler.resources import ClockResource\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": "fe0e483e", "metadata": {}, "source": [ "## Hardware 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 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 configuration dictionary\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 backend that we want to use (the Qblox backend, in this case).\n", "- A Cluster containing a QCM-RF module (in the 2nd slot).\n", "- A Local Oscillator.\n", "\n", "In the QCM-RF output's settings, {code}`interm_freq` (which stands for Intermediate Frequency or IF) is the frequency with which the device modulates the pulses.\n", "In this case, the internal LO frequency is not specified but is automatically calculated by the backend, such that the relation {math}`\\text{clock} = \\text{LO} + \\text{IF}` is respected.\n", "\n", "```{code-block} python\n", "\n", "hardware_cfg = {\n", " \"backend\": \"quantify_scheduler.backends.qblox_backend.hardware_compile\",\n", " \"cluster0\": {\n", " \"ref\": \"internal\",\n", " \"instrument_type\": \"Cluster\",\n", " \"cluster0_module2\": {\n", " \"instrument_type\": \"QCM_RF\",\n", " \"complex_output_0\": {\n", " \"lo_freq\": None,\n", " \"dc_mixer_offset_I\": -0.00552,\n", " \"dc_mixer_offset_Q\": -0.00556,\n", " \"portclock_configs\": [\n", " {\n", " \"mixer_amp_ratio\": 0.9998,\n", " \"mixer_phase_error_deg\": -4.1,\n", " \"port\": \"q0:res\",\n", " \"clock\": \"q0.ro\",\n", " \"interm_freq\": 50e6,\n", " }\n", " ],\n", " },\n", " },\n", " },\n", "}\n", "```\n", "\n", "Note that, for any experiment, all the required instruments need to be present in the hardware configuration.\n", "``````\n", "\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-quantify-core.readthedocs-hosted.com/en/latest/usage.html#data-directory)." ] }, { "cell_type": "code", "execution_count": 2, "id": "a8d486ba", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Data will be saved in:\n", "/home/rsoko/quantify-data\n" ] } ], "source": [ "from quantify_core.data import handling as dh\n", "\n", "dh.set_datadir(dh.default_datadir()) \n", "\n" ] }, { "cell_type": "code", "execution_count": 3, "id": "8361f63e", "metadata": { "mystnb": { "remove_code_outputs": true, "remove_code_source": true } }, "outputs": [], "source": [ "hardware_cfg = {\n", " \"backend\": \"quantify_scheduler.backends.qblox_backend.hardware_compile\",\n", " \"cluster0\": {\n", " \"ref\": \"internal\",\n", " \"instrument_type\": \"Cluster\",\n", " \"cluster0_module2\": {\n", " \"instrument_type\": \"QCM_RF\",\n", " \"complex_output_0\": {\n", " \"lo_freq\": None,\n", " \"dc_mixer_offset_I\": -0.00552,\n", " \"dc_mixer_offset_Q\": -0.00556,\n", " \"portclock_configs\": [\n", " {\n", " \"mixer_amp_ratio\": 0.9998,\n", " \"mixer_phase_error_deg\": -4.1,\n", " \"port\": \"q0:res\",\n", " \"clock\": \"q0.ro\",\n", " \"interm_freq\": 50e6,\n", " }\n", " ],\n", " },\n", " },\n", " },\n", "}" ] }, { "cell_type": "markdown", "id": "ad2b8070", "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 configuration must contain the necessary information to execute the schedule. We add the hardware configuration to the `QuantumDevice` object and compile the schedule using this information." ] }, { "cell_type": "code", "execution_count": 4, "id": "dd9f8012", "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "hoverinfo": "x+y+name", "hoverlabel": { "namelength": -1 }, "legendgroup": "0", "line": { "color": "#EF553B" }, "mode": "lines", "name": "ModSquarePulse, clock: q0.ro", "showlegend": true, "type": "scatter", "x": [ 0.0, 1e-09, 2e-09, 3.0000000000000004e-09, 4e-09, 5e-09, 6.000000000000001e-09, 7.000000000000001e-09 ], "xaxis": "x", "y": [ 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ], "yaxis": "y" }, { "hoverinfo": "x+y+name", "hoverlabel": { "namelength": -1 }, "legendgroup": "1", "line": { "color": "#00CC96" }, "mode": "lines", "name": "ModSquarePulse, clock: q0.ro", "showlegend": true, "type": "scatter", "x": [ 8e-09, 9.000000000000001e-09, 1.0000000000000002e-08, 1.1000000000000003e-08, 1.2000000000000003e-08, 1.3000000000000004e-08, 1.4000000000000005e-08, 1.5000000000000005e-08, 1.6000000000000004e-08, 1.7000000000000007e-08, 1.800000000000001e-08, 1.9000000000000008e-08 ], "xaxis": "x", "y": [ 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ], "yaxis": "y" } ], "layout": { "height": 300, "showlegend": false, "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "heatmap" } ], "heatmapgl": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "heatmapgl" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ], "sequentialminus": [ [ 0.0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1.0, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "title": { "text": "Simple schedule" }, "width": 1000, "xaxis": { "anchor": "y", "domain": [ 0.0, 1.0 ], "hoverformat": ".3s", "rangeslider": { "visible": true }, "showgrid": true, "tickformat": ".2s", "tickformatstops": [ { "dtickrange": [ null, 1e-09 ], "value": ".10s" }, { "dtickrange": [ 1e-09, 1e-06 ], "value": ".7s" }, { "dtickrange": [ 1e-06, 0.001 ], "value": ".4s" } ], "ticksuffix": "s", "title": { "text": "Time" } }, "yaxis": { "anchor": "x", "domain": [ 0.0, 1.0 ], "hoverformat": ".3s", "range": [ -1.1, 1.1 ], "tickformat": ".2s", "ticksuffix": "V", "title": { "text": "q0:res" } } } }, "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from quantify_scheduler.backends.graph_compilation import SerialCompiler\n", "from quantify_scheduler.device_under_test.quantum_device import QuantumDevice\n", "\n", "quantum_device = QuantumDevice(\"DUT\")\n", "\n", "quantum_device.hardware_config(hardware_cfg)\n", "compiler = SerialCompiler(name=\"compiler\")\n", "compiled_sched = compiler.compile(\n", " schedule=sched, config=quantum_device.generate_compilation_config()\n", ")\n", "\n", "compiled_sched.plot_pulse_diagram(plot_backend='plotly')\n", "\n" ] }, { "cell_type": "markdown", "id": "b0626a3a", "metadata": {}, "source": [ "The cell above compiles the schedule, returning a {class}`~quantify_scheduler.schedules.schedule.CompiledSchedule` object. This class differs from {class}`~quantify_scheduler.schedules.schedule.Schedule` in that it is immutable and contains the {attr}`~quantify_scheduler.schedules.schedule.CompiledSchedule.compiled_instructions` attribute. We inspect these instructions below." ] }, { "cell_type": "code", "execution_count": 5, "id": "b7176586", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'cluster0': {'settings': {'reference_source': 'internal'},\n", " 'cluster0_module2': {'sequencers': {'seq0': {'nco_en': True,\n", " 'sync_en': True,\n", " 'connected_outputs': [0, 1],\n", " 'connected_inputs': None,\n", " 'init_offset_awg_path_0': 0.0,\n", " 'init_offset_awg_path_1': 0.0,\n", " 'init_gain_awg_path_0': 1.0,\n", " 'init_gain_awg_path_1': 1.0,\n", " 'modulation_freq': 50000000.0,\n", " 'mixer_corr_phase_offset_degree': -4.1,\n", " 'mixer_corr_gain_ratio': 0.9998,\n", " 'integration_length_acq': None,\n", " 'sequence': {'program': ' \\n set_mrk 1 # set markers to 1 \\n wait_sync 4 \\n upd_param 4 \\n wait 4 # latency correction of 4 + 0 ns \\n move 1,R0 # iterator for loop with label start \\n start: \\n reset_ph \\n upd_param 4 \\n set_awg_gain 6553,0 # setting gain for ModSquarePulse \\n play 0,1,4 # play ModSquarePulse (8 ns) \\n wait 4 # auto generated wait (4 ns) \\n set_awg_gain 3276,0 # setting gain for ModSquarePulse \\n play 2,3,4 # play ModSquarePulse (12 ns) \\n wait 8 # auto generated wait (8 ns) \\n loop R0,@start \\n stop \\n',\n", " 'waveforms': {'8471807001840742666': {'data': [1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0],\n", " 'index': 0},\n", " '-7548636948366144465': {'data': [0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0],\n", " 'index': 1},\n", " '6506832761720335688': {'data': [1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0,\n", " 1.0],\n", " 'index': 2},\n", " '-4179281123533662613': {'data': [0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0,\n", " 0.0],\n", " 'index': 3}}},\n", " 'seq_fn': '/home/rsoko/quantify-data/schedules/20230926-173147-165-0427e9_q0res_q0.ro.json',\n", " 'ttl_acq_input_select': None,\n", " 'ttl_acq_threshold': None,\n", " 'ttl_acq_auto_bin_incr_en': None}},\n", " 'settings': {'offset_ch0_path0': -5.52,\n", " 'offset_ch0_path1': -5.56,\n", " 'offset_ch1_path0': None,\n", " 'offset_ch1_path1': None,\n", " 'in0_gain': None,\n", " 'in1_gain': None,\n", " 'lo0_freq': 6950000000.0,\n", " 'lo1_freq': None,\n", " 'out0_att': None,\n", " 'out1_att': None,\n", " 'in0_att': None},\n", " 'repetitions': 1}}}" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "compiled_sched.compiled_instructions\n", "\n" ] }, { "cell_type": "markdown", "id": "9d791dbf", "metadata": {}, "source": [ "## Execution on the hardware\n", "\n", "In the compiled schedule, we have all the information necessary to execute the schedule.\n", "In this specific case, only sequencer {code}`seq0` of the RF control module (QCM-RF) is needed. The compiled schedule contains the file path where the sequencer's program is stored, as well as the QCoDeS parameters that need to be set in the device.\n", "\n", "Now that we have compiled the schedule, we are almost ready to execute it with our control setup.\n", "\n", "We start by connecting to a dummy cluster device by passing a `dummy_cfg` argument when initializing a `Cluster`:" ] }, { "cell_type": "code", "execution_count": 6, "id": "88c6c541", "metadata": {}, "outputs": [], "source": [ "from qblox_instruments import Cluster, ClusterType\n", "\n", "Cluster.close_all() # Closes all registered instruments (not just Clusters)\n", "\n", "cluster0 = Cluster(\"cluster0\", dummy_cfg={\"2\": ClusterType.CLUSTER_QCM_RF})\n" ] }, { "cell_type": "markdown", "id": "c54b3b88", "metadata": {}, "source": [ "Here, {code}`dummy_cfg={\"2\": ClusterType.CLUSTER_QCM_RF}` initializes a dummy cluster instrument that contains an RF control module in slot 2, as specified by the example hardware config.\n", "\n", "We attach these instruments to the {class}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator` via the appropriate {class}`~quantify_scheduler.instrument_coordinator.components.base.InstrumentCoordinatorComponentBase` component wrapper class. More information on the scheduler execution can be found in the [User Guide](https://quantify-quantify-scheduler.readthedocs-hosted.com/en/0.10.1/user_guide.html#execution)." ] }, { "cell_type": "code", "execution_count": 7, "id": "436551e7", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler.instrument_coordinator import InstrumentCoordinator\n", "from quantify_scheduler.instrument_coordinator.components.qblox import ClusterComponent\n", "\n", "ic = InstrumentCoordinator(\"ic\")\n", "ic.add_component(ClusterComponent(cluster0))\n", "\n" ] }, { "cell_type": "markdown", "id": "3ee8b059", "metadata": {}, "source": [ "The {class}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator` object is responsible for the smooth and in-concert operation of the different instruments, so that the provided schedule is correctly executed.\n", "Essentially, it \"coordinates\" the control stack instruments, giving the relevant commands to the different instruments of the control stack at each point in time.\n", "\n", "The experiment can now be conducted using the methods of {class}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator`:\n", "\n", "1. We prepare the instruments with the appropriate settings and upload the schedule program by calling the {meth}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator.prepare` method and passing the compiled schedule as an argument.\n", "2. We start the hardware execution by calling the {meth}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator.start` method.\n", "\n", "Additionally, the {meth}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator.wait_done` method is useful to wait for the experiment to finish and assure the synchronicity of the python script." ] }, { "cell_type": "code", "execution_count": 8, "id": "1ffd2f90", "metadata": {}, "outputs": [], "source": [ "# Set the qcodes parameters and upload the schedule program\n", "ic.prepare(compiled_sched)\n", "\n", "# Start the hardware execution\n", "ic.start()\n", "\n", "# Wait for the experiment to finish or for a timeout\n", "ic.wait_done(timeout_sec=10)\n", "\n" ] }, { "cell_type": "markdown", "id": "e6e77e1c", "metadata": {}, "source": [ "The {class}`~~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator` has two more methods that were not covered in this experiment:\n", "\n", "- {meth}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator.retrieve_acquisition`\n", " \\- In case the schedule contained acquisitions, this method retrieves the acquired data.\n", "- {meth}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator.stop`\n", " \\- Stops all running instruments.\n", "\n", "Note that the schedule used in this tutorial was defined purely in terms of pulses.\n", "However, `quantify-scheduler` also supports the usage of quantum gates in schedules. Given that gates may require different pulses depending on the type of quantum system, an extra step of defining the quantum device configuration, i.e. the qubits, is necessary. This use case is covered in the {ref}`sec-tutorial-ops-qubits` tutorial." ] } ], "metadata": { "file_format": "mystnb", "kernelspec": { "display_name": "python3", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.18" }, "source_map": [ 6, 25, 41, 108, 117, 148, 154, 170, 174, 179, 190, 198, 203, 212, 224, 236 ] }, "nbformat": 4, "nbformat_minor": 5 }