esiaccel 0.0.17.dev447__cp310-cp310-win_amd64.whl → 0.1.5.dev406__cp310-cp310-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of esiaccel might be problematic. Click here for more details.

Files changed (54) hide show
  1. esiaccel/CosimBackend.dll +0 -0
  2. esiaccel/CosimBackend.lib +0 -0
  3. esiaccel/ESICppRuntime.dll +0 -0
  4. esiaccel/ESICppRuntime.lib +0 -0
  5. esiaccel/EsiCosimDpiServer.dll +0 -0
  6. esiaccel/EsiCosimDpiServer.lib +0 -0
  7. esiaccel/MtiPli.dll +0 -0
  8. esiaccel/MtiPli.lib +0 -0
  9. esiaccel/__init__.py +10 -1
  10. esiaccel/abseil_dll.dll +0 -0
  11. esiaccel/accelerator.py +7 -0
  12. esiaccel/cares.dll +0 -0
  13. esiaccel/cmake/esiaccelConfig.cmake +1 -1
  14. esiaccel/cosim/Cosim_DpiPkg.sv +85 -0
  15. esiaccel/cosim/Cosim_Endpoint.sv +218 -0
  16. esiaccel/cosim/Cosim_Manifest.sv +32 -0
  17. esiaccel/cosim/driver.cpp +131 -0
  18. esiaccel/cosim/driver.sv +74 -0
  19. esiaccel/cosim/questa.py +141 -0
  20. esiaccel/cosim/simulator.py +382 -0
  21. esiaccel/cosim/verilator.py +92 -0
  22. esiaccel/esi-cosim.py +104 -0
  23. esiaccel/esiCppAccel.cp310-win_amd64.pyd +0 -0
  24. esiaccel/esiquery.exe +0 -0
  25. esiaccel/include/esi/Accelerator.h +31 -15
  26. esiaccel/include/esi/CLI.h +77 -0
  27. esiaccel/include/esi/Common.h +32 -3
  28. esiaccel/include/esi/Context.h +1 -1
  29. esiaccel/include/esi/Design.h +11 -4
  30. esiaccel/include/esi/Engines.h +124 -0
  31. esiaccel/include/esi/Logging.h +57 -7
  32. esiaccel/include/esi/Manifest.h +0 -2
  33. esiaccel/include/esi/Ports.h +47 -6
  34. esiaccel/include/esi/Services.h +144 -41
  35. esiaccel/include/esi/Types.h +103 -5
  36. esiaccel/include/esi/Values.h +313 -0
  37. esiaccel/include/esi/backends/Cosim.h +85 -0
  38. esiaccel/include/esi/backends/RpcServer.h +55 -0
  39. esiaccel/include/esi/backends/Trace.h +5 -6
  40. esiaccel/libcrypto-3-x64.dll +0 -0
  41. esiaccel/libprotobuf.dll +0 -0
  42. esiaccel/libssl-3-x64.dll +0 -0
  43. esiaccel/re2.dll +0 -0
  44. esiaccel/types.py +132 -26
  45. esiaccel/utils.py +21 -3
  46. esiaccel/zlib1.dll +0 -0
  47. {esiaccel-0.0.17.dev447.dist-info → esiaccel-0.1.5.dev406.dist-info}/METADATA +3 -3
  48. esiaccel-0.1.5.dev406.dist-info/RECORD +54 -0
  49. {esiaccel-0.0.17.dev447.dist-info → esiaccel-0.1.5.dev406.dist-info}/WHEEL +1 -1
  50. esiaccel/bin/esiquery.exe +0 -0
  51. esiaccel-0.0.17.dev447.dist-info/RECORD +0 -28
  52. {esiaccel-0.0.17.dev447.dist-info → esiaccel-0.1.5.dev406.dist-info}/entry_points.txt +0 -0
  53. {esiaccel-0.0.17.dev447.dist-info → esiaccel-0.1.5.dev406.dist-info/licenses}/LICENSE +0 -0
  54. {esiaccel-0.0.17.dev447.dist-info → esiaccel-0.1.5.dev406.dist-info}/top_level.txt +0 -0
