Skip to content

Commit

Permalink
Merge pull request #44 from futurecore/fix_print_large_float_crash
Browse files Browse the repository at this point in the history
Deal explicitly with fix(NaN).
  • Loading branch information
snim2 committed Aug 3, 2016
2 parents 4a7dd90 + de20c77 commit 595129a
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 50 deletions.
151 changes: 133 additions & 18 deletions revelation/execute_farith.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,140 @@
from revelation.utils import bits2float, float2bits, get_exponent_as_decimal, trim_32
from revelation.utils import bits2float, float2bits, get_exponent_as_decimal, is_nan, trim_32
from pydgin.utils import signed

import revelation.isa

import math

def make_float_executor(is16bit):
def exec_float(s, inst):
"""
RD = float(RN)
BN = RD[31]
if (RD[30:0] == 0) { BZ=1 } else { BZ=0 }
if (UnbiasedExponent(RD) > 127) { BV=1 } else { BV=0 }
if (UbiasedExponent(RD) < -126) { BUS=1 } else { BUS=BUS }
if (RM or RN == NAN) { BIS=1 } else { BIS=BIS }
BVS = BVS | BV;
Corner cases: Overflow returns positive / negative infinity
(round-to-nearest), underflow returns positive / negative zero.
"""
if is16bit:
inst.bits &= 0xffff
rn = signed(s.rf[inst.rn])
result = float(rn)
result_bits = float2bits(result)
# RD = RN <OP> RM
s.rf[inst.rd] = trim_32(result_bits)
# BN = RD[31]
s.BN = bool((result_bits >> 31) & 1)
# if (RD[30:0] == 0) { BZ=1 } else { BZ=0 }
s.BZ = True if abs(result) < 0.0001 else False
# if (UnbiasedExponent(RD) > 127) { BV=1 } else { BV=0 }
s.BV = True if get_exponent_as_decimal(s.rf[inst.rd]) > 127 else False
# if (UbiasedExponent(RD) < -126) { BUS=1 } else { BUS=BUS }
if get_exponent_as_decimal(s.rf[inst.rd]) < -126:
s.BUS = True
# BVS = BVS | BV;
s.BVS = s.BVS | s.BV
# No exceptions for float instruction.
if s.CTIMER0CONFIG == s.timer_config['FPU VALID'] and not s.BIS:
s.rf[revelation.isa.reg_map['CTIMER0']] -= 1
if s.CTIMER1CONFIG == s.timer_config['FPU VALID'] and not s.BIS:
s.rf[revelation.isa.reg_map['CTIMER1']] -= 1
s.debug_flags()
s.pc += 2 if is16bit else 4
return exec_float


def make_fix_executor(is16bit):
def exec_fix(s, inst):
"""
RD = fix(RN)
BN = RD[31]
if (RD[30:0] == 0) { BZ=1 } else { BZ=0 }
if (UnbiasedExponent(RD) > 127) { BV=1 } else { BV=0 }
if (UbiasedExponent(RD) < -126) { BUS=1 } else { BUS=BUS }
if (RM or RN == NAN) { BIS=1 } else { BIS=BIS }
BVS = BVS | BV;
Corner cases: A NAN input returns a floating-point all ones result. All
underflow results, or input which are zero or denormal, return zero.
Overflow result always returns a signed saturated result: 0x7fffffff for
positive, and 0x80000000 for negative.
"""
if is16bit:
inst.bits &= 0xffff
rn = bits2float(s.rf[inst.rn])
if is_nan(s.rf[inst.rn]):
result = 0xffffffff
else:
result = int(rn)
if result != trim_32(result) and result > 0: # Overflow (positive)
result = 0x7fffffff
if result != trim_32(result) and result < 0: # Overflow (negative)
result = 0x80000000
# RD = RN <OP> RM
s.rf[inst.rd] = result
# BN = RD[31]
s.BN = bool((result >> 31) & 1)
# if (RD[30:0] == 0) { BZ=1 } else { BZ=0 }
s.BZ = True if abs(result) < 0.0001 else False
# if (UnbiasedExponent(RD) > 127) { BV=1 } else { BV=0 }
s.BV = True if get_exponent_as_decimal(s.rf[inst.rd]) > 127 else False
# if (UbiasedExponent(RD) < -126) { BUS=1 } else { BUS=BUS }
if get_exponent_as_decimal(s.rf[inst.rd]) < -126:
s.BUS = True
# BVS = BVS | BV;
s.BVS = s.BVS | s.BV
# FIXME: Find out whether fix generates interrupts.
if s.CTIMER0CONFIG == s.timer_config['FPU VALID'] and not s.BIS:
s.rf[revelation.isa.reg_map['CTIMER0']] -= 1
if s.CTIMER1CONFIG == s.timer_config['FPU VALID'] and not s.BIS:
s.rf[revelation.isa.reg_map['CTIMER1']] -= 1
s.debug_flags()
s.pc += 2 if is16bit else 4
return exec_fix


