Commit 3e99d0cb authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Fixed the QCOR kernel wrapper example for Q#



Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent 9eba3a3f
Loading
Loading
Loading
Loading
+78 −74
Original line number Diff line number Diff line
#pragma once
// Helper macros to generate QCOR kernel wrapper for
// external Q# kernel (compiled to QIR)
#include "qir-types.hpp"

#define STRINGIZE(arg) STRINGIZE1(arg)
#define STRINGIZE1(arg) STRINGIZE2(arg)
@@ -10,27 +12,13 @@
#define CONCATENATE2(arg1, arg2) arg1##arg2

#define FOR_EACH_1(what, x, ...) what(x, 1)
#define FOR_EACH_2(what, x, ...)\
  what(x, 2)\
  FOR_EACH_1(what,  __VA_ARGS__)
#define FOR_EACH_3(what, x, ...)\
  what(x, 3)\
  FOR_EACH_2(what, __VA_ARGS__)
#define FOR_EACH_4(what, x, ...)\
  what(x, 4)\
  FOR_EACH_3(what,  __VA_ARGS__)
#define FOR_EACH_5(what, x, ...)\
  what(x, 5)\
 FOR_EACH_4(what,  __VA_ARGS__)
#define FOR_EACH_6(what, x, ...)\
  what(x, 6)\
  FOR_EACH_5(what,  __VA_ARGS__)
#define FOR_EACH_7(what, x, ...)\
  what(x, 7)\
  FOR_EACH_6(what,  __VA_ARGS__)
#define FOR_EACH_8(what, x, ...)\
  what(x, 8)\
  FOR_EACH_7(what,  __VA_ARGS__)
#define FOR_EACH_2(what, x, ...) what(x, 2) FOR_EACH_1(what, __VA_ARGS__)
#define FOR_EACH_3(what, x, ...) what(x, 3) FOR_EACH_2(what, __VA_ARGS__)
#define FOR_EACH_4(what, x, ...) what(x, 4) FOR_EACH_3(what, __VA_ARGS__)
#define FOR_EACH_5(what, x, ...) what(x, 5) FOR_EACH_4(what, __VA_ARGS__)
#define FOR_EACH_6(what, x, ...) what(x, 6) FOR_EACH_5(what, __VA_ARGS__)
#define FOR_EACH_7(what, x, ...) what(x, 7) FOR_EACH_6(what, __VA_ARGS__)
#define FOR_EACH_8(what, x, ...) what(x, 8) FOR_EACH_7(what, __VA_ARGS__)

#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__)
@@ -38,22 +26,28 @@
#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0

#define FOR_EACH_(N, what, ...) CONCATENATE(FOR_EACH_, N)(what, __VA_ARGS__)
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
#define FOR_EACH(what, ...)                                                    \
  FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)

