1 # This stage is intended to do most of the work of analysing the multiply result
4 * https://libre-soc.org/openpower/isa/fixedarith/
5 * https://bugs.libre-soc.org/show_bug.cgi?id=432
6 * https://bugs.libre-soc.org/show_bug.cgi?id=323
9 from nmigen
import (Module
, Signal
, Cat
, Repl
, Mux
, signed
)
10 from nmutil
.pipemodbase
import PipeModBase
11 from soc
.fu
.div
.pipe_data
import DivMulOutputData
12 from soc
.fu
.mul
.pipe_data
import MulOutputData
13 from ieee754
.part
.partsig
import SimdSignal
14 from openpower
.decoder
.power_enums
import MicrOp
17 class MulMainStage3(PipeModBase
):
18 def __init__(self
, pspec
):
19 super().__init
__(pspec
, "mul3")
22 return MulOutputData(self
.pspec
) # pipeline stage output format
25 return DivMulOutputData(self
.pspec
) # defines stage output format
27 def elaborate(self
, platform
):
31 # convenience variables
32 o
, cr0
= self
.o
.o
, self
.o
.cr0
33 ov_o
, o_i
, op
= self
.o
.xer_ov
, self
.i
.o
, self
.i
.ctx
.op
35 # check if op is 32-bit, and get sign bit from operand a
36 is_32bit
= Signal(reset_less
=True)
37 comb
+= is_32bit
.eq(op
.is_32bit
)
39 # check negate: select signed/unsigned
40 mul_o
= Signal(o_i
.width
, reset_less
=True)
41 comb
+= mul_o
.eq(Mux(self
.i
.neg_res
, -o_i
, o_i
))
43 # OP_MUL_nnn - select hi32/hi64/lo64 from result
44 with m
.Switch(op
.insn_type
):
45 # hi-32 replicated twice
46 with m
.Case(MicrOp
.OP_MUL_H32
):
47 comb
+= o
.data
.eq(Repl(mul_o
[32:64], 2))
50 with m
.Case(MicrOp
.OP_MUL_H64
):
51 comb
+= o
.data
.eq(mul_o
[64:128])
54 with m
.Case(MicrOp
.OP_MUL_L64
):
55 # take the low 64 bits of the mul
56 comb
+= o
.data
.eq(mul_o
[0:64])
59 # compute overflow 32/64
60 mul_ov
= Signal(reset_less
=True)
62 # here we're checking that the top 32 bits is the
63 # sign-extended version of the bottom 32 bits.
64 m31
= mul_o
[31:64] # yes really bits 31 to 63 (incl)
65 comb
+= mul_ov
.eq(m31
.bool() & ~m31
.all())
67 # here we're checking that the top 64 bits is the
68 # sign-extended version of the bottom 64 bits.
69 m63
= mul_o
[63:128] # yes really bits 63 to 127 (incl)
70 comb
+= mul_ov
.eq(m63
.bool() & ~m63
.all())
72 # 32-bit (ov[1]) and 64-bit (ov[0]) overflow - both same
73 comb
+= ov_o
.data
.eq(Repl(mul_ov
, 2)) # sets OV _and_ OV32
76 ###### sticky overflow and context, both pass-through #####
78 comb
+= self
.o
.xer_so
.eq(self
.i
.xer_so
)
79 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)