1 # IEEE Floating Point Multiplier
3 from nmigen
import Module
, Signal
, Cat
, Const
4 from nmigen
.cli
import main
, verilog
7 from ieee754
.fpcommon
.fpbase
import FPNumDecode
, FPNumBaseRecord
9 from nmutil
.pipemodbase
import PipeModBase
, PipeModBaseChain
10 from ieee754
.fpcommon
.getop
import FPADDBaseData
11 from ieee754
.fpcommon
.denorm
import (FPSCData
, FPAddDeNormMod
)
12 from ieee754
.fpmul
.align
import FPAlignModSingle
15 class FPMulSpecialCasesMod(PipeModBase
):
16 """ special cases: NaNs, infs, zeros, denormalised
17 see "Special Operations"
18 https://steve.hollasch.net/cgindex/coding/ieeefloat.html
21 def __init__(self
, pspec
):
22 super().__init
__(pspec
, "specialcases")
25 return FPADDBaseData(self
.pspec
)
28 return FPSCData(self
.pspec
, False)
30 def elaborate(self
, platform
):
34 # decode: XXX really should move to separate stage
35 width
= self
.pspec
.width
36 a1
= FPNumBaseRecord(width
, False)
37 b1
= FPNumBaseRecord(width
, False)
38 m
.submodules
.sc_decode_a
= a1
= FPNumDecode(None, a1
)
39 m
.submodules
.sc_decode_b
= b1
= FPNumDecode(None, b1
)
40 comb
+= [a1
.v
.eq(self
.i
.a
),
46 obz
= Signal(reset_less
=True)
47 comb
+= obz
.eq(a1
.is_zero | b1
.is_zero
)
49 sabx
= Signal(reset_less
=True) # sign a xor b (sabx, get it?)
50 comb
+= sabx
.eq(a1
.s ^ b1
.s
)
52 abnan
= Signal(reset_less
=True)
53 comb
+= abnan
.eq(a1
.is_nan | b1
.is_nan
)
55 # initialise and override if needed
56 comb
+= self
.o
.out_do_z
.eq(1)
58 # if a is NaN or b is NaN return NaN
60 comb
+= self
.o
.z
.nan(0)
62 # if a is inf return inf (or NaN)
63 with m
.Elif(a1
.is_inf
):
64 comb
+= self
.o
.z
.inf(sabx
)
65 # b is zero return NaN
66 with m
.If(b1
.is_zero
):
67 comb
+= self
.o
.z
.nan(0)
69 # if b is inf return inf (or NaN)
70 with m
.Elif(b1
.is_inf
):
71 comb
+= self
.o
.z
.inf(sabx
)
72 # a is zero return NaN
73 with m
.If(a1
.is_zero
):
74 comb
+= self
.o
.z
.nan(0)
76 # if a is zero or b zero return signed-a/b
78 comb
+= self
.o
.z
.zero(sabx
)
80 # Denormalised Number checks next, so pass a/b data through
82 comb
+= self
.o
.out_do_z
.eq(0)
84 comb
+= self
.o
.oz
.eq(self
.o
.z
.v
)
85 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
90 class FPMulSpecialCasesDeNorm(PipeModBaseChain
):
91 """ special cases: NaNs, infs, zeros, denormalised
95 """ gets chain of modules
97 smod
= FPMulSpecialCasesMod(self
.pspec
)
98 dmod
= FPAddDeNormMod(self
.pspec
, False)
99 amod
= FPAlignModSingle(self
.pspec
, False)
101 return [smod
, dmod
, amod
]