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

Update QIR-QRT



- Qubit to become a struct so that future enhancements will be easier to incorporate.

- Array opaque class to handle variable element size.

- Add tests.

Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent 1ff5572a
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -5,3 +5,7 @@ add_library(qir-qrt SHARED qir-qrt.cpp)
#  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)

if (QCOR_BUILD_TESTS)
  add_subdirectory(tests)
endif()
 No newline at end of file
+29 −25
Original line number Diff line number Diff line
@@ -140,83 +140,83 @@ void __quantum__rt__set_external_qreg(qreg* q) {
}

void __quantum__qis__cnot(Qubit* src, Qubit* tgt) {
  std::size_t src_copy = reinterpret_cast<std::size_t>(src);
  std::size_t tgt_copy = reinterpret_cast<std::size_t>(tgt);
  std::size_t src_copy = src->id;
  std::size_t tgt_copy = tgt->id;
  if (verbose) printf("[qir-qrt] Applying CX %lu, %lu\n", src_copy, tgt_copy);
  ::quantum::cnot({"q", src_copy}, {"q", tgt_copy});
}

void __quantum__qis__h(Qubit* q) {
  std::size_t qcopy = reinterpret_cast<std::size_t>(q);
  std::size_t qcopy = q->id;
  if (verbose) printf("[qir-qrt] Applying H %lu\n", qcopy);
  ::quantum::h({"q", qcopy});
}

void __quantum__qis__s(Qubit* q) {
  std::size_t qcopy = reinterpret_cast<std::size_t>(q);
  std::size_t qcopy = q->id;
  if (verbose) printf("[qir-qrt] Applying S %lu\n", qcopy);
  ::quantum::s({"q", qcopy});
}

void __quantum__qis__sdg(Qubit* q) {
  std::size_t qcopy = reinterpret_cast<std::size_t>(q);
  std::size_t qcopy = q->id;
  if (verbose) printf("[qir-qrt] Applying Sdg %lu\n", qcopy);
  ::quantum::sdg({"q", qcopy});
}
void __quantum__qis__t(Qubit* q) {
  std::size_t qcopy = reinterpret_cast<std::size_t>(q);
  std::size_t qcopy = q->id;
  if (verbose) printf("[qir-qrt] Applying T %lu\n", qcopy);
  ::quantum::t({"q", qcopy});
}
void __quantum__qis__tdg(Qubit* q) {
  std::size_t qcopy = reinterpret_cast<std::size_t>(q);
  std::size_t qcopy = q->id;
  if (verbose) printf("[qir-qrt] Applying Tdg %lu\n", qcopy);
  ::quantum::tdg({"q", qcopy});
}

void __quantum__qis__x(Qubit* q) {
  std::size_t qcopy = reinterpret_cast<std::size_t>(q);
  std::size_t qcopy = q->id;
  if (verbose) printf("[qir-qrt] Applying X %lu\n", qcopy);
  ::quantum::x({"q", qcopy});
}
void __quantum__qis__y(Qubit* q) {
  std::size_t qcopy = reinterpret_cast<std::size_t>(q);
  std::size_t qcopy = q->id;
  if (verbose) printf("[qir-qrt] Applying Y %lu\n", qcopy);
  ::quantum::y({"q", qcopy});
}
void __quantum__qis__z(Qubit* q) {
  std::size_t qcopy = reinterpret_cast<std::size_t>(q);
  std::size_t qcopy = q->id;
  if (verbose) printf("[qir-qrt] Applying Z %lu\n", qcopy);
  ::quantum::z({"q", qcopy});
}

void __quantum__qis__rx(double x, Qubit* q) {
  std::size_t qcopy = reinterpret_cast<std::size_t>(q);
  std::size_t qcopy = q->id;
  if (verbose) printf("[qir-qrt] Applying Rx(%f) %lu\n", x, qcopy);
  ::quantum::rx({"q", qcopy}, x);
}

void __quantum__qis__ry(double x, Qubit* q) {
  std::size_t qcopy = reinterpret_cast<std::size_t>(q);
  std::size_t qcopy = q->id;
  if (verbose) printf("[qir-qrt] Applying Ry(%f) %lu\n", x, qcopy);
  ::quantum::ry({"q", qcopy}, x);
}

void __quantum__qis__rz(double x, Qubit* q) {
  std::size_t qcopy = reinterpret_cast<std::size_t>(q);
  std::size_t qcopy = q->id;
  if (verbose) printf("[qir-qrt] Applying Rz(%f) %lu\n", x, qcopy);
  ::quantum::rz({"q", qcopy}, x);
}
void __quantum__qis__u3(double theta, double phi, double lambda, Qubit* q) {
    std::size_t qcopy = reinterpret_cast<std::size_t>(q);
    std::size_t qcopy = q->id;
  if (verbose) printf("[qir-qrt] Applying U3(%f, %f, %f) %lu\n", theta, phi, lambda, qcopy);
  ::quantum::u3({"q", qcopy}, theta, phi, lambda);
}

