Extend CLZ to work over even, non powers of 2
[ieee754fpu.git] / src / ieee754 / cordic / clz.py
1 from nmigen import Module, Signal, Elaboratable, Cat, Repl
2 import math
3
4 class CLZ(Elaboratable):
5 def __init__(self, width):
6 self.width = width
7 self.sig_in = Signal(width, reset_less=True)
8 out_width = math.ceil(math.log2(width+1))
9 self.lz = Signal(out_width)
10
11 def generate_pairs(self, m):
12 comb = m.d.comb
13 assert self.width % 2 == 0 # TODO handle odd widths
14 pairs = []
15 for i in range(0, self.width, 2):
16 pair = Signal(2, name="pair%d" % i)
17 comb += pair.eq(self.sig_in[i:i+2])
18
19 pair_cnt = Signal(2, name="cnt_1_%d" % (i/2))
20 with m.Switch(pair):
21 with m.Case(0):
22 comb += pair_cnt.eq(2)
23 with m.Case(1):
24 comb += pair_cnt.eq(1)
25 with m.Default():
26 comb += pair_cnt.eq(0)
27 pairs.append((pair_cnt, 2)) # append pair, max_value
28 return pairs
29
30 def combine_pairs(self, m, iteration, pairs):
31 comb = m.d.comb
32 length = len(pairs)
33 ret = []
34 for i in range(0, length, 2):
35 if i+1 >= length:
36 right, mv = pairs[i]
37 width = right.width
38 print(f"single({i}) - cnt_{iteration}_{i}")
39 new_pair = Signal(width, name="cnt_%d_%d" % (iteration, i))
40 comb += new_pair.eq(Cat(right, 0))
41 ret.append((new_pair, mv))
42 else:
43 left, lv = pairs[i+1]
44 right, rv = pairs[i]
45 width = right.width + 1
46 print(left)
47 print(f"pair({left}, {right}) - cnt_{iteration}_{i}")
48 new_pair = Signal(width, name="cnt_%d_%d" %
49 (iteration, i))
50 if rv == lv:
51 with m.If(left[-1] == 1):
52 with m.If(right[-1] == 1):
53 comb += new_pair.eq(Cat(Repl(0, width-1), 1))
54 with m.Else():
55 comb += new_pair.eq(Cat(right[0:-1], 0b01))
56 with m.Else():
57 comb += new_pair.eq(Cat(left, 0))
58 else:
59 with m.If(left == lv):
60 comb += new_pair.eq(right + left)
61 with m.Else():
62 comb += new_pair.eq(left)
63
64
65 ret.append((new_pair, lv+rv))
66 return ret
67
68 def elaborate(self, platform):
69 m = Module()
70 comb = m.d.comb
71
72 pairs = self.generate_pairs(m)
73 i = 2
74 while len(pairs) > 1:
75 pairs = self.combine_pairs(m, i, pairs)
76 print(pairs)
77 i += 1
78
79 comb += self.lz.eq(pairs[0][0])
80
81 return m
82
83