943533c66426c17d88e286ae8f4c1b1314028eeb
[ieee754fpu.git] / src / ieee754 / fpadd / pipeline.py
1 """IEEE Floating Point Adder Pipeline
2
3 Relevant bugreport: http://bugs.libre-riscv.org/show_bug.cgi?id=75
4
5 Stack looks like this:
6
7 * scnorm - FPMulSpecialCasesDeNorm
8 * addalign - FPAddAlignSingleAdd
9 * normpack - FPNormToPack
10
11 scnorm - FPDIVSpecialCasesDeNorm ispec FPADDBaseData
12 ------ ospec FPSCData
13
14 StageChain: FPMULSpecialCasesMod,
15 FPAddDeNormMod
16 FPAlignModSingle
17
18 addalign - FPAddAlignSingleAdd ispec FPSCData
19 -------- ospec FPPostCalcData
20
21 StageChain: FPAddAlignSingleMod
22 FPAddStage0Mod
23 FPAddStage1Mod
24
25 normpack - FPNormToPack ispec FPPostCalcData
26 -------- ospec FPPackData
27
28 StageChain: Norm1ModSingle,
29 RoundMod,
30 CorrectionsMod,
31 PackMod
32
33 This pipeline has a 3 clock latency, and, with the separation into
34 separate "modules", it is quite clear how to create longer-latency
35 pipelines (if needed) - just create a new, longer top-level (FPADDBasePipe
36 alternative) and construct shorter pipe stages using the building blocks,
37 RoundMod, FPAddStage0Mod etc.
38
39 """
40
41 from nmigen import Module
42 from nmigen.cli import main, verilog
43
44 from nmutil.singlepipe import ControlBase
45 from nmutil.multipipe import CombMuxOutPipe
46 from nmutil.multipipe import PriorityCombMuxInPipe
47 from nmutil.concurrentunit import ReservationStations, num_bits
48
49 from ieee754.fpcommon.getop import FPADDBaseData
50 from ieee754.fpcommon.denorm import FPSCData
51 from ieee754.fpcommon.pack import FPPackData
52 from ieee754.fpcommon.normtopack import FPNormToPack
53 from ieee754.fpadd.specialcases import FPAddSpecialCasesDeNorm
54 from ieee754.fpadd.addstages import FPAddAlignSingleAdd
55 from ieee754.pipeline import PipelineSpec
56
57
58 class FPADDBasePipe(ControlBase):
59 def __init__(self, pspec):
60 ControlBase.__init__(self)
61 self.pipe1 = FPAddSpecialCasesDeNorm(pspec)
62 self.pipe2 = FPAddAlignSingleAdd(pspec)
63 self.pipe3 = FPNormToPack(pspec)
64
65 self._eqs = self.connect([self.pipe1, self.pipe2, self.pipe3])
66
67 def elaborate(self, platform):
68 m = ControlBase.elaborate(self, platform)
69 m.submodules.scnorm = self.pipe1
70 m.submodules.addalign = self.pipe2
71 m.submodules.normpack = self.pipe3
72 m.d.comb += self._eqs
73 return m
74
75
76 class FPADDMuxInOut(ReservationStations):
77 """ Reservation-Station version of FPADD pipeline.
78
79 * fan-in on inputs (an array of FPADDBaseData: a,b,mid)
80 * 3-stage adder pipeline
81 * fan-out on outputs (an array of FPPackData: z,mid)
82
83 Fan-in and Fan-out are combinatorial.
84 """
85
86 def __init__(self, width, num_rows, op_wid=None):
87 self.id_wid = num_bits(num_rows)
88 self.op_wid = op_wid
89 self.pspec = PipelineSpec(width, self.id_wid, op_wid)
90 self.alu = FPADDBasePipe(self.pspec)
91 ReservationStations.__init__(self, num_rows)
92
93 def i_specfn(self):
94 return FPADDBaseData(self.pspec)
95
96 def o_specfn(self):
97 return FPPackData(self.pspec)