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
, Cat
, Mux
8 from nmutil
.pipemodbase
import PipeModBase
9 from ieee754
.fpcommon
.basedata
import FPBaseData
10 from ieee754
.fpcommon
.packdata
import FPPackData
13 class FSGNJPipeMod(PipeModBase
):
14 """ FP Sign injection - replaces operand A's sign bit with one
15 generated from operand B
17 self.ctx.i.op & 0x3 == 0x0 : Copy sign bit from operand B
18 self.ctx.i.op & 0x3 == 0x1 : Copy inverted sign bit from operand B
19 self.ctx.i.op & 0x3 == 0x2 : Sign bit is A's sign XOR B's sign
21 def __init__(self
, in_pspec
):
22 self
.in_pspec
= in_pspec
23 super().__init
__(in_pspec
, "fsgnj")
26 return FPBaseData(self
.in_pspec
)
29 return FPPackData(self
.in_pspec
)
31 def elaborate(self
, platform
):
34 # useful clarity variables
36 width
= self
.pspec
.width
37 opcode
= self
.i
.ctx
.op
42 # Calculate the sign bit, with a chain of muxes. has to be done
43 # this way due to (planned) use of PartitionedSignal. decreases
44 # readability slightly, but hey.
46 # Handle opcodes 0b00 and 0b01, copying or inverting the sign bit of B
47 sign
= opcode
[0] ^ b
[-1] # op[0]=0, sign unmodified, op[0]=1 inverts.
49 # Handle opcodes 0b10 and 0b11, XORing sign bits of a and b together.
50 # opcode 0b11 is not defined in the RISCV spec; it is handled
51 # here as equivalent to opcode 0b10 (i.e. a1.s XOR b1.s)
52 # because this requires slightly less logic than making it the
53 # same as opcode 0b00 (1 less Mux).
54 sign
= Mux(opcode
[1], a
[-1] ^ b
[-1], sign
)
56 # Create the floating point number from the sign bit
57 # calculated earlier and the exponent and mantissa of operand a
58 comb
+= z1
.eq(Cat(a
[:width
-1], sign
))
60 # copy the context (muxid, operator)
61 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)