split out adder code (PartitionedAdder) into module, PartitionPoints too
[ieee754fpu.git] / src / ieee754 / fcvt / float2int.py
1 """IEEE754 Floating Point Converter
2
3 Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
4
5 Relevant bugreports:
6 * http://bugs.libre-riscv.org/show_bug.cgi?id=112
7 * http://bugs.libre-riscv.org/show_bug.cgi?id=113
8
9 """
10
11 from nmigen import Module, Signal, Cat, Const, Mux
12 from nmigen.cli import main, verilog
13
14 from nmutil.pipemodbase import PipeModBase
15 from ieee754.fpcommon.fpbase import Overflow
16 from ieee754.fpcommon.basedata import FPBaseData
17 from ieee754.fpcommon.packdata import FPPackData
18 from ieee754.fpcommon.exphigh import FPEXPHigh
19
20 from ieee754.fpcommon.fpbase import FPNumDecode, FPNumBaseRecord
21
22
23 class FPCVTFloatToIntMod(PipeModBase):
24 """ integer to FP conversion: copes with 16/32/64 fp to 16/32/64 int/uint
25
26 self.ctx.i.op & 0x1 == 0x1 : SIGNED int
27 self.ctx.i.op & 0x1 == 0x0 : UNSIGNED int
28
29 Note: this is a single-stage conversion that goes direct to FPPackData
30 """
31 def __init__(self, in_pspec, out_pspec):
32 self.in_pspec = in_pspec
33 self.out_pspec = out_pspec
34 super().__init__(in_pspec, "fp2int")
35
36 def ispec(self):
37 return FPBaseData(self.in_pspec)
38
39 def ospec(self):
40 return FPPackData(self.out_pspec)
41
42 def elaborate(self, platform):
43 m = Module()
44 comb = m.d.comb
45
46 # set up FP Num decoder
47 print("in_width out", self.in_pspec.width,
48 self.out_pspec.width)
49 a1 = FPNumBaseRecord(self.in_pspec.width, False)
50 print("a1", a1.width, a1.rmw, a1.e_width, a1.e_start, a1.e_end)
51 m.submodules.sc_decode_a = a1 = FPNumDecode(None, a1)
52 comb += a1.v.eq(self.i.a)
53 z1 = self.o.z
54 mz = len(z1)
55 print("z1", mz)
56
57 me = a1.rmw
58 ms = mz - me
59 print("ms-me", ms, me)
60
61 espec = (a1.e_width, True)
62
63 signed = Signal(reset_less=True)
64 comb += signed.eq(self.i.ctx.op[0])
65
66 # special cases
67 with m.If(a1.is_nan):
68 with m.If(signed):
69 comb += self.o.z.eq((1<<(mz-1))-1) # signed NaN overflow
70 with m.Else():
71 comb += self.o.z.eq((1<<mz)-1) # NaN overflow
72
73 # zero exponent: definitely out of range of INT. zero...
74 with m.Elif(a1.exp_n127):
75 comb += self.o.z.eq(0)
76
77 # unsigned, -ve, return 0
78 with m.Elif((~signed) & a1.s):
79 comb += self.o.z.eq(0)
80
81 # signed, exp too big
82 with m.Elif(signed & (a1.e >= Const(mz-1, espec))):
83 with m.If(a1.s): # negative FP, so negative overrun
84 comb += self.o.z.eq(-(1<<(mz-1)))
85 with m.Else(): # positive FP, so positive overrun
86 comb += self.o.z.eq((1<<(mz-1))-1)
87
88 # unsigned, exp too big
89 with m.Elif((~signed) & (a1.e >= Const(mz, espec))):
90 with m.If(a1.s): # negative FP, so negative overrun (zero)
91 comb += self.o.z.eq(0)
92 with m.Else(): # positive FP, so positive overrun (max INT)
93 comb += self.o.z.eq((1<<(mz))-1)
94
95 # ok exp should be in range: shift and round it
96 with m.Else():
97 adjust = 0
98 if a1.m_width > mz:
99 adjust = a1.m_width - mz
100 mlen = max(a1.m_width, mz) + 5
101 mantissa = Signal(mlen, reset_less=True)
102 l = [0] * 2 + [a1.m[:-1]] + [1]
103 comb += mantissa[-a1.m_width-3:].eq(Cat(*l))
104 comb += self.o.z.eq(mantissa)
105
106 # shift
107 msr = FPEXPHigh(mlen, espec[0])
108 m.submodules.norm_exp = msr
109 comb += [msr.m_in.eq(mantissa),
110 msr.e_in.eq(a1.e),
111 msr.ediff.eq(mz - a1.e+adjust)
112 ]
113
114 of = Overflow()
115 comb += of.guard.eq(msr.m_out[2])
116 comb += of.round_bit.eq(msr.m_out[1])
117 comb += of.sticky.eq(msr.m_out[0])
118 comb += of.m0.eq(msr.m_out[3])
119
120 # XXX TODO: check if this overflows the mantissa
121 mround = Signal(mlen, reset_less=True)
122 with m.If(of.roundz):
123 comb += mround.eq(msr.m_out[3:]+1)
124 with m.Else():
125 comb += mround.eq(msr.m_out[3:])
126
127 # check sign
128 with m.If(signed & a1.s):
129 comb += self.o.z.eq(-mround) # inverted
130 with m.Else():
131 comb += self.o.z.eq(mround)
132
133 # copy the context (muxid, operator)
134 #comb += self.o.oz.eq(self.o.z.v)
135 comb += self.o.ctx.eq(self.i.ctx)
136
137 return m