Commit 28dfd8cc authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

initial staq integration, updates to xasm


Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent efc699ee
......@@ -107,6 +107,7 @@ Circuit::operator()(const std::vector<double> &params) {
updatedInst->setParameter(i, a);
}
updatedInst->setBits(inst->bits());
updatedInst->setBufferNames(inst->getBufferNames());
}
evaluatedCircuit->addInstruction(updatedInst);
} else {
......
......@@ -262,9 +262,11 @@ public:
auto str = gateName;
str += " ";
int counter = 0;
for (auto q : bits()) {
str += (buffer_names.empty() ? "q" : getBufferName(q)) +
str += (buffer_names.empty() ? "q" : getBufferName(counter)) +
std::to_string(q) + ",";
counter++;
}
// Remove trailing comma
......
......@@ -36,11 +36,11 @@ const std::string Gate::description() const {
}
std::string Gate::getBufferName(const std::size_t bitIdx) {
if (!xacc::container::contains(bits(), bitIdx)) {
xacc::error("Invalid bit index for getBufferName: " + name() + ", " + std::to_string(bitIdx));
}
auto idx = std::distance(qbits.begin(), std::find(qbits.begin(), qbits.end(), bitIdx));
return buffer_names[idx];
// if (!xacc::container::contains(bits(), bitIdx)) {
// xacc::error("Invalid bit index for getBufferName: " + name() + ", " + std::to_string(bitIdx));
// }
// auto idx = std::distance(qbits.begin(), std::find(qbits.begin(), qbits.end(), bitIdx));
return buffer_names[bitIdx];
}
void Gate::setBufferNames(const std::vector<std::string> bufferNamesPerIdx) {
if (bufferNamesPerIdx.size() != this->nRequiredBits()) {
......@@ -69,8 +69,10 @@ const std::string Gate::toString() {
str += " ";
}
int counter = 0;
for (auto q : bits()) {
str += (buffer_names.empty() ? "q" : getBufferName(q)) + std::to_string(q) + ",";
str += (buffer_names.empty() ? "q" : buffer_names[counter]) + std::to_string(q) + ",";
counter++;
}
// Remove trailing comma
......
......@@ -17,6 +17,11 @@
#include "xacc.hpp"
using namespace xacc::quantum;
TEST(GateTester, checkBugBug) {
auto cnot = std::make_shared<CNOT>(0,1);
cnot->setBufferNames({"a","b"});
std::cout << "CNOT:\n" << cnot->toString() << "\n";
}
TEST(GateTester, checkBasicGatesAndCircuits) {
auto h = std::make_shared<Hadamard>(0);
......
......@@ -23,3 +23,4 @@ add_subdirectory(placement)
#add_subdirectory(scaffold)
add_subdirectory(xasm)
add_subdirectory(qpp)
add_subdirectory(staq)
\ No newline at end of file
# *******************************************************************************
# Copyright (c) 2020 UT-Battelle, LLC.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# and Eclipse Distribution License v.10 which accompany this distribution.
# The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
# and the Eclipse Distribution License is available at
# https://eclipse.org/org/documents/edl-v10.php
#
# Contributors:
# Alexander J. McCaskey - initial API and implementation
# *******************************************************************************/
set(LIBRARY_NAME xacc-staq-compiler)
file(GLOB SRC
compiler/*.cpp *.cpp)
usfunctiongetresourcesource(TARGET ${LIBRARY_NAME} OUT SRC)
usfunctiongeneratebundleinit(TARGET ${LIBRARY_NAME} OUT SRC)
add_library(${LIBRARY_NAME} SHARED ${SRC})
target_include_directories(${LIBRARY_NAME}
PUBLIC compiler ${STAQ_DIR}/include ${STAQ_DIR}/libs)
target_link_libraries(${LIBRARY_NAME}
PUBLIC xacc
)
target_compile_features(xacc-staq-compiler
PUBLIC
cxx_std_17)
set(_bundle_name xacc_staq_compiler)
set_target_properties(${LIBRARY_NAME}
PROPERTIES COMPILE_DEFINITIONS
US_BUNDLE_NAME=${_bundle_name}
US_BUNDLE_NAME
${_bundle_name})
usfunctionembedresources(TARGET
${LIBRARY_NAME}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
FILES
manifest.json)
if(APPLE)
set_target_properties(${LIBRARY_NAME}
PROPERTIES INSTALL_RPATH "@loader_path/../lib")
set_target_properties(${LIBRARY_NAME}
PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else()
set_target_properties(${LIBRARY_NAME}
PROPERTIES INSTALL_RPATH "$ORIGIN/../lib")
set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-shared")
endif()
if(XACC_BUILD_TESTS)
#add_subdirectory(compiler/tests)
endif()
install(TARGETS ${LIBRARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/plugins)
/*******************************************************************************
* Copyright (c) 2020 UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompanies this
* distribution. The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
*License is available at https://eclipse.org/org/documents/edl-v10.php
*
* Contributors:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#include "staq_compiler.hpp"
#include "ast/decl.hpp"
#include "xacc.hpp"
#include "xacc_service.hpp"
#include "InstructionIterator.hpp"
#include "AcceleratorBuffer.hpp"
#include "parser/parser.hpp"
#include "ast/traversal.hpp"
#include "transformations/desugar.hpp"
#include "transformations/inline.hpp"
#include "transformations/oracle_synthesizer.hpp"
#include "optimization/simplify.hpp"
using namespace staq::ast;
namespace xacc {
namespace internal_staq {
static const std::map<std::string, std::string> staq_to_xacc{
// "u3", "u2", "u1", "ccx", cu1, cu3
{"cx", "CX"}, {"id", "I"}, {"x", "X"}, {"y", "Y"},
{"z", "Z"}, {"h", "H"}, {"s", "S"}, {"sdg", "Sdg"},
{"t", "T"}, {"tdg", "Tdg"}, {"rx", "Rx"}, {"ry", "Ry"},
{"rz", "Rz"}, {"cz", "CZ"}, {"cy", "CY"}, {"swap", "Swap"},
{"ch", "CH"}, {"crz", "CRZ"}};
class CountQregs : public staq::ast::Traverse {
public:
std::vector<std::string> qregs;
void visit(staq::ast::RegisterDecl &d) override {
if (d.is_quantum()) {
qregs.push_back(d.id());
}
}
};
class CountAncillas : public staq::ast::Traverse {
public:
std::map<std::string, int> ancillas;
void visit(staq::ast::AncillaDecl &d) override {
ancillas.insert({d.id(), d.size()});
}
};
class StaqToXasm : public staq::ast::Visitor {
public:
std::stringstream ss;
void visit(VarAccess &) override {}
// Expressions
void visit(BExpr &) override {}
void visit(UExpr &) override {}
void visit(PiExpr &) override {}
void visit(IntExpr &) override {}
void visit(RealExpr &r) override {}
void visit(VarExpr &v) override {}
void visit(ResetStmt &) override {}
void visit(IfStmt &) override {}
void visit(BarrierGate &) override {}
void visit(GateDecl &) override {}
void visit(OracleDecl &) override {}
void visit(RegisterDecl &) override {}
void visit(AncillaDecl &) override {}
void visit(Program &prog) override {
// Program body
prog.foreach_stmt([this](auto &stmt) { stmt.accept(*this); });
}
void visit(MeasureStmt &m) override {
ss << "Measure(" << m.q_arg().var() << "[" << m.q_arg().offset().value()
<< "]);\n";
}
void visit(UGate &u) override {
ss << "U(" << u.arg().var() << "[" << u.arg().offset().value() << "], " << 0
<< ", " << 0 << ", " << 0 << ");\n";
}
void visit(CNOTGate &cx) override {
ss << "CX(" << cx.ctrl().var() << "[" << cx.ctrl().offset().value() << "],"
<< cx.tgt().var() << "[" << cx.tgt().offset().value() << "]);\n";
}
// void visit(BarrierGate&) = 0;
void visit(DeclaredGate &g) override {
auto xacc_name = staq_to_xacc.at(g.name());
ss << xacc_name << "(" << g.qarg(0).var() << "["
<< g.qarg(0).offset().value() << "]";
for (int i = 1; i < g.num_qargs(); i++) {
ss << ", " << g.qarg(i).var() << "[" << g.qarg(i).offset().value() << "]";
}
if (g.num_cargs() > 0) {
ss << ", " << g.carg(0).constant_eval().value();
for (int i = 1; i < g.num_cargs(); i++) {
ss << ", " << g.carg(i).constant_eval().value() << "\n";
}
}
ss << ");\n";
}
};
} // namespace internal_staq
StaqCompiler::StaqCompiler() {}
std::shared_ptr<IR> StaqCompiler::compile(const std::string &src,
std::shared_ptr<Accelerator> acc) {
// IF src contains typical xacc quantum kernel prototype, then take
// buffers names and add qreg declarations before parsing
// IF it does not, then assume qreg decls already declared.
auto xasm = xacc::getCompiler("xasm");
std::string prototype;
std::string _src = src;
bool isXaccKernel = false;
if (src.find("__qpu__") != std::string::npos) {
prototype = _src.substr(0, _src.find_first_of("{")) + "{}";
auto bufferNames = xasm->getKernelBufferNames(prototype);
isXaccKernel = true;
std::string tmp = "";
auto first = _src.find_first_of("{");
auto last = _src.find_last_of("}");
auto sub = _src.substr(first + 1, last - first - 1);
auto lines = xacc::split(sub, '\n');
for (auto &l : lines) {
xacc::trim(l);
tmp += l + "\n";
if (l.find("include") != std::string::npos) {
for (auto &b : bufferNames) {
auto size = xacc::getBuffer(b)->size();
tmp += "qreg " + b + "[" + std::to_string(size) + "];\n";
}
}
}
_src = tmp;
}
// std::cout << "SRC:\n" << _src << "\n";
using namespace staq;
auto prog = parser::parse_string(_src);
transformations::desugar(*prog);
transformations::synthesize_oracles(*prog);
optimization::simplify(*prog);
// at this point we have to find out if we have any ancilla
// registers
internal_staq::CountAncillas ancillas;
dynamic_cast<ast::Traverse &>(ancillas).visit(*prog);
// add ancilla registers to xacc
for (auto &kv : ancillas.ancillas) {
if (!xacc::hasBuffer(kv.first)) {
auto q = xacc::qalloc(kv.second);
q->setName(kv.first);
xacc::storeBuffer(q);
} else {
xacc::getBuffer(kv.first)->resetBuffer();
}
}
transformations::inline_ast(
*prog, {false, transformations::default_overrides, "anc"});
// Visit Program to find out how many qreg there are and
// use that to build up openqasm xacc function prototype
internal_staq::StaqToXasm translate;
translate.visit(*prog);
std::cout << "XASM:\n" << translate.ss.str() << "\n";
std::string kernel;
if (isXaccKernel) {
if (!ancillas.ancillas.empty()) {
kernel = prototype.substr(0, prototype.find_first_of(")"));
for (auto &kv : ancillas.ancillas) {
kernel += ", qreg " + kv.first;
}
kernel += ") {\n" + translate.ss.str() + "}";
} else {
kernel = prototype.substr(0, prototype.length() - 1) + "\n" +
translate.ss.str() + "}";
}
} else {
internal_staq::CountQregs c;
dynamic_cast<ast::Traverse &>(c).visit(*prog);
std::stringstream xx;
std::string name = "tmp";
if (xacc::hasCompiled(name)) {
int counter = 0;
while(true) {
name = "tmp"+std::to_string(counter);
if (!xacc::hasCompiled(name)) {
break;
}
counter++;
}
}
xx << "__qpu__ void "<<name<<"(";
xx << "qreg " << c.qregs[0];
for (int i = 1; i < c.qregs.size(); i++) {
xx << ", qreg " << c.qregs[i];
}
for (auto &kv : ancillas.ancillas) {
xx << ", qreg " << kv.first;
}
xx << ") {\n" << translate.ss.str() << "}";
kernel = xx.str();
}
// std::cout << "\n\nFinal:\n" << kernel << "\n";
return xasm->compile(kernel, acc);
}
std::shared_ptr<IR> StaqCompiler::compile(const std::string &src) {
return compile(src, nullptr);
}
const std::string
StaqCompiler::translate(std::shared_ptr<xacc::CompositeInstruction> function) {
return "";
}
} // namespace xacc
/*******************************************************************************
* Copyright (c) 2020 UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompanies this
* distribution. The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
*License is available at https://eclipse.org/org/documents/edl-v10.php
*
* Contributors:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#ifndef XACC_STAQCOMPILER_HPP
#define XACC_STAQCOMPILER_HPP
#include "Compiler.hpp"
namespace xacc {
class StaqCompiler : public xacc::Compiler {
public:
StaqCompiler();
std::shared_ptr<xacc::IR> compile(const std::string &src,
std::shared_ptr<Accelerator> acc) override;
std::shared_ptr<xacc::IR> compile(const std::string &src) override;
const std::string
translate(std::shared_ptr<CompositeInstruction> function) override;
const std::string name() const override { return "staq"; }
const std::string description() const override { return ""; }
virtual ~StaqCompiler() {}
};
} // namespace xacc
#endif
# *******************************************************************************
# Copyright (c) 2020 UT-Battelle, LLC.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# and Eclipse Distribution License v.10 which accompany this distribution.
# The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
# and the Eclipse Distribution License is available at
# https://eclipse.org/org/documents/edl-v10.php
#
# Contributors:
# Alexander J. McCaskey - initial API and implementation
# *******************************************************************************/
add_xacc_test(StaqCompiler)
target_link_libraries(StaqCompilerTester xacc )
\ No newline at end of file
/*******************************************************************************
* Copyright (c) 2019 UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompanies this
* distribution. The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
*License is available at https://eclipse.org/org/documents/edl-v10.php
*
* Contributors:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#include "gtest/gtest.h"
#include "xacc.hpp"
#include "xacc_service.hpp"
TEST(StaqCompilerTester, checkSimple) {
auto compiler = xacc::getCompiler("staq");
auto IR = compiler->compile(R"(OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
U(0,0,0) q[0];
CX q[0],q[1];
rx(3.3) q[0];
measure q -> c;
)");
auto hello = IR->getComposites()[0];
std::cout << "HELLO:\n" << hello->toString() << "\n";
auto q = xacc::qalloc(2);
q->setName("q");
xacc::storeBuffer(q);
IR = compiler->compile(R"(__qpu__ void f(qreg q) {
OPENQASM 2.0;
include "qelib1.inc";
creg c[2];
U(0,0,0) q[0];
CX q[0],q[1];
rx(3.3) q[0];
measure q -> c;
})");
hello = IR->getComposites()[0];
std::cout << "HELLO:\n" << hello->toString() << "\n";
}
TEST(StaqCompilerTester, checkOracle) {
auto a = xacc::qalloc(4);
a->setName("a");
xacc::storeBuffer(a);
auto b = xacc::qalloc(4);
b->setName("b");
xacc::storeBuffer(b);
auto c = xacc::qalloc(4);
c->setName("c");
xacc::storeBuffer(c);
auto src = R"(__qpu__ void add(qreg a, qreg b, qreg c) {
OPENQASM 2.0;
include "qelib1.inc";
oracle adder a0,a1,a2,a3,b0,b1,b2,b3,c0,c1,c2,c3 { "adder_4.v" }
creg result[4];
// a = 3
x a[0];
x a[1];
// b = 5
x b[0];
x b[2];
adder a[0],a[1],a[2],a[3],b[0],b[1],b[2],b[3],c[0],c[1],c[2],c[3];
// measure
measure c -> result;
})";
auto compiler = xacc::getCompiler("staq");
auto IR = compiler->compile(src);
auto hello = IR->getComposites()[0];
std::cout << hello->toString() << "\n";
auto src2 = R"(OPENQASM 2.0;
include "qelib1.inc";
oracle adder a0,a1,a2,a3,b0,b1,b2,b3,c0,c1,c2,c3 { "adder_4.v" }
qreg a[4];
qreg b[4];
qreg c[4];
creg result[4];
// a = 3
x a[0];
x a[1];
// b = 5
x b[0];
x b[2];
adder a[0],a[1],a[2],a[3],b[0],b[1],b[2],b[3],c[0],c[1],c[2],c[3];
// measure
measure c -> result;
)";
// IR = compiler->compile(src2);
// hello = IR->getComposites()[0];
// std::cout << hello->toString() << "\n";
}
int main(int argc, char **argv) {
xacc::Initialize(argc, argv);
xacc::set_verbose(true);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
{
"bundle.symbolic_name" : "xacc_staq_compiler",
"bundle.activator" : true,
"bundle.name" : "XACC Staq Compiler",
"bundle.description" : "This bundle provides a ..."
}
\ No newline at end of file
/*******************************************************************************
* Copyright (c) 2020 UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompanies this
* distribution. The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
*License is available at https://eclipse.org/org/documents/edl-v10.php
*
* Contributors:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#include "staq_compiler.hpp"
#include "cppmicroservices/BundleActivator.h"
#include "cppmicroservices/BundleContext.h"
#include "cppmicroservices/ServiceProperties.h"
#include <memory>
#include <set>
using namespace cppmicroservices;
namespace {
/**
*/
class US_ABI_LOCAL StaqActivator : public BundleActivator {
public:
StaqActivator() {}
/**
*/