21022c81a5866e4a677e60a1d639c4dec46eed49
[ieee754fpu.git] / src / ieee754 / fpfma / norm.py
1 from nmutil.pipemodbase import PipeModBaseChain, PipeModBase
2 from ieee754.fpcommon.fpbase import OverflowMod
3 from ieee754.fpcommon.postnormalise import FPNorm1Data
4 from ieee754.fpcommon.roundz import FPRoundMod
5 from ieee754.fpcommon.corrections import FPCorrectionsMod
6 from ieee754.fpcommon.pack import FPPackMod
7 from ieee754.fpfma.main_stage import FPFMAPostCalcData
8 from nmigen.hdl.dsl import Module
9 from nmigen.hdl.ast import Signal
10 from ieee754.fpfma.util import get_fpformat
11 from nmigen.lib.coding import PriorityEncoder
12
13
14 class FPFMANorm(PipeModBase):
15 def __init__(self, pspec):
16 super().__init__(pspec, "norm")
17
18 def ispec(self):
19 return FPFMAPostCalcData(self.pspec)
20
21 def ospec(self):
22 return FPNorm1Data(self.pspec)
23
24 def elaborate(self, platform):
25 m = Module()
26 fpf = get_fpformat(self.pspec)
27 assert fpf.has_sign
28 inp: FPFMAPostCalcData = self.i
29 out: FPNorm1Data = self.o
30 m.submodules.pri_enc = pri_enc = PriorityEncoder(inp.mantissa.width)
31 m.d.comb += pri_enc.i.eq(inp.mantissa[::-1])
32 unrestricted_shift_amount = Signal(range(inp.mantissa.width))
33 shift_amount = Signal(range(inp.mantissa.width))
34 m.d.comb += unrestricted_shift_amount.eq(pri_enc.o)
35 with m.If(inp.exponent - (1 + fpf.e_sub) < unrestricted_shift_amount):
36 m.d.comb += shift_amount.eq(inp.exponent - (1 + fpf.e_sub))
37 with m.Else():
38 m.d.comb += shift_amount.eq(unrestricted_shift_amount)
39 n_mantissa = Signal(inp.mantissa.width)
40 m.d.comb += n_mantissa.eq(inp.mantissa << shift_amount)
41
42 m.submodules.of = of = OverflowMod()
43 m.d.comb += [
44 pri_enc.i.eq(inp.mantissa[::-1]),
45 of.guard.eq(n_mantissa[-(out.z.m.width + 1)]),
46 of.round_bit.eq(n_mantissa[-(out.z.m.width + 2)]),
47 of.sticky.eq(n_mantissa[:-(out.z.m.width + 2)].bool()),
48 of.m0.eq(out.z.m[0]),
49 of.fpflags.eq(0),
50 of.sign.eq(inp.sign),
51 of.rm.eq(inp.rm),
52 out.roundz.eq(of.roundz_out),
53 out.z.s.eq(inp.sign),
54 out.z.e.eq(inp.exponent - shift_amount),
55 out.z.m.eq(n_mantissa[-out.z.m.width:]),
56 out.out_do_z.eq(inp.do_bypass),
57 out.oz.eq(inp.bypassed_z),
58 out.ctx.eq(inp.ctx),
59 out.rm.eq(inp.rm),
60 ]
61 return m
62
63
64 class FPFMANormToPack(PipeModBaseChain):
65 def __init__(self, pspec):
66 super().__init__(pspec)
67
68 def get_chain(self):
69 """ gets chain of modules
70 """
71 nmod = FPFMANorm(self.pspec)
72 rmod = FPRoundMod(self.pspec)
73 cmod = FPCorrectionsMod(self.pspec)
74 pmod = FPPackMod(self.pspec)
75 return [nmod, rmod, cmod, pmod]