def make_fabs_executor(is16bit):
def exec_fabs(s, inst):
"""
RD = abs(RN)
BN = RD[31]
if (RD[30:0] == 0) { BZ=1 } else { BZ=0 }
if (UnbiasedExponent(RD) > 127) { BV=1 } else { BV=0 }
if (UbiasedExponent(RD) < -126) { BUS=1 } else { BUS=BUS }
if (RM or RN == NAN) { BIS=1 } else { BIS=BIS }
BVS = BVS | BV;
"""
if is16bit:
inst.bits &= 0xffff
rn = bits2float(s.rf[inst.rn])
result = abs(rn)
# 'result' is always a Python float, result_bits is an int.
result_bits = float2bits(result)
# RD = RN <OP> RM
s.rf[inst.rd] = trim_32(result_bits)
# BN = RD[31]
s.BN = bool((result_bits >> 31) & 1)
# if (RD[30:0] == 0) { BZ=1 } else { BZ=0 }
s.BZ = True if abs(result) < 0.0001 else False
# if (RM or RN == NAN) { BIS=1 } else { BIS=BIS }
if is_nan(s.rf[inst.rn]):
s.BIS = True
# BVS = BVS | BV;
s.BVS = s.BVS | s.BV
# Deal with fpu interrupts.
if s.CTIMER0CONFIG == s.timer_config['FPU VALID'] and not s.BIS:
s.rf[revelation.isa.reg_map['CTIMER0']] -= 1 # pragma: no cover
if s.CTIMER1CONFIG == s.timer_config['FPU VALID'] and not s.BIS:
s.rf[revelation.isa.reg_map['CTIMER1']] -= 1 # pragma: no cover
s.debug_flags()
s.pc += 2 if is16bit else 4
return exec_fabs


