Merge branch 'master' of git.libre-soc.org:soc
[soc.git] / src / soc / fu / common_input_stage.py
1 # This stage is intended to adjust the input data before sending it to
2 # the acutal ALU. Things like handling inverting the input, carry_in
3 # generation for subtraction, should happen here
4 from nmigen import (Module, Signal)
5 from nmutil.pipemodbase import PipeModBase
6 from soc.decoder.power_enums import MicrOp
7 from soc.decoder.power_enums import CryIn
8
9
10 class CommonInputStage(PipeModBase):
11
12 def elaborate(self, platform):
13 m = Module()
14 comb = m.d.comb
15 op = self.i.ctx.op
16
17 ##### operand A #####
18
19 # operand a to be as-is or inverted
20 a = Signal.like(self.i.a)
21
22 op_to_invert = 'ra'
23 if hasattr(self, "invert_op"):
24 op_to_invert = self.invert_op
25
26 if hasattr(op, "invert_in") and op_to_invert == 'ra':
27 with m.If(op.invert_in):
28 comb += a.eq(~self.i.a)
29 with m.Else():
30 comb += a.eq(self.i.a)
31 else:
32 comb += a.eq(self.i.a)
33
34 comb += self.o.a.eq(a)
35
36 ##### operand B #####
37
38 # operand b to be as-is or inverted
39 b = Signal.like(self.i.b)
40
41 if hasattr(op, "invert_in") and op_to_invert == 'rb':
42 with m.If(op.invert_in):
43 comb += b.eq(~self.i.b)
44 with m.Else():
45 comb += b.eq(self.i.b)
46 else:
47 comb += b.eq(self.i.b)
48
49 comb += self.o.b.eq(b)
50
51 ##### carry-in #####
52
53 # either copy incoming carry or set to 1/0 as defined by op
54 if hasattr(self.i, "xer_ca"): # hack (for now - for LogicalInputData)
55 with m.Switch(op.input_carry):
56 with m.Case(CryIn.ZERO):
57 comb += self.o.xer_ca.eq(0b00)
58 with m.Case(CryIn.ONE):
59 comb += self.o.xer_ca.eq(0b11) # XER CA/CA32
60 with m.Case(CryIn.CA):
61 comb += self.o.xer_ca.eq(self.i.xer_ca)
62 # XXX TODO
63 #with m.Case(CryIn.OV):
64 # comb += self.o.xer_ca.eq(self.i.xer_ov)
65
66 ##### sticky overflow and context (both pass-through) #####
67
68 if hasattr(self.o, "xer_so"): # hack (for now - for LogicalInputData)
69 with m.If(op.oe.oe_ok):
70 comb += self.o.xer_so.eq(self.i.xer_so)
71 comb += self.o.ctx.eq(self.i.ctx)
72
73 return m