Fix bug in GAS test where it would load and update the same register
[soc.git] / src / soc / decoder / test / test_decoder_gas.py
index 52ae79775723565bc62d38a2fe44549c773cc8b9..be3f42b7ba407c1efc4d5da347308e5f963b11b8 100644 (file)
@@ -9,9 +9,7 @@ from soc.decoder.power_enums import (Function, InternalOp,
                                      single_bit_flags, Form, SPR,
                                      get_signal_name, get_csv)
 from soc.decoder.power_decoder2 import (PowerDecode2)
-import tempfile
-import subprocess
-import struct
+from soc.simulator.gas import get_assembled_instruction
 import random
 
 
@@ -19,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):
@@ -72,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,
@@ -108,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:
@@ -120,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,
@@ -136,6 +152,8 @@ class LdStOp:
         self.opcode = self.ops[self.opcodestr]
         self.r1 = Register(random.randrange(32))
         self.r2 = Register(random.randrange(1, 32))
+        while self.r2.num == self.r1.num:
+            self.r2 = Register(random.randrange(1, 32))
         self.imm = random.randrange(32767)
 
     def generate_instruction(self):
@@ -156,7 +174,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:
@@ -196,7 +215,7 @@ class CmpRegOp:
     def check_results(self, pdecode2):
         r1sel = yield pdecode2.e.read_reg1.data
         r2sel = yield pdecode2.e.read_reg2.data
-        crsel = yield pdecode2.dec.BF[0:-1]
+        crsel = yield pdecode2.dec.BF
 
         assert(r1sel == self.r1.num)
         assert(r2sel == self.r2.num)
@@ -236,11 +255,11 @@ class RotateOp:
         dec = pdecode2.dec
 
         if "i" in self.opcodestr:
-            shift = yield dec.SH[0:-1]
+            shift = yield dec.SH
         else:
             shift = yield pdecode2.e.read_reg2.data
-        mb = yield dec.MB[0:-1]
-        me = yield dec.ME[0:-1]
+        mb = yield dec.MB
+        me = yield dec.ME
 
         assert(r1sel == self.r1.num)
         assert(r2sel == self.r2.num)
@@ -281,7 +300,7 @@ class Branch:
             assert(lk == 1)
         else:
             assert(lk == 0)
-        aa = yield pdecode2.dec.AA[0:-1]
+        aa = yield pdecode2.dec.AA
         if "a" in self.opcodestr:
             assert(aa == 1)
         else:
@@ -315,8 +334,8 @@ class BranchCond:
 
     def check_results(self, pdecode2):
         imm = yield pdecode2.e.imm_data.data
-        bo = yield pdecode2.dec.BO[0:-1]
-        bi = yield pdecode2.dec.BI[0:-1]
+        bo = yield pdecode2.dec.BO
+        bi = yield pdecode2.dec.BI
 
         assert(imm == self.addr)
         assert(bo == self.bo)
@@ -326,7 +345,7 @@ class BranchCond:
             assert(lk == 1)
         else:
             assert(lk == 0)
-        aa = yield pdecode2.dec.AA[0:-1]
+        aa = yield pdecode2.dec.AA
         if "a" in self.opcodestr:
             assert(aa == 1)
         else:
@@ -358,8 +377,8 @@ class BranchRel:
         return string
 
     def check_results(self, pdecode2):
-        bo = yield pdecode2.dec.BO[0:-1]
-        bi = yield pdecode2.dec.BI[0:-1]
+        bo = yield pdecode2.dec.BO
+        bi = yield pdecode2.dec.BI
 
         assert(bo == self.bo)
         assert(bi == self.bi)
@@ -379,32 +398,6 @@ class BranchRel:
 
 class DecoderTestCase(FHDLTestCase):
 
-    def get_assembled_instruction(self, instruction, bigendian=False):
-        if bigendian:
-            endian_fmt = "elf64-big"
-            obj_fmt = "-be"
-        else:
-            endian_fmt = "elf64-little"
-            obj_fmt = "-le"
-        with tempfile.NamedTemporaryFile(suffix=".o") as outfile:
-            args = ["powerpc64-linux-gnu-as",
-                    obj_fmt,
-                    "-o",
-                    outfile.name]
-            p = subprocess.Popen(args, stdin=subprocess.PIPE)
-            p.communicate(instruction.encode('utf-8'))
-            assert(p.wait() == 0)
-
-            with tempfile.NamedTemporaryFile(suffix=".bin") as binfile:
-                args = ["powerpc64-linux-gnu-objcopy",
-                        "-I", endian_fmt,
-                        "-O", "binary",
-                        outfile.name,
-                        binfile.name]
-                subprocess.check_output(args)
-                binary = struct.unpack('>i', binfile.read(4))[0]
-                return binary
-
     def run_tst(self, kls, name):
         m = Module()
         comb = m.d.comb
@@ -419,17 +412,17 @@ class DecoderTestCase(FHDLTestCase):
         def process():
             for i in range(20):
                 checker = kls()
-                instruction_str = checker.generate_instruction()
-                print("instr", instruction_str.strip())
-                for endian in [0, 1]:
+                ins = checker.generate_instruction()
+                print("instr", ins.strip())
+                for mode in [0, 1]:
 
-                    instruction_bin = self.get_assembled_instruction(
-                        instruction_str, endian)
-                    print("code", endian, hex(instruction_bin),
-                                          bin(instruction_bin))
+                    # turn the instruction into binary data (endian'd)
+                    ibin = get_assembled_instruction(ins, mode)
+                    print("code", mode, hex(ibin), bin(ibin))
 
-                    yield pdecode2.dec.bigendian.eq(endian)
-                    yield instruction.eq(instruction_bin)
+                    # ask the decoder to decode this binary data (endian'd)
+                    yield pdecode2.dec.bigendian.eq(mode) # little / big?
+                    yield instruction.eq(ibin)            # raw binary instr.
                     yield Delay(1e-6)
 
                     yield from checker.check_results(pdecode2)