tidyup
[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
6 from nmigen.cli import main, verilog
7 from math import log
8
9 from ieee754.fpcommon.modbase import FPModBase
10 from ieee754.fpcommon.fpbase import FPNumBaseRecord
11 from ieee754.fpcommon.fpbase import FPNumBase
12 from ieee754.fpcommon.getop import FPPipeContext
13
14
15 class FPSCData:
16
17 def __init__(self, pspec, m_extra):
18 width = pspec.width
19 # NOTE: difference between z and oz is that oz is created by
20 # special-cases module(s) and will propagate, along with its
21 # "bypass" signal out_do_z, through the pipeline, *disabling*
22 # all processing of all subsequent stages.
23 self.a = FPNumBaseRecord(width, m_extra, name="a") # operand a
24 self.b = FPNumBaseRecord(width, m_extra, name="b") # operand b
25 self.z = FPNumBaseRecord(width, False, name="z") # denormed result
26 self.oz = Signal(width, reset_less=True) # "finished" (bypass) result
27 self.out_do_z = Signal(reset_less=True) # "bypass" enabled
28 self.ctx = FPPipeContext(pspec)
29 self.muxid = self.ctx.muxid
30
31 def __iter__(self):
32 yield from self.a
33 yield from self.b
34 yield from self.z
35 yield self.oz
36 yield self.out_do_z
37 yield from self.ctx
38
39 def eq(self, i):
40 ret = [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz),
41 self.a.eq(i.a), self.b.eq(i.b), self.ctx.eq(i.ctx)]
42 return ret
43
44
45 class FPAddDeNormMod(FPModBase):
46
47 def __init__(self, pspec, m_extra):
48 self.m_extra = m_extra
49 super().__init__(pspec, "denormalise")
50
51 def ispec(self):
52 return FPSCData(self.pspec, self.m_extra)
53
54 def ospec(self):
55 return FPSCData(self.pspec, self.m_extra)
56
57 def elaborate(self, platform):
58 m = Module()
59 comb = m.d.comb
60
61 m.submodules.denorm_in_a = in_a = FPNumBase(self.i.a)
62 m.submodules.denorm_in_b = in_b = FPNumBase(self.i.b)
63
64 with m.If(~self.i.out_do_z):
65 # XXX hmmm, don't like repeating identical code
66 comb += self.o.a.eq(self.i.a)
67 with m.If(in_a.exp_n127):
68 comb += self.o.a.e.eq(self.i.a.N126) # limit a exponent
69 with m.Else():
70 comb += self.o.a.m[-1].eq(1) # set top mantissa bit
71
72 comb += self.o.b.eq(self.i.b)
73 with m.If(in_b.exp_n127):
74 comb += self.o.b.e.eq(self.i.b.N126) # limit a exponent
75 with m.Else():
76 comb += self.o.b.m[-1].eq(1) # set top mantissa bit
77
78 comb += self.o.ctx.eq(self.i.ctx)
79 comb += self.o.z.eq(self.i.z)
80 comb += self.o.out_do_z.eq(self.i.out_do_z)
81 comb += self.o.oz.eq(self.i.oz)
82
83 return m
84
85