rename FPModBase* to PipeModBase*
[ieee754fpu.git] / src / ieee754 / fcvt / upsize.py
1 # IEEE754 Floating Point Conversion
2 # Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3
4
5 import sys
6 import functools
7
8 from nmigen import Module, Signal, Cat
9 from nmigen.cli import main, verilog
10
11 from nmutil.pipemodbase import PipeModBase
12 from ieee754.fpcommon.getop import FPADDBaseData
13 from ieee754.fpcommon.postcalc import FPAddStage1Data
14 from ieee754.fpcommon.fpbase import FPNumDecode, FPNumBaseRecord
15
16
17 class FPCVTUpConvertMod(PipeModBase):
18 """ FP up-conversion (lower to higher bitwidth)
19 """
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")
24
25 def ispec(self):
26 return FPADDBaseData(self.in_pspec)
27
28 def ospec(self):
29 return FPAddStage1Data(self.out_pspec, e_extra=False)
30
31 def elaborate(self, platform):
32 m = Module()
33 comb = m.d.comb
34
35 #m.submodules.sc_out_z = self.o.z
36
37 # decode: XXX really should move to separate stage
38 print("in_width out", self.in_pspec.width,
39 self.out_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)
44 z1 = self.o.z
45 print("z1", z1.width, z1.rmw, z1.e_width, z1.e_start, z1.e_end)
46
47 me = a1.rmw
48 ms = self.o.z.rmw - a1.rmw
49 print("ms-me", ms, me, self.o.z.rmw, a1.rmw)
50
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
56
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])
62
63 # most special cases active (except tiny-number normalisation, below)
64 comb += self.o.out_do_z.eq(1)
65
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
70 with m.Else():
71 comb += self.o.z.inf(a1.s) # RISC-V wants signed INF
72 with m.Else():
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
77 with m.Else():
78 # RISC-V zero needs actual zero
79 comb += self.o.z.zero(a1.s)
80
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)
84
85 return m