esiaccel/esi-cosim.py ADDED
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # ===- esi-cosim.py - ESI cosimulation launch utility --------*- python -*-===//
4
+ #
5
+ # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6
+ # See https://llvm.org/LICENSE.txt for license information.
7
+ # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8
+ #
9
+ # ===----------------------------------------------------------------------===//
10
+ #
11
+ # Utility script to start a simulation and launch a command to interact with it
12
+ # via ESI cosimulation.
13
+ #
14
+ # ===----------------------------------------------------------------------===//
15
+
16
+ import argparse
17
+ from pathlib import Path
18
+ import sys
19
+ import textwrap
20
+ from typing import Dict, List
21
+
22
+ from esiaccel.cosim.questa import Questa
23
+ from esiaccel.cosim.verilator import Verilator
24
+ from esiaccel.cosim.simulator import SourceFiles
25
+
26
+
27
+ def __main__(args):
28
+ argparser = argparse.ArgumentParser(
29
+ description="Wrap a 'inner_cmd' in an ESI cosimulation environment.",
30
+ formatter_class=argparse.RawDescriptionHelpFormatter,
31
+ epilog=textwrap.dedent("""
32
+ Notes:
33
+ - For Verilator, libEsiCosimDpiServer.so must be in the dynamic
34
+ library runtime search path (LD_LIBRARY_PATH) and link time path
35
+ (LIBRARY_PATH). If it is installed to a standard location (e.g.
36
+ /usr/lib), this should be handled automatically.
37
+ - This script needs to sit in the same directory as the ESI support
38
+ SystemVerilog (e.g. Cosim_DpiPkg.sv, Cosim_MMIO.sv, etc.). It can,
39
+ however, be soft linked to a different location.
40
+ - The simulator executable(s) must be in your PATH.
41
+ """))
42
+
43
+ argparser.add_argument(
44
+ "--sim",
45
+ type=str,
46
+ default="verilator",
47
+ help="Name of the RTL simulator to use or path to an executable.")
48
+ argparser.add_argument("--rundir",
49
+ default="run",
50
+ help="Directory in which simulation should be run.")
51
+ argparser.add_argument(
52
+ "--top",
53
+ default="ESI_Cosim_Top",
54
+ help="Name of the 'top' module to use in the simulation.")
55
+ argparser.add_argument("--no-compile",
56
+ action="store_true",
57
+ help="Do not run the compile.")
58
+ argparser.add_argument("--debug",
59
+ action="store_true",
60
+ help="Enable debug output.")
61
+ argparser.add_argument("--gui",
62
+ action="store_true",
63
+ help="Run the simulator in GUI mode (if supported).")
64
+ argparser.add_argument("--source",
65
+ help="Directories containing the source files.",
66
+ default="hw")
67
+
68
+ argparser.add_argument("inner_cmd",
69
+ nargs=argparse.REMAINDER,
70
+ help="Command to run in the simulation environment.")
71
+
72
+ argparser.add_argument(
73
+ "--server-only",
74
+ action="store_true",
75
+ help="Only run the cosim server, and do not run any inner command.")
76
+
77
+ if len(args) <= 1:
78
+ argparser.print_help()
79
+ return
80
+ args = argparser.parse_args(args[1:])
81
+
82
+ sources = SourceFiles(args.top)
83
+ sources.add_dir(Path(args.source))
84
+
85
+ if args.sim == "verilator":
86
+ sim = Verilator(sources, Path(args.rundir), args.debug)
87
+ elif args.sim == "questa":
88
+ sim = Questa(sources, Path(args.rundir), args.debug)
89
+ else:
90
+ print("Unknown simulator: " + args.sim)
91
+ print("Supported simulators: ")
92
+ print(" - verilator")
93
+ print(" - questa")
94
+ return 1
95
+
96
+ if not args.no_compile:
97
+ rc = sim.compile()
98
+ if rc != 0:
99
+ return rc
100
+ return sim.run(args.inner_cmd[1:], gui=args.gui, server_only=args.server_only)
101
+
102
+
103
+ if __name__ == '__main__':
104
+ sys.exit(__main__(sys.argv))
Binary file
esiaccel/esiquery.exe ADDED
Binary file
@@ -23,6 +23,7 @@
23
23
 
