845a4e007b2d695ca4084a0c9a140fbd19baeb2a
1 # IEEE754 Floating Point Converter
2 # Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
4 from nmigen
import Module
, Signal
, Cat
, Const
, Mux
, Elaboratable
5 from nmigen
.cli
import main
, verilog
7 from ieee754
.fpcommon
.fpbase
import Overflow
8 from ieee754
.fpcommon
.getop
import FPADDBaseData
9 from ieee754
.fpcommon
.postcalc
import FPPostCalcData
10 from ieee754
.fpcommon
.exphigh
import FPEXPHigh
12 from ieee754
.fpcommon
.fpbase
import FPNumDecode
, FPNumBaseRecord
15 class FPCVTFloatToIntMod(Elaboratable
):
16 """ integer to FP conversion: copes with 16/32/64 fp to 16/32/64 int/uint
18 self.ctx.i.op & 0x1 == 0x1 : SIGNED int
19 self.ctx.i.op & 0x1 == 0x0 : UNSIGNED int
21 Note: this is a single-stage conversion that goes direct to FPPackData
23 def __init__(self
, in_pspec
, out_pspec
):
24 self
.in_pspec
= in_pspec
25 self
.out_pspec
= out_pspec
30 return FPADDBaseData(self
.in_pspec
)
33 return FPPackData(self
.out_pspec
)
35 def setup(self
, m
, i
):
36 """ links module to inputs and outputs
38 m
.submodules
.upconvert
= self
39 m
.d
.comb
+= self
.i
.eq(i
)
44 def elaborate(self
, platform
):
48 # set up FP Num decoder
49 print("in_width out", self
.in_pspec
.width
,
51 a1
= FPNumBaseRecord(self
.in_pspec
.width
, False)
52 print("a1", a1
.width
, a1
.rmw
, a1
.e_width
, a1
.e_start
, a1
.e_end
)
53 m
.submodules
.sc_decode_a
= a1
= FPNumDecode(None, a1
)
54 comb
+= a1
.v
.eq(self
.i
.a
)
61 print("ms-me", ms
, me
)
63 espec
= (a1
.e_width
, True)
65 signed
= Signal(reset_less
=True)
66 comb
+= signed
.eq(self
.i
.ctx
.op
[0])
71 comb
+= self
.o
.z
.eq((1<<(mz
-1))-1) # signed NaN overflow
73 comb
+= self
.o
.z
.eq((1<<mz
)-1) # NaN overflow
75 # zero exponent: definitely out of range of INT. zero...
76 with m
.Elif(a1
.exp_n127
):
77 comb
+= self
.o
.z
.eq(0)
79 # unsigned, -ve, return 0
80 with m
.Elif((~signed
) & a1
.s
):
81 comb
+= self
.o
.z
.eq(0)
84 with m
.Elif(signed
& (a1
.e
>= Const(mz
-1, espec
))):
85 with m
.If(a1
.s
): # negative FP, so negative overrun
86 comb
+= self
.o
.z
.eq(-(1<<(mz
-1)))
87 with m
.Else(): # positive FP, so positive overrun
88 comb
+= self
.o
.z
.eq((1<<(mz
-1))-1)
90 # unsigned, exp too big
91 with m
.Elif((~signed
) & (a1
.e
>= Const(mz
, espec
))):
92 with m
.If(a1
.s
): # negative FP, so negative overrun (zero)
93 comb
+= self
.o
.z
.eq(0)
94 with m
.Else(): # positive FP, so positive overrun (max INT)
95 comb
+= self
.o
.z
.eq((1<<(mz
))-1)
97 # ok exp should be in range: shift and round it
99 mlen
= max(a1
.m_width
, mz
) + 5
100 mantissa
= Signal(mlen
, reset_less
=True)
101 l
= [0] * 2 + [a1
.m
[:-1]] + [1]
102 comb
+= mantissa
[-a1
.m_width
-3:].eq(Cat(*l
))
103 comb
+= self
.o
.z
.eq(mantissa
)
106 msr
= FPEXPHigh(mlen
, espec
[0])
107 m
.submodules
.norm_exp
= msr
108 comb
+= [msr
.m_in
.eq(mantissa
),
110 msr
.ediff
.eq(Mux(signed
, mz
, mz
)-a1
.e
)
114 comb
+= of
.guard
.eq(msr
.m_out
[2])
115 comb
+= of
.round_bit
.eq(msr
.m_out
[1])
116 comb
+= of
.sticky
.eq(msr
.m_out
[0])
117 comb
+= of
.m0
.eq(msr
.m_out
[3])
119 # XXX TODO: check if this overflows the mantissa
120 mround
= Signal(mlen
, reset_less
=True)
121 with m
.If(of
.roundz
):
122 comb
+= mround
.eq(msr
.m_out
[3:]+1)
124 comb
+= mround
.eq(msr
.m_out
[3:])
127 with m
.If(signed
& a1
.s
):
128 comb
+= self
.o
.z
.eq(-mround
) # inverted
130 comb
+= self
.o
.z
.eq(mround
)
132 # copy the context (muxid, operator)
133 #comb += self.o.oz.eq(self.o.z.v)
134 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)