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