split out denorm to separate module
[ieee754fpu.git] / src / add / 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, Cat, Mux, Array, Const
6 from nmigen.lib.coding import PriorityEncoder
7 from nmigen.cli import main, verilog
8 from math import log
9
10 from fpbase import FPNumIn, FPNumOut, FPOp, Overflow, FPBase, FPNumBase
11 from fpbase import MultiShiftRMerge, Trigger
12 from singlepipe import (ControlBase, StageChain, UnbufferedPipeline,
13 PassThroughStage)
14 from multipipe import CombMuxOutPipe
15 from multipipe import PriorityCombMuxInPipe
16
17 from fpbase import FPState
18 from fpcommon.getop import (FPGetOpMod, FPGetOp, FPNumBase2Ops, FPADDBaseData, FPGet2OpMod, FPGet2Op)
19
20
21 class FPSCData:
22
23 def __init__(self, width, id_wid):
24 self.a = FPNumBase(width, True)
25 self.b = FPNumBase(width, True)
26 self.z = FPNumOut(width, False)
27 self.oz = Signal(width, reset_less=True)
28 self.out_do_z = Signal(reset_less=True)
29 self.mid = Signal(id_wid, reset_less=True)
30
31 def eq(self, i):
32 return [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz),
33 self.a.eq(i.a), self.b.eq(i.b), self.mid.eq(i.mid)]
34
35
36 class FPAddDeNormMod(FPState):
37
38 def __init__(self, width, id_wid):
39 self.width = width
40 self.id_wid = id_wid
41 self.i = self.ispec()
42 self.o = self.ospec()
43
44 def ispec(self):
45 return FPSCData(self.width, self.id_wid)
46
47 def ospec(self):
48 return FPSCData(self.width, self.id_wid)
49
50 def process(self, i):
51 return self.o
52
53 def setup(self, m, i):
54 """ links module to inputs and outputs
55 """
56 m.submodules.denormalise = self
57 m.d.comb += self.i.eq(i)
58
59 def elaborate(self, platform):
60 m = Module()
61 m.submodules.denorm_in_a = self.i.a
62 m.submodules.denorm_in_b = self.i.b
63 m.submodules.denorm_out_a = self.o.a
64 m.submodules.denorm_out_b = self.o.b
65
66 with m.If(~self.i.out_do_z):
67 # XXX hmmm, don't like repeating identical code
68 m.d.comb += self.o.a.eq(self.i.a)
69 with m.If(self.i.a.exp_n127):
70 m.d.comb += self.o.a.e.eq(self.i.a.N126) # limit a exponent
71 with m.Else():
72 m.d.comb += self.o.a.m[-1].eq(1) # set top mantissa bit
73
74 m.d.comb += self.o.b.eq(self.i.b)
75 with m.If(self.i.b.exp_n127):
76 m.d.comb += self.o.b.e.eq(self.i.b.N126) # limit a exponent
77 with m.Else():
78 m.d.comb += self.o.b.m[-1].eq(1) # set top mantissa bit
79
80 m.d.comb += self.o.mid.eq(self.i.mid)
81 m.d.comb += self.o.z.eq(self.i.z)
82 m.d.comb += self.o.out_do_z.eq(self.i.out_do_z)
83 m.d.comb += self.o.oz.eq(self.i.oz)
84
85 return m
86
87
88 class FPAddDeNorm(FPState):
89
90 def __init__(self, width, id_wid):
91 FPState.__init__(self, "denormalise")
92 self.mod = FPAddDeNormMod(width)
93 self.out_a = FPNumBase(width)
94 self.out_b = FPNumBase(width)
95
96 def setup(self, m, i):
97 """ links module to inputs and outputs
98 """
99 self.mod.setup(m, i)
100
101 m.d.sync += self.out_a.eq(self.mod.out_a)
102 m.d.sync += self.out_b.eq(self.mod.out_b)
103
104 def action(self, m):
105 # Denormalised Number checks
106 m.next = "align"
107
108