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 PartitionedSignal
14 from soc
.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
))
44 # OP_MUL_nnn - select hi32/hi64/lo64 from result
45 with m
.Switch(op
.insn_type
):
46 # hi-32 replicated twice
47 with m
.Case(MicrOp
.OP_MUL_H32
):
48 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 # take the low 64 bits of the mul
55 comb
+= o
.data
.eq(mul_o
[0:64])
58 mul_ov
= Signal(reset_less
=True)
60 m32
= mul_o
[31:64] # yes really bits 31 to 63 (incl)
61 comb
+= mul_ov
.eq(m32
.bool() & ~m32
.all())
63 m64
= mul_o
[63:128] # yes really bits 63 to 127 (incl)
64 comb
+= mul_ov
.eq(m64
.bool() & ~m64
.all())
66 # 32-bit (ov[1]) and 64-bit (ov[0]) overflow - both same
67 comb
+= ov_o
.data
.eq(Repl(mul_ov
, 2)) # sets OV _and_ OV32
70 ###### sticky overflow and context, both pass-through #####
72 comb
+= self
.o
.xer_so
.data
.eq(self
.i
.xer_so
)
73 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)