mibuild/sim: remove server and interact with tap directly in cpp tb. for now: - need...
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 9 Mar 2015 12:17:21 +0000 (13:17 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 9 Mar 2015 12:30:21 +0000 (13:30 +0100)
mibuild/sim/ethernet_tb.cpp [new file with mode: 0644]
mibuild/sim/server.py [deleted file]
mibuild/sim/server_tb.cpp [deleted file]

diff --git a/mibuild/sim/ethernet_tb.cpp b/mibuild/sim/ethernet_tb.cpp
new file mode 100644 (file)
index 0000000..084cf13
--- /dev/null
@@ -0,0 +1,296 @@
+// This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
+// License: BSD
+#include "Vdut.h"
+#include "verilated.h"
+#include "verilated_vcd_c.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <sys/poll.h>
+
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+int trace = 0;
+
+vluint64_t main_time = 0;
+double sc_time_stamp()
+{
+       return main_time;
+}
+
+/* ios */
+
+/* Terminal functions */
+struct termios orig_termios;
+
+void reset_terminal_mode(void)
+{
+       tcsetattr(0, TCSANOW, &orig_termios);
+}
+
+void set_conio_terminal_mode(void)
+{
+       struct termios new_termios;
+
+       /* take two copies - one for now, one for later */
+       tcgetattr(0, &orig_termios);
+       memcpy(&new_termios, &orig_termios, sizeof(new_termios));
+
+       /* register cleanup handler, and set the new terminal mode */
+       atexit(reset_terminal_mode);
+       cfmakeraw(&new_termios);
+       tcsetattr(0, TCSANOW, &new_termios);
+}
+
+int kbhit(void)
+{
+       struct timeval tv = { 0L, 0L };
+       fd_set fds;
+       FD_ZERO(&fds);
+       FD_SET(0, &fds);
+       return select(1, &fds, NULL, NULL, &tv);
+}
+
+int getch(void)
+{
+       int r;
+       unsigned char c;
+       if ((r = read(0, &c, sizeof(c))) < 0) {
+               return r;
+       } else {
+               return c;
+       }
+}
+
+/* Ethernet functions */
+/* create tap:
+     openvpn --mktun --dev tap0
+     ifconfig tap0 192.168.0.14 up
+     mknod /dev/net/tap0 c 10 200
+   delete tap:
+     openvpn --rmtun --dev tap0 */
+
+unsigned char eth_txbuffer[1532];
+unsigned char eth_rxbuffer[1532];
+int eth_txbuffer_len = 0;
+int eth_rxbuffer_len = 0;
+int eth_rxbuffer_pos = 0;
+
+struct eth_device
+{
+       char *dev;
+       char *tap;
+       int fd;
+};
+
+void eth_open(struct eth_device *eth)
+{
+
+       struct ifreq ifr;
+       eth->fd = open (eth->dev, O_RDWR);
+       if(eth->fd < 0) {
+               fprintf (stderr, " Could not open dev %s\n", eth->dev);
+               return;
+       }
+
+       memset (&ifr, 0, sizeof(ifr));
+       ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+       strncpy (ifr.ifr_name, eth->tap, IFNAMSIZ);
+
+       if (ioctl (eth->fd, TUNSETIFF, (void *) &ifr) < 0) {
+               fprintf (stderr, " Could not set %s\n", eth->tap);
+               close(eth->fd);
+       }
+       return;
+}
+
+int eth_close(struct eth_device *eth)
+{
+       if (eth->fd < 0)
+               close(eth->fd);
+}
+
+void eth_write_tap(
+       struct eth_device *eth,
+       unsigned char *buf,
+       unsigned long int length)
+{
+       write (eth->fd, buf, length);
+}
+
+int eth_read_tap (
+       struct eth_device *eth,
+       unsigned char *buf)
+{
+
+       struct pollfd fds[1];
+       int n;
+       int length;
+
+       fds[0].fd = eth->fd;
+       fds[0].events = POLLIN;
+
+       n = poll(fds, 1, 0);
+       if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN)) {
+               length = read(eth->fd, buf, 1532);
+       } else {
+               length = 0;
+       }
+       return length;
+}
+
+Vdut* dut;
+VerilatedVcdC* tfp;
+
+#define MAX_LEN 2048
+
+struct sim {
+       bool run;
+
+       unsigned int tick;
+       clock_t start;
+       clock_t end;
+       float speed;
+
+       char txbuffer[MAX_LEN];
+       char rxbuffer[MAX_LEN];
+
+       char rx_serial_stb;
+       char rx_serial_data;
+       char rx_serial_presented;
+};
+
+int console_service(struct sim *s)
+{
+       /* fpga --> console */
+       SERIAL_SOURCE_ACK = 1;
+       if(SERIAL_SOURCE_STB == 1) {
+               if (SERIAL_SOURCE_DATA == '\n')
+                       putchar('\r');
+               putchar(SERIAL_SOURCE_DATA);
+               fflush(stdout);
+       }
+
+       /* console --> fpga */
+       SERIAL_SINK_STB = 0;
+       if (s->tick%(1000) == 0) {
+               if(kbhit()) {
+                       char c = getch();
+                       if (c == 27 && !kbhit()) {
+                               printf("\r\n");
+                               return -1;
+                       } else {
+                               SERIAL_SINK_STB = 1;
+                               SERIAL_SINK_DATA = c;
+                       }
+               }
+       }
+       return 0;
+}
+
+#ifdef ETH_SOURCE_STB
+int eth_last_source_stb = 0;
+
+int ethernet_service(struct eth_device *eth) {
+       /* fpga --> tap */
+       ETH_SOURCE_ACK = 1;
+       if(ETH_SOURCE_STB == 1) {
+               eth_txbuffer[eth_txbuffer_len] = ETH_SOURCE_DATA;
+               eth_txbuffer_len++;
+       } else {
+               if (eth_last_source_stb) {
+                       eth_write_tap(eth, eth_txbuffer, eth_txbuffer_len-1); // XXX FIXME software or gateware?
+                       eth_txbuffer_len = 0;
+               }
+       }
+       eth_last_source_stb = ETH_SOURCE_STB;
+
+       /* tap --> fpga */
+       if (eth_rxbuffer_len == 0) {
+               ETH_SINK_STB = 0;
+               eth_rxbuffer_pos = 0;
+               eth_rxbuffer_len = eth_read_tap(eth, eth_rxbuffer);
+       } else {
+               if (eth_rxbuffer_pos < MAX(eth_rxbuffer_len, 60)) {
+                       ETH_SINK_STB = 1;
+                       ETH_SINK_DATA = eth_rxbuffer[eth_rxbuffer_pos];
+                       eth_rxbuffer_pos++;
+               } else {
+                       ETH_SINK_STB = 0;
+                       eth_rxbuffer_len = 0;
+                       memset(eth_rxbuffer, 0, 1532);
+               }
+       }
+}
+#endif
+
+void sim_tick(struct sim *s)
+{
+       SYS_CLK = s->tick%2;
+       dut->eval();
+       if (trace)
+               tfp->dump(s->tick);
+       s->tick++;
+}
+
+void sim_init(struct sim *s)
+{
+       int i;
+       s->tick = 0;
+#ifdef SYS_RST
+       SYS_RST = 1;
+       SYS_CLK = 0;
+       for (i=0; i<8; i++)
+               sim_tick(s);
+       SYS_RST = 0;
+#endif
+       s->start = clock();
+}
+
+int main(int argc, char **argv, char **env)
+{
+       Verilated::commandArgs(argc, argv);
+       dut = new Vdut;
+
+       Verilated::traceEverOn(true);
+       tfp = new VerilatedVcdC;
+       dut->trace(tfp, 99);
+       tfp->open("dut.vcd");
+
+       struct sim s;
+       sim_init(&s);
+
+       struct eth_device eth;
+       char dev[] = "/dev/net/tap0";
+       char tap[] = "tap0";
+       eth.dev = dev;
+       eth.tap = tap;
+       eth_open(&eth);
+
+       s.run = true;
+       while(s.run) {
+               sim_tick(&s);
+               if (SYS_CLK) {
+                       if (console_service(&s) != 0)
+                               s.run = false;
+#ifdef ETH_SOURCE_STB
+                       ethernet_service(&eth);
+#endif
+               }
+       }
+       s.end = clock();
+
+       tfp->close();
+
+       exit(0);
+}
diff --git a/mibuild/sim/server.py b/mibuild/sim/server.py
deleted file mode 100644 (file)
index 87981fc..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-# This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
-# License: BSD
-
-import socket
-import os
-import pty
-import time
-import threading
-import subprocess
-import struct
-import fcntl
-
-messages= {
-       "EXIT":         0,
-       "ACK":          1,
-       "ERROR":        2,
-       "UART":         3,
-       "ETHERNET":     4
-}
-
-class PacketTooLarge(Exception):
-       pass
-
-class VerilatorServer:
-       def __init__(self, sockaddr="/tmp/simsocket"):
-               self.sockaddr = sockaddr
-               self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
-               self._cleanup_file()
-               self.socket.bind(self.sockaddr)
-               self.socket.listen(1)
-
-               master, slave = pty.openpty()
-               self.serial = master
-               self.serial_name = os.ttyname(slave)
-
-               os.system("openvpn --mktun --dev tap0")
-               os.system("ip link set tap0 up")
-               os.system("ip addr add 192.169.0.14/24 dev tap0")
-               os.system("iface tap0 inet")
-               os.system("mknod /dev/net/tap c 10 200")
-               os.system("chmod 600 /dev/net/tap")
-
-
-               self.ack = False
-
-               self._print_banner()
-
-       def _print_banner(self):
-               print("Mibuild simulation server")
-               print("sockaddr: {}".format(self.sockaddr))
-               print("serial: {}".format(self.serial_name))
-
-       def _cleanup_file(self):
-               try:
-                       os.remove(self.sockaddr)
-               except OSError:
-                       pass
-
-       def accept(self):
-               self.conn, addr = self.socket.accept()
-
-       def send(self, packet):
-               self.conn.send(packet)
-
-       def recv(self):
-               maxlen = 2048
-               packet = self.conn.recv(maxlen)
-               if len(packet) < 1:
-                       return None
-               if len(packet) >= maxlen:
-                       raise PacketTooLarge
-               return packet
-
-       def close(self):
-               if hasattr(self, "conn"):
-                       self.conn.shutdown(socket.SHUT_RDWR)
-                       self.conn.close()
-               if hasattr(self, "socket"):
-                       self.socket.shutdown(socket.SHUT_RDWR)
-                       self.socket.close()
-               os.system("openvpn --rmtun --dev tap0")
-               os.system("rm -f /dev/net/tap")
-               self._cleanup_file()
-
-# XXX proof of concept
-server = VerilatorServer()
-server.accept()
-print("Connection accepted")
-
-TUNSETIFF      = 0x400454ca
-IFF_TAP                = 0x0002
-IFF_NO_PI      = 0x1000
-
-def read():
-       while True:
-               packet = server.recv()
-               if packet is not None:
-                       if packet[0] == messages["UART"]:
-                               c = bytes(chr(packet[1]).encode('utf-8'))
-                               os.write(server.serial, c)
-                       elif packet[0] == messages["ETHERNET"]:
-                               tap = os.open("/dev/net/tun", os.O_RDWR)
-                               fcntl.ioctl(tap, TUNSETIFF, struct.pack("16sH", b"tap0", IFF_TAP | IFF_NO_PI))
-                               os.write(tap, packet[1+8:-4])
-                               os.close(tap)
-                       elif packet[0] == messages["ACK"]:
-                               server.ack = True
-
-def write():
-       while True:
-               for c in list(os.read(server.serial, 100)):
-                       packet = [messages["UART"], c]
-                       server.send(bytes(packet))
-                       while not server.ack:
-                               pass
-                       server.ack = False
-
-readthread = threading.Thread(target=read, daemon=True)
-readthread.start()
-
-writethread = threading.Thread(target=write, daemon=True)
-writethread.start()
-
-try:
-    while True:
-       time.sleep(1)
-except KeyboardInterrupt:
-       server.close()
-
diff --git a/mibuild/sim/server_tb.cpp b/mibuild/sim/server_tb.cpp
deleted file mode 100644 (file)
index 8563eeb..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-// This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
-// License: BSD
-
-#include <time.h>
-
-#include "Vdut.h"
-#include "verilated.h"
-#include "verilated_vcd_c.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/select.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/un.h>
-#include <netdb.h>
-#include <pthread.h>
-
-#define MAX(a,b) (((a)>(b))?(a):(b))
-#define MIN(a,b) (((a)<(b))?(a):(b))
-
-int trace = 0;
-
-vluint64_t main_time = 0;
-double sc_time_stamp()
-{
-       return main_time;
-}
-
-Vdut* dut;
-VerilatedVcdC* tfp;
-
-/* ios */
-
-#define MAX_LEN 2048
-
-enum {
-       MESSAGE_EXIT = 0,
-       MESSAGE_ACK,
-       MESSAGE_ERROR,
-       MESSAGE_UART,
-       MESSAGE_ETH
-};
-
-struct sim {
-       int socket;
-       bool run;
-
-       unsigned int tick;
-       clock_t start;
-       clock_t end;
-       float speed;
-
-       char txbuffer[MAX_LEN];
-       char rxbuffer[MAX_LEN];
-
-       char rx_serial_stb;
-       char rx_serial_data;
-       char rx_serial_presented;
-};
-
-unsigned char eth_txbuffer[1532];
-unsigned char eth_rxbuffer[1532];
-int eth_txbuffer_len = 0;
-int eth_rxbuffer_len = 0;
-int eth_rxbuffer_pos = 0;
-
-int sim_connect(struct sim *s, const char *sockaddr)
-{
-       struct sockaddr_un addr;
-
-       s->socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
-       if(s->socket < 0) {
-               return -1;
-       }
-
-       addr.sun_family = AF_UNIX;
-       strcpy(addr.sun_path, sockaddr);
-       if(connect(s->socket, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
-               close(s->socket);
-               return -1;
-       }
-
-       return 0;
-}
-
-int sim_send(struct sim *s, char *buffer, int len)
-{
-       send(s->socket, s->txbuffer, len, 0);
-       return 0;
-}
-
-void sim_receive_process(struct sim *s, char * buffer, int len) {
-       int i;
-       switch(buffer[0]) {
-               case MESSAGE_EXIT:
-                       s->run = false;
-                       break;
-               case MESSAGE_UART:
-                       i = 0;
-                       for(i=0; i<len-1; i++) {
-                               s->rx_serial_stb = 1;
-                               s->rx_serial_data = buffer[i+1];
-                               while (s->rx_serial_presented == 0);
-                               s->rx_serial_presented = 0;
-                       }
-                       s->rx_serial_stb = 0;
-                       break;
-               default:
-                       break;
-       }
-}
-
-void *sim_receive(void *s_void)
-{
-       struct sim *s = (sim *) s_void;
-       int rxlen;
-       while(1)
-       {
-               rxlen = recv(s->socket, s->rxbuffer, MAX_LEN, 0);
-               if (rxlen > 0)
-                       sim_receive_process(s, s->rxbuffer, rxlen);
-               s->txbuffer[0] = MESSAGE_ACK;
-               sim_send(s, s->txbuffer, 1);
-       }
-}
-
-void sim_destroy(struct sim *s)
-{
-       close(s->socket);
-       free(s);
-}
-
-int console_service(struct sim *s)
-{
-       /* fpga --> console */
-       SERIAL_SOURCE_ACK = 1;
-       if(SERIAL_SOURCE_STB == 1) {
-               s->txbuffer[0] = MESSAGE_UART;
-               s->txbuffer[1] = SERIAL_SOURCE_DATA;
-               sim_send(s, s->txbuffer, 2);
-       }
-
-       /* console --> fpga */
-       SERIAL_SINK_STB = s->rx_serial_stb;
-       SERIAL_SINK_DATA = s->rx_serial_data;
-       if (SERIAL_SINK_STB & SERIAL_SINK_ACK)
-               s->rx_serial_presented = s->rx_serial_stb;
-
-       return 0;
-}
-
-#ifdef ETH_SOURCE_STB
-int eth_last_source_stb = 0;
-
-int ethernet_service(struct sim *s) {
-       /* fpga --> ethernet tap */
-       ETH_SOURCE_ACK = 1;
-       if(ETH_SOURCE_STB == 1) {
-               eth_txbuffer[eth_txbuffer_len] = ETH_SOURCE_DATA;
-               eth_txbuffer_len++;
-       } else {
-               if (eth_last_source_stb) {
-                       s->txbuffer[0] = MESSAGE_ETH;
-                       memcpy(s->txbuffer+1, eth_txbuffer, eth_txbuffer_len);
-                       sim_send(s, s->txbuffer, eth_txbuffer_len+1);
-                       eth_txbuffer_len = 0;
-               }
-       }
-       eth_last_source_stb = ETH_SOURCE_STB;
-}
-#endif
-
-void sim_tick(struct sim *s)
-{
-       SYS_CLK = s->tick%2;
-       dut->eval();
-       if (trace)
-               tfp->dump(s->tick);
-       s->tick++;
-}
-
-void sim_init(struct sim *s)
-{
-       int i;
-       s->tick = 0;
-#ifdef SYS_RST
-       SYS_RST = 1;
-       SYS_CLK = 0;
-       for (i=0; i<8; i++)
-               sim_tick(s);
-       SYS_RST = 0;
-#endif
-       s->start = clock();
-}
-
-int main(int argc, char **argv, char **env)
-{
-       Verilated::commandArgs(argc, argv);
-       dut = new Vdut;
-
-       Verilated::traceEverOn(true);
-       tfp = new VerilatedVcdC;
-       dut->trace(tfp, 99);
-       tfp->open("dut.vcd");
-
-       struct sim s;
-       sim_init(&s);
-       sim_connect(&s, "/tmp/simsocket");
-
-       pthread_t sim_receive_thread;
-
-       pthread_create(&sim_receive_thread, NULL, sim_receive, &s);
-
-       s.run = true;
-       while(s.run) {
-               sim_tick(&s);
-               if (SYS_CLK) {
-                       if (console_service(&s) != 0)
-                               s.run = false;
-#ifdef ETH_SOURCE_STB
-                       ethernet_service(&s);
-#endif
-               }
-       }
-       s.end = clock();
-
-       tfp->close();
-       pthread_cancel(sim_receive_thread);
-       sim_destroy(&s);
-
-       exit(0);
-}