add bug cross-reference to #113 for FCVT unit tests
[ieee754fpu.git] / src / ieee754 / fpmul / align.py
1 # IEEE Floating Point Multiplier
2
3 from nmigen import Module, Signal, Cat, Mux, Elaboratable
4 from nmigen.cli import main, verilog
5 from math import log
6
7 from nmutil.singlepipe import (StageChain, SimpleHandshake)
8
9 from ieee754.fpcommon.fpbase import (Overflow, OverflowMod,
10 FPNumBase, FPNumBaseRecord)
11 from ieee754.fpcommon.getop import FPPipeContext
12 from ieee754.fpcommon.msbhigh import FPMSBHigh
13 from ieee754.fpcommon.denorm import FPSCData
14 from ieee754.fpcommon.postcalc import FPAddStage1Data
15
16
17 class FPAlignModSingle(Elaboratable):
18
19 def __init__(self, pspec, e_extra=False):
20 self.pspec = pspec
21 self.e_extra = e_extra
22 self.i = self.ispec()
23 self.o = self.ospec()
24
25 def ispec(self):
26 return FPSCData(self.pspec, False)
27
28 def ospec(self):
29 return FPSCData(self.pspec, False)
30
31 def setup(self, m, i):
32 """ links module to inputs and outputs
33 """
34 m.submodules.align = self
35 m.d.comb += self.i.eq(i)
36
37 def process(self, i):
38 return self.o
39
40 def elaborate(self, platform):
41 m = Module()
42
43 self.o.a.m.name = "o_a_m"
44 self.o.b.m.name = "o_b_m"
45
46 m.submodules.norm1_insel_a = insel_a = FPNumBase(self.i.a)
47 m.submodules.norm1_insel_b = insel_b = FPNumBase(self.i.b)
48 insel_a.m.name = "i_a_m"
49 insel_b.m.name = "i_b_m"
50
51 mwid = self.o.z.m_width
52 msb_a = FPMSBHigh(mwid, len(insel_a.e))
53 msb_b = FPMSBHigh(mwid, len(insel_b.e))
54 m.submodules.norm_pe_a = msb_a
55 m.submodules.norm_pe_b = msb_b
56
57 # connect to msb_a/b module
58 m.d.comb += msb_a.m_in.eq(insel_a.m)
59 m.d.comb += msb_a.e_in.eq(insel_a.e)
60 m.d.comb += msb_b.m_in.eq(insel_b.m)
61 m.d.comb += msb_b.e_in.eq(insel_b.e)
62
63 # copy input to output (overridden below)
64 m.d.comb += self.o.a.eq(insel_a)
65 m.d.comb += self.o.b.eq(insel_b)
66
67 # normalisation increase/decrease conditions
68 decrease_a = Signal(reset_less=True)
69 decrease_b = Signal(reset_less=True)
70 m.d.comb += decrease_a.eq(insel_a.m_msbzero)
71 m.d.comb += decrease_b.eq(insel_b.m_msbzero)
72
73 # ok this is near-identical to FPNorm. TODO: modularise
74 with m.If(~self.i.out_do_z):
75 with m.If(decrease_a):
76 m.d.comb += [
77 self.o.a.e.eq(msb_a.e_out),
78 self.o.a.m.eq(msb_a.m_out),
79 ]
80 with m.If(decrease_b):
81 m.d.comb += [
82 self.o.b.e.eq(msb_b.e_out),
83 self.o.b.m.eq(msb_b.m_out),
84 ]
85
86 m.d.comb += self.o.ctx.eq(self.i.ctx)
87 m.d.comb += self.o.out_do_z.eq(self.i.out_do_z)
88 m.d.comb += self.o.oz.eq(self.i.oz)
89
90 return m
91
92