Added some reading material, floating point support.
git-svn-id: http://www.cdkersey.com/harp/harptool@9 0246edb2-e076-4747-b392-db732a341fa2
This commit is contained in:
123
src/include/harpfloat.h
Normal file
123
src/include/harpfloat.h
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
HARPtools by Chad D. Kersey, Summer 2011
|
||||||
|
*******************************************************************************/
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#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<<expSz) - 1);
|
||||||
|
Word_u sig = bin & ((1llu<<sigSz) - 1);
|
||||||
|
DEBUGMSG(" sig=" << std::dec << sig << " exp=" << exp);
|
||||||
|
|
||||||
|
if (exp == 0) {
|
||||||
|
// Subnormal
|
||||||
|
d = sig / pow(2, ((1<<(expSz-1))-2)) / pow(2, sigSz);
|
||||||
|
DEBUGMSG(" Denorm.");
|
||||||
|
} else if (exp == ((1<<expSz) - 1)) {
|
||||||
|
// Infinity
|
||||||
|
d = HUGE_VAL;
|
||||||
|
DEBUGMSG(" Inf.");
|
||||||
|
} else {
|
||||||
|
// Normalized, implied 1.
|
||||||
|
exp -= (1<<(expSz - 1)) - 1;
|
||||||
|
d = pow(2.0, exp - int(sigSz)) * double((1ll << sigSz) + sig);
|
||||||
|
DEBUGMSG(" Norm, exp=" << exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sign) d = -d;
|
||||||
|
|
||||||
|
DEBUGMSG("Set to " << d);
|
||||||
|
}
|
||||||
|
|
||||||
|
Float(double d, Size n): sz(n), d(d) { DEBUGMSG("Float(double, size)"); }
|
||||||
|
|
||||||
|
operator Word_u() {
|
||||||
|
DEBUGMSG("Float -> 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<<expSz)-1llu)<<sigSz;
|
||||||
|
} else if (!zero && abs(exp) < (1<<(expSz-1)) - 1) {
|
||||||
|
// Normalized with implied 1.
|
||||||
|
Word_u sig = (fabs(d) * pow(2.0, -exp) - 1.0) * pow(2.0, sigSz);
|
||||||
|
DEBUGMSG(" Norm, exp=" << exp << ", sig=" << sig);
|
||||||
|
rval = ((((exp + ((1llu<<(expSz-1)) - 1llu))
|
||||||
|
&((1llu<<expSz)-1llu)))<<sigSz) | sig;
|
||||||
|
} else if (!zero && exp > -(1<<(expSz-1)) - sigSz) {
|
||||||
|
// Subnormal number.
|
||||||
|
Word_u sig = round(fabs(d)*pow(2.0,((1<<(expSz-1))-2))*pow(2.0, sigSz));
|
||||||
|
DEBUGMSG(" Denorm, exp=" << exp << ", sig=" << sig);
|
||||||
|
rval = sig;
|
||||||
|
} else {
|
||||||
|
// Zero.
|
||||||
|
rval = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sign) rval |= 1llu<<(sz*8 - 1);
|
||||||
|
|
||||||
|
DEBUGMSG(" Returning 0x" << std::hex << rval);
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator double() { DEBUGMSG("Float->double " << d); return d; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
double d;
|
||||||
|
Size sz;
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -29,7 +29,8 @@ namespace Harp {
|
|||||||
ANDI, ORI, XORI, ADDI, SUBI, MULI, DIVI, MODI, SHLI, SHRI,
|
ANDI, ORI, XORI, ADDI, SUBI, MULI, DIVI, MODI, SHLI, SHRI,
|
||||||
JALI, JALR, JMPI, JMPR, CLONE, JALIS, JALRS,
|
JALI, JALR, JMPI, JMPR, CLONE, JALIS, JALRS,
|
||||||
JMPRT, LD, ST, LDI, RTOP, ANDP, ORP, XORP, NOTP, ISNEG,
|
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 {
|
enum ArgClass {
|
||||||
AC_NONE, AC_2REG, AC_2IMM, AC_3REG, AC_3PREG, AC_3IMM, AC_3REGSRC,
|
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
|
AC_1IMM, AC_1REG, AC_3IMMSRC, AC_PREG_REG, AC_2PREG
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ namespace Harp {
|
|||||||
typedef uint64_t Word_u;
|
typedef uint64_t Word_u;
|
||||||
typedef int64_t Word_s;
|
typedef int64_t Word_s;
|
||||||
|
|
||||||
typedef Word Addr;
|
typedef Word_u Addr;
|
||||||
typedef Word Size;
|
typedef Word_u Size;
|
||||||
|
|
||||||
typedef unsigned RegNum;
|
typedef unsigned RegNum;
|
||||||
typedef unsigned ThdNum;
|
typedef unsigned ThdNum;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "include/instruction.h"
|
#include "include/instruction.h"
|
||||||
#include "include/obj.h"
|
#include "include/obj.h"
|
||||||
#include "include/core.h"
|
#include "include/core.h"
|
||||||
|
#include "include/harpfloat.h"
|
||||||
|
|
||||||
using namespace Harp;
|
using namespace Harp;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -19,7 +20,8 @@ const char *Instruction::opStrings[] = {
|
|||||||
"ori", "xori", "addi", "subi", "muli", "divi", "modi", "shli", "shri",
|
"ori", "xori", "addi", "subi", "muli", "divi", "modi", "shli", "shri",
|
||||||
"jali", "jalr", "jmpi", "jmpr", "clone", "jalis", "jalrs",
|
"jali", "jalr", "jmpi", "jmpr", "clone", "jalis", "jalrs",
|
||||||
"jmprt", "ld", "st", "ldi", "rtop", "andp", "orp", "xorp", "notp",
|
"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[] = {
|
const bool Instruction::isControlFlow[] = {
|
||||||
@@ -28,7 +30,8 @@ const bool Instruction::isControlFlow[] = {
|
|||||||
false, false, false, false, false, false, false, false, false,
|
false, false, false, false, false, false, false, false, false,
|
||||||
true, true, true, true, true, true, true,
|
true, true, true, true, true, true, true,
|
||||||
true, false, false, false, false, false, false, false, false,
|
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[] = {
|
const bool Instruction::relAddress[] = {
|
||||||
@@ -37,7 +40,8 @@ const bool Instruction::relAddress[] = {
|
|||||||
false, false, false, false, false, false, false, false, false,
|
false, false, false, false, false, false, false, false, false,
|
||||||
true, false, true, false, false, true, 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, false, false,
|
||||||
|
false, false, false, false, false, false, false
|
||||||
};
|
};
|
||||||
|
|
||||||
const bool Instruction::allSrcArgs[] = {
|
const bool Instruction::allSrcArgs[] = {
|
||||||
@@ -46,7 +50,8 @@ const bool Instruction::allSrcArgs[] = {
|
|||||||
false, false, false, false, false, false, false, false, false,
|
false, false, false, false, false, false, false, false, false,
|
||||||
false, false, true, true, false, false, false,
|
false, false, true, true, false, false, false,
|
||||||
true, false, true, false, false, false, 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[] = {
|
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, 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[] = {
|
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_1REG, AC_3IMM, AC_3IMMSRC, AC_2IMM, AC_PREG_REG, AC_3PREG, AC_3PREG,
|
||||||
AC_3PREG, AC_2PREG,
|
AC_3PREG, AC_2PREG,
|
||||||
AC_PREG_REG, AC_PREG_REG, AC_NONE, AC_NONE, AC_1REG, AC_1REG, AC_NONE,
|
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) {
|
ostream &Harp::operator<<(ostream& os, Instruction &inst) {
|
||||||
@@ -110,6 +117,7 @@ void Instruction::executeOn(Core &c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Size nextActiveThreads = c.activeThreads;
|
Size nextActiveThreads = c.activeThreads;
|
||||||
|
Size wordSz = c.a.getWordSize();
|
||||||
|
|
||||||
for (Size t = 0; t < c.activeThreads; t++) {
|
for (Size t = 0; t < c.activeThreads; t++) {
|
||||||
vector<Word> ®(c.reg[t]);
|
vector<Word> ®(c.reg[t]);
|
||||||
@@ -192,7 +200,7 @@ void Instruction::executeOn(Core &c) {
|
|||||||
break;
|
break;
|
||||||
case NOTP: pReg[pdest] = !(pReg[psrc[0]]);
|
case NOTP: pReg[pdest] = !(pReg[psrc[0]]);
|
||||||
break;
|
break;
|
||||||
case ISNEG: pReg[pdest] = (1ll<<(c.a.getWordSize()*8 - 1))®[rsrc[0]];
|
case ISNEG: pReg[pdest] = (1ll<<(wordSz*8 - 1))®[rsrc[0]];
|
||||||
break;
|
break;
|
||||||
case HALT: c.activeThreads = 0;
|
case HALT: c.activeThreads = 0;
|
||||||
nextActiveThreads = 0;
|
nextActiveThreads = 0;
|
||||||
@@ -213,6 +221,24 @@ void Instruction::executeOn(Core &c) {
|
|||||||
c.pc = c.shadowPc;
|
c.pc = c.shadowPc;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
cout << "ERROR: Unsupported instruction: " << *this << "\n";
|
cout << "ERROR: Unsupported instruction: " << *this << "\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|||||||
49
src/unit_test/float_test.cpp
Normal file
49
src/unit_test/float_test.cpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#include "include/harpfloat.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user