remove Logical operations from ALU pipeline
[soc.git] / src / soc / alu / main_stage.py
1 # This stage is intended to do most of the work of executing the ALU
2 # instructions. This would be like the additions, logical operations,
3 # and shifting, as well as carry and overflow generation. This module
4 # however should not gate the carry or overflow, that's up to the
5 # output stage
6 from nmigen import (Module, Signal, Cat, Repl, Mux, Const)
7 from nmutil.pipemodbase import PipeModBase
8 from soc.alu.pipe_data import ALUInputData, ALUOutputData
9 from ieee754.part.partsig import PartitionedSignal
10 from soc.decoder.power_enums import InternalOp
11
12
13
14 class ALUMainStage(PipeModBase):
15 def __init__(self, pspec):
16 super().__init__(pspec, "main")
17
18 def ispec(self):
19 return ALUInputData(self.pspec)
20
21 def ospec(self):
22 return ALUOutputData(self.pspec) # TODO: ALUIntermediateData
23
24 def elaborate(self, platform):
25 m = Module()
26 comb = m.d.comb
27
28
29 # check if op is 32-bit, and get sign bit from operand a
30 is_32bit = Signal(reset_less=True)
31 sign_bit = Signal(reset_less=True)
32 comb += is_32bit.eq(self.i.ctx.op.is_32bit)
33 comb += sign_bit.eq(Mux(is_32bit, self.i.a[31], self.i.a[63]))
34
35 ##########################
36 # main switch-statement for handling arithmetic and logic operations
37
38 with m.Switch(self.i.ctx.op.insn_type):
39 #### add ####
40 with m.Case(InternalOp.OP_ADD):
41 # little trick: do the add using only one add (not 2)
42 add_a = Signal(self.i.a.width + 2, reset_less=True)
43 add_b = Signal(self.i.a.width + 2, reset_less=True)
44 add_output = Signal(self.i.a.width + 2, reset_less=True)
45 # in bit 0, 1+carry_in creates carry into bit 1 and above
46 comb += add_a.eq(Cat(self.i.carry_in, self.i.a, Const(0, 1)))
47 comb += add_b.eq(Cat(Const(1, 1), self.i.b, Const(0, 1)))
48 comb += add_output.eq(add_a + add_b)
49 # bit 0 is not part of the result, top bit is the carry-out
50 comb += self.o.o.eq(add_output[1:-1])
51 comb += self.o.carry_out.eq(add_output[-1])
52
53 #### exts (sign-extend) ####
54 with m.Case(InternalOp.OP_EXTS):
55 with m.If(self.i.ctx.op.data_len == 1):
56 comb += self.o.o.eq(Cat(self.i.a[0:8],
57 Repl(self.i.a[7], 64-8)))
58 with m.If(self.i.ctx.op.data_len == 2):
59 comb += self.o.o.eq(Cat(self.i.a[0:16],
60 Repl(self.i.a[15], 64-16)))
61 with m.If(self.i.ctx.op.data_len == 4):
62 comb += self.o.o.eq(Cat(self.i.a[0:32],
63 Repl(self.i.a[31], 64-32)))
64
65 ###### sticky overflow and context, both pass-through #####
66
67 comb += self.o.so.eq(self.i.so)
68 comb += self.o.ctx.eq(self.i.ctx)
69
70 return m