58725f738167dc5387a2d5f60603c4f427d3997c
[ipdf/code.git] / src / vfpu.cpp
1 #include "vfpu.h"
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <errno.h>
5 #include <unistd.h>
6 #include <stdio.h>
7 #include <sys/types.h>
8 #include <sys/socket.h>
9 #include <sys/stat.h>
10 #include <sys/fcntl.h>
11 #include <stdbool.h>
12 #include <signal.h>
13 #include <string.h>
14
15 #include <sstream>
16 #include <iomanip>
17
18 using namespace std;
19
20 namespace VFPU
21 {
22
23 static const char g_fpu[] = "../vhdl/tb_fpu";
24
25 static bool g_running = false;
26 static int g_fpu_socket[2] = {-1,-1};
27 static pid_t g_fpu_pid = -1;
28
29 /**
30  * Starts the VFPU
31  * @returns 0 on success, errno of the failing function on failure
32  */
33 int Start()
34 {
35         assert(!g_running);
36         // create unix socket pair
37         
38         if (socketpair(AF_UNIX, SOCK_STREAM, 0, g_fpu_socket) != 0)
39                 return errno;
40         
41
42         g_fpu_pid = fork();
43         if (g_fpu_pid < 0) // error check
44                 return errno;
45
46
47         // Child branch
48         if (g_fpu_pid == 0)
49         {
50                 
51                 // Remap stdio to the socket
52                 dup2(g_fpu_socket[0],fileno(stdin));
53                 dup2(g_fpu_socket[0],fileno(stdout));
54                 dup2(open("/dev/null", O_APPEND), fileno(stderr)); //LALALA I AM NOT LISTENING TO YOUR STUPID ERRORS GHDL
55                 
56                 // Unbuffer things; buffers are a pain
57                 setbuf(stdin, NULL); setbuf(stdout, NULL); setbuf(stderr, NULL);
58
59                 //fprintf(stderr, "Goodbye!\n");
60                 execl(g_fpu, g_fpu,NULL);
61                 fprintf(stderr, "Uh oh! %s\n", strerror(errno)); // We will never see this if something goes wrong... oh dear
62                 exit(errno); // Child exits here.
63         }
64
65         // Parent branch
66         usleep(100);
67         g_running = true; // We are ready!
68         return 0;
69 }
70
71 /**
72  * Halt the VFPU
73  */
74 int Halt()
75 {
76         assert(g_running);
77         // Tell the child to stop running the VHDL simulation
78         if (close(g_fpu_socket[1]) != 0)
79                 return errno;
80         usleep(1000);
81         if (kill(g_fpu_pid, SIGKILL) != 0)
82                 return errno;
83         g_running = false;
84         return 0;
85 }
86
87 float Exec(float opa, float opb, Opcode op)
88 {
89         unsigned a; memcpy(&a, &opa, sizeof(float));
90         unsigned b; memcpy(&b, &opb, sizeof(float));
91         
92         unsigned r = (unsigned)(Exec(Register(a), Register(b), op).to_ulong());
93         float result; memcpy(&result, &r, sizeof(float));
94         return result;
95 }
96
97 /**
98  * Tell the VFPU to execute an instruction, wait for it to finish, return the result
99  * TODO: Make this not mix C++ and C so badly?
100  */
101 Register Exec(const Register & a, const Register &  b, Opcode op)
102 {
103         assert(g_running);
104                 
105         stringstream s;
106         s << hex << a.to_ullong() << "\n" << b.to_ullong() << "\n" << setw(3) << setfill('0') << op << "\n";
107         string str(s.str());
108         //fprintf(stderr, "Writing:\n%s\n", str.c_str());
109
110         // So we used C++ streams to make our C string...
111         assert(write(g_fpu_socket[1], str.c_str(), str.size()) == (int)str.size());
112         //fprintf(stderr, "Wrote!\n");
113
114         char buffer[BUFSIZ]; 
115         int len = read(g_fpu_socket[1], buffer, sizeof(buffer));
116         //assert(len == 9);
117         buffer[--len] = '\0'; // Get rid of newline
118         //fprintf(stderr, "Read!\n");
119         
120         Register result(0);
121         for (int i = 0; i < len/2; ++i)
122         {
123                 unsigned byte; // It is ONE byte (2 nibbles == 2 hex digits)
124                 sscanf(buffer+2*i, "%02x", &byte);
125                 result |= (byte << 8*(len/2-i-1));
126         }
127         return result;
128 }
129
130 }
131
132

UCC git Repository :: git.ucc.asn.au