Repository: QuTech-Delft/OpenQL (language: python)

Issue:
Diamond microcode translator
Initial pull of the diamond microcode translator


Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index 5c975b1bc..11756b408 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,6 +28,9 @@ test_output*
 .ipynb_checkpoints
 tests/visualizer/visualizer_example_output/
 
+# Diamond Example Files
+examples/diamond/test_output
+
 docs/_build
 docs/_static
 docs/_templates
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f617d352b..603f870ec 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -292,6 +292,9 @@ add_library(ql
     "${CMAKE_CURRENT_SOURCE_DIR}/src/ql/arch/cc/pass/gen/vq1asm/vq1asm.cc"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/ql/arch/cc_light/info.cc"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/ql/arch/none/info.cc"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/ql/arch/diamond/info.cc"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/ql/arch/diamond/pass/gen/microcode/microcode.cc"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/ql/arch/diamond/pass/gen/microcode/detail/functions.cc"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/ql/api/misc.cc"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/ql/api/pass.cc"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/ql/api/compiler.cc"
@@ -302,7 +305,7 @@ add_library(ql
     "${CMAKE_CURRENT_SOURCE_DIR}/src/ql/api/kernel.cc"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/ql/api/program.cc"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/ql/api/cqasm_reader.cc"
-)
+    )
 
 # Specify resources.
 create_resource("src/ql/arch/cc/resources/hwconf_default.json")
@@ -311,6 +314,8 @@ create_resource("src/ql/arch/cc_light/resources/hwconf_s5.json")
 create_resource("src/ql/arch/cc_light/resources/hwconf_s7.json")
 create_resource("src/ql/arch/cc_light/resources/hwconf_s17.json")
 create_resource("src/ql/arch/none/resources/hwconf_default.json")
+create_resource("src/ql/arch/diamond/resources/hwconf_default.json")
+
 
 # Generate a header file with configuration options that cannot be compiled
 # (entirely) into the shared/static library due to use of templates.
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 301edf617..c71c23c73 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -90,3 +90,6 @@ Note: please fill your contributions in this file
     -   doxygen documentation
     -   improved pass management
     -   extensive cleanup; basically a rewrite of everything at this point
