Commit c4d7f7db authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

Adding more flexible registration mechanism, removing XACCFactory. clean up throughout

parent 513e9c5a
......@@ -50,6 +50,8 @@ const std::string src("__qpu__ teleport (qbit qreg) {\n"
int main (int argc, char** argv) {
xacc::Initialize();
// Create a convenient alias for our simulator...
using CircuitSimulator = xacc::quantum::FireTensorAccelerator<6>;
......@@ -78,6 +80,8 @@ int main (int argc, char** argv) {
// Pretty print the resultant state
qubitReg->printBufferState(std::cout);
xacc::Finalize();
return 0;
}
......
......@@ -312,8 +312,10 @@ std::shared_ptr<IR> ScaffoldCompiler::compile(const std::string& src) {
} // end namespace quantum
} // end namespace xacc
//
//// Required in CPP file to be discovered by factory pattern
//REGISTER_XACCOBJECT_WITH_XACCTYPE(xacc::quantum::ScaffoldCompiler, "compiler",
// "scaffold");
// Required in CPP file to be discovered by factory pattern
REGISTER_XACCOBJECT_WITH_XACCTYPE(xacc::quantum::ScaffoldCompiler, "compiler",
"scaffold");
// Register the ScaffoldCompiler with the CompilerRegistry.
static xacc::RegisterCompiler<xacc::quantum::ScaffoldCompiler> X("scaffold");
......@@ -33,16 +33,13 @@
#include <boost/test/included/unit_test.hpp>
#include "ScaffoldCompiler.hpp"
#include "XACCFactory.hpp"
using namespace xacc::quantum;
using GraphType = QuantumCircuit;
struct F {
F() :
compiler(
xacc::XACCFactory::createAndCast<xacc::Compiler>("compiler",
"scaffold")) {
compiler(xacc::CompilerRegistry::instance()->create("scaffold")) {
BOOST_TEST_MESSAGE("setup fixture");
BOOST_VERIFY(compiler);
}
......
......@@ -33,12 +33,36 @@
#include <iostream>
#include <memory>
#include "Accelerator.hpp"
#include "spdlog/spdlog.h"
#include "Program.hpp"
namespace xacc {
/**
* This method should be called by
* clients to initialize the XACC framework.
* It should be called before using any of the
* XACC API.
*/
void Initialize() {
auto console = spdlog::stdout_logger_mt("console", true);
console->info("[xacc] Initializing XACC Framework");
auto compilerRegistry = xacc::CompilerRegistry::instance();
auto s = compilerRegistry->size();
console->info("\t[xacc::compiler] XACC has " + std::to_string(s) + " Compiler" + (s==1 ? "" : "s") + " available.");
}
/**
* This method should be called by clients to
* clean up and finalize the XACC framework. It should
* be called after using the XACC API.
*/
void Finalize() {
auto console = spdlog::get("console");
console->info("[xacc] XACC Finalizing\n\tCleaning up Compiler Registry.");
xacc::CompilerRegistry::instance()->destroy();
}
}
#endif /* XACC_XACC_HPP_ */
#endif
......@@ -32,10 +32,11 @@
#define XACC_ACCELERATOR_HPP_
#include <string>
#include "IRTransformation.hpp"
#include "XACCFactory.hpp"
#include <vector>
#include <array>
#include <bitset>
#include "IRTransformation.hpp"
#include "XACCError.hpp"
namespace xacc {
......@@ -97,7 +98,7 @@ protected:
std::string bufferId;
};
class IAccelerator : public xacc::XACCObject {
class IAccelerator {
public:
/**
* Return the type of this Accelerator.
......@@ -144,6 +145,7 @@ public:
return cp->value;
}
virtual ~IAccelerator() {}
protected:
virtual bool isValidBufferSize(const int NBits) {return true;}
......
......@@ -33,7 +33,7 @@
#include <memory>
#include <iostream>
#include "XACCFactory.hpp"
#include "Registry.hpp"
#include "IR.hpp"
#include "Accelerator.hpp"
......@@ -42,7 +42,7 @@ namespace xacc {
/**
*
*/
class Compiler: public xacc::XACCObject {
class Compiler {
public:
......@@ -74,5 +74,26 @@ protected:
std::shared_ptr<IAccelerator> accelerator;
};
/**
* Compiler Registry is just an alias for a
* Registry of Compilers.
*/
using CompilerRegistry = Registry<Compiler>;
/**
* The RegisterCompiler class simply provides
* a convenience constructor that adds the provided template
* parameter type to the CompilerRegistry.
*/
template<typename T>
class RegisterCompiler {
public:
RegisterCompiler(const std::string& name) {
CompilerRegistry::instance()->add(name,
(std::function<std::shared_ptr<xacc::Compiler>()>) ([]() {
return std::make_shared<T>();
}));
}
};
}
#endif
......@@ -31,7 +31,6 @@
#ifndef XACC_COMPILER_IR_HPP_
#define XACC_COMPILER_IR_HPP_
#include <iostream>
#include "XACCFactory.hpp"
namespace xacc {
......
......@@ -134,9 +134,7 @@ public:
auto compilerToRun = compileParameters["compiler"].as<std::string>();
// Create the appropriate compiler
compiler = std::shared_ptr<Compiler>(
xacc::XACCFactory::createAndCast<Compiler>(
"compiler", compilerToRun));
compiler = xacc::CompilerRegistry::instance()->create(compilerToRun);
// Make sure we got a valid
if (!compiler) {
......
......@@ -63,8 +63,8 @@ public:
}
};
REGISTER_XACCOBJECT_WITH_XACCTYPE(DummyCompiler, "compiler",
"dummy");
// Register the ScaffoldCompiler with the CompilerRegistry.
static xacc::RegisterCompiler<DummyCompiler> X("dummy");
BOOST_AUTO_TEST_CASE(checkBuildRuntimeArguments) {
......
......@@ -28,169 +28,79 @@
* Initial API and implementation - Alex McCaskey
*
**********************************************************************************/
#ifndef XACC_XACCFACTORY_HPP_
#define XACC_XACCFACTORY_HPP_
#ifndef XACC_UTILS_REGISTRY_HPP_
#define XACC_UTILS_REGISTRY_HPP_
#include <map>
#include <boost/core/demangle.hpp>
#include <boost/assign/list_of.hpp>
#include "Singleton.hpp"
#include "XACCError.hpp"
#include <vector>
#include <map>
namespace xacc {
/**
* Registry is a Singleton that provides a
* mapping of string ids to creation functions that
* create and return the provided Registry template
* parameter T.
*
* Clients can add new creation functions to be placed
* in the map with a unique name key, and can request
* that the Registry return a new created instance of
* the template parameter T.
*/
class XACCObject {
public:
std::string name = "";
std::string description = "";
virtual ~XACCObject() {
}
};
template<typename T>
class Registry : public Singleton<Registry<T>> {
protected:
/**
* The XACCFactory serves as a dynamically registered factory
* pattern for general XACCObjects.
/**
* Reference to the database of creation functions
* for classes of superclass type T.
*/
class XACCFactory {
std::map<std::string, std::function<std::shared_ptr<T>()>> registry;
public:
static XACCObject * create(const std::string& id) {
for (auto t = getConstructors().begin(); t != getConstructors().end();
++t) {
if (t->first.second == id) {
return (*t->second)();
}
}
return nullptr;
}
template <typename B>
static B * createAndCast (const std::string& id) {
return dynamic_cast<B*>(create(id));
}
/** Create and return a new QCIObject corresponding to
* the given string Id.
*/
static XACCObject * create(const std::string& type, const std::string& id) {
const ConstructorMap::const_iterator iter = getConstructors().find(std::make_pair(type, id));
return iter == getConstructors().end() ? 0 : (*iter->second)();
}
/**
* This is a helper function for creating a new QCIObject
* and casting it immediately to its known base class.
*/
template <typename B>
static B * createAndCast (const std::string& type, const std::string& id) {
return dynamic_cast<B*>(create(type, id));
}
/**
* Add a new creation function to the Registry, keyed
* on the provided string id.
*
* @param id
* @param f
* @return
*/
static void listTypes() {
listTypes(std::cout);
bool add(const std::string& id, std::function<std::shared_ptr<T>()> f) {
bool s = registry.insert(std::make_pair(id, f)).second;
if (!s) {
XACCError("Could not add " + id + " to the Registry.");
} else {
return s;
}
static void listTypes(std::ostream& stream) {
for (auto t = getConstructors().begin(); t != getConstructors().end();
++t) {
stream << boost::core::demangle(typeid(*(t->second)()).name())
<< " of type " << t->first.first << "\n";
}
}
template<typename B>
static std::vector<B*> getAllofType(const std::string& type) {
std::vector<B*> retTypes;
for (auto t = getConstructors().begin(); t != getConstructors().end();
++t) {
if (t->first.first == type) {
retTypes.push_back(createAndCast<B>(type, t->first.second));
}
}
return retTypes;
}
private:
enum xacc_types {
triggerFailure,
unknown,
compiler,
accelerator,
qpu,
npu
};
// Create a typedef for XACCObject constructors
typedef XACCObject * XACCObjectConstructor();
typedef std::pair<std::string, std::string> TypeIdPair;
// Create a typedef for the mapping between string ids and
// XACCObject constructors.
typedef std::map<TypeIdPair, XACCObjectConstructor*> ConstructorMap;
/**
* Return the static Constructor mapping
* Create an instance of T by using the creation
* function found at the given key string id.
* @param id
* @return
*/
static ConstructorMap& getConstructors() {
static ConstructorMap constructors;
return constructors;
std::shared_ptr<T> create(const std::string& id) {
auto search = registry.find(id);
if (search != registry.end()) {
return registry[id]();
} else {
XACCError("Invalid Registry map id string - " + id);
}
}
/**
* This class handles dynamic registration of
* new XACCObjects.
* Return the number of creation functions
* this registry contains.
* @return
*/
template<class T = int>
struct DynamicRegister {
static XACCObject* create() {
return new T();
}
static XACCObjectConstructor * initialize(const std::string& type,
const std::string& id) {
std::map<std::string, xacc_types> tmpMap =
boost::assign::map_list_of("unknown",unknown)("compiler", compiler)(
"accelerator", accelerator)("qpu", qpu)("npu", npu);
if (tmpMap[type] == triggerFailure) {
XACCError(type + " is not a valid XACC Type "
"(must be 'compiler', 'accelerator', "
"'qpu', 'npu'). Exiting.\n\n");
}
return getConstructors()[std::make_pair(type, id)] = create;
std::size_t size() {
return registry.size();
}
static XACCObjectConstructor * initialize(const std::string& id) {
return getConstructors()[std::make_pair("unknown", id)] = create;
}
static XACCObjectConstructor * creator;
};
};
#define REGISTER_XACCOBJECT_WITH_XACCTYPE(T, XACCTYPE, STR) template<> xacc::XACCFactory::XACCObjectConstructor* \
xacc::XACCFactory::DynamicRegister<T>::creator = \
xacc::XACCFactory::DynamicRegister<T>::initialize(XACCTYPE, STR)
#define REGISTER_XACCOBJECT(T, STR) template<> xacc::XACCFactory::XACCObjectConstructor* \
xacc::XACCFactory::DynamicRegister<T>::creator = \
xacc::XACCFactory::DynamicRegister<T>::initialize(STR)
}
#endif
/***********************************************************************************
* Copyright (c) 2016, UT-Battelle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* Initial API and implementation - Alex McCaskey
*
**********************************************************************************/
#ifndef XACC_UTILS_SINGLETON_HPP_
#define XACC_UTILS_SINGLETON_HPP_
#include <memory>
#include <string>
namespace xacc {
/**
* Singleton provides a templated implementation of
* the Singleton Design Pattern. This class takes a template parameter
* and provides behviour around that template that models
* a singleton - ie there is only one instance available during runtime.
*/
template<class T>
class Singleton {
public:
/**
* Return the single instance of T
* @return
*/
static T* instance() {
if (!instance_) {
instance_ = new T();
}
return instance_;
}
/**
* Destroy the single instance of T
*/
static void destroy() {
delete instance_;
instance_ = nullptr;
}
protected:
/**
* Reference to the single T instance
*/
static T* instance_;
/**
* constructor
*/
inline explicit Singleton() {
}
/**
* destructor
*/
virtual ~Singleton() {
}
};
template<class T> T* Singleton<T>::instance_ = nullptr;
}
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment