[NFC][ESI Runtime] Eliminate `using namespace std`

Get rid of having std namespace implicitly and fix all the code relying
on it.
This commit is contained in:
John Demme 2024-07-03 11:48:05 +00:00
parent e0dbc6458f
commit aaaebcd46e
10 changed files with 259 additions and 258 deletions

View File

@ -27,21 +27,19 @@
// TODO: this.
#endif
using namespace std;
using namespace esi;
using namespace esi::services;
namespace esi {
AcceleratorConnection::AcceleratorConnection(Context &ctxt)
: ctxt(ctxt), serviceThread(make_unique<AcceleratorServiceThread>()) {}
: ctxt(ctxt), serviceThread(std::make_unique<AcceleratorServiceThread>()) {}
services::Service *AcceleratorConnection::getService(Service::Type svcType,
AppIDPath id,
std::string implName,
ServiceImplDetails details,
HWClientDetails clients) {
unique_ptr<Service> &cacheEntry = serviceCache[make_tuple(&svcType, id)];
std::unique_ptr<Service> &cacheEntry = serviceCache[make_tuple(&svcType, id)];
if (cacheEntry == nullptr) {
Service *svc = createService(svcType, id, implName, details, clients);
if (!svc)
@ -49,7 +47,7 @@ services::Service *AcceleratorConnection::getService(Service::Type svcType,
clients);
if (!svc)
return nullptr;
cacheEntry = unique_ptr<Service>(svc);
cacheEntry = std::unique_ptr<Service>(svc);
}
return cacheEntry.get();
}
@ -60,7 +58,7 @@ static std::filesystem::path getExePath() {
char result[PATH_MAX];
ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
if (count == -1)
throw runtime_error("Could not get executable path");
throw std::runtime_error("Could not get executable path");
return std::filesystem::path(std::string(result, count));
#elif _WIN32
// TODO: this.
@ -131,23 +129,23 @@ static void loadBackend(std::string backend) {
namespace registry {
namespace internal {
static map<string, BackendCreate> backendRegistry;
void registerBackend(string name, BackendCreate create) {
static std::map<std::string, BackendCreate> backendRegistry;
void registerBackend(std::string name, BackendCreate create) {
if (backendRegistry.count(name))
throw runtime_error("Backend already exists in registry");
throw std::runtime_error("Backend already exists in registry");
backendRegistry[name] = create;
}
} // namespace internal
unique_ptr<AcceleratorConnection> connect(Context &ctxt, string backend,
string connection) {
std::unique_ptr<AcceleratorConnection>
connect(Context &ctxt, std::string backend, std::string connection) {
auto f = internal::backendRegistry.find(backend);
if (f == internal::backendRegistry.end()) {
// If it's not already found in the registry, try to load it dynamically.
loadBackend(backend);
f = internal::backendRegistry.find(backend);
if (f == internal::backendRegistry.end())
throw runtime_error("Backend not found");
throw std::runtime_error("Backend not found");
}
return f->second(ctxt, connection);
}
@ -172,7 +170,7 @@ private:
volatile bool shutdown = false;
std::thread me;
// Protect the listeners map.
// Protect the listeners std::map.
std::mutex listenerMutex;
// Map of read ports to callbacks.
std::map<ReadChannelPort *,
@ -225,7 +223,7 @@ void AcceleratorServiceThread::Impl::addListener(
std::lock_guard<std::mutex> g(listenerMutex);
for (auto port : listenPorts) {
if (listeners.count(port))
throw runtime_error("Port already has a listener");
throw std::runtime_error("Port already has a listener");
listeners[port] = std::make_pair(callback, port->readAsync());
}
}
@ -245,9 +243,9 @@ void AcceleratorServiceThread::stop() {
}
}
// When there's data on any of the listenPorts, call the callback. This is kinda
// silly now that we have callback port support, especially given the polling
// loop. Keep the functionality for now.
// When there's data on any of the listenPorts, call the callback. This is
// kinda silly now that we have callback port support, especially given the
// polling loop. Keep the functionality for now.
void AcceleratorServiceThread::addListener(
std::initializer_list<ReadChannelPort *> listenPorts,
std::function<void(ReadChannelPort *, MessageData)> callback) {

View File

@ -17,24 +17,23 @@
#include <map>
#include <stdexcept>
using namespace std;
using namespace esi;
namespace esi {
/// Build an index of children by AppID.
static map<AppID, Instance *>
buildIndex(const vector<unique_ptr<Instance>> &insts) {
map<AppID, Instance *> index;
static std::map<AppID, Instance *>
buildIndex(const std::vector<std::unique_ptr<Instance>> &insts) {
std::map<AppID, Instance *> index;
for (auto &item : insts)
index[item->getID()] = item.get();
return index;
}
/// Build an index of ports by AppID.
static map<AppID, const BundlePort &>
buildIndex(const vector<unique_ptr<BundlePort>> &ports) {
map<AppID, const BundlePort &> index;
static std::map<AppID, const BundlePort &>
buildIndex(const std::vector<std::unique_ptr<BundlePort>> &ports) {
std::map<AppID, const BundlePort &> index;
for (auto &item : ports)
index.emplace(item->getID(), *item);
return index;

View File

@ -19,15 +19,13 @@
#include <nlohmann/json.hpp>
#include <sstream>
using namespace std;
using namespace esi;
// While building the design, keep around a map of active services indexed by
// the service name. When a new service is encountered during descent, add it to
// the table (perhaps overwriting one). Modifications to the table only apply to
// the current branch, so copy this and update it at each level of the tree.
using ServiceTable = map<string, services::Service *>;
// While building the design, keep around a std::map of active services indexed
// by the service name. When a new service is encountered during descent, add it
// to the table (perhaps overwriting one). Modifications to the table only apply
// to the current branch, so copy this and update it at each level of the tree.
using ServiceTable = std::map<std::string, services::Service *>;
// This is a proxy class to the manifest JSON. It is used to avoid having to
// include the JSON parser in the header. Forward references don't work since
@ -39,12 +37,12 @@ class Manifest::Impl {
friend class ::esi::Manifest;
public:
Impl(Context &ctxt, const string &jsonManifest);
Impl(Context &ctxt, const std::string &jsonManifest);
auto at(const string &key) const { return manifestJson.at(key); }
auto at(const std::string &key) const { return manifestJson.at(key); }
// Get the module info (if any) for the module instance in 'json'.
optional<ModuleInfo> getModInfo(const nlohmann::json &) const;
std::optional<ModuleInfo> getModInfo(const nlohmann::json &) const;
/// Go through the "service_decls" section of the manifest and populate the
/// services table as appropriate.
@ -59,29 +57,28 @@ public:
/// Get all the services in the description of an instance. Update the active
/// services table.
vector<services::Service *> getServices(AppIDPath idPath,
AcceleratorConnection &,
const nlohmann::json &,
std::vector<services::Service *>
getServices(AppIDPath idPath, AcceleratorConnection &, const nlohmann::json &,
ServiceTable &activeServices) const;
/// Get the bundle ports for the instance at 'idPath' and specified in
/// 'instJson'. Look them up in 'activeServies'.
vector<std::unique_ptr<BundlePort>>
std::vector<std::unique_ptr<BundlePort>>
getBundlePorts(AcceleratorConnection &acc, AppIDPath idPath,
const ServiceTable &activeServices,
const nlohmann::json &instJson) const;
/// Build the set of child instances (recursively) for the module instance
/// description.
vector<unique_ptr<Instance>>
std::vector<std::unique_ptr<Instance>>
getChildInstances(AppIDPath idPath, AcceleratorConnection &acc,
const ServiceTable &activeServices,
const nlohmann::json &instJson) const;
/// Get a single child instance. Implicitly copy the active services table so
/// that it can be safely updated for the child's branch of the tree.
unique_ptr<Instance> getChildInstance(AppIDPath idPath,
AcceleratorConnection &acc,
std::unique_ptr<Instance>
getChildInstance(AppIDPath idPath, AcceleratorConnection &acc,
ServiceTable activeServices,
const nlohmann::json &childJson) const;
@ -89,24 +86,27 @@ public:
void populateTypes(const nlohmann::json &typesJson);
/// Get the ordered list of types from the manifest.
const vector<const Type *> &getTypeTable() const { return _typeTable; }
const std::vector<const Type *> &getTypeTable() const { return _typeTable; }
/// Build a dynamic API for the Accelerator connection 'acc' based on the
/// manifest stored herein.
unique_ptr<Accelerator> buildAccelerator(AcceleratorConnection &acc) const;
std::unique_ptr<Accelerator>
buildAccelerator(AcceleratorConnection &acc) const;
const Type *parseType(const nlohmann::json &typeJson);
private:
Context &ctxt;
vector<const Type *> _typeTable;
std::vector<const Type *> _typeTable;
optional<const Type *> getType(Type::ID id) const { return ctxt.getType(id); }
std::optional<const Type *> getType(Type::ID id) const {
return ctxt.getType(id);
}
// The parsed json.
nlohmann::json manifestJson;
// Cache the module info for each symbol.
map<string, ModuleInfo> symbolInfoCache;
std::map<std::string, ModuleInfo> symbolInfoCache;
};
//===----------------------------------------------------------------------===//
@ -114,10 +114,10 @@ private:
//===----------------------------------------------------------------------===//
static AppID parseID(const nlohmann::json &jsonID) {
optional<uint32_t> idx;
std::optional<uint32_t> idx;
if (jsonID.contains("index"))
idx = jsonID.at("index").get<uint32_t>();
return AppID(jsonID.at("name").get<string>(), idx);
return AppID(jsonID.at("name").get<std::string>(), idx);
}
static AppIDPath parseIDPath(const nlohmann::json &jsonIDPath) {
@ -128,29 +128,29 @@ static AppIDPath parseIDPath(const nlohmann::json &jsonIDPath) {
}
static ServicePortDesc parseServicePort(const nlohmann::json &jsonPort) {
return ServicePortDesc{jsonPort.at("outer_sym").get<string>(),
jsonPort.at("inner").get<string>()};
return ServicePortDesc{jsonPort.at("outer_sym").get<std::string>(),
jsonPort.at("inner").get<std::string>()};
}
/// Convert the json value to a 'any', which can be exposed outside of this
/// Convert the json value to a 'std::any', which can be exposed outside of this
/// file.
static any getAny(const nlohmann::json &value) {
static std::any getAny(const nlohmann::json &value) {
auto getObject = [](const nlohmann::json &json) {
map<string, any> ret;
std::map<std::string, std::any> ret;
for (auto &e : json.items())
ret[e.key()] = getAny(e.value());
return ret;
};
auto getArray = [](const nlohmann::json &json) {
vector<any> ret;
std::vector<std::any> ret;
for (auto &e : json)
ret.push_back(getAny(e));
return ret;
};
if (value.is_string())
return value.get<string>();
return value.get<std::string>();
else if (value.is_number_integer())
return value.get<int64_t>();
else if (value.is_number_unsigned())
@ -160,28 +160,28 @@ static any getAny(const nlohmann::json &value) {
else if (value.is_boolean())
return value.get<bool>();
else if (value.is_null())
return value.get<nullptr_t>();
return value.get<std::nullptr_t>();
else if (value.is_object())
return getObject(value);
else if (value.is_array())
return getArray(value);
else
throw runtime_error("Unknown type in manifest: " + value.dump(2));
throw std::runtime_error("Unknown type in manifest: " + value.dump(2));
}
static ModuleInfo parseModuleInfo(const nlohmann::json &mod) {
map<string, any> extras;
std::map<std::string, std::any> extras;
for (auto &extra : mod.items())
if (extra.key() != "name" && extra.key() != "summary" &&
extra.key() != "version" && extra.key() != "repo" &&
extra.key() != "commitHash" && extra.key() != "symbolRef")
extras[extra.key()] = getAny(extra.value());
auto value = [&](const string &key) -> optional<string> {
auto value = [&](const std::string &key) -> std::optional<std::string> {
auto f = mod.find(key);
if (f == mod.end())
return nullopt;
return std::nullopt;
return f.value();
};
return ModuleInfo{value("name"), value("summary"), value("version"),
@ -192,7 +192,8 @@ static ModuleInfo parseModuleInfo(const nlohmann::json &mod) {
// Manifest::Impl class implementation.
//===----------------------------------------------------------------------===//
Manifest::Impl::Impl(Context &ctxt, const string &manifestStr) : ctxt(ctxt) {
Manifest::Impl::Impl(Context &ctxt, const std::string &manifestStr)
: ctxt(ctxt) {
manifestJson = nlohmann::ordered_json::parse(manifestStr);
for (auto &mod : manifestJson.at("symbols"))
@ -201,7 +202,7 @@ Manifest::Impl::Impl(Context &ctxt, const string &manifestStr) : ctxt(ctxt) {
populateTypes(manifestJson.at("types"));
}
unique_ptr<Accelerator>
std::unique_ptr<Accelerator>
Manifest::Impl::buildAccelerator(AcceleratorConnection &acc) const {
ServiceTable activeSvcs;
@ -211,7 +212,7 @@ Manifest::Impl::buildAccelerator(AcceleratorConnection &acc) const {
// Get the services instantiated at the top level.
auto designJson = manifestJson.at("design");
vector<services::Service *> services =
std::vector<services::Service *> services =
getServices({}, acc, designJson, activeSvcs);
// Get the ports at the top level.
@ -222,15 +223,15 @@ Manifest::Impl::buildAccelerator(AcceleratorConnection &acc) const {
getChildInstances({}, acc, activeSvcs, designJson), services, ports);
}
optional<ModuleInfo>
std::optional<ModuleInfo>
Manifest::Impl::getModInfo(const nlohmann::json &json) const {
auto instOfIter = json.find("inst_of");
if (instOfIter == json.end())
return nullopt;
return std::nullopt;
auto f = symbolInfoCache.find(instOfIter.value());
if (f != symbolInfoCache.end())
return f->second;
return nullopt;
return std::nullopt;
}
void Manifest::Impl::scanServiceDecls(AcceleratorConnection &acc,
@ -254,11 +255,11 @@ void Manifest::Impl::scanServiceDecls(AcceleratorConnection &acc,
}
}
vector<unique_ptr<Instance>>
std::vector<std::unique_ptr<Instance>>
Manifest::Impl::getChildInstances(AppIDPath idPath, AcceleratorConnection &acc,
const ServiceTable &activeServices,
const nlohmann::json &instJson) const {
vector<unique_ptr<Instance>> ret;
std::vector<std::unique_ptr<Instance>> ret;
auto childrenIter = instJson.find("children");
if (childrenIter == instJson.end())
return ret;
@ -267,14 +268,14 @@ Manifest::Impl::getChildInstances(AppIDPath idPath, AcceleratorConnection &acc,
return ret;
}
unique_ptr<Instance>
std::unique_ptr<Instance>
Manifest::Impl::getChildInstance(AppIDPath idPath, AcceleratorConnection &acc,
ServiceTable activeServices,
const nlohmann::json &child) const {
AppID childID = parseID(child.at("app_id"));
idPath.push_back(childID);
vector<services::Service *> services =
std::vector<services::Service *> services =
getServices(idPath, acc, child, activeServices);
auto children = getChildInstances(idPath, acc, activeServices, child);
@ -333,11 +334,11 @@ Manifest::Impl::getService(AppIDPath idPath, AcceleratorConnection &acc,
return svc;
}
vector<services::Service *>
std::vector<services::Service *>
Manifest::Impl::getServices(AppIDPath idPath, AcceleratorConnection &acc,
const nlohmann::json &svcsJson,
ServiceTable &activeServices) const {
vector<services::Service *> ret;
std::vector<services::Service *> ret;
auto contentsIter = svcsJson.find("contents");
if (contentsIter == svcsJson.end())
return ret;
@ -348,11 +349,11 @@ Manifest::Impl::getServices(AppIDPath idPath, AcceleratorConnection &acc,
return ret;
}
vector<std::unique_ptr<BundlePort>>
std::vector<std::unique_ptr<BundlePort>>
Manifest::Impl::getBundlePorts(AcceleratorConnection &acc, AppIDPath idPath,
const ServiceTable &activeServices,
const nlohmann::json &instJson) const {
vector<std::unique_ptr<BundlePort>> ret;
std::vector<std::unique_ptr<BundlePort>> ret;
auto contentsIter = instJson.find("contents");
if (contentsIter == instJson.end())
return ret;
@ -370,24 +371,24 @@ Manifest::Impl::getBundlePorts(AcceleratorConnection &acc, AppIDPath idPath,
// If a specific service isn't found, search for the default service
// (typically provided by a BSP).
if (svcIter = activeServices.find(""); svcIter == activeServices.end())
throw runtime_error(
throw std::runtime_error(
"Malformed manifest: could not find active service '" +
serviceName + "'");
}
services::Service *svc = svcIter->second;
string typeName = content.at("bundleType").at("circt_name");
std::string typeName = content.at("bundleType").at("circt_name");
auto type = getType(typeName);
if (!type)
throw runtime_error("Malformed manifest: could not find port type '" +
typeName + "'");
throw std::runtime_error(
"Malformed manifest: could not find port type '" + typeName + "'");
const BundleType *bundleType = dynamic_cast<const BundleType *>(*type);
if (!bundleType)
throw runtime_error("Malformed manifest: type '" + typeName +
throw std::runtime_error("Malformed manifest: type '" + typeName +
"' is not a bundle type");
idPath.push_back(parseID(content.at("appID")));
map<string, ChannelPort &> portChannels =
std::map<std::string, ChannelPort &> portChannels =
acc.requestChannelsFor(idPath, bundleType);
services::ServicePort *svcPort =
@ -409,17 +410,18 @@ const Type *parseType(const nlohmann::json &typeJson, Context &ctxt);
BundleType *parseBundleType(const nlohmann::json &typeJson, Context &cache) {
assert(typeJson.at("mnemonic") == "bundle");
vector<tuple<string, BundleType::Direction, const Type *>> channels;
std::vector<std::tuple<std::string, BundleType::Direction, const Type *>>
channels;
for (auto &chanJson : typeJson["channels"]) {
string dirStr = chanJson.at("direction");
std::string dirStr = chanJson.at("direction");
BundleType::Direction dir;
if (dirStr == "to")
dir = BundleType::Direction::To;
else if (dirStr == "from")
dir = BundleType::Direction::From;
else
throw runtime_error("Malformed manifest: unknown direction '" + dirStr +
"'");
throw std::runtime_error("Malformed manifest: unknown direction '" +
dirStr + "'");
channels.emplace_back(chanJson.at("name"), dir,
parseType(chanJson["type"], cache));
}
@ -448,12 +450,12 @@ Type *parseInt(const nlohmann::json &typeJson, Context &cache) {
else if (sign == "signless" && width > 0)
return new BitsType(id, width);
else
throw runtime_error("Malformed manifest: unknown sign '" + sign + "'");
throw std::runtime_error("Malformed manifest: unknown sign '" + sign + "'");
}
StructType *parseStruct(const nlohmann::json &typeJson, Context &cache) {
assert(typeJson.at("mnemonic") == "struct");
vector<pair<string, const Type *>> fields;
std::vector<std::pair<std::string, const Type *>> fields;
for (auto &fieldJson : typeJson["fields"])
fields.emplace_back(fieldJson.at("name"),
parseType(fieldJson["type"], cache));
@ -471,7 +473,7 @@ using TypeParser = std::function<Type *(const nlohmann::json &, Context &)>;
const std::map<std::string_view, TypeParser> typeParsers = {
{"bundle", parseBundleType},
{"channel", parseChannelType},
{"any",
{"std::any",
[](const nlohmann::json &typeJson, Context &cache) {
return new AnyType(typeJson.at("circt_name"));
}},
@ -484,11 +486,11 @@ const std::map<std::string_view, TypeParser> typeParsers = {
// Parse a type if it doesn't already exist in the cache.
const Type *parseType(const nlohmann::json &typeJson, Context &cache) {
// We use the circt type string as a unique ID.
string circt_name = typeJson.at("circt_name");
if (optional<const Type *> t = cache.getType(circt_name))
std::string circt_name = typeJson.at("circt_name");
if (std::optional<const Type *> t = cache.getType(circt_name))
return *t;
string mnemonic = typeJson.at("mnemonic");
std::string mnemonic = typeJson.at("mnemonic");
Type *t;
auto f = typeParsers.find(mnemonic);
if (f != typeParsers.end())
@ -516,7 +518,7 @@ void Manifest::Impl::populateTypes(const nlohmann::json &typesJson) {
// Manifest class implementation.
//===----------------------------------------------------------------------===//
Manifest::Manifest(Context &ctxt, const string &jsonManifest)
Manifest::Manifest(Context &ctxt, const std::string &jsonManifest)
: impl(new Impl(ctxt, jsonManifest)) {}
Manifest::~Manifest() { delete impl; }
@ -525,19 +527,19 @@ uint32_t Manifest::getApiVersion() const {
return impl->at("api_version").get<uint32_t>();
}
vector<ModuleInfo> Manifest::getModuleInfos() const {
vector<ModuleInfo> ret;
std::vector<ModuleInfo> Manifest::getModuleInfos() const {
std::vector<ModuleInfo> ret;
for (auto &mod : impl->at("symbols"))
ret.push_back(parseModuleInfo(mod));
return ret;
}
unique_ptr<Accelerator>
std::unique_ptr<Accelerator>
Manifest::buildAccelerator(AcceleratorConnection &acc) const {
return impl->buildAccelerator(acc);
}
const vector<const Type *> &Manifest::getTypeTable() const {
const std::vector<const Type *> &Manifest::getTypeTable() const {
return impl->getTypeTable();
}
@ -546,20 +548,20 @@ const vector<const Type *> &Manifest::getTypeTable() const {
//===----------------------------------------------------------------------===//
// Print a module info, including the extra metadata.
ostream &operator<<(ostream &os, const ModuleInfo &m) {
auto printAny = [&os](any a) {
const type_info &t = a.type();
if (t == typeid(string))
os << any_cast<string>(a);
std::ostream &operator<<(std::ostream &os, const ModuleInfo &m) {
auto printAny = [&os](std::any a) {
const std::type_info &t = a.type();
if (t == typeid(std::string))
os << std::any_cast<std::string>(a);
else if (t == typeid(int64_t))
os << any_cast<int64_t>(a);
os << std::any_cast<int64_t>(a);
else if (t == typeid(uint64_t))
os << any_cast<uint64_t>(a);
os << std::any_cast<uint64_t>(a);
else if (t == typeid(double))
os << any_cast<double>(a);
os << std::any_cast<double>(a);
else if (t == typeid(bool))
os << any_cast<bool>(a);
else if (t == typeid(nullptr_t))
os << std::any_cast<bool>(a);
else if (t == typeid(std::nullptr_t))
os << "null";
else
os << "unknown";
@ -599,8 +601,8 @@ AppIDPath AppIDPath::operator+(const AppIDPath &b) {
return ret;
}
string AppIDPath::toStr() const {
ostringstream os;
std::string AppIDPath::toStr() const {
std::ostringstream os;
os << *this;
return os.str();
}
@ -620,13 +622,13 @@ bool operator<(const AppIDPath &a, const AppIDPath &b) {
}
} // namespace esi
ostream &operator<<(ostream &os, const AppID &id) {
std::ostream &operator<<(std::ostream &os, const AppID &id) {
os << id.name;
if (id.idx)
os << "[" << *id.idx << "]";
return os;
}
ostream &operator<<(ostream &os, const AppIDPath &path) {
std::ostream &operator<<(std::ostream &os, const AppIDPath &path) {
for (size_t i = 0, e = path.size(); i < e; ++i) {
if (i > 0)
os << '.';

View File

@ -17,29 +17,28 @@
#include <chrono>
#include <stdexcept>
using namespace std;
using namespace esi;
BundlePort::BundlePort(AppID id, map<string, ChannelPort &> channels)
BundlePort::BundlePort(AppID id, std::map<std::string, ChannelPort &> channels)
: id(id), channels(channels) {}
WriteChannelPort &BundlePort::getRawWrite(const string &name) const {
WriteChannelPort &BundlePort::getRawWrite(const std::string &name) const {
auto f = channels.find(name);
if (f == channels.end())
throw runtime_error("Channel '" + name + "' not found");
throw std::runtime_error("Channel '" + name + "' not found");
auto *write = dynamic_cast<WriteChannelPort *>(&f->second);
if (!write)
throw runtime_error("Channel '" + name + "' is not a write channel");
throw std::runtime_error("Channel '" + name + "' is not a write channel");
return *write;
}
ReadChannelPort &BundlePort::getRawRead(const string &name) const {
ReadChannelPort &BundlePort::getRawRead(const std::string &name) const {
auto f = channels.find(name);
if (f == channels.end())
throw runtime_error("Channel '" + name + "' not found");
throw std::runtime_error("Channel '" + name + "' not found");
auto *read = dynamic_cast<ReadChannelPort *>(&f->second);
if (!read)
throw runtime_error("Channel '" + name + "' is not a read channel");
throw std::runtime_error("Channel '" + name + "' is not a read channel");
return *read;
}
void ReadChannelPort::connect(std::function<bool(MessageData)> callback) {

View File

@ -21,49 +21,48 @@
#include <cassert>
#include <stdexcept>
using namespace std;
using namespace esi;
using namespace esi::services;
string SysInfo::getServiceSymbol() const { return "__builtin_SysInfo"; }
std::string SysInfo::getServiceSymbol() const { return "__builtin_SysInfo"; }
// Allocate 10MB for the uncompressed manifest. This should be plenty.
constexpr uint32_t MAX_MANIFEST_SIZE = 10 << 20;
/// Get the compressed manifest, uncompress, and return it.
string SysInfo::getJsonManifest() const {
vector<uint8_t> compressed = getCompressedManifest();
vector<Bytef> dst(MAX_MANIFEST_SIZE);
std::string SysInfo::getJsonManifest() const {
std::vector<uint8_t> compressed = getCompressedManifest();
std::vector<Bytef> dst(MAX_MANIFEST_SIZE);
uLongf dstSize = MAX_MANIFEST_SIZE;
int rc =
uncompress(dst.data(), &dstSize, compressed.data(), compressed.size());
if (rc != Z_OK)
throw runtime_error("zlib uncompress failed with rc=" + to_string(rc));
return string(reinterpret_cast<char *>(dst.data()), dstSize);
throw std::runtime_error("zlib uncompress failed with rc=" +
std::to_string(rc));
return std::string(reinterpret_cast<char *>(dst.data()), dstSize);
}
string MMIO::getServiceSymbol() const { return "__builtin_MMIO"; }
std::string MMIO::getServiceSymbol() const { return "__builtin_MMIO"; }
MMIOSysInfo::MMIOSysInfo(const MMIO *mmio) : mmio(mmio) {}
uint32_t MMIOSysInfo::getEsiVersion() const {
uint32_t reg;
if ((reg = mmio->read(MetadataOffset)) != MagicNumberLo)
throw runtime_error("Invalid magic number low bits: " + toHex(reg));
throw std::runtime_error("Invalid magic number low bits: " + toHex(reg));
if ((reg = mmio->read(MetadataOffset + 4)) != MagicNumberHi)
throw runtime_error("Invalid magic number high bits: " + toHex(reg));
throw std::runtime_error("Invalid magic number high bits: " + toHex(reg));
return mmio->read(MetadataOffset + 8);
}
vector<uint8_t> MMIOSysInfo::getCompressedManifest() const {
std::vector<uint8_t> MMIOSysInfo::getCompressedManifest() const {
uint32_t manifestPtr = mmio->read(MetadataOffset + 12);
uint32_t size = mmio->read(manifestPtr);
uint32_t numWords = (size + 3) / 4;
vector<uint32_t> manifestWords(numWords);
std::vector<uint32_t> manifestWords(numWords);
for (size_t i = 0; i < numWords; ++i)
manifestWords[i] = mmio->read(manifestPtr + 4 + (i * 4));
vector<uint8_t> manifest;
std::vector<uint8_t> manifest;
for (size_t i = 0; i < size; ++i) {
uint32_t word = manifestWords[i / 4];
manifest.push_back(word >> (8 * (i % 4)));
@ -76,7 +75,7 @@ CustomService::CustomService(AppIDPath idPath,
const HWClientDetails &clients)
: id(idPath) {
if (auto f = details.find("service"); f != details.end()) {
serviceSymbol = any_cast<string>(f->second);
serviceSymbol = std::any_cast<std::string>(f->second);
// Strip off initial '@'.
serviceSymbol = serviceSymbol.substr(1);
}
@ -87,7 +86,7 @@ FuncService::FuncService(AcceleratorConnection *acc, AppIDPath idPath,
ServiceImplDetails details, HWClientDetails clients) {
if (auto f = details.find("service"); f != details.end())
// Strip off initial '@'.
symbol = any_cast<string>(f->second).substr(1);
symbol = std::any_cast<std::string>(f->second).substr(1);
}
std::string FuncService::getServiceSymbol() const { return symbol; }
@ -124,7 +123,7 @@ CallService::CallService(AcceleratorConnection *acc, AppIDPath idPath,
HWClientDetails clients) {
if (auto f = details.find("service"); f != details.end())
// Strip off initial '@'.
symbol = any_cast<string>(f->second).substr(1);
symbol = std::any_cast<std::string>(f->second).substr(1);
}
std::string CallService::getServiceSymbol() const { return symbol; }
@ -144,7 +143,7 @@ CallService::Callback::Callback(
result(dynamic_cast<WriteChannelPort &>(channels.at("result"))),
acc(acc) {
if (channels.size() != 2)
throw runtime_error("CallService must have exactly two channels");
throw std::runtime_error("CallService must have exactly two channels");
}
void CallService::Callback::connect(

View File

@ -96,8 +96,8 @@ CosimAccelerator::connect(Context &ctxt, std::string connectionString) {
else
throw std::runtime_error("ESI_COSIM_PORT environment variable not set");
} else {
throw std::runtime_error("Invalid connection string '" + connectionString +
"'");
throw std::runtime_error("Invalid connection std::string '" +
connectionString + "'");
}
uint16_t port = stoul(portStr);
return make_unique<CosimAccelerator>(ctxt, host, port);
@ -381,7 +381,7 @@ Service *CosimAccelerator::createService(Service::Type svcType,
for (auto client : clients) {
AppIDPath fullClientPath = prefix + client.relPath;
std::map<std::string, std::string> channelAssignments;
for (auto assignment : any_cast<std::map<std::string, std::any>>(
for (auto assignment : std::any_cast<std::map<std::string, std::any>>(
client.implOptions.at("channel_assignments")))
channelAssignments[assignment.first] =
std::any_cast<std::string>(assignment.second);

View File

@ -24,8 +24,6 @@
#include <regex>
#include <sstream>
using namespace std;
using namespace esi;
using namespace esi::services;
using namespace esi::backends::trace;
@ -38,18 +36,19 @@ class TraceChannelPort;
}
struct esi::backends::trace::TraceAccelerator::Impl {
Impl(Mode mode, filesystem::path manifestJson, filesystem::path traceFile)
Impl(Mode mode, std::filesystem::path manifestJson,
std::filesystem::path traceFile)
: manifestJson(manifestJson), traceFile(traceFile) {
if (!filesystem::exists(manifestJson))
throw runtime_error("manifest file '" + manifestJson.string() +
if (!std::filesystem::exists(manifestJson))
throw std::runtime_error("manifest file '" + manifestJson.string() +
"' does not exist");
if (mode == Write) {
// Open the trace file for writing.
traceWrite = new ofstream(traceFile);
traceWrite = new std::ofstream(traceFile);
if (!traceWrite->is_open())
throw runtime_error("failed to open trace file '" + traceFile.string() +
"'");
throw std::runtime_error("failed to open trace file '" +
traceFile.string() + "'");
} else {
assert(false && "not implemented");
}
@ -74,41 +73,43 @@ struct esi::backends::trace::TraceAccelerator::Impl {
void adoptChannelPort(ChannelPort *port) { channels.emplace_back(port); }
void write(const AppIDPath &id, const string &portName, const void *data,
void write(const AppIDPath &id, const std::string &portName, const void *data,
size_t size);
private:
ofstream *traceWrite;
filesystem::path manifestJson;
filesystem::path traceFile;
vector<unique_ptr<ChannelPort>> channels;
std::ofstream *traceWrite;
std::filesystem::path manifestJson;
std::filesystem::path traceFile;
std::vector<std::unique_ptr<ChannelPort>> channels;
};
void TraceAccelerator::Impl::write(const AppIDPath &id, const string &portName,
void TraceAccelerator::Impl::write(const AppIDPath &id,
const std::string &portName,
const void *data, size_t size) {
string b64data;
std::string b64data;
utils::encodeBase64(data, size, b64data);
*traceWrite << "write " << id << '.' << portName << ": " << b64data << endl;
*traceWrite << "write " << id << '.' << portName << ": " << b64data
<< std::endl;
}
unique_ptr<AcceleratorConnection>
TraceAccelerator::connect(Context &ctxt, string connectionString) {
string modeStr;
string manifestPath;
string traceFile = "trace.log";
std::unique_ptr<AcceleratorConnection>
TraceAccelerator::connect(Context &ctxt, std::string connectionString) {
std::string modeStr;
std::string manifestPath;
std::string traceFile = "trace.log";
// Parse the connection string.
// Parse the connection std::string.
// <mode>:<manifest path>[:<traceFile>]
regex connPattern("(\\w):([^:]+)(:(\\w+))?");
smatch match;
std::regex connPattern("(\\w):([^:]+)(:(\\w+))?");
std::smatch match;
if (regex_search(connectionString, match, connPattern)) {
modeStr = match[1];
manifestPath = match[2];
if (match[3].matched)
traceFile = match[3];
} else {
throw runtime_error("connection string must be of the form "
throw std::runtime_error("connection std::string must be of the form "
"'<mode>:<manifest path>[:<traceFile>]'");
}
@ -117,17 +118,18 @@ TraceAccelerator::connect(Context &ctxt, string connectionString) {
if (modeStr == "w")
mode = Write;
else
throw runtime_error("unknown mode '" + modeStr + "'");
throw std::runtime_error("unknown mode '" + modeStr + "'");
return make_unique<TraceAccelerator>(
ctxt, mode, filesystem::path(manifestPath), filesystem::path(traceFile));
return std::make_unique<TraceAccelerator>(ctxt, mode,
std::filesystem::path(manifestPath),
std::filesystem::path(traceFile));
}
TraceAccelerator::TraceAccelerator(Context &ctxt, Mode mode,
filesystem::path manifestJson,
filesystem::path traceFile)
std::filesystem::path manifestJson,
std::filesystem::path traceFile)
: AcceleratorConnection(ctxt) {
impl = make_unique<Impl>(mode, manifestJson, traceFile);
impl = std::make_unique<Impl>(mode, manifestJson, traceFile);
}
Service *TraceAccelerator::createService(Service::Type svcType,
@ -139,28 +141,30 @@ Service *TraceAccelerator::createService(Service::Type svcType,
namespace {
class TraceSysInfo : public SysInfo {
public:
TraceSysInfo(filesystem::path manifestJson) : manifestJson(manifestJson) {}
TraceSysInfo(std::filesystem::path manifestJson)
: manifestJson(manifestJson) {}
uint32_t getEsiVersion() const override { return ESIVersion; }
string getJsonManifest() const override {
std::string getJsonManifest() const override {
// Read in the whole json file and return it.
ifstream manifest(manifestJson);
std::ifstream manifest(manifestJson);
if (!manifest.is_open())
throw runtime_error("failed to open manifest file '" +
throw std::runtime_error("failed to open manifest file '" +
manifestJson.string() + "'");
stringstream buffer;
std::stringstream buffer;
buffer << manifest.rdbuf();
manifest.close();
return buffer.str();
}
vector<uint8_t> getCompressedManifest() const override {
throw runtime_error("compressed manifest not supported by trace backend");
std::vector<uint8_t> getCompressedManifest() const override {
throw std::runtime_error(
"compressed manifest not supported by trace backend");
}
private:
filesystem::path manifestJson;
std::filesystem::path manifestJson;
};
} // namespace
@ -168,7 +172,7 @@ namespace {
class WriteTraceChannelPort : public WriteChannelPort {
public:
WriteTraceChannelPort(TraceAccelerator::Impl &impl, const Type *type,
const AppIDPath &id, const string &portName)
const AppIDPath &id, const std::string &portName)
: WriteChannelPort(type), impl(impl), id(id), portName(portName) {}
virtual void write(const MessageData &data) override {
@ -178,7 +182,7 @@ public:
protected:
TraceAccelerator::Impl &impl;
AppIDPath id;
string portName;
std::string portName;
};
} // namespace
@ -209,7 +213,8 @@ private:
std::ptrdiff_t numBits = getType()->getBitWidth();
if (numBits < 0)
// TODO: support other types.
throw runtime_error("unsupported type for read: " + getType()->getID());
throw std::runtime_error("unsupported type for read: " +
getType()->getID());
std::ptrdiff_t size = (numBits + 7) / 8;
std::vector<uint8_t> bytes(size);
@ -244,10 +249,10 @@ public:
};
} // namespace
map<string, ChannelPort &>
std::map<std::string, ChannelPort &>
TraceAccelerator::Impl::requestChannelsFor(AppIDPath idPath,
const BundleType *bundleType) {
map<string, ChannelPort &> channels;
std::map<std::string, ChannelPort &> channels;
for (auto [name, dir, type] : bundleType->getChannels()) {
ChannelPort *port;
if (BundlePort::isWrite(dir))
@ -260,7 +265,7 @@ TraceAccelerator::Impl::requestChannelsFor(AppIDPath idPath,
return channels;
}
map<string, ChannelPort &>
std::map<std::string, ChannelPort &>
TraceAccelerator::requestChannelsFor(AppIDPath idPath,
const BundleType *bundleType) {
return impl->requestChannelsFor(idPath, bundleType);

View File

@ -26,23 +26,21 @@
#include <iostream>
#include <set>
using namespace std;
using namespace esi;
using namespace esi::services;
using namespace esi::backends::xrt;
/// Parse the connection string and instantiate the accelerator. Connection
/// string format:
/// Parse the connection std::string and instantiate the accelerator. Connection
/// std::string format:
/// <xclbin>[:<device_id>]
/// wherein <device_id> is in BDF format.
unique_ptr<AcceleratorConnection>
XrtAccelerator::connect(Context &ctxt, string connectionString) {
string xclbin;
string device_id;
std::unique_ptr<AcceleratorConnection>
XrtAccelerator::connect(Context &ctxt, std::string connectionString) {
std::string xclbin;
std::string device_id;
size_t colon = connectionString.find(':');
if (colon == string::npos) {
if (colon == std::string::npos) {
xclbin = connectionString;
} else {
xclbin = connectionString.substr(0, colon);
@ -55,7 +53,7 @@ XrtAccelerator::connect(Context &ctxt, string connectionString) {
struct esi::backends::xrt::XrtAccelerator::Impl {
constexpr static char kernel[] = "esi_kernel";
Impl(string xclbin, string device_id) {
Impl(std::string xclbin, std::string device_id) {
if (device_id.empty())
device = ::xrt::device(0);
else
@ -67,7 +65,7 @@ struct esi::backends::xrt::XrtAccelerator::Impl {
std::map<std::string, ChannelPort &> requestChannelsFor(AppIDPath,
const BundleType *) {
throw runtime_error("XRT does not support channel communication yet");
throw std::runtime_error("XRT does not support channel communication yet");
}
::xrt::device device;
@ -75,7 +73,8 @@ struct esi::backends::xrt::XrtAccelerator::Impl {
};
/// Construct and connect to a cosim server.
XrtAccelerator::XrtAccelerator(Context &ctxt, string xclbin, string device_id)
XrtAccelerator::XrtAccelerator(Context &ctxt, std::string xclbin,
std::string device_id)
: AcceleratorConnection(ctxt) {
impl = make_unique<Impl>(xclbin, device_id);
}
@ -95,7 +94,7 @@ private:
};
} // namespace
map<string, ChannelPort &>
std::map<std::string, ChannelPort &>
XrtAccelerator::requestChannelsFor(AppIDPath idPath,
const BundleType *bundleType) {
return impl->requestChannelsFor(idPath, bundleType);

View File

@ -21,18 +21,16 @@
#include <map>
#include <stdexcept>
using namespace std;
using namespace esi;
void printInfo(ostream &os, AcceleratorConnection &acc);
void printHier(ostream &os, AcceleratorConnection &acc);
void printInfo(std::ostream &os, AcceleratorConnection &acc);
void printHier(std::ostream &os, AcceleratorConnection &acc);
int main(int argc, const char *argv[]) {
// TODO: find a command line parser library rather than doing this by hand.
if (argc < 3) {
cerr << "Expected usage: " << argv[0]
<< " <backend> <connection specifier> [command]" << endl;
std::cerr << "Expected usage: " << argv[0]
<< " <backend> <connection specifier> [command]" << std::endl;
return -1;
}
@ -40,89 +38,93 @@ int main(int argc, const char *argv[]) {
const char *backend = argv[1];
const char *conn = argv[2];
string cmd;
std::string cmd;
if (argc > 3)
cmd = argv[3];
try {
unique_ptr<AcceleratorConnection> acc = ctxt.connect(backend, conn);
std::unique_ptr<AcceleratorConnection> acc = ctxt.connect(backend, conn);
const auto &info = *acc->getService<services::SysInfo>();
if (cmd == "version")
cout << "ESI system version: " << info.getEsiVersion() << endl;
std::cout << "ESI system version: " << info.getEsiVersion() << std::endl;
else if (cmd == "json_manifest")
cout << info.getJsonManifest() << endl;
std::cout << info.getJsonManifest() << std::endl;
else if (cmd == "info")
printInfo(cout, *acc);
printInfo(std::cout, *acc);
else if (cmd == "hier")
printHier(cout, *acc);
printHier(std::cout, *acc);
else {
cout << "Connection successful." << endl;
std::cout << "Connection successful." << std::endl;
if (!cmd.empty()) {
cerr << "Unknown command: " << cmd << endl;
std::cerr << "Unknown command: " << cmd << std::endl;
return 1;
}
}
return 0;
} catch (exception &e) {
cerr << "Error: " << e.what() << endl;
} catch (std::exception &e) {
std::cerr << "Error: " << e.what() << std::endl;
return -1;
}
}
void printInfo(ostream &os, AcceleratorConnection &acc) {
string jsonManifest = acc.getService<services::SysInfo>()->getJsonManifest();
void printInfo(std::ostream &os, AcceleratorConnection &acc) {
std::string jsonManifest =
acc.getService<services::SysInfo>()->getJsonManifest();
Manifest m(acc.getCtxt(), jsonManifest);
os << "API version: " << m.getApiVersion() << endl << endl;
os << "********************************" << endl;
os << "* Module information" << endl;
os << "********************************" << endl;
os << endl;
os << "API version: " << m.getApiVersion() << std::endl << std::endl;
os << "********************************" << std::endl;
os << "* Module information" << std::endl;
os << "********************************" << std::endl;
os << std::endl;
for (ModuleInfo mod : m.getModuleInfos())
os << "- " << mod;
os << endl;
os << "********************************" << endl;
os << "* Type table" << endl;
os << "********************************" << endl;
os << endl;
os << std::endl;
os << "********************************" << std::endl;
os << "* Type table" << std::endl;
os << "********************************" << std::endl;
os << std::endl;
size_t i = 0;
for (const Type *t : m.getTypeTable())
os << " " << i++ << ": " << t->getID() << endl;
os << " " << i++ << ": " << t->getID() << std::endl;
}
void printPort(ostream &os, const BundlePort &port, string indent = "") {
os << indent << " " << port.getID() << ":" << endl;
void printPort(std::ostream &os, const BundlePort &port,
std::string indent = "") {
os << indent << " " << port.getID() << ":" << std::endl;
for (const auto &[name, chan] : port.getChannels()) {
os << indent << " " << name << ": " << chan.getType()->getID() << endl;
os << indent << " " << name << ": " << chan.getType()->getID()
<< std::endl;
}
}
void printInstance(ostream &os, const HWModule *d, string indent = "") {
void printInstance(std::ostream &os, const HWModule *d,
std::string indent = "") {
os << indent << "* Instance:";
if (auto inst = dynamic_cast<const Instance *>(d))
os << inst->getID() << endl;
os << inst->getID() << std::endl;
else
os << "top" << endl;
os << indent << "* Ports:" << endl;
os << "top" << std::endl;
os << indent << "* Ports:" << std::endl;
for (const BundlePort &port : d->getPortsOrdered())
printPort(os, port, indent + " ");
std::vector<const Instance *> children = d->getChildrenOrdered();
if (!children.empty()) {
os << indent << "* Children:" << endl;
os << indent << "* Children:" << std::endl;
for (const Instance *child : d->getChildrenOrdered())
printInstance(os, child, indent + " ");
}
os << endl;
os << std::endl;
}
void printHier(ostream &os, AcceleratorConnection &acc) {
void printHier(std::ostream &os, AcceleratorConnection &acc) {
Manifest manifest(acc.getCtxt(),
acc.getService<services::SysInfo>()->getJsonManifest());
std::unique_ptr<Accelerator> design = manifest.buildAccelerator(acc);
os << "********************************" << endl;
os << "* Design hierarchy" << endl;
os << "********************************" << endl;
os << endl;
os << "********************************" << std::endl;
os << "* Design hierarchy" << std::endl;
os << "********************************" << std::endl;
os << std::endl;
printInstance(os, design.get());
}

View File

@ -27,8 +27,6 @@
#include <map>
#include <stdexcept>
using namespace std;
using namespace esi;
static void registerCallbacks(Accelerator *);
@ -36,20 +34,20 @@ static void registerCallbacks(Accelerator *);
int main(int argc, const char *argv[]) {
// TODO: find a command line parser library rather than doing this by hand.
if (argc < 3) {
cerr << "Expected usage: " << argv[0]
<< " <backend> <connection specifier> [command]" << endl;
std::cerr << "Expected usage: " << argv[0]
<< " <backend> <connection specifier> [command]" << std::endl;
return -1;
}
const char *backend = argv[1];
const char *conn = argv[2];
string cmd;
std::string cmd;
if (argc > 3)
cmd = argv[3];
try {
Context ctxt;
unique_ptr<AcceleratorConnection> acc = ctxt.connect(backend, conn);
std::unique_ptr<AcceleratorConnection> acc = ctxt.connect(backend, conn);
const auto &info = *acc->getService<services::SysInfo>();
Manifest manifest(ctxt, info.getJsonManifest());
std::unique_ptr<Accelerator> accel = manifest.buildAccelerator(*acc);
@ -58,18 +56,18 @@ int main(int argc, const char *argv[]) {
if (cmd == "loop") {
while (true) {
this_thread::sleep_for(chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
} else if (cmd == "wait") {
this_thread::sleep_for(chrono::seconds(1));
std::this_thread::sleep_for(std::chrono::seconds(1));
}
acc->disconnect();
cerr << "Exiting successfully\n";
std::cerr << "Exiting successfully\n";
return 0;
} catch (exception &e) {
cerr << "Error: " << e.what() << endl;
} catch (std::exception &e) {
std::cerr << "Error: " << e.what() << std::endl;
return -1;
}
}
@ -82,7 +80,7 @@ void registerCallbacks(Accelerator *accel) {
if (callPort)
callPort->connect(
[](const MessageData &data) -> MessageData {
cout << "PrintfExample: " << *data.as<uint32_t>() << endl;
std::cout << "PrintfExample: " << *data.as<uint32_t>() << std::endl;
return MessageData();
},
true);