fix ALU with XLEN=32, carry and overflow
[soc.git] / src / soc / fu / alu / main_stage.py
index f2e751d6965e58a0872a5956a61a1f43de06e5fa..1f17943c4b6116270b052a1486e1d6358627c749 100644 (file)
@@ -4,16 +4,20 @@
 # however should not gate the carry or overflow, that's up to the
 # output stage
 
+# License: LGPLv3+
+# Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
 # Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+# (michael: note that there are multiple copyright holders)
+
 from nmigen import (Module, Signal, Cat, Repl, Mux, Const)
 from nmutil.pipemodbase import PipeModBase
 from nmutil.extend import exts, extz
 from soc.fu.alu.pipe_data import ALUInputData, ALUOutputData
-from ieee754.part.partsig import PartitionedSignal
-from soc.decoder.power_enums import MicrOp
+from ieee754.part.partsig import SimdSignal
+from openpower.decoder.power_enums import MicrOp
 
-from soc.decoder.power_fields import DecodeFields
-from soc.decoder.power_fieldsn import SignalBitRange
+from openpower.decoder.power_fields import DecodeFields
+from openpower.decoder.power_fieldsn import SignalBitRange
 
 
 # microwatt calc_ov function.
@@ -34,6 +38,7 @@ class ALUMainStage(PipeModBase):
         return ALUOutputData(self.pspec) # defines pipeline stage output format
 
     def elaborate(self, platform):
+        XLEN = self.pspec.XLEN
         m = Module()
         comb = m.d.comb
 
@@ -60,13 +65,16 @@ class ALUMainStage(PipeModBase):
 
         a_i = Signal.like(a)
         b_i = Signal.like(b)
-        with m.If(is_32bit):
+        with m.If(op.insn_type == MicrOp.OP_CMP): # another temporary hack
+            comb += a_i.eq(a)                     # reaaaally need to move CMP
+            comb += b_i.eq(b)                     # into trap pipeline
+        with m.Elif(is_32bit):
             with m.If(op.is_signed):
-                comb += a_i.eq(exts(a, 32, 64))
-                comb += b_i.eq(exts(b, 32, 64))
+                comb += a_i.eq(exts(a, 32, XLEN))
+                comb += b_i.eq(exts(b, 32, XLEN))
             with m.Else():
-                comb += a_i.eq(extz(a, 32, 64))
-                comb += b_i.eq(extz(b, 32, 64))
+                comb += a_i.eq(extz(a, 32, XLEN))
+                comb += b_i.eq(extz(b, 32, XLEN))
         with m.Else():
             comb += a_i.eq(a)
             comb += b_i.eq(b)
@@ -87,7 +95,7 @@ class ALUMainStage(PipeModBase):
             #### CMP, CMPL v3.0B p85-86
 
             with m.Case(MicrOp.OP_CMP):
-                a_n = Signal(64) # temporary - inverted a
+                a_n = Signal(XLEN) # temporary - inverted a
                 tval = Signal(5)
                 a_lt = Signal()
                 carry_32 = Signal()
@@ -100,18 +108,21 @@ class ALUMainStage(PipeModBase):
 
                 # this is supposed to be inverted (b-a, not a-b)
                 comb += a_n.eq(~a) # sigh a gets inverted
-                comb += carry_32.eq(add_o[33] ^ a_n[32] ^ b[32])
-                comb += carry_64.eq(add_o[65])
+                if XLEN == 64:
+                    comb += carry_32.eq(add_o[33] ^ a[32] ^ b[32])
+                else:
+                    comb += carry_32.eq(add_o[XLEN+1])
+                comb += carry_64.eq(add_o[XLEN+1])
 
                 comb += zerolo.eq(~((a_n[0:32] ^ b[0:32]).bool()))
-                comb += zerohi.eq(~((a_n[32:64] ^ b[32:64]).bool()))
+                comb += zerohi.eq(~((a_n[32:XLEN] ^ b[32:XLEN]).bool()))
 
                 with m.If(zerolo & (is_32bit | zerohi)):
                     # values are equal
                     comb += tval[2].eq(1)
                 with m.Else():
-                    comb += msb_a.eq(Mux(is_32bit, a_n[31], a_n[63]))
-                    comb += msb_b.eq(Mux(is_32bit, b[31], b[63]))
+                    comb += msb_a.eq(Mux(is_32bit, a_n[31], a_n[XLEN-1]))
+                    comb += msb_b.eq(Mux(is_32bit, b[31], b[XLEN-1]))
                     C0 = Const(0, 1)
                     with m.If(msb_a != msb_b):
                         # Subtraction might overflow, but
@@ -142,13 +153,21 @@ class ALUMainStage(PipeModBase):
                 # https://bugs.libre-soc.org/show_bug.cgi?id=319#c5
                 ca = Signal(2, reset_less=True)
                 comb += ca[0].eq(add_o[-1])                   # XER.CA
-                comb += ca[1].eq(add_o[33] ^ (a_i[32] ^ b_i[32])) # XER.CA32
+                if XLEN == 64:
+                    comb += ca[1].eq(add_o[33] ^ (a_i[32] ^ b_i[32])) # XER.CA32
+                else:
+                    comb += ca[1].eq(add_o[-1])                   # XER.CA32
                 comb += cry_o.data.eq(ca)
                 comb += cry_o.ok.eq(1)
                 # 32-bit (ov[1]) and 64-bit (ov[0]) overflow
                 ov = Signal(2, reset_less=True)
                 comb += ov[0].eq(calc_ov(a_i[-1], b_i[-1], ca[0], add_o[-2]))
-                comb += ov[1].eq(calc_ov(a_i[31], b_i[31], ca[1], add_o[32]))
+                if XLEN == 64:
+                    comb += ov[1].eq(calc_ov(a_i[31], b_i[31], ca[1],
+                                             add_o[32]))
+                else:
+                    comb += ov[1].eq(calc_ov(a_i[-1], b_i[-1], ca[0],
+                                            add_o[-2]))
                 comb += ov_o.data.eq(ov)
                 comb += ov_o.ok.eq(1)
 
@@ -157,11 +176,11 @@ class ALUMainStage(PipeModBase):
 
             with m.Case(MicrOp.OP_EXTS):
                 with m.If(op.data_len == 1):
-                    comb += o.data.eq(exts(a, 8, 64))
+                    comb += o.data.eq(exts(a, 8, XLEN))
                 with m.If(op.data_len == 2):
-                    comb += o.data.eq(exts(a, 16, 64))
+                    comb += o.data.eq(exts(a, 16, XLEN))
                 with m.If(op.data_len == 4):
-                    comb += o.data.eq(exts(a, 32, 64))
+                    comb += o.data.eq(exts(a, 32, XLEN))
                 comb += o.ok.eq(1) # output register
 
             ###################