1 # IEEE754 Floating Point Conversion
2 # Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
8 from nmigen
import Module
, Signal
, Cat
, Const
, Mux
, Elaboratable
9 from nmigen
.cli
import main
, verilog
11 from nmutil
.singlepipe
import ControlBase
12 from nmutil
.concurrentunit
import ReservationStations
, num_bits
14 from ieee754
.fpcommon
.fpbase
import Overflow
15 from ieee754
.fpcommon
.getop
import FPADDBaseData
16 from ieee754
.fpcommon
.pack
import FPPackData
17 from ieee754
.fpcommon
.normtopack
import FPNormToPack
18 from ieee754
.fpcommon
.postcalc
import FPAddStage1Data
19 from ieee754
.fpcommon
.msbhigh
import FPMSBHigh
20 from ieee754
.fpcommon
.exphigh
import FPEXPHigh
23 from nmigen
import Module
, Signal
, Elaboratable
26 from ieee754
.fpcommon
.fpbase
import FPNumIn
, FPNumOut
, FPNumBaseRecord
27 from ieee754
.fpcommon
.fpbase
import FPState
, FPNumBase
28 from ieee754
.fpcommon
.getop
import FPPipeContext
30 from ieee754
.fpcommon
.fpbase
import FPNumDecode
, FPNumBaseRecord
31 from nmutil
.singlepipe
import SimpleHandshake
, StageChain
33 from ieee754
.fpcommon
.fpbase
import FPState
34 from ieee754
.pipeline
import PipelineSpec
37 class FPCVTUpConvertMod(Elaboratable
):
38 """ FP up-conversion (lower to higher bitwidth)
40 def __init__(self
, in_pspec
, out_pspec
):
41 self
.in_pspec
= in_pspec
42 self
.out_pspec
= out_pspec
47 return FPADDBaseData(self
.in_pspec
)
50 return FPAddStage1Data(self
.out_pspec
, e_extra
=False)
52 def setup(self
, m
, i
):
53 """ links module to inputs and outputs
55 m
.submodules
.upconvert
= self
56 m
.d
.comb
+= self
.i
.eq(i
)
61 def elaborate(self
, platform
):
65 #m.submodules.sc_out_z = self.o.z
67 # decode: XXX really should move to separate stage
68 print("in_width out", self
.in_pspec
.width
,
70 a1
= FPNumBaseRecord(self
.in_pspec
.width
, False)
71 print("a1", a1
.width
, a1
.rmw
, a1
.e_width
, a1
.e_start
, a1
.e_end
)
72 m
.submodules
.sc_decode_a
= a1
= FPNumDecode(None, a1
)
73 comb
+= a1
.v
.eq(self
.i
.a
)
75 print("z1", z1
.width
, z1
.rmw
, z1
.e_width
, z1
.e_start
, z1
.e_end
)
78 ms
= self
.o
.z
.rmw
- a1
.rmw
79 print("ms-me", ms
, me
, self
.o
.z
.rmw
, a1
.rmw
)
81 # conversion can mostly be done manually...
82 comb
+= self
.o
.z
.s
.eq(a1
.s
)
83 comb
+= self
.o
.z
.e
.eq(a1
.e
)
84 comb
+= self
.o
.z
.m
[ms
:].eq(a1
.m
)
85 comb
+= self
.o
.z
.create(a1
.s
, a1
.e
, self
.o
.z
.m
) # ... here
87 # initialise rounding to all zeros (deactivate)
88 comb
+= self
.o
.of
.guard
.eq(0)
89 comb
+= self
.o
.of
.round_bit
.eq(0)
90 comb
+= self
.o
.of
.sticky
.eq(0)
91 comb
+= self
.o
.of
.m0
.eq(a1
.m
[0])
93 # most special cases active (except tiny-number normalisation, below)
94 comb
+= self
.o
.out_do_z
.eq(1)
96 # detect NaN/Inf first
97 with m
.If(a1
.exp_128
):
98 with m
.If(~a1
.m_zero
):
99 comb
+= self
.o
.z
.nan(0) # RISC-V wants normalised NaN
101 comb
+= self
.o
.z
.inf(a1
.s
) # RISC-V wants signed INF
103 with m
.If(a1
.exp_n127
):
104 with m
.If(~a1
.m_zero
):
105 comb
+= self
.o
.z
.m
[ms
:].eq(Cat(0, a1
.m
))
106 comb
+= self
.o
.out_do_z
.eq(0) # activate normalisation
108 # RISC-V zero needs actual zero
109 comb
+= self
.o
.z
.zero(a1
.s
)
111 # copy the context (muxid, operator)
112 comb
+= self
.o
.oz
.eq(self
.o
.z
.v
)
113 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)