switch to exact version of cython
[ieee754fpu.git] / src / ieee754 / fpmul / align.py
1 # IEEE Floating Point Multiplier
2
3 from nmigen import Module, Signal, Cat, Mux
4 from nmigen.cli import main, verilog
5 from math import log
6
7 from nmutil.pipemodbase import PipeModBase
8 from ieee754.fpcommon.fpbase import FPNumBase
9 from ieee754.fpcommon.getop import FPPipeContext
10 from ieee754.fpcommon.msbhigh import FPMSBHigh
11 from ieee754.fpcommon.denorm import FPSCData
12 from ieee754.fpcommon.postcalc import FPPostCalcData
13
14
15 class FPAlignModSingle(PipeModBase):
16
17 def __init__(self, pspec, e_extra=False):
18 self.e_extra = e_extra
19 super().__init__(pspec, "align")
20
21 def ispec(self):
22 return FPSCData(self.pspec, False)
23
24 def ospec(self):
25 return FPSCData(self.pspec, False)
26
27 def elaborate(self, platform):
28 m = Module()
29 comb = m.d.comb
30
31 self.o.a.m.name = "o_a_m"
32 self.o.b.m.name = "o_b_m"
33
34 m.submodules.norm1_insel_a = insel_a = FPNumBase(self.i.a)
35 m.submodules.norm1_insel_b = insel_b = FPNumBase(self.i.b)
36 insel_a.m.name = "i_a_m"
37 insel_b.m.name = "i_b_m"
38
39 # FPMSBHigh makes sure that the MSB is HI (duh).
40 # it does so (in a single cycle) by counting the leading zeros
41 # and performing a shift on the mantissa. the same count is then
42 # subtracted from the exponent.
43 mwid = self.o.z.m_width
44 msb_a = FPMSBHigh(mwid, len(insel_a.e))
45 msb_b = FPMSBHigh(mwid, len(insel_b.e))
46 m.submodules.norm_pe_a = msb_a
47 m.submodules.norm_pe_b = msb_b
48
49 # connect to msb_a/b module
50 comb += msb_a.m_in.eq(insel_a.m)
51 comb += msb_a.e_in.eq(insel_a.e)
52 comb += msb_b.m_in.eq(insel_b.m)
53 comb += msb_b.e_in.eq(insel_b.e)
54
55 # copy input to output sign
56 comb += self.o.a.s.eq(insel_a.s)
57 comb += self.o.b.s.eq(insel_b.s)
58
59 # normalisation increase/decrease conditions
60 decrease_a = Signal(reset_less=True)
61 decrease_b = Signal(reset_less=True)
62 comb += decrease_a.eq(insel_a.m_msbzero)
63 comb += decrease_b.eq(insel_b.m_msbzero)
64
65 # ok this is near-identical to FPNorm: use same class (FPMSBHigh)
66 comb += [
67 self.o.a.e.eq(Mux(decrease_a, msb_a.e_out, insel_a.e)),
68 self.o.a.m.eq(Mux(decrease_a, msb_a.m_out, insel_a.m))
69 ]
70 comb += [
71 self.o.b.e.eq(Mux(decrease_b, msb_b.e_out, insel_b.e)),
72 self.o.b.m.eq(Mux(decrease_b, msb_b.m_out, insel_b.m))
73 ]
74
75 comb += self.o.ctx.eq(self.i.ctx)
76 comb += self.o.out_do_z.eq(self.i.out_do_z)
77 comb += self.o.oz.eq(self.i.oz)
78
79 return m