bug #672: shorten pospopcount further
[openpower-isa.git] / src / openpower / decoder / isa / test_caller_svp64_pospopcount.py
1 """Implementation of chacha20 core in SVP64
2 Copyright (C) 2022,2023 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 Licensed under the LGPLv3+
4 Funded by NLnet NGI-ASSURE under EU grant agreement No 957073.
5 * https://nlnet.nl/project/LibreSOC-GigabitRouter/
6 * https://bugs.libre-soc.org/show_bug.cgi?id=965
7 * https://libre-soc.org/openpower/sv/cookbook/pospopcount/
8 """
9
10 import unittest
11 from copy import deepcopy
12
13 from nmutil.formaltest import FHDLTestCase
14 from openpower.decoder.isa.test_caller import run_tst
15 from openpower.decoder.selectable_int import SelectableInt
16 from openpower.simulator.program import Program
17 from openpower.insndb.asm import SVP64Asm
18
19
20 def write_byte(mem, addr, val):
21 addr, offs = (addr // 8)*8, (addr % 8)*8
22 mask = (0xff << offs)
23 value = mem.get(addr, 0) & ~mask
24 value = value | (val << offs)
25 mem[addr] = value & 0xffff_ffff_ffff_ffff
26
27
28
29 class PosPopCountTestCase(FHDLTestCase):
30
31 def _check_regs(self, sim, expected):
32 for i in range(32):
33 self.assertEqual(sim.gpr(i), SelectableInt(expected[i], 64))
34
35 def test_sv_pospopcount(self):
36 """positional popcount
37 """
38 lst = SVP64Asm(
39 [
40 "mtspr 9, 3", # move r3 to CTR
41 # VL = MIN(CTR,MAXVL=8), Rc=1 (CR0 set if CTR ends)
42 "setvl 3,0,8,0,1,1", # set MVL=8, VL=CTR and CR0 (Rc=1)
43 # load VL bytes (update r4 addr) but compressed (dw=8)
44 "addi 6, 0, 0", # initialise r6 to zero
45 "sv.lbzu/pi/dw=8 *6, 1(4)", # should be /lf here as well
46 # gather performs the transpose (which gets us to positional..)
47 "gbbd 8,6",
48 # now those bits have been turned around,
49 "setvl 0,0,8,0,1,1", # set MVL=VL=8
50 "sv.popcntd/sw=8 *24,*8", # do the (now transposed) popcount
51 "sv.add *16,*16,*24",
52 # branch back if still CTR
53 "sv.bc/all 16, *0, -0x28", # CTR mode, reduce VL by CTR
54 ]
55 )
56 lst = list(lst)
57
58 tst_array = [23,19,25,189,76,255,32,191,67,205,0,39,107]
59 #tst_array = [1,2,3,4,5,6,7,8,9,10,11,12,13]
60 #tst_array = [254] * 10
61 #tst_array = [1,2,3,4,5,6,7,8,9,10,11,12,13]
62 #tst_array = [1,2,3,4,5,6,7,8,9,10,11,12,13]
63 #tst_array = [1,2,3,4,5,6,7,8,9]
64 #tst_array = list(range(240))
65 initial_regs = [0] * 64
66 initial_regs[3] = len(tst_array)
67 initial_regs[4] = 256-8 # load address
68
69 # some memory with identifying garbage in it
70 initial_mem = {16: 0xf0f1_f2f3_f4f5_f6f7,
71 24: 0x4041_4243_4445_4647,
72 40: 0x8081_8283_8485_8687,
73 48: 0x9091_9293_9495_9697,
74 248: 0xffff_aaaa_cccc_eeee,
75 256: 0xa0a1_a2a3_a4a5_a6a7,
76 }
77
78 # overwrite the garbage with the test data
79 for i, c in enumerate(tst_array):
80 write_byte(initial_mem, initial_regs[4]+i, c)
81
82 for i, c in enumerate(tst_array):
83 print ("array", i, bin(c), c)
84
85 # now get the expected results: do a simple pospopcount
86 expected = [0]*8
87 for c in tst_array:
88 for j in range(8):
89 expected[j] += (c >> j) & 1
90
91 with Program(lst, bigendian=False) as program:
92 sim = self.run_tst_program(program, initial_mem=initial_mem,
93 initial_regs=initial_regs)
94 mem = sim.mem.dump(printout=True, asciidump=True)
95 print (mem)
96 # contents of memory expected at:
97 # element 0: r1=0x10, D=24, => EA = 0x10+24*0 = 16 (0x10)
98 # element 1: r1=0x10, D=24, => EA = 0x10+24*1 = 40 (0x28)
99 # therefore, at address 0x10 ==> 0x1234
100 # therefore, at address 0x28 ==> 0x1235
101 for (k, val) in enumerate(expected):
102 print("idx, count, reg", k, val, sim.gpr(k+16).value)
103 for (k, val) in enumerate(expected):
104 self.assertEqual(val, sim.gpr(k+16))
105
106 def run_tst_program(self, prog, initial_regs=None,
107 svstate=None, initial_fprs=None,
108 initial_mem=None):
109 if initial_regs is None:
110 initial_regs = [0] * 32
111 if initial_fprs is None:
112 initial_fprs = [0] * 32
113 simulator = run_tst(prog, initial_regs, svstate=svstate,
114 initial_fprs=initial_fprs,
115 mem=initial_mem)
116 print("GPRs")
117 simulator.gpr.dump()
118 return simulator
119
120
121 if __name__ == "__main__":
122 unittest.main()