9f3d69632cf33b5410083907bde83f498bfc3b9b
1 # This stage is intended to do most of the work of analysing the multiply result
3 from nmigen
import (Module
, Signal
, Cat
, Repl
, Mux
, signed
)
4 from nmutil
.pipemodbase
import PipeModBase
5 from soc
.fu
.div
.pipe_data
import DivMulOutputData
6 from soc
.fu
.mul
.pipe_data
import MulOutputData
7 from ieee754
.part
.partsig
import PartitionedSignal
8 from soc
.decoder
.power_enums
import InternalOp
11 class MulMainStage3(PipeModBase
):
12 def __init__(self
, pspec
):
13 super().__init
__(pspec
, "mul3")
16 return MulOutputData(self
.pspec
) # pipeline stage output format
19 return DivMulOutputData(self
.pspec
) # defines stage output format
21 def elaborate(self
, platform
):
25 # convenience variables
26 o
, cr0
= self
.o
.o
, self
.o
.cr0
27 ov_o
, o_i
, op
= self
.o
.xer_ov
, self
.i
.o
, self
.i
.ctx
.op
29 # check if op is 32-bit, and get sign bit from operand a
30 is_32bit
= Signal(reset_less
=True)
31 comb
+= is_32bit
.eq(op
.is_32bit
)
33 # check negate: select signed/unsigned
34 mul_o
= Signal(o_i
.width
, reset_less
=True)
35 comb
+= mul_o
.eq(Mux(self
.i
.neg_res
, -o_i
, o_i
))
38 # OP_MUL_nnn - select hi32/hi64/lo64 from result
39 with m
.Switch(op
.insn_type
):
40 # hi-32 replicated twice
41 with m
.Case(InternalOp
.OP_MUL_H32
):
42 comb
+= o
.data
.eq(Repl(mul_o
[32:64], 2))
44 with m
.Case(InternalOp
.OP_MUL_H64
):
45 comb
+= o
.data
.eq(mul_o
[64:128])
48 # take the low 64 bits of the mul
49 comb
+= o
.data
.eq(mul_o
[0:64])
52 mul_ov
= Signal(reset_less
=True)
55 comb
+= mul_ov
.eq(m32
.bool() & ~m32
.all())
58 comb
+= mul_ov
.eq(m64
.bool() & ~m64
.all())
60 # 32-bit (ov[1]) and 64-bit (ov[0]) overflow - both same
61 comb
+= ov_o
.data
.eq(Repl(mul_ov
, 2)) # sets OV _and_ OV32
64 ###### sticky overflow and context, both pass-through #####
66 comb
+= self
.o
.xer_so
.data
.eq(self
.i
.xer_so
)
67 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)