32 static std::unique_ptr<RpcServer>
server =
nullptr;
43 fprintf(
logFile,
"[ep: %50s to: %4s]", epId, toClient ?
"host" :
"sim");
46 for (
size_t i = 0; i < msgSize; ++i) {
49 if (i % 4 == 0 && i > 0)
52 if (i % 8 == 0 && i > 0)
63 const char *portEnv = getenv(
"COSIM_PORT");
64 if (portEnv ==
nullptr) {
66 "[COSIM] RPC server port not found. Letting RPC server select one\n");
69 printf(
"[COSIM] Opening RPC server on port %s\n", portEnv);
70 return std::strtoull(portEnv,
nullptr, 10);
76 int expectedElemSize) {
78 printf(
"DPI-C: ERROR passed array argument that doesn't have expected 1D "
83 printf(
"DPI-C: ERROR passed array argument that doesn't have C layout "
88 if (totalBytes == 0) {
89 printf(
"DPI-C: ERROR passed array argument that doesn't have C layout "
90 "(total_bytes==0)\n");
93 int numElems =
svSize(data, 1);
94 int elemSize = numElems == 0 ? 0 : (totalBytes / numElems);
95 if (numElems * expectedElemSize != totalBytes) {
96 printf(
"DPI-C: ERROR: passed array argument that doesn't have expected "
97 "element-size: expected=%d actual=%d numElems=%d totalBytes=%d\n",
98 expectedElemSize, elemSize, numElems, totalBytes);
109 std::map<ReadChannelPort *, std::future<MessageData>>
readFutures;
117 int fromHostTypeSize,
char *toHostTypeIdC,
118 int toHostTypeSize) {
121 std::string fromHostTypeId(fromHostTypeIdC), toHostTypeId(toHostTypeIdC);
124 if (!(fromHostTypeId.empty() ^ toHostTypeId.empty())) {
125 printf(
"ERROR: Only one of fromHostTypeId and toHostTypeId can be set!\n");
129 printf(
"ERROR: Endpoint already registered!\n");
133 if (!fromHostTypeId.empty()) {
135 server->registerReadPort(endpointId, fromHostTypeId);
140 server->registerWritePort(endpointId, toHostTypeId));
154 unsigned int *dataSize) {
158 auto portIt =
readPorts.find(endpointId);
160 fprintf(stderr,
"Endpoint not found in registry!\n");
165 std::future<MessageData> &f =
readFutures.at(&port);
167 if (f.wait_for(std::chrono::milliseconds(0)) != std::future_status::ready) {
174 log(endpointId,
false, msg);
180 printf(
"ERROR: DPI-func=%s line=%d event=invalid-sv-array\n", __func__,
186 if (*dataSize == ~0u) {
189 printf(
"ERROR: DPI-func=%s line %d event=invalid-size (max %d)\n", __func__,
194 size_t msgSize = msg.
getSize();
195 if (msgSize > *dataSize) {
196 printf(
"ERROR: Message size too big to fit in HW buffer\n");
203 for (i = 0; i < msgSize; ++i) {
208 for (; i < *dataSize; ++i) {
227 printf(
"ERROR: DPI-func=%s line=%d event=invalid-sv-array\n", __func__,
236 printf(
"ERROR: DPI-func=%s line %d event=invalid-size limit %d array %d\n",
242 std::vector<uint8_t> dataVec(dataSize);
243 for (
int i = 0; i < dataSize; ++i) {
246 auto blob = std::make_unique<esi::MessageData>(dataVec);
251 fprintf(stderr,
"Endpoint not found in registry!\n");
254 log(endpointId,
true, *blob);
264 printf(
"[cosim] Tearing down RPC server.\n");
280 const char *logFN = getenv(
"COSIM_DEBUG_FILE");
281 if (logFN !=
nullptr) {
282 printf(
"[cosim] Opening debug log: %s\n", logFN);
287 printf(
"[cosim] Starting RPC server.\n");
288 server = std::make_unique<RpcServer>();
303 printf(
"ERROR: DPI-func=%s line=%d event=invalid-sv-array\n", __func__,
310 std::vector<uint8_t> blob(size);
311 for (
int i = 0; i < size; ++i) {
314 printf(
"[cosim] Setting manifest (esiVersion=%d, size=%d)\n", esiVersion,
316 server->setManifest(esiVersion, blob);
328 printf(
"ERROR: DPI MMIO master already registered!");
348 assert(
false &&
"unimplemented");
360 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
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.
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)
int svDimensions(const svOpenArrayHandle h)
void * svGetArrayPtr(const svOpenArrayHandle)
A logical chunk of data representing serialized data.
size_t getSize() const
Get the size of the data in bytes.
const uint8_t * getBytes() const
A ChannelPort which reads data from the accelerator.
virtual std::future< MessageData > readAsync()
Asynchronous read.
A ChannelPort which sends data to the accelerator.
virtual void write(const MessageData &)=0
A very basic blocking write API.
XXTERN typedef void * svOpenArrayHandle