diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b399ace..d054e98 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,7 +33,7 @@ jobs: name: Install SBCL, libraries, and quicklisp run: | sudo apt update && sudo apt install -y sbcl build-essential - sudo git clone --branch sbcl-2.2.4 git://git.code.sf.net/p/sbcl/sbcl /usr/src/sbcl + sudo git clone --single-branch --branch sbcl-2.2.4 git://git.code.sf.net/p/sbcl/sbcl /usr/src/sbcl cd /usr/src/sbcl && sudo sh make.sh && sudo sh make-shared-library.sh sudo apt remove -y sbcl sudo sh install.sh @@ -63,6 +63,7 @@ jobs: cd $GITHUB_WORKSPACE/libquil ls sbcl --noinform --non-interactive --eval '(ql:quickload :sbcl-librarian)' + sbcl --dynamic-space-size 8192 --noinform --non-interactive --eval '(ql:quickload :libquil)' make - name: Test @@ -139,6 +140,7 @@ jobs: cd $GITHUB_WORKSPACE/libquil ls sbcl --noinform --non-interactive --eval '(ql:quickload :sbcl-librarian)' + sbcl --dynamic-space-size 8192 --noinform --non-interactive --eval '(ql:quickload :libquil)' make - name: ls diff --git a/examples/qvm/multishot.c b/examples/qvm/multishot.c index 0baab21..da06009 100644 --- a/examples/qvm/multishot.c +++ b/examples/qvm/multishot.c @@ -43,7 +43,7 @@ void multishot_with_explicit_ro_indices() { } for (int i = 0; i < num_trials; i++) { - int vals[3]; + char vals[3]; if (qvm_multishot_result_get(qvm_res, "ro", i, &vals) != LIBQUIL_ERROR_SUCCESS) { LIBQUIL_ERROR("failed to call qvm_multishot_result_get"); @@ -89,7 +89,8 @@ void multishot_with_implicit_ro_indices() { } for (int i = 0; i < num_trials; i++) { - int *vals, len; + int len; + char *vals; if (qvm_multishot_result_get_all(qvm_res, "ro", i, &vals, &len) != LIBQUIL_ERROR_SUCCESS) { diff --git a/src/quilc/api.lisp b/src/quilc/api.lisp index 91b457a..0941969 100644 --- a/src/quilc/api.lisp +++ b/src/quilc/api.lisp @@ -97,16 +97,43 @@ (setf (cffi:mem-aref (sb-alien:alien-sap result-lens-ptr) :int i) (length gls))))))) +(defun find-program-memory-descriptor (program region-name) + (let* ((regions (cl-quil:parsed-program-memory-definitions program))) + (find region-name regions + :key #'cl-quil:memory-descriptor-name + :test #'equalp))) + +(defun quil-memory-type-to-int (memory-type) + (adt:match cl-quil:quil-type memory-type + (cl-quil:quil-bit 0) + (cl-quil:quil-octet 1) + (cl-quil:quil-integer 2) + (cl-quil:quil-real 3))) + +(defun parsed-program-get-memory-region-type (program region-name region-type-ptr) + (let ((region (find-program-memory-descriptor program region-name))) + (if (null region) + (error "region ~a not found in program" region) + (setf (cffi:mem-ref (sb-alien:alien-sap region-type-ptr) :int) + (quil-memory-type-to-int (cl-quil:memory-descriptor-type region)))))) + +(sbcl-librarian:define-enum-type program-memory-type "program_memory_type_t" + ("LIBQUIL_TYPE_BIT" 0) + ("LIBQUIL_TYPE_OCTET" 1) + ("LIBQUIL_TYPE_INTEGER" 2) + ("LIBQUIL_TYPE_REAL" 3)) + (sbcl-librarian:define-api quilc (:error-map error-map :function-prefix "quilc_") (:literal "/* Quilc types */") - (:type quil-program chip-specification quilc-version-info compilation-metadata) + (:type program-memory-type quil-program chip-specification quilc-version-info compilation-metadata) (:literal "/* Quilc functions */") (:function (("get_version_info" quilc-get-version-info) quilc-version-info ()) (("version_info_version" quilc-version-info-version) :void ((version-info quilc-version-info) (ptr :pointer))) (("version_info_githash" quilc-version-info-githash) :void ((version-info quilc-version-info) (ptr :pointer))) (("parse_quil" cl-quil.frontend:safely-parse-quil) quil-program ((source :string))) + (("program_memory_type" parsed-program-get-memory-region-type) :void ((program quil-program) (region-name :string) (region-type-ptr :pointer))) (("print_program" cl-quil.frontend:print-parsed-program) :void ((program quil-program))) (("compile_quil" cl-quil:compiler-hook) quil-program ((program quil-program) (chip-spec chip-specification))) (("compilation_metadata_len" compilation-metadata-len) :int ((metadata compilation-metadata))) diff --git a/src/qvm/api.lisp b/src/qvm/api.lisp index fe685bb..b64f1d2 100644 --- a/src/qvm/api.lisp +++ b/src/qvm/api.lisp @@ -28,22 +28,49 @@ (sbcl-librarian:define-handle-type qvm-multishot-result "qvm_multishot_result") +(defstruct qvm-multishot-result + results-map + program-memory-descriptors) + (defun qvm-multishot (compiled-quil addresses trials) "Executes COMPILED-QUIL on a pure-state QVM TRIALS numbers of times. At the end of each execution, the measurements for ADDRESSES are collected. The return value is a list of those measurements." (let* ((num-qubits (cl-quil.frontend::qubits-needed compiled-quil)) (results (%perform-multishot compiled-quil num-qubits addresses trials nil nil))) - results)) + (make-qvm-multishot-result + :results-map results + :program-memory-descriptors (cl-quil:parsed-program-memory-definitions compiled-quil)))) (defun qvm-multishot-result-get (multishot-result address-name shot-index result-pointer) - (let* ((results (elt (gethash address-name multishot-result) shot-index))) + (let* ((results-map (qvm-multishot-result-results-map multishot-result)) + (memory-descriptors (qvm-multishot-result-program-memory-descriptors multishot-result)) + (memory-descriptor (find address-name memory-descriptors + :key #'cl-quil:memory-descriptor-name + :test #'equalp)) + (results (elt (gethash address-name results-map) shot-index))) (loop :for val :in results :for i :from 0 :do - (setf (cffi:mem-aref (sb-alien:alien-sap result-pointer) :int i) val)))) + (setf (cffi:mem-aref (sb-alien:alien-sap result-pointer) + (memory-descriptor-type-to-cffi-type + (cl-quil:memory-descriptor-type memory-descriptor)) + i) + val)))) + +(defun memory-descriptor-type-to-cffi-type (descriptor-type) + (adt:match cl-quil:quil-type descriptor-type + (cl-quil:quil-bit :char) + (cl-quil:quil-octet :char) + (cl-quil:quil-integer :int) + (cl-quil:quil-real :double))) (defun qvm-multishot-result-get-all (multishot-result address-name shot-index result-ptr result-len-ptr) - (let* ((results (elt (gethash address-name multishot-result) shot-index)) + (let* ((results-map (qvm-multishot-result-results-map multishot-result)) + (results (elt (gethash address-name results-map) shot-index)) (len (length results)) - (ptr (cffi:foreign-alloc :int :initial-contents results))) + (descriptors (qvm-multishot-result-program-memory-descriptors multishot-result)) + (memory-descriptor (find address-name descriptors :key #'cl-quil:memory-descriptor-name :test #'equalp)) + (cffi-type (memory-descriptor-type-to-cffi-type + (cl-quil:memory-descriptor-type memory-descriptor))) + (ptr (cffi:foreign-alloc cffi-type :initial-contents results))) (setf (cffi:mem-ref (sb-alien:alien-sap result-ptr) :pointer) ptr) (setf (cffi:mem-ref (sb-alien:alien-sap result-len-ptr) :int) len))) @@ -135,7 +162,9 @@ (name :string))) (("multishot" qvm-multishot) qvm-multishot-result - ((program quil-program) (addresses qvm-multishot-addresses) (trials :int))) + ((program quil-program) + (addresses qvm-multishot-addresses) + (trials :int))) (("multishot_result_get" qvm-multishot-result-get) :void ((qvm-result qvm-multishot-result)