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) {
201 server->messageConsumed(port);
202 log(endpointId,
false, msg);
209 std::format(
"DPI-func={} line={} event=invalid-sv-array",
210 __func__, __LINE__));
215 if (*dataSize == ~0u) {
220 std::format(
"DPI-func={} line={} event=invalid-size (max {})", __func__,
225 size_t msgSize = msg.
getSize();
226 if (msgSize > *dataSize) {
227 getLogger().
error(
"cosim",
"Message size too big to fit in HW buffer");
234 for (i = 0; i < msgSize; ++i) {
239 for (; i < *dataSize; ++i) {
260 std::format(
"DPI-func={} line={} event=invalid-sv-array",
261 __func__, __LINE__));
271 std::format(
"DPI-func={} line={} event=invalid-size limit={} array={}",
277 std::vector<uint8_t> dataVec(dataSize);
278 for (
int i = 0; i < dataSize; ++i) {
281 auto blob = std::make_unique<esi::MessageData>(dataVec);
294 log(endpointId,
true, *blob);
321 const char *logFN = getenv(
"COSIM_DEBUG_FILE");
322 if (logFN !=
nullptr) {
323 getLogger().
info(
"cosim", std::format(
"Opening debug log: {}", logFN));
345 std::format(
"DPI-func={} line={} event=invalid-sv-array",
346 __func__, __LINE__));
352 std::vector<uint8_t> blob(size);
353 for (
int i = 0; i < size; ++i) {
357 std::format(
"Setting manifest (esiVersion={}, size={})",
359 server->setManifest(esiVersion, blob);
371 getLogger().
error(
"cosim",
"DPI MMIO master already registered!");
391 assert(
false &&
"unimplemented");
403 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)
A logger that writes to the console. Includes color support.
static std::unique_ptr< Context > withLogger(Args &&...args)
Create a context with a specific logger type.
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 concrete flat message backed by a single vector of bytes.
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 void connect(ReadCallback callback, const ConnectOptions &options={})
virtual std::future< MessageData > readAsync()
Asynchronous polling read.
A ChannelPort which sends data to the accelerator.
bool tryWrite(const MessageData &data)
A basic non-blocking write API.
virtual void connect(const ConnectOptions &options={}) override
Set up a connection to the accelerator.
XXTERN int svSizeOfArray(const svOpenArrayHandle)
XXTERN int svDimensions(const svOpenArrayHandle h)
XXTERN void * svGetArrElemPtr1(const svOpenArrayHandle, int indx1)
XXTERN int svSize(const svOpenArrayHandle h, int d)
XXTERN void * svGetArrayPtr(const svOpenArrayHandle)
XXTERN typedef void * svOpenArrayHandle