24
24
  #include "esi/Context.h"
25
25
  #include "esi/Design.h"
26
+ #include "esi/Engines.h"
26
27
  #include "esi/Manifest.h"
27
28
  #include "esi/Ports.h"
28
29
  #include "esi/Services.h"
@@ -85,18 +86,6 @@ public:
85
86
  /// Disconnect from the accelerator cleanly.
86
87
  virtual void disconnect();
87
88
 
88
- // While building the design, keep around a std::map of active services
89
- // indexed by the service name. When a new service is encountered during
90
- // descent, add it to the table (perhaps overwriting one). Modifications to
91
- // the table only apply to the current branch, so copy this and update it at
92
- // each level of the tree.
93
- using ServiceTable = std::map<std::string, services::Service *>;
94
-
95
- /// Request the host side channel ports for a particular instance (identified
96
- /// by the AppID path). For convenience, provide the bundle type.
97
- virtual std::map<std::string, ChannelPort &>
98
- requestChannelsFor(AppIDPath, const BundleType *, const ServiceTable &) = 0;
99
-
100
89
  /// Return a pointer to the accelerator 'service' thread (or threads). If the
101
90
  /// thread(s) are not running, they will be started when this method is
102
91
  /// called. `std::thread` is used. If users don't want the runtime to spin up
@@ -126,7 +115,30 @@ public:
126
115
  /// accelerator to this connection. Returns a raw pointer to the object.
127
116
  Accelerator *takeOwnership(std::unique_ptr<Accelerator> accel);
128
117
 
118
+ /// Create a new engine for channel communication with the accelerator. The
119
+ /// default is to call the global `createEngine` to get an engine which has
120
+ /// registered itself. Individual accelerator connection backends can override
121
+ /// this to customize behavior.
122
+ virtual void createEngine(const std::string &engineTypeName, AppIDPath idPath,
123
+ const ServiceImplDetails &details,
124
+ const HWClientDetails &clients);
125
+ virtual const BundleEngineMap &getEngineMapFor(AppIDPath id) {
126
+ return clientEngines[id];
127
+ }
128
+
129
+ Accelerator &getAccelerator() {
130
+ if (!ownedAccelerator)
131
+ throw std::runtime_error(
132
+ "AcceleratorConnection does not own an accelerator");
133
+ return *ownedAccelerator;
134
+ }
135
+
129
136
  protected:
137
+ /// If `createEngine` is overridden, this method should be called to register
138
+ /// the engine and all of the channels it services.
139
+ void registerEngine(AppIDPath idPath, std::unique_ptr<Engine> engine,
140
+ const HWClientDetails &clients);
141
+
130
142
  /// Called by `getServiceImpl` exclusively. It wraps the pointer returned by
131
143
  /// this in a unique_ptr and caches it. Separate this from the
132
144
  /// wrapping/caching since wrapping/caching is an implementation detail.
@@ -135,6 +147,11 @@ protected:
135
147
  const ServiceImplDetails &details,
136
148
  const HWClientDetails &clients) = 0;
137
149
 
150
+ /// Collection of owned engines.
151
+ std::map<AppIDPath, std::unique_ptr<Engine>> ownedEngines;
152
+ /// Mapping of clients to their servicing engines.
153
+ std::map<AppIDPath, BundleEngineMap> clientEngines;
154
+
138
155
  private:
139
156
  /// ESI accelerator context.
140
157
  Context &ctxt;
@@ -146,9 +163,8 @@ private:
146
163
 
147
164
  std::unique_ptr<AcceleratorServiceThread> serviceThread;
148
165
 
