41 fprintf(
logFile,
"[ep: %50s to: %4s]", epId, toClient ?
"host" :
"sim");
42 size_t msgSize = msg->size();
43 for (
size_t i = 0; i < msgSize; ++i) {
46 if (i % 4 == 0 && i > 0)
49 if (i % 8 == 0 && i > 0)
60 const char *portEnv = getenv(
"COSIM_PORT");
61 if (portEnv ==
nullptr) {
62 printf(
"[COSIM] RPC server port not found. Letting CapnpRPC select one\n");
65 printf(
"[COSIM] Opening RPC server on port %s\n", portEnv);
66 return std::strtoull(portEnv,
nullptr, 10);
72 int expectedElemSize) {
74 printf(
"DPI-C: ERROR passed array argument that doesn't have expected 1D "
79 printf(
"DPI-C: ERROR passed array argument that doesn't have C layout "
84 if (totalBytes == 0) {
85 printf(
"DPI-C: ERROR passed array argument that doesn't have C layout "
86 "(total_bytes==0)\n");
89 int numElems =
svSize(data, 1);
90 int elemSize = numElems == 0 ? 0 : (totalBytes / numElems);
91 if (numElems * expectedElemSize != totalBytes) {
92 printf(
"DPI-C: ERROR: passed array argument that doesn't have expected "
93 "element-size: expected=%d actual=%d numElems=%d totalBytes=%d\n",
94 expectedElemSize, elemSize, numElems, totalBytes);
105 int fromHostTypeSize,
char *toHostTypeId,
106 int toHostTypeSize) {
111 fromHostTypeSize, toHostTypeId,
126 unsigned int *dataSize) {
132 fprintf(stderr,
"Endpoint not found in registry!\n");
147 log(endpointId,
false, msg);
150 printf(
"ERROR: DPI-func=%s line=%d event=invalid-sv-array\n", __func__,
156 if (*dataSize == ~0u) {
159 printf(
"ERROR: DPI-func=%s line %d event=invalid-size (max %d)\n", __func__,
164 size_t msgSize = msg->size();
165 if (msgSize > *dataSize) {
166 printf(
"ERROR: Message size too big to fit in HW buffer\n");
172 for (i = 0; i < msgSize; ++i) {
177 for (; i < *dataSize; ++i) {
181 *dataSize = msg->size();
196 printf(
"ERROR: DPI-func=%s line=%d event=invalid-sv-array\n", __func__,
205 printf(
"ERROR: DPI-func=%s line %d event=invalid-size limit %d array %d\n",
212 for (
int i = 0; i < dataSize; ++i) {
218 fprintf(stderr,
"Endpoint not found in registry!\n");
221 log(endpointId,
true, blob);
230 printf(
"[cosim] Tearing down RPC server.\n");
246 const char *logFN = getenv(
"COSIM_DEBUG_FILE");
247 if (logFN !=
nullptr) {
248 printf(
"[cosim] Opening debug log: %s\n", logFN);
253 printf(
"[cosim] Starting RPC server.\n");
269 printf(
"ERROR: DPI-func=%s line=%d event=invalid-sv-array\n", __func__,
276 std::vector<uint8_t> blob(size);
277 for (
int i = 0; i < size; ++i) {
280 printf(
"[cosim] Setting manifest (esiVersion=%d, size=%d)\n", esiVersion,
290 printf(
"ERROR: DPI MMIO master already registered!");
301 if (!reqAddress.has_value())
303 *address = reqAddress.value();
311 printf(
"ERROR: More read responses than requests! Not queuing response.\n");
322 "ERROR: More write responses than requests! Not queuing response.\n");
332 if (!req.has_value())
334 *address = req.value().first;
335 *data = req.value().second;
assert(baseType &&"element must be base type")
static FILE * logFile
If non-null, log to this file. Protected by 'serverMutex`.
DPI void sv2cCosimserverMMIOWriteRespond(char error)
static int findPort()
Get the TCP port on which to listen.
DPI int sv2cCosimserverMMIORegister()
Register an MMIO module. Just checks that there is only one instantiated.
static bool mmioRegistered
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 RpcServer * server
DPI int sv2cCosimserverEpRegister(char *endpointId, char *fromHostTypeId, int fromHostTypeSize, char *toHostTypeId, int toHostTypeSize)
Register an endpoint.
static void log(char *epId, bool toClient, const Endpoint::BlobPtr &msg)
Emit the contents of 'msg' to the log file in hex.
static std::mutex serverMutex
DPI int sv2cCosimserverEpTryPut(char *endpointId, const svOpenArrayHandle data, int dataSize)
Send a message to a client.
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)
DPI void sv2cCosimserverSetManifest(unsigned int esiVersion, const svOpenArrayHandle compressedManifest)
Set the system zlib-compressed manifest.
bool registerEndpoint(std::string epId, std::string fromHostTypeId, int sendTypeMaxSize, std::string toHostTypeId, int recvTypeMaxSize)
Register an Endpoint.
Implements a bi-directional, thread-safe bridge between the RPC server and DPI functions.
void pushMessageToClient(BlobPtr msg)
Queue message to the RPC client.
std::unique_ptr< Blob > BlobPtr
bool getMessageToSim(BlobPtr &msg)
Pop from the to-simulator queue.
TSQueue< uint32_t > readReqs
std::atomic< unsigned > writesOutstanding
TSQueue< std::pair< uint64_t, uint8_t > > readResps
TSQueue< uint8_t > writeResps
std::atomic< unsigned > readsOutstanding
TSQueue< std::pair< uint32_t, uint64_t > > writeReqs
void setManifest(unsigned int esiVersion, const std::vector< uint8_t > &manifest)
EndpointRegistry endpoints
void stop()
Signal the RPC server thread to stop. Wait for it to exit.
void run(uint16_t port)
Start and stop the server thread.
void push(E... t)
Push onto the queue.
std::optional< T > pop()
Pop something off the queue but return nullopt if the queue is empty.
XXTERN int svSizeOfArray(const svOpenArrayHandle)
XXTERN void * svGetArrElemPtr1(const svOpenArrayHandle, int indx1)
XXTERN int svDimensions(const svOpenArrayHandle h)
XXTERN int svSize(const svOpenArrayHandle h, int d)
XXTERN void * svGetArrayPtr(const svOpenArrayHandle)
XXTERN typedef void * svOpenArrayHandle