1 """IEEE754 Floating Point Multiplier
3 Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
4 Copyright (C) 2019 Jake Lifshay
8 from nmigen
import Module
, Signal
, Cat
, Const
9 from nmigen
.cli
import main
, verilog
12 from ieee754
.fpcommon
.fpbase
import FPNumDecode
, FPNumBaseRecord
14 from nmutil
.pipemodbase
import PipeModBase
, PipeModBaseChain
15 from ieee754
.fpcommon
.basedata
import FPBaseData
16 from ieee754
.fpcommon
.denorm
import (FPSCData
, FPAddDeNormMod
)
17 from ieee754
.fpmul
.align
import FPAlignModSingle
20 class FPMulSpecialCasesMod(PipeModBase
):
21 """ special cases: NaNs, infs, zeros, denormalised
22 see "Special Operations"
23 https://steve.hollasch.net/cgindex/coding/ieeefloat.html
26 def __init__(self
, pspec
):
27 super().__init
__(pspec
, "specialcases")
30 return FPBaseData(self
.pspec
)
33 return FPSCData(self
.pspec
, False)
35 def elaborate(self
, platform
):
39 # decode: XXX really should move to separate stage
40 width
= self
.pspec
.width
41 a1
= FPNumBaseRecord(width
, False)
42 b1
= FPNumBaseRecord(width
, False)
43 m
.submodules
.sc_decode_a
= a1
= FPNumDecode(None, a1
)
44 m
.submodules
.sc_decode_b
= b1
= FPNumDecode(None, b1
)
45 comb
+= [a1
.v
.eq(self
.i
.a
),
51 obz
= Signal(reset_less
=True)
52 comb
+= obz
.eq(a1
.is_zero | b1
.is_zero
)
54 sabx
= Signal(reset_less
=True) # sign a xor b (sabx, get it?)
55 comb
+= sabx
.eq(a1
.s ^ b1
.s
)
57 abnan
= Signal(reset_less
=True)
58 comb
+= abnan
.eq(a1
.is_nan | b1
.is_nan
)
60 # initialise and override if needed
61 comb
+= self
.o
.out_do_z
.eq(1)
63 # if a is NaN or b is NaN return NaN
65 comb
+= self
.o
.z
.nan(0)
67 # if a is inf return inf (or NaN)
68 with m
.Elif(a1
.is_inf
):
69 comb
+= self
.o
.z
.inf(sabx
)
70 # b is zero return NaN
71 with m
.If(b1
.is_zero
):
72 comb
+= self
.o
.z
.nan(0)
74 # if b is inf return inf (or NaN)
75 with m
.Elif(b1
.is_inf
):
76 comb
+= self
.o
.z
.inf(sabx
)
77 # a is zero return NaN
78 with m
.If(a1
.is_zero
):
79 comb
+= self
.o
.z
.nan(0)
81 # if a is zero or b zero return signed-a/b
83 comb
+= self
.o
.z
.zero(sabx
)
85 # Denormalised Number checks next, so pass a/b data through
87 comb
+= self
.o
.out_do_z
.eq(0)
89 comb
+= self
.o
.oz
.eq(self
.o
.z
.v
)
90 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
95 class FPMulSpecialCasesDeNorm(PipeModBaseChain
):
96 """ special cases: NaNs, infs, zeros, denormalised
100 """ gets chain of modules
102 smod
= FPMulSpecialCasesMod(self
.pspec
)
103 dmod
= FPAddDeNormMod(self
.pspec
, False)
104 amod
= FPAlignModSingle(self
.pspec
, False)
106 return [smod
, dmod
, amod
]