split out pipeline and statemachine to separate modules
[ieee754fpu.git] / src / add / fpadd / pipeline.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.getop import (FPGetOpMod, FPGetOp, FPNumBase2Ops, FPADDBaseData,
19 FPGet2OpMod, FPGet2Op)
20 from fpcommon.denorm import (FPSCData, FPAddDeNormMod, FPAddDeNorm)
21 from fpcommon.postcalc import FPAddStage1Data
22 from fpcommon.postnormalise import (FPNorm1Data, FPNorm1ModSingle,
23 FPNorm1ModMulti, FPNorm1Single, FPNorm1Multi)
24 from fpcommon.roundz import (FPRoundData, FPRoundMod, FPRound)
25 from fpcommon.corrections import (FPCorrectionsMod, FPCorrections)
26 from fpcommon.pack import (FPPackData, FPPackMod, FPPack)
27 from fpcommon.normtopack import FPNormToPack
28 from fpcommon.putz import (FPPutZ, FPPutZIdx)
29
30 from fpadd.specialcases import (FPAddSpecialCasesMod, FPAddSpecialCases,
31 FPAddSpecialCasesDeNorm)
32 from fpadd.align import (FPAddAlignMulti, FPAddAlignMultiMod, FPNumIn2Ops,
33 FPAddAlignSingleMod, FPAddAlignSingle)
34 from fpadd.add0 import (FPAddStage0Data, FPAddStage0Mod, FPAddStage0)
35 from fpadd.add1 import (FPAddStage1Mod, FPAddStage1)
36 from fpadd.addstages import FPAddAlignSingleAdd
37
38
39 class FPADDBasePipe(ControlBase):
40 def __init__(self, width, id_wid):
41 ControlBase.__init__(self)
42 self.pipe1 = FPAddSpecialCasesDeNorm(width, id_wid)
43 self.pipe2 = FPAddAlignSingleAdd(width, id_wid)
44 self.pipe3 = FPNormToPack(width, id_wid)
45
46 self._eqs = self.connect([self.pipe1, self.pipe2, self.pipe3])
47
48 def elaborate(self, platform):
49 m = Module()
50 m.submodules.scnorm = self.pipe1
51 m.submodules.addalign = self.pipe2
52 m.submodules.normpack = self.pipe3
53 m.d.comb += self._eqs
54 return m
55
56
57 class FPADDInMuxPipe(PriorityCombMuxInPipe):
58 def __init__(self, width, id_wid, num_rows):
59 self.num_rows = num_rows
60 def iospec(): return FPADDBaseData(width, id_wid)
61 stage = PassThroughStage(iospec)
62 PriorityCombMuxInPipe.__init__(self, stage, p_len=self.num_rows)
63
64
65 class FPADDMuxOutPipe(CombMuxOutPipe):
66 def __init__(self, width, id_wid, num_rows):
67 self.num_rows = num_rows
68 def iospec(): return FPPackData(width, id_wid)
69 stage = PassThroughStage(iospec)
70 CombMuxOutPipe.__init__(self, stage, n_len=self.num_rows)
71
72
73 class FPADDMuxInOut:
74 """ Reservation-Station version of FPADD pipeline.
75
76 * fan-in on inputs (an array of FPADDBaseData: a,b,mid)
77 * 3-stage adder pipeline
78 * fan-out on outputs (an array of FPPackData: z,mid)
79
80 Fan-in and Fan-out are combinatorial.
81 """
82 def __init__(self, width, id_wid, num_rows):
83 self.num_rows = num_rows
84 self.inpipe = FPADDInMuxPipe(width, id_wid, num_rows) # fan-in
85 self.fpadd = FPADDBasePipe(width, id_wid) # add stage
86 self.outpipe = FPADDMuxOutPipe(width, id_wid, num_rows) # fan-out
87
88 self.p = self.inpipe.p # kinda annoying,
89 self.n = self.outpipe.n # use pipe in/out as this class in/out
90 self._ports = self.inpipe.ports() + self.outpipe.ports()
91
92 def elaborate(self, platform):
93 m = Module()
94 m.submodules.inpipe = self.inpipe
95 m.submodules.fpadd = self.fpadd
96 m.submodules.outpipe = self.outpipe
97
98 m.d.comb += self.inpipe.n.connect_to_next(self.fpadd.p)
99 m.d.comb += self.fpadd.connect_to_next(self.outpipe)
100
101 return m
102
103 def ports(self):
104 return self._ports
105
106