From 559b42287c2fceba11134f85b5dad0abdbadba9b Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Mon, 8 Jul 2019 07:38:31 +0100 Subject: [PATCH] add regressions and corner cases --- src/ieee754/fpadd/test/add_data32.py | 2 +- src/ieee754/fpadd/test/test_fpadd_pipe_32.py | 31 ++++++++ src/ieee754/fpcommon/test/case_gen.py | 79 +++++++++++++++++++ src/ieee754/fpcommon/test/fpmux.py | 75 ++++++++++-------- src/ieee754/fpcommon/test/unit_test_single.py | 6 +- 5 files changed, 158 insertions(+), 35 deletions(-) create mode 100644 src/ieee754/fpadd/test/test_fpadd_pipe_32.py create mode 100644 src/ieee754/fpcommon/test/case_gen.py diff --git a/src/ieee754/fpadd/test/add_data32.py b/src/ieee754/fpadd/test/add_data32.py index e50afdad..d7836365 100644 --- a/src/ieee754/fpadd/test/add_data32.py +++ b/src/ieee754/fpadd/test/add_data32.py @@ -42,7 +42,7 @@ def regressions(): yield 0x4E5693A4, 0x42500000 yield 0x42500000, 0x4E5693A4 - yield 0x08000000, 0xff8000010 + yield 0x08000000, 0xff800001 yield 0x22cb525a, 0xadd79efa yield 0x40000000, 0xC0000000 yield 0x83e73d5c, 0x1c800000 diff --git a/src/ieee754/fpadd/test/test_fpadd_pipe_32.py b/src/ieee754/fpadd/test/test_fpadd_pipe_32.py new file mode 100644 index 00000000..d6cbd599 --- /dev/null +++ b/src/ieee754/fpadd/test/test_fpadd_pipe_32.py @@ -0,0 +1,31 @@ +""" test of FPADDMuxInOut +""" + +from ieee754.fpadd.pipeline import (FPADDMuxInOut,) +from ieee754.fpcommon.test.fpmux import runfp, repeat +from ieee754.fpcommon.test.case_gen import get_corner_cases +from ieee754.fpcommon.test import unit_test_single +from ieee754.fpadd.test.add_data32 import regressions + +from sfpy import Float32 +from operator import add + +def test_pipe_fp32_cornercases(): + dut = FPADDMuxInOut(32, 4) + vals = repeat(dut.num_rows, get_corner_cases(unit_test_single)) + runfp(dut, 32, "test_fpadd_pipe_fp32_cornercases", Float32, add, vals=vals) + +def test_pipe_fp32_regressions(): + dut = FPADDMuxInOut(32, 4) + vals = repeat(dut.num_rows, regressions()) + runfp(dut, 32, "test_fpadd_pipe_fp32_regressions", Float32, add, vals=vals) + +def test_pipe_fp32_rand(): + dut = FPADDMuxInOut(32, 4) + runfp(dut, 32, "test_fpadd_pipe_fp32_rand", Float32, add) + +if __name__ == '__main__': + test_pipe_fp32_rand() + test_pipe_fp32_regressions() + test_pipe_fp32_cornercases() + diff --git a/src/ieee754/fpcommon/test/case_gen.py b/src/ieee754/fpcommon/test/case_gen.py new file mode 100644 index 00000000..0d7aa9bd --- /dev/null +++ b/src/ieee754/fpcommon/test/case_gen.py @@ -0,0 +1,79 @@ +from random import randint +from random import seed + +import sys +from sfpy import Float32 + +corner_cases = [0x80000000, 0x00000000, 0x7f800000, 0xff800000, + 0x7fc00000, 0xffc00000] + +def get_corner_cases(mod): + #corner cases + from itertools import permutations + corner_cases = [mod.zero(1), mod.zero(0), + mod.inf(1), mod.inf(0), + mod.nan(1), mod.nan(0)] + stimulus_a = [i[0] for i in permutations(corner_cases, 2)] + stimulus_b = [i[1] for i in permutations(corner_cases, 2)] + return zip(stimulus_a, stimulus_b) + + +def run_fpunit_2(dut, stimulus_a, stimulus_b, op, get_case_fn): + yield from run_fpunit(dut, stimulus_a, stimulus_b, op, get_case_fn) + yield from run_fpunit(dut, stimulus_b, stimulus_a, op, get_case_fn) + +def run_cases(dut, count, op, fixed_num, maxcount, get_case_fn): + if isinstance(fixed_num, int): + stimulus_a = [fixed_num for i in range(maxcount)] + report = hex(fixed_num) + else: + stimulus_a = fixed_num + report = "random" + + stimulus_b = [randint(0, 1<<32) for i in range(maxcount)] + yield from run_fpunit_2(dut, stimulus_a, stimulus_b, op, get_case_fn) + count += len(stimulus_a) + print (count, "vectors passed 2^32", report) + + # non-canonical NaNs. + stimulus_b = [set_exponent(randint(0, 1<<32), 128) \ + for i in range(maxcount)] + yield from run_fpunit_2(dut, stimulus_a, stimulus_b, op, get_case_fn) + count += len(stimulus_a) + print (count, "vectors passed Non-Canonical NaN", report) + + # -127 + stimulus_b = [set_exponent(randint(0, 1<<32), -127) \ + for i in range(maxcount)] + yield from run_fpunit_2(dut, stimulus_a, stimulus_b, op, get_case_fn) + count += len(stimulus_a) + print (count, "vectors passed exp=-127", report) + + # nearly zero + stimulus_b = [set_exponent(randint(0, 1<<32), -126) \ + for i in range(maxcount)] + yield from run_fpunit_2(dut, stimulus_a, stimulus_b, op, get_case_fn) + count += len(stimulus_a) + print (count, "vectors passed exp=-126", report) + + # nearly inf + stimulus_b = [set_exponent(randint(0, 1<<32), 127) \ + for i in range(maxcount)] + yield from run_fpunit_2(dut, stimulus_a, stimulus_b, op, get_case_fn) + count += len(stimulus_a) + print (count, "vectors passed exp=127", report) + + return count + +def run_edge_cases(dut, count, op, get_case_fn, maxcount=10, num_loops=1000): + #edge cases + for testme in corner_cases: + count = yield from run_cases(dut, count, op, testme, + maxcount, get_case_fn) + + for i in range(num_loops): + stimulus_a = [randint(0, 1<<32) for i in range(maxcount)] + count = yield from run_cases(dut, count, op, stimulus_a, 10, + get_case_fn) + return count + diff --git a/src/ieee754/fpcommon/test/fpmux.py b/src/ieee754/fpcommon/test/fpmux.py index 19967e58..15441fe7 100644 --- a/src/ieee754/fpcommon/test/fpmux.py +++ b/src/ieee754/fpcommon/test/fpmux.py @@ -30,6 +30,7 @@ class InputTest: self.di[muxid][i] = (op1, ) else: (op1, op2, ) = vals.pop(0) + print ("test", hex(op1), hex(op2)) res = self.fpop(self.fpkls(op1), self.fpkls(op2)) self.di[muxid][i] = (op1, op2) self.do[muxid].append(res.bits) @@ -119,44 +120,56 @@ class InputTest: print ("recv ended", muxid) -class InputTestRandom(InputTest): - def __init__(self, dut, width, fpkls, fpop, single_op=False, n_vals=10): - vals = [] - for muxid in range(dut.num_rows): - for i in range(n_vals): - if single_op: - op1 = randint(0, (1<