1 # IEEE Floating Point Conversion, FSGNJ
2 # Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 # Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
6 from nmigen
import Module
, Signal
, Mux
8 from nmutil
.pipemodbase
import PipeModBase
9 from ieee754
.fpcommon
.basedata
import FPBaseData
10 from ieee754
.fpcommon
.packdata
import FPPackData
11 from ieee754
.fpcommon
.fpbase
import FPNumDecode
, FPNumBaseRecord
14 class FPMAXPipeMod(PipeModBase
):
15 """ FP Sign injection - replaces operand A's sign bit with one
16 generated from operand B
18 self.ctx.i.op & 0x3 == 0x0 : Copy sign bit from operand B
19 self.ctx.i.op & 0x3 == 0x1 : Copy inverted sign bit from operand B
20 self.ctx.i.op & 0x3 == 0x2 : Sign bit is A's sign XOR B's sign
22 def __init__(self
, in_pspec
):
23 self
.in_pspec
= in_pspec
24 super().__init
__(in_pspec
, "fpmax")
27 return FPBaseData(self
.in_pspec
)
30 return FPPackData(self
.in_pspec
)
32 def elaborate(self
, platform
):
35 # useful clarity variables
37 width
= self
.pspec
.width
38 opcode
= self
.i
.ctx
.op
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
)
46 m
.d
.comb
+= [a1
.v
.eq(self
.i
.a
),
49 no_nans
= Signal(width
)
50 some_nans
= Signal(width
)
54 comb
+= has_nan
.eq(a1
.is_nan | b1
.is_nan
)
56 comb
+= both_nan
.eq(a1
.is_nan
& b1
.is_nan
)
59 # some_nans = NaN - created from scratch
61 # some_nans = Mux(a1.is_nan, b, a)
62 comb
+= some_nans
.eq(Mux(both_nan
,
64 Mux(a1
.is_nan
, self
.i
.b
, self
.i
.a
)))
66 # if sign(a) != sign(b):
67 # no_nans = Mux(a1.s ^ opcode[0], b, a)
68 signs_different
= Signal()
69 comb
+= signs_different
.eq(a1
.s
!= b1
.s
)
71 signs_different_value
= Signal(width
)
72 comb
+= signs_different_value
.eq(Mux(a1
.s ^ opcode
[0],
78 # no_nans = Mux(opcode[0], b, a)
80 # no_nans = Mux(opcode[0], a, b)
83 signs_same
= Signal(width
)
85 comb
+= gt
.eq(a1
.v
> b1
.v
)
86 comb
+= signs_same
.eq(Mux(gt ^ sign ^ opcode
[0],
88 comb
+= no_nans
.eq(Mux(signs_different
, signs_different_value
,
91 comb
+= z1
.eq(Mux(has_nan
, some_nans
, no_nans
))
93 # copy the context (muxid, operator)
94 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)