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
.alu
.pipe_data
import ALUOutputData
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 ALUOutputData(self
.pspec
) # defines pipeline stage output format
21 def elaborate(self
, platform
):
25 # convenience variables
26 cry_o
, o
, cr0
= self
.o
.xer_ca
, self
.o
.o
, self
.o
.cr0
28 o_i
, cry_i
, op
= self
.i
.o
, self
.i
.xer_ca
, self
.i
.ctx
.op
30 # check if op is 32-bit, and get sign bit from operand a
31 is_32bit
= Signal(reset_less
=True)
32 comb
+= is_32bit
.eq(op
.is_32bit
)
34 # check negate: select signed/unsigned
35 mul_o
= Signal(o_i
.width
, reset_less
=True)
36 comb
+= mul_o
.eq(Mux(self
.i
.neg_res
, -o_i
, o_i
))
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 comb
+= o
.data
.eq(mul_o
[0:64])
51 mul_ov
= Signal(reset_less
=True)
54 comb
+= mul_ov
.eq(m32
.bool() & ~m32
.all())
57 comb
+= mul_ov
.eq(m64
.bool() & ~m64
.all())
59 # 32-bit (ov[1]) and 64-bit (ov[0]) overflow
60 ov
= Signal(2, reset_less
=True)
61 comb
+= ov
[0].eq(mul_ov
)
62 comb
+= ov
[1].eq(mul_ov
)
63 comb
+= ov_o
.data
.eq(ov
)
66 # https://bugs.libre-soc.org/show_bug.cgi?id=319#c5
67 ca
= Signal(2, reset_less
=True)
68 comb
+= ca
[0].eq(mul_o
[-1]) # XER.CA - XXX more?
69 comb
+= ca
[1].eq(mul_o
[32] ^
(self
.i
.neg_res32
)) # XER.CA32
70 comb
+= cry_o
.data
.eq(ca
)
71 comb
+= cry_o
.ok
.eq(1)
73 ###### sticky overflow and context, both pass-through #####
75 comb
+= self
.o
.xer_so
.data
.eq(self
.i
.xer_so
)
76 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)