start on converting MUL and DIV pipelines to XLEN
[soc.git] / src / soc / fu / mul / pre_stage.py
1 # This stage is intended to prepare the multiplication operands
2
3 from nmigen import (Module, Signal, Mux)
4 from nmutil.pipemodbase import PipeModBase
5 from soc.fu.div.pipe_data import DivInputData
6 from soc.fu.mul.pipe_data import MulIntermediateData
7 from ieee754.part.partsig import SimdSignal
8 from nmutil.util import eq32
9
10 class MulMainStage1(PipeModBase):
11 def __init__(self, pspec):
12 super().__init__(pspec, "mul1")
13
14 def ispec(self):
15 return DivInputData(self.pspec) # defines pipeline stage input format
16
17 def ospec(self):
18 return MulIntermediateData(self.pspec) # pipeline stage output format
19
20 def elaborate(self, platform):
21 XLEN = self.pspec.XLEN
22 m = Module()
23 comb = m.d.comb
24
25 # convenience variables
26 a, b, op = self.i.a, self.i.b, self.i.ctx.op
27 a_o, b_o, neg_res_o = self.o.a, self.o.b, self.o.neg_res
28 neg_res_o, neg_res32_o = self.o.neg_res, self.o.neg_res32
29
30 # check if op is 32-bit, and get sign bit from operand a
31 is_32bit = Signal(reset_less=True)
32 sign_a = Signal(reset_less=True)
33 sign_b = Signal(reset_less=True)
34 sign32_a = Signal(reset_less=True)
35 sign32_b = Signal(reset_less=True)
36 comb += is_32bit.eq(op.is_32bit)
37
38 # work out if a/b are negative (check 32-bit / signed)
39 comb += sign_a.eq(Mux(op.is_32bit, a[31], a[XLEN-1]) & op.is_signed)
40 comb += sign_b.eq(Mux(op.is_32bit, b[31], b[XLEN-1]) & op.is_signed)
41 comb += sign32_a.eq(a[31] & op.is_signed)
42 comb += sign32_b.eq(b[31] & op.is_signed)
43
44 # work out if result is negative sign
45 comb += neg_res_o.eq(sign_a ^ sign_b)
46 comb += neg_res32_o.eq(sign32_a ^ sign32_b) # pass through for OV32
47
48 # negation of a 64-bit value produces the same lower 32-bit
49 # result as negation of just the lower 32-bits, so we don't
50 # need to do anything special before negating
51 abs_a = Signal(XLEN, reset_less=True)
52 abs_b = Signal(XLEN, reset_less=True)
53 comb += abs_a.eq(Mux(sign_a, -a, a))
54 comb += abs_b.eq(Mux(sign_b, -b, b))
55
56 # set up 32/64 bit inputs
57 comb += eq32(is_32bit, a_o, abs_a)
58 comb += eq32(is_32bit, b_o, abs_b)
59
60 ###### XER and context, both pass-through #####
61
62 comb += self.o.xer_so.eq(self.i.xer_so)
63 comb += self.o.ctx.eq(self.i.ctx)
64
65 return m
66