split out add1 to separate module
[ieee754fpu.git] / src / add / fpadd / add1.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, FPID
18 from fpcommon.denorm import (FPSCData, FPAddDeNormMod, FPAddDeNorm)
19 from fpcommon.postcalc import FPAddStage1Data
20 from fpcommon.postnormalise import (FPNorm1Data, FPNorm1ModSingle,
21 FPNorm1ModMulti, FPNorm1Single, FPNorm1Multi)
22 from fpcommon.roundz import (FPRoundData, FPRoundMod, FPRound)
23 from fpcommon.corrections import (FPCorrectionsMod, FPCorrections)
24 from fpcommon.pack import (FPPackData, FPPackMod, FPPack)
25 from fpcommon.normtopack import FPNormToPack
26 from fpcommon.putz import (FPPutZ, FPPutZIdx)
27
28 from fpadd.specialcases import (FPAddSpecialCasesMod, FPAddSpecialCases,
29 FPAddSpecialCasesDeNorm)
30 from fpadd.align import (FPAddAlignMulti, FPAddAlignMultiMod, FPNumIn2Ops,
31 FPAddAlignSingleMod, FPAddAlignSingle)
32 from fpadd.add0 import (FPAddStage0Data, FPAddStage0Mod, FPAddStage0)
33
34
35 class FPAddStage1Mod(FPState):
36 """ Second stage of add: preparation for normalisation.
37 detects when tot sum is too big (tot[27] is kinda a carry bit)
38 """
39
40 def __init__(self, width, id_wid):
41 self.width = width
42 self.id_wid = id_wid
43 self.i = self.ispec()
44 self.o = self.ospec()
45
46 def ispec(self):
47 return FPAddStage0Data(self.width, self.id_wid)
48
49 def ospec(self):
50 return FPAddStage1Data(self.width, self.id_wid)
51
52 def process(self, i):
53 return self.o
54
55 def setup(self, m, i):
56 """ links module to inputs and outputs
57 """
58 m.submodules.add1 = self
59 m.submodules.add1_out_overflow = self.o.of
60
61 m.d.comb += self.i.eq(i)
62
63 def elaborate(self, platform):
64 m = Module()
65 m.d.comb += self.o.z.eq(self.i.z)
66 # tot[-1] (MSB) gets set when the sum overflows. shift result down
67 with m.If(~self.i.out_do_z):
68 with m.If(self.i.tot[-1]):
69 m.d.comb += [
70 self.o.z.m.eq(self.i.tot[4:]),
71 self.o.of.m0.eq(self.i.tot[4]),
72 self.o.of.guard.eq(self.i.tot[3]),
73 self.o.of.round_bit.eq(self.i.tot[2]),
74 self.o.of.sticky.eq(self.i.tot[1] | self.i.tot[0]),
75 self.o.z.e.eq(self.i.z.e + 1)
76 ]
77 # tot[-1] (MSB) zero case
78 with m.Else():
79 m.d.comb += [
80 self.o.z.m.eq(self.i.tot[3:]),
81 self.o.of.m0.eq(self.i.tot[3]),
82 self.o.of.guard.eq(self.i.tot[2]),
83 self.o.of.round_bit.eq(self.i.tot[1]),
84 self.o.of.sticky.eq(self.i.tot[0])
85 ]
86
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 m.d.comb += self.o.mid.eq(self.i.mid)
90
91 return m
92
93
94 class FPAddStage1(FPState):
95
96 def __init__(self, width, id_wid):
97 FPState.__init__(self, "add_1")
98 self.mod = FPAddStage1Mod(width)
99 self.out_z = FPNumBase(width, False)
100 self.out_of = Overflow()
101 self.norm_stb = Signal()
102
103 def setup(self, m, i):
104 """ links module to inputs and outputs
105 """
106 self.mod.setup(m, i)
107
108 m.d.sync += self.norm_stb.eq(0) # sets to zero when not in add1 state
109
110 m.d.sync += self.out_of.eq(self.mod.out_of)
111 m.d.sync += self.out_z.eq(self.mod.out_z)
112 m.d.sync += self.norm_stb.eq(1)
113
114 def action(self, m):
115 m.next = "normalise_1"
116