From c3e4927b86efa72a7b70111e1447a99ef2945cf5 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Wed, 10 Jul 2019 05:19:10 -0700 Subject: [PATCH] add more tests; they all pass --- src/ieee754/div_rem_sqrt_rsqrt/test_core.py | 146 +++++++++++++++----- 1 file changed, 109 insertions(+), 37 deletions(-) diff --git a/src/ieee754/div_rem_sqrt_rsqrt/test_core.py b/src/ieee754/div_rem_sqrt_rsqrt/test_core.py index a9a3d29f..88b61326 100755 --- a/src/ieee754/div_rem_sqrt_rsqrt/test_core.py +++ b/src/ieee754/div_rem_sqrt_rsqrt/test_core.py @@ -31,6 +31,8 @@ def get_core_op(alg_op): class TestCaseData: + __test__ = False # make pytest ignore class + def __init__(self, dividend, divisor_radicand, @@ -90,25 +92,74 @@ def generate_test_case(core_config, dividend, divisor_radicand, alg_op): core_config) +def shifted_ints(total_bits, int_bits): + """ Generate a sequence like a generalized binary version of A037124. + + See https://oeis.org/A037124 + + Generates the sequence of all non-negative integers ``n`` in ascending + order with no repeats where ``n < (1 << total_bits) and n == (v << i)`` + where ``i`` is a non-negative integer and ``v`` is a non-negative + integer less than ``1 << int_bits``. + """ + n = 0 + while n < (1 << total_bits): + yield n + if n < (1 << int_bits): + n += 1 + else: + n += 1 << (n.bit_length() - int_bits) + + +def partitioned_ints(bit_width): + """ Get ints with all 1s on one side and 0s on the other. """ + for i in range(bit_width): + yield (-1 << i) & ((1 << bit_width) - 1) + yield (1 << (i + 1)) - 1 + + +class TestShiftedInts(unittest.TestCase): + def test(self): + expected = [0x000, + 0x001, + 0x002, 0x003, + 0x004, 0x005, 0x006, 0x007, + 0x008, 0x009, 0x00A, 0x00B, 0x00C, 0x00D, 0x00E, 0x00F, + 0x010, 0x012, 0x014, 0x016, 0x018, 0x01A, 0x01C, 0x01E, + 0x020, 0x024, 0x028, 0x02C, 0x030, 0x034, 0x038, 0x03C, + 0x040, 0x048, 0x050, 0x058, 0x060, 0x068, 0x070, 0x078, + 0x080, 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, + 0x100, 0x120, 0x140, 0x160, 0x180, 0x1A0, 0x1C0, 0x1E0, + 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x340, 0x380, 0x3C0, + 0x400, 0x480, 0x500, 0x580, 0x600, 0x680, 0x700, 0x780, + 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00, 0xF00] + self.assertEqual(list(shifted_ints(12, 4)), expected) + + def get_test_cases(core_config, dividends=None, divisors=None, radicands=None): if dividends is None: - dividends = range(1 << (core_config.bit_width - + core_config.fract_width)) + dividend_width = core_config.bit_width + core_config.fract_width + dividends = [*shifted_ints(dividend_width, + max(3, core_config.log2_radix)), + *partitioned_ints(dividend_width)] else: assert isinstance(dividends, list) if divisors is None: - divisors = range(1 << core_config.bit_width) + divisors = [*shifted_ints(core_config.bit_width, + max(3, core_config.log2_radix)), + *partitioned_ints(core_config.bit_width)] else: assert isinstance(divisors, list) if radicands is None: - radicands = range(1 << core_config.bit_width) + radicands = [*shifted_ints(core_config.bit_width, 5), + *partitioned_ints(core_config.bit_width)] else: assert isinstance(radicands, list) - for alg_op in Operation: + for alg_op in reversed(Operation): # put UDivRem at end if alg_op is Operation.UDivRem: for dividend in dividends: for divisor in divisors: @@ -160,27 +211,18 @@ class DivPipeCoreTestPipeline(Elaboratable): class TestDivPipeCore(unittest.TestCase): - def handle_case(self, - core_config, - dividends=None, - divisors=None, - radicands=None, - sync=True): - if dividends is not None: - dividends = list(dividends) - if divisors is not None: - divisors = list(divisors) - if radicands is not None: - radicands = list(radicands) - - def gen_test_cases(): - yield from get_test_cases(core_config, - dividends, - divisors, - radicands) - base_name = f"div_pipe_core_bit_width_{core_config.bit_width}" + def handle_config(self, + core_config, + test_cases=None, + sync=True): + if test_cases is None: + test_cases = get_test_cases(core_config) + test_cases = list(test_cases) + base_name = f"test_div_pipe_core_bit_width_{core_config.bit_width}" base_name += f"_fract_width_{core_config.fract_width}" base_name += f"_radix_{1 << core_config.log2_radix}" + if not sync: + base_name += "_comb" with self.subTest(part="synthesize"): dut = DivPipeCoreTestPipeline(core_config, sync) vl = rtlil.convert(dut, ports=[*dut.i, *dut.o]) @@ -192,7 +234,7 @@ class TestDivPipeCore(unittest.TestCase): gtkw_file=open(f"{base_name}.gtkw", "w"), traces=[*dut.traces()]) as sim: def generate_process(): - for test_case in gen_test_cases(): + for test_case in test_cases: yield Tick() yield dut.i.dividend.eq(test_case.dividend) yield dut.i.divisor_radicand.eq(test_case.divisor_radicand) @@ -208,7 +250,7 @@ class TestDivPipeCore(unittest.TestCase): yield # now synched with generator - for test_case in gen_test_cases(): + for test_case in test_cases: yield Tick() yield Delay(0.9e-6) quotient_root = (yield dut.o.quotient_root) @@ -222,19 +264,49 @@ class TestDivPipeCore(unittest.TestCase): sim.add_sync_process(check_process) sim.run() - def test_bit_width_8_fract_width_4_radix_2(self): - self.handle_case(DivPipeCoreConfig(bit_width=8, - fract_width=4, - log2_radix=1), - dividends=[*range(1 << 8), - *range(1 << 8, 1 << 12, 1 << 4)], - sync=False) + def test_bit_width_2_fract_width_1_radix_2_comb(self): + self.handle_config(DivPipeCoreConfig(bit_width=2, + fract_width=1, + log2_radix=1), + sync=False) def test_bit_width_2_fract_width_1_radix_2(self): - self.handle_case(DivPipeCoreConfig(bit_width=2, - fract_width=1, - log2_radix=1), - sync=False) + self.handle_config(DivPipeCoreConfig(bit_width=2, + fract_width=1, + log2_radix=1)) + + def test_bit_width_8_fract_width_4_radix_2_comb(self): + self.handle_config(DivPipeCoreConfig(bit_width=8, + fract_width=4, + log2_radix=1), + sync=False) + + def test_bit_width_8_fract_width_4_radix_2(self): + self.handle_config(DivPipeCoreConfig(bit_width=8, + fract_width=4, + log2_radix=1)) + + def test_bit_width_32_fract_width_24_radix_8_comb(self): + self.handle_config(DivPipeCoreConfig(bit_width=32, + fract_width=24, + log2_radix=3), + sync=False) + + def test_bit_width_32_fract_width_24_radix_8(self): + self.handle_config(DivPipeCoreConfig(bit_width=32, + fract_width=24, + log2_radix=3)) + + def test_bit_width_32_fract_width_28_radix_8_comb(self): + self.handle_config(DivPipeCoreConfig(bit_width=32, + fract_width=28, + log2_radix=3), + sync=False) + + def test_bit_width_32_fract_width_28_radix_8(self): + self.handle_config(DivPipeCoreConfig(bit_width=32, + fract_width=28, + log2_radix=3)) # FIXME: add more test_* functions -- 2.30.2