switch to using nmutil's FHDLTestCase
[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 import sys
8 import functools
9
10 from nmutil.singlepipe import ControlBase
11 from nmutil.concurrentunit import ReservationStations, num_bits
12
13 from ieee754.fpcommon.normtopack import FPNormToPack
14 from ieee754.pipeline import PipelineSpec, DynamicPipe
15
16 from ieee754.fcvt.float2int import FPCVTFloatToIntMod
17 from ieee754.fcvt.int2float import FPCVTIntToFloatMod
18 from ieee754.fcvt.upsize import FPCVTUpConvertMod
19 from ieee754.fcvt.downsize import FPCVTDownConvertMod
20
21
22 # not used, yet
23 # from nmigen import Signal
24 class SignedOp:
25 def __init__(self):
26 self.signed = Signal(reset_less=True)
27
28 def eq(self, i):
29 return [self.signed.eq(i)]
30
31
32 class FPCVTConvertDeNorm(DynamicPipe):
33 """ FPConversion and De-norm
34 """
35
36 def __init__(self, in_pspec, out_pspec, modkls):
37 print ("cvtdenorm")
38 sc = modkls(in_pspec, out_pspec)
39 in_pspec.stage = sc
40 super().__init__(in_pspec)
41
42
43 # this one is slightly weird-looking because of course the INT output
44 # is, duh, an INT, so of course does not get "FP normalised".
45 class FPCVTFtoIntBasePipe(ControlBase):
46 def __init__(self, modkls, e_extra, in_pspec, out_pspec):
47 ControlBase.__init__(self)
48 self.pipe1 = FPCVTConvertDeNorm(in_pspec, out_pspec, modkls)
49 #self.pipe2 = FPNormToPack(out_pspec, e_extra=e_extra)
50
51 #self._eqs = self.connect([self.pipe1, self.pipe2])
52 self._eqs = self.connect([self.pipe1, ])
53
54 def elaborate(self, platform):
55 m = ControlBase.elaborate(self, platform)
56 m.submodules.down = self.pipe1
57 #m.submodules.normpack = self.pipe2
58 m.d.comb += self._eqs
59 return m
60
61
62 class FPCVTBasePipe(ControlBase):
63 def __init__(self, modkls, e_extra, in_pspec, out_pspec):
64 ControlBase.__init__(self)
65 self.pipe1 = FPCVTConvertDeNorm(in_pspec, out_pspec, modkls)
66 self.pipe2 = FPNormToPack(out_pspec, e_extra=e_extra)
67
68 self._eqs = self.connect([self.pipe1, self.pipe2])
69
70 def elaborate(self, platform):
71 m = ControlBase.elaborate(self, platform)
72 m.submodules.down = self.pipe1
73 m.submodules.normpack = self.pipe2
74 m.d.comb += self._eqs
75 return m
76
77
78 class FPCVTMuxInOutBase(ReservationStations):
79 """ Reservation-Station version of FPCVT pipeline.
80
81 * fan-in on inputs (an array of FPBaseData: a,b,mid)
82 * converter pipeline (alu)
83 * fan-out on outputs (an array of FPPackData: z,mid)
84
85 Fan-in and Fan-out are combinatorial.
86 """
87
88 def __init__(self, modkls, e_extra, in_width, out_width,
89 num_rows, op_wid=0, pkls=FPCVTBasePipe):
90 self.op_wid = op_wid
91 self.id_wid = num_bits(num_rows)
92
93 self.in_pspec = PipelineSpec(in_width, self.id_wid, self.op_wid)
94 self.out_pspec = PipelineSpec(out_width, self.id_wid, op_wid)
95
96 self.alu = pkls(modkls, e_extra, self.in_pspec, self.out_pspec)
97 ReservationStations.__init__(self, num_rows)
98
99
100 class FPCVTF2IntMuxInOut(FPCVTMuxInOutBase):
101 """ Reservation-Station version of FPCVT pipeline.
102
103 * fan-in on inputs (an array of FPBaseData: a,b,mid)
104 * 2-stage multiplier pipeline
105 * fan-out on outputs (an array of FPPackData: z,mid)
106
107 Fan-in and Fan-out are combinatorial.
108 """
109
110 def __init__(self, in_width, out_width, num_rows, op_wid=0):
111 FPCVTMuxInOutBase.__init__(self, FPCVTFloatToIntMod, False,
112 in_width, out_width,
113 num_rows, op_wid,
114 pkls=FPCVTFtoIntBasePipe)
115
116
117 # factory which creates near-identical class structures that differ by
118 # the module and the e_extra argument. at some point it would be good
119 # to merge these into a single dynamic "thing" that takes an operator.
120 # however, the difference(s) in the bitwidths makes that a little less
121 # straightforward.
122 muxfactoryinput = [("FPCVTDownMuxInOut", FPCVTDownConvertMod, True, ),
123 ("FPCVTUpMuxInOut", FPCVTUpConvertMod, False, ),
124 ("FPCVTIntMuxInOut", FPCVTIntToFloatMod, True, ),
125 ]
126
127 def getkls(*args, **kwargs):
128 print ("getkls", args, kwargs)
129 return FPCVTMuxInOutBase(*args, **kwargs)
130
131 for (name, kls, e_extra) in muxfactoryinput:
132 fn = functools.partial(getkls, kls, e_extra)
133 setattr(sys.modules[__name__], name, fn)
134
135