From: Sam Moore Date: Fri, 11 Apr 2014 05:30:53 +0000 (+0800) Subject: Add rounding mode to VFPU X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=commitdiff_plain;h=c0f947a6ce10a329eec81e4df820ac52f7ab371f;hp=79d61ba24ac2d29cea6e7f1fee2f83705c5fb4ac Add rounding mode to VFPU 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. --- diff --git a/src/tests/repr.cpp b/src/tests/repr.cpp new file mode 100644 index 0000000..26ed668 --- /dev/null +++ b/src/tests/repr.cpp @@ -0,0 +1,33 @@ +#include "main.h" + +#include + +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 + +} diff --git a/src/tests/vfpufloat.cpp b/src/tests/vfpufloat.cpp index 606ba5e..5f89a66 100644 --- a/src/tests/vfpufloat.cpp +++ b/src/tests/vfpufloat.cpp @@ -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 index 0000000..218546c --- /dev/null +++ b/src/vfpu @@ -0,0 +1 @@ +../bin/vfpu \ No newline at end of file diff --git a/src/vfpu.cpp b/src/vfpu.cpp index 58725f7..2c6d703 100644 --- a/src/vfpu.cpp +++ b/src/vfpu.cpp @@ -15,12 +15,14 @@ #include #include +#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; } diff --git a/src/vfpu.h b/src/vfpu.h index c489e89..edf471a 100644 --- a/src/vfpu.h +++ b/src/vfpu.h @@ -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