37static std::unique_ptr<Context>
context =
nullptr;
38static std::unique_ptr<RpcServer>
server =
nullptr;
46 return fallbackLogger;
57 fprintf(
logFile,
"[ep: %50s to: %4s]", epId, toClient ?
"host" :
"sim");
60 for (
size_t i = 0; i < msgSize; ++i) {
63 if (i % 4 == 0 && i > 0)
66 if (i % 8 == 0 && i > 0)
77 const char *portEnv = getenv(
"COSIM_PORT");
78 if (portEnv ==
nullptr) {
80 "cosim",
"RPC server port not found. Letting RPC server select one");
84 std::format(
"Opening RPC server on port {}", portEnv));
85 return std::strtoull(portEnv,
nullptr, 10);
91 int expectedElemSize) {
93 getLogger().
error(
"cosim",
"DPI-C ERROR: passed array argument that "
94 "doesn't have expected 1D dimensions");
98 getLogger().
error(
"cosim",
"DPI-C ERROR: passed array argument that "
99 "doesn't have C layout (ptr==NULL)");
103 if (totalBytes == 0) {
104 getLogger().
error(
"cosim",
"DPI-C ERROR: passed array argument that "
105 "doesn't have C layout (total_bytes==0)");
108 int numElems =
svSize(data, 1);
109 int elemSize = numElems == 0 ? 0 : (totalBytes / numElems);
110 if (numElems * expectedElemSize != totalBytes) {
114 "DPI-C ERROR: passed array argument that doesn't have expected "
115 "element-size: expected={} actual={} numElems={} "
117 expectedElemSize, elemSize, numElems, totalBytes));
136 int fromHostTypeSize,
char *toHostTypeIdC,
137 int toHostTypeSize) {
140 std::string fromHostTypeId(fromHostTypeIdC), toHostTypeId(toHostTypeIdC);
143 if (!(fromHostTypeId.empty() ^ toHostTypeId.empty())) {
145 "cosim",
"Only one of fromHostTypeId and toHostTypeId can be set!");
153 if (!fromHostTypeId.empty()) {
155 server->registerReadPort(endpointId, fromHostTypeId);
162 server->registerWritePort(endpointId, toHostTypeId);
179 unsigned int *dataSize) {
183 auto portIt =
readPorts.find(endpointId);
190 std::future<MessageData> &f =
readFutures.at(&port);
192 if (f.wait_for(std::chrono::milliseconds(0)) != std::future_status::ready) {
199 log(endpointId,
false, msg);
206 std::format(
"DPI-func={} line={} event=invalid-sv-array",
207 __func__, __LINE__));
212 if (*dataSize == ~0u) {
217 std::format(
"DPI-func={} line={} event=invalid-size (max {})", __func__,
222 size_t msgSize = msg.
getSize();
223 if (msgSize > *dataSize) {
224 getLogger().
error(
"cosim",
"Message size too big to fit in HW buffer");
231 for (i = 0; i < msgSize; ++i) {
236 for (; i < *dataSize; ++i) {
256 std::format(
"DPI-func={} line={} event=invalid-sv-array",
257 __func__, __LINE__));
267 std::format(
"DPI-func={} line={} event=invalid-size limit={} array={}",
273 std::vector<uint8_t> dataVec(dataSize);
274 for (
int i = 0; i < dataSize; ++i) {
277 auto blob = std::make_unique<esi::MessageData>(dataVec);
285 log(endpointId,
true, *blob);
310 context = Context::withLogger<ConsoleLogger>(Logger::Level::Debug);
314 const char *logFN = getenv(
"COSIM_DEBUG_FILE");
315 if (logFN !=
nullptr) {
316 getLogger().
info(
"cosim", std::format(
"Opening debug log: {}", logFN));
338 std::format(
"DPI-func={} line={} event=invalid-sv-array",
339 __func__, __LINE__));
345 std::vector<uint8_t> blob(size);
346 for (
int i = 0; i < size; ++i) {
350 std::format(
"Setting manifest (esiVersion={}, size={})",
352 server->setManifest(esiVersion, blob);
364 getLogger().
error(
"cosim",
"DPI MMIO master already registered!");
384 assert(
false &&
"unimplemented");
396 assert(
false &&
"unimplemented");
assert(baseType &&"element must be base type")
static std::unique_ptr< RpcServer > server
std::map< std::string, ReadChannelPort & > readPorts
static FILE * logFile
If non-null, log to this file. Protected by 'serverMutex`.
DPI void sv2cCosimserverMMIOWriteRespond(char error)
std::map< std::string, WriteChannelPort & > writePorts
static int findPort()
Get the TCP port on which to listen.
DPI void sv2cCosimserverSetManifest(int esiVersion, const svOpenArrayHandle compressedManifest)
Set the system zlib-compressed manifest.
DPI int sv2cCosimserverMMIORegister()
Register an MMIO module. Just checks that there is only one instantiated.
static bool mmioRegistered
static void log(char *epId, bool toClient, const MessageData &msg)
Emit the contents of 'msg' to the log file in hex.
DPI void sv2cCosimserverFinish()
Shutdown the RPC server.
static int validateSvOpenArray(const svOpenArrayHandle data, int expectedElemSize)
Check that an array is an array of bytes and has some size.
static std::mutex serverMutex
static std::unique_ptr< Context > context
std::map< ReadChannelPort *, std::future< MessageData > > readFutures
DPI int sv2cCosimserverEpTryPut(char *endpointId, const svOpenArrayHandle data, int dataSize)
Send a message to a client.
DPI int sv2cCosimserverEpRegister(char *endpointId, char *fromHostTypeIdC, int fromHostTypeSize, char *toHostTypeIdC, int toHostTypeSize)
Register an endpoint.
DPI int sv2cCosimserverInit()
Start the server.
static Logger & getLogger()
Get the logger from the context.
DPI int sv2cCosimserverEpTryGet(char *endpointId, const svOpenArrayHandle data, unsigned int *dataSize)
Try to get a message from a client.
DPI int sv2cCosimserverMMIOWriteTryGet(uint32_t *address, uint32_t *data)
Write MMIO function pair.
DPI int sv2cCosimserverMMIOReadTryGet(uint32_t *address)
Read MMIO function pair.
DPI void sv2cCosimserverMMIOReadRespond(uint32_t data, char error)
int svSizeOfArray(const svOpenArrayHandle)
void * svGetArrElemPtr1(const svOpenArrayHandle, int indx1)
int svSize(const svOpenArrayHandle h, int d)
void * svGetArrayPtr(const svOpenArrayHandle)
int svDimensions(const svOpenArrayHandle h)
A logger that writes to the console. Includes color support.
virtual void error(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)
Report an error.
virtual void info(const std::string &subsystem, const std::string &msg, const std::map< std::string, std::any > *details=nullptr)
Report an informational message.
A logical chunk of data representing serialized data.
const uint8_t * getBytes() const
size_t getSize() const
Get the size of the data in bytes.
A ChannelPort which reads data from the accelerator.
virtual std::future< MessageData > readAsync()
Asynchronous read.
virtual void connect(std::function< bool(MessageData)> callback, const ConnectOptions &options={})
A ChannelPort which sends data to the accelerator.
void write(const MessageData &data)
A very basic blocking write API.
virtual void connect(const ConnectOptions &options={}) override
Set up a connection to the accelerator.
XXTERN typedef void * svOpenArrayHandle