+  
+- [Quinten van Wingerden](https://github.com/qvanwingerden)
+    -   added support for diamond architecture
diff --git a/examples/diamond/gateset.json b/examples/diamond/gateset.json
new file mode 100644
index 000000000..632b435c5
--- /dev/null
+++ b/examples/diamond/gateset.json
@@ -0,0 +1,41 @@
+[
+    {"name": "measure",     "params": "Q",      "ql_name": "measure"},
+    {"name": "measure",     "params": "QB",     "ql_name": "measure"},
+    {"name": "measure_x",   "params": "Q",      "ql_name": "measure_x"},
+    {"name": "measure_x",   "params": "QB",     "ql_name": "measure_X"},
+    {"name": "measure_y",   "params": "Q",      "ql_name": "measure_y"},
+    {"name": "measure_y",   "params": "QB",     "ql_name": "measure_y"},
+    {"name": "measure_z",   "params": "Q",      "ql_name": "measure"},
+    {"name": "measure_z",   "params": "QB",     "ql_name": "measure"},
+    {"name": "prep",        "params": "Q",      "ql_name": "prep_z"},
+    {"name": "prep_x",      "params": "Q",      "ql_name": "prep_x"},
+    {"name": "prep_y",      "params": "Q",      "ql_name": "prep_y"},
+    {"name": "prep_z",      "params": "Q",      "ql_name": "prep_z"},
+    {"name": "i",           "params": "Q"},
+    {"name": "h",           "params": "Q"},
+    {"name": "x",           "params": "Q"},
+    {"name": "y",           "params": "Q"},
+    {"name": "z",           "params": "Q"},
+    {"name": "s",           "params": "Q"},
+    {"name": "sdag",        "params": "Q"},
+    {"name": "t",           "params": "Q"},
+    {"name": "tdag",        "params": "Q"},
+    {"name": "x90",         "params": "Q",      "ql_name": "x90"},
+    {"name": "mx90",        "params": "Q",      "ql_name": "mx90"},
+    {"name": "y90",         "params": "Q",      "ql_name": "y90"},
+    {"name": "my90",        "params": "Q",      "ql_name": "my90"},
+    {"name": "rx",          "params": "Qr"},
+    {"name": "ry",          "params": "Qr"},
+    {"name": "rz",          "params": "Qr"},
+    {"name": "cnot",        "params": "QQ"},
+    {"name": "cz",          "params": "QQ"},
+    {"name": "swap",        "params": "QQ"},
+    {"name": "cr",          "params": "QQr"},
+    {"name": "crk",         "params": "QQi",    "ql_angle": "%2", "ql_angle_type": "pow2"},
+    {"name": "toffoli",     "params": "QQQ"},
+    {"name": "measure_all", "params": "",       "ql_name": "measure", "ql_qubits": "all", "implicit_sgmq": true},
+    {"name": "display",     "params": ""},
+    {"name": "wait",        "params": ""},
+    {"name": "wait",        "params": "i"},
+    {"name": "decouple",    "params": "Q",	"ql_name": "decouple"}
+]
diff --git a/include/ql/api/kernel.h b/include/ql/api/kernel.h
index 2f3dcf643..f3da87008 100644
--- a/include/ql/api/kernel.h
+++ b/include/ql/api/kernel.h
@@ -402,6 +402,42 @@ class Kernel {
      */
     void display();
 
+    /**
+     * Appends the diamond excite_MW instruction.
+     */
+    void diamond_excite_mw(size_t envelope, size_t duration, size_t frequency, size_t phase, size_t amplitude, size_t qubit);
+
+    /**
+     * Appends the diamond memswap instruction, that swaps the state from a qubit
+     * to a nuclear spin qubit within the color center.
+     */
+    void diamond_memswap(size_t qubit, size_t nuclear_qubit);
+
+    /**
+     * Appends the diamond qentangle instruction, that entangles a qubit with a
+     * nuclear spin qubit within the color center.
+     */
+    void diamond_qentangle(size_t qubit, size_t nuclear_qubit);
+
+    /**
+     * Appends the diamond sweep_bias instruction, that sweeps the frequency over
+     * a color center to help determine the magnetic biasing.
+     */
+    void diamond_sweep_bias(size_t qubit, size_t value, size_t dacreg, size_t start, size_t step, size_t max, size_t memaddress);
+
+    /**
+     * Appends the diamond crc instruction, that checks whether the color center is
+     * still in the correct charge state.
+     */
+    void diamond_crc(size_t qubit, size_t threshold, size_t value);
+
+    /**
+     * Appends the diamond rabi_check instruction, that measures the result of
+     * an operation on a qubit to determine how long the color centers needs to
+     * be excited for to have it flip.
+     */
+    void diamond_rabi_check(size_t qubit, size_t measurements, size_t duration, size_t t_max);
+
     /**
      * Appends a controlled kernel. The number of control and ancilla qubits
      * must be equal.
diff --git a/include/ql/arch/diamond/annotations.h b/include/ql/arch/diamond/annotations.h
new file mode 100644
index 000000000..a6ed796a8
--- /dev/null
+++ b/include/ql/arch/diamond/annotations.h
@@ -0,0 +1,55 @@
+/** \file
+ * Defines annotations about the diamond architecture.
+ */
+
+#pragma once
+
+#include "ql/utils/num.h"
+
+namespace ql {
+namespace arch {
+namespace diamond {
+namespace annotations {
+
+struct ExciteMicrowaveParameters {
+    utils::UInt envelope;
+    utils::UInt duration;
+    utils::UInt frequency;
+    utils::UInt phase;
+    utils::UInt amplitude;
+};
+
+struct MemSwapParameters {
+    utils::UInt nuclear;
+};
+
+struct QEntangleParameters {
+    utils::UInt nuclear;
+};
+
+struct SweepBiasParameters {
+    utils::UInt value;
+    utils::UInt dacreg;
+    utils::UInt start;
+    utils::UInt step;
+    utils::UInt max;
+    utils::UInt memaddress;
+};
+
+struct CRCParameters {
+    utils::UInt threshold;
+    utils::UInt value;
+};
+
+struct RabiParameters {
+    utils::UInt measurements;
+    utils::UInt duration;
+    utils::UInt t_max;
+};
+
+
+
+} // namespace annotations
+} // namespace diamond
+} // namespace arch
+} // namespace ql
diff --git a/include/ql/arch/diamond/info.h b/include/ql/arch/diamond/info.h
new file mode 100644
index 000000000..ad1256011
--- /dev/null
+++ b/include/ql/arch/diamond/info.h
@@ -0,0 +1,75 @@
+/** \file
+ * Defines information about the no-op architecture.
+ */
+
+#pragma once
+
+#include <iostream>
+#include "ql/utils/num.h"
+#include "ql/utils/str.h"
+#include "ql/utils/set.h"
+#include "ql/utils/ptr.h"
+#include "ql/utils/json.h"
+#include "ql/pmgr/manager.h"
+#include "ql/arch/info_base.h"
+
+namespace ql {
+namespace arch {
+namespace diamond {
+
+/**
+ * No-op architecture-specific information class.
+ */
+class Info : public InfoBase {
+public:
+
+    /**
+     * Writes the documentation for this architecture to the given output
+     * stream.
+     */
+    void dump_docs(std::ostream &os, const utils::Str &line_prefix) const override;
+
+    /**
+     * Returns a user-friendly type name for this architecture. Used for
+     * documentation generation.
+     */
+    utils::Str get_friendly_name() const override;
+
+    /**
+     * Returns the name of the namespace for this architecture.
+     */
+    utils::Str get_namespace_name() const override;
+
+    /**
+     * Returns a list of strings accepted for the "eqasm_compiler" key in the
+     * platform configuration file. This can be more than one, to support both
+     * legacy (inconsistent) names and the new namespace names. The returned
+     * set must include at least the name of the namespace.
+     */
+    utils::List<utils::Str> get_eqasm_compiler_names() const override;
+
+    /**
+     * Should generate a sane default platform JSON file, for when the user
+     * constructs a Platform without JSON data. This is done by specifying an
+     * architecture namespace identifier instead of a JSON filename. Optionally,
+     * the user may specify a variant suffix, separated using a dot, to select
+     * a variation of the architecture; for instance, for CC-light, there might
+     * be variations for surface-5, surface-7, and surface-17. This JSON data
+     * will still be preprocessed by preprocess_platform().
+     */
+    utils::Str get_default_platform(const utils::Str &variant) const override;
+
+    /**
+     * Adds the default "backend passes" for this platform. Called by
+     * pmgr::Manager::from_defaults() when no compiler configuration file is
+     * specified. This typically includes at least the architecture-specific
+     * code generation pass, but anything after prescheduling and optimization
+     * is considered a backend pass.
+     */
+    void populate_backend_passes(pmgr::Manager &manager, const utils::Str &variant) const override;
+
+};
+
+} // namespace diamond
+} // namespace arch
+} // namespace ql
diff --git a/include/ql/arch/diamond/pass/gen/microcode/microcode.h b/include/ql/arch/diamond/pass/gen/microcode/microcode.h
new file mode 100644
index 000000000..79a5c5d6d
--- /dev/null
+++ b/include/ql/arch/diamond/pass/gen/microcode/microcode.h
@@ -0,0 +1,68 @@
+/** \file
+ * Defines the pass for generation the microcode for the Fujitsu project quantum
+ * computer
+ */
+
+#pragma once
+
+#include "ql/com/options.h"
+#include "ql/pmgr/pass_types/specializations.h"
+
+namespace ql {
+namespace arch {
+namespace diamond {
+namespace pass {
+namespace gen {
+namespace microcode {
+
+/**
+ * QuTech Central Controller Q1 processor assembly generator pass.
+ */
+class GenerateMicrocodePass : public pmgr::pass_types::ProgramTransformation {
+protected:
+
+    /**
+     * Dumps docs for the code generator.
+     */
+    void dump_docs(
+        std::ostream &os,
+        const utils::Str &line_prefix
+    ) const override;
+
+public:
+
+    /**
+     * Returns a user-friendly type name for this pass.
+     */
+    utils::Str get_friendly_type() const override;
+
+    /**
+     * Constructs a code generator.
+     */
+    GenerateMicrocodePass(
+        const utils::Ptr<const pmgr::Factory> &pass_factory,
+        const utils::Str &instance_name,
+        const utils::Str &type_name
+    );
+
+    /**
+     * Runs the code generator.
+     */
+    utils::Int run(
+        const ir::ProgramRef &program,
+        const pmgr::pass_types::Context &context
+    ) const override;
+
+};
+
+/**
+ * Shorthand for referring to the pass using namespace notation.
+ */
+using Pass = GenerateMicrocodePass;
+
+} // namespace microcode
+} // namespace gen
+} // namespace pass
+} // namespace cc
+} // namespace arch
+} // namespace ql
diff --git a/src/ql/api/kernel.cc b/src/ql/api/kernel.cc
index 25cdcd06e..eb227440f 100644
--- a/src/ql/api/kernel.cc
+++ b/src/ql/api/kernel.cc
@@ -7,6 +7,7 @@
 #include "ql/api/creg.h"
 #include "ql/api/operation.h"
 #include "ql/api/unitary.h"
+#include "ql/arch/diamond/annotations.h"
 
 //============================================================================//
 //                               W A R N I N G                                //
@@ -434,6 +435,61 @@ void Kernel::display() {
     kernel->display();
 }
 
+/**
+ * Appends the diamond excite_mw instruction.
+ */
+void Kernel::diamond_excite_mw(size_t envelope, size_t duration, size_t frequency, size_t phase, size_t amplitude, size_t qubit) {
+    kernel->gate("excite_mw", qubit);
+    kernel->gates.back()->set_annotation<ql::arch::diamond::annotations::ExciteMicrowaveParameters>({envelope, duration, frequency, phase, amplitude});
+}
+
+/**
+ * Appends the diamond memswap instruction, that swaps the state from a qubit
+ * to a nuclear spin qubit within the color center.
+ */
+void Kernel::diamond_memswap(size_t qubit, size_t nuclear_qubit) {
+    kernel->gate("memswap", qubit);
+    kernel->gates.back()->set_annotation<ql::arch::diamond::annotations::MemSwapParameters>({nuclear_qubit});
+}
+
+/**
+ * Appends the diamond qentangle instruction, that entangles a qubit with a
+ * nuclear spin qubit within the color center.
+ */
+void Kernel::diamond_qentangle(size_t qubit, size_t nuclear_qubit){
+    kernel->gate("qentangle", qubit);
+    kernel->gates.back()->set_annotation<ql::arch::diamond::annotations::QEntangleParameters>({nuclear_qubit});
+}
+
+/**
+ * Appends the diamond sweep_bias instruction, that sweeps the frequency over
+ * a color center to help determine the magnetic biasing.
+ */
+void Kernel::diamond_sweep_bias(size_t qubit, size_t value, size_t dacreg, size_t start, size_t step, size_t max, size_t memaddress)
+{
+    kernel->gate("sweep_bias", qubit);
+    kernel->gates.back()->set_annotation<ql::arch::diamond::annotations::SweepBiasParameters>({value, dacreg, start, step, max, memaddress});
+}
+
+/**
+ * Appends the diamond crc instruction, that checks whether the color center is
+ * still in the correct charge state.
+ */
+void Kernel::diamond_crc(size_t qubit, size_t threshold, size_t value) {
+    kernel->gate("crc", qubit);
+    kernel->gates.back()->set_annotation<ql::arch::diamond::annotations::CRCParameters>({threshold, value});
+}
+
+/**
+ * Appends the diamond rabi_check instruction, that measures the result of
+ * an operation on a qubit to determine how long the color centers needs to
+ * be excited for to have it flip.
+ */
+void Kernel::diamond_rabi_check(size_t qubit, size_t measurements, size_t duration, size_t t_max){
+    kernel->gate("rabi_check", qubit);
+    kernel->gates.back()->set_annotation<ql::arch::diamond::annotations::RabiParameters>({measurements, duration, t_max});
+}
+
 /**
  * Appends a controlled kernel. The number of control and ancilla qubits
  * must be equal.
diff --git a/src/ql/api/kernel.i b/src/ql/api/kernel.i
index 3ccdebcc9..b69662fef 100644
--- a/src/ql/api/kernel.i
+++ b/src/ql/api/kernel.i
@@ -797,6 +797,148 @@ None
 """
 
 
+%feature("docstring") ql::api::Kernel::diamond_excite_mw
+"""
+Appends the diamond \"excite_mw\" instruction.
+
+Parameters
+----------
+envelope : int
+    The envelope of the microwave.
+
+duration : int
+    The duration of the microwave in nanoseconds.
+
+frequency : int
+    The frequency of the microwave in kilohertz.
+
+phase: int
+    The phase of the microwave.
+
+amplitude: int
+    The amplitude of the microwave.
+
+qubit: int
+    The target qubit index.
+
+Returns
+-------
+None
+"""
+
+
+%feature("docstring") ql::api::Kernel::diamond_memswap
+"""
+Appends the diamond \"memswap\" instruction.
+
+Parameters
+----------
+qubit : int
+    The index of the qubit.
+
+nuclear_qubit : int
+    The index of the nuclear spin qubit of the color center.
+
+Returns
+-------
+None
+"""
+
+
+%feature("docstring") ql::api::Kernel::diamond_qentangle
+"""
+Appends the diamond \"qentangle\" instruction.
+
+Parameters
+----------
+qubit : int
+    The index of the qubit.
+
+nuclear_qubit : int
+    The index of the nuclear spin qubit of the color center.
+
+Returns
+-------
+None
+"""
+
+%feature("docstring") ql::api::Kernel::diamond_sweep_bias
+"""
+Appends the diamond \"sweep_bias\" instruction.
+
+Parameters
+----------
+qubit : int
+    The index of the qubit.
+
+value : int
+    The value that has to be send to the dac for biasing.
+
+dacreg: int
+    The index or address of the register of the dac.
+
+start: int
+    The start frequency value of the sweep.
+
+step: int
+    The step frequency value of the sweep.
+
+max: int
+    The maximum frequency value of the sweep.
+
+memaddress: int
+    The memory address to write the results to.
+
+Returns
+-------
+None
+"""
+
+
+%feature("docstring") ql::api::Kernel::diamond_crc
+"""
+Appends the diamond \"crc\" instruction.
+
+Parameters
+----------
+qubit : int
+    The index of the qubit.
+
+treshold : int
+    The threshold value that has to be matched.
+
+value: int
+    The value of the voltage sent to the dac.
+
+Returns
+-------
+None
+"""
+
+%feature("docstring") ql::api::Kernel::diamond_rabi_check
+"""
+Appends the diamond \"rabi_check\" instruction.
+
+Parameters
+----------
+qubit : int
+    The index of the qubit.
+
+measurements : int
+    How manu measurements have to be recorded.
+
+duration: int
+    The starting value of the duration of the microwave.
+
+t_max: int
+    The value of the voltage sent to the dac.
+
+Returns
+-------
+None
+"""
+
+
 %feature("docstring") ql::api::Kernel::controlled
 """
 Appends a controlled kernel. The number of control and ancilla qubits
diff --git a/src/ql/arch/diamond/info.cc b/src/ql/arch/diamond/info.cc
new file mode 100644
index 000000000..d23b787a5
--- /dev/null
+++ b/src/ql/arch/diamond/info.cc
@@ -0,0 +1,78 @@
+/** \file
+ * Defines information about the diamond architecture.
+ */
+
+#include "ql/arch/diamond/info.h"
+
+#include "ql/arch/diamond/resources/hwconf_default.inc"
+
+namespace ql {
+namespace arch {
+namespace diamond {
+
+/**
+ * Writes the documentation for this architecture to the given output
+ * stream.
+ */
+void Info::dump_docs(std::ostream &os, const utils::Str &line_prefix) const {
+    utils::dump_str(os, line_prefix, R"(
+    NOTE THAT THIS SECTION IS INCOMPLETE AND THE DOCUMENTATION IS WRONG, EXCEPT
+    FROM THE FOLLOWING DESCRIPTION:
+
+    This architecture is aimed towards computing with qubits made in color
+    centers in diamond. It is part of the fujitsu project and work is in
+    progress. The backend will, for now as it is in it's early stages, work as a
+    translation tool from a high-level algorithm to our own defined microcode.
+    )");
+}
+
+/**
+ * Returns a user-friendly type name for this architecture. Used for
+ * documentation generation.
+ */
+utils::Str Info::get_friendly_name() const {
+    return "Diamond";
+}
+
+/**
+ * Returns the name of the namespace for this architecture.
+ */
+utils::Str Info::get_namespace_name() const {
+    return "diamond";
+}
+
+/**
+ * Returns a list of strings accepted for the "eqasm_compiler" key in the
+ * platform configuration file. This can be more than one, to support both
+ * legacy (inconsistent) names and the new namespace names. The returned
+ * set must include at least the name of the namespace.
+ */
+utils::List<utils::Str> Info::get_eqasm_compiler_names() const {
+    return {"diamond"};
+}
+
+/**
+ * Should generate a sane default platform JSON file, for when the user
+ * constructs a Platform without JSON data. This is done by specifying an
+ * architecture namespace identifier instead of a JSON filename. Optionally,
+ * the user may specify a variant suffix, separated using a dot, to select
+ * a variation of the architecture; for instance, for CC-light, there might
+ * be variations for surface-5, surface-7, and surface-17. This JSON data
+ * will still be preprocessed by preprocess_platform().
+ */
+utils::Str Info::get_default_platform(const utils::Str &variant) const {
+
+    // NOTE: based on tests/hardware_config_qx.json at the time of writing.
+    return HWCONF_DEFAULT_DATA;
+
+}
+
+void Info::populate_backend_passes(pmgr::Manager &manager, const utils::Str &variant) const {
+
+    // Add the microcode generator pass
+    manager.append_pass("arch.diamond.gen.Microcode", "diamond_codegen");
+}
+
+} // namespace diamond
+} // namespace arch
+} // namespace ql
diff --git a/src/ql/arch/diamond/pass/gen/microcode/detail/functions.cc b/src/ql/arch/diamond/pass/gen/microcode/detail/functions.cc
new file mode 100644
index 000000000..d46ebb055
--- /dev/null
+++ b/src/ql/arch/diamond/pass/gen/microcode/detail/functions.cc
@@ -0,0 +1,144 @@
+#include "ql/utils/str.h"
+#include "ql/utils/filesystem.h"
+#include "ql/plat/platform.h"
+#include "ql/com/options.h"
+#include "functions.h"
+
+
+namespace ql {
+namespace arch {
+namespace diamond {
+namespace pass {
+namespace gen {
+namespace microcode {
+namespace detail {
+
+using namespace utils;
+
+/**
+ * Function for switching on the optical path
+ */
+Str switchOn(UInt arg) {
+    Str body = "switchOn q" + to_string(arg);
+    return body;
+}
+
+/**
+ * Function for switching off the optical path
+ */
+Str switchOff(UInt arg) {
+    Str body = "switchOff q" + to_string(arg);
+    return body;
+}
+
+/**
+ * Function for load immediate (LDi)
+ */
+Str loadimm(Str value, Str reg_name, Str reg_value) {
+    Str body = "LDi " + value + ", " + reg_name + to_string(reg_value);
+    return body;
+}
+
+/**
+ * Function for move (mov)
+ */
+Str mov(Str reg1_name, Str reg1_value, Str reg2_name, Str reg2_value) {
+    Str body = "mov " + reg1_name + reg1_value + ", " + reg2_name + reg2_value;
+    return body;
+}
+
+/**
+ * Function for exciting the qubit with a custom laser (excite_mw)
+ */
+Str excite_mw(Str envelope, Str duration, Str frequency, Str phase, Str amp, UInt qubit){
+    Str body_1 = "excite_MW " + to_string(envelope) + ", " +  to_string(duration) + ", ";
+    Str body_2 = to_string(frequency) + ", " + to_string(phase) + ", " +
+        to_string(amp)+ ", q" + to_string(qubit);
+    Str body = body_1 + body_2;
+    return body;
+}
+
+/**
+ * Function for branch instructions (br)
+ */
+Str branch(Str name_1, Str value_1, Str comparison, Str name_2, Str value_2, Str target_name, Str target_value) {
+    Str compare = name_1 + to_string(value_1) + comparison + name_2 + to_string(value_2);
+    Str body = "BR " + compare +", " + target_name + to_string(target_value);
+    return body;
+}
+
+/**
+ * Function for creating a label (label)
+ */
+Str label(Str labelcount){
+   Str body = "LABEL LAB" + labelcount;
+   return body;
+}
+
+/**
+ * Function for single qubit gate (qgate)
+ */
+Str qgate(Str gatename, UInt operand) {
+    Str body_1 = "qgate " + to_upper(gatename) + ", ";
+    Str body_2 = "q" + to_string(operand);
+    Str body = body_1 + body_2;
+    return body;
+}
+
+/**
+ * Function for two-qubit gate (qgate2)
+ */
+Str qgate2(Str gatename, Str operand_1, Str operand_2) {
+    Str body_1 = "qgate2 " + to_upper(gatename) + ", ";
+    Str body_2 = operand_1 + ", " + operand_2;
+    Str body = body_1 + body_2;
+    return body;
+}
+
+/**
+ * Function for storing information in memory (ST)
+ */
+Str store(Str reg_name1, Str reg_value1, Str reg_name2, Str reg_value2, Str memaddr){
+    Str body_1 = "ST " + reg_name1 + reg_value1 + ", " + reg_name2 + reg_value2 + "($" + memaddr + ")";
+
+//    Str body_2;
+//    if (!memaddr.empty()) {
+//        Str body_2 = "(" + memaddr + ")";
+//    } else {
+//    }
+//    Str body = body_1 + body_2;
+    return body_1;
+}
+
+/**
+ * Function for addition (ADD)
+ */
+Str add(Str name_1, Str value_1, Str name_2, Str value_2, Str name_3, Str value_3) {
+    Str body = "ADD " + name_1 + value_1 + ", " + name_2 + value_2 + ", " + name_3 + value_3;
+    return body;
+}
+
+/**
+ * Function for immediate addition (ADDi)
+ */
+Str addimm(Str value, Str regname, Str regvalue) {
+    Str body = "ADDi " + regname + regvalue + ", " + value;
+    return body;
+}
+
+/**
+ * Function for unconditional jump (jump)
+ */
+Str jump(Str labelcount) {
+    Str body = "JUMP LAB" + labelcount;
+    return body;
+}
+
+
+} // namespace detail
+} // namespace microcode
+} // namespace gen
+} // namespace pass
+} // namespace diamond
+} // namespace arch
+} // namespace ql
\ No newline at end of file
diff --git a/src/ql/arch/diamond/pass/gen/microcode/detail/functions.h b/src/ql/arch/diamond/pass/gen/microcode/detail/functions.h
new file mode 100644
index 000000000..dfb953f6a
--- /dev/null
+++ b/src/ql/arch/diamond/pass/gen/microcode/detail/functions.h
@@ -0,0 +1,83 @@
+#pragma once
+
+namespace ql {
+namespace arch {
+namespace diamond {
+namespace pass {
+namespace gen {
+namespace microcode {
+namespace detail {
+
+using namespace utils;
+
+/**
+ * Function for switching on the optical path
+ */
+Str switchOn(UInt qubit_path );
+
+/**
+ * Function for switching off the optical path
+ */
+Str switchOff(UInt qubit_path );
+
+/**
+ * Function for load immediate (LDi)
+ */
+Str loadimm(Str value, Str reg_name, Str reg_value);
+
+/**
+ * Function for move (mov)
+ */
+Str mov(Str reg1_name, Str reg1_value, Str reg2_name, Str reg2_value);
+
+/**
+ * Function for exciting the qubit with a custom laser (excite_mw)
+ */
+Str excite_mw(Str envelope, Str duration, Str frequency, Str phase, Str amp, UInt qubit);
+
+/**
+ * Function for branch instructions (br)
+ */
+Str branch(Str name_1, Str value_1, Str comparison, Str name_2, Str value_2, Str target_name, Str target_value);
+
+/**
+ * Function for creating a label (label)
+ */
+Str label(Str labelcount);
+
+/**
+ * Function for single qubit gate (qgate)
+ */
+Str qgate(Str gatename, UInt operand);
+
+/**
+ * Function for two-qubit gate (qgate2)
+ */
+Str qgate2(Str gatename, Str operand_1, Str operand_2);
+
+/**
+ * Function for storing information in memory (ST)
+ */
+Str store(Str reg_name1, Str reg_value1, Str reg_name2, Str reg_value2, Str memaddr);
+
+/**
+ * Function for addition (ADD)
+ */
+Str add(Str name_1, Str value_1, Str name_2, Str value_2, Str name_3, Str value_3);
+
+/**
+ * Function for immediate addition (ADDi)
+ */
+Str addimm(Str value, Str regname, Str regvalue);
+
+/**
+ * Function for unconditional jump (jump)
+ */
+Str jump(Str labelcount);
+} // namespace detail
+} // namespace microcode
+} // namespace gen
+} // namespace pass
+} // namespace diamond
+} // namespace arch
+} // namespace ql
diff --git a/src/ql/arch/diamond/pass/gen/microcode/microcode.cc b/src/ql/arch/diamond/pass/gen/microcode/microcode.cc
new file mode 100644
index 000000000..5f1e823ed
--- /dev/null
+++ b/src/ql/arch/diamond/pass/gen/microcode/microcode.cc
@@ -0,0 +1,761 @@
+/** \file
+ * Defines the pass for generation the microcode for the Fujitsu project quantum
+ * computer
+ */
+
+#include "ql/arch/diamond/pass/gen/microcode/microcode.h"
+#include "ql/arch/diamond/pass/gen/microcode/detail/functions.h"
+#include "ql/arch/diamond/annotations.h"
+
+#include "ql/pmgr/pass_types/base.h"
+
+#include "ql/utils/str.h"
+#include "ql/utils/filesystem.h"
+#include "ql/plat/platform.h"
+#include "ql/com/options.h"
+
+namespace ql {
+namespace arch {
+namespace diamond {
+namespace pass {
+namespace gen {
+namespace microcode {
+
+using namespace utils;
+
+/**
+ * Dumps docs for the code generator
+ */
+void GenerateMicrocodePass::dump_docs(
+    std::ostream &os,
+    const utils::Str &line_prefix
+) const {
+    utils::dump_str(os, line_prefix, R"(
+    Generates the microcode from the algorithm (cQASM/C++/Python) description
+    for quantum computing in diamond.
+    )");
+}
+
+utils::Str GenerateMicrocodePass::get_friendly_type() const {
+    return "Diamond microcode generator";
+}
+
+GenerateMicrocodePass::GenerateMicrocodePass(
+    const utils::Ptr<const pmgr::Factory> &pass_factory,
+    const utils::Str &instance_name,
+    const utils::Str &type_name
+) : pmgr::pass_types::ProgramTransformation(pass_factory, instance_name, type_name) {
+
+}
+
+utils::Int GenerateMicrocodePass::run(
+    const ir::ProgramRef &program,
+    const pmgr::pass_types::Context &context
+) const {
+    // General Idea: Make a big case statement with all the different options that
+    // cQASM provides. Then, decide for each option what to write to the output file.
+
+    // Specify output file name
+    Str file_name(context.output_prefix + ".dqasm");
+
+    // Specify the outfile name
+    OutFile outfile{file_name};
+
+    // Copy the kernel into a new kernel, add the necessary gates before and in between the existing gates.
+    for (const auto &kernel : program->kernels) {
+        ir::Kernel temp_kernel(
+            "dummy",
+            program->platform,
+            kernel->qubit_count,
+            kernel->creg_count,
+            kernel->breg_count
+        );
+
+        // Only for the first kernel
+
+        // For every qubit, insert a magnetic bias check
+        for (UInt q = 0; q < kernel->qubit_count; q++) {
+            temp_kernel.gate("sweep_bias", q);
+            temp_kernel.gates.back()->set_annotation<ql::arch::diamond::annotations::SweepBiasParameters>(
+                {10, q, 0, 10, 100, 0});
+            temp_kernel.gate("calculate_current", q);
+        }
+
+        // For every qubit, inset a rabi check
+        for (UInt q = 0; q < kernel->qubit_count; q++) {
+            // rabi check
+            temp_kernel.gate("rabi_check", q);
+            temp_kernel.gates.back()->set_annotation<ql::arch::diamond::annotations::RabiParameters>({100, 2, 3});
+        }
+
+        // For every qubit, insert a CRC
+        for (UInt q = 0; q < kernel->qubit_count; q++) {
+
+            temp_kernel.gate("crc", q);
+            temp_kernel.gates.back()->set_annotation<ql::arch::diamond::annotations::CRCParameters>({5, q});
+        }
+
+        // For every qubit, initialize to |0>
+        for (UInt q = 0; q < kernel->qubit_count; q++) {
+
+            temp_kernel.gate("initialize", q);
+        }
+
+        // Add the gates from the original kernel. Every 10 gates, add a CRC check
+        // for all qubits.
+        UInt number_gates = 0;
+        for (const auto &gate : kernel->gates) {
+            if (number_gates > 9) {
+                for (UInt q = 0; q < kernel->qubit_count; q++) {
+
+                    temp_kernel.gate("crc", q);
+                    temp_kernel.gates.back()->set_annotation<ql::arch::diamond::annotations::CRCParameters>({5, q});
+                }
+                number_gates = 0;
+            }
+
+            temp_kernel.gates.add(gate);
+            number_gates++;
+        }
+
+        // Copy the gates to the original kernel and set the cycles_valid flag to false
+        // because the cycle count is not accurate anymore.
+        kernel->gates = std::move(temp_kernel.gates);
+        kernel->cycles_valid = false;
+    }
+
+    // Make global variable for keeping track label numbers.
+    int labelcount = 0;
+
+    for (const ir::KernelRef &kernel : program->kernels) {
+        for (const ir::GateRef &gate : kernel->gates) {
+            const auto &data = program->platform->find_instruction(gate->name);
+
+            outfile << "# " << gate->qasm() << "\n";
+
+            // Determine gate type.
+            utils::Str type = "unknown";
+            auto iterator = data.find("diamond_type");
+            if (iterator != data.end() && iterator->is_string()) {
+                type = iterator->get<utils::Str>();
+            }
+
+            // Check for condition
+            Str end_label;
+            if (gate->condition == ir::ConditionType::UNARY) {
+                end_label = to_string(labelcount++);
+                outfile << detail::branch("ResultReg", to_string(gate->cond_operands[0]), "<", "", "1", "LAB", end_label) << "\n";
+            } else if (gate->condition != ir::ConditionType::ALWAYS) {
+                throw utils::Exception("gate with " + to_string(gate->condition) + " is not supported");
+            }
+
+            // Determine the microcode output for the given gate-type
+            // If the gate-type is known, check the gate name.
+            // If the gate-type is not known, check the gate name
+            // If the gate-name is not known, print that the gate `name` is not known.
+            // Last option likely will not occur as OpenQL will throw an error
+            // when running the algorithm.
+            if (type == "qgate") {
+                // Single qubit gate
+                outfile << detail::qgate(gate->name, gate->operands[0]) << "\n";
+            } else if (type == "qgate2") {
+                // Two qubit gate. Not that in the diamond structure, 2 qubit gates are only possible between
+                // a qubit and a nuclear spin qubit.
+                Str op_1 = "q" + to_string(gate->operands[0]);
+                Str op_2 = "nuq" + to_string(gate->operands[1]);
+                outfile << detail::qgate2(gate->name, op_1, op_2) << "\n";
+            } else if (type == "rotation") {
+                // custom rotations around an axis
+                UInt a = 1000 / 3.14159265359;
+                Str duration = to_string(a * gate->angle);
+                if (gate->name == "rx") {
+                    Str phase = to_string(1.57);
+                    outfile << detail::excite_mw("0", duration, "200", phase, "60",
+                                                 gate->operands[0]);
+                } else if (gate->name == "ry") {
+                    Str phase = to_string(3.14);
+                    outfile << detail::excite_mw("0", duration, "200", phase, "60",
+                                                 gate->operands[0]);
+                } else if (gate->name == "rz") {
+                    Str phase = to_string(0);
+                    outfile << detail::excite_mw("0", duration, "200", phase, "60",
+                                                 gate->operands[0]);
+                } else if (gate->name == "cr") {
+                    Str phase = to_string(0);
+                    outfile << detail::qgate2(gate->name, "q" + to_string(
+                        gate->operands[0]), "nuq" + to_string(gate->operands[1]));
+                    outfile << ", " << duration << "\n";
+                } else if (gate->name == "crk") {
+                    Str phase = to_string(0);
+                    UInt angle = 1000 / (3.14 / pow(2, gate->angle));
+                    outfile << detail::qgate2(gate->name, "q" + to_string(
+                        gate->operands[0]), "nuq" + to_string(gate->operands[1]));
+                    outfile << ", " << to_string(angle) << "\n";
+                }
+
+                // Alternate representation of x90, mx90, y90 and my90. Now works with using qgate.
+                // Can be changed to excite_MW by setting diamond_type in hw config file to
+                // "rotation" instead of "qgate".
+                else if (gate->name == "x90") {
+                    Str phase = to_string(1.57);
+                    duration = to_string((1000 / 3.14) * 1.57);
+                    outfile << detail::excite_mw("0", duration, "200", phase, "60",
+                                                 gate->operands[0]);
+                } else if (gate->name == "mx90") {
+                    Str phase = to_string(1.57);
+                    duration = to_string((1000 / 3.14) * 4.71);
+                    outfile << detail::excite_mw("0", duration, "200", phase, "60",
+                                                 gate->operands[0]);
+                } else if (gate->name == "y90") {
+                    Str phase = to_string(3.14);
+                    duration = to_string((1000 / 3.14) * 1.57);
+                    outfile << detail::excite_mw("0", duration, "200", phase, "60",
+                                                 gate->operands[0]);
+                } else if (gate->name == "my90") {
+                    Str phase = to_string(3.14);
+                    duration = to_string((1000 / 3.14) * 4.71);
+                    outfile << detail::excite_mw("0", duration, "200", phase, "60",
+                                                 gate->operands[0]);
+                }
+            } else if (type == "prepare") {
+                if (gate->name == "prep_z") {
+                    // nothing, already in z-basis
+                } else if (gate->name == "prep_x") {
+                    // Rotate 1/2-pi around y-axis
+                    outfile
+                        << detail::excite_mw("0", to_string(500), "200", "3.14", "60",
+                                             gate->operands[0]);
+                } else if (gate->name == "prep_y") {
+                    // Rotate 1/2-pi around x-axis
+                    outfile
+                        << detail::excite_mw("0", to_string(500), "200", "1.57", "60",
+                                             gate->operands[0]);
+                } else if (gate->name == "mprep_x") {
+                    // Rotate -1/2-pi around y-axis
+                    outfile << detail::excite_mw("0", to_string(1500), "200", "3.14", "60", gate->operands[0]);
+                } else if (gate->name == "mprep_y") {
+                    // Rotate -1/2-pi around x-axis
+                    outfile << detail::excite_mw("0", to_string(1500), "200", "1.57", "60", gate->operands[0]);
+                }
+            } else if (type == "classical") {
+                // These instructions calculate a new value for either current or
+                // voltage using purely classical instructions. They have to be
+                // elaborated using the classical instructions from the micro ISA.
+                if (gate->name == "calculate_current") {
+                    outfile << "calculate_current()" << "\n";
+                } else if (gate->name == "calculate_voltage") {
+                    outfile << "calculate_voltage()" << "\n";
+                }
+            } else if (type == "initial_checks") {
+                if (gate->name == "mag_bias") {
+                    // Code for magnetic biasing
+                    // Not added because it is decomposed into sweep_bias and calculate_current()
+                    // at lines 76-79 of microcode.cc
+                } else if (gate->name == "rabi_check") {
+                    // Implements the rabi check.
+                    Str qubit_number = to_string(gate->operands[0]);
+
+                    const auto &params =
+                        gate->get_annotation<annotations::RabiParameters>();
+                    const Str threshold = "0";
+                    const Str threshold_measure = "33";
+                    Str count = to_string(labelcount);
+                    Str count_1 = to_string(labelcount + 1);
+                    Str count_2 = to_string(labelcount + 2);
+
+                    outfile
+                        << detail::loadimm(to_string(params.measurements), "R",
+                                           "1") << "\n";
+                    outfile
+                        << detail::loadimm(to_string(params.duration), "R", "2")
+                        << "\n";
+                    outfile
+                        << detail::loadimm(to_string(params.t_max), "R", "3")
+                        << "\n";
+
+                    outfile << detail::loadimm("0", "R", "32")
+                            << "\n"; // number measurements
+                    outfile << detail::label(count) << "\n";
+                    outfile << detail::label(count_1) << "\n";
+                    //Init qubit
+                    outfile << detail::label(count_2) << "\n";
+                    outfile << detail::switchOn(gate->operands[0]) << "\n";
+                    outfile << detail::loadimm("0", "photonReg", qubit_number)
+                            << "\n";
+                    outfile << detail::excite_mw("1", "100", "200", "0", "60",
+                                                 gate->operands[0]) << "\n";
+                    outfile << detail::mov("photonReg", qubit_number, "R",
+                                           qubit_number) << "\n";
+                    outfile << detail::switchOff(gate->operands[0]) << "\n";
+                    outfile
+                        << detail::branch("R", qubit_number, ">", "", threshold,
+                                          "LAB", count_2) << "\n";
+
+                    //Excite with Time Duration T
+                    outfile << detail::excite_mw("1", "R2", "200", "0", "60",
+                                                 gate->operands[0]) << "\n";
+
+                    //Readout
+                    outfile << detail::switchOn(gate->operands[0]) << "\n";
+                    outfile << detail::loadimm("0", "photonReg", qubit_number)
+                            << "\n";
+                    outfile << detail::excite_mw("1", "100", "200", "0", "60",
+                                                 gate->operands[0]) << "\n";
+                    outfile << detail::mov("photonReg", qubit_number, "R",
+                                           qubit_number) << "\n";
+                    outfile << detail::switchOff(gate->operands[0]) << "\n";
+                    outfile << detail::branch("R", qubit_number, "<", "R",
+                                              threshold_measure, "ResultReg",
+                                              qubit_number) << "\n";
+
+                    // Store result and adjust memory address for next value
+                    outfile << detail::store("ResultReg", qubit_number,
+                                             "memAddress", qubit_number, "0")
+                            << "\n";
+                    outfile << detail::addimm("4", "memAddr", qubit_number)
+                            << "\n";
+                    outfile << detail::addimm("1", "R", "32") << "\n";
+
+                    // if #measurements < threshold, measure again
+                    outfile << detail::branch("R", "32", "<", "R", "1", "LAB",
+                                              count_1) << "\n";
+                    outfile
+                        << detail::store("R", "2", "memAddr", qubit_number, "0")
+                        << "\n";
+                    outfile << detail::addimm("4", "memAddr", qubit_number)
+                            << "\n";
+                    outfile << detail::addimm("10", "R", "2") << "\n";
+                    outfile
+                        << detail::branch("R", "2", "<", "R", "3", "LAB", count)
+                        << "\n";
+
+                    // Add 3 to labelcount because label was used thrice.
+                    labelcount++;
+                    labelcount++;
+                    labelcount++;
+                } else if (gate->name == "crc") {
+                    // Implements the Charge Resonance Check.
+                    const auto &params =
+                        gate->get_annotation<annotations::CRCParameters>();
+
+                    Str qubit_number = to_string(gate->operands[0]);
+                    Str count = to_string(labelcount);
+                    Str count2 = to_string(labelcount + 1);
+
+                    outfile << detail::loadimm(to_string(params.threshold),
+                                               "treshReg", qubit_number)
+                            << "\n";
+                    outfile
+                        << detail::loadimm(to_string(params.value), "dacReg",
+                                           qubit_number) << "\n";
+
+                    outfile << detail::label(count) << "\n";
+                    outfile << detail::loadimm("0", "photon Reg", qubit_number)
+                            << "\n";
+                    outfile << detail::switchOn(gate->operands[0]) << "\n";
+                    outfile << detail::excite_mw("1", "100", "200", "0", "60",
+                                                 gate->operands[0]) << "\n";
+                    outfile << detail::mov("photonReg", qubit_number, "R",
+                                           qubit_number) << "\n";
+                    outfile << detail::switchOff(gate->operands[0]) << "\n";
+                    outfile
+                        << detail::branch("R", qubit_number, ">", "treshReg",
+                                          qubit_number, "LAB",
+                                          count2) << "\n";
+                    outfile << "calculateVoltage()" << "\n";
+                    outfile << detail::jump(count) << "\n";
+                    outfile << detail::label(count2) << "\n";
+
+                    // Add 2 to labelcount because label was used twice.
+                    labelcount++;
+                    labelcount++;
+                }
+            } else if (type == "calibration") {
+               if (gate->name == "decouple") {
+                   // Code for XY-8 dynamical decoupling
+                   Str t = to_string(50);
+                   Str t2 = to_string(100);
+                   outfile << detail::excite_mw("0", "500", "200", "1.57", "60", gate->operands[0])<< "\n"; // pi/2 x
+                   outfile << "wait "<< t << "\n";
+                   outfile << detail::excite_mw("0", "1000", "200", "1.57", "60", gate->operands[0]) << "\n"; // pi x
+                   outfile << "wait "<< t2 << "\n";
+                   outfile << detail::excite_mw("0", "1000", "200", "3.14", "60", gate->operands[0]) << "\n"; // pi y
+                   outfile << "wait "<< t2 << "\n";
+                   outfile << detail::excite_mw("0", "1000", "200", "1.57", "60", gate->operands[0]) << "\n"; // pi x
+                   outfile << "wait "<< t2 << "\n";
+                   outfile << detail::excite_mw("0", "1000", "200", "3.14", "60", gate->operands[0]) << "\n"; // pi y
+                   outfile << "wait "<< t2 << "\n";
+                   outfile << detail::excite_mw("0", "1000", "200", "3.14", "60", gate->operands[0]) << "\n"; // pi y
+                   outfile << "wait "<< t2 << "\n";
+                   outfile << detail::excite_mw("0", "1000", "200", "1.57", "60", gate->operands[0]) << "\n"; // pi x
+                   outfile << "wait "<< t2 << "\n";
+                   outfile << detail::excite_mw("0", "1000", "200", "3.14", "60", gate->operands[0]) << "\n"; // pi y
+                   outfile << "wait "<< t2 << "\n";
+                   outfile << detail::excite_mw("0", "1000", "200", "1.57", "60", gate->operands[0]) << "\n"; // pi x
+                   outfile << "wait "<< t << "\n";
+                   outfile << detail::excite_mw("0", "500", "200", "1.57", "60", gate->operands[0]) << "\n"; // pi/2 x
+
+               } else if (gate->name == "cal_measure") {
+                   // code for measurement calibration
+                   Str lab_1 = to_string(labelcount+1);
+                   Str lab_2 = to_string(labelcount+3);
+
+                   Str qubit_number = to_string(gate->operands[0]);
+                   const Str threshold = "0";
+                   Str count = to_string(labelcount);
+                   Str count_2 = to_string(labelcount+2);
+
+                   // initialize qubit to 0
+                   outfile << detail::label(count) << "\n";
+                   outfile << detail::switchOn(gate->operands[0]) << "\n";
+                   outfile << detail::loadimm("0", "photonReg", qubit_number)
+                           << "\n";
+                   outfile << detail::excite_mw("1", "100", "200", "0", "60",
+                                                gate->operands[0]) << "\n";
+                   outfile << detail::mov("photonReg", qubit_number, "R",
+                                          qubit_number) << "\n";
+                   outfile << detail::switchOff(gate->operands[0]) << "\n";
+                   outfile
+                       << detail::branch("R", qubit_number, ">", "", threshold,
+                                         "LAB", count) << "\n";
+
+                   outfile << detail::loadimm(to_string(0), "photonReg", to_string(gate->operands[0])) << "\n";
+                   outfile << detail::loadimm(to_string(1), "R", "30") << "\n";
+                   outfile << detail::label(lab_1) << "\n";
+                   outfile << detail::switchOn(gate->operands[0]) << "\n";
+                   outfile << detail::excite_mw("0", "1", "200", "0", "60", gate->operands[0]) << "\n";
+                   outfile << detail::switchOff(gate->operands[0]) << "\n";
+                   outfile << detail::store("photonReg", to_string(gate->operands[0]), "R", "1", "0") << "\n";
+                   outfile << detail::store("R", "30", "R", "1", "0") << "\n";
+                   outfile << detail::addimm("1", "R", "30") << "\n";
+                   outfile << detail::branch("R", "30", "<", "", "40", "LAB", lab_1) << "\n";
+
+                   // initialize qubit to 0
+                   outfile << detail::label(count_2) << "\n";
+                   outfile << detail::switchOn(gate->operands[0]) << "\n";
+                   outfile << detail::loadimm("0", "photonReg", qubit_number)
+                           << "\n";
+                   outfile << detail::excite_mw("1", "100", "200", "0", "60",
+                                                gate->operands[0]) << "\n";
+                   outfile << detail::mov("photonReg", qubit_number, "R",
+                                          qubit_number) << "\n";
+                   outfile << detail::switchOff(gate->operands[0]) << "\n";
+                   outfile
+                       << detail::branch("R", qubit_number, ">", "", threshold,
+                                         "LAB", count_2) << "\n";
+                   outfile << detail::qgate("x", gate->operands[0]) << "\n";
+
+                   outfile << detail::loadimm(to_string(0), "photonReg", to_string(gate->operands[0])) << "\n";
+                   outfile << detail::loadimm(to_string(1), "R", "30") << "\n";
+                   outfile << detail::label(lab_2) << "\n";
+                   outfile << detail::switchOn(gate->operands[0]) << "\n";
+                   outfile << detail::excite_mw("0", "1", "200", "0", "60", gate->operands[0]) << "\n";
+                   outfile << detail::switchOff(gate->operands[0]) << "\n";
+                   outfile << detail::store("photonReg", to_string(gate->operands[0]), "R", "2", "0") << "\n";
+                   outfile << detail::store("R", "30", "R", "3", "0") << "\n";
+                   outfile << detail::addimm("1", "R", "30") << "\n";
+                   outfile << detail::branch("R", "30", "<", "", "40", "LAB",
+                                             lab_2) << "\n";
+
+                   outfile << "calculate_readouttime(R0, R1, R2, R3)" << "\n"; //function still needs to be implemented/designed
+
+                   labelcount = labelcount+4;
+
+               } else if (gate->name == "cal_pi") {
+                   // code for pi-rotation calibration
+                   Str qubit_number = to_string(gate->operands[0]);
+                   const Str threshold = "0";
+                   Str count = to_string(labelcount);
+                   Str lab1 = to_string(labelcount+1);
+                   Str lab2 = to_string(labelcount+2);
+
+                   // init qubit to 0
+                   outfile << detail::label(count) << "\n";
+                   outfile << detail::switchOn(gate->operands[0]) << "\n";
+                   outfile << detail::loadimm("0", "photonReg", qubit_number)
+                           << "\n";
+                   outfile << detail::excite_mw("1", "100", "200", "0", "60",
+                                                gate->operands[0]) << "\n";
+                   outfile << detail::mov("photonReg", qubit_number, "R",
+                                          qubit_number) << "\n";
+                   outfile << detail::switchOff(gate->operands[0]) << "\n";
+                   outfile
+                       << detail::branch("R", qubit_number, ">", "", threshold,
+                                         "LAB", count) << "\n";
+
+
+                   outfile << detail::loadimm("0", "R", to_string(gate->operands[0])) << "\n";
+                   outfile << detail::loadimm("0", "R", to_string(gate->operands[0]+1)) << "\n";
+                   outfile << detail::loadimm("0", "R", to_string(gate->operands[0]+2)) << "\n";
+                   outfile << detail::label(lab1) << "\n";
+                   outfile << detail::label(lab2) << "\n";
+                   outfile << detail::switchOn(gate->operands[0]) << "\n";
+                   outfile << detail::excite_mw("0", "1000", "200", "0", "R"+to_string(gate->operands[0]), gate->operands[0]) << "\n";
+                   outfile << detail::switchOff(gate->operands[0]) << "\n";
+                   outfile << detail::addimm("1", "R", to_string(gate->operands[0]+1)) << "\n";
+                   outfile << detail::branch("R", to_string(gate->operands[0]+1), "<", "", "12", "LAB", lab1) << "\n";
+                   outfile << "measure_fidelity(R0) \n";
+                   outfile << detail::addimm("0.1", "R", to_string(gate->operands[0])) << "\n";
+                   outfile << detail::addimm("1", "R", to_string(gate->operands[0]+2)) << "\n";
+                   outfile << detail::branch("R", to_string(gate->operands[0]+2), ">", "", "10", "LAB", lab2) << "\n";
+                   outfile << "calculate_minimum_fidelity() \n";
+
+                   labelcount = labelcount+2;
+               } else if (gate->name == "cal_halfpi") {
+                   // code for pi/2-rotation calibration
+                   Str qubit_number = to_string(gate->operands[0]);
+                   const Str threshold = "0";
+                   Str count = to_string(labelcount);
+                   Str lab1 = to_string(labelcount+1);
+                   Str lab2 = to_string(labelcount+2);
+
+                   // init qubit to 0
+                   outfile << detail::label(count) << "\n";
+                   outfile << detail::switchOn(gate->operands[0]) << "\n";
+                   outfile << detail::loadimm("0", "photonReg", qubit_number)
+                           << "\n";
+                   outfile << detail::excite_mw("1", "100", "200", "0", "60",
+                                                gate->operands[0]) << "\n";
+                   outfile << detail::mov("photonReg", qubit_number, "R",
+                                          qubit_number) << "\n";
+                   outfile << detail::switchOff(gate->operands[0]) << "\n";
+                   outfile
+                       << detail::branch("R", qubit_number, ">", "", threshold,
+                                         "LAB", count) << "\n";
+
+                   outfile << detail::loadimm("0", "R", to_string(gate->operands[0])) << "\n";
+                   outfile << detail::loadimm("0", "R", to_string(gate->operands[0]+1)) << "\n";
+                   outfile << detail::loadimm("0", "R", to_string(gate->operands[0]+2)) << "\n";
+                   outfile << detail::label(lab1) << "\n";
+                   outfile << detail::switchOn(gate->operands[0]) << "\n";
+                   outfile << detail::excite_mw("0", "500", "200", "0", "R"+to_string(gate->operands[0]), gate->operands[0]) << "\n";
+                   outfile << detail::switchOff(gate->operands[0]) << "\n";
+
+                   outfile << detail::addimm("1", "R", to_string(gate->operands[0]+1)) << "\n";
+                   outfile << detail::branch("R", to_string(gate->operands[0]+1), "<", "", "7", "LAB", lab1) << "\n";
+                   outfile << "measure_fidelity(R0) \n";
+
+                   // init qubit to 0
+                   outfile << detail::label(count) << "\n";
+                   outfile << detail::switchOn(gate->operands[0]) << "\n";
+                   outfile << detail::loadimm("0", "photonReg", qubit_number)
+                           << "\n";
+                   outfile << detail::excite_mw("1", "100", "200", "0", "60",
+                                                gate->operands[0]) << "\n";
+                   outfile << detail::mov("photonReg", qubit_number, "R",
+                                          qubit_number) << "\n";
+                   outfile << detail::switchOff(gate->operands[0]) << "\n";
+                   outfile
+                       << detail::branch("R", qubit_number, ">", "", threshold,
+                                         "LAB", count) << "\n";
+
+                   outfile << detail::loadimm("0", "R", to_string(gate->operands[0])) << "\n";
+                   outfile << detail::loadimm("0", "R", to_string(gate->operands[0]+1)) << "\n";
+                   outfile << detail::loadimm("0", "R", to_string(gate->operands[0]+2)) << "\n";
+                   outfile << detail::label(lab2) << "\n";
+                   outfile << detail::switchOn(gate->operands[0]) << "\n";
+                   outfile << detail::excite_mw("0", "500", "200", "0", "R"+to_string(gate->operands[0]), gate->operands[0]) << "\n";
+                   outfile << detail::excite_mw("0", "1000", "200", "0", "60", gate->operands[0]) << "\n";
+                   outfile << detail::switchOff(gate->operands[0]) << "\n";
+
+                   outfile << detail::addimm("1", "R", to_string(gate->operands[0]+1)) << "\n";
+                   outfile << detail::branch("R", to_string(gate->operands[0]+1), "<", "", "7", "LAB", lab2) << "\n";
+                   outfile << "measure_fidelity(R0) \n";
+
+                   labelcount = labelcount + 3;
+               }
+            } else {
+                if (gate->name == "measure") {
+                    // Measures a qubit and stores the result in ResultRegQ,
+                    // where Q is the qubit number. Also stores the result in
+                    // breg[Q], as per OpenQL standard.
+                    Str qubit_number = to_string(gate->operands[0]);
+                    const Str threshold = "33";
+
+                    outfile << detail::switchOn(gate->operands[0]) << "\n";
+                    outfile << detail::loadimm("0", "photonReg", qubit_number)
+                            << "\n";
+                    outfile << detail::excite_mw("1", "100", "200", "0", "60",
+                                                 gate->operands[0]) << "\n";
+                    outfile
+                        << detail::mov("photonReg", qubit_number, "R",
+                                       qubit_number)
+                        << "\n";
+                    outfile << detail::switchOff(gate->operands[0]) << "\n";
+                    outfile << detail::branch("R", qubit_number, "<", "R",
+                                              threshold, "ResultReg",
+                                              qubit_number) << "\n";
+                } else if (gate->name == "initialize") {
+                    // Initializes a qubit to |0>.
+                    Str qubit_number = to_string(gate->operands[0]);
+                    const Str threshold = "0";
+                    Str count = to_string(labelcount);
+
+                    outfile << detail::label(count) << "\n";
+                    outfile << detail::switchOn(gate->operands[0]) << "\n";
+                    outfile << detail::loadimm("0", "photonReg", qubit_number)
+                            << "\n";
+                    outfile << detail::excite_mw("1", "100", "200", "0", "60",
+                                                 gate->operands[0]) << "\n";
+                    outfile << detail::mov("photonReg", qubit_number, "R",
+                                           qubit_number) << "\n";
+                    outfile << detail::switchOff(gate->operands[0]) << "\n";
+                    outfile
+                        << detail::branch("R", qubit_number, ">", "", threshold,
+                                          "LAB", count) << "\n";
+
+                    labelcount++;
+                } else if (gate->name == "wait") {
+                    // Implements the wait x-cycles instruction.
+                    outfile << "wait "
+                            << to_string(gate->duration) << "\n";
+                } else if (gate->name == "qnop") {
+                    // Quantum nop instruction
+                    outfile << "wait 1" << "\n";
+                } else if (gate->name == "sweep_bias") {
+                    // Implements the instruction sweep_bias, that sweeps the frequency
+                    // of the laser of a qubit to help determine the magnetic biasing value
+                    // for correct biasing.
+                    const auto &params =
+                        gate->get_annotation<annotations::SweepBiasParameters>();
+
+                    Str qubit_number = to_string(gate->operands[0]);
+                    Str count = to_string(labelcount);
+
+                    outfile
+                        << detail::loadimm(to_string(params.value), "dacReg",
+                                           to_string(params.dacreg)) << "\n";
+                    outfile
+                        << detail::loadimm(to_string(params.start),
+                                           "sweepStartReg",
+                                           qubit_number) << "\n";
+                    outfile
+                        << detail::loadimm(to_string(params.step),
+                                           "sweepStepReg",
+                                           qubit_number) << "\n";
+                    outfile
+                        << detail::loadimm(to_string(params.max),
+                                           "sweepStopReg",
+                                           qubit_number) << "\n";
+                    outfile
+                        << detail::loadimm(to_string(params.memaddress),
+                                           "memAddr",
+                                           qubit_number) << "\n";
+                    outfile << detail::label(count) << "\n";
+                    outfile << detail::switchOn(gate->operands[0]) << "\n";
+                    outfile << detail::excite_mw("1", "100",
+                                                 "sweepStartReg" + qubit_number,
+                                                 "0", "60", gate->operands[0])
+                            << "\n";
+                    outfile << detail::switchOff(gate->operands[0]) << "\n";
+                    outfile
+                        << detail::mov("photonReg", qubit_number, "R",
+                                       qubit_number)
+                        << "\n";
+                    outfile
+                        << detail::store("R", qubit_number, "memAddr",
+                                         qubit_number,
+                                         "0") << "\n";
+                    outfile
+                        << detail::store("sweepStartReg", qubit_number,
+                                         "memAddr",
+                                         qubit_number, "0") << "\n";
+                    outfile << detail::add("sweepStartReg", qubit_number,
+                                           "sweepStartReg", qubit_number,
+                                           "sweepStepReg", qubit_number)
+                            << "\n";
+                    outfile << detail::addimm("4", "memAddr", qubit_number)
+                            << "\n";
+                    outfile
+                        << detail::branch("sweepStartReg", qubit_number, "<",
+                                          "sweepStopReg", qubit_number, "LAB",
+                                          count) << "\n";
+                    labelcount++;
+                } else if (gate->name == "excite_mw") {
+                    // Implements the custom instruction on how the user wants
+                    // to use the laser.
+                    const auto &params =
+                        gate->get_annotation<annotations::ExciteMicrowaveParameters>();
+
+                    outfile << detail::excite_mw(to_string(params.envelope),
+                                                 to_string(params.duration),
+                                                 to_string(params.frequency),
+                                                 to_string(params.phase),
+                                                 to_string(params.amplitude),
+                                                 gate->operands[0]) << "\n";
+                } else if (gate->name == "memswap") {
+                    // Implements the swap from electron qubit to nuclear spin qubit.
+                    const auto &params =
+                        gate->get_annotation<annotations::MemSwapParameters>();
+
+                    Str nuq = "nuq" + to_string(params.nuclear);
+                    Str qubit = "q" + to_string(gate->operands[0]);
+                    outfile << detail::qgate2("pmy90", qubit, nuq) << "\n";
+                    outfile << detail::qgate("x90", gate->operands[0]) << "\n";
+                    outfile << detail::qgate2("pmx90", qubit, nuq) << "\n";
+                    outfile << detail::qgate("my90", gate->operands[0]) << "\n";
+                } else if (gate->name == "qentangle") {
+                    // Implements electron-nuclear spin entanglement.
+                    const auto &params =
+                        gate->get_annotation<annotations::QEntangleParameters>();
+
+                    Str nuq = "nuq" + to_string(params.nuclear);
+                    Str qubit = "q" + to_string(gate->operands[0]);
+                    outfile << detail::qgate("mx90", gate->operands[0]) << "\n";
+                    outfile << detail::qgate2("pmx90", qubit, nuq) << "\n";
+                    outfile << detail::qgate("x90", gate->operands[0]) << "\n";
+                } else if (gate->name == "nventangle") {
+                    // Implements electron-electron entanglement following the
+                    // Barrett and Kok scheme.
+                    Str count = to_string(labelcount);
+                    Str count_1 = to_string(labelcount + 1);
+
+                    outfile << detail::loadimm("0", "R", "2") << "\n";
+                    outfile << detail::label(count) << "\n";
+                    outfile << detail::switchOn(gate->operands[0]) << "\n";
+                    outfile << detail::switchOn(gate->operands[1]) << "\n";
+                    outfile << detail::excite_mw("1", "100", "200", "0", "60",
+                                                 gate->operands[0]) << "\n";
+                    outfile << detail::excite_mw("1", "100", "200", "0", "60",
+                                                 gate->operands[1]) << "\n";
+                    outfile << "wait 100" << "\n";
+                    outfile << detail::mov("R", "0", "photonReg", "01") << "\n";
+                    outfile << detail::switchOff(gate->operands[0]) << "\n";
+                    outfile << detail::switchOff(gate->operands[1]) << "\n";
+                    outfile << detail::addimm("1", "R", "2") << "\n";
+                    outfile << "wait 50" << "\n";
+                    outfile
+                        << detail::branch("R", "1", ">", "", "1", "LAB",
+                                          count_1)
+                        << "\n";
+                    outfile << detail::qgate("x", gate->operands[0]) << "\n";
+                    outfile << detail::qgate("x", gate->operands[1]) << "\n";
+                    outfile << detail::mov("R", "0", "R", "1") << "\n";
+                    outfile << detail::jump(count) << "\n";
+                    outfile << detail::label(count_1) << "\n";
+
+                    labelcount++;
+                    labelcount++;
+                } else {
+                    outfile << "ERROR: Gate " + gate->name +
+                               " is not supported by the Diamond Architecture."
+                            << "\n";
+                }
+            }
+
+            if (!end_label.empty()) {
+                outfile << detail::label(end_label) << "\n";
+            }
+
+            outfile << "\n";
+        }
+    }
+    return 0;
+}
+
+} // namespace microcode
+} // namespace gen
+} // namespace pass
+} // namespace diamond
+} // namespace arch
+} // namespace ql
diff --git a/src/ql/arch/diamond/resources/hwconf_default.json b/src/ql/arch/diamond/resources/hwconf_default.json
new file mode 100644
index 000000000..9dd1b557e
--- /dev/null
+++ b/src/ql/arch/diamond/resources/hwconf_default.json
@@ -0,0 +1,266 @@
+{
+  "eqasm_compiler": "diamond",
+
+  "hardware_settings": {
+    "qubit_number": 10,
+    "cycle_time": 20
+  },
+
+  "gate_decomposition": {
+    "toffoli %0, %1, %2" : ["h %2", "cnot %1 %2", "tdag %2", "cnot %0 %2", "t %2","cnot %1 %2", "tdag %2", "cnot %0 %2", "t %1", "t %2", "cnot %0 %1", "h %2", "t %0", "tdag %1", "cnot %0 %1"],
+    "measure_z %0": ["measure %0"],
+    "measure_y %0": ["mprep_y %0", "measure %0"],
+    "measure_x %0": ["mprep_x %0", "measure %0"]
+  },
+
+  "instructions": {
+
+    "prep_x": {
+      "duration": 40,
+      "diamond_type": "prepare"
+    },
+
+    "prep_y": {
+      "duration": 40,
+      "diamond_type": "prepare"
+    },
+
+    "prep_z": {
+      "duration": 40,
+      "diamond_type": "prepare"
+    },
+
+    "mprep_x": {
+      "duration": 40,
+      "diamond_type": "prepare"
+    },
+
+    "mprep_y": {
+      "duration": 40,
+      "diamond_type": "prepare"
+    },
+
+    "qnop": {
+      "duration": 1
+    },
+
+    "calculate_current": {
+      "duration": 1,
+      "diamond_type": "classical"
+    },
+
+    "calculate_voltage": {
+      "duration": 1,
+      "diamond_type": "classical"
+    },
+
+    "i": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+    "h": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+    "x": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+    "y": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+
+    "z": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+
+    "initialize": {
+      "duration": 40
+    },
+
+    "x90": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+
+    "y90": {
+      "duration": 20,
+      "diamond_type": "qgate"
+    },
+
+    "x180": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+
+    "y180": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+
+    "mx90": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+
+    "my90": {
+      "duration": 20,
+      "diamond_type": "qgate"
+    },
+
+    "rx": {
+      "duration": 40,
+      "diamond_type": "rotation"
+    },
+
+    "ry": {
+      "duration": 40,
+      "diamond_type": "rotation"
+    },
+
+    "rz": {
+      "duration": 40,
+      "diamond_type": "rotation"
+    },
+
+    "cr": {
+      "duration": 40,
+      "diamond_type": "rotation"
+    },
+
+    "crk": {
+      "duration": 40,
+      "diamond_type": "rotation"
+    },
+
+    "s": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+
+    "sdag": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+
+    "t": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+
+    "tdag": {
+      "duration": 40,
+      "diamond_type": "qgate"
+    },
+
+    "cnot": {
+      "duration": 80,
+      "diamond_type": "qgate2"
+    },
+
+    "pmx90": {
+      "duration": 80,
+      "diamond_type": "qgate2"
+    },
+
+    "pmy90": {
+      "duration": 80,
+      "diamond_type": "qgate2"
+    },
+
+    "pmx180": {
+      "duration": 80,
+      "diamond_type": "qgate2"
+    },
+
+    "pmy180": {
+      "duration": 80,
+      "diamond_type": "qgate2"
+    },
+
+    "cz": {
+      "duration": 80,
+      "diamond_type": "qgate2"
+    },
+
+    "measure": {
+      "duration": 300
+    },
+
+    "display": {
+      "duration": 20,
+      "qubits": []
+    },
+
+    "display_binary": {
+      "duration": 20,
+      "qubits": []
+    },
+
+    "swap": {
+      "duration": 80,
+      "diamond_type": "qgate2"
+    },
+
+    "memswap": {
+      "duration": 80
+    },
+
+    "qentangle": {
+      "duration": 60
+    },
+
+    "nventangle": {
+      "duration": 100
+    },
+
+    "sweep_bias": {
+      "duration": 300
+    },
+
+    "excite_mw": {
+      "duration": 20
+    },
+
+    "crc": {
+      "duration": 20,
+      "diamond_type": "initial_checks"
+    },
+
+    "mag_bias": {
+      "duration": 300,
+      "diamond_type": "initial_checks"
+    },
+
+    "rabi_check": {
+      "duration": 300,
+      "diamond_type": "initial_checks"
+    },
+
+    "wait": {
+      "duration": 1
+    },
+
+    "decouple": {
+      "duration": 300,
+      "diamond_type": "calibration"
+    },
+
+    "cal_measure": {
+      "duration": 300,
+      "diamond_type": "calibration"
+    },
+
+    "cal_pi": {
+      "duration": 300,
+      "diamond_type": "calibration"
+    },
+
+    "cal_halfpi": {
+      "duration": 300,
+      "diamond_type": "calibration"
+    }
+  }
+}
diff --git a/src/ql/arch/factory.cc b/src/ql/arch/factory.cc
index 963f6ecad..fc4ff0e53 100644
--- a/src/ql/arch/factory.cc
+++ b/src/ql/arch/factory.cc
@@ -7,6 +7,7 @@
 #include "ql/arch/cc/info.h"
 #include "ql/arch/cc_light/info.h"
 #include "ql/arch/none/info.h"
+#include "ql/arch/diamond/info.h"
 
 namespace ql {
 namespace arch {
@@ -18,6 +19,7 @@ Factory::Factory() {
     register_architecture<cc::Info>();
     register_architecture<cc_light::Info>();
     register_architecture<none::Info>();
+    register_architecture<diamond::Info>();
 }
 
 /**
diff --git a/src/ql/pass/io/cqasm/detail/cqasm_reader.cc b/src/ql/pass/io/cqasm/detail/cqasm_reader.cc
index 463d5cd7d..d2db613c4 100644
--- a/src/ql/pass/io/cqasm/detail/cqasm_reader.cc
+++ b/src/ql/pass/io/cqasm/detail/cqasm_reader.cc
@@ -157,7 +157,9 @@ GateConversionRule::GateConversionRule(
     }
 
     // Default duration and angle to 0.
-    ql_duration.emplace<FixedValue<UInt>>(0);
+    if (ql_duration.empty()) {
+        ql_duration.emplace<FixedValue<UInt>>(0);
+    }
     if (ql_angle.empty()) {
         ql_angle.emplace<FixedValue<Real>>(0.0);
     }
diff --git a/src/ql/pmgr/factory.cc b/src/ql/pmgr/factory.cc
index e6a9fea27..164c16342 100644
--- a/src/ql/pmgr/factory.cc
+++ b/src/ql/pmgr/factory.cc
@@ -21,6 +21,7 @@
 //#include "ql/pass/map/qubits/place_mip/place_mip.h" // Broken: need half-decent IR for gates and virtual vs real qubit operands first.
 #include "ql/pass/map/qubits/map/map.h"
 #include "ql/arch/cc/pass/gen/vq1asm/vq1asm.h"
+#include "ql/arch/diamond/pass/gen/microcode/microcode.h"
 
 namespace ql {
 namespace pmgr {
@@ -44,6 +45,8 @@ Factory::Factory() {
     //register_pass<::ql::pass::map::qubits::place_mip::Pass>("map.qubits.PlaceMIP"); // Broken: need half-decent IR for gates and virtual vs real qubit operands first.
     register_pass<::ql::pass::map::qubits::map::Pass>("map.qubits.Map");
     register_pass<::ql::arch::cc::pass::gen::vq1asm::Pass>("arch.cc.gen.VQ1Asm");
+    register_pass<::ql::arch::diamond::pass::gen::microcode::Pass>("arch.diamond.gen.Microcode");
+
 
 }
 


Test patch:
diff --git a/examples/diamond/cqasm_test.cq b/examples/diamond/cqasm_test.cq
new file mode 100644
index 000000000..a24283d6a
--- /dev/null
+++ b/examples/diamond/cqasm_test.cq
@@ -0,0 +1,49 @@
+version 1.0
+qubits 3
+
+#prep_z q[0]
+#prep_y q[0]
+#prep_x q[0]
+
+x q[0]
+y q[0]
+z q[0]
+h q[0]
+i q[0]
+rx q[0], 3.14
+ry q[0], 3.14
+rz q[0], 3.14
+
+x90 q[0]
+mx90 q[0]
+
+y90 q[0]
+my90 q[0]
+
+s q[0]
+sdag q[0]
+
+t q[0]
+tdag q[0]
+
+cnot q[0], q[1]
+cz q[0], q[1]
+swap q[0], q[1]
+
+cr q[0], q[1], 3.14
+crk q[0], q[1], 0
+
+
+toffoli q[0], q[1], q[2]
+
+measure_z q[0]
+measure_y q[0]
+measure_x q[0]
+
+measure_all
+
+#display
+#display_binary
+
+
+
diff --git a/examples/diamond/test.py b/examples/diamond/test.py
new file mode 100644
index 000000000..655acf3b3
--- /dev/null
+++ b/examples/diamond/test.py
@@ -0,0 +1,83 @@
+import openql as ql
+
+# turn off automatic scheduling by OpenQL to preserve instruction order
+ql.set_option('prescheduler', 'no') 
+
+# Specify the platform
+platform = ql.Platform("diamond_test", "diamond")
+
+# Put a cQASM reader before the diamond pass, so a cQASM file is read instead of the python code
+#platform.get_compiler().prefix_pass('io.cqasm.Read', '', {'cqasm_file': 'cqasm_measure.cq', 'gateset_file': 'gateset.json'})
+
+nqubits = 1	
+p = ql.Program("testProgram", platform, nqubits)
+k = ql.Kernel("testKernel", platform, nqubits)
+
+
+# Below follow examples for all gates that are supported, arranged by category:
+
+# Initialization
+#k.gate('prep_z', [0])
+#k.gate('prep_x', [0])
+#k.gate('prep_y', [0])
+#k.gate('initialize', [0])
+
+# Measurement
+#k.gate('measure', [0])
+#k.gate('measure_z', [0])
+#k.gate('measure_x', [0])
+#k.gate('measure_y', [0])
+
+# single qubit gates
+#k.x(0)
+#k.y(0)
+#k.z(0)
+#k.s(0)
+#k.t(0)
+
+# two qubit gates 
+#k.gate('cnot', [0, 1]) # only between color center - nuclear spin qubit
+#k.gate('cz', [0, 1])
+
+# three qubit gate
+#k.gate('toffoli', [0, 1, 2])
+
+# calibration
+#k.gate('cal_measure', [0])
+#k.gate('cal_pi', [0])
+#k.gate('cal_halfpi', [0])
+#k.gate('decouple', [0])
+
+# custom rotations
+#k.gate('rx', [0], 0, 1.57)
+#k.gate('ry', [0], 0, 1.57)
+#k.gate('crk', [0, 1], 0, 1)
+#k.gate('cr', [0, 1], 0, 3.14)
+
+# diamond protocols/sequences
+#k.diamond_crc(0,30,5)
+#k.diamond_rabi_check(0, 100, 2, 3) # qubit, duration, measurement, t_max
+#k.diamond_excite_mw(1, 100, 200, 0, 60, 0) # envelope, duration, frequency, phase, amplitude, qubit
+#k.diamond_qentangle(0,15) # qubit, nuclear qubit
+#k.gate('nventangle', [0, 1])
+#k.diamond_memswap(0,1) # qubit, nuclear qubit
+#k.diamond_sweep_bias(0, 10, 0, 0, 10, 100, 0) #qubit, value, dacreg, start, step, max, memaddress
+
+# timing
+#k.gate('wait', [], 200)
+#k.gate('qnop', [0]) # qubit, mandatory from openQL
+
+# calculate bias
+#k.gate('calculate_current', [0])
+
+# calculate voltage
+#k.gate('calculate_voltage', [0])
+
+# magnetic bias check
+#k.diamond_sweep_bias(0, 10, 0, 0, 10, 100, 0)
+#k.gate('calculate_voltage', [0])
+
+p.add_kernel(k)
+p.compile()
+
+