import warnings
+import sys
from migen.fhdl.std import *
from migen.fhdl.structure import _Fragment
self.ios = {cd.clk, cd.rst}
def get(self, sockaddr):
+ if sys.platform == "win32":
+ sockaddr = sockaddr[0] # Get the IP address only
+
template1 = """`timescale 1ns / 1ps
module {top_name}();
if sim_runner is None:
sim_runner = icarus.Runner()
self.top_level = top_level
- self.ipc = Initiator(sockaddr)
+ if sys.platform == "win32":
+ sockaddr = ("127.0.0.1", 50007)
+ self.ipc = Initiator(sockaddr)
+ else:
+ self.ipc = Initiator(sockaddr)
+
self.sim_runner = sim_runner
c_top = self.top_level.get(sockaddr)
def run_simulation(fragment, ncycles=None, vcd_name=None, **kwargs):
with Simulator(fragment, TopLevel(vcd_name), icarus.Runner(**kwargs)) as s:
s.run(ncycles)
+
import socket
import os
+import sys
+import struct
+
#
# Message classes
#
-
class Int32(int):
pass
message_classes = [MessageTick, MessageGo, MessageWrite, MessageRead, MessageReadReply]
+
#
# Packing
#
-
def _pack_int(v):
if v == 0:
p = [1, 0]
return p
+def _pack_int16(v):
+ return [v & 0xff,
+ (v & 0xff00) >> 8]
+
+
def _pack_int32(v):
return [
v & 0xff,
r += _pack_int32(value)
else:
raise TypeError
+ if sys.platform == "win32":
+ size = _pack_int16(len(r) + 2) # size specifier adds to size
+ r = size + r
return bytes(r)
+
#
# Unpacking
#
-
def _unpack_int(i, nchunks=None):
v = 0
power = 1
pvalues.append(v)
return msgclass(*pvalues)
+
#
# I/O
#
-
class PacketTooLarge(Exception):
pass
class Initiator:
def __init__(self, sockaddr):
self.sockaddr = sockaddr
- self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
- self._cleanup_file()
+ if sys.platform == "win32":
+ self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ else:
+ self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
+ self._cleanup_file()
self.socket.bind(self.sockaddr)
self.socket.listen(1)
def recv(self):
maxlen = 2048
- packet = self.conn.recv(maxlen)
- if len(packet) < 1:
- return None
- if len(packet) >= maxlen:
- raise PacketTooLarge
+ if sys.platform == "win32":
+ packet = self.conn.recv(maxlen)
+ if len(packet) < 1:
+ return None
+ if len(packet) >= maxlen:
+ raise PacketTooLarge
+ expected_size = struct.unpack("<H", packet[:2])[0]
+
+ # If full packet wasn't received, keep waiting!
+ if len(packet) < expected_size:
+ packet_frag = self.conn.recv(maxlen)
+ packet += packet_frag
+ if len(packet_frag) < 1:
+ return None
+ if len(packet) >= maxlen:
+ raise PacketTooLarge
+
+ # Discard the length from the packet - it's not needed anymore.
+ packet = packet[2:]
+ else:
+ packet = self.conn.recv(maxlen)
+ if len(packet) < 1:
+ return None
+ if len(packet) >= maxlen:
+ raise PacketTooLarge
return _unpack(packet)
def close(self):
self.conn.shutdown(socket.SHUT_RDWR)
self.conn.close()
if hasattr(self, "socket"):
- self.socket.shutdown(socket.SHUT_RDWR)
- self.socket.close()
- self._cleanup_file()
+ if sys.platform == "win32":
+ # self.socket.shutdown(socket.SHUT_RDWR)
+ # Fails with WinError 10057:
+ # A request to send or receive data was disallowed because the
+ # socket is not connected and (when sending on a datagram
+ # socket using a sendto call) no address was supplied
+ # This error will cascade into WinError 10038, where
+ # Simulator.__exit__ didn't finish cleaning up and left an
+ # invalid socket.
+ self.socket.close()
+ else:
+ self.socket.shutdown(socket.SHUT_RDWR)
+ self.socket.close()
+ self._cleanup_file()
#include <assert.h>
#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#define WIN_SOCKET_PORT "50007"
+#else
+#include <sys/socket.h>
+#include <sys/un.h>
+#endif
+
+
#include "ipc.h"
struct ipc_softc {
go_handler h_go, write_handler h_write, read_handler h_read, void *user)
{
struct ipc_softc *sc;
+#ifdef _WIN32
+ struct addrinfo hints, *my_addrinfo;
+ WSADATA wsaData;
+#else
struct sockaddr_un addr;
-
+#endif
+
sc = malloc(sizeof(struct ipc_softc));
if(!sc) return NULL;
-
+
sc->h_go = h_go;
sc->h_write = h_write;
sc->h_read = h_read;
sc->user = user;
-
+
+#ifdef _WIN32
+ /* Initialize Winsock. */
+ if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
+ free(sc);
+ return NULL;
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ if(getaddrinfo(sockaddr, WIN_SOCKET_PORT, NULL, &my_addrinfo) != 0) {
+ free(sc);
+ return NULL;
+ }
+
+ sc->socket = socket(AF_INET, SOCK_STREAM, 0);
+ if(sc->socket < 0) {
+ free(sc);
+ return NULL;
+ }
+
+ if(connect(sc->socket, my_addrinfo->ai_addr, my_addrinfo->ai_addrlen) != 0) {
+ close(sc->socket);
+ free(sc);
+ return NULL;
+ }
+#else
sc->socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if(sc->socket < 0) {
free(sc);
return NULL;
}
-
+
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, sockaddr);
if(connect(sc->socket, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
free(sc);
return NULL;
}
-
+#endif
+
return sc;
}
{
close(sc->socket);
free(sc);
+#ifdef _WIN32
+ WSACleanup();
+#endif
}
enum {
int ipc_receive(struct ipc_softc *sc)
{
unsigned char buffer[MAX_LEN];
- ssize_t l;
+ ssize_t l = 0;
int i;
-
+#ifdef _WIN32
+ int expected_num;
+ int received_num = 0;
+#endif
+
+#ifdef _WIN32
+ /* Initial recv. Includes a length identifier so that we wait
+ * until a full message is received. The length of the message
+ * includes the length identifier. */
+ while(received_num < 2) {
+ /* Ensure we wait to get the packet length,
+ * which requires two bytes, before continuing. */
+ received_num = recv(sc->socket, (char *)&buffer[l], \
+ (MAX_LEN - received_num), 0);
+ l += received_num;
+
+ if(received_num == 0)
+ return 2;
+ if((received_num < 0) || (received_num >= MAX_LEN) || \
+ (l >= MAX_LEN))
+ return 0;
+ }
+
+ expected_num = ((buffer[1] << 8) | (buffer[0]));
+ while(l < expected_num) {
+ /* received_num will never exceed MAX_LEN, unless
+ * recv is broken. */
+ received_num = recv(sc->socket, (char *)&buffer[l], \
+ (MAX_LEN - received_num), 0);
+ l += received_num;
+
+ if(received_num == 0)
+ return 2;
+ if((received_num < 0) || (received_num >= MAX_LEN) || \
+ (l >= MAX_LEN))
+ return 0;
+ } /* l is assumed to have the message length
+ * in the message unpacking code. */
+ i = 2; /* Skip the length identifier. */
+#else
+ /* On Unix, SOCK_SEQPACKET will take care of ensuring message
+ * boundaries are satisfied. */
l = recv(sc->socket, buffer, MAX_LEN, 0);
if(l == 0)
return 2;
if((l < 0) || (l >= MAX_LEN))
return 0;
-
- i = 0;
+ i = 0; /* No length identifier, so we care about the entire buffer */
+#endif
+
switch(buffer[i++]) {
case MESSAGE_GO:
- assert(l == 1);
+ assert((l - i) == 0);
+
return sc->h_go(sc->user);
case MESSAGE_WRITE: {
char *name;
int nchunks;
unsigned char *chunks;
unsigned int chunk_index;
-
+
name = (char *)&buffer[i];
i += strlen(name) + 1;
assert((i+4) < l);
nchunks = buffer[i++];
assert(i + nchunks == l);
chunks = (unsigned char *)&buffer[i];
-
+
return sc->h_write(name, chunk_index, nchunks, chunks, sc->user);
}
case MESSAGE_READ: {
char *name;
unsigned int name_index;
-
+
name = (char *)&buffer[i];
i += strlen(name) + 1;
assert((i+4) == l);
name_index = buffer[i] | buffer[i+1] << 8 | buffer[i+2] << 16 | buffer[i+3] << 24;
-
+
return sc->h_read(name, name_index, sc->user);
}
default:
int ipc_tick(struct ipc_softc *sc)
{
- char c;
ssize_t l;
-
+
+#ifdef _WIN32
+ char c[3];
+
+ c[0] = 3;
+ c[1] = 0;
+ c[2] = MESSAGE_TICK;
+ l = send(sc->socket, c, 3, 0);
+ if(l != 3)
+ return 0;
+#else
+ char c;
+
c = MESSAGE_TICK;
l = send(sc->socket, &c, 1, 0);
if(l != 1)
return 0;
+#endif
+
return 1;
}
int len;
char buffer[MAX_LEN];
ssize_t l;
-
+
+#ifdef _WIN32
+ len = nchunks + 4;
+ assert(len < MAX_LEN);
+ assert(nchunks < 256);
+
+ buffer[0] = len & 0xFF;
+ buffer[1] = (0xFF00 & len) >> 8;
+ buffer[2] = MESSAGE_READ_REPLY;
+ buffer[3] = nchunks;
+ memcpy(&buffer[4], chunks, nchunks);
+#else
len = nchunks + 2;
assert(len < MAX_LEN);
assert(nchunks < 256);
-
+
buffer[0] = MESSAGE_READ_REPLY;
buffer[1] = nchunks;
memcpy(&buffer[2], chunks, nchunks);
-
+#endif
+
l = send(sc->socket, buffer, len, 0);
if(l != len)
return 0;
return 1;
}
+