149
- /// List of accelerator objects owned by this connection. These are destroyed
150
- /// when the connection dies or is shutdown.
151
- std::vector<std::unique_ptr<Accelerator>> ownedAccelerators;
166
+ /// Accelerator object owned by this connection.
167
+ std::unique_ptr<Accelerator> ownedAccelerator;
152
168
  };
153
169
 
154
170
  namespace registry {
@@ -0,0 +1,77 @@
1
+ //===- CLI.h - ESI runtime tool CLI parser common ---------------*- C++ -*-===//
2
+ //
3
+ // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
+ // See https://llvm.org/LICENSE.txt for license information.
5
+ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
+ //
7
+ //===----------------------------------------------------------------------===//
8
+ //
9
+ // This file contains the common CLI parser code for ESI runtime tools. Exposed
10
+ // publicly so that out-of-tree tools can use it. This is a header-only library
11
+ // to make compilation easier for out-of-tree tools.
12
+ //
13
+ // DO NOT EDIT!
14
+ // This file is distributed as part of an ESI package. The source for this file
15
+ // should always be modified within CIRCT (lib/dialect/ESI/runtime/cpp).
16
+ //
17
+ //===----------------------------------------------------------------------===//
18
+
19
+ // NOLINTNEXTLINE(llvm-header-guard)
20
+ #ifndef ESI_CLI_H
21
+ #define ESI_CLI_H
22
+
23
+ #include "CLI/CLI.hpp"
24
+ #include "esi/Context.h"
25
+
26
+ namespace esi {
27
+
28
+ /// Common options and code for ESI runtime tools.
29
+ class CliParser : public CLI::App {
30
+ public:
31
+ CliParser(const std::string &toolName)
32
+ : CLI::App(toolName), debug(false), verbose(false) {
33
+ add_option("backend", backend, "Backend to use for connection")->required();
34
+ add_option("connection", connStr,
35
+ "Connection string to use for accelerator communication")
36
+ ->required();
37
+ add_flag("--debug", debug, "Enable debug logging");
38
+ #ifdef ESI_RUNTIME_TRACE
39
+ add_flag("--trace", trace, "Enable trace logging");
40
+ #endif
41
+ add_flag("-v,--verbose", verbose, "Enable verbose (info) logging");
42
+ require_subcommand(0, 1);
43
+ }
44
+
45
+ /// Run the parser.
46
+ int esiParse(int argc, const char **argv) {
47
+ CLI11_PARSE(*this, argc, argv);
48
+ if (trace)
49
+ ctxt = Context::withLogger<ConsoleLogger>(Logger::Level::Trace);
50
+ else if (debug)
51
+ ctxt = Context::withLogger<ConsoleLogger>(Logger::Level::Debug);
52
+ else if (verbose)
53
+ ctxt = Context::withLogger<ConsoleLogger>(Logger::Level::Info);
54
+ return 0;
55
+ }
56
+
57
+ /// Connect to the accelerator using the specified backend and connection.
58
+ std::unique_ptr<AcceleratorConnection> connect() {
59
+ return ctxt.connect(backend, connStr);
60
+ }
61
+
62
+ /// Get the context.
63
+ Context &getContext() { return ctxt; }
64
+
65
+ protected:
66
+ Context ctxt;
67
+
68
+ std::string backend;
69
+ std::string connStr;
70
+ bool trace = false;
71
+ bool debug = false;
72
+ bool verbose = false;
73
+ };
74
+
75
+ } // namespace esi
76
+
77
+ #endif // ESI_CLI_H
@@ -20,6 +20,7 @@
20
20
  #include <cstdint>
21
21
  #include <map>
22
22
  #include <optional>
23
+ #include <span>
23
24
  #include <stdexcept>
24
25
  #include <string>
25
26
  #include <vector>
@@ -42,6 +43,13 @@ struct AppID {
42
43
  return name == other.name && idx == other.idx;
43
44
  }
44
45
  bool operator!=(const AppID &other) const { return !(*this == other); }
46
+ friend std::ostream &operator<<(std::ostream &os, const AppID &id);
47
+
48
+ std::string toString() const {
49
+ if (idx.has_value())
50
+ return name + "[" + std::to_string(idx.value()) + "]";
51
+ return name;
52
+ }
45
53
  };
