Redo the FloatRegFile using unsigned integers
Edit the convert_and_round function which access FloatRegFile arch/isa_parser.py: recognize when we are writing a 'uint64_t' FloatReg and set the width appropriately arch/mips/isa/decoder.isa: Send a 'float' to the convert function instead of a unsigned word. Do this so we dont have to worry about the bit manipulation ourselves. We can just concern ourselves with values. Use unsigned double to get movd... arch/mips/isa/formats/fp.isa: float debug statement arch/mips/isa_traits.cc: add different versions of convert_and_round functions arch/mips/isa_traits.hh: Use an array of uint32_t unsigned integers to represent the Floating Point Regfile configs/test/hello_mips: basic FP program cpu/simple/cpu.hh: spacing --HG-- extra : convert_revision : a6fca91ad6365c83025f1131d71fa1b8ee76d7bc
This commit is contained in:
parent
2d077df1a0
commit
97429d8eee
7 changed files with 124 additions and 55 deletions
|
@ -1251,6 +1251,9 @@ class FloatRegOperand(Operand):
|
||||||
elif (self.ctype == 'double'):
|
elif (self.ctype == 'double'):
|
||||||
width = 64
|
width = 64
|
||||||
func = 'setFloatReg'
|
func = 'setFloatReg'
|
||||||
|
elif (self.ctype == 'uint64_t'):
|
||||||
|
func = 'setFloatRegBits'
|
||||||
|
width = 64
|
||||||
else:
|
else:
|
||||||
func = 'setFloatRegBits'
|
func = 'setFloatRegBits'
|
||||||
final_ctype = 'uint%d_t' % self.dflt_size
|
final_ctype = 'uint%d_t' % self.dflt_size
|
||||||
|
|
|
@ -397,7 +397,7 @@ decode OPCODE_HI default Unknown::unknown() {
|
||||||
format FloatOp {
|
format FloatOp {
|
||||||
0x0: mfc1 ({{ Rt.uw = Fs.uw<31:0>; }});
|
0x0: mfc1 ({{ Rt.uw = Fs.uw<31:0>; }});
|
||||||
0x3: mfhc1({{ Rt.uw = Fs.ud<63:32>;}});
|
0x3: mfhc1({{ Rt.uw = Fs.ud<63:32>;}});
|
||||||
0x4: mtc1 ({{ Fs.uw = Rt.uw; }});
|
0x4: mtc1 ({{ Fs.uw = Rt.uw; }});
|
||||||
0x7: mthc1({{
|
0x7: mthc1({{
|
||||||
uint64_t fs_hi = Rt.ud << 32;
|
uint64_t fs_hi = Rt.ud << 32;
|
||||||
uint64_t fs_lo = Fs.ud & 0x0000FFFF;
|
uint64_t fs_lo = Fs.ud & 0x0000FFFF;
|
||||||
|
@ -572,7 +572,7 @@ decode OPCODE_HI default Unknown::unknown() {
|
||||||
format FloatOp {
|
format FloatOp {
|
||||||
0x1: cvt_d_s({{
|
0x1: cvt_d_s({{
|
||||||
int rnd_mode = xc->readMiscReg(FCSR) & 0x03;
|
int rnd_mode = xc->readMiscReg(FCSR) & 0x03;
|
||||||
Fd.ud = convert_and_round(Fs.uw, SINGLE_TO_DOUBLE, rnd_mode);
|
Fd.ud = convert_and_round(Fs.sf, SINGLE_TO_DOUBLE, rnd_mode);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
0x4: cvt_w_s({{
|
0x4: cvt_w_s({{
|
||||||
|
@ -605,7 +605,7 @@ decode OPCODE_HI default Unknown::unknown() {
|
||||||
0x3: divd({{ Fd.df = Fs.df / Ft.df;}});
|
0x3: divd({{ Fd.df = Fs.df / Ft.df;}});
|
||||||
0x4: sqrtd({{ Fd.df = sqrt(Fs.df);}});
|
0x4: sqrtd({{ Fd.df = sqrt(Fs.df);}});
|
||||||
0x5: absd({{ Fd.df = fabs(Fs.df);}});
|
0x5: absd({{ Fd.df = fabs(Fs.df);}});
|
||||||
0x6: movd({{ Fd.df = Fs.df;}});
|
0x6: movd({{ Fd.ud = Fs.ud;}});
|
||||||
0x7: negd({{ Fd.df = -1 * Fs.df;}});
|
0x7: negd({{ Fd.df = -1 * Fs.df;}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ output decoder {{
|
||||||
|
|
||||||
// Primary format for float operate instructions:
|
// Primary format for float operate instructions:
|
||||||
def format FloatOp(code, *flags) {{
|
def format FloatOp(code, *flags) {{
|
||||||
|
code = 'std::cout << "Floating Point Op" << std::endl;\n' + code
|
||||||
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
|
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
|
||||||
header_output = BasicDeclare.subst(iop)
|
header_output = BasicDeclare.subst(iop)
|
||||||
decoder_output = BasicConstructor.subst(iop)
|
decoder_output = BasicConstructor.subst(iop)
|
||||||
|
@ -41,6 +42,7 @@ def format FloatOp(code, *flags) {{
|
||||||
|
|
||||||
// Primary format for float64 operate instructions:
|
// Primary format for float64 operate instructions:
|
||||||
def format Float64Op(code, *flags) {{
|
def format Float64Op(code, *flags) {{
|
||||||
|
code = 'std::cout << "Floating Point 64" << std::endl;\n' + code
|
||||||
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
|
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
|
||||||
header_output = BasicDeclare.subst(iop)
|
header_output = BasicDeclare.subst(iop)
|
||||||
decoder_output = BasicConstructor.subst(iop)
|
decoder_output = BasicConstructor.subst(iop)
|
||||||
|
|
|
@ -30,25 +30,95 @@
|
||||||
#include "config/full_system.hh"
|
#include "config/full_system.hh"
|
||||||
#include "cpu/static_inst.hh"
|
#include "cpu/static_inst.hh"
|
||||||
#include "sim/serialize.hh"
|
#include "sim/serialize.hh"
|
||||||
|
#include "base/bitfield.hh"
|
||||||
|
|
||||||
using namespace MipsISA;
|
using namespace MipsISA;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
MipsISA::convert_and_round(uint64_t fp_val, ConvertType cvt_type, int rnd_mode)
|
MipsISA::convert_and_round(uint32_t fp_val, ConvertType cvt_type, int rnd_mode)
|
||||||
{
|
{
|
||||||
|
|
||||||
uint64_t ret_val = 0;
|
uint64_t ret_val = 0;
|
||||||
|
|
||||||
switch (cvt_type)
|
switch (cvt_type)
|
||||||
{
|
{
|
||||||
case SINGLE_TO_DOUBLE:
|
case SINGLE_TO_DOUBLE:
|
||||||
|
uint64_t single_sign = fp_val & 0x80000000;
|
||||||
|
|
||||||
break;
|
uint64_t single_exp = (fp_val & 0x7F800000) >> 22;
|
||||||
|
single_exp -= 127;
|
||||||
|
|
||||||
|
uint64_t single_mantissa = fp_val & 0x007FFFFF;
|
||||||
|
|
||||||
|
uint64_t double_exp = single_exp + 1023;
|
||||||
|
double_exp = double_exp << 51;
|
||||||
|
|
||||||
|
uint64_t double_val = single_sign << 63 | double_exp | single_mantissa;
|
||||||
|
|
||||||
|
return double_val;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("Invalid Floating Point Conversion Type (%d) being used.\n",cvt_type);
|
panic("Invalid Floating Point Conversion Type (%d) being used.\n",cvt_type);
|
||||||
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret_val;
|
uint64_t
|
||||||
|
MipsISA::convert_and_round(uint64_t fp_val, ConvertType cvt_type, int rnd_mode)
|
||||||
|
{
|
||||||
|
|
||||||
|
uint64_t ret_val = 0;
|
||||||
|
|
||||||
|
switch (cvt_type)
|
||||||
|
{
|
||||||
|
case SINGLE_TO_DOUBLE:
|
||||||
|
uint64_t single_sign = fp_val & 0x80000000;
|
||||||
|
|
||||||
|
uint64_t single_exp = (fp_val & 0x7F800000) >> 22;
|
||||||
|
single_exp -= 127;
|
||||||
|
|
||||||
|
uint64_t single_mantissa = fp_val & 0x007FFFFF;
|
||||||
|
|
||||||
|
uint64_t double_exp = single_exp + 1023;
|
||||||
|
double_exp = double_exp << 51;
|
||||||
|
|
||||||
|
uint64_t double_val = single_sign << 63 | double_exp | single_mantissa;
|
||||||
|
|
||||||
|
return double_val;
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("Invalid Floating Point Conversion Type (%d) being used.\n",cvt_type);
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
MipsISA::convert_and_round(float fp_val, ConvertType cvt_type, int rnd_mode)
|
||||||
|
{
|
||||||
|
void * ptr = &fp_val;
|
||||||
|
uint32_t fp_bits = * (uint32_t *) ptr;
|
||||||
|
|
||||||
|
cout << "Converting " << fp_val << " (" << hex << fp_bits << ") " << endl;
|
||||||
|
|
||||||
|
uint64_t ret_val = 0;
|
||||||
|
|
||||||
|
switch (cvt_type)
|
||||||
|
{
|
||||||
|
case SINGLE_TO_DOUBLE:
|
||||||
|
double double_val = fp_val;
|
||||||
|
void *double_ptr = &double_val;
|
||||||
|
uint64_t dp_bits = *(uint64_t *) double_ptr ;
|
||||||
|
cout << "To " << double_val << " (" << hex << dp_bits << ") " << endl;
|
||||||
|
double_ptr = &dp_bits;
|
||||||
|
cout << "Testing: " << *(double *) double_ptr << endl;
|
||||||
|
return dp_bits;
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("Invalid Floating Point Conversion Type (%d) being used.\n",cvt_type);
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -189,21 +189,24 @@ namespace MipsISA
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef double FloatReg;
|
typedef float FloatReg;
|
||||||
|
|
||||||
|
typedef uint32_t FloatReg32;
|
||||||
|
typedef uint64_t FloatReg64;
|
||||||
typedef uint64_t FloatRegBits;
|
typedef uint64_t FloatRegBits;
|
||||||
|
|
||||||
|
// const uint64_t hi_mask64 = 0xFFFFFFFF00000000;
|
||||||
|
//const uint64_t lo_mask64 = 0x00000000FFFFFFFF;
|
||||||
|
|
||||||
const int SingleWidth = 32;
|
const int SingleWidth = 32;
|
||||||
const int SingleBytes = SingleWidth / 4;
|
const int SingleBytes = 4;
|
||||||
|
|
||||||
const int DoubleWidth = 64;
|
const int DoubleWidth = 64;
|
||||||
const int DoubleBytes = DoubleWidth / 4;
|
const int DoubleBytes = 8;
|
||||||
|
|
||||||
const int QuadWidth = 128;
|
const int QuadWidth = 128;
|
||||||
const int QuadBytes = QuadWidth / 4;
|
const int QuadBytes = QuadWidth / 4;
|
||||||
|
|
||||||
const int FloatRegSize = SingleWidth / SingleBytes;
|
|
||||||
const int DoubleRegSize = FloatRegSize * 2;
|
|
||||||
|
|
||||||
class FloatRegFile
|
class FloatRegFile
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -211,31 +214,27 @@ namespace MipsISA
|
||||||
//Since the floating point registers overlap each other,
|
//Since the floating point registers overlap each other,
|
||||||
//A generic storage space is used. The float to be returned is
|
//A generic storage space is used. The float to be returned is
|
||||||
//pulled from the appropriate section of this region.
|
//pulled from the appropriate section of this region.
|
||||||
char regSpace[FloatRegSize * NumFloatRegs];
|
//char regSpace[SingleBytes * NumFloatRegs];
|
||||||
|
FloatReg32 regs[NumFloatRegs];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
bzero(regSpace, sizeof(regSpace));
|
bzero(regs, sizeof(regs));
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatReg readReg(int floatReg, int width)
|
double readReg(int floatReg, int width)
|
||||||
{
|
{
|
||||||
//In each of these cases, we have to copy the value into a temporary
|
|
||||||
//variable. This is because we may otherwise try to access an
|
|
||||||
//unaligned portion of memory.
|
|
||||||
switch(width)
|
switch(width)
|
||||||
{
|
{
|
||||||
case SingleWidth:
|
case SingleWidth:
|
||||||
float result32;
|
void *float_ptr = ®s[floatReg];
|
||||||
memcpy(&result32, regSpace + 4 * floatReg, FloatRegSize);
|
return *(float *) float_ptr;
|
||||||
return htog(result32);
|
|
||||||
|
|
||||||
case DoubleWidth:
|
case DoubleWidth:
|
||||||
double result64;
|
void *double_ptr = ®s[floatReg];
|
||||||
memcpy(&result64, regSpace + 4 * floatReg, DoubleRegSize);
|
return *(double *) double_ptr;
|
||||||
return htog(result64);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("Attempted to read a %d bit floating point register!", width);
|
panic("Attempted to read a %d bit floating point register!", width);
|
||||||
|
@ -244,20 +243,17 @@ namespace MipsISA
|
||||||
|
|
||||||
FloatRegBits readRegBits(int floatReg, int width)
|
FloatRegBits readRegBits(int floatReg, int width)
|
||||||
{
|
{
|
||||||
//In each of these cases, we have to copy the value into a temporary
|
using namespace std;
|
||||||
//variable. This is because we may otherwise try to access an
|
|
||||||
//unaligned portion of memory.
|
|
||||||
switch(width)
|
switch(width)
|
||||||
{
|
{
|
||||||
case SingleWidth:
|
case SingleWidth:
|
||||||
uint32_t result32;
|
return regs[floatReg];
|
||||||
memcpy(&result32, regSpace + 4 * floatReg, FloatRegSize);
|
|
||||||
return htog(result32);
|
|
||||||
|
|
||||||
case DoubleWidth:
|
case DoubleWidth:
|
||||||
uint64_t result64;
|
cout << hex << "Combining " << regs[floatReg + 1] << " & " << regs[floatReg + 1] << endl;
|
||||||
memcpy(&result64, regSpace + 4 * floatReg, DoubleRegSize);
|
cout << hex << "Returning " << ((FloatReg64)regs[floatReg] << 32 | regs[floatReg + 1]) << endl;
|
||||||
return htog(result64);
|
return (FloatReg64)regs[floatReg] << 32 | regs[floatReg + 1];
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("Attempted to read a %d bit floating point register!", width);
|
panic("Attempted to read a %d bit floating point register!", width);
|
||||||
|
@ -266,47 +262,45 @@ namespace MipsISA
|
||||||
|
|
||||||
Fault setReg(int floatReg, const FloatReg &val, int width)
|
Fault setReg(int floatReg, const FloatReg &val, int width)
|
||||||
{
|
{
|
||||||
//In each of these cases, we have to copy the value into a temporary
|
|
||||||
//variable. This is because we may otherwise try to access an
|
|
||||||
//unaligned portion of memory.
|
|
||||||
switch(width)
|
switch(width)
|
||||||
{
|
{
|
||||||
case SingleWidth:
|
case SingleWidth:
|
||||||
uint32_t result32;
|
float temp = val;
|
||||||
result32 = gtoh((uint32_t)val);
|
void *float_ptr = &temp;
|
||||||
memcpy(regSpace + 4 * floatReg, &result32, FloatRegSize);
|
regs[floatReg] = *(FloatReg32 *) float_ptr;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DoubleWidth:
|
case DoubleWidth:
|
||||||
uint64_t result64;
|
const void *double_ptr = &val;
|
||||||
result64 = gtoh((uint64_t)val);
|
FloatReg64 temp_double = *(FloatReg64 *) double_ptr;
|
||||||
memcpy(regSpace + 4 * floatReg, &result64, DoubleRegSize);
|
regs[floatReg] = temp_double >> 32;
|
||||||
|
regs[floatReg + 1] = temp_double;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("Attempted to read a %d bit floating point register!", width);
|
panic("Attempted to read a %d bit floating point register!", width);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
Fault setRegBits(int floatReg, const FloatRegBits &val, int width)
|
Fault setRegBits(int floatReg, const FloatRegBits &val, int width)
|
||||||
{
|
{
|
||||||
//In each of these cases, we have to copy the value into a temporary
|
using namespace std;
|
||||||
//variable. This is because we may otherwise try to access an
|
|
||||||
//unaligned portion of memory.
|
|
||||||
switch(width)
|
switch(width)
|
||||||
{
|
{
|
||||||
case SingleWidth:
|
case SingleWidth:
|
||||||
uint32_t result32;
|
regs[floatReg] = val;
|
||||||
result32 = gtoh((uint32_t)val);
|
|
||||||
memcpy(regSpace + 4 * floatReg, &result32, FloatRegSize);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DoubleWidth:
|
case DoubleWidth:
|
||||||
uint64_t result64;
|
cout << hex << "Setting val: " << val << endl;
|
||||||
result64 = gtoh((uint64_t)val);
|
regs[floatReg] = val >> 32;
|
||||||
memcpy(regSpace + 4 * floatReg, &result64, DoubleRegSize);
|
regs[floatReg + 1] = val;
|
||||||
|
cout << dec << "f" << floatReg << ": " << hex<< readRegBits(floatReg,32) << endl;
|
||||||
|
cout << dec << "f" << floatReg + 1 << ": " << hex << readRegBits(floatReg+1,32) << endl;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -348,8 +342,9 @@ namespace MipsISA
|
||||||
RND_NEAREST
|
RND_NEAREST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint64_t convert_and_round(uint32_t fp_val,ConvertType cvt_type, int rnd_mode = 0);
|
||||||
uint64_t convert_and_round(uint64_t fp_val,ConvertType cvt_type, int rnd_mode = 0);
|
uint64_t convert_and_round(uint64_t fp_val,ConvertType cvt_type, int rnd_mode = 0);
|
||||||
|
uint64_t convert_and_round(float fp_val,ConvertType cvt_type, int rnd_mode = 0);
|
||||||
|
|
||||||
void copyRegs(ExecContext *src, ExecContext *dest);
|
void copyRegs(ExecContext *src, ExecContext *dest);
|
||||||
|
|
||||||
|
@ -637,7 +632,6 @@ extern const Addr PageOffset;
|
||||||
return miscRegFile.setRegWithEffect(miscReg, val, xc);
|
return miscRegFile.setRegWithEffect(miscReg, val, xc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FloatReg readFloatReg(int floatReg)
|
FloatReg readFloatReg(int floatReg)
|
||||||
{
|
{
|
||||||
return floatRegFile.readReg(floatReg,SingleWidth);
|
return floatRegFile.readReg(floatReg,SingleWidth);
|
||||||
|
|
Binary file not shown.
|
@ -369,7 +369,7 @@ class SimpleCPU : public BaseCPU
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFloatRegBits(const StaticInst *si, int idx,
|
void setFloatRegBits(const StaticInst *si, int idx,
|
||||||
FloatRegBits val, int width)
|
FloatRegBits val, int width)
|
||||||
{
|
{
|
||||||
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
|
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
|
||||||
cpuXC->setFloatRegBits(reg_idx, val, width);
|
cpuXC->setFloatRegBits(reg_idx, val, width);
|
||||||
|
|
Loading…
Reference in a new issue