1a8a82b620149ce83aceabe8a0cf6262e7ab58b0
[soc.git] / src / soc / alu / output_stage.py
1 # This stage is intended to handle the gating of carry and overflow
2 # out, summary overflow generation, and updating the condition
3 # register
4 from nmigen import (Module, Signal, Cat)
5 from nmutil.pipemodbase import PipeModBase
6 from soc.alu.pipe_data import ALUInputData, ALUOutputData
7 from ieee754.part.partsig import PartitionedSignal
8 from soc.decoder.power_enums import InternalOp
9
10
11 class ALUOutputStage(PipeModBase):
12 def __init__(self, pspec):
13 super().__init__(pspec, "output")
14
15 def ispec(self):
16 return ALUOutputData(self.pspec)
17
18 def ospec(self):
19 return ALUOutputData(self.pspec)
20
21 def elaborate(self, platform):
22 m = Module()
23 comb = m.d.comb
24
25 o = Signal.like(self.i.o)
26 with m.If(self.i.ctx.op.invert_out):
27 comb += o.eq(~self.i.o)
28 with m.Else():
29 comb += o.eq(self.i.o)
30
31 is_zero = Signal(reset_less=True)
32 is_positive = Signal(reset_less=True)
33 is_negative = Signal(reset_less=True)
34 so = Signal(reset_less=True)
35
36 comb += is_zero.eq(o == 0)
37 comb += is_positive.eq(~is_zero & ~o[63])
38 comb += is_negative.eq(~is_zero & o[63])
39 comb += so.eq(self.i.so | self.i.ov)
40
41 comb += self.o.o.eq(o)
42 comb += self.o.cr0.eq(Cat(is_negative, is_positive, is_zero, so))
43 comb += self.o.so.eq(so)
44
45 comb += self.o.ctx.eq(self.i.ctx)
46
47 return m