Properly sign extend immediates
authorMichael Nolan <mtnolan2640@gmail.com>
Mon, 23 Mar 2020 18:40:22 +0000 (14:40 -0400)
committerMichael Nolan <mtnolan2640@gmail.com>
Mon, 23 Mar 2020 20:01:45 +0000 (16:01 -0400)
src/soc/decoder/power_decoder2.py
src/soc/decoder/test/test_decoder_gas.py

index 08c9f44d52026e304f38d8387e30eff9068aa46c..27b520c04c8a9b1cb5dc92fe0506c14221805dcd 100644 (file)
@@ -3,7 +3,7 @@
 based on Anton Blanchard microwatt decode2.vhdl
 
 """
-from nmigen import Module, Elaboratable, Signal, Mux, Const
+from nmigen import Module, Elaboratable, Signal, Mux, Const, Cat, Repl
 from nmigen.cli import rtlil
 
 from soc.decoder.power_decoder import create_pdecode
@@ -91,6 +91,13 @@ class DecodeB(Elaboratable):
         self.imm_out = Data(64, "imm_b")
         self.spr_out = Data(10, "spr_b")
 
+    def exts(self, exts_data, width, fullwidth):
+        exts_data = exts_data[0:width]
+        topbit = exts_data[-1]
+        signbits = Repl(topbit, fullwidth-width)
+        return Cat(exts_data, signbits)
+
+
     def elaborate(self, platform):
         m = Module()
         comb = m.d.comb
@@ -104,13 +111,16 @@ class DecodeB(Elaboratable):
                 comb += self.imm_out.data.eq(self.dec.UI[0:-1])
                 comb += self.imm_out.ok.eq(1)
             with m.Case(In2Sel.CONST_SI): # TODO: sign-extend here?
-                comb += self.imm_out.data.eq(self.dec.SI[0:-1])
+                comb += self.imm_out.data.eq(
+                    self.exts(self.dec.SI[0:-1], 16, 64))
                 comb += self.imm_out.ok.eq(1)
             with m.Case(In2Sel.CONST_UI_HI):
                 comb += self.imm_out.data.eq(self.dec.UI[0:-1]<<16)
                 comb += self.imm_out.ok.eq(1)
             with m.Case(In2Sel.CONST_SI_HI): # TODO: sign-extend here?
                 comb += self.imm_out.data.eq(self.dec.SI[0:-1]<<16)
+                comb += self.imm_out.data.eq(
+                    self.exts(self.dec.SI[0:-1] << 16, 32, 64))
                 comb += self.imm_out.ok.eq(1)
             with m.Case(In2Sel.CONST_LI):
                 comb += self.imm_out.data.eq(self.dec.LI[0:-1]<<2)
index 4ed591e6c64caacc2408edf073339c7ddf683873..0003e2e6315297765e5d5097a347c340c6a2a938 100644 (file)
@@ -17,6 +17,23 @@ class Register:
     def __init__(self, num):
         self.num = num
 
+class Checker:
+    def __init__(self):
+        self.imm = 0
+
+    def get_imm(self, in2_sel):
+        if in2_sel == In2Sel.CONST_UI.value:
+            return self.imm & 0xffff
+        if in2_sel == In2Sel.CONST_UI_HI.value:
+            return (self.imm & 0xffff) << 16
+        if in2_sel == In2Sel.CONST_SI.value:
+            sign_bit = 1 << 15
+            return (self.imm & (sign_bit-1)) - (self.imm & sign_bit)
+        if in2_sel == In2Sel.CONST_SI_HI.value:
+            imm = self.imm << 16
+            sign_bit = 1 << 31
+            return (imm & (sign_bit-1)) - (imm & sign_bit)
+        
 
 class RegRegOp:
     def __init__(self):
@@ -70,8 +87,9 @@ class RegRegOp:
             assert(rc == 0)
 
 
-class RegImmOp:
+class RegImmOp(Checker):
     def __init__(self):
+        super().__init__()
         self.ops = {
             "addi": InternalOp.OP_ADD,
             "addis": InternalOp.OP_ADD,
@@ -106,10 +124,9 @@ class RegImmOp:
 
         imm = yield pdecode2.e.imm_data.data
         in2_sel = yield pdecode2.dec.op.in2_sel
-        if in2_sel in [In2Sel.CONST_SI_HI.value, In2Sel.CONST_UI_HI.value]:
-            assert(imm == (self.imm << 16))
-        else:
-            assert(imm == self.imm)
+        imm_expected = self.get_imm(in2_sel)
+        msg = "imm: got {:x}, expected {:x}".format(imm, imm_expected)
+        assert imm == imm_expected, msg
 
         rc = yield pdecode2.e.rc.data
         if '.' in self.opcodestr:
@@ -118,8 +135,9 @@ class RegImmOp:
             assert(rc == 0)
 
 
-class LdStOp:
+class LdStOp(Checker):
     def __init__(self):
+        super().__init__()
         self.ops = {
             "lwz": InternalOp.OP_LOAD,
             "stw": InternalOp.OP_STORE,
@@ -154,7 +172,8 @@ class LdStOp:
         assert(r2sel == self.r2.num)
 
         imm = yield pdecode2.e.imm_data.data
-        assert(imm == self.imm)
+        in2_sel = yield pdecode2.dec.op.in2_sel
+        assert(imm == self.get_imm(in2_sel))
 
         update = yield pdecode2.e.update
         if "u" in self.opcodestr: