add qemu_test
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 23 Apr 2021 12:32:36 +0000 (13:32 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 23 Apr 2021 12:32:36 +0000 (13:32 +0100)
16 files changed:
src/openpower/simulator/__init__.py [new file with mode: 0644]
src/openpower/simulator/envcmds.py [new file with mode: 0644]
src/openpower/simulator/gas.py [new file with mode: 0644]
src/openpower/simulator/program.py [new file with mode: 0644]
src/openpower/simulator/qemu.py [new file with mode: 0644]
src/openpower/simulator/qemu_test/Makefile [new file with mode: 0644]
src/openpower/simulator/qemu_test/README.md [new file with mode: 0644]
src/openpower/simulator/qemu_test/gdbscript [new file with mode: 0644]
src/openpower/simulator/qemu_test/launch.sh [new file with mode: 0755]
src/openpower/simulator/qemu_test/test.s [new file with mode: 0644]
src/openpower/simulator/test_div_sim.py [new file with mode: 0644]
src/openpower/simulator/test_helloworld_sim.py [new file with mode: 0644]
src/openpower/simulator/test_mul_sim.py [new file with mode: 0644]
src/openpower/simulator/test_shift_sim.py [new file with mode: 0644]
src/openpower/simulator/test_sim.py [new file with mode: 0644]
src/openpower/simulator/test_trap_sim.py [new file with mode: 0644]

diff --git a/src/openpower/simulator/__init__.py b/src/openpower/simulator/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/openpower/simulator/envcmds.py b/src/openpower/simulator/envcmds.py
new file mode 100644 (file)
index 0000000..e6525c0
--- /dev/null
@@ -0,0 +1,9 @@
+import os
+
+# set up environment variable overrides, can use for different versions
+# as well as native (TALOS-II POWER9) builds.
+cmds = {}
+for cmd in ['objcopy', 'as', 'ld', 'gcc', 'ar', 'gdb']:
+    cmds[cmd] = os.environ.get(cmd.upper(), "powerpc64-linux-gnu-%s" % cmd)
+
+
diff --git a/src/openpower/simulator/gas.py b/src/openpower/simulator/gas.py
new file mode 100644 (file)
index 0000000..5e36a14
--- /dev/null
@@ -0,0 +1,34 @@
+# License: LPGLv3
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+# Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+
+import tempfile
+import subprocess
+import struct
+
+
+def get_assembled_instruction(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
diff --git a/src/openpower/simulator/program.py b/src/openpower/simulator/program.py
new file mode 100644 (file)
index 0000000..c55a67d
--- /dev/null
@@ -0,0 +1,141 @@
+# License: LGPLv3+
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+# Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+
+"""POWER Program
+
+takes powerpc assembly instructions and turns them into LE/BE binary
+data.  calls powerpc64-linux-gnu-as, ld and objcopy to do so.
+"""
+
+import tempfile
+import subprocess
+import struct
+import os
+import sys
+from io import BytesIO
+
+from soc.simulator.envcmds import cmds
+
+filedir = os.path.dirname(os.path.realpath(__file__))
+memmap = os.path.join(filedir, "memmap")
+
+
+class Program:
+    def __init__(self, instructions, bigendian):
+        self.bigendian = bigendian
+        if self.bigendian:
+            self.endian_fmt = "elf64-big"
+            self.obj_fmt = "-be"
+            self.ld_fmt = "-EB"
+        else:
+            self.ld_fmt = "-EL"
+            self.endian_fmt = "elf64-little"
+            self.obj_fmt = "-le"
+
+        if isinstance(instructions, bytes):  # actual bytes
+            self.binfile = BytesIO(instructions)
+            self.binfile.name = "assembly"
+            self.assembly = ''  # noo disassemble number fiiive
+        elif isinstance(instructions, str):  # filename
+            # read instructions into a BytesIO to avoid "too many open files"
+            with open(instructions, "rb") as f:
+                b = f.read()
+            self.binfile = BytesIO(b)
+            self.assembly = ''  # noo disassemble number fiiive
+            print("program", self.binfile)
+        else:
+            if isinstance(instructions, list):
+                instructions = '\n'.join(instructions)
+            self.assembly = instructions + '\n'  # plus final newline
+            self._assemble()
+        self._instructions = list(self._get_instructions())
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, traceback):
+        self.close()
+
+    def _get_binary(self, elffile):
+        self.binfile = tempfile.NamedTemporaryFile(suffix=".bin")
+        args = [cmds['objcopy'],
+                "-O", "binary",
+                "-I", self.endian_fmt,
+                elffile.name,
+                self.binfile.name]
+        subprocess.check_output(args)
+
+    def _link(self, ofile):
+        with tempfile.NamedTemporaryFile(suffix=".elf") as elffile:
+            args = [cmds['ld'],
+                    self.ld_fmt,
+                    "-o", elffile.name,
+                    "-T", memmap,
+                    ofile.name]
+            subprocess.check_output(args)
+            self._get_binary(elffile)
+
+    def _assemble(self):
+        with tempfile.NamedTemporaryFile(suffix=".o") as outfile:
+            args = [cmds['as'],
+                    '-mpower9',
+                    '-mregnames',
+                    self.obj_fmt,
+                    "-o",
+                    outfile.name]
+            p = subprocess.Popen(args, stdin=subprocess.PIPE)
+            p.communicate(self.assembly.encode('utf-8'))
+            if p.wait() != 0:
+                print("Error in program:")
+                print(self.assembly)
+                sys.exit(1)
+            self._link(outfile)
+
+    def _get_instructions(self):
+        while True:
+            data = self.binfile.read(4)
+            if not data:
+                break
+            yield struct.unpack('<I', data)[0]  # unsigned int
+
+    def generate_instructions(self):
+        yield from self._instructions
+
+    def reset(self):
+        self.binfile.seek(0)
+
+    def size(self):
+        curpos = self.binfile.tell()
+        self.binfile.seek(0, 2)  # Seek to end of file
+        size = self.binfile.tell()
+        self.binfile.seek(curpos, 0)
+        return size
+
+    def write_bin(self, fname):
+        self.reset()
+        data = self.binfile.read()
+        with open(fname, "wb") as f:
+            f.write(data)
+
+    def close(self):
+        self.binfile.close()
+
+if __name__ == '__main__':
+    lst = ['addi 5, 0, 4660/2',
+           'mtcrf 255, 5+3',
+           'mfocrf 2, 1',
+           'addi r2, 3, 1',
+           'attn',
+          ]
+    lst = ["addi 9, 0, 0x10",  # i = 16
+           "addi 9,9,-1",    # i = i - 1
+           "cmpi 2,1,9,12",     # compare 9 to value 12, store in CR2
+           "bc 4,10,-8",        # branch if CR2 "test was != 12"
+           'attn',
+           ]
+
+    with Program(lst, False) as p:
+        for instruction in p.generate_instructions():
+            print (hex(instruction))
+        p.write_bin("/tmp/test.bin")
diff --git a/src/openpower/simulator/qemu.py b/src/openpower/simulator/qemu.py
new file mode 100644 (file)
index 0000000..c4511e1
--- /dev/null
@@ -0,0 +1,175 @@
+from pygdbmi.gdbcontroller import GdbController
+import subprocess
+
+launch_args_be = ['qemu-system-ppc64',
+                  '-machine', 'powernv9',
+                  '-nographic',
+                  '-s', '-S']
+
+launch_args_le = ['qemu-system-ppc64le',
+                  '-machine', 'powernv9',
+                  '-nographic',
+                  '-s', '-S']
+
+
+def swap_order(x, nbytes):
+    x = x.to_bytes(nbytes, byteorder='little')
+    x = int.from_bytes(x, byteorder='big', signed=False)
+    return x
+
+
+class QemuController:
+    def __init__(self, kernel, bigendian):
+        if bigendian:
+            args = launch_args_be + ['-kernel', kernel]
+        else:
+            args = launch_args_le + ['-kernel', kernel]
+        self.qemu_popen = subprocess.Popen(args,
+                                           stdout=subprocess.PIPE,
+                                           stdin=subprocess.PIPE)
+        self.gdb = GdbController(gdb_path='powerpc64-linux-gnu-gdb')
+        self.bigendian = bigendian
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, traceback):
+        self.exit()
+
+    def connect(self):
+        return self.gdb.write('-target-select remote localhost:1234')
+
+    def set_endian(self, bigendian):
+        if bigendian:
+            cmd = '-gdb-set endian big'
+        else:
+            cmd = '-gdb-set endian little'
+        return self.gdb.write(cmd)
+
+    def break_address(self, addr):
+        cmd = '-break-insert *0x{:x}'.format(addr)
+        return self.gdb.write(cmd)
+
+    def delete_breakpoint(self, breakpoint=None):
+        breakstring = ''
+        if breakpoint:
+            breakstring = f' {breakpoint}'
+        return self.gdb.write('-break-delete' + breakstring)
+
+    def set_byte(self, addr, v):
+        print("qemu set byte", hex(addr), hex(v))
+        faddr = '&{int}0x%x' % addr
+        res = self.gdb.write('-data-write-memory-bytes %s "%02x"' % (faddr, v))
+        print("confirm", self.get_mem(addr, 1))
+
+    def get_mem(self, addr, nbytes):
+        res = self.gdb.write("-data-read-memory %d u 1 1 %d" %
+                             (addr, 8*nbytes))
+        #print ("get_mem", res)
+        for x in res:
+            if(x["type"] == "result"):
+                l = list(map(int, x['payload']['memory'][0]['data']))
+                res = []
+                for j in range(0, len(l), 8):
+                    b = 0
+                    for i, v in enumerate(l[j:j+8]):
+                        b += v << (i*8)
+                    res.append(b)
+                return res
+        return None
+
+    def get_registers(self):
+        return self.gdb.write('-data-list-register-values x')
+
+    def _get_register(self, fmt):
+        res = self.gdb.write('-data-list-register-values '+fmt,
+                             timeout_sec=1.0)  # increase this timeout if needed
+        for x in res:
+            if(x["type"] == "result"):
+                assert 'register-values' in x['payload']
+                res = int(x['payload']['register-values'][0]['value'], 0)
+                return res
+                # return swap_order(res, 8)
+        return None
+
+    # TODO: use -data-list-register-names instead of hardcoding the values
+    def get_pc(self): return self._get_register('x 64')
+    def get_msr(self): return self._get_register('x 65')
+    def get_cr(self): return self._get_register('x 66')
+    def get_lr(self): return self._get_register('x 67')
+    def get_ctr(self): return self._get_register('x 68')  # probably
+    def get_xer(self): return self._get_register('x 69')
+    def get_fpscr(self): return self._get_register('x 70')
+    def get_mq(self): return self._get_register('x 71')
+
+    def get_register(self, num):
+        return self._get_register('x {}'.format(num))
+
+    def step(self):
+        return self.gdb.write('-exec-next-instruction')
+
+    def gdb_continue(self):
+        return self.gdb.write('-exec-continue')
+
+    def gdb_eval(self, expr):
+        return self.gdb.write(f'-data-evaluate-expression {expr}')
+
+    def exit(self):
+        self.gdb.exit()
+        self.qemu_popen.kill()
+        outs, errs = self.qemu_popen.communicate()
+        self.qemu_popen.stdout.close()
+        self.qemu_popen.stdin.close()
+
+
+def run_program(program, initial_mem=None, extra_break_addr=None,
+                bigendian=False):
+    q = QemuController(program.binfile.name, bigendian)
+    q.connect()
+    q.set_endian(True)  # easier to set variables this way
+
+    # Run to the start of the program
+    if initial_mem:
+        for addr, (v, wid) in initial_mem.items():
+            for i in range(wid):
+                q.set_byte(addr+i, (v >> i*8) & 0xff)
+
+    # set breakpoint at start
+    q.break_address(0x20000000)
+    q.gdb_continue()
+    # set the MSR bit 63, to set bigendian/littleendian mode
+    msr = q.get_msr()
+    print("msr", bigendian, hex(msr))
+    if bigendian:
+        msr &= ~(1 << 0)
+        msr = msr & ((1 << 64)-1)
+    else:
+        msr |= (1 << 0)
+    q.gdb_eval('$msr=%d' % msr)
+    print("msr set to", hex(msr))
+    # set the CR to 0, matching the simulator
+    q.gdb_eval('$cr=0')
+    # delete the previous breakpoint so loops don't screw things up
+    q.delete_breakpoint()
+    # run to completion
+    q.break_address(0x20000000 + program.size())
+    # or to trap
+    q.break_address(0x700)
+    # or to alternative (absolute) address)
+    if extra_break_addr:
+        q.break_address(extra_break_addr)
+    q.gdb_continue()
+    q.set_endian(bigendian)
+
+    return q
+
+
+if __name__ == '__main__':
+    q = QemuController("simulator/qemu_test/kernel.bin", bigendian=True)
+    q.connect()
+    q.break_address(0x20000000)
+    q.gdb_continue()
+    print(q.get_register(1))
+    print(q.step())
+    print(q.get_register(1))
+    q.exit()
diff --git a/src/openpower/simulator/qemu_test/Makefile b/src/openpower/simulator/qemu_test/Makefile
new file mode 100644 (file)
index 0000000..88833cd
--- /dev/null
@@ -0,0 +1,18 @@
+TOOLCHAIN=powerpc64-linux-gnu
+CC=$(TOOLCHAIN)-gcc
+AS=$(TOOLCHAIN)-as
+AFLAGS=-mpwr9
+
+all: kernel.bin
+
+clean:
+       rm *.o *.elf *.bin
+
+kernel.elf: test.o
+       $(TOOLCHAIN)-ld $^ -o $@ -T memmap
+
+kernel.bin: kernel.elf
+       $(TOOLCHAIN)-objcopy $< -O binary $@
+
+%.o: %.s
+       $(AS) $(AFLAGS) -c $< -o $@
diff --git a/src/openpower/simulator/qemu_test/README.md b/src/openpower/simulator/qemu_test/README.md
new file mode 100644 (file)
index 0000000..32f90ee
--- /dev/null
@@ -0,0 +1,8 @@
+# Qemu test directory
+
+To launch and debug qemu, run the following:
+```
+make
+./launch.sh
+powerpc64-linux-gnu-gdb -x gdbscript
+```
diff --git a/src/openpower/simulator/qemu_test/gdbscript b/src/openpower/simulator/qemu_test/gdbscript
new file mode 100644 (file)
index 0000000..1337e6a
--- /dev/null
@@ -0,0 +1,4 @@
+target remote localhost:1234
+layout asm
+b *0x20000000
+c
diff --git a/src/openpower/simulator/qemu_test/launch.sh b/src/openpower/simulator/qemu_test/launch.sh
new file mode 100755 (executable)
index 0000000..2844553
--- /dev/null
@@ -0,0 +1 @@
+qemu-system-ppc64 -machine powernv9 -nographic -s -S -kernel kernel.bin
diff --git a/src/openpower/simulator/qemu_test/test.s b/src/openpower/simulator/qemu_test/test.s
new file mode 100644 (file)
index 0000000..fb2ec15
--- /dev/null
@@ -0,0 +1,6 @@
+       lis 1, 0xdead
+       ori 1, 1, 0xbeef
+       lis 2, 0x2000
+       ori 2, 2, 0x0100
+       std 1, 0(2)
+       lhz 1, 4(2)
diff --git a/src/openpower/simulator/test_div_sim.py b/src/openpower/simulator/test_div_sim.py
new file mode 100644 (file)
index 0000000..171af5c
--- /dev/null
@@ -0,0 +1,148 @@
+from nmigen import Module, Signal
+from nmigen.back.pysim import Simulator, Delay, Settle
+from nmutil.formaltest import FHDLTestCase
+import unittest
+from soc.decoder.power_decoder import (create_pdecode)
+from soc.decoder.power_enums import (Function, MicrOp,
+                                     In1Sel, In2Sel, In3Sel,
+                                     OutSel, RC, LdstLen, CryIn,
+                                     single_bit_flags, Form, SPR,
+                                     get_signal_name, get_csv)
+from soc.decoder.power_decoder2 import (PowerDecode2)
+from soc.simulator.program import Program
+from soc.simulator.qemu import run_program
+from soc.decoder.isa.all import ISA
+from soc.fu.test.common import TestCase
+from soc.simulator.test_sim import DecoderBase
+
+
+
+class DivTestCases(FHDLTestCase):
+    test_data = []
+
+    def __init__(self, name="div"):
+        super().__init__(name)
+        self.test_name = name
+
+    def test_0_divw(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x1234",
+               "divw  3, 1, 2",
+               ]
+        with Program(lst) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    def test_1_divw_(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x1234",
+               "divw.  3, 1, 2",
+               ]
+        with Program(lst) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    def test_2_divw_(self):
+        lst = ["addi 1, 0, 0x1234",
+               "addi 2, 0, 0x5678",
+               "divw.  3, 1, 2",
+               ]
+        with Program(lst) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    def test_1_divwe(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x1234",
+               "divwe  3, 1, 2",
+               ]
+        with Program(lst) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    def test_2_divweu(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x1234",
+               "divweu  3, 1, 2",
+               ]
+        with Program(lst) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    def test_4_moduw(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x1234",
+               "moduw  3, 1, 2",
+               ]
+        with Program(lst) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    def test_5_div_regression(self):
+        lst = ["addi 1, 0, 0x4",
+               "addi 2, 0, 0x2",
+               "neg 2, 2",
+               "neg 1, 1",
+               "divwo  3, 1, 2",
+               ]
+        with Program(lst) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
+                                    initial_mem=None):
+        initial_regs = [0] * 32
+        tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
+                                            initial_mem, 0)
+        self.test_data.append(tc)
+
+
+class DivZeroTestCases(FHDLTestCase):
+    test_data = []
+
+    def __init__(self, name="divbyzero"):
+        super().__init__(name)
+        self.test_name = name
+
+    def test_0_divw(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x0",
+               "divw  3, 1, 2",
+               ]
+        with Program(lst) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    def test_1_divwe(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x0",
+               "divwe  3, 1, 2",
+               ]
+        with Program(lst) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    def test_2_divweu(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x0",
+               "divweu  3, 1, 2",
+               ]
+        with Program(lst) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    def test_4_moduw(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x0",
+               "moduw  3, 1, 2",
+               ]
+        with Program(lst) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
+                                    initial_mem=None):
+        initial_regs = [0] * 32
+        tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
+                                            initial_mem, 0)
+        self.test_data.append(tc)
+
+
+
+class DivDecoderTestCase(DecoderBase, DivTestCases):
+    pass
+
+class DivZeroDecoderTestCase(DecoderBase, DivZeroTestCases):
+    pass
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/openpower/simulator/test_helloworld_sim.py b/src/openpower/simulator/test_helloworld_sim.py
new file mode 100644 (file)
index 0000000..d113043
--- /dev/null
@@ -0,0 +1,58 @@
+from nmigen import Module, Signal
+from nmigen.back.pysim import Simulator, Delay, Settle
+from nmutil.formaltest import FHDLTestCase
+import unittest
+from soc.decoder.power_decoder import (create_pdecode)
+from soc.decoder.power_enums import (Function, MicrOp,
+                                     In1Sel, In2Sel, In3Sel,
+                                     OutSel, RC, LdstLen, CryIn,
+                                     single_bit_flags, Form, SPR,
+                                     get_signal_name, get_csv)
+from soc.decoder.power_decoder2 import (PowerDecode2)
+from soc.simulator.program import Program
+from soc.simulator.qemu import run_program
+from soc.decoder.isa.all import ISA
+from soc.fu.test.common import TestCase
+from soc.simulator.test_sim import DecoderBase
+from soc.config.endian import bigendian
+
+
+class HelloTestCases(FHDLTestCase):
+    test_data = []
+
+    def __init__(self, name="div"):
+        super().__init__(name)
+        self.test_name = name
+
+    def test_microwatt_helloworld(self):
+        lst = ["addis     1,0,0",
+                "ori     1,1,0",
+                "rldicr  1,1,32,31",
+                "oris    1,1,0",
+                "ori     1,1,7936",
+                "addis     12,0,0",
+                "ori     12,12,0",
+                "rldicr  12,12,32,31",
+                "oris    12,12,0",
+                "ori     12,12,4116",
+                "mtspr   9, 12",     # mtctr r12
+                "bcctrl  20,0,0", # bctrl
+                ]
+        self.run_tst_program(Program(lst, bigendian),
+                             [1,12], extra_break_addr=0x1014)
+
+    def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
+                                    initial_mem=None, extra_break_addr=None):
+        initial_regs = [0] * 32
+        tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
+                                            initial_mem, 0,
+                                            extra_break_addr=extra_break_addr)
+        self.test_data.append(tc)
+
+
+class HelloDecoderTestCase(DecoderBase, HelloTestCases):
+    pass
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/openpower/simulator/test_mul_sim.py b/src/openpower/simulator/test_mul_sim.py
new file mode 100644 (file)
index 0000000..6d25105
--- /dev/null
@@ -0,0 +1,55 @@
+from nmigen import Module, Signal
+from nmigen.back.pysim import Simulator, Delay, Settle
+from nmutil.formaltest import FHDLTestCase
+import unittest
+from soc.decoder.power_decoder import (create_pdecode)
+from soc.decoder.power_enums import (Function, MicrOp,
+                                     In1Sel, In2Sel, In3Sel,
+                                     OutSel, RC, LdstLen, CryIn,
+                                     single_bit_flags, Form, SPR,
+                                     get_signal_name, get_csv)
+from soc.decoder.power_decoder2 import (PowerDecode2)
+from soc.simulator.program import Program
+from soc.simulator.qemu import run_program
+from soc.decoder.isa.all import ISA
+from soc.fu.test.common import TestCase
+from soc.simulator.test_sim import DecoderBase
+from soc.config.endian import bigendian
+
+
+
+class MulTestCases(FHDLTestCase):
+    test_data = []
+
+    def __init__(self, name="div"):
+        super().__init__(name)
+        self.test_name = name
+
+    def tst_mullw(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x1234",
+               "mullw 3, 1, 2"]
+        self.run_tst_program(Program(lst, bigendian), [3])
+
+    def test_mullwo(self):
+        lst = ["addi 1, 0, 0x5678",
+               "neg 1, 1",
+               "addi 2, 0, 0x1234",
+               "neg 2, 2",
+               "mullwo 3, 1, 2"]
+        self.run_tst_program(Program(lst, bigendian), [3])
+
+    def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
+                                    initial_mem=None):
+        initial_regs = [0] * 32
+        tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
+                                            initial_mem, 0)
+        self.test_data.append(tc)
+
+
+class MulDecoderTestCase(DecoderBase, MulTestCases):
+    pass
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/openpower/simulator/test_shift_sim.py b/src/openpower/simulator/test_shift_sim.py
new file mode 100644 (file)
index 0000000..e164210
--- /dev/null
@@ -0,0 +1,46 @@
+from nmigen import Module, Signal
+from nmigen.back.pysim import Simulator, Delay, Settle
+from nmutil.formaltest import FHDLTestCase
+import unittest
+from soc.decoder.power_decoder import (create_pdecode)
+from soc.decoder.power_enums import (Function, MicrOp,
+                                     In1Sel, In2Sel, In3Sel,
+                                     OutSel, RC, LdstLen, CryIn,
+                                     single_bit_flags, Form, SPR,
+                                     get_signal_name, get_csv)
+from soc.decoder.power_decoder2 import (PowerDecode2)
+from soc.simulator.program import Program
+from soc.simulator.qemu import run_program
+from soc.decoder.isa.all import ISA
+from soc.fu.test.common import TestCase
+from soc.simulator.test_sim import DecoderBase
+from soc.config.endian import bigendian
+
+
+
+class MulTestCases(FHDLTestCase):
+    test_data = []
+
+    def __init__(self, name="div"):
+        super().__init__(name)
+        self.test_name = name
+
+    def test_1_extswsli(self):
+        lst = ["addi 1, 0, 0x5678",
+               "extswsli 3, 1, 34"]
+        self.run_tst_program(Program(lst, bigendian), [3])
+
+    def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
+                                    initial_mem=None):
+        initial_regs = [0] * 32
+        tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
+                                            initial_mem, 0)
+        self.test_data.append(tc)
+
+
+class MulDecoderTestCase(DecoderBase, MulTestCases):
+    pass
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/openpower/simulator/test_sim.py b/src/openpower/simulator/test_sim.py
new file mode 100644 (file)
index 0000000..4d586fa
--- /dev/null
@@ -0,0 +1,569 @@
+from nmigen import Module, Signal
+from nmigen.back.pysim import Simulator, Delay, Settle
+from nmutil.formaltest import FHDLTestCase
+import unittest
+from soc.decoder.power_decoder import (create_pdecode)
+from soc.decoder.power_enums import (Function, MicrOp,
+                                     In1Sel, In2Sel, In3Sel,
+                                     OutSel, RC, LdstLen, CryIn,
+                                     single_bit_flags, Form,
+                                     get_signal_name, get_csv)
+from soc.decoder.power_decoder2 import (PowerDecode2)
+from soc.simulator.program import Program
+from soc.simulator.qemu import run_program
+from soc.decoder.isa.all import ISA
+from soc.fu.test.common import TestCase
+from soc.config.endian import bigendian
+
+
+class AttnTestCase(FHDLTestCase):
+    test_data = []
+
+    def __init__(self, name="general"):
+        super().__init__(name)
+        self.test_name = name
+
+    def test_0_attn(self):
+        """simple test of attn.  program is 4 long: should halt at 2nd op
+        """
+        lst = ["addi 6, 0, 0x10",
+               "attn",
+               "subf. 1, 6, 7",
+               "cmp cr2, 1, 6, 7",
+               ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1])
+
+    def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
+                        initial_mem=None):
+        initial_regs = [0] * 32
+        tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
+                      initial_mem, 0)
+        self.test_data.append(tc)
+
+
+class GeneralTestCases(FHDLTestCase):
+    test_data = []
+
+    def __init__(self, name="general"):
+        super().__init__(name)
+        self.test_name = name
+
+    @unittest.skip("disable")
+    def test_0_litex_bios_ctr_loop(self):
+        """
+        32a4:   ff ff 63 38     addi    r3,r3,-1
+        32a8:   20 00 63 78     clrldi  r3,r3,32
+        32ac:   01 00 23 39     addi    r9,r3,1
+        32b0:   a6 03 29 7d     mtctr   r9
+        32b4:   00 00 00 60     nop
+        32b8:   fc ff 00 42     bdnz    32b4 <cdelay+0x10>
+        32bc:   20 00 80 4e     blr
+
+        notes on converting pseudo-assembler to actual:
+
+        * bdnz target (equivalent to: bc 16,0,target)
+        * Clear left immediate clrldi ra,rs,n (n < 64) rldicl ra,rs,0,n
+        * CTR mtctr Rx mtspr 9,Rx
+        """
+        pass
+
+    @unittest.skip("disable")
+    def test_0_litex_bios_cmp(self):
+        """litex bios cmp test
+        """
+        lst = [ "addis    26, 0, 21845",
+                "ori      26, 26, 21845",
+                "addi     5, 26, 0",
+                "rldicr  5,5,32,31",
+                "addi     5, 26, 0",
+                "cmp     0, 0, 5, 26",
+                "bc      12, 2, 28",
+                "addis   6, 0, 1",
+                "addis   7, 0, 1",
+               ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [5,6,7,26], initial_mem={})
+
+    @unittest.skip("disable")
+    def test_0_litex_bios_r1(self):
+        """litex bios IMM64 macro test
+        """
+        lst = [ "addis     1,0,0",
+                 "ori     1,1,0",
+                 "rldicr  1,1,32,31",
+                 "oris    1,1,256",
+                 "ori     1,1,3832",
+               ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1], initial_mem={})
+
+    @unittest.skip("disable")
+    def test_0_litex_trampoline(self):
+        lst = ["tdi   0,0,0x48",
+               "b     0x28",
+               "mfmsr r11",
+               "bcl 20,31,4",
+               "mflr r10",
+               "addi r10,r10,20",
+               "mthsrr0 r10",
+               "mthsrr1 r11",
+               "hrfid",
+               ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [], initial_mem={})
+
+    @unittest.skip("disable")
+    def test_0_cmp(self):
+        lst = ["addi 6, 0, 0x10",
+               "addi 7, 0, 0x05",
+               "subf. 1, 6, 7",
+               "cmp cr2, 1, 6, 7",
+               ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1])
+
+    @unittest.skip("disable")
+    def test_example(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x1234",
+               "add  3, 1, 2",
+               "and  4, 1, 2"]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1, 2, 3, 4])
+
+    @unittest.skip("disable")
+    def test_ldst(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x1234",
+               "stw  1, 0(2)",
+               "lwz  3, 0(2)"
+               ]
+        initial_mem = {0x1230: (0x5432123412345678, 8),
+                       0x1238: (0xabcdef0187654321, 8),
+                       }
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program,
+                                 [1, 2, 3],
+                                 initial_mem)
+
+    @unittest.skip("disable")
+    def test_ldst_update(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x1234",
+               "stwu  1, 0(2)",
+               "lwz  3, 0(2)"
+               ]
+        initial_mem = {0x1230: (0x5432123412345678, 8),
+                       0x1238: (0xabcdef0187654321, 8),
+                       }
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program,
+                                 [1, 2, 3],
+                                 initial_mem)
+
+    @unittest.skip("disable")
+    def test_ld_rev_ext(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x1234",
+               "addi 4, 0, 0x40",
+               "stw  1, 0x40(2)",
+               "lwbrx  3, 4, 2"]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    @unittest.skip("disable")
+    def test_st_rev_ext(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x1234",
+               "addi 4, 0, 0x40",
+               "stwbrx  1, 4, 2",
+               "lwzx  3, 4, 2"]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    @unittest.skip("disable")
+    def test_ldst_extended(self):
+        lst = ["addi 1, 0, 0x5678",
+               "addi 2, 0, 0x1234",
+               "addi 4, 0, 0x40",
+               "stw  1, 0x40(2)",
+               "lwzx  3, 4, 2"]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    @unittest.skip("disable")
+    def test_0_ldst_widths(self):
+        lst = ["addis 1, 0, 0xdead",
+               "ori 1, 1, 0xbeef",
+               "addi 2, 0, 0x1000",
+               "std 1, 0(2)",
+               "lbz 1, 5(2)",
+               "lhz 3, 4(2)",
+               "lwz 4, 4(2)",
+               "addi 5, 0, 0x12",
+               "stb 5, 5(2)",
+               "ld  5, 0(2)"]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1, 2, 3, 4, 5])
+
+    @unittest.skip("disable")
+    def test_sub(self):
+        lst = ["addi 1, 0, 0x1234",
+               "addi 2, 0, 0x5678",
+               "subf 3, 1, 2",
+               "subfic 4, 1, 0x1337",
+               "neg 5, 1"]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1, 2, 3, 4, 5])
+
+    @unittest.skip("disable")
+    def test_add_with_carry(self):
+        lst = ["addi 1, 0, 5",
+               "neg 1, 1",
+               "addi 2, 0, 7",
+               "neg 2, 2",
+               "addc 3, 2, 1",
+               "addi 3, 3, 1"
+               ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1, 2, 3])
+
+    @unittest.skip("disable")
+    def test_addis(self):
+        lst = ["addi 1, 0, 0x0FFF",
+               "addis 1, 1, 0x0F"
+               ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1])
+
+    @unittest.skip("broken")
+    def test_mulli(self):
+        lst = ["addi 1, 0, 3",
+               "mulli 1, 1, 2"
+               ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1])
+
+    #@unittest.skip("disable")
+    def test_crxor(self):
+        lst = ["addi 1, 0, 0x1004",
+               "addi 2, 0, 0x1008",
+               "addi 3, 0, 0x01ee",
+               "mtcrf 0b1111111, 3",
+               "crxor 3, 30, 4",
+               "mfcr 3",
+               ]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x1004
+        initial_regs[2] = 0x1008
+        initial_regs[3] = 0x01ee
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [3, 4])
+
+    #@unittest.skip("disable")
+    def test_crxor_2(self):
+        lst = ["addi 1, 0, 0x1004",
+               "addi 2, 0, 0x1008",
+               "addi 3, 0, 0x01ee",
+               "mtcrf 0b1111111, 3",
+               "crxor 29, 30, 29",
+               "mfcr 3",
+               ]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x1004
+        initial_regs[2] = 0x1008
+        initial_regs[3] = 0x01ee
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [3, 4])
+
+    #@unittest.skip("disable")
+    def test_crnand(self):
+        lst = ["addi 1, 0, 0x1004",
+               "addi 2, 0, 0x1008",
+               "addi 3, 0, 0x01ee",
+               "mtcrf 0b1111111, 3",
+               "crnand 3, 30, 4",
+               "mfcr 3",
+               ]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x1004
+        initial_regs[2] = 0x1008
+        initial_regs[3] = 0x01ee
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [3, 4])
+
+    #@unittest.skip("disable")
+    def test_crnand_2(self):
+        lst = ["addi 1, 0, 0x1004",
+               "addi 2, 0, 0x1008",
+               "addi 3, 0, 0x01ee",
+               "mtcrf 0b1111111, 3",
+               "crnand 28, 30, 29",
+               "mfcr 3",
+               ]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x1004
+        initial_regs[2] = 0x1008
+        initial_regs[3] = 0x01ee
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [3, 4])
+
+    @unittest.skip("disable")
+    def test_isel_1(self):
+        lst = ["addi 1, 0, 0x1004",
+               "addi 2, 0, 0x1008",
+               "addi 3, 0, 0x01ee",
+               "mtcrf 0b1111111, 3",
+               "isel 4, 1, 2, 2"
+               ]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x1004
+        initial_regs[2] = 0x1008
+        initial_regs[3] = 0x00ee
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [3, 4])
+
+    #@unittest.skip("disable")
+    def test_isel_2(self):
+        lst = ["addi 1, 0, 0x1004",
+               "addi 2, 0, 0x1008",
+               "addi 3, 0, 0x01ee",
+               "mtcrf 0b1111111, 3",
+               "isel 4, 1, 2, 30"
+               ]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x1004
+        initial_regs[2] = 0x1008
+        initial_regs[3] = 0x00ee
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [3, 4])
+
+    @unittest.skip("disable")
+    def test_isel_3(self):
+        lst = ["addi 1, 0, 0x1004",
+               "addi 2, 0, 0x1008",
+               "addi 3, 0, 0x01ee",
+               "mtcrf 0b1111111, 3",
+               "isel 4, 1, 2, 31"
+               ]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x1004
+        initial_regs[2] = 0x1008
+        initial_regs[3] = 0x00ee
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [3, 4])
+
+    @unittest.skip("disable")
+    def test_2_load_store(self):
+        lst = ["addi 1, 0, 0x1004",
+               "addi 2, 0, 0x1008",
+               "addi 3, 0, 0x00ee",
+               "stb 3, 1(2)",
+               "lbz 4, 1(2)",
+               ]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x1004
+        initial_regs[2] = 0x1008
+        initial_regs[3] = 0x00ee
+        initial_mem = {0x1000: (0x5432123412345678, 8),
+                       0x1008: (0xabcdef0187654321, 8),
+                       0x1020: (0x1828384822324252, 8),
+                       }
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [3, 4], initial_mem)
+
+    @unittest.skip("disable")
+    def test_3_load_store(self):
+        lst = ["addi 1, 0, 0x1004",
+               "addi 2, 0, 0x1002",
+               "addi 3, 0, 0x15eb",
+               "sth 4, 0(2)",
+               "lhz 4, 0(2)"]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x1004
+        initial_regs[2] = 0x1002
+        initial_regs[3] = 0x15eb
+        initial_mem = {0x1000: (0x5432123412345678, 8),
+                       0x1008: (0xabcdef0187654321, 8),
+                       0x1020: (0x1828384822324252, 8),
+                       }
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1, 2, 3, 4], initial_mem)
+
+    @unittest.skip("disable")
+    def test_nop(self):
+        lst = ["addi 1, 0, 0x1004",
+               "ori 0,0,0", # "preferred" form of nop
+               "addi 3, 0, 0x15eb",
+              ]
+        initial_regs = [0] * 32
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1, 3])
+
+    @unittest.skip("disable")
+    def test_zero_illegal(self):
+        lst = bytes([0x10,0x00,0x20,0x39,
+                     0x0,0x0,0x0,0x0,
+                     0x0,0x0,0x0,0x0 ])
+        disassembly = ["addi 9, 0, 0x10",
+                       "nop", # not quite
+                       "nop"] # not quite
+        initial_regs = [0] * 32
+        with Program(lst, bigendian) as program:
+            program.assembly = '\n'.join(disassembly) + '\n' # XXX HACK!
+            self.run_tst_program(program, [1, 3])
+
+    def test_loop(self):
+        """
+        in godbolt.org:
+        register unsigned long i asm ("r9");
+        void square(void) {
+            i = 16;
+            do {
+                i = i - 1;
+            } while (i != 12);
+        }
+        """
+        lst = ["addi 9, 0, 0x10",  # i = 16
+               "addi 9,9,-1",    # i = i - 1
+               "cmpi 2,1,9,12",     # compare 9 to value 12, store in CR2
+               "bc 4,10,-8"         # branch if CR2 "test was != 12"
+               ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [9], initial_mem={})
+
+    @unittest.skip("disable")
+    def test_30_addis(self):
+        lst = [  # "addi 0, 0, 5",
+            "addis 12, 0, 0",
+        ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [12])
+
+    @unittest.skip("disable")
+    def test_31_addis(self):
+        """tests for zero not in register zero
+        """
+        lst = [  "rldicr  0, 0, 32, 31",
+                 "oris    0, 0, 32767",
+                 "ori     0, 0, 65535",
+                 "addis 1, 0, 1",
+                 "ori     1, 1, 515",
+                 "rldicr  1, 1, 32, 31",
+                 "oris    1, 1, 1029",
+                 "ori     1, 1, 1543",
+                 "addis   2, 0, -1",
+        ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [0, 1, 2])
+
+    def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
+                        initial_mem=None):
+        initial_regs = [0] * 32
+        tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
+                      initial_mem, 0)
+        self.test_data.append(tc)
+
+
+class DecoderBase:
+
+    def run_tst(self, generator, initial_mem=None, initial_pc=0):
+        m = Module()
+        comb = m.d.comb
+
+        gen = list(generator.generate_instructions())
+        insn_code = generator.assembly.splitlines()
+        instructions = list(zip(gen, insn_code))
+
+        pdecode = create_pdecode()
+        m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
+
+        # place program at requested address
+        gen = (initial_pc, gen)
+
+        simulator = ISA(pdecode2, [0] * 32, {}, 0, initial_mem, 0,
+                        initial_insns=gen, respect_pc=True,
+                        disassembly=insn_code,
+                        initial_pc=initial_pc,
+                        bigendian=bigendian)
+
+        sim = Simulator(m)
+
+        def process():
+            # yield pdecode2.dec.bigendian.eq(bigendian)
+            yield Settle()
+
+            while True:
+                try:
+                    yield from simulator.setup_one()
+                except KeyError:  # indicates instruction not in imem: stop
+                    break
+                yield Settle()
+                yield from simulator.execute_one()
+                yield Settle()
+
+        sim.add_process(process)
+        with sim.write_vcd("pdecode_simulator.vcd"):
+            sim.run()
+
+        return simulator
+
+    def run_tst_program(self, prog, reglist, initial_mem=None,
+                        extra_break_addr=None):
+        import sys
+        simulator = self.run_tst(prog, initial_mem=initial_mem,
+                                 initial_pc=0x20000000)
+        prog.reset()
+        with run_program(prog, initial_mem, extra_break_addr,
+                         bigendian=bigendian) as q:
+            self.qemu_register_compare(simulator, q, reglist)
+            self.qemu_mem_compare(simulator, q, True)
+        print(simulator.gpr.dump())
+
+    def qemu_mem_compare(self, sim, qemu, check=True):
+        if False:  # disable convenient large interesting debugging memory dump
+            addr = 0x0
+            qmemdump = qemu.get_mem(addr, 2048)
+            for i in range(len(qmemdump)):
+                s = hex(int(qmemdump[i]))
+                print("qemu mem %06x %s" % (addr+i*8, s))
+        for k, v in sim.mem.mem.items():
+            qmemdump = qemu.get_mem(k*8, 8)
+            s = hex(int(qmemdump[0]))[2:]
+            print("qemu mem %06x %16s" % (k*8, s))
+        for k, v in sim.mem.mem.items():
+            print("sim mem  %06x %016x" % (k*8, v))
+        if not check:
+            return
+        for k, v in sim.mem.mem.items():
+            qmemdump = qemu.get_mem(k*8, 1)
+            self.assertEqual(int(qmemdump[0]), v)
+
+    def qemu_register_compare(self, sim, qemu, regs):
+        qpc, qxer, qcr = qemu.get_pc(), qemu.get_xer(), qemu.get_cr()
+        sim_cr = sim.cr.value
+        sim_pc = sim.pc.CIA.value
+        sim_xer = sim.spr['XER'].value
+        print("qemu pc", hex(qpc))
+        print("qemu cr", hex(qcr))
+        print("qemu xer", bin(qxer))
+        print("sim nia", hex(sim.pc.NIA.value))
+        print("sim pc", hex(sim.pc.CIA.value))
+        print("sim cr", hex(sim_cr))
+        print("sim xer", hex(sim_xer))
+        self.assertEqual(qpc, sim_pc)
+        for reg in regs:
+            qemu_val = qemu.get_register(reg)
+            sim_val = sim.gpr(reg).value
+            self.assertEqual(qemu_val, sim_val,
+                             "expect %x got %x" % (qemu_val, sim_val))
+        self.assertEqual(qcr, sim_cr)
+
+
+class DecoderTestCase(DecoderBase, GeneralTestCases):
+    pass
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/src/openpower/simulator/test_trap_sim.py b/src/openpower/simulator/test_trap_sim.py
new file mode 100644 (file)
index 0000000..1c79482
--- /dev/null
@@ -0,0 +1,54 @@
+from nmigen import Module, Signal
+from nmigen.back.pysim import Simulator, Delay, Settle
+from nmutil.formaltest import FHDLTestCase
+import unittest
+from soc.decoder.power_decoder import (create_pdecode)
+from soc.decoder.power_enums import (Function, MicrOp,
+                                     In1Sel, In2Sel, In3Sel,
+                                     OutSel, RC, LdstLen, CryIn,
+                                     single_bit_flags, Form, SPR,
+                                     get_signal_name, get_csv)
+from soc.decoder.power_decoder2 import (PowerDecode2)
+from soc.simulator.program import Program
+from soc.simulator.qemu import run_program
+from soc.decoder.isa.all import ISA
+from soc.fu.test.common import TestCase
+from soc.simulator.test_sim import DecoderBase
+from soc.config.endian import bigendian
+
+
+class TrapSimTestCases(FHDLTestCase):
+    test_data = []
+
+    def __init__(self, name="div"):
+        super().__init__(name)
+        self.test_name = name
+
+    def test_0_not_twi(self):
+        lst = ["addi 1, 0, 0x5678",
+               "twi  4, 1, 0x5677",
+               ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1])
+
+    def test_1_twi_eq(self):
+        lst = ["addi 1, 0, 0x5678",
+               "twi  4, 1, 0x5678",
+               ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [1])
+
+    def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
+                                    initial_mem=None):
+        initial_regs = [0] * 32
+        tc = TestCase(prog, self.test_name, initial_regs, initial_sprs, 0,
+                                            initial_mem, 0)
+        self.test_data.append(tc)
+
+
+class TrapDecoderTestCase(DecoderBase, TrapSimTestCases):
+    pass
+
+
+if __name__ == "__main__":
+    unittest.main()