diff --git a/src/include/harpfloat.h b/src/include/harpfloat.h new file mode 100644 index 00000000..5fc50ebb --- /dev/null +++ b/src/include/harpfloat.h @@ -0,0 +1,123 @@ +/******************************************************************************* + HARPtools by Chad D. Kersey, Summer 2011 +*******************************************************************************/ +#include +#include + +#include "types.h" + +#ifdef DEBUG +#include + +#define DEBUGMSG(x) do { \ + std::cout << __FILE__ << ':' <<__LINE__ << ": " << x << '\n'; \ +} while(0) +#else +#define DEBUGMSG(x) do { } while(0) +#endif + +namespace Harp { + // This class serves to handle the strange-precision floating point that can + // crop up in HARP. + class Float { + public: + Float(Word_u bin, Size n): sz(n) { + DEBUGMSG("Float(0x" << std::hex << bin << ", " << std::dec << n << ')'); + + bool sign(bin >> (n*8 - 1)); + + Size expSz; + if (n < 4) { + expSz = 5; + } else if (n < 8) { + expSz = 8; + } else { + expSz = 11; + } + + Size sigSz = n*8 - expSz - 1; + + DEBUGMSG(" exp: " << std::dec << expSz << + " bits, sig: " << std::dec << sigSz << " bits."); + + int exp = (bin >> sigSz) & ((1< Word_u: " << d); + Size expSz; + if (sz < 4) { + expSz = 5; + } else if (sz < 8) { + expSz = 8; + } else { + expSz = 11; + } + + Size sigSz = 8*sz - expSz - 1; + + bool sign(d < 0); + + bool inf(isinf(d)), zero(d == 0.0); + int exp; + + if (!inf && !zero) exp = floor(log2(fabs(d))); + + Word_u rval; + if (inf) { + // Infinity + DEBUGMSG(" Inf."); + rval = ((1llu<double " << d); return d; } + + private: + double d; + Size sz; + }; +}; diff --git a/src/include/instruction.h b/src/include/instruction.h index d809a6d5..b99f3861 100644 --- a/src/include/instruction.h +++ b/src/include/instruction.h @@ -29,7 +29,8 @@ namespace Harp { ANDI, ORI, XORI, ADDI, SUBI, MULI, DIVI, MODI, SHLI, SHRI, JALI, JALR, JMPI, JMPR, CLONE, JALIS, JALRS, JMPRT, LD, ST, LDI, RTOP, ANDP, ORP, XORP, NOTP, ISNEG, - ISZERO, HALT, TRAP, JMPRU, SKEP, RETI, TLBRM }; + ISZERO, HALT, TRAP, JMPRU, SKEP, RETI, TLBRM, + ITOF, FTOI, FADD, FSUB, FMUL, FDIV, FNEG }; enum ArgClass { AC_NONE, AC_2REG, AC_2IMM, AC_3REG, AC_3PREG, AC_3IMM, AC_3REGSRC, AC_1IMM, AC_1REG, AC_3IMMSRC, AC_PREG_REG, AC_2PREG diff --git a/src/include/types.h b/src/include/types.h index e71f018e..ae14cd8b 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -12,8 +12,8 @@ namespace Harp { typedef uint64_t Word_u; typedef int64_t Word_s; - typedef Word Addr; - typedef Word Size; + typedef Word_u Addr; + typedef Word_u Size; typedef unsigned RegNum; typedef unsigned ThdNum; diff --git a/src/instruction.cpp b/src/instruction.cpp index 0311498b..20b8109a 100644 --- a/src/instruction.cpp +++ b/src/instruction.cpp @@ -7,6 +7,7 @@ #include "include/instruction.h" #include "include/obj.h" #include "include/core.h" +#include "include/harpfloat.h" using namespace Harp; using namespace std; @@ -19,7 +20,8 @@ const char *Instruction::opStrings[] = { "ori", "xori", "addi", "subi", "muli", "divi", "modi", "shli", "shri", "jali", "jalr", "jmpi", "jmpr", "clone", "jalis", "jalrs", "jmprt", "ld", "st", "ldi", "rtop", "andp", "orp", "xorp", "notp", - "isneg", "iszero", "halt", "trap", "jmpru", "skep", "reti", "tlbrm", 0 + "isneg", "iszero", "halt", "trap", "jmpru", "skep", "reti", "tlbrm", + "itof", "ftoi", "fadd", "fsub", "fmul", "fdiv", "fneg", 0 }; const bool Instruction::isControlFlow[] = { @@ -28,7 +30,8 @@ const bool Instruction::isControlFlow[] = { false, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, - false, false, false, false, true, false, true, false + false, false, false, false, true, false, true, false, + false, false, false, false, false, false, false }; const bool Instruction::relAddress[] = { @@ -37,7 +40,8 @@ const bool Instruction::relAddress[] = { false, false, false, false, false, false, false, false, false, true, false, true, false, false, true, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false }; const bool Instruction::allSrcArgs[] = { @@ -46,7 +50,8 @@ const bool Instruction::allSrcArgs[] = { false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, true, false, true, false, false, false, false, false, false, - false, false, false, false, true, true, false, false + false, false, false, false, true, true, false, false, + false, false, false, false, false, false, false }; const bool Instruction::privileged[] = { @@ -55,7 +60,8 @@ const bool Instruction::privileged[] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, true, false, true, true, true, true + false, false, true, false, true, true, true, true, + false, false, false, false, false, false, false }; const Instruction::ArgClass Instruction::argClasses[] = { @@ -68,7 +74,8 @@ const Instruction::ArgClass Instruction::argClasses[] = { AC_1REG, AC_3IMM, AC_3IMMSRC, AC_2IMM, AC_PREG_REG, AC_3PREG, AC_3PREG, AC_3PREG, AC_2PREG, AC_PREG_REG, AC_PREG_REG, AC_NONE, AC_NONE, AC_1REG, AC_1REG, AC_NONE, - AC_1REG + AC_1REG, + AC_2REG, AC_2REG, AC_3REG, AC_3REG, AC_3REG, AC_3REG, AC_2REG }; ostream &Harp::operator<<(ostream& os, Instruction &inst) { @@ -110,6 +117,7 @@ void Instruction::executeOn(Core &c) { } Size nextActiveThreads = c.activeThreads; + Size wordSz = c.a.getWordSize(); for (Size t = 0; t < c.activeThreads; t++) { vector ®(c.reg[t]); @@ -192,7 +200,7 @@ void Instruction::executeOn(Core &c) { break; case NOTP: pReg[pdest] = !(pReg[psrc[0]]); break; - case ISNEG: pReg[pdest] = (1ll<<(c.a.getWordSize()*8 - 1))®[rsrc[0]]; + case ISNEG: pReg[pdest] = (1ll<<(wordSz*8 - 1))®[rsrc[0]]; break; case HALT: c.activeThreads = 0; nextActiveThreads = 0; @@ -213,6 +221,24 @@ void Instruction::executeOn(Core &c) { c.pc = c.shadowPc; } break; + case ITOF: reg[rdest] = Float(double(reg[rsrc[0]]), wordSz); + break; + case FTOI: reg[rdest] = Word_s(double(Float(reg[rsrc[0]], wordSz))); + break; + case FNEG: reg[rdest] = Float(-double(Float(reg[rsrc[0]],wordSz)),wordSz); + break; + case FADD: reg[rdest] = Float(double(Float(reg[rsrc[0]], wordSz)) + + double(Float(reg[rsrc[1]], wordSz)),wordSz); + break; + case FSUB: reg[rdest] = Float(double(Float(reg[rsrc[0]], wordSz)) - + double(Float(reg[rsrc[1]], wordSz)),wordSz); + break; + case FMUL: reg[rdest] = Float(double(Float(reg[rsrc[0]], wordSz)) * + double(Float(reg[rsrc[1]], wordSz)),wordSz); + break; + case FDIV: reg[rdest] = Float(double(Float(reg[rsrc[0]], wordSz)) / + double(Float(reg[rsrc[1]], wordSz)),wordSz); + break; default: cout << "ERROR: Unsupported instruction: " << *this << "\n"; exit(1); diff --git a/src/unit_test/float_test.cpp b/src/unit_test/float_test.cpp new file mode 100644 index 00000000..8d5169a1 --- /dev/null +++ b/src/unit_test/float_test.cpp @@ -0,0 +1,49 @@ +#include "include/harpfloat.h" + +#include +#include +#include + +using namespace Harp; +using namespace std; + +static void try_val(double d, Size sz) { + Float f(d, sz); + Word w(f); + double e(Float(w, sz)); + printf("%uB: %g -> 0x%llx -> %g\n", sz, d, (unsigned long long)w, e); +} + +int main() { + /* Loop over available integer sizes. */ + unsigned randseed(time(NULL)); + for (unsigned sz = 1; sz <= 8; sz++) { + srand(randseed); + + /* First test some random ordinary numbers and their conversions. */ + for (unsigned i = 0; i < 2; i++) { + int n = rand() - RAND_MAX/2; + double d = n * 0.0000001; + try_val(d, sz); + } + + /* Next, let's try +/- infinity. */ + for (unsigned i = 0; i < 2; i++) { + double d(i?HUGE_VAL:-HUGE_VAL); + try_val(d, sz); + } + + /* Last, let's try some random subnormal numbers and their conversions. */ + double mote; + if (sz < 4) mote = pow(2, int(-14 - (sz*8 - 6))); + else if (sz < 8) mote = pow(2, int(-126 - (sz*8 - 9))); + else mote = pow(2, int(-1022 - (sz*8 - 12))); + for (unsigned i = 0; i < 2; i++) { + int n = rand()%256; + double d = n * mote; + try_val(d, sz); + } + } + + return 0; +}