add first cut at fu mul pipeline
[soc.git] / src / soc / fu / mul / pre_stage.py
1 # This stage is intended to do most of the work of executing multiply
2 from nmigen import (Module, Signal, Mux)
3 from nmutil.pipemodbase import PipeModBase
4 from soc.fu.alu.pipe_data import ALUInputData
5 from soc.fu.mul.pipe_data import MulIntermediateData
6 from ieee754.part.partsig import PartitionedSignal
7
8
9 class MulMainStage1(PipeModBase):
10 def __init__(self, pspec):
11 super().__init__(pspec, "mul1")
12
13 def ispec(self):
14 return ALUInputData(self.pspec) # defines pipeline stage input format
15
16 def ospec(self):
17 return MulIntermediateData(self.pspec) # pipeline stage output format
18
19 def elaborate(self, platform):
20 m = Module()
21 comb = m.d.comb
22
23 # convenience variables
24 a, b = self.i.a, self.i.b
25 a_o, b_o, neg_res_o = self.o.a, self.o.b, self.o.neg_res
26
27 # check if op is 32-bit, and get sign bit from operand a
28 is_32bit = Signal(reset_less=True)
29 sign_a = Signal(reset_less=True)
30 sign_b = Signal(reset_less=True)
31 comb += is_32bit.eq(op.is_32bit)
32
33 # work out if a/b are negative (check 32-bit / signed)
34 comb += sign_a.eq(Mux(op.is_32bit, a[31], a[63]) & op.is_signed)
35 comb += sign_b.eq(Mux(op.is_32bit, b[31], b[63]) & op.is_signed)
36
37 # work out if result is negative sign
38 comb += neg_res_o.eq(sign_a ^ sign_b)
39
40 # negation of a 64-bit value produces the same lower 32-bit
41 # result as negation of just the lower 32-bits, so we don't
42 # need to do anything special before negating
43 comb += a_o.eq(Mux(sign_a, -a, a))
44 comb += b_o.eq(Mux(sign_b, -b, b))
45
46 ###### XER and context, both pass-through #####
47
48 comb += self.o.xer_ca.data.eq(self.i.xer_ca)
49 comb += self.o.xer_so.data.eq(self.i.xer_so)
50 comb += self.o.ctx.eq(self.i.ctx)
51
52 return m
53