#include <sstream>
#include <iomanip>
+#include "common.h"
+
using namespace std;
namespace VFPU
{
-static const char g_fpu[] = "../vhdl/tb_fpu";
+static const char g_fpu[] = "vfpu";
static bool g_running = false;
static int g_fpu_socket[2] = {-1,-1};
// Remap stdio to the socket
dup2(g_fpu_socket[0],fileno(stdin));
dup2(g_fpu_socket[0],fileno(stdout));
- dup2(open("/dev/null", O_APPEND), fileno(stderr)); //LALALA I AM NOT LISTENING TO YOUR STUPID ERRORS GHDL
// Unbuffer things; buffers are a pain
setbuf(stdin, NULL); setbuf(stdout, NULL); setbuf(stderr, NULL);
- //fprintf(stderr, "Goodbye!\n");
+ Debug("Child about to suppress stderr and exec vfpu");
+ dup2(open("/dev/null", O_APPEND), fileno(stderr)); //LALALA I AM NOT LISTENING TO YOUR STUPID ERRORS GHDL
execl(g_fpu, g_fpu,NULL);
- fprintf(stderr, "Uh oh! %s\n", strerror(errno)); // We will never see this if something goes wrong... oh dear
- exit(errno); // Child exits here.
+ int err = errno; // Because errno will be set again by the next system call
+ Fatal("Uh oh! %s\n", strerror(err)); // We will never see this if something goes wrong... oh dear
+ exit(err); // Child exits here.
}
// Parent branch
return 0;
}
-float Exec(float opa, float opb, Opcode op)
+float Exec(float opa, float opb, Opcode op, Rmode rmode)
{
unsigned a; memcpy(&a, &opa, sizeof(float));
unsigned b; memcpy(&b, &opb, sizeof(float));
- unsigned r = (unsigned)(Exec(Register(a), Register(b), op).to_ulong());
+ unsigned r = (unsigned)(Exec(Register(a), Register(b), op, rmode).to_ulong());
float result; memcpy(&result, &r, sizeof(float));
return result;
}
/**
* Tell the VFPU to execute an instruction, wait for it to finish, return the result
* TODO: Make this not mix C++ and C so badly?
+ * TODO: It will still only work for magic 32 bit FPU
*/
-Register Exec(const Register & a, const Register & b, Opcode op)
+Register Exec(const Register & a, const Register & b, Opcode op, Rmode rmode)
{
assert(g_running);
stringstream s;
- s << hex << a.to_ullong() << "\n" << b.to_ullong() << "\n" << setw(3) << setfill('0') << op << "\n";
+ s << hex << setw(8) << setfill('0') << a.to_ullong() << "\n" << b.to_ullong() << "\n" << setw(3) << op <<"\n" << setw(2) << rmode << "\n\n";
string str(s.str());
- //fprintf(stderr, "Writing:\n%s\n", str.c_str());
+ //Debug("Writing: %s", str.c_str());
// So we used C++ streams to make our C string...
assert(write(g_fpu_socket[1], str.c_str(), str.size()) == (int)str.size());
- //fprintf(stderr, "Wrote!\n");
char buffer[BUFSIZ];
int len = read(g_fpu_socket[1], buffer, sizeof(buffer));
//assert(len == 9);
buffer[--len] = '\0'; // Get rid of newline
- //fprintf(stderr, "Read!\n");
+ //Debug("Read: %s", buffer);
Register result(0);
for (int i = 0; i < len/2; ++i)
sscanf(buffer+2*i, "%02x", &byte);
result |= (byte << 8*(len/2-i-1));
}
+
+ stringstream s2;
+ s2 << hex << result.to_ullong();
+ //Debug("Result is: %s", s2.str().c_str());
return result;
}
-- 111 = unused
*/
typedef enum {ADD=0x000, SUB=0x001, MULT=0x010, DIV=0x011, SQRT=0x100} Opcode;
+ typedef enum {EVEN=0x00, ZERO=0x01, UP=0x10, DOWN=0x11} Rmode;
typedef std::bitset<32> Register;
- extern Register Exec(const Register & a, const Register & b, Opcode op); // operate with registers
- extern float Exec(float a, float b, Opcode op); //converts floats into registers and back
+ extern Register Exec(const Register & a, const Register & b, Opcode op, Rmode rmode = EVEN); // operate with registers
+ extern float Exec(float a, float b, Opcode op, Rmode rmode = EVEN); //converts floats into registers and back
}
#endif //_VFPU_H