Thanks, Gabe.

For when you or someone else does get a chance to look at it, here are
some details that may be useful to you.

Starting from the Add_d::execute() function in
atomic_simple_cpu_exec.cc (when compiled for MIPS), which is the
function that simulates the double-precision floating-point add
instruction, the variables Fs and Ft are declared as type 'double'.
Then both are assigned to xc->readFloatRegOperand() (which is defined
in src/cpu/simple/base.hh).

This function returns thread->readFloatReg().  This function is defined in
src/cpu/simple_thread.cc and returns floatRegs.f[flatIndex].
floatRegs.f is an array of type TheISA::FloatReg.  FloatReg is
typedef'ed in arch/mips/registers.hh as a float.

So the addition is supposed to operate on double-precision (64-bit)
floating-point operands, but is actually only getting float (32-bit)
floating-point operands.  In MIPS, the floating-point registers are
32-bits wide, so double-precision floating point operations are
supposed to use pairs of floating-point registers to hold each operand
and the result.  So M5 ought to read two 32-bit floating-point
registers for each operand and concatenate the bits into 64-bit double
variables before doing any double-precision floating-point
arithmetic.

M5 used to handle this correctly.  In particular, on the old m5-stable
branch, starting from Add_d::execute(), xc->readFloatRegOperand() was
passed a width argument of 64.  Then, when it called
thread->readFloatReg(), it passed along this width argument.  Then,
this function would call regs.readFloatReg() and pass along the width
argument.  This function would call RegFile::readFloatReg(), which
would call FloatRegFile::readReg(), again passing along the width
argument.  Finally, this function would read two floating-point
registers (if the width argument was 64) and concatenate the bits into
a single 64-bit double.

One additional monkey wrench is this.  Many of these functions return
a FloatReg type, which used to be typedef'ed as double, but is now
typedef'ed as float (and in a different header file).

All of these changes seem to be have been introduced in changeset
781969fbeca9.  I understand the good intention of trying to eliminate
all these width arguments, but in the end, it seems to have broken a
legitimate use for them (to distinguish between single and
double-precision operations).

I haven't checked too carefully, but this same problem may be
affecting ARM as well (since I think it uses the same paired
floating-point register scheme).  Also, other double-precision things
like checking for NaNs may be broken by this change.

On Wed, Dec 9, 2009 at 3:39 PM, Gabriel Michael Black
<[email protected]> wrote:
> I looked briefly at that change earlier, and I do think it's likely
> that I broke it. I don't know how much time I'll have to dig into it
> in the near future, but I'll put it on my short(ish :-/) list.
>
> Gabe
>
> Quoting Matt <[email protected]>:
>
>> Gabe,
>>
>> It looks like it was your changes that broke this.  Do you have any
>> insight on this?
>> Thanks.
>>
>> On Fri, Dec 4, 2009 at 3:31 PM, Matt <[email protected]> wrote:
>>> I'm having problems getting double-precision floating-point to work in
>>> m5 for the MIPS isa.
>>>
>>> The 32-bit MIPS isa has 32 32-bit floating-point registers.
>>> Double-precision floating-point numbers are stored in pairs of
>>> floating-point registers.  At least that's how I understand it.
>>>
>>> Simple floating point math used to work in m5 until changeset
>>> 781969fbeca9.  After the change, it seams that m5 does not read two
>>> 32-bit floating point registers to get a double-precision
>>> floating-point operand, but only one 32-bit floating-point register
>>> (when it's simulating an add_d instruction, for example).  This
>>> results in incorrect floating point arithmetic.
>>>
>>> I have the following C program (compiled for MIPS) that exercises
>>> the problem:
>>>
>>> #include<stdio.h>
>>>
>>> int main (void)
>>> {
>>>        double x, y, z;
>>>
>>>        x = 5.0;
>>>        y = 0.1;
>>>
>>>        z = x + y;
>>>
>>>        printf ("z = %lf\n", z);
>>>
>>>        return 0;
>>> }
>>>
>>> It should print "z = 5.1", but it doesn't because the simulation of
>>> the floating-point addition is wrong.
>>>
>>> Can anyone tell me why this change was made that seems to break the
>>> simulation of double-precision floating-point arithmetic in m5?
>>>
>>> Thanks.
>>>
>>> --
>>> Cheers,
>>> Matt
>>>
>>
>>
>>
>> --
>> Cheers,
>> Matt
>>
>
>
> _______________________________________________
> m5-dev mailing list
> [email protected]
> http://m5sim.org/mailman/listinfo/m5-dev
>



-- 
Cheers,
Matt
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to