def make_farith_executor(name, is16bit, is_unary=False):
def make_farith_executor(name, is16bit):
def farith(s, inst):
"""
RD = RN <OP> RM
Expand All @@ -24,7 +152,6 @@ def farith(s, inst):
rd = bits2float(s.rf[inst.rd])
rn = bits2float(s.rf[inst.rn])
rm = bits2float(s.rf[inst.rm])
# Binary operations.
if name == 'add': # FADD
result = rn + rm
elif name == 'sub': # FSUB
Expand All @@ -35,17 +162,7 @@ def farith(s, inst):
result = rd + (rn * rm)
elif name == 'msub': # FMSUB
result = rd - (rn * rm)
# Unary operations.
elif name == 'float': # FLOAT
result = float(signed(s.rf[inst.rn]))
elif name == 'fix': # FIX
if math.isnan(rn):
result = 0xffffffff
else:
result = int(rn)
elif name == 'abs': # FABS
result = abs(rn)
# 'result' is always a Python float, result_bits is an int.
# 'result' is a Python float, result_bits is a signed integer.
result_bits = float2bits(result)
# RD = RN <OP> RM
s.rf[inst.rd] = trim_32(result if name == 'fix' else result_bits)
Expand All @@ -59,9 +176,7 @@ def farith(s, inst):
if get_exponent_as_decimal(s.rf[inst.rd]) < -126:
s.BUS = True
# if (RM or RN == NAN) { BIS=1 } else { BIS=BIS }
if ((is_unary and math.isnan(rn)) or
(not is_unary) and
(math.isnan(rn) or math.isnan(rm))):
if is_nan(s.rf[inst.rn]) or is_nan(s.rf[inst.rm]):
s.BIS = True
# BVS = BVS | BV;
s.BVS = s.BVS | s.BV
Expand Down
12 changes: 6 additions & 6 deletions revelation/isa.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,17 +219,17 @@
execute_fmul16 = execute_farith.make_farith_executor('mul', True)
execute_fmadd16 = execute_farith.make_farith_executor('madd', True)
execute_fmsub16 = execute_farith.make_farith_executor('msub', True)
execute_float16 = execute_farith.make_farith_executor('float', True)
execute_fix16 = execute_farith.make_farith_executor('fix', True)
execute_fabs16 = execute_farith.make_farith_executor('abs', True)
execute_float16 = execute_farith.make_float_executor(True)
execute_fix16 = execute_farith.make_fix_executor(True)
execute_fabs16 = execute_farith.make_fabs_executor(True)
execute_fadd32 = execute_farith.make_farith_executor('add', False)
execute_fsub32 = execute_farith.make_farith_executor('sub', False)
execute_fmul32 = execute_farith.make_farith_executor('mul', False)
execute_fmadd32 = execute_farith.make_farith_executor('madd', False)
execute_fmsub32 = execute_farith.make_farith_executor('msub', False)
execute_float32 = execute_farith.make_farith_executor('float', False)
execute_fix32 = execute_farith.make_farith_executor('fix', False)
execute_fabs32 = execute_farith.make_farith_executor('abs', False)
execute_float32 = execute_farith.make_float_executor(False)
execute_fix32 = execute_farith.make_fix_executor(False)
execute_fabs32 = execute_farith.make_fabs_executor(False)

# Move instructions
execute_movcond32 = execute_mov.make_movcond_executor(False)
Expand Down
16 changes: 16 additions & 0 deletions revelation/test/c/float_corner_cases.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* Some floating point corner cases. */
#include <float.h>
#include <stdio.h>
#include <stdint.h>

int main() {
int val_i = 0xffffffff;
float val_f = 0xffffffff;
float convert_f = (float)val_i;
int convert_i = (int)val_f;
printf("Signed integer value = %d, %x\n", val_i, val_i);
printf("Float value = %.*e\n", DECIMAL_DIG, val_f);
printf("Convert float to signed integer: %d, %x\n", convert_i, convert_i);
printf("Convert signed integer to float = %.*e\n", DECIMAL_DIG, convert_f);
return 0;
}
Binary file added revelation/test/c/float_corner_cases.elf
Binary file not shown.
6 changes: 4 additions & 2 deletions revelation/test/c/interrupt_ctimer0.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <e-lib.h>
#include <math.h>
#include <stdio.h>

void timer_handler();
Expand All @@ -9,7 +10,7 @@ void __attribute__((interrupt)) timer_handler() {

int main() {
float a = 1., b = 2., c = 0.;
int i = 0;
int i = 0, d = 0;

/* Attach and set-up timer interrupt. */
e_irq_attach(E_TIMER0_INT, timer_handler);
Expand All @@ -21,7 +22,8 @@ int main() {
e_ctimer_start(E_CTIMER_0, E_CTIMER_FPU_INST);

for (i = 0; i < 15; i++) {
c = a + b;
c = fabs(a + b + (float)d);
d = (int)c;
}
/* Interrupt should be triggered here. */

Expand Down
Binary file modified revelation/test/c/interrupt_ctimer0.elf
Binary file not shown.
6 changes: 4 additions & 2 deletions revelation/test/c/interrupt_ctimer1.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <e-lib.h>
#include <math.h>
#include <stdio.h>

void timer_handler();
Expand All @@ -9,7 +10,7 @@ void __attribute__((interrupt)) timer_handler() {

int main() {
float a = 1., b = 2., c = 0.;
int i = 0;
int i = 0, d = 0;

/* Attach and set-up timer interrupt. */
e_irq_attach(E_TIMER1_INT, timer_handler);
Expand All @@ -21,7 +22,8 @@ int main() {
e_ctimer_start(E_CTIMER_1, E_CTIMER_FPU_INST);

for (i = 0; i < 15; i++) {
c = a + b;
c = fabs(a + b + (float)d);
d = (int)c;
}
/* Interrupt should be triggered here. */

Expand Down
Binary file modified revelation/test/c/interrupt_ctimer1.elf
Binary file not shown.
5 changes: 5 additions & 0 deletions revelation/test/test_compiled_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
('div_by_zero.elf', 'Exception_isr 214023\nEnd.\n'),
('get_core_coords.elf', 'Core id: 808 row=32 col=8\n'),
('fib_print.elf', '10946\n'),
('float_corner_cases.elf', 'Signed integer value = -1, ffffffff\n'
'Float value = 4.29496729600000000e+09\n'
'Convert float to signed integer: 2147483647,'
' 7fffffff\nConvert signed integer to float ='
' -1.00000000000000000e+00\n'),
('hello.elf', 'Hello, world!\n'),
('interrupt_fire_all.elf', 'Interrupt E_SW_EXCEPTION ... handler fired.\n'
'Interrupt E_MEM_FAULT ... handler fired.\n'
Expand Down

0 comments on commit 595129a

Please sign in to comment.