58d9708da2ac37cc1b74ccc5faae2342ade872b3
[soc.git] / src / soc / fu / 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, Repl)
5 from soc.fu.alu.pipe_data import ALUInputData, ALUOutputData
6 from soc.fu.common_output_stage import CommonOutputStage
7 from ieee754.part.partsig import PartitionedSignal
8 from soc.decoder.power_enums import InternalOp
9
10
11 class ALUOutputStage(CommonOutputStage):
12
13 def ispec(self):
14 return ALUOutputData(self.pspec)
15
16 def ospec(self):
17 return ALUOutputData(self.pspec)
18
19 def elaborate(self, platform):
20 m = super().elaborate(platform)
21 comb = m.d.comb
22 op = self.i.ctx.op
23 xer_so_i, xer_ov_i = self.i.xer_so.data, self.i.xer_ov.data
24
25 # copy overflow and sticky-overflow. indicate to CompALU if they
26 # are actually required (oe enabled/set) otherwise the CompALU
27 # can (will) ignore them.
28 oe = Signal(reset_less=True)
29 comb += oe.eq(op.oe.oe & op.oe.oe_ok)
30 with m.If(oe):
31 # XXX see https://bugs.libre-soc.org/show_bug.cgi?id=319#c5
32 comb += self.so.eq(xer_so_i[0] | xer_ov_i[0]) # SO
33 comb += self.o.xer_so.data.eq(self.so)
34 comb += self.o.xer_so.ok.eq(1)
35 comb += self.o.xer_ov.data.eq(xer_ov_i)
36 comb += self.o.xer_ov.ok.eq(1) # OV/32 is to be set
37
38 return m