1 # IEEE754 FCLASS Module
2 # Copyright (C) 2019 Luke Kenneth Casson Leighon <lkcl@lkcl.net>
4 from nmigen
import Module
, Signal
, Cat
6 from nmutil
.pipemodbase
import PipeModBase
7 from ieee754
.fpcommon
.basedata
import FPBaseData
8 from ieee754
.fpcommon
.pack
import FPPackData
9 from ieee754
.fpcommon
.fpbase
import FPNumDecode
, FPNumBaseRecord
12 class FPClassMod(PipeModBase
):
13 """ obtains floating point information (zero, nan, inf etc.)
15 def __init__(self
, in_pspec
, out_pspec
):
16 self
.in_pspec
= in_pspec
17 self
.out_pspec
= out_pspec
18 super().__init
__(in_pspec
, "fclass")
21 return FPBaseData(self
.in_pspec
)
24 return FPPackData(self
.out_pspec
)
26 def elaborate(self
, platform
):
30 # decode incoming FP number
31 print("in_width out", self
.in_pspec
.width
,
33 a1
= FPNumBaseRecord(self
.in_pspec
.width
, False)
34 print("a1", a1
.width
, a1
.rmw
, a1
.e_width
, a1
.e_start
, a1
.e_end
)
35 m
.submodules
.sc_decode_a
= a1
= FPNumDecode(None, a1
)
36 comb
+= a1
.v
.eq(self
.i
.a
)
38 # FCLASS: work out the "type" of the FP number
40 finite_nzero
= Signal(reset_less
=True)
41 msbzero
= Signal(reset_less
=True)
42 is_sig_nan
= Signal(reset_less
=True)
43 # XXX use *REAL* mantissa width to detect msb.
44 # XXX do NOT use a1.m_msbzero because it has extra bitspace
45 comb
+= msbzero
.eq(a1
.m
[a1
.rmw
-1] == 0) # sigh, 1 extra msb bit
46 comb
+= finite_nzero
.eq(~a1
.is_nan
& ~a1
.is_inf
& ~a1
.is_zero
)
47 comb
+= is_sig_nan
.eq(a1
.exp_128
& (msbzero
) & (~a1
.m_zero
))
48 subnormal
= a1
.exp_n127
50 # this is hardware-optimal but very hard to understand.
51 # see unit test test_fclass_pipe.py fclass() for what's
53 comb
+= self
.o
.z
.eq(Cat(
54 a1
.s
& a1
.is_inf
, # | −inf.
55 a1
.s
& finite_nzero
& ~subnormal
, # | -normal number.
56 a1
.s
& finite_nzero
& subnormal
, # | -subnormal number.
57 a1
.s
& a1
.is_zero
, # | −0.
58 ~a1
.s
& a1
.is_zero
, # | +0.
59 ~a1
.s
& finite_nzero
& subnormal
, # | +subnormal number.
60 ~a1
.s
& finite_nzero
& ~subnormal
, # | +normal number.
61 ~a1
.s
& a1
.is_inf
, # | +inf.
62 is_sig_nan
, # | a signaling NaN.
63 a1
.is_nan
& ~is_sig_nan
)) # | a quiet NaN
65 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)