remove fcvttgs since it's redundant
[openpower-isa.git] / src / openpower / fpscr.py
1 # SPDX-License-Identifier: LGPLv3+
2 # Funded by NLnet https://nlnet.nl/
3
4 # XXX TODO: get this into openpower/consts.py instead.
5 # create the layout from an auto-created Enum FPSCRb
6 """ Record for FPSCR as defined in
7 Power ISA v3.1B Book I section 4.2.2 page 136(162)
8
9 FPSCR fields in MSB0:
10
11 |Bits |Mnemonic | Description |
12 |-----|---------|-------------------------------------------------------------|
13 |0:28 |   | Reserved |
14 |29:31| DRN | Decimal Rounding Mode |
15 |32 | FX | FP Exception Summary |
16 |33 | FEX | FP Enabled Exception Summary |
17 |34 | VX | FP Invalid Operation Exception Summary |
18 |35 | OX | FP Overflow Exception |
19 |36 | UX | FP Underflow Exception |
20 |37 | ZX | FP Zero Divide Exception |
21 |38 | XX | FP Inexact Exception |
22 |39 | VXSNAN | FP Invalid Operation Exception (SNaN) |
23 |40 | VXISI | FP Invalid Operation Exception (∞ - ∞) |
24 |41 | VXIDI | FP Invalid Operation Exception (∞ ÷ ∞) |
25 |42 | VXZDZ | FP Invalid Operation Exception (0 ÷ 0) |
26 |43 | VXIMZ | FP Invalid Operation Exception (∞ × 0) |
27 |44 | VXVC | FP Invalid Operation Exception (Invalid Compare) |
28 |45 | FR | FP Fraction Rounded |
29 |46 | FI | FP Fraction Inexact |
30 |47:51| FPRF | FP Result Flags |
31 |47 | C | FP Result Class Descriptor |
32 |48:51| FPCC | FP Condition Code |
33 |48 | FL | FP Less Than or Negative |
34 |49 | FG | FP Greater Than or Positive |
35 |50 | FE | FP Equal or Zero |
36 |51 | FU | FP Unordered or NaN |
37 |52 |   | Reserved |
38 |53 | VXSOFT | FP Invalid Operation Exception (Software-Defined Condition) |
39 |54 | VXSQRT | FP Invalid Operation Exception (Invalid Square Root) |
40 |55 | VXCVI | FP Invalid Operation Exception (Invalid Integer Convert) |
41 |56 | VE | FP Invalid Operation Exception Enable |
42 |57 | OE | FP Overflow Exception Enable |
43 |58 | UE | FP Underflow Exception Enable |
44 |59 | ZE | FP Zero Divide Exception Enable |
45 |60 | XE | FP Inexact Exception Enable |
46 |61 | NI | FP Non-IEEE Mode |
47 |62:63| RN | FP Rounding Control |
48 """
49
50 from nmigen import Record
51 from copy import deepcopy
52 from openpower.util import log
53 from openpower.decoder.selectable_int import (
54 FieldSelectableInt, SelectableInt)
55
56
57 class FPSCRRecord(Record):
58 layout = [("RN", 2),
59 ("NI", 1),
60 ("XE", 1),
61 ("ZE", 1),
62 ("UE", 1),
63 ("OE", 1),
64 ("VE", 1),
65 ("VXCVI", 1),
66 ("VXSQRT", 1),
67 ("VXSOFT", 1),
68 ("rsvd1", 1),
69 ("FPRF", [
70 ("FPCC", [
71 ("FU", 1),
72 ("FE", 1),
73 ("FG", 1),
74 ("FL", 1),
75 ]),
76 ("C", 1),
77 ]),
78 ("FI", 1),
79 ("FR", 1),
80 ("VXVC", 1),
81 ("VXIMZ", 1),
82 ("VXZDZ", 1),
83 ("VXIDI", 1),
84 ("VXISI", 1),
85 ("VXSNAN", 1),
86 ("XX", 1),
87 ("ZX", 1),
88 ("UX", 1),
89 ("OX", 1),
90 ("VX", 1),
91 ("FEX", 1),
92 ("FX", 1),
93 ("DRN", 3),
94 ("rsvd2", 29),
95 ]
96
97 def __init__(self, name=None):
98 super().__init__(name=name, layout=FPSCRRecord.layout)
99
100
101 class FPSCR_FPRF(FieldSelectableInt):
102 """ special FieldSelectableInt instance to handle assigning strings to
103 FPSCR.FPRF
104
105 Translation Table from:
106 PowerISA v3.1B Book I Section 4.2.2 Page 139(165)
107 Figure 47 Floating-Point Result Flags
108 """
109 TRANSLATION_TABLE = (
110 ("Quiet NaN", 0b10001),
111 ("QNaN", 0b10001),
112 ("- Infinity", 0b01001),
113 ("- Normalized Number", 0b01000),
114 ("- Normal Number", 0b01000),
115 ("- Denormalized Number", 0b11000),
116 ("- Zero", 0b10010),
117 ("+ Zero", 0b00010),
118 ("+ Denormalized Number", 0b10100),
119 ("+ Normalized Number", 0b00100),
120 ("+ Normal Number", 0b00100),
121 ("+ Infinity", 0b00101),
122 )
123 TRANSLATION_TABLE_DICT = {k.casefold(): v for k, v in TRANSLATION_TABLE}
124
125 def eq(self, b):
126 if isinstance(b, str):
127 b = FPSCR_FPRF.TRANSLATION_TABLE_DICT[b.casefold()]
128 super().eq(b)
129
130
131 class FPSCRState(SelectableInt):
132 def __init__(self, value=0, *, auto_update_summary_bits=True):
133 self.__do_update_summary_bits = False
134 SelectableInt.__init__(self, value, 64)
135 self.fsi = {}
136 offs = 0
137 # set up sub-fields from Record layout
138 self.fsi = {}
139 l = deepcopy(FPSCRRecord.layout)
140 l.reverse()
141 for field, width in l:
142 if field == "FPRF":
143 v = FPSCR_FPRF(self, tuple(range(47, 52)))
144 end = 52
145 else:
146 end = offs + width
147 fs = tuple(range(offs, end))
148 v = FieldSelectableInt(self, fs)
149 self.fsi[field] = v
150 offs = end
151 # extra fields, temporarily explicitly added. TODO nested layout above
152 extras = [
153 (47, "C"),
154 (range(48, 52), "FPCC"),
155 (48, "FL"),
156 (49, "FG"),
157 (50, "FE"),
158 (51, "FU"),
159 ]
160 for offs, field in extras:
161 if isinstance(offs, int):
162 fs = (offs,)
163 else:
164 fs = tuple(offs)
165 v = FieldSelectableInt(self, fs)
166 self.fsi[field] = v
167 if auto_update_summary_bits:
168 self.__update_summary_bits()
169
170 @property
171 def value(self):
172 return self.__value
173
174 @value.setter
175 def value(self, value):
176 self.__value = value
177 if self.__do_update_summary_bits:
178 self.__update_summary_bits()
179
180 def __update_summary_bits(self):
181 self.__do_update_summary_bits = False
182 try:
183 # update summary bits -- FX is manually handled by pseudo-code,
184 # so we don't update it here
185 self.VX = (self.VXSNAN |
186 self.VXISI |
187 self.VXIDI |
188 self.VXZDZ |
189 self.VXIMZ |
190 self.VXVC |
191 self.VXSOFT |
192 self.VXSQRT |
193 self.VXCVI)
194 self.FEX = ((self.VX & self.VE) |
195 (self.OX & self.OE) |
196 (self.UX & self.UE) |
197 (self.ZX & self.ZE) |
198 (self.XX & self.XE))
199 finally:
200 self.__do_update_summary_bits = True
201
202 @property
203 def DRN(self):
204 return self.fsi['DRN'].asint(msb0=True)
205
206 @DRN.setter
207 def DRN(self, value):
208 self.fsi['DRN'].eq(value)
209
210 @property
211 def FX(self):
212 return self.fsi['FX'].asint(msb0=True)
213
214 @FX.setter
215 def FX(self, value):
216 self.fsi['FX'].eq(value)
217
218 @property
219 def FEX(self):
220 return self.fsi['FEX'].asint(msb0=True)
221
222 @FEX.setter
223 def FEX(self, value):
224 self.fsi['FEX'].eq(value)
225
226 @property
227 def VX(self):
228 return self.fsi['VX'].asint(msb0=True)
229
230 @VX.setter
231 def VX(self, value):
232 self.fsi['VX'].eq(value)
233
234 @property
235 def OX(self):
236 return self.fsi['OX'].asint(msb0=True)
237
238 @OX.setter
239 def OX(self, value):
240 self.fsi['OX'].eq(value)
241
242 @property
243 def UX(self):
244 return self.fsi['UX'].asint(msb0=True)
245
246 @UX.setter
247 def UX(self, value):
248 self.fsi['UX'].eq(value)
249
250 @property
251 def ZX(self):
252 return self.fsi['ZX'].asint(msb0=True)
253
254 @ZX.setter
255 def ZX(self, value):
256 self.fsi['ZX'].eq(value)
257
258 @property
259 def XX(self):
260 return self.fsi['XX'].asint(msb0=True)
261
262 @XX.setter
263 def XX(self, value):
264 self.fsi['XX'].eq(value)
265
266 @property
267 def VXSNAN(self):
268 return self.fsi['VXSNAN'].asint(msb0=True)
269
270 @VXSNAN.setter
271 def VXSNAN(self, value):
272 self.fsi['VXSNAN'].eq(value)
273
274 @property
275 def VXISI(self):
276 return self.fsi['VXISI'].asint(msb0=True)
277
278 @VXISI.setter
279 def VXISI(self, value):
280 self.fsi['VXISI'].eq(value)
281
282 @property
283 def VXIDI(self):
284 return self.fsi['VXIDI'].asint(msb0=True)
285
286 @VXIDI.setter
287 def VXIDI(self, value):
288 self.fsi['VXIDI'].eq(value)
289
290 @property
291 def VXZDZ(self):
292 return self.fsi['VXZDZ'].asint(msb0=True)
293
294 @VXZDZ.setter
295 def VXZDZ(self, value):
296 self.fsi['VXZDZ'].eq(value)
297
298 @property
299 def VXIMZ(self):
300 return self.fsi['VXIMZ'].asint(msb0=True)
301
302 @VXIMZ.setter
303 def VXIMZ(self, value):
304 self.fsi['VXIMZ'].eq(value)
305
306 @property
307 def VXVC(self):
308 return self.fsi['VXVC'].asint(msb0=True)
309
310 @VXVC.setter
311 def VXVC(self, value):
312 self.fsi['VXVC'].eq(value)
313
314 @property
315 def FR(self):
316 return self.fsi['FR'].asint(msb0=True)
317
318 @FR.setter
319 def FR(self, value):
320 self.fsi['FR'].eq(value)
321
322 @property
323 def FI(self):
324 return self.fsi['FI'].asint(msb0=True)
325
326 @FI.setter
327 def FI(self, value):
328 self.fsi['FI'].eq(value)
329
330 @property
331 def FPRF(self):
332 return self.fsi['FPRF'].asint(msb0=True)
333
334 @FPRF.setter
335 def FPRF(self, value):
336 self.fsi['FPRF'].eq(value)
337
338 @property
339 def C(self):
340 return self.fsi['C'].asint(msb0=True)
341
342 @C.setter
343 def C(self, value):
344 self.fsi['C'].eq(value)
345
346 @property
347 def FPCC(self):
348 return self.fsi['FPCC'].asint(msb0=True)
349
350 @FPCC.setter
351 def FPCC(self, value):
352 self.fsi['FPCC'].eq(value)
353
354 @property
355 def FL(self):
356 return self.fsi['FL'].asint(msb0=True)
357
358 @FL.setter
359 def FL(self, value):
360 self.fsi['FL'].eq(value)
361
362 @property
363 def FG(self):
364 return self.fsi['FG'].asint(msb0=True)
365
366 @FG.setter
367 def FG(self, value):
368 self.fsi['FG'].eq(value)
369
370 @property
371 def FE(self):
372 return self.fsi['FE'].asint(msb0=True)
373
374 @FE.setter
375 def FE(self, value):
376 self.fsi['FE'].eq(value)
377
378 @property
379 def FU(self):
380 return self.fsi['FU'].asint(msb0=True)
381
382 @FU.setter
383 def FU(self, value):
384 self.fsi['FU'].eq(value)
385
386 @property
387 def VXSOFT(self):
388 return self.fsi['VXSOFT'].asint(msb0=True)
389
390 @VXSOFT.setter
391 def VXSOFT(self, value):
392 self.fsi['VXSOFT'].eq(value)
393
394 @property
395 def VXSQRT(self):
396 return self.fsi['VXSQRT'].asint(msb0=True)
397
398 @VXSQRT.setter
399 def VXSQRT(self, value):
400 self.fsi['VXSQRT'].eq(value)
401
402 @property
403 def VXCVI(self):
404 return self.fsi['VXCVI'].asint(msb0=True)
405
406 @VXCVI.setter
407 def VXCVI(self, value):
408 self.fsi['VXCVI'].eq(value)
409
410 @property
411 def VE(self):
412 return self.fsi['VE'].asint(msb0=True)
413
414 @VE.setter
415 def VE(self, value):
416 self.fsi['VE'].eq(value)
417
418 @property
419 def OE(self):
420 return self.fsi['OE'].asint(msb0=True)
421
422 @OE.setter
423 def OE(self, value):
424 self.fsi['OE'].eq(value)
425
426 @property
427 def UE(self):
428 return self.fsi['UE'].asint(msb0=True)
429
430 @UE.setter
431 def UE(self, value):
432 self.fsi['UE'].eq(value)
433
434 @property
435 def ZE(self):
436 return self.fsi['ZE'].asint(msb0=True)
437
438 @ZE.setter
439 def ZE(self, value):
440 self.fsi['ZE'].eq(value)
441
442 @property
443 def XE(self):
444 return self.fsi['XE'].asint(msb0=True)
445
446 @XE.setter
447 def XE(self, value):
448 self.fsi['XE'].eq(value)
449
450 @property
451 def NI(self):
452 return self.fsi['NI'].asint(msb0=True)
453
454 @NI.setter
455 def NI(self, value):
456 self.fsi['NI'].eq(value)
457
458 @property
459 def RN(self):
460 return self.fsi['RN'].asint(msb0=True)
461
462 @RN.setter
463 def RN(self, value):
464 self.fsi['RN'].eq(value)
465
466
467 if __name__ == "__main__":
468 from pprint import pprint
469 print("FPSCRRecord.layout:")
470 pprint(FPSCRRecord.layout)
471 print("FPSCRState.fsi:")
472 pprint(FPSCRState().fsi)
473
474 # quick test of setter/getters
475 fpscr = FPSCRState()
476 fpscr.FPCC = 0b0001
477 print(fpscr.FPCC, fpscr.FL, fpscr.FG, fpscr.FE, fpscr.FU)
478 fpscr.FG = 0b1
479 print(fpscr.FPCC, fpscr.FL, fpscr.FG, fpscr.FE, fpscr.FU)
480 fpscr.FPRF = 0b00011
481 print(fpscr.FPRF, fpscr.C)
482 fpscr[63] = 1
483 print(fpscr.RN)