1 """IEEE754 Floating Point Conversion
3 Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
10 from nmutil
.singlepipe
import ControlBase
11 from nmutil
.concurrentunit
import ReservationStations
, num_bits
13 from ieee754
.fpcommon
.normtopack
import FPNormToPack
14 from ieee754
.pipeline
import PipelineSpec
, DynamicPipe
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
23 # from nmigen import Signal
26 self
.signed
= Signal(reset_less
=True)
29 return [self
.signed
.eq(i
)]
32 class FPCVTConvertDeNorm(DynamicPipe
):
33 """ FPConversion and De-norm
36 def __init__(self
, in_pspec
, out_pspec
, modkls
):
38 sc
= modkls(in_pspec
, out_pspec
)
40 super().__init
__(in_pspec
)
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)
51 #self._eqs = self.connect([self.pipe1, self.pipe2])
52 self
._eqs
= self
.connect([self
.pipe1
, ])
54 def elaborate(self
, platform
):
55 m
= ControlBase
.elaborate(self
, platform
)
56 m
.submodules
.down
= self
.pipe1
57 #m.submodules.normpack = self.pipe2
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
)
68 self
._eqs
= self
.connect([self
.pipe1
, self
.pipe2
])
70 def elaborate(self
, platform
):
71 m
= ControlBase
.elaborate(self
, platform
)
72 m
.submodules
.down
= self
.pipe1
73 m
.submodules
.normpack
= self
.pipe2
78 class FPCVTMuxInOutBase(ReservationStations
):
79 """ Reservation-Station version of FPCVT pipeline.
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)
85 Fan-in and Fan-out are combinatorial.
88 def __init__(self
, modkls
, e_extra
, in_width
, out_width
,
89 num_rows
, op_wid
=0, pkls
=FPCVTBasePipe
):
91 self
.id_wid
= num_bits(num_rows
)
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
)
96 self
.alu
= pkls(modkls
, e_extra
, self
.in_pspec
, self
.out_pspec
)
97 ReservationStations
.__init
__(self
, num_rows
)
100 class FPCVTF2IntMuxInOut(FPCVTMuxInOutBase
):
101 """ Reservation-Station version of FPCVT pipeline.
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)
107 Fan-in and Fan-out are combinatorial.
110 def __init__(self
, in_width
, out_width
, num_rows
, op_wid
=0):
111 FPCVTMuxInOutBase
.__init
__(self
, FPCVTFloatToIntMod
, False,
114 pkls
=FPCVTFtoIntBasePipe
)
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
122 muxfactoryinput
= [("FPCVTDownMuxInOut", FPCVTDownConvertMod
, True, ),
123 ("FPCVTUpMuxInOut", FPCVTUpConvertMod
, False, ),
124 ("FPCVTIntMuxInOut", FPCVTIntToFloatMod
, True, ),
127 def getkls(*args
, **kwargs
):
128 print ("getkls", args
, kwargs
)
129 return FPCVTMuxInOutBase(*args
, **kwargs
)
131 for (name
, kls
, e_extra
) in muxfactoryinput
:
132 fn
= functools
.partial(getkls
, kls
, e_extra
)
133 setattr(sys
.modules
[__name__
], name
, fn
)