Result* __quantum__qis__mz(Qubit* q) {
  if (verbose)
    printf("[qir-qrt] Measuring qubit %lu\n", reinterpret_cast<std::size_t>(q));
  std::size_t qcopy = reinterpret_cast<std::size_t>(q);
    printf("[qir-qrt] Measuring qubit %lu\n", q->id);
  std::size_t qcopy = q->id;

  if (!qbits) {
    qbits = std::make_shared<xacc::AcceleratorBuffer>(allocated_qbits);
@@ -234,9 +234,12 @@ Array* __quantum__rt__qubit_allocate_array(uint64_t size) {

  auto new_array = std::make_unique<Array>(size);
  for (uint64_t i = 0; i < size; i++) {
    auto qubit = new uint64_t;  // Qubit("q", i);
    *qubit = i;
    (*new_array)[i] = reinterpret_cast<int8_t*>(qubit);
    auto qubit = new Qubit(i); 
    int8_t *arrayPtr = (*new_array)[i];
    // Sequence: Cast to arrayPtr to Qubit**
    auto qubitPtr = reinterpret_cast<Qubit **>(arrayPtr);
    // Then save the qubit *pointer* to the location.
    *qubitPtr = qubit;
  }

  allocated_qbits = size;
@@ -253,10 +256,9 @@ Array* __quantum__rt__qubit_allocate_array(uint64_t size) {
int8_t* __quantum__rt__array_get_element_ptr_1d(Array* q, uint64_t idx) {
  Array &arr = *q;
  int8_t *ptr = arr[idx];
  Qubit* qq = reinterpret_cast<Qubit*>(ptr);

  // Don't deref the underlying type since we don't know what it points to.
  if (verbose)
    printf("[qir-qrt] Returning qubit array element %lu, idx=%lu.\n", *qq, idx);
    printf("[qir-qrt] Returning array element at idx=%lu.\n", idx);
  return ptr;
}

@@ -269,7 +271,9 @@ void __quantum__rt__qubit_release_array(Array* q) {
        printf("[qir-qrt] deallocating the qubit array of size %lu\n",
               array_size);
      for (int k = 0; k < array_size; k++) {
        delete (*array_ptr)[k];
        int8_t *arrayPtr = (*array_ptr)[k];
        Qubit *qubitPtr = *(reinterpret_cast<Qubit **>(arrayPtr));
        delete qubitPtr;
      }
      array_ptr->clear();
    }
+1 −8
Original line number Diff line number Diff line
#include <memory>
#include <vector>
#include "qalloc.hpp"
#include "qir-types.hpp"

#pragma GCC diagnostic ignored "-Wignored-qualifiers"
#pragma GCC diagnostic ignored "-Wreorder"
@@ -12,14 +13,6 @@
#pragma GCC diagnostic ignored "-Wsign-compare"

extern "C" {

// FIXME - Qubit should be a struct that keeps track of idx
// qreg name, array it comes from, and associated accelerator buffer

using Qubit = uint64_t;
using Result = uint64_t;
using Array = std::vector<int8_t*>;
using TupleHeader = int *;
using qreg = xacc::internal_compiler::qreg;

extern Result ResultZero;
+43 −0
Original line number Diff line number Diff line
#include <cassert>

// Defines implementations of QIR Opaque types

// FIXME - Qubit should be a struct that keeps track of idx
// qreg name, array it comes from, and associated accelerator buffer
// Make this a struct now so that we can upgrade the API later
// more easily.
struct Qubit {
  uint64_t id;
  operator int() const { return id; }
  Qubit(uint64_t idVal) : id(idVal) {}
};

using Result = uint64_t;

struct Array {
  // Vector of bytes
  using Storage = std::vector<int8_t>;
  int8_t *getItemPointer(int64_t index) {
    assert(index >= 0);
    assert(static_cast<uint64_t>(index * m_itemSizeInBytes) < m_storage.size());
    return &m_storage.at(index * m_itemSizeInBytes);
  }
  int8_t *operator[](int64_t index) { return getItemPointer(index); }
  // Ctors
  // Default items are pointers.
  Array(int64_t nbItems, int itemSizeInBytes = sizeof(int8_t *))
      : m_itemSizeInBytes(itemSizeInBytes),
        // Initialized to zero
        m_storage(nbItems * itemSizeInBytes, 0) {
    assert(m_itemSizeInBytes > 0);
  };
  int64_t size() { return m_storage.size() / m_itemSizeInBytes; }
  void clear() { m_storage.clear(); }

private:
  // Must be const, i.e. changing the element size is NOT allowed.
  const int m_itemSizeInBytes;
  Storage m_storage;
};

using TupleHeader = int *;
+8 −0
Original line number Diff line number Diff line
link_directories(${XACC_ROOT}/lib)
add_executable(QirQrtTester QirQrtTester.cpp)
add_test(NAME qcor_QirQrtTester COMMAND QirQrtTester)
target_include_directories(QirQrtTester PRIVATE . .. ${CMAKE_BINARY_DIR} ${XACC_ROOT}/include/gtest)
target_link_libraries(QirQrtTester ${XACC_TEST_LIBRARIES} xacc::xacc qir-qrt)

# Test compile a QASM -> QIR lowering
add_test(NAME mlir_qrt_compile COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/bell_qasm.qasm)
 No newline at end of file
Loading