Add rounding mode to VFPU
authorSam Moore <matches@ucc.asn.au>
Fri, 11 Apr 2014 05:30:53 +0000 (13:30 +0800)
committerSam Moore <matches@ucc.asn.au>
Fri, 11 Apr 2014 05:30:53 +0000 (13:30 +0800)
For some reason it needs an extra newline?
It would be much better if this used binary read/write.

Will look into getting that to happen in the ipdf/vfpu repo at some point.

src/tests/repr.cpp [new file with mode: 0644]
src/tests/vfpufloat.cpp
src/vfpu [new symlink]
src/vfpu.cpp
src/vfpu.h

diff --git a/src/tests/repr.cpp b/src/tests/repr.cpp
new file mode 100644 (file)
index 0000000..26ed668
--- /dev/null
@@ -0,0 +1,33 @@
+#include "main.h"
+
+#include <bitset>
+
+using namespace std;
+
+
+
+int main(int argc, char ** argv)
+{
+       char buffer[BUFSIZ];
+       double input;
+       printf("Enter a double: ");
+       fgets(buffer, BUFSIZ, stdin);
+       sscanf(buffer, "%lf", &input);
+
+
+       float f = (float)(input);
+
+       unsigned long long i;
+       memcpy(&i, &f, 4);
+       bitset<32> b32(i);
+       memcpy(&i, &input, 8);
+       bitset<64> b64(i);
+
+       printf("\nAs float: %s\n", b32.to_string().c_str());
+       printf("\nAs double: %s\n", b64.to_string().c_str());
+       #ifdef REAL_BITSET
+               Real r(input);
+               printf("\nAs real: %s\n", r.repr.to_string().c_str());
+       #endif //REAL_BITSET
+       
+}
index 606ba5e..5f89a66 100644 (file)
@@ -8,7 +8,8 @@ int main(int argc, char ** argv)
 {
        VFPU::Start();
        float result = VFPU::Exec(25,10, VFPU::SUB);
-       printf("%f\n", result);
+       Debug("%f\n", result);
        VFPU::Halt();
+
        return 0;
 }
diff --git a/src/vfpu b/src/vfpu
new file mode 120000 (symlink)
index 0000000..218546c
--- /dev/null
+++ b/src/vfpu
@@ -0,0 +1 @@
+../bin/vfpu
\ No newline at end of file
index 58725f7..2c6d703 100644 (file)
 #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};
@@ -51,15 +53,16 @@ int Start()
                // 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
@@ -84,12 +87,12 @@ int Halt()
        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;
 }
@@ -97,25 +100,25 @@ float Exec(float opa, float opb, Opcode op)
 /**
  * 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)
@@ -124,6 +127,10 @@ Register Exec(const Register & a, const Register &  b, Opcode op)
                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;
 }
 
index c489e89..edf471a 100644 (file)
@@ -23,10 +23,11 @@ namespace VFPU
                -- 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

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