b171db272550a49289c2db6242a10248b9c41538
[ieee754fpu.git] / src / ieee754 / fpdiv / pipeline.py
1 """IEEE Floating Point Divider Pipeline
2
3 Relevant bugreport: http://bugs.libre-riscv.org/show_bug.cgi?id=99
4
5 Stack looks like this:
6
7 scnorm - FPDIVSpecialCasesDeNorm ispec FPADDBaseData ospec FPSCData
8 StageChain: FPDIVSpecialCasesMod,
9 FPAddDeNormMod
10
11 pipediv0 - FPDivStages(start=true) ispec FPSCData ospec FPDivStage0Data
12 StageChain: FPDivStage0Mod,
13 FPDivStage1Mod,
14 ...
15 FPDivStage1Mod
16
17 pipediv1 - FPDivStages() ispec FPDivStage0Data ospec FPDivStage0Data
18 StageChain: FPDivStage1Mod,
19 ...
20 FPDivStage1Mod
21 ...
22 ...
23
24 pipediv5 - FPDivStages(end=true ispec FPDivStage0Data ospec FPAddStage1Data
25 StageChain: FPDivStage1Mod,
26 ...
27 FPDivStage1Mod,
28 FPDivStage2Mod
29
30 normpack - FPNormToPack ispec FPAddStage1Data ospec FPPackData
31 StageChain: Norm1ModSingle,
32 RoundMod,
33 CorrectionsMod,
34 PackMod
35
36 the number of combinatorial StageChains (n_combinatorial_stages) in
37 FPDivStages is an argument arranged to get the length of the whole
38 pipeline down to sane numbers.
39 """
40
41 from nmigen import Module
42 from nmigen.cli import main, verilog
43
44 from nmutil.singlepipe import ControlBase
45 from nmutil.concurrentunit import ReservationStations, num_bits
46
47 from ieee754.fpcommon.getop import FPADDBaseData
48 from ieee754.fpcommon.denorm import FPSCData
49 from ieee754.fpcommon.pack import FPPackData
50 from ieee754.fpcommon.normtopack import FPNormToPack
51 from .specialcases import FPDIVSpecialCasesDeNorm
52 from .divstages import FPDivStages
53
54
55
56 class FPDIVBasePipe(ControlBase):
57 def __init__(self, width, id_wid):
58 ControlBase.__init__(self)
59 self.pipestart = FPDIVSpecialCasesDeNorm(width, id_wid)
60 pipechain = []
61 n_stages = 6 # TODO
62 n_combinatorial_stages = 2 # TODO
63 for i in range(n_stages):
64 begin = i == 0 # needs to convert input from pipestart ospec
65 end = i == n_stages - 1 # needs to convert output to pipeend ispec
66 pipechain.append(FPDivStages(width, id_wid,
67 n_combinatorial_stages,
68 begin, end))
69 self.pipechain = pipechain
70 self.pipeend = FPNormToPack(width, id_wid)
71
72 self._eqs = self.connect([self.pipestart] + pipechain + [self.pipeend])
73
74 def elaborate(self, platform):
75 m = ControlBase.elaborate(self, platform)
76 m.submodules.scnorm = self.pipestart
77 for i, p in enumerate(self.pipechain):
78 setattr(m.submodules, "pipediv%d" % i, p)
79 m.submodules.normpack = self.pipeend
80 m.d.comb += self._eqs
81 return m
82
83
84 class FPDIVMuxInOut(ReservationStations):
85 """ Reservation-Station version of FPDIV pipeline.
86
87 * fan-in on inputs (an array of FPADDBaseData: a,b,mid)
88 * N-stage divider pipeline
89 * fan-out on outputs (an array of FPPackData: z,mid)
90
91 Fan-in and Fan-out are combinatorial.
92 """
93 def __init__(self, width, num_rows):
94 self.width = width
95 self.id_wid = num_bits(width)
96 self.alu = FPDIVBasePipe(width, self.id_wid)
97 ReservationStations.__init__(self, num_rows)
98
99 def i_specfn(self):
100 return FPADDBaseData(self.width, self.id_wid)
101
102 def o_specfn(self):
103 return FPPackData(self.width, self.id_wid)