46
54
  bool operator<(const AppID &a, const AppID &b);
47
55
 
@@ -49,8 +57,10 @@ class AppIDPath : public std::vector<AppID> {
49
57
  public:
50
58
  using std::vector<AppID>::vector;
51
59
 
52
- AppIDPath operator+(const AppIDPath &b);
60
+ AppIDPath operator+(const AppIDPath &b) const;
61
+ AppIDPath parent() const;
53
62
  std::string toStr() const;
63
+ friend std::ostream &operator<<(std::ostream &os, const AppIDPath &path);
54
64
  };
55
65
  bool operator<(const AppIDPath &a, const AppIDPath &b);
56
66
 
@@ -104,13 +114,32 @@ class MessageData {
104
114
  public:
105
115
  /// Adopts the data vector buffer.
106
116
  MessageData() = default;
117
+ MessageData(std::span<const uint8_t> data)
118
+ : data(data.data(), data.data() + data.size()) {}
107
119
  MessageData(std::vector<uint8_t> &data) : data(std::move(data)) {}
120
+ MessageData(std::vector<uint8_t> &&data) : data(std::move(data)) {}
108
121
  MessageData(const uint8_t *data, size_t size) : data(data, data + size) {}
109
122
  ~MessageData() = default;
110
123
 
111
124
  const uint8_t *getBytes() const { return data.data(); }
125
+
126
+ /// Get the data as a vector of bytes.
127
+ const std::vector<uint8_t> &getData() const { return data; }
128
+
129
+ /// Implicit conversion to a vector/span of bytes, to play nice with other
130
+ /// APIs that accept bytearray-like things.
131
+ operator const std::vector<uint8_t> &() const { return data; }
132
+ operator std::span<const uint8_t>() const { return data; }
133
+
134
+ /// Move the data out of this object.
135
+ std::vector<uint8_t> takeData() { return std::move(data); }
136
+
112
137
  /// Get the size of the data in bytes.
113
138
  size_t getSize() const { return data.size(); }
139
+ size_t size() const { return getSize(); }
140
+
141
+ /// Returns true if this message contains no data.
142
+ bool empty() const { return data.empty(); }
114
143
 
115
144
  /// Cast to a type. Throws if the size of the data does not match the size of
116
145
  /// the message. The lifetime of the resulting pointer is tied to the lifetime
@@ -140,14 +169,14 @@ private:
140
169
  } // namespace esi
141
170
 
142
171
  std::ostream &operator<<(std::ostream &, const esi::ModuleInfo &);
143
- std::ostream &operator<<(std::ostream &, const esi::AppID &);
144
172
 
145
173
  //===----------------------------------------------------------------------===//
146
174
  // Functions which should be in the standard library.
147
175
  //===----------------------------------------------------------------------===//
148
176
 
149
177
  namespace esi {
150
- std::string toHex(uint32_t val);
178
+ std::string toHex(void *val);
179
+ std::string toHex(uint64_t val);
151
180
  } // namespace esi
152
181
 
153
182
  #endif // ESI_COMMON_H
@@ -30,7 +30,7 @@ class AcceleratorConnection;
30
30
  /// context. It owns all the types, uniquifying them.
31
31
  class Context {
32
32
  public:
33
- Context() : logger(std::make_unique<NullLogger>()) {}
33
+ Context() : logger(std::make_unique<ConsoleLogger>(Logger::Level::Warning)) {}
34
34
  Context(std::unique_ptr<Logger> logger) : logger(std::move(logger)) {}
35
35
 
36
36
  /// Create a context with a specific logger type.
@@ -73,9 +73,7 @@ public:
73
73
  return ret;
74
74
  }
75
75
  /// Access the module's ports by ID.
76
- const std::map<AppID, const BundlePort &> &getPorts() const {
77
- return portIndex;
78
- }
76
+ const std::map<AppID, BundlePort &> &getPorts() const { return portIndex; }
79
77
  /// Access the services provided by this module.
