35 class TraceChannelPort;
39 Impl(
Mode mode, std::filesystem::path manifestJson,
40 std::filesystem::path traceFile)
41 : manifestJson(manifestJson), traceFile(traceFile) {
42 if (!std::filesystem::exists(manifestJson))
43 throw std::runtime_error(
"manifest file '" + manifestJson.string() +
48 traceWrite =
new std::ofstream(traceFile);
49 if (!traceWrite->is_open())
50 throw std::runtime_error(
"failed to open trace file '" +
51 traceFile.string() +
"'");
52 }
else if (mode == Discard) {
55 assert(
false &&
"not implemented");
73 std::map<std::string, ChannelPort &> requestChannelsFor(
AppIDPath,
78 void write(
const AppIDPath &
id,
const std::string &portName,
const void *data,
79 size_t size,
const std::string &prefix =
"");
80 std::ostream &
write(std::string service) {
81 assert(traceWrite &&
"traceWrite is null");
82 *traceWrite <<
"[" << service <<
"] ";
91 std::vector<std::unique_ptr<ChannelPort>>
channels;
94 void TraceAccelerator::Impl::write(
const AppIDPath &
id,
95 const std::string &portName,
96 const void *data,
size_t size,
97 const std::string &prefix) {
103 *traceWrite << prefix << (prefix.empty() ?
"w" :
"W") <<
"rite " <<
id <<
'.'
104 << portName <<
": " << b64data << std::endl;
107 std::unique_ptr<AcceleratorConnection>
110 std::string manifestPath;
111 std::string traceFile =
"trace.log";
115 std::regex connPattern(
"([\\w-]):([^:]+)(:(\\w+))?");
117 if (regex_search(connectionString, match, connPattern)) {
119 manifestPath = match[2];
120 if (match[3].matched)
121 traceFile = match[3];
123 throw std::runtime_error(
"connection std::string must be of the form "
124 "'<mode>:<manifest path>[:<traceFile>]'");
131 else if (modeStr ==
"-")
134 throw std::runtime_error(
"unknown mode '" + modeStr +
"'");
136 return std::make_unique<TraceAccelerator>(
ctxt, mode,
137 std::filesystem::path(manifestPath),
138 std::filesystem::path(traceFile));
142 std::filesystem::path manifestJson,
143 std::filesystem::path traceFile)
145 impl = std::make_unique<Impl>(mode, manifestJson, traceFile);
153 return impl->createService(svcType, idPath, details, clients);
156 class TraceSysInfo :
public SysInfo {
158 TraceSysInfo(std::filesystem::path manifestJson)
159 : manifestJson(manifestJson) {}
161 uint32_t getEsiVersion()
const override {
return ESIVersion; }
163 std::string getJsonManifest()
const override {
165 std::ifstream manifest(manifestJson);
166 if (!manifest.is_open())
167 throw std::runtime_error(
"failed to open manifest file '" +
168 manifestJson.string() +
"'");
169 std::stringstream buffer;
170 buffer << manifest.rdbuf();
175 std::vector<uint8_t> getCompressedManifest()
const override {
176 throw std::runtime_error(
177 "compressed manifest not supported by trace backend");
181 std::filesystem::path manifestJson;
189 const AppIDPath &
id,
const std::string &portName)
192 virtual void write(
const MessageData &data)
override {
193 impl.write(
id, portName,
data.getBytes(),
data.getSize());
197 impl.write(
id, portName,
data.getBytes(),
data.getSize(),
"try");
204 std::string portName;
213 ~ReadTraceChannelPort() { disconnect(); }
217 std::ptrdiff_t numBits = getType()->getBitWidth();
220 throw std::runtime_error(
"unsupported type for read: " +
223 std::ptrdiff_t size = (numBits + 7) / 8;
224 std::vector<uint8_t> bytes(size);
225 for (std::ptrdiff_t i = 0; i < size; ++i)
226 bytes[i] = rand() % 256;
230 bool pollImpl()
override {
return callback(genMessage()); }
244 std::map<std::string, ChannelPort &>
247 std::map<std::string, ChannelPort &>
channels;
248 for (
auto [name, dir, type] : bundleType->
getChannels()) {
251 port =
new WriteTraceChannelPort(*
this, type, idPath, name);
253 port =
new ReadTraceChannelPort(*
this, type);
260 std::map<std::string, ChannelPort &>
263 return impl->requestChannelsFor(idPath, bundleType);
270 virtual uint64_t
read(uint32_t addr)
const override {
271 uint64_t data = rand();
272 if (
impl.isWriteable())
273 impl.write(
"MMIO") <<
"[" << std::hex << addr <<
"] -> " << data
277 virtual void write(uint32_t addr, uint64_t data)
override {
278 if (!
impl.isWriteable())
280 impl.write(
"MMIO") <<
"[" << std::hex << addr <<
"] <- " << data
299 if (
impl.isWriteable())
300 impl.write(
"HostMem") <<
"free " << ptr << std::endl;
303 virtual void *
getPtr()
const override {
return ptr; }
304 virtual std::size_t
getSize()
const override {
return size; }
312 virtual std::unique_ptr<HostMemRegion>
316 if (
impl.isWriteable())
317 impl.write(
"HostMem 0x")
318 << ret->getPtr() <<
" allocate " << size
319 <<
" bytes. Writeable: " << opts.
writeable
326 if (
impl.isWriteable())
327 impl.write(
"HostMem")
328 <<
"map 0x" << ptr <<
" size " << size
329 <<
" bytes. Writeable: " << opts.
writeable
334 if (
impl.isWriteable())
335 impl.write(
"HostMem") <<
"unmap 0x" << ptr << std::endl;
346 if (svcType ==
typeid(
SysInfo))
347 return new TraceSysInfo(manifestJson);
348 if (svcType ==
typeid(
MMIO))
350 if (svcType ==
typeid(
HostMem))
353 return new TraceCustomService(*
this, idPath, details, clients);
assert(baseType &&"element must be base type")
constexpr uint32_t ESIVersion
REGISTER_ACCELERATOR("trace", TraceAccelerator)
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::Impl &impl)
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
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
TraceMMIO(TraceAccelerator::Impl &impl)
Abstract class representing a connection to an accelerator.
virtual void disconnect()
Disconnect from the accelerator cleanly.
static bool isWrite(BundleType::Direction bundleDir)
Compute the direction of a channel given the bundle direction and the bundle port's direction.
Bundles represent a collection of channels.
const ChannelVector & getChannels() const
Unidirectional channels are the basic communication primitive between the host and accelerator.
AcceleratorConnections, Accelerators, and Manifests must all share a context.
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() override
virtual Service * createService(Service::Type service, AppIDPath idPath, std::string implName, const ServiceImplDetails &details, const HWClientDetails &clients) override
Called by getServiceImpl exclusively.
std::map< std::string, ChannelPort & > requestChannelsFor(AppIDPath, const BundleType *) override
Request the host side channel ports for a particular instance (identified by the AppID path).
A service for which there are no standard services registered.
Parent class of all APIs modeled as 'services'.
const std::type_info & Type
Information about the Accelerator system.
def connect(destination, source)
void encodeBase64(const void *data, size_t size, std::string &out)
std::map< std::string, std::any > ServiceImplDetails
std::vector< HWClientDetail > HWClientDetails
virtual void * getPtr() const override
virtual std::size_t getSize() const override
TraceHostMemRegion(std::size_t size, TraceAccelerator::Impl &impl)
virtual ~TraceHostMemRegion()
TraceAccelerator::Impl & impl
Service * createService(Service::Type svcType, AppIDPath idPath, const ServiceImplDetails &details, const HWClientDetails &clients)
std::ofstream * traceWrite
std::vector< std::unique_ptr< ChannelPort > > channels
std::filesystem::path manifestJson
std::map< std::string, ChannelPort & > requestChannelsFor(AppIDPath, const BundleType *)
Request the host side channel ports for a particular instance (identified by the AppID path).
std::ostream & write(std::string service)
void adoptChannelPort(ChannelPort *port)
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.