35class TraceChannelPort;
47 throw std::runtime_error(
"manifest file '" +
manifestJson.string() +
54 throw std::runtime_error(
"failed to open trace file '" +
59 assert(
false &&
"not implemented");
76 void write(
const AppIDPath &
id,
const std::string &portName,
const void *data,
77 size_t size,
const std::string &prefix =
"");
78 std::ostream &
write(std::string service) {
78 std::ostream &
write(std::string service) {
…}
89 std::vector<std::unique_ptr<ChannelPort>>
channels;
92void TraceAccelerator::Impl::write(
const AppIDPath &
id,
93 const std::string &portName,
94 const void *data,
size_t size,
95 const std::string &prefix) {
101 *
traceWrite << prefix << (prefix.empty() ?
"w" :
"W") <<
"rite " <<
id <<
'.'
102 << portName <<
": " << b64data << std::endl;
92void TraceAccelerator::Impl::write(
const AppIDPath &
id, {
…}
105std::unique_ptr<AcceleratorConnection>
108 std::string manifestPath;
109 std::string traceFile =
"trace.log";
113 std::regex connPattern(
"([\\w-]):([^:]+)(:(\\w+))?");
115 if (regex_search(connectionString, match, connPattern)) {
117 manifestPath = match[2];
118 if (match[3].matched)
119 traceFile = match[3];
121 throw std::runtime_error(
"connection std::string must be of the form "
122 "'<mode>:<manifest path>[:<traceFile>]'");
129 else if (modeStr ==
"-")
132 throw std::runtime_error(
"unknown mode '" + modeStr +
"'");
134 return std::make_unique<TraceAccelerator>(
ctxt, mode,
135 std::filesystem::path(manifestPath),
136 std::filesystem::path(traceFile));
140 std::filesystem::path manifestJson,
141 std::filesystem::path traceFile)
143 impl = std::make_unique<Impl>(mode, manifestJson, traceFile);
148class TraceSysInfo :
public SysInfo {
151 :
SysInfo(conn), manifestJson(manifestJson) {}
153 uint32_t getEsiVersion()
const override {
return ESIVersion; }
155 std::string getJsonManifest()
const override {
157 std::ifstream manifest(manifestJson);
158 if (!manifest.is_open())
159 throw std::runtime_error(
"failed to open manifest file '" +
160 manifestJson.string() +
"'");
161 std::stringstream buffer;
162 buffer << manifest.rdbuf();
167 std::vector<uint8_t> getCompressedManifest()
const override {
168 throw std::runtime_error(
169 "compressed manifest not supported by trace backend");
173 std::filesystem::path manifestJson;
181 const AppIDPath &
id,
const std::string &portName)
184 virtual void write(
const MessageData &data)
override {
185 impl.write(
id, portName,
data.getBytes(),
data.getSize());
189 impl.write(
id, portName,
data.getBytes(),
data.getSize(),
"try");
196 std::string portName;
205 ~ReadTraceChannelPort() { disconnect(); }
209 std::ptrdiff_t numBits = getType()->getBitWidth();
212 throw std::runtime_error(
"unsupported type for read: " +
215 std::ptrdiff_t size = (numBits + 7) / 8;
216 std::vector<uint8_t> bytes(size);
217 for (std::ptrdiff_t i = 0; i < size; ++i)
218 bytes[i] = rand() % 256;
222 bool pollImpl()
override {
return callback(genMessage()); }
227class TraceEngine :
public Engine {
230 :
Engine(conn), impl(impl) {}
232 std::unique_ptr<ChannelPort> createPort(
AppIDPath idPath,
233 const std::string &channelName,
235 const Type *type)
override {
236 std::unique_ptr<ChannelPort> port;
237 if (BundlePort::isWrite(dir))
238 port = std::make_unique<WriteTraceChannelPort>(impl, type, idPath,
241 port = std::make_unique<ReadTraceChannelPort>(impl, type);
262 :
MMIO(conn, idPath, clients), impl(conn.getImpl()) {}
264 virtual uint64_t
read(uint32_t addr)
const override {
265 uint64_t data = rand();
266 if (impl.isWriteable())
267 impl.write(
"MMIO") <<
"[" << std::hex << addr <<
"] -> " << data
264 virtual uint64_t
read(uint32_t addr)
const override {
…}
271 virtual void write(uint32_t addr, uint64_t data)
override {
272 if (!impl.isWriteable())
274 impl.write(
"MMIO") <<
"[" << std::hex << addr <<
"] <- " << data
271 virtual void write(uint32_t addr, uint64_t data)
override {
…}
293 if (impl.isWriteable())
294 impl.write(
"HostMem") <<
"free " << ptr << std::endl;
297 virtual void *
getPtr()
const override {
return ptr; }
298 virtual std::size_t
getSize()
const override {
return size; }
306 virtual std::unique_ptr<HostMemRegion>
310 if (impl.isWriteable())
311 impl.write(
"HostMem 0x")
312 << ret->getPtr() <<
" allocate " << size
313 <<
" bytes. Writeable: " << opts.
writeable
320 if (impl.isWriteable())
321 impl.write(
"HostMem")
322 <<
"map 0x" << ptr <<
" size " << size
323 <<
" bytes. Writeable: " << opts.
writeable
328 if (impl.isWriteable())
329 impl.write(
"HostMem") <<
"unmap 0x" << ptr << std::endl;
340 if (svcType ==
typeid(
SysInfo))
341 return new TraceSysInfo(*
this,
getImpl().manifestJson);
342 if (svcType ==
typeid(
MMIO))
343 return new TraceMMIO(*
this, idPath, clients);
344 if (svcType ==
typeid(
HostMem))
#define REGISTER_ACCELERATOR(Name, TAccelerator)
assert(baseType &&"element must be base type")
constexpr uint32_t ESIVersion
virtual std::unique_ptr< HostMemRegion > allocate(std::size_t size, HostMem::Options opts) const override
Allocate a region of host memory in accelerator accessible address space.
TraceHostMem(TraceAccelerator &conn)
virtual bool mapMemory(void *ptr, std::size_t size, HostMem::Options opts) const override
Try to make a region of host memory accessible to the accelerator.
virtual void unmapMemory(void *ptr) const override
Unmap memory which was previously mapped with 'mapMemory'.
TraceAccelerator::Impl & impl
TraceMMIO(TraceAccelerator &conn, const AppIDPath &idPath, const HWClientDetails &clients)
virtual uint64_t read(uint32_t addr) const override
Read a 64-bit value from the global MMIO space.
virtual void write(uint32_t addr, uint64_t data) override
Write a 64-bit value to the global MMIO space.
TraceAccelerator::Impl & impl
Abstract class representing a connection to an accelerator.
virtual void disconnect()
Disconnect from the accelerator cleanly.
Context & ctxt
ESI accelerator context.
void registerEngine(AppIDPath idPath, std::unique_ptr< Engine > engine, const HWClientDetails &clients)
If createEngine is overridden, this method should be called to register the engine and all of the cha...
Unidirectional channels are the basic communication primitive between the host and accelerator.
AcceleratorConnections, Accelerators, and Manifests must all share a context.
Engines implement the actual channel communication between the host and the accelerator.
A logical chunk of data representing serialized data.
A ChannelPort which reads data from the accelerator.
Root class of the ESI type system.
A ChannelPort which sends data to the accelerator.
Connect to an ESI simulation.
std::unique_ptr< Impl > impl
TraceAccelerator(Context &, Mode mode, std::filesystem::path manifestJson, std::filesystem::path traceFile)
Create a trace-based accelerator backend.
void createEngine(const std::string &engineTypeName, AppIDPath idPath, const ServiceImplDetails &details, const HWClientDetails &clients) override
Create a new engine for channel communication with the accelerator.
~TraceAccelerator() override
virtual Service * createService(Service::Type service, AppIDPath idPath, std::string implName, const ServiceImplDetails &details, const HWClientDetails &clients) override
Called by getServiceImpl exclusively.
static std::unique_ptr< AcceleratorConnection > connect(Context &, std::string connectionString)
Parse the connection string and instantiate the accelerator.
Parent class of all APIs modeled as 'services'.
const std::type_info & Type
Information about the Accelerator system.
void encodeBase64(const void *data, size_t size, std::string &out)
std::map< std::string, std::any > ServiceImplDetails
std::vector< HWClientDetail > HWClientDetails
virtual std::size_t getSize() const override
TraceHostMemRegion(std::size_t size, TraceAccelerator::Impl &impl)
virtual ~TraceHostMemRegion()
virtual void * getPtr() const override
Get a pointer to the host memory.
TraceAccelerator::Impl & impl
std::ofstream * traceWrite
void write(const AppIDPath &id, const std::string &portName, const void *data, size_t size, const std::string &prefix="")
std::vector< std::unique_ptr< ChannelPort > > channels
std::filesystem::path manifestJson
std::ostream & write(std::string service)
void adoptChannelPort(ChannelPort *port)
Service * createService(TraceAccelerator &conn, Service::Type svcType, AppIDPath idPath, const ServiceImplDetails &details, const HWClientDetails &clients)
std::filesystem::path traceFile
Impl(Mode mode, std::filesystem::path manifestJson, std::filesystem::path traceFile)
RAII memory region for host memory.
Options for allocating host memory.