From 8c9c9eb5767416057fc00824568008a96bc72c99 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Tue, 1 Jun 2021 03:59:34 +0100 Subject: [PATCH] sorting out qemu co-simulation to read/write FP regs --- src/openpower/decoder/helpers.py | 12 ++--- src/openpower/decoder/isa/pypowersim.py | 13 +++--- src/openpower/simulator/qemu.py | 49 +++++++++++++++++++-- src/test/basic_pypowersim/Makefile | 8 +--- src/test/basic_pypowersim_fp/.gitignore | 3 ++ src/test/basic_pypowersim_fp/Makefile | 26 +++++++++++ src/test/basic_pypowersim_fp/fpr.list | 4 ++ src/test/basic_pypowersim_fp/gpr.list | 3 ++ src/test/basic_pypowersim_fp/memmap | 11 +++++ src/test/basic_pypowersim_fp/qemu_launch.sh | 6 +++ src/test/basic_pypowersim_fp/testfp.s | 4 ++ src/test/basic_pypowersim_fp/writefp.sh | 4 ++ 12 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 src/test/basic_pypowersim_fp/.gitignore create mode 100644 src/test/basic_pypowersim_fp/Makefile create mode 100644 src/test/basic_pypowersim_fp/fpr.list create mode 100644 src/test/basic_pypowersim_fp/gpr.list create mode 100644 src/test/basic_pypowersim_fp/memmap create mode 100755 src/test/basic_pypowersim_fp/qemu_launch.sh create mode 100644 src/test/basic_pypowersim_fp/testfp.s create mode 100755 src/test/basic_pypowersim_fp/writefp.sh diff --git a/src/openpower/decoder/helpers.py b/src/openpower/decoder/helpers.py index 40d05959..3f0c7fcd 100644 --- a/src/openpower/decoder/helpers.py +++ b/src/openpower/decoder/helpers.py @@ -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 diff --git a/src/openpower/decoder/isa/pypowersim.py b/src/openpower/decoder/isa/pypowersim.py index 02f2685b..040fb64d 100644 --- a/src/openpower/decoder/isa/pypowersim.py +++ b/src/openpower/decoder/isa/pypowersim.py @@ -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: diff --git a/src/openpower/simulator/qemu.py b/src/openpower/simulator/qemu.py index de108649..3c9238ae 100644 --- a/src/openpower/simulator/qemu.py +++ b/src/openpower/simulator/qemu.py @@ -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) diff --git a/src/test/basic_pypowersim/Makefile b/src/test/basic_pypowersim/Makefile index c4cbc4df..b9ef925e 100644 --- a/src/test/basic_pypowersim/Makefile +++ b/src/test/basic_pypowersim/Makefile @@ -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 index 00000000..9cd5496e --- /dev/null +++ b/src/test/basic_pypowersim_fp/.gitignore @@ -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 index 00000000..583285af --- /dev/null +++ b/src/test/basic_pypowersim_fp/Makefile @@ -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 index 00000000..53b8edd2 --- /dev/null +++ b/src/test/basic_pypowersim_fp/fpr.list @@ -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 index 00000000..8b29e3be --- /dev/null +++ b/src/test/basic_pypowersim_fp/gpr.list @@ -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 index 00000000..8cc1a16e --- /dev/null +++ b/src/test/basic_pypowersim_fp/memmap @@ -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 index 00000000..2b4c3dee --- /dev/null +++ b/src/test/basic_pypowersim_fp/qemu_launch.sh @@ -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 index 00000000..e3f97b2b --- /dev/null +++ b/src/test/basic_pypowersim_fp/testfp.s @@ -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 index 00000000..a115f9b3 --- /dev/null +++ b/src/test/basic_pypowersim_fp/writefp.sh @@ -0,0 +1,4 @@ +#!/bin/bash +echo -n -e '\x66\x66\x02\x42' > testdata.bin +echo -n -e '\x00\x00\x80\x3f' >> testdata.bin + -- 2.30.2