comment where ALUIntermediateData to go
[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)
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 class ALUMainStage(PipeModBase):
14 def __init__(self, pspec):
15 super().__init__(pspec, "main")
16
17 def ispec(self):
18 return ALUInputData(self.pspec)
19
20 def ospec(self):
21 return ALUOutputData(self.pspec) # TODO: ALUIntermediateData
22
23 def elaborate(self, platform):
24 m = Module()
25 comb = m.d.comb
26
27 add_output = Signal(self.i.a.width + 1, reset_less=True)
28 comb += add_output.eq(self.i.a + self.i.b + self.i.carry_in)
29
30
31 with m.Switch(self.i.ctx.op.insn_type):
32 with m.Case(InternalOp.OP_ADD):
33 comb += self.o.o.eq(add_output[0:64])
34 comb += self.o.carry_out.eq(add_output[64])
35 with m.Case(InternalOp.OP_AND):
36 comb += self.o.o.eq(self.i.a & self.i.b)
37 with m.Case(InternalOp.OP_OR):
38 comb += self.o.o.eq(self.i.a | self.i.b)
39 with m.Case(InternalOp.OP_XOR):
40 comb += self.o.o.eq(self.i.a ^ self.i.b)
41
42 ###### sticky overflow and context, both pass-through #####
43
44 comb += so.eq(self.i.so)
45 comb += self.o.ctx.eq(self.i.ctx)
46
47 return m