Merge branch 'support-fields'
[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 ("FPCC", 4), # layout FL/FG/FE/FU TODO
70 ("FPRF", 2), # layout C/rsvd TODO
71 ("FI", 1),
72 ("FR", 1),
73 ("VXVC", 1),
74 ("VXZDZ", 1),
75 ("VXIDI", 1),
76 ("VXISI", 1),
77 ("VXSNAN", 1),
78 ("XX", 1),
79 ("ZX", 1),
80 ("UX", 1),
81 ("OX", 1),
82 ("VX", 1),
83 ("FEX", 1),
84 ("FX", 1),
85 ("DRN", 3),
86 ("rsvd2", 29),
87 ]
88
89 def __init__(self, name=None):
90 super().__init__(name=name, layout=FPSCRRecord.layout)
91
92
93 class FPSCR_FPRF(FieldSelectableInt):
94 """ special FieldSelectableInt instance to handle assigning strings to
95 FPSCR.FPRF
96
97 Translation Table from:
98 PowerISA v3.1B Book I Section 4.2.2 Page 139(165)
99 Figure 47 Floating-Point Result Flags
100 """
101 TRANSLATION_TABLE = (
102 ("Quiet NaN", 0b10001),
103 ("QNaN", 0b10001),
104 ("- Infinity", 0b01001),
105 ("- Normalized Number", 0b01000),
106 ("- Normal Number", 0b01000),
107 ("- Denormalized Number", 0b11000),
108 ("- Zero", 0b10010),
109 ("+ Zero", 0b00010),
110 ("+ Denormalized Number", 0b10100),
111 ("+ Normalized Number", 0b00100),
112 ("+ Normal Number", 0b00100),
113 ("+ Infinity", 0b00101),
114 )
115 TRANSLATION_TABLE_DICT = {k.casefold(): v for k, v in TRANSLATION_TABLE}
116
117 def eq(self, b):
118 if isinstance(b, str):
119 b = FPSCR_FPRF.TRANSLATION_TABLE_DICT[b.casefold()]
120 super().eq(b)
121
122
123 class FPSCRState(SelectableInt):
124 def __init__(self, value=0):
125 SelectableInt.__init__(self, value, 64)
126 self.fsi = {}
127 offs = 0
128 # set up sub-fields from Record layout
129 self.fsi = {}
130 l = deepcopy(FPSCRRecord.layout)
131 l.reverse()
132 for field, width in l:
133 end = offs+width
134 fs = tuple(range(offs, end))
135 if field == "FPRF":
136 v = FPSCR_FPRF(self, fs)
137 else:
138 v = FieldSelectableInt(self, fs)
139 self.fsi[field] = v
140 offs = end
141 # extra fields, temporarily explicitly added. TODO nested layout above
142 extras = [(47, "C"),
143 (48, "FL"),
144 (49, "FG"),
145 (50, "FE"),
146 (51, "FU"),
147 ]
148 for offs, field in extras:
149 end = offs+1
150 fs = tuple(range(offs, end))
151 v = FieldSelectableInt(self, fs)
152 self.fsi[field] = v
153
154 @property
155 def DRN(self):
156 return self.fsi['DRN'].asint(msb0=True)
157
158 @DRN.setter
159 def DRN(self, value):
160 self.fsi['DRN'].eq(value)
161
162 @property
163 def FX(self):
164 return self.fsi['FX'].asint(msb0=True)
165
166 @FX.setter
167 def FX(self, value):
168 self.fsi['FX'].eq(value)
169
170 @property
171 def FEX(self):
172 return self.fsi['FEX'].asint(msb0=True)
173
174 @FEX.setter
175 def FEX(self, value):
176 self.fsi['FEX'].eq(value)
177
178 @property
179 def VX(self):
180 return self.fsi['VX'].asint(msb0=True)
181
182 @VX.setter
183 def VX(self, value):
184 self.fsi['VX'].eq(value)
185
186 @property
187 def OX(self):
188 return self.fsi['OX'].asint(msb0=True)
189
190 @OX.setter
191 def OX(self, value):
192 self.fsi['OX'].eq(value)
193
194 @property
195 def UX(self):
196 return self.fsi['UX'].asint(msb0=True)
197
198 @UX.setter
199 def UX(self, value):
200 self.fsi['UX'].eq(value)
201
202 @property
203 def ZX(self):
204 return self.fsi['ZX'].asint(msb0=True)
205
206 @ZX.setter
207 def ZX(self, value):
208 self.fsi['ZX'].eq(value)
209
210 @property
211 def XX(self):
212 return self.fsi['XX'].asint(msb0=True)
213
214 @XX.setter
215 def XX(self, value):
216 self.fsi['XX'].eq(value)
217
218 @property
219 def VXSNAN(self):
220 return self.fsi['VXSNAN'].asint(msb0=True)
221
222 @VXSNAN.setter
223 def VXSNAN(self, value):
224 self.fsi['VXSNAN'].eq(value)
225
226 @property
227 def VXISI(self):
228 return self.fsi['VXISI'].asint(msb0=True)
229
230 @VXISI.setter
231 def VXISI(self, value):
232 self.fsi['VXISI'].eq(value)
233
234 @property
235 def VXIDI(self):
236 return self.fsi['VXIDI'].asint(msb0=True)
237
238 @VXIDI.setter
239 def VXIDI(self, value):
240 self.fsi['VXIDI'].eq(value)
241
242 @property
243 def VXZDZ(self):
244 return self.fsi['VXZDZ'].asint(msb0=True)
245
246 @VXZDZ.setter
247 def VXZDZ(self, value):
248 self.fsi['VXZDZ'].eq(value)
249
250 @property
251 def VXIMZ(self):
252 return self.fsi['VXIMZ'].asint(msb0=True)
253
254 @VXIMZ.setter
255 def VXIMZ(self, value):
256 self.fsi['VXIMZ'].eq(value)
257
258 @property
259 def VXVC(self):
260 return self.fsi['VXVC'].asint(msb0=True)
261
262 @VXVC.setter
263 def VXVC(self, value):
264 self.fsi['VXVC'].eq(value)
265
266 @property
267 def FR(self):
268 return self.fsi['FR'].asint(msb0=True)
269
270 @FR.setter
271 def FR(self, value):
272 self.fsi['FR'].eq(value)
273
274 @property
275 def FI(self):
276 return self.fsi['FI'].asint(msb0=True)
277
278 @FI.setter
279 def FI(self, value):
280 self.fsi['FI'].eq(value)
281
282 @property
283 def FPRF(self):
284 return self.fsi['FPRF'].asint(msb0=True)
285
286 @FPRF.setter
287 def FPRF(self, value):
288 self.fsi['FPRF'].eq(value)
289
290 @property
291 def C(self):
292 return self.fsi['C'].asint(msb0=True)
293
294 @C.setter
295 def C(self, value):
296 self.fsi['C'].eq(value)
297
298 @property
299 def FPCC(self):
300 return self.fsi['FPCC'].asint(msb0=True)
301
302 @FPCC.setter
303 def FPCC(self, value):
304 self.fsi['FPCC'].eq(value)
305
306 @property
307 def FL(self):
308 return self.fsi['FL'].asint(msb0=True)
309
310 @FL.setter
311 def FL(self, value):
312 self.fsi['FL'].eq(value)
313
314 @property
315 def FG(self):
316 return self.fsi['FG'].asint(msb0=True)
317
318 @FG.setter
319 def FG(self, value):
320 self.fsi['FG'].eq(value)
321
322 @property
323 def FE(self):
324 return self.fsi['FE'].asint(msb0=True)
325
326 @FE.setter
327 def FE(self, value):
328 self.fsi['FE'].eq(value)
329
330 @property
331 def FU(self):
332 return self.fsi['FU'].asint(msb0=True)
333
334 @FU.setter
335 def FU(self, value):
336 self.fsi['FU'].eq(value)
337
338 @property
339 def VXSOFT(self):
340 return self.fsi['VXSOFT'].asint(msb0=True)
341
342 @VXSOFT.setter
343 def VXSOFT(self, value):
344 self.fsi['VXSOFT'].eq(value)
345
346 @property
347 def VXSQRT(self):
348 return self.fsi['VXSQRT'].asint(msb0=True)
349
350 @VXSQRT.setter
351 def VXSQRT(self, value):
352 self.fsi['VXSQRT'].eq(value)
353
354 @property
355 def VXCVI(self):
356 return self.fsi['VXCVI'].asint(msb0=True)
357
358 @VXCVI.setter
359 def VXCVI(self, value):
360 self.fsi['VXCVI'].eq(value)
361
362 @property
363 def VE(self):
364 return self.fsi['VE'].asint(msb0=True)
365
366 @VE.setter
367 def VE(self, value):
368 self.fsi['VE'].eq(value)
369
370 @property
371 def OE(self):
372 return self.fsi['OE'].asint(msb0=True)
373
374 @OE.setter
375 def OE(self, value):
376 self.fsi['OE'].eq(value)
377
378 @property
379 def UE(self):
380 return self.fsi['UE'].asint(msb0=True)
381
382 @UE.setter
383 def UE(self, value):
384 self.fsi['UE'].eq(value)
385
386 @property
387 def ZE(self):
388 return self.fsi['ZE'].asint(msb0=True)
389
390 @ZE.setter
391 def ZE(self, value):
392 self.fsi['ZE'].eq(value)
393
394 @property
395 def XE(self):
396 return self.fsi['XE'].asint(msb0=True)
397
398 @XE.setter
399 def XE(self, value):
400 self.fsi['XE'].eq(value)
401
402 @property
403 def NI(self):
404 return self.fsi['NI'].asint(msb0=True)
405
406 @NI.setter
407 def NI(self, value):
408 self.fsi['NI'].eq(value)
409
410 @property
411 def RN(self):
412 return self.fsi['RN'].asint(msb0=True)
413
414 @RN.setter
415 def RN(self, value):
416 self.fsi['RN'].eq(value)
417
418
419 if __name__ == "__main__":
420 from pprint import pprint
421 print("FPSCRRecord.layout:")
422 pprint(FPSCRRecord.layout)
423 print("FPSCRState.fsi:")
424 pprint(FPSCRState().fsi)
425
426 # quick test of setter/getters
427 fpscr = FPSCRState()
428 fpscr.FPCC = 0b001
429 print (fpscr.FPCC, fpscr.FL, fpscr.FG, fpscr.FE, fpscr.FU)
430 fpscr.FG = 0b1
431 print (fpscr.FPCC, fpscr.FL, fpscr.FG, fpscr.FE, fpscr.FU)
432 fpscr.FPRF = 0b11
433 print (fpscr.FPRF, fpscr.C)
434 fpscr[63] = 1
435 print (fpscr.RN)