continue ALUHelpers check alu outputs code-morph
[soc.git] / src / soc / fu / common_output_stage.py
index 1faa1ee6015babb747829584fc00e7cbb63790e7..0232aa66ead191ea89788ea28579aef9fe564ac6 100644 (file)
@@ -1,6 +1,6 @@
 # This stage is intended to handle the gating of carry out,
 # and updating the condition register
-from nmigen import (Module, Signal, Cat, Repl)
+from nmigen import (Module, Signal, Cat)
 from nmutil.pipemodbase import PipeModBase
 from ieee754.part.partsig import PartitionedSignal
 from soc.decoder.power_enums import InternalOp
@@ -15,12 +15,15 @@ class CommonOutputStage(PipeModBase):
         comb = m.d.comb
         op = self.i.ctx.op
 
-        # op requests inversion of the output
+        # op requests inversion of the output...
         o = Signal.like(self.i.o)
-        with m.If(op.invert_out):
-            comb += o.eq(~self.i.o.data)
-        with m.Else():
-            comb += o.eq(self.i.o.data)
+        if hasattr(op, "invert_out"): # ... optionally
+            with m.If(op.invert_out):
+                comb += o.eq(~self.i.o.data)
+            with m.Else():
+                comb += o.eq(self.i.o.data)
+        else:
+            comb += o.eq(self.i.o.data) # ... no inversion
 
         # target register if 32-bit is only the 32 LSBs
         target = Signal(64, reset_less=True)
@@ -34,12 +37,12 @@ class CommonOutputStage(PipeModBase):
         comb += self.o.xer_ca.ok.eq(op.output_carry)
 
         # create condition register cr0 and sticky-overflow
-        is_zero = Signal(reset_less=True)
+        is_nzero = Signal(reset_less=True)
         is_positive = Signal(reset_less=True)
         is_negative = Signal(reset_less=True)
         msb_test = Signal(reset_less=True) # set equal to MSB, invert if OP=CMP
-        is_cmp = Signal(reset_less=True)   # true if OP=CMP
-        is_cmpeqb = Signal(reset_less=True)   # true if OP=CMP
+        is_cmp = Signal(reset_less=True)     # true if OP=CMP
+        is_cmpeqb = Signal(reset_less=True)  # true if OP=CMPEQB
         self.so = Signal(1, reset_less=True)
         cr0 = Signal(4, reset_less=True)
 
@@ -50,21 +53,22 @@ class CommonOutputStage(PipeModBase):
         comb += is_cmp.eq(op.insn_type == InternalOp.OP_CMP)
         comb += is_cmpeqb.eq(op.insn_type == InternalOp.OP_CMPEQB)
         comb += msb_test.eq(target[-1] ^ is_cmp)
-        comb += is_zero.eq(target == 0)
-        comb += is_positive.eq(~is_zero & ~msb_test)
-        comb += is_negative.eq(~is_zero & msb_test)
+        comb += is_nzero.eq(target.bool())
+        comb += is_positive.eq(is_nzero & ~msb_test)
+        comb += is_negative.eq(is_nzero & msb_test)
 
         with m.If(is_cmpeqb):
-            comb += cr0.eq(self.i.cr0)
+            comb += cr0.eq(self.i.cr0.data)
         with m.Else():
-            comb += cr0.eq(Cat(self.so, is_zero, is_positive, is_negative))
+            comb += cr0.eq(Cat(self.so, ~is_nzero, is_positive, is_negative))
 
-        # copy out [inverted] cr0, output, and context out
+        # copy out [inverted?] output, cr0, and context out
         comb += self.o.o.data.eq(o)
         comb += self.o.o.ok.eq(self.i.o.ok)
+        # CR0 to be set
         comb += self.o.cr0.data.eq(cr0)
         comb += self.o.cr0.ok.eq(op.write_cr.ok)
-        # CR0 to be set
+        # context
         comb += self.o.ctx.eq(self.i.ctx)
 
         return m