sorting out qemu co-simulation to read/write FP regs
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 1 Jun 2021 02:59:34 +0000 (03:59 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 1 Jun 2021 02:59:34 +0000 (03:59 +0100)
12 files changed:
src/openpower/decoder/helpers.py
src/openpower/decoder/isa/pypowersim.py
src/openpower/simulator/qemu.py
src/test/basic_pypowersim/Makefile
src/test/basic_pypowersim_fp/.gitignore [new file with mode: 0644]
src/test/basic_pypowersim_fp/Makefile [new file with mode: 0644]
src/test/basic_pypowersim_fp/fpr.list [new file with mode: 0644]
src/test/basic_pypowersim_fp/gpr.list [new file with mode: 0644]
src/test/basic_pypowersim_fp/memmap [new file with mode: 0644]
src/test/basic_pypowersim_fp/qemu_launch.sh [new file with mode: 0755]
src/test/basic_pypowersim_fp/testfp.s [new file with mode: 0644]
src/test/basic_pypowersim_fp/writefp.sh [new file with mode: 0755]

index 40d05959258782e60156ecc24e88c0249da2b088..3f0c7fcd875f15070969638faf89258bddd1255a 100644 (file)
@@ -175,7 +175,7 @@ def DOUBLE(WORD):
         FRT[5:64] = selectconcat(WORD[2:32], z29)
 
     # Denormalized Operand
-    if e.value  == 0 and m.value  != 0:
+    if e.value  == 0 and m.value != 0:
         log ("denormalised")
         sign = WORD[0]
         exp = -126
@@ -210,7 +210,7 @@ def SINGLE(FRS):
     WORD = SelectableInt(0, 32)
 
     e = FRS[1:12]
-    m = FRS[9:32]
+    m = FRS[12:64]
     s = FRS[0]
 
     log ("SINGLE", FRS)
@@ -218,16 +218,18 @@ def SINGLE(FRS):
 
     #No Denormalization Required (includes Zero / Infinity / NaN)
     if e.value > 896 or FRS[1:64].value  == 0:
+          log("nodenorm", FRS[0:2].value, hex(FRS[5:35].value))
           WORD[0:2] = FRS[0:2]
           WORD[2:32] = FRS[5:35]
 
     #Denormalization Required
-    if e.value  >= 874 and e.value  <= 896:
+    if e.value  >= 874 and e.value <= 896:
           sign = FRS[0]
-          exp = e - 1023
+          exp = e.value - 1023
           frac = selectconcat(SelectableInt(1, 1), FRS[12:64])
+          log("exp, fract", exp, hex(frac.value))
           # denormalize operand
-          while exp.value  < -126:
+          while exp < -126:
               frac[0:53] = selectconcat(SelectableInt(0, 1), frac[0:52])
               exp = exp + 1
           WORD[0] = sign
index 02f2685bf782f67876c625e7d22f2762525b2853..040fb64dfa38fe03a481036aaa8ef599be9232ed 100644 (file)
@@ -137,15 +137,10 @@ def run_tst(args, generator, qemu,
         log("qemu program", generator.binfile.name)
         qemu = run_program(generator, initial_mem=mem, 
                 bigendian=False, start_addr=initial_pc,
-                continuous_run=False, initial_sprs=initial_sprs)
-        if initial_regs is not None:
-            for reg, val in enumerate(initial_regs):
-                qemu.set_gpr(reg, val)
-        if initial_fprs is not None:
-            for fpr, val in enumerate(initial_fprs):
-                qemu.set_fpr(fpr, val)
+                continuous_run=False, initial_sprs=initial_sprs,
+                initial_regs=initial_regs, initial_fprs=initial_fprs)
         for reg, val in qemu._get_registers().items():
-            print (reg, hex(val))
+            log ("qemu reg", reg, hex(val))
 
     m = Module()
     comb = m.d.comb
@@ -359,6 +354,8 @@ def run_simulation():
                 qmem = qemu.get_mem(offs, length)
                 for i, mem in enumerate(qmem):
                     log(hex(offs+i*8), hex(mem))
+                for reg, val in qemu._get_registers().items():
+                    log ("qemu reg", reg, hex(val))
 
         # cleanup
         if qemu:
index de108649c2b05a78de7d566796fc7efe466c90dd..3c9238ae89d0a3ed8ed3d0d7480448ac55e1c31a 100644 (file)
@@ -20,6 +20,15 @@ def swap_order(x, nbytes):
     return x
 
 
+def find_uint128(val):
+    print (val[1:])
+    assert val[1:].startswith('uint128 =')
+    val = val.split("=")[1]
+    val = val.split(',')[0].strip()
+    val = int(val, 0)
+    return swap_order(val, 16)
+
+
 class QemuController:
     def __init__(self, kernel, bigendian):
         if bigendian:
@@ -108,9 +117,12 @@ class QemuController:
                 for rdict in rlist:
                     regnum = int(rdict['number'])
                     regval = rdict['value']
+                    print ("reg get", regnum, rdict)
                     if regval.startswith("{"): # TODO, VSX
-                        continue
-                    self._reg_cache["x %d" % regnum] = int(regval, 0)
+                        regval = find_uint128(regval)
+                    else:
+                        regval = int(regval, 0)
+                    self._reg_cache["x %d" % regnum] = regval
         return self._reg_cache
 
     def _get_register(self, fmt):
@@ -157,7 +169,19 @@ class QemuController:
 
     def set_fpr(self, reg, val):
         self._rcache_trash('x %d' % (reg+32))
-        self.gdb_eval('$fp%d=%d' % (reg, val))
+        self._rcache_trash('x %d' % (reg+471))
+        # grr, fp set cannot enter raw data
+        #val = swap_order(val, 8)
+        #val = 1<<31
+        valhi = (val >> 32) & 0xffffffff
+        vallo = val & 0xffffffff
+        res = self.gdb_eval('$vs%d.v4_int32={0,0,0x%x,0x%x}' % \
+                            (reg, vallo, valhi))
+        #res = self.gdb_eval('$fp%d=1.0')
+        #res = self.gdb_eval('$vs%d.uint128=0x%x' % \
+        #                    (reg, val))
+        print ("set fpr", reg, hex(val), res)
+        print ("get fpr", hex(self.get_fpr(reg)))
 
     def set_pc(self, pc):
         self._rcache_trash('x 64')
@@ -221,7 +245,8 @@ class QemuController:
 
 def run_program(program, initial_mem=None, extra_break_addr=None,
                 bigendian=False, start_addr=0x20000000, init_endian=True,
-                continuous_run=True, initial_sprs=None):
+                continuous_run=True, initial_sprs=None,
+                initial_regs=None, initial_fprs=None):
     q = QemuController(program.binfile.name, bigendian)
     q.connect()
     q.set_endian(init_endian)  # easier to set variables this way
