Allow the formal engine to perform a same-cycle result in the ALU
[soc.git] / src / soc / fu / mul / post_stage.py
1 # This stage is intended to do most of the work of analysing the multiply result
2 """
3 bugreports/links:
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
7 """
8
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
15
16
17 class MulMainStage3(PipeModBase):
18 def __init__(self, pspec):
19 super().__init__(pspec, "mul3")
20
21 def ispec(self):
22 return MulOutputData(self.pspec) # pipeline stage output format
23
24 def ospec(self):
25 return DivMulOutputData(self.pspec) # defines stage output format
26
27 def elaborate(self, platform):
28 m = Module()
29 comb = m.d.comb
30
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
34
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)
38
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))
42
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))
48 comb += o.ok.eq(1)
49 # hi-64
50 with m.Case(MicrOp.OP_MUL_H64):
51 comb += o.data.eq(mul_o[64:128])
52 comb += o.ok.eq(1)
53 # lo-64 - overflow
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])
57 comb += o.ok.eq(1)
58
59 # compute overflow 32/64
60 mul_ov = Signal(reset_less=True)
61 with m.If(is_32bit):
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())
66 with m.Else():
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())
71
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
74 comb += ov_o.ok.eq(1)
75
76 ###### sticky overflow and context, both pass-through #####
77
78 comb += self.o.xer_so.eq(self.i.xer_so)
79 comb += self.o.ctx.eq(self.i.ctx)
80
81 return m
82