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
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
14 class ALUMainStage(PipeModBase
):
15 def __init__(self
, pspec
):
16 super().__init
__(pspec
, "main")
19 return ALUInputData(self
.pspec
)
22 return ALUOutputData(self
.pspec
) # TODO: ALUIntermediateData
24 def elaborate(self
, platform
):
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]))
35 ##########################
36 # main switch-statement for handling arithmetic and logic operations
38 with m
.Switch(self
.i
.ctx
.op
.insn_type
):
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])
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)))
65 ###### sticky overflow and context, both pass-through #####
67 comb
+= self
.o
.so
.eq(self
.i
.so
)
68 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)