#define CONSTRUCT_ARGS_LIST_(type_name, var_name) , type_name var_name
#define CONSTRUCT_ARGS_LIST(type_name, counter) CONSTRUCT_ARGS_LIST_(type_name, __internal__var__##counter)
#define CONSTRUCT_ARGS_LIST(type_name, counter)                                \
  CONSTRUCT_ARGS_LIST_(type_name, __internal__var__##counter)
#define CONSTRUCT_VAR_NAME_LIST(type_name, counter) , __internal__var__##counter

// Macro to use to construct list of types and var names.
#define ARGS_LIST_FOR_FUNC_SIGNATURE(...) FOR_EACH(CONSTRUCT_ARGS_LIST, __VA_ARGS__)
#define ARGS_LIST_FOR_FUNC_INVOKE(...) FOR_EACH(CONSTRUCT_VAR_NAME_LIST, __VA_ARGS__)
#define ARGS_LIST_FOR_FUNC_SIGNATURE(...)                                      \
  FOR_EACH(CONSTRUCT_ARGS_LIST, __VA_ARGS__)
#define ARGS_LIST_FOR_FUNC_INVOKE(...)                                         \
  FOR_EACH(CONSTRUCT_VAR_NAME_LIST, __VA_ARGS__)

#define qcor_import_qsharp_kernel(OPERATION_NAME, ...)                         \
  extern "C" void OPERATION_NAME##__body(QReg *, __VA_ARGS__); \
  class OPERATION_NAME : public qcor::QuantumKernel<class OPERATION_NAME, qreg, __VA_ARGS__> { \
  extern "C" void OPERATION_NAME##__body(::Array *, __VA_ARGS__);              \
  class OPERATION_NAME                                                         \
      : public qcor::QuantumKernel<class OPERATION_NAME, qreg, __VA_ARGS__> {  \
  private:                                                                     \
    std::deque<Qubit> m_qubits; \
    ::Array *m_qubits = nullptr;                                               \
    friend class qcor::QuantumKernel<class OPERATION_NAME, qreg, __VA_ARGS__>; \
                                                                               \
  protected:                                                                   \
    void operator()(qreg q ARGS_LIST_FOR_FUNC_SIGNATURE(__VA_ARGS__)) {        \
      if (!parent_kernel) {                                                    \
@@ -63,19 +57,30 @@
      if (runtime_env == QrtType::FTQC) {                                      \
        quantum::set_current_buffer(q.results());                              \
      }                                                                        \
      QReg qReg; \
      /* Convert the qreg to QIR Array of Qubits */                            \
      if (!m_qubits) {                                                         \
        m_qubits = new ::Array(q.size());                                      \
        for (int i = 0; i < q.size(); ++i) {                                   \
        m_qubits.push_back(i); \
        qReg.emplace_back(&m_qubits.back()); \
          auto qubit = Qubit::allocate();                                      \
          int8_t *arrayPtr = (*m_qubits)[i];                                   \
          auto qubitPtr = reinterpret_cast<Qubit **>(arrayPtr);                \
          *qubitPtr = qubit;                                                   \
        }                                                                      \
      OPERATION_NAME##__body(&qReg ARGS_LIST_FOR_FUNC_INVOKE(__VA_ARGS__)); \
      /* std::cout << "INVOKE:\n" << parent_kernel->toString(); */\
      }                                                                        \
      OPERATION_NAME##__body(m_qubits ARGS_LIST_FOR_FUNC_INVOKE(               \
          __VA_ARGS__)); /* std::cout << "INVOKE:\n" <<                        \
                            parent_kernel->toString(); */                      \
    }                                                                          \
                                                                               \
  public:                                                                      \
    inline static const std::string kernel_name = #OPERATION_NAME;             \
    OPERATION_NAME(qreg q ARGS_LIST_FOR_FUNC_SIGNATURE(__VA_ARGS__)) : QuantumKernel<OPERATION_NAME, qreg, __VA_ARGS__>(q ARGS_LIST_FOR_FUNC_INVOKE(__VA_ARGS__)) {} \
    OPERATION_NAME(std::shared_ptr<qcor::CompositeInstruction> _parent, qreg q ARGS_LIST_FOR_FUNC_SIGNATURE(__VA_ARGS__)) \
        : QuantumKernel<OPERATION_NAME, qreg, __VA_ARGS__>(_parent, q ARGS_LIST_FOR_FUNC_INVOKE(__VA_ARGS__)) {} \
    OPERATION_NAME(qreg q ARGS_LIST_FOR_FUNC_SIGNATURE(__VA_ARGS__))           \
        : QuantumKernel<OPERATION_NAME, qreg, __VA_ARGS__>(                    \
              q ARGS_LIST_FOR_FUNC_INVOKE(__VA_ARGS__)) {}                     \
    OPERATION_NAME(std::shared_ptr<qcor::CompositeInstruction> _parent,        \
                   qreg q ARGS_LIST_FOR_FUNC_SIGNATURE(__VA_ARGS__))           \
        : QuantumKernel<OPERATION_NAME, qreg, __VA_ARGS__>(                    \
              _parent, q ARGS_LIST_FOR_FUNC_INVOKE(__VA_ARGS__)) {}            \
    virtual ~OPERATION_NAME() {                                                \
      if (disable_destructor) {                                                \
        return;                                                                \
@@ -98,4 +103,3 @@
// void MyQsharpKernel(qreg, double, int);
// which can be used in QCOR, e.g. supporting NISQ remote submit API
// and runtime pass manager, etc.
+4 −6
Original line number Diff line number Diff line
@@ -3,8 +3,6 @@
#include "qcor.hpp"
#include "import_kernel_utils.hpp"

using Qubit = uint64_t;
using QReg = std::vector<Qubit*>;
// Util pre-processor to wrap Q# operation in a QCOR QuantumKernel.
qcor_import_qsharp_kernel(QCOR__TestKernel, double);

@@ -17,13 +15,13 @@ qcor_import_qsharp_kernel(QCOR__TestKernel, double);
int main() {
  auto q = qalloc(3);
  qcor::set_verbose(true);
  // QCOR__TestKernel(q, 1.0);
  // q.print();
  QCOR__TestKernel(q, 1.0);
  q.print();

  // Integrate w/ QCOR's kernel utility...
  // e.g. kernel print-out...
  std::cout << "HELLO:\n";
  QCOR__TestKernel::print_kernel(std::cout, q, M_PI/4);
  // std::cout << "HELLO:\n";
  // QCOR__TestKernel::print_kernel(std::cout, q, M_PI/4);

  return 0;
}
 No newline at end of file
+3 −0
Original line number Diff line number Diff line
file(GLOB SRC *.cpp)
file(GLOB HEADERS qir-types.hpp qir-qrt.hpp)

add_library(qir-qrt SHARED ${SRC})

#target_include_directories(
@@ -6,6 +8,7 @@ add_library(qir-qrt SHARED ${SRC})
#  PUBLIC . ${CMAKE_SOURCE_DIR}/runtime/qrt ${XACC_ROOT}/include/cppmicroservices4 ${XACC_ROOT}/include/xacc ${XACC_ROOT}/include/qcor ${XACC_ROOT}/include/eigen ${XACC_ROOT}/include/quantum/gate)
target_link_libraries(qir-qrt PRIVATE xacc::xacc qcor qrt)
install (TARGETS qir-qrt DESTINATION lib)
install(FILES ${HEADERS} DESTINATION include/qcor)

if (QCOR_BUILD_TESTS)
  add_subdirectory(tests)