make truediv available to pseudocode
[openpower-isa.git] / src / openpower / decoder / helpers.py
1 import unittest
2 import struct
3 import sys
4 from openpower.decoder.selectable_int import (SelectableInt, onebit,
5 selectconcat, FieldSelectableInt)
6 from openpower.decoder.selectable_int import EFFECTIVELY_UNLIMITED as EU
7 from nmutil.divmod import trunc_divs, trunc_rems
8 from operator import floordiv, mod, truediv # truediv used by bfp_* functions
9 from openpower.decoder.selectable_int import selectltu as ltu
10 from openpower.decoder.selectable_int import selectgtu as gtu
11 from openpower.decoder.selectable_int import check_extsign
12 from openpower.fpscr import FPSCRState
13 from openpower.decoder.fp_working_format import (
14 BFPState, SelectableMSB0Fraction)
15
16 from openpower.util import log
17 import math
18
19 trunc_div = floordiv
20 trunc_rem = mod
21 DIVS = trunc_divs
22 MODS = trunc_rems
23
24 """
25 Links:
26 * https://bugs.libre-soc.org/show_bug.cgi?id=324 - add trunc_div and trunc_rem
27 * https://bugs.libre-soc.org/show_bug.cgi?id=671#c38 - RANGE (and bugfixes)
28 """
29
30
31 def RANGE(start, end):
32 if start > end:
33 # reverse direction
34 # auto-subtract-one (sigh) due to python range
35 return range(start, end-1, -1)
36 # auto-add-one (sigh) due to python range
37 return range(start, end+1)
38
39
40 def exts(value, bits):
41 sign = 1 << (bits - 1)
42 return (value & (sign - 1)) - (value & sign)
43
44
45 def EXTS(value):
46 """ extends sign bit out from current MSB to MAX limit bits
47 """
48 log("EXTS", value, type(value))
49 assert isinstance(value, SelectableInt)
50 return SelectableInt(exts(value.value, value.bits) & ((1 << EU)-1), EU)
51
52
53 def EXTZ(value):
54 """ zero extend to EFFECTIVELY_UNLIMITED bits
55 """
56 if isinstance(value, SelectableInt):
57 value = value.value
58 return SelectableInt(value & ((1 << EU) - 1), EU)
59
60
61 def EXTS64(value):
62 """ extends sign bit out from current MSB to 64 bits
63 """
64 assert isinstance(value, SelectableInt)
65 return SelectableInt(exts(value.value, value.bits) & ((1 << 64)-1), 64)
66
67
68 def EXTS128(value):
69 """ extends sign bit out from current MSB to 128 bits
70 """
71 assert isinstance(value, SelectableInt)
72 return SelectableInt(exts(value.value, value.bits) & ((1 << 128)-1), 128)
73
74
75 def copy_assign_rhs(inp):
76 """ implicitly added function call to all assignment RHSes.
77 This copies the passed-in value so later assignments to parts of the
78 LHS don't modify the RHS if it's a SelectableInt.
79
80 Example:
81 ```
82 # this needs to copy the SelectableInt instance in RA
83 # not just assign a reference to it to A
84 A <- RA
85 A[0] <- 1 # if the copy wasn't performed, we just modified RA too!
86 ```
87 """
88 if isinstance(inp, (str, int)):
89 return inp
90 if isinstance(inp, (SelectableInt, FieldSelectableInt)):
91 return SelectableInt(inp)
92 if isinstance(inp, BFPState):
93 return BFPState(inp)
94 if isinstance(inp, SelectableMSB0Fraction):
95 return SelectableMSB0Fraction(inp)
96 if isinstance(inp, tuple):
97 return tuple(map(copy_assign_rhs, inp))
98 if isinstance(inp, dict):
99 return {copy_assign_rhs(k): copy_assign_rhs(v) for k, v in inp.items()}
100 raise TypeError("tried to assign an unsupported type in pseudo-code",
101 repr(type(inp)))
102
103
104 # signed version of MUL
105 def MULS(a, b):
106 if isinstance(b, int):
107 b = SelectableInt(b, self.bits)
108 b = check_extsign(a, b)
109 a_s = a.value & (1 << (a.bits-1)) != 0
110 b_s = b.value & (1 << (b.bits-1)) != 0
111 result = abs(a) * abs(b)
112 log("MULS", result, a_s, b_s)
113 if a_s == b_s:
114 return result
115 return -result
116
117
118 # XXX should this explicitly extend from 32 to 64?
119 def EXTZ64(value):
120 if isinstance(value, SelectableInt):
121 value = value.value
122 return SelectableInt(value & ((1 << 32)-1), 64)
123
124
125 def rotl(value, bits, wordlen):
126 if isinstance(bits, SelectableInt):
127 bits = bits.value
128 mask = (1 << wordlen) - 1
129 bits = bits & (wordlen - 1)
130 return ((value << bits) | (value >> (wordlen-bits))) & mask
131
132
133 def SHL64(value, bits, wordlen=64):
134 if isinstance(bits, SelectableInt):
135 bits = bits.value
136 mask = (1 << wordlen) - 1
137 bits = bits & (wordlen - 1)
138 return SelectableInt((value << bits) & mask, 64)
139
140
141 def ne(a, b):
142 return onebit(a != b)
143
144
145 def eq(a, b):
146 return onebit(a == b)
147
148
149 def gt(a, b):
150 return onebit(a > b)
151
152
153 def ge(a, b):
154 return onebit(a >= b)
155
156
157 def lt(a, b):
158 return onebit(a < b)
159
160
161 def le(a, b):
162 return onebit(a <= b)
163
164
165 def length(a):
166 return len(a)
167
168
169 def undefined(v):
170 """ function that, for Power spec purposes, returns undefined bits of
171 the same shape as the input bits. however, for purposes of matching
172 POWER9's behavior returns the input bits unchanged. this effectively
173 "marks" (tags) locations in the v3.0B spec that need to be submitted
174 for clarification.
175 """
176 return v
177
178
179 def SINGLE(FRS):
180 """convert incoming FRS into 32-bit word. v3.0B p144 section 4.6.3
181 """
182 # result - WORD - start off all zeros
183 WORD = SelectableInt(0, 32)
184
185 e = FRS[1:12]
186 m = FRS[12:64]
187 s = FRS[0]
188
189 log("SINGLE", FRS)
190 log("s e m", s.value, e.value, m.value)
191
192 # No Denormalization Required (includes Zero / Infinity / NaN)
193 if e.value > 896 or FRS[1:64].value == 0:
194 log("nodenorm", FRS[0:2].value, hex(FRS[5:35].value))
195 WORD[0:2] = FRS[0:2]
196 WORD[2:32] = FRS[5:35]
197
198 # Denormalization Required
199 if e.value >= 874 and e.value <= 896:
200 sign = FRS[0]
201 exp = e.value - 1023
202 frac = selectconcat(SelectableInt(1, 1), FRS[12:64])
203 log("exp, fract", exp, hex(frac.value))
204 # denormalize operand
205 while exp < -126:
206 frac[0:53] = selectconcat(SelectableInt(0, 1), frac[0:52])
207 exp = exp + 1
208 WORD[0] = sign
209 WORD[1:9] = SelectableInt(0, 8)
210 WORD[9:32] = frac[1:24]
211 # else WORD = undefined # return zeros
212
213 log("WORD", WORD)
214
215 return WORD
216
217 # XXX NOTE: these are very quick hacked functions for utterly basic
218 # FP support
219
220
221 def signinv(res, sign):
222 if sign == 1:
223 return res
224 if sign == 0:
225 return 0.0
226 if sign == -1:
227 return -res
228
229
230 def fp32toselectable(flt):
231 """convert FP number to 32 bit SelectableInt
232 """
233 b = struct.pack("<f", flt)
234 val = int.from_bytes(b, byteorder='little', signed=False)
235 return SelectableInt(val, 32)
236
237
238 def fp64toselectable(flt):
239 """convert FP number to 64 bit SelectableInt
240 """
241 b = struct.pack("<d", flt)
242 val = int.from_bytes(b, byteorder='little', signed=False)
243 return SelectableInt(val, 64)
244
245
246 def _minmag(a, b):
247 if abs(a) < abs(b):
248 return a
249 if abs(a) > abs(b):
250 return b
251 return min(a, b)
252
253
254 def _maxmag(a, b):
255 if abs(a) < abs(b):
256 return b
257 if abs(a) > abs(b):
258 return a
259 return max(a, b)
260
261
262 class ISAFPHelpers:
263 # bfp32/64_OP naming mirrors that in the Power ISA spec.
264
265 def bfp64_ATAN2PI(self, a, b):
266 # FIXME: use proper implementation
267 return fp64toselectable(math.atan2(float(a), float(b)) / math.pi)
268
269 def bfp32_ATAN2PI(self, a, b):
270 # FIXME: use proper implementation
271 return fp32toselectable(math.atan2(float(a), float(b)) / math.pi)
272
273 def bfp64_ATAN2(self, a, b):
274 # FIXME: use proper implementation
275 return fp64toselectable(math.atan2(float(a), float(b)))
276
277 def bfp32_ATAN2(self, a, b):
278 # FIXME: use proper implementation
279 return fp32toselectable(math.atan2(float(a), float(b)))
280
281 def bfp64_HYPOT(self, a, b):
282 # FIXME: use proper implementation
283 return fp64toselectable(math.hypot(float(a), float(b)))
284
285 def bfp32_HYPOT(self, a, b):
286 # FIXME: use proper implementation
287 return fp32toselectable(math.hypot(float(a), float(b)))
288
289 def bfp64_MINNUM08(self, a, b):
290 # FIXME: use proper implementation
291 return fp64toselectable(min(float(a), float(b)))
292
293 def bfp32_MINNUM08(self, a, b):
294 # FIXME: use proper implementation
295 return fp32toselectable(min(float(a), float(b)))
296
297 def bfp64_MIN19(self, a, b):
298 # FIXME: use proper implementation
299 return fp64toselectable(min(float(a), float(b)))
300
301 def bfp32_MIN19(self, a, b):
302 # FIXME: use proper implementation
303 return fp32toselectable(min(float(a), float(b)))
304
305 def bfp64_MINNUM19(self, a, b):
306 # FIXME: use proper implementation
307 return fp64toselectable(min(float(a), float(b)))
308
309 def bfp32_MINNUM19(self, a, b):
310 # FIXME: use proper implementation
311 return fp32toselectable(min(float(a), float(b)))
312
313 def bfp64_MINC(self, a, b):
314 # FIXME: use proper implementation
315 return fp64toselectable(min(float(a), float(b)))
316
317 def bfp32_MINC(self, a, b):
318 # FIXME: use proper implementation
319 return fp32toselectable(min(float(a), float(b)))
320
321 def bfp64_MAXNUM08(self, a, b):
322 # FIXME: use proper implementation
323 return fp64toselectable(max(float(a), float(b)))
324
325 def bfp32_MAXNUM08(self, a, b):
326 # FIXME: use proper implementation
327 return fp32toselectable(max(float(a), float(b)))
328
329 def bfp64_MAX19(self, a, b):
330 # FIXME: use proper implementation
331 return fp64toselectable(max(float(a), float(b)))
332
333 def bfp32_MAX19(self, a, b):
334 # FIXME: use proper implementation
335 return fp32toselectable(max(float(a), float(b)))
336
337 def bfp64_MAXNUM19(self, a, b):
338 # FIXME: use proper implementation
339 return fp64toselectable(max(float(a), float(b)))
340
341 def bfp32_MAXNUM19(self, a, b):
342 # FIXME: use proper implementation
343 return fp32toselectable(max(float(a), float(b)))
344
345 def bfp64_MAXC(self, a, b):
346 # FIXME: use proper implementation
347 return fp64toselectable(max(float(a), float(b)))
348
349 def bfp32_MAXC(self, a, b):
350 # FIXME: use proper implementation
351 return fp32toselectable(max(float(a), float(b)))
352
353 def bfp64_MINMAGNUM08(self, a, b):
354 # FIXME: use proper implementation
355 return fp64toselectable(_minmag(float(a), float(b)))
356
357 def bfp32_MINMAGNUM08(self, a, b):
358 # FIXME: use proper implementation
359 return fp32toselectable(_minmag(float(a), float(b)))
360
361 def bfp64_MAXMAGNUM08(self, a, b):
362 # FIXME: use proper implementation
363 return fp64toselectable(_maxmag(float(a), float(b)))
364
365 def bfp32_MAXMAGNUM08(self, a, b):
366 # FIXME: use proper implementation
367 return fp32toselectable(_maxmag(float(a), float(b)))
368
369 def bfp64_MOD(self, a, b):
370 # FIXME: use proper implementation
371 return fp64toselectable(math.fmod(float(a), float(b)))
372
373 def bfp32_MOD(self, a, b):
374 # FIXME: use proper implementation
375 return fp32toselectable(math.fmod(float(a), float(b)))
376
377 def bfp64_MINMAG19(self, a, b):
378 # FIXME: use proper implementation
379 return fp64toselectable(_minmag(float(a), float(b)))
380
381 def bfp32_MINMAG19(self, a, b):
382 # FIXME: use proper implementation
383 return fp32toselectable(_minmag(float(a), float(b)))
384
385 def bfp64_MAXMAG19(self, a, b):
386 # FIXME: use proper implementation
387 return fp64toselectable(_maxmag(float(a), float(b)))
388
389 def bfp32_MAXMAG19(self, a, b):
390 # FIXME: use proper implementation
391 return fp32toselectable(_maxmag(float(a), float(b)))
392
393 def bfp64_MINMAGNUM19(self, a, b):
394 # FIXME: use proper implementation
395 return fp64toselectable(_minmag(float(a), float(b)))
396
397 def bfp32_MINMAGNUM19(self, a, b):
398 # FIXME: use proper implementation
399 return fp32toselectable(_minmag(float(a), float(b)))
400
401 def bfp64_MAXMAGNUM19(self, a, b):
402 # FIXME: use proper implementation
403 return fp64toselectable(_maxmag(float(a), float(b)))
404
405 def bfp32_MAXMAGNUM19(self, a, b):
406 # FIXME: use proper implementation
407 return fp32toselectable(_maxmag(float(a), float(b)))
408
409 def bfp64_REMAINDER(self, a, b):
410 # FIXME: use proper implementation
411 return fp64toselectable(math.remainder(float(a), float(b)))
412
413 def bfp32_REMAINDER(self, a, b):
414 # FIXME: use proper implementation
415 return fp32toselectable(math.remainder(float(a), float(b)))
416
417 def bfp64_POWR(self, a, b):
418 # FIXME: use proper implementation
419 return fp64toselectable(pow(float(a), float(b)))
420
421 def bfp32_POWR(self, a, b):
422 # FIXME: use proper implementation
423 return fp32toselectable(pow(float(a), float(b)))
424
425 def bfp64_POW(self, a, b):
426 # FIXME: use proper implementation
427 return fp64toselectable(pow(float(a), float(b)))
428
429 def bfp32_POW(self, a, b):
430 # FIXME: use proper implementation
431 return fp32toselectable(pow(float(a), float(b)))
432
433 def bfp64_MINMAGC(self, a, b):
434 # FIXME: use proper implementation
435 return fp64toselectable(_minmag(float(a), float(b)))
436
437 def bfp32_MINMAGC(self, a, b):
438 # FIXME: use proper implementation
439 return fp32toselectable(_minmag(float(a), float(b)))
440
441 def bfp64_MAXMAGC(self, a, b):
442 # FIXME: use proper implementation
443 return fp64toselectable(_maxmag(float(a), float(b)))
444
445 def bfp32_MAXMAGC(self, a, b):
446 # FIXME: use proper implementation
447 return fp32toselectable(_maxmag(float(a), float(b)))
448
449 def bfp64_POWN(self, a, b):
450 # FIXME: use proper implementation
451 return fp64toselectable(pow(float(a), int(b)))
452
453 def bfp32_POWN(self, a, b):
454 # FIXME: use proper implementation
455 return fp32toselectable(pow(float(a), int(b)))
456
457 def bfp64_ROOTN(self, a, b):
458 # FIXME: use proper implementation
459 return fp64toselectable(pow(float(a), 1 / int(b)))
460
461 def bfp32_ROOTN(self, a, b):
462 # FIXME: use proper implementation
463 return fp32toselectable(pow(float(a), 1 / int(b)))
464
465 def bfp64_CBRT(self, v):
466 # FIXME: use proper implementation
467 return fp64toselectable(pow(float(v), 1 / 3))
468
469 def bfp32_CBRT(self, v):
470 # FIXME: use proper implementation
471 return fp32toselectable(pow(float(v), 1 / 3))
472
473 def bfp64_SINPI(self, v):
474 # FIXME: use proper implementation
475 return fp64toselectable(math.sin(float(v) * math.pi))
476
477 def bfp32_SINPI(self, v):
478 # FIXME: use proper implementation
479 return fp32toselectable(math.sin(float(v) * math.pi))
480
481 def bfp64_ASINPI(self, v):
482 # FIXME: use proper implementation
483 return fp64toselectable(math.asin(float(v)) / math.pi)
484
485 def bfp32_ASINPI(self, v):
486 # FIXME: use proper implementation
487 return fp32toselectable(math.asin(float(v)) / math.pi)
488
489 def bfp64_COSPI(self, v):
490 # FIXME: use proper implementation
491 return fp64toselectable(math.cos(float(v) * math.pi))
492
493 def bfp32_COSPI(self, v):
494 # FIXME: use proper implementation
495 return fp32toselectable(math.cos(float(v) * math.pi))
496
497 def bfp64_TANPI(self, v):
498 # FIXME: use proper implementation
499 return fp64toselectable(math.tan(float(v) * math.pi))
500
501 def bfp32_TANPI(self, v):
502 # FIXME: use proper implementation
503 return fp32toselectable(math.tan(float(v) * math.pi))
504
505 def bfp64_ACOSPI(self, v):
506 # FIXME: use proper implementation
507 return fp64toselectable(math.acos(float(v)) / math.pi)
508
509 def bfp32_ACOSPI(self, v):
510 # FIXME: use proper implementation
511 return fp32toselectable(math.acos(float(v)) / math.pi)
512
513 def bfp64_ATANPI(self, v):
514 # FIXME: use proper implementation
515 return fp64toselectable(math.atan(float(v)) / math.pi)
516
517 def bfp32_ATANPI(self, v):
518 # FIXME: use proper implementation
519 return fp32toselectable(math.atan(float(v)) / math.pi)
520
521 def bfp64_RSQRT(self, v):
522 # FIXME: use proper implementation
523 return fp64toselectable(1 / math.sqrt(float(v)))
524
525 def bfp32_RSQRT(self, v):
526 # FIXME: use proper implementation
527 return fp32toselectable(1 / math.sqrt(float(v)))
528
529 def bfp64_SIN(self, v):
530 # FIXME: use proper implementation
531 return fp64toselectable(math.sin(float(v)))
532
533 def bfp32_SIN(self, v):
534 # FIXME: use proper implementation
535 return fp32toselectable(math.sin(float(v)))
536
537 def bfp64_ASIN(self, v):
538 # FIXME: use proper implementation
539 return fp64toselectable(math.asin(float(v)))
540
541 def bfp32_ASIN(self, v):
542 # FIXME: use proper implementation
543 return fp32toselectable(math.asin(float(v)))
544
545 def bfp64_COS(self, v):
546 # FIXME: use proper implementation
547 return fp64toselectable(math.cos(float(v)))
548
549 def bfp32_COS(self, v):
550 # FIXME: use proper implementation
551 return fp32toselectable(math.cos(float(v)))
552
553 def bfp64_TAN(self, v):
554 # FIXME: use proper implementation
555 return fp64toselectable(math.tan(float(v)))
556
557 def bfp32_TAN(self, v):
558 # FIXME: use proper implementation
559 return fp32toselectable(math.tan(float(v)))
560
561 def bfp64_ACOS(self, v):
562 # FIXME: use proper implementation
563 return fp64toselectable(math.acos(float(v)))
564
565 def bfp32_ACOS(self, v):
566 # FIXME: use proper implementation
567 return fp32toselectable(math.acos(float(v)))
568
569 def bfp64_ATAN(self, v):
570 # FIXME: use proper implementation
571 return fp64toselectable(math.atan(float(v)))
572
573 def bfp32_ATAN(self, v):
574 # FIXME: use proper implementation
575 return fp32toselectable(math.atan(float(v)))
576
577 def bfp64_RECIP(self, v):
578 # FIXME: use proper implementation
579 return fp64toselectable(1 / float(v))
580
581 def bfp32_RECIP(self, v):
582 # FIXME: use proper implementation
583 return fp32toselectable(1 / float(v))
584
585 def bfp64_SINH(self, v):
586 # FIXME: use proper implementation
587 return fp64toselectable(math.sinh(float(v)))
588
589 def bfp32_SINH(self, v):
590 # FIXME: use proper implementation
591 return fp32toselectable(math.sinh(float(v)))
592
593 def bfp64_ASINH(self, v):
594 # FIXME: use proper implementation
595 return fp64toselectable(math.asinh(float(v)))
596
597 def bfp32_ASINH(self, v):
598 # FIXME: use proper implementation
599 return fp32toselectable(math.asinh(float(v)))
600
601 def bfp64_COSH(self, v):
602 # FIXME: use proper implementation
603 return fp64toselectable(math.cosh(float(v)))
604
605 def bfp32_COSH(self, v):
606 # FIXME: use proper implementation
607 return fp32toselectable(math.cosh(float(v)))
608
609 def bfp64_TANH(self, v):
610 # FIXME: use proper implementation
611 return fp64toselectable(math.tanh(float(v)))
612
613 def bfp32_TANH(self, v):
614 # FIXME: use proper implementation
615 return fp32toselectable(math.tanh(float(v)))
616
617 def bfp64_ACOSH(self, v):
618 # FIXME: use proper implementation
619 return fp64toselectable(math.acosh(float(v)))
620
621 def bfp32_ACOSH(self, v):
622 # FIXME: use proper implementation
623 return fp32toselectable(math.acosh(float(v)))
624
625 def bfp64_ATANH(self, v):
626 # FIXME: use proper implementation
627 return fp64toselectable(math.atanh(float(v)))
628
629 def bfp32_ATANH(self, v):
630 # FIXME: use proper implementation
631 return fp32toselectable(math.atanh(float(v)))
632
633 def bfp64_EXP2M1(self, v):
634 # FIXME: use proper implementation
635 return fp64toselectable(pow(2, float(v)) - 1)
636
637 def bfp32_EXP2M1(self, v):
638 # FIXME: use proper implementation
639 return fp32toselectable(pow(2, float(v)) - 1)
640
641 def bfp64_LOG2P1(self, v):
642 # FIXME: use proper implementation
643 return fp64toselectable(math.log2(float(v) + 1))
644
645 def bfp32_LOG2P1(self, v):
646 # FIXME: use proper implementation
647 return fp32toselectable(math.log2(float(v) + 1))
648
649 def bfp64_EXPM1(self, v):
650 # FIXME: use proper implementation
651 return fp64toselectable(math.expm1(float(v)))
652
653 def bfp32_EXPM1(self, v):
654 # FIXME: use proper implementation
655 return fp32toselectable(math.expm1(float(v)))
656
657 def bfp64_LOGP1(self, v):
658 # FIXME: use proper implementation
659 return fp64toselectable(math.log1p(float(v)))
660
661 def bfp32_LOGP1(self, v):
662 # FIXME: use proper implementation
663 return fp32toselectable(math.log1p(float(v)))
664
665 def bfp64_EXP10M1(self, v):
666 # FIXME: use proper implementation
667 return fp64toselectable(pow(10, float(v)) - 1)
668
669 def bfp32_EXP10M1(self, v):
670 # FIXME: use proper implementation
671 return fp32toselectable(pow(10, float(v)) - 1)
672
673 def bfp64_LOG10P1(self, v):
674 # FIXME: use proper implementation
675 return fp64toselectable(math.log10(float(v) + 1))
676
677 def bfp32_LOG10P1(self, v):
678 # FIXME: use proper implementation
679 return fp32toselectable(math.log10(float(v) + 1))
680
681 def bfp64_EXP2(self, v):
682 # FIXME: use proper implementation
683 return fp64toselectable(pow(2, float(v)))
684
685 def bfp32_EXP2(self, v):
686 # FIXME: use proper implementation
687 return fp32toselectable(pow(2, float(v)))
688
689 def bfp64_LOG2(self, v):
690 # FIXME: use proper implementation
691 return fp64toselectable(math.log2(float(v)))
692
693 def bfp32_LOG2(self, v):
694 # FIXME: use proper implementation
695 return fp32toselectable(math.log2(float(v)))
696
697 def bfp64_EXP(self, v):
698 # FIXME: use proper implementation
699 return fp64toselectable(math.exp(float(v)))
700
701 def bfp32_EXP(self, v):
702 # FIXME: use proper implementation
703 return fp32toselectable(math.exp(float(v)))
704
705 def bfp64_LOG(self, v):
706 # FIXME: use proper implementation
707 return fp64toselectable(math.log(float(v)))
708
709 def bfp32_LOG(self, v):
710 # FIXME: use proper implementation
711 return fp32toselectable(math.log(float(v)))
712
713 def bfp64_EXP10(self, v):
714 # FIXME: use proper implementation
715 return fp64toselectable(pow(10, float(v)))
716
717 def bfp32_EXP10(self, v):
718 # FIXME: use proper implementation
719 return fp32toselectable(pow(10, float(v)))
720
721 def bfp64_LOG10(self, v):
722 # FIXME: use proper implementation
723 return fp64toselectable(math.log10(float(v)))
724
725 def bfp32_LOG10(self, v):
726 # FIXME: use proper implementation
727 return fp32toselectable(math.log10(float(v)))
728
729 def FPADD32(self, FRA, FRB):
730 # return FPADD64(FRA, FRB)
731 #FRA = DOUBLE(SINGLE(FRA))
732 #FRB = DOUBLE(SINGLE(FRB))
733 result = float(FRA) + float(FRB)
734 cvt = fp64toselectable(result)
735 cvt = self.DOUBLE2SINGLE(cvt)
736 log("FPADD32", FRA, FRB, float(FRA), "+", float(FRB), "=", result, cvt)
737 return cvt
738
739 def FPSUB32(self, FRA, FRB):
740 # return FPSUB64(FRA, FRB)
741 #FRA = DOUBLE(SINGLE(FRA))
742 #FRB = DOUBLE(SINGLE(FRB))
743 result = float(FRA) - float(FRB)
744 cvt = fp64toselectable(result)
745 cvt = self.DOUBLE2SINGLE(cvt)
746 log("FPSUB32", FRA, FRB, float(FRA), "-", float(FRB), "=", result, cvt)
747 return cvt
748
749 def FPMUL32(self, FRA, FRB, sign=1):
750 # return FPMUL64(FRA, FRB)
751 FRA = self.DOUBLE(SINGLE(FRA))
752 FRB = self.DOUBLE(SINGLE(FRB))
753 result = signinv(float(FRA) * float(FRB), sign)
754 log("FPMUL32", FRA, FRB, float(FRA), float(FRB), result, sign)
755 cvt = fp64toselectable(result)
756 cvt = self.DOUBLE2SINGLE(cvt)
757 log(" cvt", cvt)
758 return cvt
759
760 def FPMULADD32(self, FRA, FRC, FRB, mulsign, addsign):
761 # return FPMUL64(FRA, FRB)
762 #FRA = DOUBLE(SINGLE(FRA))
763 #FRB = DOUBLE(SINGLE(FRB))
764 if addsign == 1:
765 if mulsign == 1:
766 result = float(FRA) * float(FRC) + float(FRB) # fmadds
767 elif mulsign == -1:
768 result = -(float(FRA) * float(FRC) - float(FRB)) # fnmsubs
769 elif addsign == -1:
770 if mulsign == 1:
771 result = float(FRA) * float(FRC) - float(FRB) # fmsubs
772 elif mulsign == -1:
773 result = -(float(FRA) * float(FRC) + float(FRB)) # fnmadds
774 elif addsign == 0:
775 result = 0.0
776 log("FPMULADD32 FRA FRC FRB", FRA, FRC, FRB)
777 log(" FRA", float(FRA))
778 log(" FRC", float(FRC))
779 log(" FRB", float(FRB))
780 log(" (FRA*FRC)+FRB=", mulsign, addsign, result)
781 cvt = fp64toselectable(result)
782 cvt = self.DOUBLE2SINGLE(cvt)
783 log(" cvt", cvt)
784 return cvt
785
786 def FPDIV32(self, FRA, FRB, sign=1):
787 # return FPDIV64(FRA, FRB)
788 #FRA = DOUBLE(SINGLE(FRA))
789 #FRB = DOUBLE(SINGLE(FRB))
790 result = signinv(float(FRA) / float(FRB), sign)
791 cvt = fp64toselectable(result)
792 cvt = self.DOUBLE2SINGLE(cvt)
793 log("FPDIV32", FRA, FRB, result, cvt)
794 return cvt
795
796
797 def FPADD64(FRA, FRB):
798 result = float(FRA) + float(FRB)
799 cvt = fp64toselectable(result)
800 log("FPADD64", FRA, FRB, result, cvt)
801 return cvt
802
803
804 def FPSUB64(FRA, FRB):
805 result = float(FRA) - float(FRB)
806 cvt = fp64toselectable(result)
807 log("FPSUB64", FRA, FRB, result, cvt)
808 return cvt
809
810
811 def FPMUL64(FRA, FRB, sign=1):
812 result = signinv(float(FRA) * float(FRB), sign)
813 cvt = fp64toselectable(result)
814 log("FPMUL64", FRA, FRB, result, cvt, sign)
815 return cvt
816
817
818 def FPDIV64(FRA, FRB, sign=1):
819 result = signinv(float(FRA) / float(FRB), sign)
820 cvt = fp64toselectable(result)
821 log("FPDIV64", FRA, FRB, result, cvt, sign)
822 return cvt
823
824
825 def bitrev(val, VL):
826 """Returns the integer whose value is the reverse of the lowest
827 'width' bits of the integer 'val'
828 """
829 result = 0
830 width = VL.bit_length()-1
831 for _ in range(width):
832 result = (result << 1) | (val & 1)
833 val >>= 1
834 return result
835
836
837 def log2(val):
838 """return the base-2 logarithm of `val`. Only works for powers of 2."""
839 if isinstance(val, SelectableInt):
840 val = val.value
841 retval = val.bit_length() - 1
842 assert val == 2 ** retval, "value is not a power of 2"
843 return retval
844
845
846 # BFP classification predicates
847 # these need to be implemented in python because they work with multiple
848 # input types
849 def IsInf(v):
850 if isinstance(v, BFPState):
851 return onebit(v.class_.Infinity)
852 # TODO: implement for SelectableInt/int
853 raise NotImplementedError("not yet implemented for non-BFPState values")
854
855
856 def IsNaN(v):
857 if isinstance(v, BFPState):
858 return onebit(v.class_.SNaN or v.class_.QNaN)
859 # TODO: implement for SelectableInt/int
860 raise NotImplementedError("not yet implemented for non-BFPState values")
861
862
863 def IsNeg(v):
864 if isinstance(v, BFPState):
865 if v.class_.SNaN or v.class_.QNaN or v.class_.Zero:
866 return onebit(0)
867 return onebit(v.sign)
868 # TODO: implement for SelectableInt/int
869 raise NotImplementedError("not yet implemented for non-BFPState values")
870
871
872 def IsSNaN(v):
873 if isinstance(v, BFPState):
874 return onebit(v.class_.SNaN)
875 # TODO: implement for SelectableInt/int
876 raise NotImplementedError("not yet implemented for non-BFPState values")
877
878
879 def IsZero(v):
880 if isinstance(v, BFPState):
881 return onebit(v.class_.Zero)
882 # TODO: implement for SelectableInt/int
883 raise NotImplementedError("not yet implemented for non-BFPState values")
884
885
886 class ISACallerHelper:
887 def __init__(self, XLEN, FPSCR):
888 self.__XLEN = XLEN
889 if FPSCR is None:
890 FPSCR = FPSCRState()
891 self.__FPSCR = FPSCR
892
893 @property
894 def XLEN(self):
895 return self.__XLEN
896
897 @property
898 def FPSCR(self):
899 return self.__FPSCR
900
901 def EXTZXL(self, value, bits=None):
902 if bits is None:
903 bits = self.XLEN
904 elif isinstance(bits, SelectableInt):
905 bits = bits.value
906 if isinstance(value, SelectableInt):
907 value = value.value
908 return SelectableInt(value & ((1 << bits) - 1), self.XLEN)
909
910 def EXTSXL(self, value, bits=None):
911 if isinstance(value, SelectableInt):
912 value = value.value
913 if bits is None:
914 bits = self.XLEN
915 elif isinstance(bits, SelectableInt):
916 bits = bits.value
917 return SelectableInt(exts(value, bits), self.XLEN)
918
919 def DOUBLE2SINGLE(self, FRS):
920 """ DOUBLE2SINGLE has been renamed to FRSP since it is the
921 implementation of the frsp instruction.
922 use SINGLE() or FRSP() instead, or just use struct.pack/unpack
923 """
924 return self.FRSP(FRS)
925
926 def ROTL32(self, value, bits):
927 if isinstance(bits, SelectableInt):
928 bits = bits.value
929 if isinstance(value, SelectableInt):
930 value = SelectableInt(value.value, self.XLEN)
931 value = value | (value << (self.XLEN//2))
932 value = rotl(value, bits, self.XLEN)
933 return value
934
935 def ROTL128(self, value, bits):
936 return rotl(value, bits, self.XLEN*2)
937
938 def ROTL64(self, value, bits):
939 return rotl(value, bits, self.XLEN)
940
941 def MASK32(self, x, y):
942 if isinstance(x, SelectableInt):
943 x = x.value
944 if isinstance(y, SelectableInt):
945 y = y.value
946 return self.MASK(x+(self.XLEN//2), y+(self.XLEN//2))
947
948 def MASK(self, x, y, lim=None):
949 if lim is None:
950 lim = self.XLEN
951 if isinstance(x, SelectableInt):
952 x = x.value
953 if isinstance(y, SelectableInt):
954 y = y.value
955 if x < y:
956 x = lim-x
957 y = (lim-1)-y
958 mask_a = ((1 << x) - 1) & ((1 << lim) - 1)
959 mask_b = ((1 << y) - 1) & ((1 << lim) - 1)
960 elif x == y:
961 return 1 << ((lim-1)-x)
962 else:
963 x = lim-x
964 y = (lim-1)-y
965 mask_a = ((1 << x) - 1) & ((1 << lim) - 1)
966 mask_b = (~((1 << y) - 1)) & ((1 << lim) - 1)
967 return mask_a ^ mask_b
968
969 def __getattr__(self, attr):
970 """workaround for getting function out of the global namespace
971 within this module, as a way to get functions being transitioned
972 to Helper classes within ISACaller (and therefore pseudocode)
973 """
974 try:
975 return globals()[attr]
976 except KeyError:
977 raise AttributeError(attr)
978
979
980 # For these tests I tried to find power instructions that would let me
981 # isolate each of these helper operations. So for instance, when I was
982 # testing the MASK() function, I chose rlwinm and rldicl because if I
983 # set the shift equal to 0 and passed in a value of all ones, the
984 # result I got would be exactly the same as the output of MASK()
985
986 class HelperTests(unittest.TestCase, ISACallerHelper):
987 def __init__(self, *args, **kwargs):
988 # TODO: dynamic (64/32/16/8)
989 ISACallerHelper.__init__(self, 64, FPSCR=None)
990 unittest.TestCase.__init__(self, *args, **kwargs)
991
992 def test_MASK(self):
993 # Verified using rlwinm, rldicl, rldicr in qemu
994 # li 1, -1
995 # rlwinm reg, 1, 0, 5, 15
996 self.assertHex(self.MASK(5+32, 15+32), 0x7ff0000)
997 # rlwinm reg, 1, 0, 15, 5
998 self.assertHex(self.MASK(15+32, 5+32), 0xfffffffffc01ffff)
999 self.assertHex(self.MASK(30+32, 2+32), 0xffffffffe0000003)
1000 # rldicl reg, 1, 0, 37
1001 self.assertHex(self.MASK(37, 63), 0x7ffffff)
1002 self.assertHex(self.MASK(10, 63), 0x3fffffffffffff)
1003 self.assertHex(self.MASK(58, 63), 0x3f)
1004 # rldicr reg, 1, 0, 37
1005 self.assertHex(self.MASK(0, 37), 0xfffffffffc000000)
1006 self.assertHex(self.MASK(0, 10), 0xffe0000000000000)
1007 self.assertHex(self.MASK(0, 58), 0xffffffffffffffe0)
1008
1009 # li 2, 5
1010 # slw 1, 1, 2
1011 self.assertHex(self.MASK(32, 63-5), 0xffffffe0)
1012
1013 self.assertHex(self.MASK(32, 33), 0xc0000000)
1014 self.assertHex(self.MASK(32, 32), 0x80000000)
1015 self.assertHex(self.MASK(33, 33), 0x40000000)
1016
1017 def test_ROTL64(self):
1018 # r1 = 0xdeadbeef12345678
1019 value = 0xdeadbeef12345678
1020
1021 # rldicl reg, 1, 10, 0
1022 self.assertHex(self.ROTL64(value, 10), 0xb6fbbc48d159e37a)
1023 # rldicl reg, 1, 35, 0
1024 self.assertHex(self.ROTL64(value, 35), 0x91a2b3c6f56df778)
1025 self.assertHex(self.ROTL64(value, 58), 0xe37ab6fbbc48d159)
1026 self.assertHex(self.ROTL64(value, 22), 0xbbc48d159e37ab6f)
1027
1028 def test_ROTL32(self):
1029 # r1 = 0xdeadbeef
1030 value = SelectableInt(0xdeadbeef, self.XLEN)
1031
1032 # rlwinm reg, 1, 10, 0, 31
1033 self.assertHex(self.ROTL32(value, 10), 0xb6fbbf7a)
1034 # rlwinm reg, 1, 17, 0, 31
1035 self.assertHex(self.ROTL32(value, 17), 0x7ddfbd5b)
1036 self.assertHex(self.ROTL32(value, 25), 0xdfbd5b7d)
1037 self.assertHex(self.ROTL32(value, 30), 0xf7ab6fbb)
1038
1039 def test_EXTS64(self):
1040 value_a = SelectableInt(0xdeadbeef, 32) # r1
1041 value_b = SelectableInt(0x73123456, 32) # r2
1042 value_c = SelectableInt(0x80000000, 32) # r3
1043
1044 # extswsli reg, 1, 0
1045 self.assertHex(self.EXTS64(value_a), 0xffffffffdeadbeef)
1046 # extswsli reg, 2, 0
1047 self.assertHex(self.EXTS64(value_b), SelectableInt(value_b.value, 64))
1048 # extswsli reg, 3, 0
1049 self.assertHex(self.EXTS64(value_c), 0xffffffff80000000)
1050
1051 def test_FPADD32(self):
1052 value_a = SelectableInt(0x4014000000000000, 64) # 5.0
1053 value_b = SelectableInt(0x403B4CCCCCCCCCCD, 64) # 27.3
1054 result = FPADD32(value_a, value_b)
1055 self.assertHex(0x4040266666666666, result)
1056
1057 def assertHex(self, a, b):
1058 a_val = a
1059 if isinstance(a, SelectableInt):
1060 a_val = a.value
1061 b_val = b
1062 if isinstance(b, SelectableInt):
1063 b_val = b.value
1064 msg = "{:x} != {:x}".format(a_val, b_val)
1065 return self.assertEqual(a, b, msg)
1066
1067
1068
1069 if __name__ == '__main__':
1070 log(SelectableInt.__bases__)
1071 unittest.main()