From: Luke Kenneth Casson Leighton Date: Thu, 2 May 2019 14:13:00 +0000 (+0100) Subject: move common unit test code X-Git-Tag: ls180-24jan2020~1075 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c3c766cd5a2052f23ed8ede119a9bff7ef00da98;p=ieee754fpu.git move common unit test code --- diff --git a/src/ieee754/add/unit_test_double.py b/src/ieee754/add/unit_test_double.py deleted file mode 100644 index 8cc097f2..00000000 --- a/src/ieee754/add/unit_test_double.py +++ /dev/null @@ -1,227 +0,0 @@ -import sys -from random import randint -from random import seed - -from sfpy import Float64 - -def get_mantissa(x): - return x & 0x000fffffffffffff - -def get_exponent(x): - return ((x & 0x7ff0000000000000) >> 52) - 1023 - -def get_sign(x): - return ((x & 0x8000000000000000) >> 63) - -def is_nan(x): - return get_exponent(x) == 1024 and get_mantissa(x) != 0 - -def is_inf(x): - return get_exponent(x) == 1024 and get_mantissa(x) == 0 - -def is_pos_inf(x): - return is_inf(x) and not get_sign(x) - -def is_neg_inf(x): - return is_inf(x) and get_sign(x) - -def match(x, y): - return ( - (is_pos_inf(x) and is_pos_inf(y)) or - (is_neg_inf(x) and is_neg_inf(y)) or - (is_nan(x) and is_nan(y)) or - (x == y) - ) - -def get_case(dut, a, b): - yield dut.in_a.v.eq(a) - yield dut.in_a.stb.eq(1) - yield - yield - a_ack = (yield dut.in_a.ack) - assert a_ack == 0 - yield dut.in_b.v.eq(b) - yield dut.in_b.stb.eq(1) - b_ack = (yield dut.in_b.ack) - assert b_ack == 0 - - while True: - yield - out_z_stb = (yield dut.out_z.stb) - if not out_z_stb: - continue - yield dut.in_a.stb.eq(0) - yield dut.in_b.stb.eq(0) - yield dut.out_z.ack.eq(1) - yield - yield dut.out_z.ack.eq(0) - yield - yield - break - - out_z = yield dut.out_z.v - return out_z - -def check_case(dut, a, b, z): - out_z = yield from get_case(dut, a, b) - assert out_z == z, "Output z 0x%x not equal to expected 0x%x" % (out_z, z) - - -def run_test(dut, stimulus_a, stimulus_b, op): - - expected_responses = [] - actual_responses = [] - for a, b in zip(stimulus_a, stimulus_b): - af = Float64.from_bits(a) - bf = Float64.from_bits(b) - z = op(af, bf) - expected_responses.append(z.get_bits()) - #print (af, bf, z) - actual = yield from get_case(dut, a, b) - actual_responses.append(actual) - - if len(actual_responses) < len(expected_responses): - print ("Fail ... not enough results") - exit(0) - - for exp, act, a, b in zip(expected_responses, actual_responses, - stimulus_a, stimulus_b): - passed = match(exp, act) - - if not passed: - - print ("Fail ... expected:", hex(exp), "actual:", hex(act)) - - print (hex(a)) - print ("a mantissa:", a & 0x000fffffffffffff) - print ("a exponent:", ((a & 0x7ff0000000000000) >> 52)\ - - 1023) - print ("a sign:", ((a & 0x8000000000000000) >> 63)) - - print (hex(b)) - print ("b mantissa:", b & 0x000fffffffffffff) - print ("b exponent:", ((b & 0x7ff0000000000000) >> 52)\ - - 1023) - print ("b sign:", ((b & 0x8000000000000000) >> 63)) - - print (hex(exp)) - print ("expected mantissa:", exp & 0x000fffffffffffff) - print ("expected exponent:", ((exp & 0x7ff0000000000000) >> 52)\ - - 1023) - print ("expected sign:", ((exp & 0x8000000000000000) >> 63)) - - print (hex(act)) - print ("actual mantissa:", act & 0x000fffffffffffff) - print ("actual exponent:", ((act & 0x7ff0000000000000) >> 52)\ - - 1023) - print ("actual sign:", ((act & 0x8000000000000000) >> 63)) - - sys.exit(0) - - -def run_corner_cases(dut, count, op): - #corner cases - from itertools import permutations - stimulus_a = [i[0] for i in permutations([ - 0x8000000000000000, - 0x0000000000000000, - 0x7ff8000000000000, - 0xfff8000000000000, - 0x7ff0000000000000, - 0xfff0000000000000 - ], 2)] - stimulus_b = [i[1] for i in permutations([ - 0x8000000000000000, - 0x0000000000000000, - 0x7ff8000000000000, - 0xfff8000000000000, - 0x7ff0000000000000, - 0xfff0000000000000 - ], 2)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - -def run_edge_cases(dut, count, op): - #edge cases - stimulus_a = [0x8000000000000000 for i in range(1000)] - stimulus_b = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_a = [0x0000000000000000 for i in range(1000)] - stimulus_b = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_b = [0x8000000000000000 for i in range(1000)] - stimulus_a = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_b = [0x0000000000000000 for i in range(1000)] - stimulus_a = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_a = [0x7FF8000000000000 for i in range(1000)] - stimulus_b = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_a = [0xFFF8000000000000 for i in range(1000)] - stimulus_b = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_b = [0x7FF8000000000000 for i in range(1000)] - stimulus_a = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_b = [0xFFF8000000000000 for i in range(1000)] - stimulus_a = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_a = [0x7FF0000000000000 for i in range(1000)] - stimulus_b = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_a = [0xFFF0000000000000 for i in range(1000)] - stimulus_b = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_b = [0x7FF0000000000000 for i in range(1000)] - stimulus_a = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_b = [0xFFF0000000000000 for i in range(1000)] - stimulus_a = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - #seed(0) - for i in range(100000): - stimulus_a = [randint(0, 1<<64) for i in range(1000)] - stimulus_b = [randint(0, 1<<64) for i in range(1000)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += 1000 - print (count, "random vectors passed") - diff --git a/src/ieee754/add/unit_test_half.py b/src/ieee754/add/unit_test_half.py deleted file mode 100644 index 73c9b653..00000000 --- a/src/ieee754/add/unit_test_half.py +++ /dev/null @@ -1,211 +0,0 @@ -from random import randint -from random import seed - -import sys -from sfpy import Float16 - -def get_mantissa(x): - return 0x3ff & x - -def get_exponent(x): - return ((x & 0xf800) >> 11) - 15 - -def get_sign(x): - return ((x & 0x8000) >> 15) - -def is_nan(x): - return get_exponent(x) == 16 and get_mantissa(x) != 0 - -def is_inf(x): - return get_exponent(x) == 16 and get_mantissa(x) == 0 - -def is_pos_inf(x): - return is_inf(x) and not get_sign(x) - -def is_neg_inf(x): - return is_inf(x) and get_sign(x) - -def match(x, y): - return ( - (is_pos_inf(x) and is_pos_inf(y)) or - (is_neg_inf(x) and is_neg_inf(y)) or - (is_nan(x) and is_nan(y)) or - (x == y) - ) - -def get_case(dut, a, b): - yield dut.in_a.v.eq(a) - yield dut.in_a.stb.eq(1) - yield - yield - a_ack = (yield dut.in_a.ack) - assert a_ack == 0 - yield dut.in_b.v.eq(b) - yield dut.in_b.stb.eq(1) - b_ack = (yield dut.in_b.ack) - assert b_ack == 0 - - while True: - yield - out_z_stb = (yield dut.out_z.stb) - if not out_z_stb: - continue - yield dut.in_a.stb.eq(0) - yield dut.in_b.stb.eq(0) - yield dut.out_z.ack.eq(1) - yield - yield dut.out_z.ack.eq(0) - yield - yield - break - - out_z = yield dut.out_z.v - return out_z - -def check_case(dut, a, b, z): - out_z = yield from get_case(dut, a, b) - assert out_z == z, "Output z 0x%x not equal to expected 0x%x" % (out_z, z) - - -def run_test(dut, stimulus_a, stimulus_b, op): - - expected_responses = [] - actual_responses = [] - for a, b in zip(stimulus_a, stimulus_b): - af = Float16.from_bits(a) - bf = Float16.from_bits(b) - z = op(af, bf) - expected_responses.append(z.get_bits()) - #print (af, bf, z) - actual = yield from get_case(dut, a, b) - actual_responses.append(actual) - - if len(actual_responses) < len(expected_responses): - print ("Fail ... not enough results") - exit(0) - - for expected, actual, a, b in zip(expected_responses, actual_responses, - stimulus_a, stimulus_b): - passed = match(expected, actual) - - if not passed: - - print ("Fail ... expected:", hex(expected), "actual:", hex(actual)) - - print (hex(a)) - print ("a mantissa:", get_mantissa(a)) - print ("a exponent:", get_exponent(a)) - print ("a sign:", get_sign(a)) - - print (hex(b)) - print ("b mantissa:", get_mantissa(b)) - print ("b exponent:", get_exponent(b)) - print ("b sign:", get_sign(b)) - - print (hex(expected)) - print ("expected mantissa:", get_mantissa(expected)) - print ("expected exponent:", get_exponent(expected)) - print ("expected sign:", get_sign(expected)) - - print (hex(actual)) - print ("actual mantissa:", get_mantissa(actual)) - print ("actual exponent:", get_exponent(actual)) - print ("actual sign:", get_sign(actual)) - - sys.exit(0) - -def run_corner_cases(dut, count, op): - #corner cases - corners = [0x8000, 0x0000, 0x7800, 0xf800, 0x7c00, 0xfc00] - from itertools import permutations - stimulus_a = [i[0] for i in permutations(corners, 2)] - stimulus_b = [i[1] for i in permutations(corners, 2)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - -def run_edge_cases(dut, count, op): - maxint16 = 1<<16 - maxcount = 10 - #edge cases - stimulus_a = [0x8000 for i in range(maxcount)] - stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_a = [0x0000 for i in range(maxcount)] - stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_b = [0x8000 for i in range(maxcount)] - stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_b = [0x0000 for i in range(maxcount)] - stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_a = [0x7800 for i in range(maxcount)] - stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_a = [0xF800 for i in range(maxcount)] - stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_b = [0x7800 for i in range(maxcount)] - stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_b = [0xF800 for i in range(maxcount)] - stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_a = [0x7C00 for i in range(maxcount)] - stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_a = [0xFC00 for i in range(maxcount)] - stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_b = [0x7C00 for i in range(maxcount)] - stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - stimulus_b = [0xFC00 for i in range(maxcount)] - stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += len(stimulus_a) - print (count, "vectors passed") - - #seed(0) - for i in range(100000): - stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] - stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] - yield from run_test(dut, stimulus_a, stimulus_b, op) - count += maxcount - print (count, "random vectors passed") - diff --git a/src/ieee754/add/unit_test_single.py b/src/ieee754/add/unit_test_single.py deleted file mode 100644 index 2b0d9e56..00000000 --- a/src/ieee754/add/unit_test_single.py +++ /dev/null @@ -1,255 +0,0 @@ -from random import randint -from random import seed - -import sys -from sfpy import Float32 - -def get_mantissa(x): - return 0x7fffff & x - -def get_exponent(x): - return ((x & 0x7f800000) >> 23) - 127 - -def set_exponent(x, e): - return (x & ~0x7f800000) | ((e+127) << 23) - -def get_sign(x): - return ((x & 0x80000000) >> 31) - -def is_nan(x): - return get_exponent(x) == 128 and get_mantissa(x) != 0 - -def is_inf(x): - return get_exponent(x) == 128 and get_mantissa(x) == 0 - -def is_pos_inf(x): - return is_inf(x) and not get_sign(x) - -def is_neg_inf(x): - return is_inf(x) and get_sign(x) - -def match(x, y): - return ( - (is_pos_inf(x) and is_pos_inf(y)) or - (is_neg_inf(x) and is_neg_inf(y)) or - (is_nan(x) and is_nan(y)) or - (x == y) - ) - -def get_rs_case(dut, a, b, mid): - in_a, in_b = dut.rs[0] - out_z = dut.res[0] - yield dut.ids.in_mid.eq(mid) - yield in_a.v.eq(a) - yield in_a.valid_i.eq(1) - yield - yield - yield - yield - a_ack = (yield in_a.ready_o) - assert a_ack == 0 - - yield in_a.valid_i.eq(0) - - yield in_b.v.eq(b) - yield in_b.valid_i.eq(1) - yield - yield - b_ack = (yield in_b.ready_o) - assert b_ack == 0 - - yield in_b.valid_i.eq(0) - - yield out_z.ready_i.eq(1) - - while True: - out_z_stb = (yield out_z.valid_o) - if not out_z_stb: - yield - continue - vout_z = yield out_z.v - #out_mid = yield dut.ids.out_mid - yield out_z.ready_i.eq(0) - yield - break - - return vout_z, mid - -def check_rs_case(dut, a, b, z, mid=None): - if mid is None: - mid = randint(0, 6) - mid = 0 - out_z, out_mid = yield from get_rs_case(dut, a, b, mid) - assert out_z == z, "Output z 0x%x not equal to expected 0x%x" % (out_z, z) - assert out_mid == mid, "Output mid 0x%x != expected 0x%x" % (out_mid, mid) - - -def get_case(dut, a, b, mid): - #yield dut.in_mid.eq(mid) - yield dut.in_a.v.eq(a) - yield dut.in_a.valid_i_test.eq(1) - yield - yield - yield - yield - a_ack = (yield dut.in_a.ready_o) - assert a_ack == 0 - - yield dut.in_a.valid_i.eq(0) - - yield dut.in_b.v.eq(b) - yield dut.in_b.valid_i.eq(1) - yield - yield - b_ack = (yield dut.in_b.ready_o) - assert b_ack == 0 - - yield dut.in_b.valid_i.eq(0) - - yield dut.out_z.ready_i.eq(1) - - while True: - out_z_stb = (yield dut.out_z.valid_o) - if not out_z_stb: - yield - continue - out_z = yield dut.out_z.v - #out_mid = yield dut.out_mid - yield dut.out_z.ready_i.eq(0) - yield - break - - return out_z, mid # TODO: mid - -def check_case(dut, a, b, z, mid=None): - if mid is None: - mid = randint(0, 6) - mid = 0 - out_z, out_mid = yield from get_case(dut, a, b, mid) - assert out_z == z, "Output z 0x%x not equal to expected 0x%x" % (out_z, z) - assert out_mid == mid, "Output mid 0x%x != expected 0x%x" % (out_mid, mid) - - -def run_test(dut, stimulus_a, stimulus_b, op, get_case_fn): - - expected_responses = [] - actual_responses = [] - for a, b in zip(stimulus_a, stimulus_b): - mid = randint(0, 6) - mid = 0 - af = Float32.from_bits(a) - bf = Float32.from_bits(b) - z = op(af, bf) - expected_responses.append((z.get_bits(), mid)) - actual = yield from get_case_fn(dut, a, b, mid) - actual_responses.append(actual) - - if len(actual_responses) < len(expected_responses): - print ("Fail ... not enough results") - exit(0) - - for expected, actual, a, b in zip(expected_responses, actual_responses, - stimulus_a, stimulus_b): - passed = match(expected[0], actual[0]) - if expected[1] != actual[1]: # check mid - print ("MID failed", expected[1], actual[1]) - sys.exit(0) - - if not passed: - - expected = expected[0] - actual = actual[0] - print ("Fail ... expected:", hex(expected), "actual:", hex(actual)) - - print (hex(a)) - print ("a mantissa:", a & 0x7fffff) - print ("a exponent:", ((a & 0x7f800000) >> 23) - 127) - print ("a sign:", ((a & 0x80000000) >> 31)) - - print (hex(b)) - print ("b mantissa:", b & 0x7fffff) - print ("b exponent:", ((b & 0x7f800000) >> 23) - 127) - print ("b sign:", ((b & 0x80000000) >> 31)) - - print (hex(expected)) - print ("expected mantissa:", expected & 0x7fffff) - print ("expected exponent:", ((expected & 0x7f800000) >> 23) - 127) - print ("expected sign:", ((expected & 0x80000000) >> 31)) - - print (hex(actual)) - print ("actual mantissa:", actual & 0x7fffff) - print ("actual exponent:", ((actual & 0x7f800000) >> 23) - 127) - print ("actual sign:", ((actual & 0x80000000) >> 31)) - - sys.exit(0) - -corner_cases = [0x80000000, 0x00000000, 0x7f800000, 0xff800000, - 0x7fc00000, 0xffc00000] - -def run_corner_cases(dut, count, op, get_case_fn): - #corner cases - from itertools import permutations - stimulus_a = [i[0] for i in permutations(corner_cases, 2)] - stimulus_b = [i[1] for i in permutations(corner_cases, 2)] - yield from run_test(dut, stimulus_a, stimulus_b, op, get_case_fn) - count += len(stimulus_a) - print (count, "vectors passed") - -def run_test_2(dut, stimulus_a, stimulus_b, op, get_case_fn): - yield from run_test(dut, stimulus_a, stimulus_b, op, get_case_fn) - yield from run_test(dut, stimulus_b, stimulus_a, op, get_case_fn) - -def run_cases(dut, count, op, fixed_num, num_entries, get_case_fn): - if isinstance(fixed_num, int): - stimulus_a = [fixed_num for i in range(num_entries)] - report = hex(fixed_num) - else: - stimulus_a = fixed_num - report = "random" - - stimulus_b = [randint(0, 1<<32) for i in range(num_entries)] - yield from run_test_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(num_entries)] - yield from run_test_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(num_entries)] - yield from run_test_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(num_entries)] - yield from run_test_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(num_entries)] - yield from run_test_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): - #edge cases - for testme in corner_cases: - count = yield from run_cases(dut, count, op, testme, 10, get_case_fn) - - for i in range(100000): - stimulus_a = [randint(0, 1<<32) for i in range(10)] - count = yield from run_cases(dut, count, op, stimulus_a, 10, - get_case_fn) - return count - diff --git a/src/ieee754/fpcommon/test/__init__.py b/src/ieee754/fpcommon/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/ieee754/fpcommon/test/unit_test_double.py b/src/ieee754/fpcommon/test/unit_test_double.py new file mode 100644 index 00000000..8cc097f2 --- /dev/null +++ b/src/ieee754/fpcommon/test/unit_test_double.py @@ -0,0 +1,227 @@ +import sys +from random import randint +from random import seed + +from sfpy import Float64 + +def get_mantissa(x): + return x & 0x000fffffffffffff + +def get_exponent(x): + return ((x & 0x7ff0000000000000) >> 52) - 1023 + +def get_sign(x): + return ((x & 0x8000000000000000) >> 63) + +def is_nan(x): + return get_exponent(x) == 1024 and get_mantissa(x) != 0 + +def is_inf(x): + return get_exponent(x) == 1024 and get_mantissa(x) == 0 + +def is_pos_inf(x): + return is_inf(x) and not get_sign(x) + +def is_neg_inf(x): + return is_inf(x) and get_sign(x) + +def match(x, y): + return ( + (is_pos_inf(x) and is_pos_inf(y)) or + (is_neg_inf(x) and is_neg_inf(y)) or + (is_nan(x) and is_nan(y)) or + (x == y) + ) + +def get_case(dut, a, b): + yield dut.in_a.v.eq(a) + yield dut.in_a.stb.eq(1) + yield + yield + a_ack = (yield dut.in_a.ack) + assert a_ack == 0 + yield dut.in_b.v.eq(b) + yield dut.in_b.stb.eq(1) + b_ack = (yield dut.in_b.ack) + assert b_ack == 0 + + while True: + yield + out_z_stb = (yield dut.out_z.stb) + if not out_z_stb: + continue + yield dut.in_a.stb.eq(0) + yield dut.in_b.stb.eq(0) + yield dut.out_z.ack.eq(1) + yield + yield dut.out_z.ack.eq(0) + yield + yield + break + + out_z = yield dut.out_z.v + return out_z + +def check_case(dut, a, b, z): + out_z = yield from get_case(dut, a, b) + assert out_z == z, "Output z 0x%x not equal to expected 0x%x" % (out_z, z) + + +def run_test(dut, stimulus_a, stimulus_b, op): + + expected_responses = [] + actual_responses = [] + for a, b in zip(stimulus_a, stimulus_b): + af = Float64.from_bits(a) + bf = Float64.from_bits(b) + z = op(af, bf) + expected_responses.append(z.get_bits()) + #print (af, bf, z) + actual = yield from get_case(dut, a, b) + actual_responses.append(actual) + + if len(actual_responses) < len(expected_responses): + print ("Fail ... not enough results") + exit(0) + + for exp, act, a, b in zip(expected_responses, actual_responses, + stimulus_a, stimulus_b): + passed = match(exp, act) + + if not passed: + + print ("Fail ... expected:", hex(exp), "actual:", hex(act)) + + print (hex(a)) + print ("a mantissa:", a & 0x000fffffffffffff) + print ("a exponent:", ((a & 0x7ff0000000000000) >> 52)\ + - 1023) + print ("a sign:", ((a & 0x8000000000000000) >> 63)) + + print (hex(b)) + print ("b mantissa:", b & 0x000fffffffffffff) + print ("b exponent:", ((b & 0x7ff0000000000000) >> 52)\ + - 1023) + print ("b sign:", ((b & 0x8000000000000000) >> 63)) + + print (hex(exp)) + print ("expected mantissa:", exp & 0x000fffffffffffff) + print ("expected exponent:", ((exp & 0x7ff0000000000000) >> 52)\ + - 1023) + print ("expected sign:", ((exp & 0x8000000000000000) >> 63)) + + print (hex(act)) + print ("actual mantissa:", act & 0x000fffffffffffff) + print ("actual exponent:", ((act & 0x7ff0000000000000) >> 52)\ + - 1023) + print ("actual sign:", ((act & 0x8000000000000000) >> 63)) + + sys.exit(0) + + +def run_corner_cases(dut, count, op): + #corner cases + from itertools import permutations + stimulus_a = [i[0] for i in permutations([ + 0x8000000000000000, + 0x0000000000000000, + 0x7ff8000000000000, + 0xfff8000000000000, + 0x7ff0000000000000, + 0xfff0000000000000 + ], 2)] + stimulus_b = [i[1] for i in permutations([ + 0x8000000000000000, + 0x0000000000000000, + 0x7ff8000000000000, + 0xfff8000000000000, + 0x7ff0000000000000, + 0xfff0000000000000 + ], 2)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + +def run_edge_cases(dut, count, op): + #edge cases + stimulus_a = [0x8000000000000000 for i in range(1000)] + stimulus_b = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_a = [0x0000000000000000 for i in range(1000)] + stimulus_b = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_b = [0x8000000000000000 for i in range(1000)] + stimulus_a = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_b = [0x0000000000000000 for i in range(1000)] + stimulus_a = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_a = [0x7FF8000000000000 for i in range(1000)] + stimulus_b = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_a = [0xFFF8000000000000 for i in range(1000)] + stimulus_b = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_b = [0x7FF8000000000000 for i in range(1000)] + stimulus_a = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_b = [0xFFF8000000000000 for i in range(1000)] + stimulus_a = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_a = [0x7FF0000000000000 for i in range(1000)] + stimulus_b = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_a = [0xFFF0000000000000 for i in range(1000)] + stimulus_b = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_b = [0x7FF0000000000000 for i in range(1000)] + stimulus_a = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_b = [0xFFF0000000000000 for i in range(1000)] + stimulus_a = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + #seed(0) + for i in range(100000): + stimulus_a = [randint(0, 1<<64) for i in range(1000)] + stimulus_b = [randint(0, 1<<64) for i in range(1000)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += 1000 + print (count, "random vectors passed") + diff --git a/src/ieee754/fpcommon/test/unit_test_half.py b/src/ieee754/fpcommon/test/unit_test_half.py new file mode 100644 index 00000000..73c9b653 --- /dev/null +++ b/src/ieee754/fpcommon/test/unit_test_half.py @@ -0,0 +1,211 @@ +from random import randint +from random import seed + +import sys +from sfpy import Float16 + +def get_mantissa(x): + return 0x3ff & x + +def get_exponent(x): + return ((x & 0xf800) >> 11) - 15 + +def get_sign(x): + return ((x & 0x8000) >> 15) + +def is_nan(x): + return get_exponent(x) == 16 and get_mantissa(x) != 0 + +def is_inf(x): + return get_exponent(x) == 16 and get_mantissa(x) == 0 + +def is_pos_inf(x): + return is_inf(x) and not get_sign(x) + +def is_neg_inf(x): + return is_inf(x) and get_sign(x) + +def match(x, y): + return ( + (is_pos_inf(x) and is_pos_inf(y)) or + (is_neg_inf(x) and is_neg_inf(y)) or + (is_nan(x) and is_nan(y)) or + (x == y) + ) + +def get_case(dut, a, b): + yield dut.in_a.v.eq(a) + yield dut.in_a.stb.eq(1) + yield + yield + a_ack = (yield dut.in_a.ack) + assert a_ack == 0 + yield dut.in_b.v.eq(b) + yield dut.in_b.stb.eq(1) + b_ack = (yield dut.in_b.ack) + assert b_ack == 0 + + while True: + yield + out_z_stb = (yield dut.out_z.stb) + if not out_z_stb: + continue + yield dut.in_a.stb.eq(0) + yield dut.in_b.stb.eq(0) + yield dut.out_z.ack.eq(1) + yield + yield dut.out_z.ack.eq(0) + yield + yield + break + + out_z = yield dut.out_z.v + return out_z + +def check_case(dut, a, b, z): + out_z = yield from get_case(dut, a, b) + assert out_z == z, "Output z 0x%x not equal to expected 0x%x" % (out_z, z) + + +def run_test(dut, stimulus_a, stimulus_b, op): + + expected_responses = [] + actual_responses = [] + for a, b in zip(stimulus_a, stimulus_b): + af = Float16.from_bits(a) + bf = Float16.from_bits(b) + z = op(af, bf) + expected_responses.append(z.get_bits()) + #print (af, bf, z) + actual = yield from get_case(dut, a, b) + actual_responses.append(actual) + + if len(actual_responses) < len(expected_responses): + print ("Fail ... not enough results") + exit(0) + + for expected, actual, a, b in zip(expected_responses, actual_responses, + stimulus_a, stimulus_b): + passed = match(expected, actual) + + if not passed: + + print ("Fail ... expected:", hex(expected), "actual:", hex(actual)) + + print (hex(a)) + print ("a mantissa:", get_mantissa(a)) + print ("a exponent:", get_exponent(a)) + print ("a sign:", get_sign(a)) + + print (hex(b)) + print ("b mantissa:", get_mantissa(b)) + print ("b exponent:", get_exponent(b)) + print ("b sign:", get_sign(b)) + + print (hex(expected)) + print ("expected mantissa:", get_mantissa(expected)) + print ("expected exponent:", get_exponent(expected)) + print ("expected sign:", get_sign(expected)) + + print (hex(actual)) + print ("actual mantissa:", get_mantissa(actual)) + print ("actual exponent:", get_exponent(actual)) + print ("actual sign:", get_sign(actual)) + + sys.exit(0) + +def run_corner_cases(dut, count, op): + #corner cases + corners = [0x8000, 0x0000, 0x7800, 0xf800, 0x7c00, 0xfc00] + from itertools import permutations + stimulus_a = [i[0] for i in permutations(corners, 2)] + stimulus_b = [i[1] for i in permutations(corners, 2)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + +def run_edge_cases(dut, count, op): + maxint16 = 1<<16 + maxcount = 10 + #edge cases + stimulus_a = [0x8000 for i in range(maxcount)] + stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_a = [0x0000 for i in range(maxcount)] + stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_b = [0x8000 for i in range(maxcount)] + stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_b = [0x0000 for i in range(maxcount)] + stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_a = [0x7800 for i in range(maxcount)] + stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_a = [0xF800 for i in range(maxcount)] + stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_b = [0x7800 for i in range(maxcount)] + stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_b = [0xF800 for i in range(maxcount)] + stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_a = [0x7C00 for i in range(maxcount)] + stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_a = [0xFC00 for i in range(maxcount)] + stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_b = [0x7C00 for i in range(maxcount)] + stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + stimulus_b = [0xFC00 for i in range(maxcount)] + stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += len(stimulus_a) + print (count, "vectors passed") + + #seed(0) + for i in range(100000): + stimulus_a = [randint(0, maxint16-1) for i in range(maxcount)] + stimulus_b = [randint(0, maxint16-1) for i in range(maxcount)] + yield from run_test(dut, stimulus_a, stimulus_b, op) + count += maxcount + print (count, "random vectors passed") + diff --git a/src/ieee754/fpcommon/test/unit_test_single.py b/src/ieee754/fpcommon/test/unit_test_single.py new file mode 100644 index 00000000..2b0d9e56 --- /dev/null +++ b/src/ieee754/fpcommon/test/unit_test_single.py @@ -0,0 +1,255 @@ +from random import randint +from random import seed + +import sys +from sfpy import Float32 + +def get_mantissa(x): + return 0x7fffff & x + +def get_exponent(x): + return ((x & 0x7f800000) >> 23) - 127 + +def set_exponent(x, e): + return (x & ~0x7f800000) | ((e+127) << 23) + +def get_sign(x): + return ((x & 0x80000000) >> 31) + +def is_nan(x): + return get_exponent(x) == 128 and get_mantissa(x) != 0 + +def is_inf(x): + return get_exponent(x) == 128 and get_mantissa(x) == 0 + +def is_pos_inf(x): + return is_inf(x) and not get_sign(x) + +def is_neg_inf(x): + return is_inf(x) and get_sign(x) + +def match(x, y): + return ( + (is_pos_inf(x) and is_pos_inf(y)) or + (is_neg_inf(x) and is_neg_inf(y)) or + (is_nan(x) and is_nan(y)) or + (x == y) + ) + +def get_rs_case(dut, a, b, mid): + in_a, in_b = dut.rs[0] + out_z = dut.res[0] + yield dut.ids.in_mid.eq(mid) + yield in_a.v.eq(a) + yield in_a.valid_i.eq(1) + yield + yield + yield + yield + a_ack = (yield in_a.ready_o) + assert a_ack == 0 + + yield in_a.valid_i.eq(0) + + yield in_b.v.eq(b) + yield in_b.valid_i.eq(1) + yield + yield + b_ack = (yield in_b.ready_o) + assert b_ack == 0 + + yield in_b.valid_i.eq(0) + + yield out_z.ready_i.eq(1) + + while True: + out_z_stb = (yield out_z.valid_o) + if not out_z_stb: + yield + continue + vout_z = yield out_z.v + #out_mid = yield dut.ids.out_mid + yield out_z.ready_i.eq(0) + yield + break + + return vout_z, mid + +def check_rs_case(dut, a, b, z, mid=None): + if mid is None: + mid = randint(0, 6) + mid = 0 + out_z, out_mid = yield from get_rs_case(dut, a, b, mid) + assert out_z == z, "Output z 0x%x not equal to expected 0x%x" % (out_z, z) + assert out_mid == mid, "Output mid 0x%x != expected 0x%x" % (out_mid, mid) + + +def get_case(dut, a, b, mid): + #yield dut.in_mid.eq(mid) + yield dut.in_a.v.eq(a) + yield dut.in_a.valid_i_test.eq(1) + yield + yield + yield + yield + a_ack = (yield dut.in_a.ready_o) + assert a_ack == 0 + + yield dut.in_a.valid_i.eq(0) + + yield dut.in_b.v.eq(b) + yield dut.in_b.valid_i.eq(1) + yield + yield + b_ack = (yield dut.in_b.ready_o) + assert b_ack == 0 + + yield dut.in_b.valid_i.eq(0) + + yield dut.out_z.ready_i.eq(1) + + while True: + out_z_stb = (yield dut.out_z.valid_o) + if not out_z_stb: + yield + continue + out_z = yield dut.out_z.v + #out_mid = yield dut.out_mid + yield dut.out_z.ready_i.eq(0) + yield + break + + return out_z, mid # TODO: mid + +def check_case(dut, a, b, z, mid=None): + if mid is None: + mid = randint(0, 6) + mid = 0 + out_z, out_mid = yield from get_case(dut, a, b, mid) + assert out_z == z, "Output z 0x%x not equal to expected 0x%x" % (out_z, z) + assert out_mid == mid, "Output mid 0x%x != expected 0x%x" % (out_mid, mid) + + +def run_test(dut, stimulus_a, stimulus_b, op, get_case_fn): + + expected_responses = [] + actual_responses = [] + for a, b in zip(stimulus_a, stimulus_b): + mid = randint(0, 6) + mid = 0 + af = Float32.from_bits(a) + bf = Float32.from_bits(b) + z = op(af, bf) + expected_responses.append((z.get_bits(), mid)) + actual = yield from get_case_fn(dut, a, b, mid) + actual_responses.append(actual) + + if len(actual_responses) < len(expected_responses): + print ("Fail ... not enough results") + exit(0) + + for expected, actual, a, b in zip(expected_responses, actual_responses, + stimulus_a, stimulus_b): + passed = match(expected[0], actual[0]) + if expected[1] != actual[1]: # check mid + print ("MID failed", expected[1], actual[1]) + sys.exit(0) + + if not passed: + + expected = expected[0] + actual = actual[0] + print ("Fail ... expected:", hex(expected), "actual:", hex(actual)) + + print (hex(a)) + print ("a mantissa:", a & 0x7fffff) + print ("a exponent:", ((a & 0x7f800000) >> 23) - 127) + print ("a sign:", ((a & 0x80000000) >> 31)) + + print (hex(b)) + print ("b mantissa:", b & 0x7fffff) + print ("b exponent:", ((b & 0x7f800000) >> 23) - 127) + print ("b sign:", ((b & 0x80000000) >> 31)) + + print (hex(expected)) + print ("expected mantissa:", expected & 0x7fffff) + print ("expected exponent:", ((expected & 0x7f800000) >> 23) - 127) + print ("expected sign:", ((expected & 0x80000000) >> 31)) + + print (hex(actual)) + print ("actual mantissa:", actual & 0x7fffff) + print ("actual exponent:", ((actual & 0x7f800000) >> 23) - 127) + print ("actual sign:", ((actual & 0x80000000) >> 31)) + + sys.exit(0) + +corner_cases = [0x80000000, 0x00000000, 0x7f800000, 0xff800000, + 0x7fc00000, 0xffc00000] + +def run_corner_cases(dut, count, op, get_case_fn): + #corner cases + from itertools import permutations + stimulus_a = [i[0] for i in permutations(corner_cases, 2)] + stimulus_b = [i[1] for i in permutations(corner_cases, 2)] + yield from run_test(dut, stimulus_a, stimulus_b, op, get_case_fn) + count += len(stimulus_a) + print (count, "vectors passed") + +def run_test_2(dut, stimulus_a, stimulus_b, op, get_case_fn): + yield from run_test(dut, stimulus_a, stimulus_b, op, get_case_fn) + yield from run_test(dut, stimulus_b, stimulus_a, op, get_case_fn) + +def run_cases(dut, count, op, fixed_num, num_entries, get_case_fn): + if isinstance(fixed_num, int): + stimulus_a = [fixed_num for i in range(num_entries)] + report = hex(fixed_num) + else: + stimulus_a = fixed_num + report = "random" + + stimulus_b = [randint(0, 1<<32) for i in range(num_entries)] + yield from run_test_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(num_entries)] + yield from run_test_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(num_entries)] + yield from run_test_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(num_entries)] + yield from run_test_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(num_entries)] + yield from run_test_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): + #edge cases + for testme in corner_cases: + count = yield from run_cases(dut, count, op, testme, 10, get_case_fn) + + for i in range(100000): + stimulus_a = [randint(0, 1<<32) for i in range(10)] + count = yield from run_cases(dut, count, op, stimulus_a, 10, + get_case_fn) + return count +