@@ -273,9 +298,25 @@ def run_program(program, initial_mem=None, extra_break_addr=None,
         msr = msr & ((1 << 53)-1)
     else:
         msr |= (1 << 13)
+    #msr = 0x4000000000009
+
     q.set_msr(msr)
     print("msr set to", hex(msr), bin(msr))
 
+    # upload regs
+    if initial_regs:
+        for i, reg in enumerate(initial_regs):
+            if reg != 0:
+                q.set_gpr(i, reg)
+    if initial_fprs:
+        if isinstance(initial_fprs, dict):
+            for i, reg in initial_fprs.items():
+                q.set_fpr(i, reg)
+        else:
+            for i, reg in enumerate(initial_fprs):
+                if reg != 0:
+                    q.set_fpr(i, reg)
+
     # can't do many of these - lr, ctr, etc. etc. later, just LR for now
     if initial_sprs:
         lr = initial_sprs.get('lr', None)
index c4cbc4df4baf03bffc23b246e8c80173436d51e6..b9ef925ef47470838c2745add445a71284a4f8d2 100644 (file)
@@ -1,4 +1,4 @@
-TOOLCHAIN=powerpc64le-linux-gnu
+TOOLCHAIN=powerpc64-linux-gnu
 CC=$(TOOLCHAIN)-gcc
 AS=$(TOOLCHAIN)-as
 AFLAGS=-mpwr9
@@ -8,11 +8,7 @@ all: sim
 sim: kernel.bin
        echo -n -e \\0060\\0000\\0061\\0000 > test.bin
        echo -n -e \\0060\\0000\\0061\\0000 >> test.bin
-       pypowersim -q --load test.bin:0 \
-                  -p 0x20000000 \
-               --dump testout.bin:0x20000100:8 \
-               --dump testout2.bin:0x0:16 \
-               -g gpr.list -i kernel.bin
+       pypowersim --load test.bin:0 -g gpr.list -i kernel.bin
 
 clean:
        rm *.o *.elf *.bin
diff --git a/src/test/basic_pypowersim_fp/.gitignore b/src/test/basic_pypowersim_fp/.gitignore
new file mode 100644 (file)
index 0000000..9cd5496
--- /dev/null
@@ -0,0 +1,3 @@
+*.bin
+*.elf
+*.o
diff --git a/src/test/basic_pypowersim_fp/Makefile b/src/test/basic_pypowersim_fp/Makefile
new file mode 100644 (file)
index 0000000..583285a
--- /dev/null
@@ -0,0 +1,26 @@
+TOOLCHAIN=powerpc64le-linux-gnu
+CC=$(TOOLCHAIN)-gcc
+AS=$(TOOLCHAIN)-as
+AFLAGS=-mpwr9
+
+all: sim
+
+sim: kernel.bin
+       ./writefp.sh
+       pypowersim -q --load testdata.bin:0 \
+                  -p 0x20000000 \
+               --dump testout.bin:0x20000100:8 \
+               --dump testout2.bin:0x0:16 \
+               -g gpr.list -f fpr.list -i kernel.bin
+
+clean:
+       rm *.o *.elf *.bin
+
+kernel.elf: testfp.o
+       $(TOOLCHAIN)-ld $^ -EL -o $@ -T memmap
+
+kernel.bin: kernel.elf
+       $(TOOLCHAIN)-objcopy $< -I elf64-little -O binary $@
+
+%.o: %.s
+       $(AS) $(AFLAGS) -c $< -le -o $@
diff --git a/src/test/basic_pypowersim_fp/fpr.list b/src/test/basic_pypowersim_fp/fpr.list
new file mode 100644 (file)
index 0000000..53b8edd
--- /dev/null
@@ -0,0 +1,4 @@
+0:   0x40404cccc0000000
+9:   0x4040266660000000
+10:  0x3ff0000000000000 
+#10: 0xf3f
diff --git a/src/test/basic_pypowersim_fp/gpr.list b/src/test/basic_pypowersim_fp/gpr.list
new file mode 100644 (file)
index 0000000..8b29e3b
--- /dev/null
@@ -0,0 +1,3 @@
+8: 0x5005
+12: 0b1010
+15: 5
diff --git a/src/test/basic_pypowersim_fp/memmap b/src/test/basic_pypowersim_fp/memmap
new file mode 100644 (file)
index 0000000..8cc1a16
--- /dev/null
@@ -0,0 +1,11 @@
+
+MEMORY
+{
+    ram  : ORIGIN = 0x20000000, LENGTH = 128M
+}
+
+SECTIONS
+{
+   .text : { *(.text*) } > ram
+   .bss  : { *(.text*) } > ram
+}
diff --git a/src/test/basic_pypowersim_fp/qemu_launch.sh b/src/test/basic_pypowersim_fp/qemu_launch.sh
new file mode 100755 (executable)
index 0000000..2b4c3de
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+qemu-system-ppc64le -machine powernv9 \
+                  -cpu power9 \
+                  -nographic \
+                  -s -S -m size=4096 \
+                  -kernel kernel.bin > /dev/null &
diff --git a/src/test/basic_pypowersim_fp/testfp.s b/src/test/basic_pypowersim_fp/testfp.s
new file mode 100644 (file)
index 0000000..e3f97b2
--- /dev/null
@@ -0,0 +1,4 @@
+       lfsx 1, 1, 0
+       stfsu 1, 16(1)
+       stfsu 9, 32(2)
+       stfsu 10, 8(3)
diff --git a/src/test/basic_pypowersim_fp/writefp.sh b/src/test/basic_pypowersim_fp/writefp.sh
new file mode 100755 (executable)
index 0000000..a115f9b
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+echo -n -e '\x66\x66\x02\x42' > testdata.bin
+echo -n -e '\x00\x00\x80\x3f' >> testdata.bin
+