Commit 01cdc8c3 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

updating with support for pragma xacc observe


Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent 2539fcca
Pipeline #61765 passed with stages
in 10 minutes and 13 seconds
......@@ -68,7 +68,7 @@ void GateFunction::load(std::istream &inStream) {
auto provider = xacc::getService<IRProvider>("gate");
std::string json(std::istreambuf_iterator<char>(inStream), {});
// std::cout << "JSON: " << json << "\n";
// std::cout << "JSON: " << json << "\n";
Document doc;
doc.Parse(json);
......@@ -76,13 +76,26 @@ void GateFunction::load(std::istream &inStream) {
auto &kernel = doc["kernels"].GetArray()[0];
functionName = kernel["function"].GetString();
auto &options = kernel["options"];
for (auto itr = options.MemberBegin(); itr != options.MemberEnd(); ++itr) {
auto &value = options[itr->name.GetString()];
if (value.IsInt()) {
setOption(itr->name.GetString(), InstructionParameter(value.GetInt()));
} else if (value.IsDouble()) {
setOption(itr->name.GetString(), InstructionParameter(value.GetDouble()));
} else {
setOption(itr->name.GetString(), InstructionParameter(value.GetString()));
}
}
if (kernel.HasMember("bitmap")) {
auto bitMapArr = kernel["bitmap"].GetArray();
std::vector<int> bitMap;
for (int i = 0; i < bitMapArr.Size(); i++) {
bitMap.push_back(bitMapArr[i].GetInt());
}
setBitMap(bitMap);
auto bitMapArr = kernel["bitmap"].GetArray();
std::vector<int> bitMap;
for (int i = 0; i < bitMapArr.Size(); i++) {
bitMap.push_back(bitMapArr[i].GetInt());
}
setBitMap(bitMap);
}
auto instructionsArray = kernel["instructions"].GetArray();
......@@ -92,9 +105,10 @@ void GateFunction::load(std::istream &inStream) {
auto gname = inst["gate"].GetString();
bool isAnIRG = false;
if (std::find(irGeneratorNames.begin(), irGeneratorNames.end(), gname) != irGeneratorNames.end()) {
// this is an IRG
isAnIRG = true;
if (std::find(irGeneratorNames.begin(), irGeneratorNames.end(), gname) !=
irGeneratorNames.end()) {
// this is an IRG
isAnIRG = true;
}
std::vector<int> qbits;
......@@ -118,10 +132,9 @@ void GateFunction::load(std::istream &inStream) {
std::shared_ptr<Instruction> instToAdd;
if (!isAnIRG) {
instToAdd =
provider->createInstruction(gname, qbits, local_parameters);
instToAdd = provider->createInstruction(gname, qbits, local_parameters);
} else {
instToAdd = xacc::getService<IRGenerator>(gname);
instToAdd = xacc::getService<IRGenerator>(gname);
}
auto &optionsObj = inst["options"];
......@@ -150,25 +163,25 @@ void GateFunction::load(std::istream &inStream) {
void GateFunction::expandIRGenerators(
std::map<std::string, InstructionParameter> irGenMap) {
std::list<InstPtr> newinsts;
std::list<InstPtr> newinsts;
for (int idx = 0; idx < nInstructions(); idx++) {
auto inst = getInstruction(idx);
auto irg = std::dynamic_pointer_cast<IRGenerator>(inst);
if (irg) {
auto evaluated = irg->generate(irGenMap);
// replaceInstruction(idx, evaluated);
// replaceInstruction(idx, evaluated);
for (auto i : evaluated->getInstructions()) {
newinsts.push_back(i);
newinsts.push_back(i);
}
} else {
newinsts.push_back(inst);
newinsts.push_back(inst);
}
}
instructions.clear();
for (auto i : newinsts) {
addInstruction(i);
addInstruction(i);
}
}
......@@ -190,15 +203,15 @@ std::list<InstPtr> GateFunction::getInstructions() { return instructions; }
const std::string GateFunction::name() const { return functionName; }
const std::vector<int> GateFunction::bits() {
// Functions should return the unique bits that they operate on
std::set<int> bits;
for (int i = 0; i < nInstructions(); i++) {
for (auto & b : getInstruction(i)->bits()) {
bits.insert(b);
}
// Functions should return the unique bits that they operate on
std::set<int> bits;
for (int i = 0; i < nInstructions(); i++) {
for (auto &b : getInstruction(i)->bits()) {
bits.insert(b);
}
std::vector<int> output(bits.begin(), bits.end());
return output;
}
std::vector<int> output(bits.begin(), bits.end());
return output;
}
// lambda functions for determining if an InstructionParameter is a
......
......@@ -4,6 +4,12 @@ set (LIBRARY_NAME xacc-fermion)
file (GLOB_RECURSE HEADERS *.hpp generated/*.hpp)
file (GLOB SRC *.cpp generated/*.cpp)
# Set up dependencies to resources to track changes
usFunctionGetResourceSource(TARGET ${LIBRARY_NAME} OUT SRC)
# Generate bundle initialization code
usFunctionGenerateBundleInit(TARGET ${LIBRARY_NAME} OUT SRC)
add_library(${LIBRARY_NAME} SHARED ${SRC})
target_include_directories(${LIBRARY_NAME}
PUBLIC
......@@ -17,6 +23,24 @@ target_include_directories(${LIBRARY_NAME}
add_dependencies(${LIBRARY_NAME} antlr4_shared)
set(_bundle_name xacc_fermion)
set_target_properties(${LIBRARY_NAME}
PROPERTIES # This is required for every bundle
COMPILE_DEFINITIONS
US_BUNDLE_NAME=${_bundle_name}
# This is for convenience, used by other CMake
# functions
US_BUNDLE_NAME ${_bundle_name})
# Embed meta-data from a manifest.json file
usFunctionEmbedResources(TARGET
${LIBRARY_NAME}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
FILES
manifest.json)
if(APPLE)
target_link_libraries(${LIBRARY_NAME} PUBLIC xacc PRIVATE CppMicroServices ${CMAKE_SOURCE_DIR}/dist/libantlr4-runtime.dylib)
set_target_properties(${LIBRARY_NAME} PROPERTIES INSTALL_RPATH "@loader_path")
......
/*******************************************************************************
* 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 "FermionOperator.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 FermionActivator : public BundleActivator {
public:
FermionActivator() {}
/**
*/
void Start(BundleContext context) {
auto f =
std::make_shared<xacc::quantum::FermionOperator>();
context.RegisterService<xacc::Observable>(
f);
}
/**
*/
void Stop(BundleContext /*context*/) {}
};
} // namespace
CPPMICROSERVICES_EXPORT_BUNDLE_ACTIVATOR(FermionActivator)
......@@ -5,6 +5,7 @@
#include "operators.hpp"
#include <memory>
#include <unordered_map>
#include "Cloneable.hpp"
namespace xacc {
namespace quantum {
......@@ -126,7 +127,7 @@ public:
};
class FermionOperator
: public Observable,
: public Observable, public Cloneable<Observable>,
public std::enable_shared_from_this<FermionOperator>,
public tao::operators::commutative_ring<FermionOperator>,
public tao::operators::equality_comparable<FermionOperator>,
......@@ -138,6 +139,9 @@ protected:
std::unordered_map<std::string, FermionTerm> terms;
public:
std::shared_ptr<Observable> clone() override {
return std::make_shared<FermionOperator>();
}
FermionOperator();
FermionOperator(std::complex<double> c);
FermionOperator(double c);
......
{
"bundle.symbolic_name" : "xacc_fermion",
"bundle.activator" : true,
"bundle.name" : "XACC Gate Model Quantum Computing FermionObservable",
"bundle.description" : "This bundle provides utilities for gate model QC."
}
\ No newline at end of file
......@@ -4,6 +4,12 @@ set (LIBRARY_NAME xacc-pauli)
file (GLOB_RECURSE HEADERS *.hpp generated/*.hpp)
file (GLOB SRC *.cpp generated/*.cpp)
# Set up dependencies to resources to track changes
usFunctionGetResourceSource(TARGET ${LIBRARY_NAME} OUT SRC)
# Generate bundle initialization code
usFunctionGenerateBundleInit(TARGET ${LIBRARY_NAME} OUT SRC)
add_library(${LIBRARY_NAME} SHARED ${SRC})
target_include_directories(${LIBRARY_NAME}
PUBLIC
......@@ -17,6 +23,24 @@ target_include_directories(${LIBRARY_NAME}
add_dependencies(${LIBRARY_NAME} antlr4_shared)
set(_bundle_name xacc_pauli)
set_target_properties(${LIBRARY_NAME}
PROPERTIES # This is required for every bundle
COMPILE_DEFINITIONS
US_BUNDLE_NAME=${_bundle_name}
# This is for convenience, used by other CMake
# functions
US_BUNDLE_NAME ${_bundle_name})
# Embed meta-data from a manifest.json file
usFunctionEmbedResources(TARGET
${LIBRARY_NAME}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
FILES
manifest.json)
if(APPLE)
target_link_libraries(${LIBRARY_NAME} PUBLIC xacc PRIVATE CppMicroServices ${CMAKE_SOURCE_DIR}/dist/libantlr4-runtime.dylib)
set_target_properties(${LIBRARY_NAME} PROPERTIES INSTALL_RPATH "@loader_path")
......
/*******************************************************************************
* 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 "PauliOperator.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 PauliActivator : public BundleActivator {
public:
PauliActivator() {}
/**
*/
void Start(BundleContext context) {
auto pauli =
std::make_shared<xacc::quantum::PauliOperator>();
context.RegisterService<xacc::Observable>(
pauli);
}
/**
*/
void Stop(BundleContext /*context*/) {}
};
} // namespace
CPPMICROSERVICES_EXPORT_BUNDLE_ACTIVATOR(PauliActivator)
......@@ -22,6 +22,8 @@
#include "IR.hpp"
#include <iostream>
#include "Cloneable.hpp"
// Putting this here due to clang error
// not able to find operator!= from operators.hpp
namespace xacc {
......@@ -220,7 +222,7 @@ public:
};
class PauliOperator
: public xacc::Observable,
: public xacc::Observable, public xacc::Cloneable<Observable>,
public tao::operators::commutative_ring<PauliOperator>,
public tao::operators::equality_comparable<PauliOperator>,
public tao::operators::commutative_multipliable<PauliOperator, double>,
......@@ -230,6 +232,10 @@ protected:
std::unordered_map<std::string, Term> terms;
public:
std::shared_ptr<Observable> clone() override {
return std::make_shared<PauliOperator>();
}
std::unordered_map<std::string, Term>::iterator begin() {
return terms.begin();
}
......
{
"bundle.symbolic_name" : "xacc_pauli",
"bundle.activator" : true,
"bundle.name" : "XACC Gate Model Quantum Computing PauliObservable",
"bundle.description" : "This bundle provides utilities for gate model QC."
}
\ No newline at end of file
......@@ -57,7 +57,7 @@ template <class W, class B> std::string JsonVisitor<W, B>::write() {
}
writer->EndArray();
}
// All functions have instructions, start
// that array here.
writer->String("instructions");
......@@ -74,6 +74,27 @@ template <class W, class B> std::string JsonVisitor<W, B>::write() {
// End Instructions
writer->EndArray();
writer->String("options");
writer->StartObject();
for (auto& kv : f->getOptions()) {
writer->Key(kv.first);
auto p = kv.second;
switch (p.which()) {
case 0:
writer->Int(p.as<int>());
break;
case 1:
writer->Double(p.as<double>());
break;
case 2:
writer->String(p.as<std::string>());
break;
default:
writer->String(p.toString());
}
}
writer->EndObject();
// End Function
writer->EndObject();
}
......
......@@ -63,7 +63,7 @@ def main(argv=None):
'-I', '@CMAKE_INSTALL_PREFIX@/include/cppmicroservices4']
baseLibs = ['@CMAKE_INSTALL_PREFIX@/lib/libxacc.so', '@CMAKE_INSTALL_PREFIX@/lib/libCppMicroServices.so']
command = ['@CMAKE_CXX_COMPILER@', '-Wno-attributes', '-O3', '-DNDEBUG', '-rdynamic', '-std=c++11',
command = ['clang++-9', '-Wno-attributes', '-O3', '-DNDEBUG', '-rdynamic', '-std=c++11',
'.' + opts.file.replace('.', '_out.'), '-Wl,-rpath,@CMAKE_INSTALL_PREFIX@/lib']
command += includes + baseIncludes + baseLibs
......@@ -71,6 +71,7 @@ def main(argv=None):
command += ['-o', opts.output]
#print('Final command', command)
#print(' '.join(command))
try:
s = time.time()
result = subprocess.run(command, check=True)
......@@ -83,6 +84,8 @@ def main(argv=None):
if not opts.keep_tmp_src:
os.remove('.'+opts.file.replace('.','_out.'))
os.remove('.'+opts.file.replace('.','_pragma_out.'))
return 0
......
......@@ -21,6 +21,30 @@ namespace compiler {
KernelVisitor::KernelVisitor(CompilerInstance &c, Rewriter &rw)
: ci(c), rewriter(rw) {}
bool KernelVisitor::VisitCallExpr(CallExpr *expr) {
auto F = expr->getDirectCallee();
if (F != nullptr && F->hasAttr<AnnotateAttr>() &&
F->getAttr<AnnotateAttr>()->getAnnotation().str() == "__qpu__") {
auto fdeclName = expr->getDirectCallee()->getNameAsString();
if (F->getAttrs().size() > 1 &&
dyn_cast<AnnotateAttr>(F->getAttrs()[1])
->getAnnotation()
.str()
.find("observe_") != std::string::npos) {
auto obsName =
dyn_cast<AnnotateAttr>(F->getAttrs()[1])->getAnnotation().str();
obsName = xacc::split(obsName, '_')[1];
obsName = obsName.substr(1, obsName.length() - 2);
auto endl = expr->getEndLoc();
rewriter.ReplaceText(endl, 1,
","+obsName+")");
}
}
return true;
}
bool KernelVisitor::VisitFunctionDecl(FunctionDecl *F) {
if (F->hasAttr<AnnotateAttr>() &&
......@@ -49,10 +73,12 @@ bool KernelVisitor::VisitFunctionDecl(FunctionDecl *F) {
auto acceleratorName = xacc::getAccelerator()->name();
// Here we need to do Quantum Compilation
// ...
// ...
// ... get Accelerator IRTransformations
// ... run hardware independent transforms too
//
function->setOption("compiled_for", acceleratorName);
std::stringstream ss;
function->persist(ss);
auto irStr = ss.str();
......@@ -71,23 +97,40 @@ bool KernelVisitor::VisitFunctionDecl(FunctionDecl *F) {
replacement += "," + F->getParamDecl(i)->getNameAsString();
}
replacement += "};\n";
}
replacement +=
"auto acc = xacc::getAccelerator(\"" + acceleratorName + "\");\n";
if (F->getAttrs().size() > 1 &&
dyn_cast<AnnotateAttr>(F->getAttrs()[1])
->getAnnotation()
.str()
.find("observe_") != std::string::npos) {
auto obsName =
dyn_cast<AnnotateAttr>(F->getAttrs()[1])->getAnnotation().str();
obsName = xacc::split(obsName, '_')[1];
obsName = obsName.substr(1, obsName.length() - 2);
replacement +=
"xacc::observe(" + bufferName + ", params, acc, function, obs);\n";
auto endl = F->getParamDecl(F->getNumParams() - 1)->getEndLoc();
rewriter.ReplaceText(endl.getLocWithOffset(2), 1,
", std::shared_ptr<xacc::Observable> obs)");
} else {
replacement += "function = function->operator()(params);\n";
replacement += "acc->execute(" + bufferName + ",function);\n";
}
replacement += "xacc::getAccelerator(\"" + acceleratorName +
"\")->execute(" + bufferName + ",function);\n";
replacement += "}\n";
rewriter.ReplaceText(sr, replacement);
xacc::appendCompiled(function);
}
return true;
}
KernelVisitor::CppToXACCIRVisitor::CppToXACCIRVisitor(
const std::string name) {
KernelVisitor::CppToXACCIRVisitor::CppToXACCIRVisitor(const std::string name) {
provider = xacc::getService<IRProvider>("quantum");
function = provider->createFunction(name, {}, {InstructionParameter("gate")});
auto irgens = xacc::getRegisteredIds<xacc::IRGenerator>();
......@@ -101,15 +144,16 @@ bool KernelVisitor::CppToXACCIRVisitor::VisitCallExpr(CallExpr *expr) {
auto firstchild = *(expr->child_begin());
if (dyn_cast<DeclRefExpr>(firstchild)) {
gate_name = dyn_cast<DeclRefExpr>(*(expr->child_begin()))
->getNameInfo()
.getAsString();
->getNameInfo()
.getAsString();
} else if (dyn_cast<ImplicitCastExpr>(firstchild)) {
// For this case, we have a reference to a previous __qpu__ function
auto ice = dyn_cast<ImplicitCastExpr>(firstchild);
auto irFunctionName = dyn_cast<DeclRefExpr>(ice->getSubExpr())->getNameInfo().getAsString();
auto irFunction = xacc::getCompiled(irFunctionName);
function->addInstruction(irFunction);
return true;
// For this case, we have a reference to a previous __qpu__ function
auto ice = dyn_cast<ImplicitCastExpr>(firstchild);
auto irFunctionName =
dyn_cast<DeclRefExpr>(ice->getSubExpr())->getNameInfo().getAsString();
auto irFunction = xacc::getCompiled(irFunctionName);
function->addInstruction(irFunction);
return true;
}
if (std::find(irGeneratorNames.begin(), irGeneratorNames.end(), gate_name) !=
......@@ -141,7 +185,6 @@ bool KernelVisitor::CppToXACCIRVisitor::VisitCallExpr(CallExpr *expr) {
function->addInstruction(inst);
}
return true;
}
......
......@@ -118,11 +118,11 @@ public:
KernelVisitor(CompilerInstance &c, Rewriter &rw);
bool VisitFunctionDecl(FunctionDecl *F);
bool VisitCallExpr(CallExpr *expr);
private:
CompilerInstance &ci;
Rewriter &rewriter;
std::map<std::string, std::shared_ptr<Function>> functions;
};
} // namespace compiler
} // namespace xacc
......
#ifndef COMPILER_CLANG_XACCPRAGMAHANDLER_HPP__
#define COMPILER_CLANG_XACCPRAGMAHANDLER_HPP__
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/TokenKinds.def"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include <iostream>
#include <sstream>
using namespace clang;
namespace xacc {
namespace compiler {
class XACCPragmaHandler : public PragmaHandler {
protected:
// Rewriter &rewriter;
struct XACCPragmaAttributeInfo {
// enum ActionType { Push, Pop, Attribute };
// ParsedAttributes &Attributes;
// ActionType Action;
const IdentifierInfo *Namespace = nullptr;
ArrayRef<Token> Tokens;
// PragmaAttributeInfo(ParsedAttributes &Attributes) :
// Attributes(Attributes) {}
};
public:
std::string observable = "";
std::string functionName = "";
XACCPragmaHandler() :PragmaHandler("xacc") {}