80
78
  const std::vector<services::Service *> &getServices() const {
81
79
  return services;
@@ -86,13 +84,22 @@ public:
86
84
  /// the `poll` calls returns true.
87
85
  bool poll();
88
86
 
87
+ /// Attempt to resolve a path to a module instance. If a child is not found,
88
+ /// return null and set lastLookup to the path which wasn't found.
89
+ const HWModule *resolveInst(const AppIDPath &path,
90
+ AppIDPath &lastLookup) const;
91
+
92
+ /// Attempt to resolve a path to a port. If a child or port is not found,
93
+ /// return null and set lastLookup to the path which wasn't found.
94
+ BundlePort *resolvePort(const AppIDPath &path, AppIDPath &lastLookup) const;
95
+
89
96
  protected:
90
97
  const std::optional<ModuleInfo> info;
91
98
  const std::vector<std::unique_ptr<Instance>> children;
92
99
  const std::map<AppID, Instance *> childIndex;
93
100
  const std::vector<services::Service *> services;
94
101
  const std::vector<std::unique_ptr<BundlePort>> ports;
95
- const std::map<AppID, const BundlePort &> portIndex;
102
+ const std::map<AppID, BundlePort &> portIndex;
96
103
  };
97
104
 
98
105
  /// Subclass of `HWModule` which represents a submodule instance. Adds an AppID,
