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, and handling of immediates should happen
5 from nmigen
import (Module
, Signal
, Cat
, Const
, Mux
, Repl
, signed
,
7 from nmutil
.pipemodbase
import PipeModBase
8 from soc
.decoder
.power_enums
import InternalOp
9 from soc
.alu
.pipe_data
import ALUInputData
10 from soc
.decoder
.power_enums
import CryIn
13 class ALUInputStage(PipeModBase
):
14 def __init__(self
, pspec
):
15 super().__init
__(pspec
, "input")
18 return ALUInputData(self
.pspec
)
21 return ALUInputData(self
.pspec
)
23 def elaborate(self
, platform
):
29 # operand a to be as-is or inverted
30 a
= Signal
.like(self
.i
.a
)
32 with m
.If(self
.i
.ctx
.op
.insn_type
!= InternalOp
.OP_CMP
):
33 with m
.If(self
.i
.ctx
.op
.invert_a
):
34 comb
+= a
.eq(~self
.i
.a
)
36 comb
+= a
.eq(self
.i
.a
)
38 comb
+= self
.o
.a
.eq(a
)
39 comb
+= self
.o
.b
.eq(self
.i
.b
)
41 with m
.If(self
.i
.ctx
.op
.invert_a
):
42 comb
+= self
.o
.a
.eq(~self
.i
.b
)
44 comb
+= self
.o
.a
.eq(self
.i
.b
)
46 comb
+= self
.o
.b
.eq(self
.i
.a
)
51 # either copy incoming carry or set to 1/0 as defined by op
52 with m
.Switch(self
.i
.ctx
.op
.input_carry
):
53 with m
.Case(CryIn
.ZERO
):
54 comb
+= self
.o
.carry_in
.eq(0)
55 with m
.Case(CryIn
.ONE
):
56 comb
+= self
.o
.carry_in
.eq(1)
57 with m
.Case(CryIn
.CA
):
58 comb
+= self
.o
.carry_in
.eq(self
.i
.carry_in
)
60 ##### sticky overflow and context (both pass-through) #####
62 comb
+= self
.o
.so
.eq(self
.i
.so
)
63 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)