format code
[soc.git] / src / soc / decoder / helpers.py
1 import unittest
2 from soc.decoder.selectable_int import SelectableInt, onebit
3 from nmutil.divmod import trunc_divs, trunc_rems
4 from operator import floordiv, mod
5 from soc.decoder.selectable_int import selectltu as ltu
6 from soc.decoder.selectable_int import selectgtu as gtu
7
8 trunc_div = floordiv
9 trunc_rem = mod
10 DIVS = trunc_divs
11 MODS = trunc_rems
12
13 """
14 Links:
15 * https://bugs.libre-soc.org/show_bug.cgi?id=324 - add trunc_div and trunc_rem
16 """
17
18
19 def exts(value, bits):
20 sign = 1 << (bits - 1)
21 return (value & (sign - 1)) - (value & sign)
22
23
24 def EXTS(value):
25 """ extends sign bit out from current MSB to all 256 bits
26 """
27 assert isinstance(value, SelectableInt)
28 return SelectableInt(exts(value.value, value.bits) & ((1 << 256)-1), 256)
29
30
31 def EXTS64(value):
32 """ extends sign bit out from current MSB to 64 bits
33 """
34 assert isinstance(value, SelectableInt)
35 return SelectableInt(exts(value.value, value.bits) & ((1 << 64)-1), 64)
36
37
38 # signed version of MUL
39 def MULS(a, b):
40 a_s = a.value & (1 << (a.bits-1)) != 0
41 b_s = b.value & (1 << (b.bits-1)) != 0
42 result = abs(a) * abs(b)
43 print("MULS", result, a_s, b_s)
44 if a_s == b_s:
45 return result
46 return -result
47
48
49 # XXX should this explicitly extend from 32 to 64?
50 def EXTZ64(value):
51 if isinstance(value, SelectableInt):
52 value = value.value
53 return SelectableInt(value & ((1 << 32)-1), 64)
54
55
56 def rotl(value, bits, wordlen):
57 if isinstance(bits, SelectableInt):
58 bits = bits.value
59 mask = (1 << wordlen) - 1
60 bits = bits & (wordlen - 1)
61 return ((value << bits) | (value >> (wordlen-bits))) & mask
62
63
64 def ROTL64(value, bits):
65 return rotl(value, bits, 64)
66
67
68 def ROTL32(value, bits):
69 if isinstance(value, SelectableInt):
70 value = SelectableInt(value.value, 64)
71 return rotl(value | (value << 32), bits, 64)
72
73
74 def MASK(x, y):
75 if isinstance(x, SelectableInt):
76 x = x.value
77 if isinstance(y, SelectableInt):
78 y = y.value
79 if x < y:
80 x = 64-x
81 y = 63-y
82 mask_a = ((1 << x) - 1) & ((1 << 64) - 1)
83 mask_b = ((1 << y) - 1) & ((1 << 64) - 1)
84 elif x == y:
85 return 1 << (63-x)
86 else:
87 x = 64-x
88 y = 63-y
89 mask_a = ((1 << x) - 1) & ((1 << 64) - 1)
90 mask_b = (~((1 << y) - 1)) & ((1 << 64) - 1)
91 return mask_a ^ mask_b
92
93
94 def ne(a, b):
95 return onebit(a != b)
96
97
98 def eq(a, b):
99 return onebit(a == b)
100
101
102 def gt(a, b):
103 return onebit(a > b)
104
105
106 def ge(a, b):
107 return onebit(a >= b)
108
109
110 def lt(a, b):
111 return onebit(a < b)
112
113
114 def le(a, b):
115 return onebit(a <= b)
116
117
118 def length(a):
119 return len(a)
120
121 # For these tests I tried to find power instructions that would let me
122 # isolate each of these helper operations. So for instance, when I was
123 # testing the MASK() function, I chose rlwinm and rldicl because if I
124 # set the shift equal to 0 and passed in a value of all ones, the
125 # result I got would be exactly the same as the output of MASK()
126
127
128 class HelperTests(unittest.TestCase):
129 def test_MASK(self):
130 # Verified using rlwinm, rldicl, rldicr in qemu
131 # li 1, -1
132 # rlwinm reg, 1, 0, 5, 15
133 self.assertHex(MASK(5+32, 15+32), 0x7ff0000)
134 # rlwinm reg, 1, 0, 15, 5
135 self.assertHex(MASK(15+32, 5+32), 0xfffffffffc01ffff)
136 self.assertHex(MASK(30+32, 2+32), 0xffffffffe0000003)
137 # rldicl reg, 1, 0, 37
138 self.assertHex(MASK(37, 63), 0x7ffffff)
139 self.assertHex(MASK(10, 63), 0x3fffffffffffff)
140 self.assertHex(MASK(58, 63), 0x3f)
141 # rldicr reg, 1, 0, 37
142 self.assertHex(MASK(0, 37), 0xfffffffffc000000)
143 self.assertHex(MASK(0, 10), 0xffe0000000000000)
144 self.assertHex(MASK(0, 58), 0xffffffffffffffe0)
145
146 # li 2, 5
147 # slw 1, 1, 2
148 self.assertHex(MASK(32, 63-5), 0xffffffe0)
149
150 self.assertHex(MASK(32, 33), 0xc0000000)
151 self.assertHex(MASK(32, 32), 0x80000000)
152 self.assertHex(MASK(33, 33), 0x40000000)
153
154 def test_ROTL64(self):
155 # r1 = 0xdeadbeef12345678
156 value = 0xdeadbeef12345678
157
158 # rldicl reg, 1, 10, 0
159 self.assertHex(ROTL64(value, 10), 0xb6fbbc48d159e37a)
160 # rldicl reg, 1, 35, 0
161 self.assertHex(ROTL64(value, 35), 0x91a2b3c6f56df778)
162 self.assertHex(ROTL64(value, 58), 0xe37ab6fbbc48d159)
163 self.assertHex(ROTL64(value, 22), 0xbbc48d159e37ab6f)
164
165 def test_ROTL32(self):
166 # r1 = 0xdeadbeef
167 value = 0xdeadbeef
168
169 # rlwinm reg, 1, 10, 0, 31
170 self.assertHex(ROTL32(value, 10), 0xb6fbbf7a)
171 # rlwinm reg, 1, 17, 0, 31
172 self.assertHex(ROTL32(value, 17), 0x7ddfbd5b)
173 self.assertHex(ROTL32(value, 25), 0xdfbd5b7d)
174 self.assertHex(ROTL32(value, 30), 0xf7ab6fbb)
175
176 def test_EXTS64(self):
177 value_a = SelectableInt(0xdeadbeef, 32) # r1
178 value_b = SelectableInt(0x73123456, 32) # r2
179 value_c = SelectableInt(0x80000000, 32) # r3
180
181 # extswsli reg, 1, 0
182 self.assertHex(EXTS64(value_a), 0xffffffffdeadbeef)
183 # extswsli reg, 2, 0
184 self.assertHex(EXTS64(value_b), SelectableInt(value_b.value, 64))
185 # extswsli reg, 3, 0
186 self.assertHex(EXTS64(value_c), 0xffffffff80000000)
187
188 def assertHex(self, a, b):
189 a_val = a
190 if isinstance(a, SelectableInt):
191 a_val = a.value
192 b_val = b
193 if isinstance(b, SelectableInt):
194 b_val = b.value
195 msg = "{:x} != {:x}".format(a_val, b_val)
196 return self.assertEqual(a, b, msg)
197
198
199 if __name__ == '__main__':
200 print(SelectableInt.__bases__)
201 unittest.main()