@@ -0,0 +1,124 @@
1
+ //===- Engines.h - Implement port communication -----------------*- C++ -*-===//
2
+ //
3
+ // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
+ // See https://llvm.org/LICENSE.txt for license information.
5
+ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
+ //
7
+ //===----------------------------------------------------------------------===//
8
+ //
9
+ // DO NOT EDIT!
10
+ // This file is distributed as part of an ESI package. The source for this file
11
+ // should always be modified within CIRCT.
12
+ //
13
+ //===----------------------------------------------------------------------===//
14
+ //
15
+ // Engines (as in DMA engine) implement the actual communication between the
16
+ // host and the accelerator. They are low level of the ESI runtime API and are
17
+ // not intended to be used directly by users.
18
+ //
19
+ // They are called "engines" rather than "DMA engines" since communication need
20
+ // not be implemented via DMA.
21
+ //
22
+ //===----------------------------------------------------------------------===//
23
+
24
+ // NOLINTNEXTLINE(llvm-header-guard)
25
+ #ifndef ESI_ENGINGES_H
26
+ #define ESI_ENGINGES_H
27
+
28
+ #include "esi/Common.h"
29
+ #include "esi/Ports.h"
30
+ #include "esi/Services.h"
31
+ #include "esi/Utils.h"
32
+
33
+ #include <cassert>
34
+ #include <future>
35
+
36
+ namespace esi {
37
+ class Accelerator;
38
+
39
+ /// Engines implement the actual channel communication between the host and the
40
+ /// accelerator. Engines can support multiple channels. They are low level of
41
+ /// the ESI runtime API and are not intended to be used directly by users.
42
+ class Engine {
43
+ public:
44
+ Engine(AcceleratorConnection &conn) : connected(false), conn(conn) {}
45
+ virtual ~Engine() = default;
46
+ /// Start the engine, if applicable.
47
+ virtual void connect() { connected = true; };
48
+ /// Stop the engine, if applicable.
49
+ virtual void disconnect() { connected = false; };
50
+ /// Get a port for a channel, from the cache if it exists or create it. An
51
+ /// engine may override this method if different behavior is desired.
52
+ virtual ChannelPort &requestPort(AppIDPath idPath,
53
+ const std::string &channelName,
54
+ BundleType::Direction dir, const Type *type);
55
+
56
+ protected:
57
+ /// Each engine needs to know how to create a ports. This method is called if
58
+ /// a port doesn't exist in the engine cache.
59
+ virtual std::unique_ptr<ChannelPort>
60
+ createPort(AppIDPath idPath, const std::string &channelName,
61
+ BundleType::Direction dir, const Type *type) = 0;
62
+
63
+ bool connected;
64
+ AcceleratorConnection &conn;
65
+
66
+ private:
67
+ std::map<std::pair<AppIDPath, std::string>, std::unique_ptr<ChannelPort>>
68
+ ownedPorts;
69
+ };
70
+
71
+ /// Since engines can support multiple channels BUT not necessarily all of the
72
+ /// channels in a bundle, a mapping from bundle channels to engines is needed.
73
+ class BundleEngineMap {
74
+ friend class AcceleratorConnection;
75
+
76
+ public:
77
+ /// Request ports for all the channels in a bundle. If the engine doesn't
78
+ /// exist for a particular channel, skip said channel.
79
+ PortMap requestPorts(const AppIDPath &idPath,
80
+ const BundleType *bundleType) const;
81
+
82
+ private:
83
+ /// Set a particlar engine for a particular channel. Should only be called by
84
+ /// AcceleratorConnection while registering engines.
85
+ void setEngine(const std::string &channelName, Engine *engine);
86
+ std::map<std::string, Engine *> bundleEngineMap;
87
+ };
88
+
89
+ namespace registry {
90
+
91
+ /// Create an engine by name. This is the primary way to create engines for
92
+ /// "normal" backends.
93
+ std::unique_ptr<Engine> createEngine(AcceleratorConnection &conn,
94
+ const std::string &dmaEngineName,
95
+ AppIDPath idPath,
96
+ const ServiceImplDetails &details,
97
+ const HWClientDetails &clients);
98
+
99
+ namespace internal {
100
+
101
+ /// Engines can register themselves for pluggable functionality.
102
+ using EngineCreate = std::function<std::unique_ptr<Engine>(
103
+ AcceleratorConnection &conn, AppIDPath idPath,
104
+ const ServiceImplDetails &details, const HWClientDetails &clients)>;
105
+ void registerEngine(const std::string &name, EngineCreate create);
106
+
107
+ /// Helper struct to register engines.
108
+ template <typename TEngine>
109
+ struct RegisterEngine {
110
+ RegisterEngine(const char *name) { registerEngine(name, &TEngine::create); }
111
+ };
112
+
113
+ #define CONCAT_(prefix, suffix) prefix##suffix
114
+ #define CONCAT(prefix, suffix) CONCAT_(prefix, suffix)
115
+ #define REGISTER_ENGINE(Name, TEngine) \
116
+ static ::esi::registry::internal::RegisterEngine<TEngine> CONCAT( \
117
+ __register_engine__, __LINE__)(Name)
118
+
119
+ } // namespace internal
120
+ } // namespace registry
121
+
122
+ } // namespace esi
123
+
124
+ #endif // ESI_PORTS_H
@@ -35,15 +35,19 @@ namespace esi {
35
35
  class Logger {
36
36
  public:
37
37
  enum class Level {
38
- Debug, // Everything and the kitchen sink, possibly including _all_
39
- // messages written and read.
40
- Info, // General information, like connecting to an accelerator.
38
+ Trace, // Trace is even more detailed than debug and requires a compiler
39
+ // flag to be enabled when the runtime is built. Allows clients to do
40
+ // things like log every single message or interaction.
41
+ Debug, // Information useful when trying to debug an application.
42
+ Info, // General information, like connecting to an accelerator.
41
43
  Warning, // May indicate a problem.
42
44
  Error, // Many errors will be followed by exceptions which may get caught.
43
45
  };
44
- Logger(bool debugEnabled) : debugEnabled(debugEnabled) {}
46
+ Logger(bool debugEnabled, bool traceEnabled)
47
+ : debugEnabled(debugEnabled), traceEnabled(traceEnabled) {}
45
48
  virtual ~Logger() = default;
46
49
  bool getDebugEnabled() { return debugEnabled; }
50
+ bool getTraceEnabled() { return traceEnabled; }
47
51
 
48
52
  /// Report a log message.
49
53
  /// Arguments:
@@ -95,6 +99,35 @@ public:
95
99
  debugImpl(debugFunc);
96
100
  }
97
101
 
102
+ /// Log a trace message. If tracing is not enabled, this is a no-op. Since it
103
+ /// is inlined, the compiler will hopefully optimize it away creating a
104
+ /// zero-overhead call. This means that clients are free to go crazy with
105
+ /// trace messages.
106
+ inline void trace(const std::string &subsystem, const std::string &msg,
107
+ const std::map<std::string, std::any> *details = nullptr) {
108
+ #ifdef ESI_RUNTIME_TRACE
109
+ if (traceEnabled)
110
+ log(Level::Trace, subsystem, msg, details);
111
+ #endif
112
+ }
113
+ /// Log a trace message using a callback. Same as above, users can go hog-wild
114
+ /// calling this.
115
+ inline void
116
+ trace(std::function<
117
+ void(std::string &subsystem, std::string &msg,
118
+ std::unique_ptr<std::map<std::string, std::any>> &details)>
119
+ traceFunc) {
120
+ #ifdef ESI_RUNTIME_TRACE
121
+ if (!traceEnabled)
122
+ return;
123
+ std::string subsystem;
124
+ std::string msg;
125
+ std::unique_ptr<std::map<std::string, std::any>> details = nullptr;
126
+ traceFunc(subsystem, msg, details);
127
+ log(Level::Trace, subsystem, msg, details.get());
128
+ #endif
129
+ }
130
+
98
131
  protected:
99
132
  /// Overrideable version of debug. Only gets called if debug is enabled.
100
133
  virtual void debugImpl(const std::string &subsystem, const std::string &msg,
@@ -118,6 +151,9 @@ protected:
118
151
 
119
152
  /// Enable or disable debug messages.
120
153
  bool debugEnabled = false;
154
+
155
+ /// Enable or disable trace messages.
156
+ bool traceEnabled;
121
157
  };
122
158
 
123
159
  /// A thread-safe logger which calls functions implemented by subclasses. Only
@@ -147,8 +183,8 @@ public:
147
183
  /// Create a stream logger that logs to the given output stream and error
148
184
  /// output stream.
149
185
  StreamLogger(Level minLevel, std::ostream &out, std::ostream &error)
150
- : TSLogger(minLevel == Level::Debug), minLevel(minLevel), outStream(out),
151
- errorStream(error) {}
186
+ : TSLogger(minLevel <= Level::Debug, minLevel <= Level::Trace),
187
+ minLevel(minLevel), outStream(out), errorStream(error) {}
152
188
  /// Create a stream logger that logs to stdout, stderr.
153
189
  StreamLogger(Level minLevel);
154
190
  void logImpl(Level level, const std::string &subsystem,
@@ -165,10 +201,24 @@ private:
165
201
  std::ostream &errorStream;
166
202
  };
167
203
 
204
+ /// A logger that writes to the console. Includes color support.
205
+ class ConsoleLogger : public TSLogger {
206
+ public:
207
+ /// Create a stream logger that logs to stdout, stderr.
208
+ ConsoleLogger(Level minLevel);
209
+ void logImpl(Level level, const std::string &subsystem,
210
+ const std::string &msg,
211
+ const std::map<std::string, std::any> *details) override;
212
+
213
+ private:
214
+ /// The minimum log level to emit.
215
+ Level minLevel;
216
+ };
217
+
168
218
  /// A logger that does nothing.
169
219
  class NullLogger : public Logger {
170
220
  public:
171
- NullLogger() : Logger(false) {}
221
+ NullLogger() : Logger(false, false) {}
172
222
  void log(Level, const std::string &, const std::string &,
173
223
  const std::map<std::string, std::any> *) override {}
174
224
  };
@@ -65,8 +65,6 @@ private:
65
65
 
66
66
  } // namespace esi
67
67
 
68
- std::ostream &operator<<(std::ostream &os, const esi::AppID &id);
69
- std::ostream &operator<<(std::ostream &, const esi::AppIDPath &);
70
68
  std::ostream &operator<<(std::ostream &, const esi::ModuleInfo &);
71
69
 
72
70
  #endif // ESI_MANIFEST_H