Skip to content

Commit

Permalink
Implement a PayloadRegister as a factory to register and create `Pa…
Browse files Browse the repository at this point in the history
…yload`s (#68)

This PR implements a `PayloadRegistry` factory as a template
specialization of `plugin::registry::PluginRegistry<T>` (see #63). This
registry can instantiate `PayloadInfo` items which, in turn, are
responsible of instantiate concrete `Payload` implementations (same
schema as `TargetSystem`).

It also turns the `ZipPayload` into a pluggable `Payload` for this new
registry.

---------

Co-authored-by: Marius Hillenbrand <marius.hillenbrand@ibm.com>
  • Loading branch information
jgsogo and mhillenbrand committed Mar 27, 2023
1 parent cfb8f45 commit cb29d2e
Show file tree
Hide file tree
Showing 15 changed files with 568 additions and 268 deletions.
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ if(QSSC_WITH_MOCK_TARGET)
)
endif()

set(QSSC_PAYLOAD_PATHS
""
CACHE STRING
"List of directories containing QSS compiler payloads."
)


set(QSSC_RESOURCES_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/lib/qssc)
configure_file(include/Config.h.in ${QSSC_BINARY_DIR}/include/Config.h)

Expand Down
42 changes: 11 additions & 31 deletions include/Payload/Payload.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,21 @@
#include "llvm/Support/raw_ostream.h"

namespace qssc::payload {

struct PayloadConfig {
std::string prefix;
std::string name;
};

// Payload class will wrap the QSS Payload and interface with the qss-compiler
class Payload {
public:
using PluginConfiguration = PayloadConfig;

public:
Payload() : prefix(""), name("exp") {}
Payload(std::string prefix, std::string name)
: prefix(std::move(prefix) + "/"), name(std::move(name)) {
explicit Payload(PayloadConfig config)
: prefix(std::move(config.prefix) + "/"), name(std::move(config.name)) {
files.clear();
}
virtual ~Payload() = default;
Expand Down Expand Up @@ -76,35 +85,6 @@ class Payload {
std::unordered_map<std::filesystem::path, std::string, PathHash> files;
}; // class Payload

class ZipPayload : public Payload {
public:
ZipPayload() = default;
ZipPayload(std::string prefix, std::string name)
: Payload(std::move(prefix), std::move(name)) {}
virtual ~ZipPayload() = default;

// write all files to the stream
virtual void write(llvm::raw_ostream &stream) override;
// write all files to the stream
virtual void write(std::ostream &stream) override;
// write all files in plaintext to the stream
virtual void writePlain(std::ostream &stream) override;
virtual void writePlain(llvm::raw_ostream &stream) override;

// write all files to a zip archive named fName
void writeZip(std::string fName);
// write all files to a zip archive and output it to the stream
void writeZip(std::ostream &stream);
void writeZip(llvm::raw_ostream &stream);
// write all files in plaintext to the dir named dirName
void writePlain(const std::string &dirName = ".");

private:
// creates a manifest json file
void addManifest();

}; // class ZipPayload

} // namespace qssc::payload

#endif // PAYLOAD_PAYLOAD_H
35 changes: 35 additions & 0 deletions include/Payload/PayloadRegistry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===- PayloadRegistry.h - Payload Registry ---------------------*- C++ -*-===//
//
// (C) Copyright IBM 2023.
//
// This code is part of Qiskit.
//
// This code is licensed under the Apache License, Version 2.0 with LLVM
// Exceptions. You may obtain a copy of this license in the LICENSE.txt
// file in the root directory of this source tree.
//
// Any modifications or derivative works of this code must retain this
// copyright notice, and modified files need to carry a notice indicating
// that they have been altered from the originals.
//
//===----------------------------------------------------------------------===//
//
// Declaration of the QSSC payload registry system.
//
//===----------------------------------------------------------------------===//
#ifndef PAYLOADREGISTRY_H
#define PAYLOADREGISTRY_H

#include "Payload.h"

#include "Plugin/PluginInfo.h"
#include "Plugin/PluginRegistry.h"

namespace qssc::payload::registry {

using PayloadInfo = plugin::registry::PluginInfo<Payload>;
using PayloadRegistry = plugin::registry::PluginRegistry<PayloadInfo>;

} // namespace qssc::payload::registry

#endif
42 changes: 28 additions & 14 deletions lib/API/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,39 +20,31 @@
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/InitAllDialects.h"
#include "mlir/InitAllPasses.h"
#include "mlir/Parser.h"
#include "mlir/Pass/PassManager.h"
#include "mlir/Support/FileUtilities.h"
#include "mlir/Support/Timing.h"

#include "llvm/ADT/Optional.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/ToolOutputFile.h"

#include "Payload/Payload.h"
#include "Payload/PayloadRegistry.h"
#include "QSSC.h"

#include "HAL/PassRegistration.h"
#include "HAL/TargetSystem.h"
#include "HAL/TargetSystemRegistry.h"

#include "Dialect/RegisterDialects.h"

#include "Dialect/OQ3/IR/OQ3Dialect.h"

#include "Dialect/Pulse/IR/PulseDialect.h"
#include "Dialect/Pulse/Transforms/Passes.h"

#include "Dialect/QUIR/IR/QUIRDialect.h"
#include "Dialect/QUIR/Transforms/Passes.h"

#include "Dialect/QCS/IR/QCSDialect.h"
#include "Dialect/RegisterDialects.h"

#include "Frontend/OpenQASM3/OpenQASM3Frontend.h"

Expand Down Expand Up @@ -135,6 +127,11 @@ static llvm::cl::opt<bool>
llvm::cl::desc("Print the list of registered targets"),
llvm::cl::init(false), llvm::cl::cat(qsscCat));

static llvm::cl::opt<bool>
showPayloads("show-payloads",
llvm::cl::desc("Print the list of registered payloads"),
llvm::cl::init(false), llvm::cl::cat(qsscCat));

static llvm::cl::opt<bool>
plaintextPayload("plaintext-payload",
llvm::cl::desc("Write the payload in plaintext"),
Expand Down Expand Up @@ -374,6 +371,17 @@ compile_(int argc, char const **argv, std::string *outputString,
return llvm::Error::success();
}

if (showPayloads) {
llvm::outs() << "Registered Payloads:\n";
for (const auto &payload :
qssc::payload::registry::PayloadRegistry::registeredPlugins()) {
// Constants chosen empirically to align with --help.
// TODO: Select constants more intelligently.
qssc::plugin::registry::printHelpStr(payload.second, 2, 57);
}
return llvm::Error::success();
}

if (auto err = determineInputType())
return err;

Expand Down Expand Up @@ -426,12 +434,18 @@ compile_(int argc, char const **argv, std::string *outputString,

if (emitAction == Action::GenQEM) {
if (outputFilename == "-") {
payload = std::make_unique<qssc::payload::ZipPayload>();
auto payloadInfo =
qssc::payload::registry::PayloadRegistry::lookupPluginInfo("ZIP");
payload = std::move(
payloadInfo.getValue()->createPluginInstance(llvm::None).get());
} else {
std::filesystem::path payloadPath(outputFilename.c_str());
std::string fNamePrefix = payloadPath.stem();
const std::filesystem::path payloadPath(outputFilename.c_str());
const std::string fNamePrefix = payloadPath.stem();
const qssc::payload::PayloadConfig config{fNamePrefix, fNamePrefix};
auto payloadInfo =
qssc::payload::registry::PayloadRegistry::lookupPluginInfo("ZIP");
payload =
std::make_unique<qssc::payload::ZipPayload>(fNamePrefix, fNamePrefix);
std::move(payloadInfo.getValue()->createPluginInstance(config).get());
}
}
if (outputString) {
Expand Down
37 changes: 29 additions & 8 deletions lib/Payload/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,34 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

ADD_LIBRARY(QSSCPayload Payload.cpp)
include_directories(${PROJECT_SOURCE_DIR}/include)
add_subdirectory(ZipPayload)

get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
get_property(conversion_libs GLOBAL PROPERTY MLIR_CONVERSION_LIBS)
set(LIBS
libzip::zip
)
# Register payloads with build system
foreach(payload_path ${QSSC_PAYLOAD_PATHS})
message(STATUS "Adding QSS Payload directory: ${payload_path}")
add_subdirectory(${payload_path} ${CMAKE_CURRENT_BINARY_DIR}/Payloads/${payload_path})
endforeach()

target_link_libraries(QSSCPayload PRIVATE ${LIBS})
# Write Payloads.inc file for registration
get_property(reg_headers GLOBAL PROPERTY QSSC_PAYLOAD_REGISTRATION_HEADERS)
foreach(REG_HEADER ${reg_headers})
set(PAYLOAD_REGISTRATION_INCLUDE_SECTION "${PAYLOAD_REGISTRATION_INCLUDE_SECTION}#include \"${REG_HEADER}\"\n")
endforeach()

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Payloads.inc.in ${CMAKE_CURRENT_BINARY_DIR}/Payloads.inc)
unset(PAYLOAD_REGISTRATION_INCLUDE_SECTION)

# Add QSSCHAL lib
get_property(qssc_payloads GLOBAL PROPERTY QSSC_PAYLOADS)
qssc_add_library(QSSCPayload
Payload.cpp

ADDITIONAL_HEADER_DIRS
${QSSC_INCLUDE_DIR}/Payload

LINK_LIBS
${qssc_payloads}
)

# Add include directory to pick up generated Payloads.inc
target_include_directories(QSSCPayload PRIVATE ${QSSC_BINARY_DIR}/lib/Payload/)

0 comments on commit cb29d2e

Please sign in to comment.