1 # IEEE754 Floating Point Conversion
2 # Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
8 from nmigen
import Module
, Signal
, Cat
9 from nmigen
.cli
import main
, verilog
11 from nmutil
.pipemodbase
import PipeModBase
12 from ieee754
.fpcommon
.basedata
import FPBaseData
13 from ieee754
.fpcommon
.postcalc
import FPPostCalcData
14 from ieee754
.fpcommon
.fpbase
import FPNumDecode
, FPNumBaseRecord
17 class FPCVTUpConvertMod(PipeModBase
):
18 """ FP up-conversion (lower to higher bitwidth)
20 def __init__(self
, in_pspec
, out_pspec
):
21 self
.in_pspec
= in_pspec
22 self
.out_pspec
= out_pspec
23 super().__init
__(in_pspec
, "upconvert")
26 return FPBaseData(self
.in_pspec
)
29 return FPPostCalcData(self
.out_pspec
, e_extra
=False)
31 def elaborate(self
, platform
):
35 #m.submodules.sc_out_z = self.o.z
37 # decode: XXX really should move to separate stage
38 print("in_width out", self
.in_pspec
.width
,
40 a1
= FPNumBaseRecord(self
.in_pspec
.width
, False)
41 print("a1", a1
.width
, a1
.rmw
, a1
.e_width
, a1
.e_start
, a1
.e_end
)
42 m
.submodules
.sc_decode_a
= a1
= FPNumDecode(None, a1
)
43 comb
+= a1
.v
.eq(self
.i
.a
)
45 print("z1", z1
.width
, z1
.rmw
, z1
.e_width
, z1
.e_start
, z1
.e_end
)
48 ms
= self
.o
.z
.rmw
- a1
.rmw
49 print("ms-me", ms
, me
, self
.o
.z
.rmw
, a1
.rmw
)
51 # conversion can mostly be done manually...
52 comb
+= self
.o
.z
.s
.eq(a1
.s
)
53 comb
+= self
.o
.z
.e
.eq(a1
.e
)
54 comb
+= self
.o
.z
.m
[ms
:].eq(a1
.m
)
55 comb
+= self
.o
.z
.create(a1
.s
, a1
.e
, self
.o
.z
.m
) # ... here
57 # initialise rounding to all zeros (deactivate)
58 comb
+= self
.o
.of
.guard
.eq(0)
59 comb
+= self
.o
.of
.round_bit
.eq(0)
60 comb
+= self
.o
.of
.sticky
.eq(0)
61 comb
+= self
.o
.of
.m0
.eq(a1
.m
[0])
63 # most special cases active (except tiny-number normalisation, below)
64 comb
+= self
.o
.out_do_z
.eq(1)
66 # detect NaN/Inf first
67 with m
.If(a1
.exp_128
):
68 with m
.If(~a1
.m_zero
):
69 comb
+= self
.o
.z
.nan(0) # RISC-V wants normalised NaN
71 comb
+= self
.o
.z
.inf(a1
.s
) # RISC-V wants signed INF
73 with m
.If(a1
.exp_n127
):
74 with m
.If(~a1
.m_zero
):
75 comb
+= self
.o
.z
.m
[ms
:].eq(Cat(0, a1
.m
))
76 comb
+= self
.o
.out_do_z
.eq(0) # activate normalisation
78 # RISC-V zero needs actual zero
79 comb
+= self
.o
.z
.zero(a1
.s
)
81 # copy the context (muxid, operator)
82 comb
+= self
.o
.oz
.eq(self
.o
.z
.v
)
83 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)