e6ab48ea32dba22bf55831b33b42891118b524e1
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
.invert_a
):
33 comb
+= a
.eq(~self
.i
.a
)
35 comb
+= a
.eq(self
.i
.a
)
37 comb
+= self
.o
.a
.eq(a
)
41 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
42 # remove this, just do self.o.b.eq(self.i.b) and move the
43 # immediate-detection into set_alu_inputs in the unit test
44 # If there's an immediate, set the B operand to that
45 comb
+= self
.o
.b
.eq(self
.i
.b
)
49 # either copy incoming carry or set to 1/0 as defined by op
50 with m
.Switch(self
.i
.ctx
.op
.input_carry
):
51 with m
.Case(CryIn
.ZERO
):
52 comb
+= self
.o
.carry_in
.eq(0)
53 with m
.Case(CryIn
.ONE
):
54 comb
+= self
.o
.carry_in
.eq(1)
55 with m
.Case(CryIn
.CA
):
56 comb
+= self
.o
.carry_in
.eq(self
.i
.carry_in
)
58 ##### sticky overflow and context (both pass-through) #####
60 comb
+= self
.o
.so
.eq(self
.i
.so
)
61 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)