From 29859acc34d181442050adf98514021fbad752f2 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 4 Mar 2012 19:17:03 +0100 Subject: [PATCH] sim: two way IPC working --- migen/sim/ipc.py | 50 ++++++++++++----- vpi/ipc.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++ vpi/ipc.h | 19 +++++++ 3 files changed, 196 insertions(+), 13 deletions(-) create mode 100644 vpi/ipc.c create mode 100644 vpi/ipc.h diff --git a/migen/sim/ipc.py b/migen/sim/ipc.py index ad89ce111..7e80fc860 100644 --- a/migen/sim/ipc.py +++ b/migen/sim/ipc.py @@ -10,6 +10,14 @@ class Message: for parameter, value in zip(self.parameters, pvalues): assert(isinstance(value, parameter[0])) setattr(self, parameter[1], value) + + def __str__(self): + p = "" + for parameter in self.parameters: + p += parameter[1] + "=" + str(getattr(self, parameter[1])) + if p: + p = " " + p + return "<" + self.__class__.__name__ + p + ">" class MessageTick(Message): code = 0 @@ -21,11 +29,11 @@ class MessageGo(Message): class MessageWrite(Message): code = 2 - parameters = [(str, "signal"), (int, "value")] + parameters = [(str, "name"), (int, "value")] class MessageRead(Message): code = 3 - parameters = [(str, "signal")] + parameters = [(str, "name")] class MessageReadReply(Message): code = 4 @@ -38,16 +46,21 @@ message_classes = [MessageTick, MessageGo, MessageWrite, MessageRead, MessageRea # def _pack_int(v): - # TODO - return [] + p = [] + while v != 0: + p.append(v & 0xff) + v >>= 8 + p.insert(0, len(p)) + return p def _pack_str(v): - # TODO - return [] + p = [ord(c) for c in v] + p.append(0) + return p def _pack(message): r = [message.code] - for p, t in message.parameters: + for t, p in message.parameters: value = getattr(message, p) assert(isinstance(value, t)) if t == int: @@ -63,19 +76,28 @@ def _pack(message): # def _unpack_int(i): - # TODO - return 0 + v = 0 + power = 1 + nchunks = next(i) + for j in range(nchunks): + v += power*next(i) + power *= 256 + return v def _unpack_str(i): - # TODO - return "" + v = "" + c = next(i) + while c: + v += chr(c) + c = next(i) + return v def _unpack(message): i = iter(message) code = next(i) msgclass = next(filter(lambda x: x.code == code, message_classes)) pvalues = [] - for p, t in msgclass.parameters: + for t, p in msgclass.parameters: if t == int: v = _unpack_int(i) elif t == str: @@ -113,8 +135,10 @@ class Initiator: self.conn.send(_pack(message)) def recv(self): - maxlen = 4096 + maxlen = 2048 packet = self.conn.recv(maxlen) + if len(packet) < 1: + return None if len(packet) >= maxlen: raise PacketTooLarge return _unpack(packet) diff --git a/vpi/ipc.c b/vpi/ipc.c new file mode 100644 index 000000000..9b3e5299c --- /dev/null +++ b/vpi/ipc.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ipc.h" + +struct ipc_softc { + int socket; + go_handler h_go; + write_handler h_write; + read_handler h_read; + void *user; +}; + +struct ipc_softc *ipc_connect(const char *sockaddr, + go_handler h_go, write_handler h_write, read_handler h_read, void *user) +{ + struct ipc_softc *sc; + struct sockaddr_un addr; + + 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; + + 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) { + close(sc->socket); + free(sc); + return NULL; + } + + return sc; +} + +void ipc_destroy(struct ipc_softc *sc) +{ + close(sc->socket); + free(sc); +} + +enum { + MESSAGE_TICK = 0, + MESSAGE_GO, + MESSAGE_WRITE, + MESSAGE_READ, + MESSAGE_READ_REPLY +}; + +#define MAX_LEN 2048 + +int ipc_receive(struct ipc_softc *sc) +{ + char buffer[MAX_LEN]; + ssize_t l; + int i; + + l = recv(sc->socket, buffer, MAX_LEN, 0); + if((l <= 0) || (l >= MAX_LEN)) + return 0; + + i = 0; + switch(buffer[i++]) { + case MESSAGE_GO: + assert(l == 1); + return sc->h_go(sc->user); + case MESSAGE_WRITE: { + char *name; + int nchunks; + unsigned char *chunks; + + name = &buffer[i]; + i += strlen(name) + 1; + assert(i < l); + nchunks = buffer[i++]; + assert(i + nchunks == l); + chunks = (unsigned char *)&buffer[i]; + + return sc->h_write(name, nchunks, chunks, sc->user); + } + case MESSAGE_READ: { + char *name; + + name = &buffer[i]; + i += strlen(name) + 1; + assert(i == l); + + return sc->h_read(name, sc->user); + } + default: + return 0; + } +} + +int ipc_tick(struct ipc_softc *sc) +{ + char c; + ssize_t l; + + c = MESSAGE_TICK; + l = send(sc->socket, &c, 1, 0); + if(l != 1) + return 0; + return 1; +} + +int ipc_read_reply(struct ipc_softc *sc, int nchunks, const unsigned char *chunks) +{ + int len; + char buffer[MAX_LEN]; + ssize_t l; + + len = nchunks + 2; + assert(len < MAX_LEN); + assert(nchunks < 256); + + buffer[0] = MESSAGE_READ_REPLY; + buffer[1] = nchunks; + memcpy(&buffer[2], chunks, nchunks); + + l = send(sc->socket, buffer, len, 0); + if(l != len) + return 0; + return 1; +} diff --git a/vpi/ipc.h b/vpi/ipc.h new file mode 100644 index 000000000..ba07ede5f --- /dev/null +++ b/vpi/ipc.h @@ -0,0 +1,19 @@ +#ifndef __IPC_H +#define __IPC_H + +struct ipc_softc; + +typedef int(*go_handler)(void *); +typedef int(*write_handler)(char *, int, const unsigned char *, void *); +typedef int(*read_handler)(char *, void *); + +struct ipc_softc *ipc_connect(const char *sockaddr, + go_handler h_go, write_handler h_write, read_handler h_read, void *user); +void ipc_destroy(struct ipc_softc *sc); + +int ipc_receive(struct ipc_softc *sc); + +int ipc_tick(struct ipc_softc *sc); +int ipc_read_reply(struct ipc_softc *sc, int nchunks, const unsigned char *value); + +#endif /* __IPC_H */