2eb83c5aece89851c705cfd0dfb13a6daf54e4d1
[ieee754fpu.git] / src / ieee754 / fcvt / pipeline.py
1 """IEEE754 Floating Point Conversion
2
3 Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
4
5 """
6
7
8 import sys
9 import functools
10
11 from nmigen import Module, Signal, Cat, Const, Mux, Elaboratable
12 from nmigen.cli import main, verilog
13
14 from nmutil.singlepipe import ControlBase
15 from nmutil.concurrentunit import ReservationStations, num_bits
16
17 from ieee754.fpcommon.basedata import FPBaseData
18 from ieee754.fpcommon.pack import FPPackData
19 from ieee754.fpcommon.normtopack import FPNormToPack
20
21
22 from nmigen import Module, Signal, Elaboratable
23 from math import log
24
25 from ieee754.fpcommon.getop import FPPipeContext
26
27 from ieee754.pipeline import PipelineSpec, DynamicPipe
28
29 from ieee754.fcvt.float2int import FPCVTFloatToIntMod
30 from ieee754.fcvt.int2float import FPCVTIntToFloatMod
31 from ieee754.fcvt.upsize import FPCVTUpConvertMod
32 from ieee754.fcvt.downsize import FPCVTDownConvertMod
33
34
35 class SignedOp:
36 def __init__(self):
37 self.signed = Signal(reset_less=True)
38
39 def eq(self, i):
40 return [self.signed.eq(i)]
41
42
43 class FPCVTConvertDeNorm(DynamicPipe):
44 """ FPConversion and De-norm
45 """
46
47 def __init__(self, in_pspec, out_pspec, modkls):
48 print ("cvtdenorm")
49 sc = modkls(in_pspec, out_pspec)
50 in_pspec.stage = sc
51 super().__init__(in_pspec)
52 self.out = self.ospec(None)
53
54
55 class FPCVTFtoIntBasePipe(ControlBase):
56 def __init__(self, modkls, e_extra, in_pspec, out_pspec):
57 ControlBase.__init__(self)
58 self.pipe1 = FPCVTConvertDeNorm(in_pspec, out_pspec, modkls)
59 #self.pipe2 = FPNormToPack(out_pspec, e_extra=e_extra)
60
61 #self._eqs = self.connect([self.pipe1, self.pipe2])
62 self._eqs = self.connect([self.pipe1, ])
63
64 def elaborate(self, platform):
65 m = ControlBase.elaborate(self, platform)
66 m.submodules.down = self.pipe1
67 #m.submodules.normpack = self.pipe2
68 m.d.comb += self._eqs
69 return m
70
71
72 class FPCVTBasePipe(ControlBase):
73 def __init__(self, modkls, e_extra, in_pspec, out_pspec):
74 ControlBase.__init__(self)
75 self.pipe1 = FPCVTConvertDeNorm(in_pspec, out_pspec, modkls)
76 self.pipe2 = FPNormToPack(out_pspec, e_extra=e_extra)
77
78 self._eqs = self.connect([self.pipe1, self.pipe2])
79
80 def elaborate(self, platform):
81 m = ControlBase.elaborate(self, platform)
82 m.submodules.down = self.pipe1
83 m.submodules.normpack = self.pipe2
84 m.d.comb += self._eqs
85 return m
86
87
88 class FPCVTMuxInOutBase(ReservationStations):
89 """ Reservation-Station version of FPCVT pipeline.
90
91 * fan-in on inputs (an array of FPBaseData: a,b,mid)
92 * 2-stage multiplier pipeline
93 * fan-out on outputs (an array of FPPackData: z,mid)
94
95 Fan-in and Fan-out are combinatorial.
96 """
97
98 def __init__(self, modkls, e_extra, in_width, out_width,
99 num_rows, op_wid=0, pkls=FPCVTBasePipe):
100 self.op_wid = op_wid
101 self.id_wid = num_bits(num_rows)
102
103 self.in_pspec = PipelineSpec(in_width, self.id_wid, self.op_wid)
104 self.out_pspec = PipelineSpec(out_width, self.id_wid, op_wid)
105
106 self.alu = pkls(modkls, e_extra, self.in_pspec, self.out_pspec)
107 ReservationStations.__init__(self, num_rows)
108
109 def i_specfn(self):
110 return FPBaseData(self.in_pspec)
111
112 def o_specfn(self):
113 return FPPackData(self.out_pspec)
114
115
116 class FPCVTF2IntMuxInOut(FPCVTMuxInOutBase):
117 """ Reservation-Station version of FPCVT pipeline.
118
119 * fan-in on inputs (an array of FPBaseData: a,b,mid)
120 * 2-stage multiplier pipeline
121 * fan-out on outputs (an array of FPPackData: z,mid)
122
123 Fan-in and Fan-out are combinatorial.
124 """
125
126 def __init__(self, in_width, out_width, num_rows, op_wid=0):
127 FPCVTMuxInOutBase.__init__(self, FPCVTFloatToIntMod, False,
128 in_width, out_width,
129 num_rows, op_wid,
130 pkls=FPCVTFtoIntBasePipe)
131
132
133 # factory which creates near-identical class structures that differ by
134 # the module and the e_extra argument. at some point it would be good
135 # to merge these into a single dynamic "thing" that takes an operator.
136 # however, the difference(s) in the bitwidths makes that a little less
137 # straightforward.
138 muxfactoryinput = [("FPCVTDownMuxInOut", FPCVTDownConvertMod, True, ),
139 ("FPCVTUpMuxInOut", FPCVTUpConvertMod, False, ),
140 ("FPCVTIntMuxInOut", FPCVTIntToFloatMod, True, ),
141 ]
142
143 def getkls(*args, **kwargs):
144 print ("getkls", args, kwargs)
145 return FPCVTMuxInOutBase(*args, **kwargs)
146
147 for (name, kls, e_extra) in muxfactoryinput:
148 fn = functools.partial(getkls, kls, e_extra)
149 setattr(sys.modules[__name__], name, fn)
150
151