From: Luke Kenneth Casson Leighton Date: Tue, 23 Jul 2019 21:15:43 +0000 (+0100) Subject: use PriorityEncoder and Array selection X-Git-Tag: ls180-24jan2020~743 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3abccd640745fba3d2375bbe1a4b1d8822d7345e;p=ieee754fpu.git use PriorityEncoder and Array selection --- diff --git a/src/ieee754/div_rem_sqrt_rsqrt/core.py b/src/ieee754/div_rem_sqrt_rsqrt/core.py index c41bb93a..97b4a998 100644 --- a/src/ieee754/div_rem_sqrt_rsqrt/core.py +++ b/src/ieee754/div_rem_sqrt_rsqrt/core.py @@ -18,7 +18,8 @@ Formulas solved are: The remainder is the left-hand-side of the comparison minus the right-hand-side of the comparison in the above formulas. """ -from nmigen import (Elaboratable, Module, Signal, Const, Mux, Cat) +from nmigen import (Elaboratable, Module, Signal, Const, Mux, Cat, Array) +from nmigen.lib.coding import PriorityEncoder import enum @@ -398,7 +399,7 @@ class DivPipeCoreCalculateStage(Elaboratable): pass_flags = Signal(radix, reset_less=True) m.d.comb += pass_flags.eq(Cat(*pfl)) - # convert pass_flags to next_bits. + # convert pass_flags (unary priority) to next_bits (binary index) # # Assumes that for each set bit in pass_flag, all previous bits are # also set. @@ -406,30 +407,19 @@ class DivPipeCoreCalculateStage(Elaboratable): # Assumes that pass_flag[0] is always set (since # compare_lhs >= compare_rhs is a pipeline invariant). - next_bits = Signal(log2_radix, reset_less=True) - l = [] - for i in range(log2_radix): - bit_value = 1 - for j in range(0, radix, 1 << i): - bit_value ^= pass_flags[j] - bv = Signal(reset_less=True) - m.d.comb += bv.eq(bit_value) - l.append(bv) - m.d.comb += next_bits.eq(Cat(*l)) - - # merge/select multi-bit trial_compare_rhs_values, to go - # into compare_rhs. XXX (only one of these will succeed?) - next_compare_rhs = 0 - for i in range(radix): - next_flag = Signal(name=f"next_flag{i}", reset_less=True) - selected = Signal(name=f"selected_{i}", reset_less=True) - m.d.comb += next_flag.eq(~pass_flags[i + 1] if i + 1 < radix else 1) - m.d.comb += selected.eq(pass_flags[i] & next_flag) - next_compare_rhs |= Mux(selected, - trial_compare_rhs_values[i], - 0) - - m.d.comb += self.o.compare_rhs.eq(next_compare_rhs) + m.submodules.pe = pe = PriorityEncoder(radix) + next_bits = Signal(log2_radix+1, reset_less=True) + m.d.comb += pe.i.eq(~pass_flags) + with m.If(~pe.n): + m.d.comb += next_bits.eq(pe.o-1) + with m.Else(): + m.d.comb += next_bits.eq(radix-1) + + # get the highest passing rhs trial (indexed by next_bits) + ta = Array(trial_compare_rhs_values) + m.d.comb += self.o.compare_rhs.eq(ta[next_bits]) + + # creae outputs for next phase m.d.comb += self.o.root_times_radicand.eq(self.i.root_times_radicand + ((self.i.divisor_radicand * next_bits)