remove now-unused EqualLeadingZeroCount
authorJacob Lifshay <programmerjake@gmail.com>
Thu, 5 May 2022 07:45:33 +0000 (00:45 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Thu, 5 May 2022 07:45:33 +0000 (00:45 -0700)
src/nmigen_gf/hdl/cldivrem.py
src/nmigen_gf/hdl/test/test_cldivrem.py

index 73bdd1e9b75f144bcd81d5ad961b688f1a70f8c7..48105fa7e0d005854afb6da4d7a215d3431ec57d 100644 (file)
@@ -10,104 +10,12 @@ https://bugs.libre-soc.org/show_bug.cgi?id=784
 """
 
 from dataclasses import dataclass, field, fields
 """
 
 from dataclasses import dataclass, field, fields
-from nmigen.hdl.ir import Elaboratable
 from nmigen.hdl.ast import Signal, Value
 from nmigen.hdl.dsl import Module
 from nmutil.singlepipe import ControlBase
 from nmutil.clz import CLZ, clz
 
 
 from nmigen.hdl.ast import Signal, Value
 from nmigen.hdl.dsl import Module
 from nmutil.singlepipe import ControlBase
 from nmutil.clz import CLZ, clz
 
 
-def equal_leading_zero_count_reference(a, b, width):
-    """checks if `clz(a) == clz(b)`.
-    Reference code for algorithm used in `EqualLeadingZeroCount`.
-    """
-    assert isinstance(width, int) and 0 <= width
-    assert isinstance(a, int) and 0 <= a < (1 << width)
-    assert isinstance(b, int) and 0 <= b < (1 << width)
-    eq = True  # both have no leading zeros so far...
-    for i in range(width):
-        a_bit = (a >> i) & 1
-        b_bit = (b >> i) & 1
-        # `both_ones` is set if both have no leading zeros so far
-        both_ones = a_bit & b_bit
-        # `different` is set if there are a different number of leading
-        # zeros so far
-        different = a_bit != b_bit
-        if both_ones:
-            eq = True
-        elif different:
-            eq = False
-        else:
-            pass  # propagate from lower bits
-    return eq
-
-
-class EqualLeadingZeroCount(Elaboratable):
-    """checks if `clz(a) == clz(b)`.
-
-    Properties:
-    width: int
-        the width in bits of `a` and `b`.
-    a: Signal of width `width`
-        input
-    b: Signal of width `width`
-        input
-    out: Signal of width `1`
-        output, set if the number of leading zeros in `a` is the same as in
-        `b`.
-    """
-
-    def __init__(self, width):
-        assert isinstance(width, int)
-        self.width = width
-        self.a = Signal(width)
-        self.b = Signal(width)
-        self.out = Signal()
-
-    def elaborate(self, platform):
-        # the operation is converted into calculation of the carry-out of a
-        # binary addition, allowing FPGAs to re-use their specialized
-        # carry-propagation logic. This should be simplified by yosys to
-        # remove the extraneous xor gates from addition when targeting
-        # FPGAs/ASICs, so no efficiency is lost.
-        #
-        # see `equal_leading_zero_count_reference` for a Python version of
-        # the algorithm, but without conversion to carry-propagation.
-        # note that it's possible to do all the bits at once: a for-loop
-        # (unlike in the reference-code) is not necessary
-
-        m = Module()
-        both_ones = Signal(self.width)
-        different = Signal(self.width)
-
-        # build `both_ones` and `different` such that:
-        # for every bit index `i`:
-        # * if `both_ones[i]` is set, then both addends bits at index `i` are
-        #   set in order to set the carry bit out, since `cin + 1 + 1` always
-        #   has a carry out.
-        # * if `different[i]` is set, then both addends bits at index `i` are
-        #   zeros in order to clear the carry bit out, since `cin + 0 + 0`
-        #   never has a carry out.
-        # * otherwise exactly one of the addends bits at index `i` is set and
-        #   the other is clear in order to propagate the carry bit from
-        #   less significant bits, since `cin + 1 + 0` has a carry out that is
-        #   equal to `cin`.
-
-        # `both_ones` is set if both have no leading zeros so far
-        m.d.comb += both_ones.eq(self.a & self.b)
-        # `different` is set if there are a different number of leading
-        # zeros so far
-        m.d.comb += different.eq(self.a ^ self.b)
-
-        # now [ab]use add: the last bit [carry-out] is the result
-        csum = Signal(self.width + 1)
-        carry_in = 1  # both have no leading zeros so far, so set carry in
-        m.d.comb += csum.eq(both_ones + (~different) + carry_in)
-        m.d.comb += self.out.eq(csum[self.width])  # out is carry-out
-
-        return m
-
-
 def cldivrem_shifting(n, d, width):
     """ Carry-less Division and Remainder based on shifting at start and end
         allowing us to get away with checking a single bit each iteration
 def cldivrem_shifting(n, d, width):
     """ Carry-less Division and Remainder based on shifting at start and end
         allowing us to get away with checking a single bit each iteration
index 27820705176c7528d2298a499292f72b03377b9b..438b547fca5cc822f91c6add9f71cadd2ddfe8cb 100644 (file)
 # of Horizon 2020 EU Programme 957073.
 
 import unittest
 # of Horizon 2020 EU Programme 957073.
 
 import unittest
-from nmigen.hdl.ast import AnyConst, Assert, Signal, Const, unsigned
+from nmigen.hdl.ast import Signal, Const, unsigned
 from nmigen.hdl.dsl import Module
 from nmutil.formaltest import FHDLTestCase
 from nmigen_gf.hdl.cldivrem import (CLDivRemFSMStage, CLDivRemInputData,
                                     CLDivRemOutputData, CLDivRemShape,
 from nmigen.hdl.dsl import Module
 from nmutil.formaltest import FHDLTestCase
 from nmigen_gf.hdl.cldivrem import (CLDivRemFSMStage, CLDivRemInputData,
                                     CLDivRemOutputData, CLDivRemShape,
-                                    cldivrem_shifting, CLDivRemState,
-                                    equal_leading_zero_count_reference,
-                                    EqualLeadingZeroCount)
+                                    cldivrem_shifting, CLDivRemState)
 from nmigen.sim import Delay, Tick
 from nmutil.sim_util import do_sim, hash_256
 from nmigen_gf.reference.cldivrem import cldivrem
 
 
 from nmigen.sim import Delay, Tick
 from nmutil.sim_util import do_sim, hash_256
 from nmigen_gf.reference.cldivrem import cldivrem
 
 
-class TestEqualLeadingZeroCount(FHDLTestCase):
-    def tst(self, width, full):
-        dut = EqualLeadingZeroCount(width)
-        self.assertEqual(dut.a.shape(), unsigned(width))
-        self.assertEqual(dut.b.shape(), unsigned(width))
-        self.assertEqual(dut.out.shape(), unsigned(1))
-
-        def case(a, b):
-            assert isinstance(a, int)
-            assert isinstance(b, int)
-            expected = a.bit_length() == b.bit_length()
-            with self.subTest(a=hex(a), b=hex(b),
-                              expected=expected):
-                reference = equal_leading_zero_count_reference(a, b, width)
-                with self.subTest(reference=reference):
-                    self.assertEqual(expected, reference)
-
-            with self.subTest(a=hex(a), b=hex(b),
-                              expected=expected):
-                yield dut.a.eq(a)
-                yield dut.b.eq(b)
-                yield Delay(1e-6)
-                out = yield dut.out
-                with self.subTest(out=out):
-                    self.assertEqual(expected, out)
-
-        def process():
-            if full:
-                for a in range(1 << width):
-                    for b in range(1 << width):
-                        yield from case(a, b)
-            else:
-                for i in range(100):
-                    a = hash_256(f"eqlzc input a {i}")
-                    a = Const.normalize(a, dut.a.shape())
-                    b = hash_256(f"eqlzc input b {i}")
-                    b = Const.normalize(b, dut.b.shape())
-                    yield from case(a, b)
-
-        with do_sim(self, dut, [dut.a, dut.b, dut.out]) as sim:
-            sim.add_process(process)
-            sim.run()
-
-    def tst_formal(self, width):
-        dut = EqualLeadingZeroCount(width)
-        m = Module()
-        m.submodules.dut = dut
-        m.d.comb += dut.a.eq(AnyConst(width))
-        m.d.comb += dut.b.eq(AnyConst(width))
-        # use a bunch of Value.matches() and boolean logic rather than a
-        # giant Switch()/If() to avoid
-        # https://github.com/YosysHQ/yosys/issues/3268
-        expected_v = False
-        for leading_zeros in range(width + 1):
-            pattern = '0' * leading_zeros + '1' + '-' * width
-            pattern = pattern[0:width]
-            a_has_count = Signal(name=f"a_has_{leading_zeros}")
-            b_has_count = Signal(name=f"b_has_{leading_zeros}")
-            m.d.comb += [
-                a_has_count.eq(dut.a.matches(pattern)),
-                b_has_count.eq(dut.b.matches(pattern)),
-            ]
-            expected_v |= a_has_count & b_has_count
-        expected = Signal()
-        m.d.comb += expected.eq(expected_v)
-        m.d.comb += Assert(dut.out == expected)
-        self.assertFormal(m)
-
-    def test_64(self):
-        self.tst(64, full=False)
-
-    def test_8(self):
-        self.tst(8, full=False)
-
-    def test_3(self):
-        self.tst(3, full=True)
-
-    def test_formal_64(self):
-        self.tst_formal(64)
-
-    def test_formal_8(self):
-        self.tst_formal(8)
-
-    def test_formal_3(self):
-        self.tst_formal(3)
-
-
 class TestCLDivRemShifting(FHDLTestCase):
     def tst(self, width, full):
         def case(n, d):
 class TestCLDivRemShifting(FHDLTestCase):
     def tst(self, width, full):
         def case(n, d):