big convert g/s/r mid --> muxid
[ieee754fpu.git] / src / ieee754 / fpcommon / denorm.py
1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
3 # 2013-12-12
4
5 from nmigen import Module, Signal, Elaboratable
6 from nmigen.cli import main, verilog
7 from math import log
8
9 from ieee754.fpcommon.fpbase import FPNumIn, FPNumOut, FPNumBaseRecord
10 from ieee754.fpcommon.fpbase import FPState, FPNumBase
11 from ieee754.fpcommon.getop import FPBaseData
12
13
14 class FPSCData:
15
16 def __init__(self, width, pspec, m_extra):
17
18 # NOTE: difference between z and oz is that oz is created by
19 # special-cases module(s) and will propagate, along with its
20 # "bypass" signal out_do_z, through the pipeline, *disabling*
21 # all processing of all subsequent stages.
22 self.a = FPNumBaseRecord(width, m_extra) # operand a
23 self.b = FPNumBaseRecord(width, m_extra) # operand b
24 self.z = FPNumBaseRecord(width, False) # denormed result
25 self.oz = Signal(width, reset_less=True) # "finished" (bypass) result
26 self.out_do_z = Signal(reset_less=True) # "bypass" enabled
27 self.ctx = FPBaseData(width, pspec)
28 self.muxid = self.ctx.muxid
29
30 def __iter__(self):
31 yield from self.a
32 yield from self.b
33 yield from self.z
34 yield self.oz
35 yield self.out_do_z
36 yield from self.ctx
37
38 def eq(self, i):
39 ret = [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz),
40 self.a.eq(i.a), self.b.eq(i.b), self.ctx.eq(i.ctx)]
41 return ret
42
43
44 class FPAddDeNormMod(FPState, Elaboratable):
45
46 def __init__(self, width, pspec, m_extra):
47 self.width = width
48 self.pspec = pspec
49 self.m_extra = m_extra
50 self.i = self.ispec()
51 self.o = self.ospec()
52
53 def ispec(self):
54 return FPSCData(self.width, self.pspec, self.m_extra)
55
56 def ospec(self):
57 return FPSCData(self.width, self.pspec, self.m_extra)
58
59 def process(self, i):
60 return self.o
61
62 def setup(self, m, i):
63 """ links module to inputs and outputs
64 """
65 m.submodules.denormalise = self
66 m.d.comb += self.i.eq(i)
67
68 def elaborate(self, platform):
69 m = Module()
70 m.submodules.denorm_in_a = in_a = FPNumBase(self.i.a)
71 m.submodules.denorm_in_b = in_b = FPNumBase(self.i.b)
72 #m.submodules.denorm_out_a = self.o.a
73 #m.submodules.denorm_out_b = self.o.b
74 #m.submodules.denorm_out_z = self.o.z
75
76 with m.If(~self.i.out_do_z):
77 # XXX hmmm, don't like repeating identical code
78 m.d.comb += self.o.a.eq(self.i.a)
79 with m.If(in_a.exp_n127):
80 m.d.comb += self.o.a.e.eq(self.i.a.N126) # limit a exponent
81 with m.Else():
82 m.d.comb += self.o.a.m[-1].eq(1) # set top mantissa bit
83
84 m.d.comb += self.o.b.eq(self.i.b)
85 with m.If(in_b.exp_n127):
86 m.d.comb += self.o.b.e.eq(self.i.b.N126) # limit a exponent
87 with m.Else():
88 m.d.comb += self.o.b.m[-1].eq(1) # set top mantissa bit
89
90 m.d.comb += self.o.ctx.eq(self.i.ctx)
91 m.d.comb += self.o.z.eq(self.i.z)
92 m.d.comb += self.o.out_do_z.eq(self.i.out_do_z)
93 m.d.comb += self.o.oz.eq(self.i.oz)
94
95 return m
96
97
98 class FPAddDeNorm(FPState):
99
100 def __init__(self, width, id_wid):
101 FPState.__init__(self, "denormalise")
102 self.mod = FPAddDeNormMod(width)
103 self.out_a = FPNumBaseRecord(width)
104 self.out_b = FPNumBaseRecord(width)
105
106 def setup(self, m, i):
107 """ links module to inputs and outputs
108 """
109 self.mod.setup(m, i)
110
111 m.d.sync += self.out_a.eq(self.mod.out_a)
112 m.d.sync += self.out_b.eq(self.mod.out_b)
113
114 def action(self, m):
115 # Denormalised Number checks
116 m.next = "align"
117
118