1 # SPDX-License-Identifier: LGPLv3+
2 # Funded by NLnet https://nlnet.nl/
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)
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 |
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
)
57 class FPSCRRecord(Record
):
69 ("FPCC", 4), # layout FL/FG/FE/FU TODO
70 ("FPRF", 2), # layout C/rsvd TODO
89 def __init__(self
, name
=None):
90 super().__init
__(name
=name
, layout
=FPSCRRecord
.layout
)
93 class FPSCR_FPRF(FieldSelectableInt
):
94 """ special FieldSelectableInt instance to handle assigning strings to
97 Translation Table from:
98 PowerISA v3.1B Book I Section 4.2.2 Page 139(165)
99 Figure 47 Floating-Point Result Flags
101 TRANSLATION_TABLE
= (
102 ("Quiet NaN", 0b10001),
104 ("- Infinity", 0b01001),
105 ("- Normalized Number", 0b01000),
106 ("- Normal Number", 0b01000),
107 ("- Denormalized Number", 0b11000),
110 ("+ Denormalized Number", 0b10100),
111 ("+ Normalized Number", 0b00100),
112 ("+ Normal Number", 0b00100),
113 ("+ Infinity", 0b00101),
115 TRANSLATION_TABLE_DICT
= {k
.casefold(): v
for k
, v
in TRANSLATION_TABLE
}
118 if isinstance(b
, str):
119 b
= FPSCR_FPRF
.TRANSLATION_TABLE_DICT
[b
.casefold()]
123 class FPSCRState(SelectableInt
):
124 def __init__(self
, value
=0):
125 SelectableInt
.__init
__(self
, value
, 64)
128 # set up sub-fields from Record layout
130 l
= deepcopy(FPSCRRecord
.layout
)
132 for field
, width
in l
:
134 fs
= tuple(range(offs
, end
))
136 v
= FPSCR_FPRF(self
, fs
)
138 v
= FieldSelectableInt(self
, fs
)
141 # extra fields, temporarily explicitly added. TODO nested layout above
148 for offs
, field
in extras
:
150 fs
= tuple(range(offs
, end
))
151 v
= FieldSelectableInt(self
, fs
)
156 return self
.fsi
['DRN'].asint(msb0
=True)
159 def DRN(self
, value
):
160 self
.fsi
['DRN'].eq(value
)
164 return self
.fsi
['FX'].asint(msb0
=True)
168 self
.fsi
['FX'].eq(value
)
172 return self
.fsi
['FEX'].asint(msb0
=True)
175 def FEX(self
, value
):
176 self
.fsi
['FEX'].eq(value
)
180 return self
.fsi
['VX'].asint(msb0
=True)
184 self
.fsi
['VX'].eq(value
)
188 return self
.fsi
['OX'].asint(msb0
=True)
192 self
.fsi
['OX'].eq(value
)
196 return self
.fsi
['UX'].asint(msb0
=True)
200 self
.fsi
['UX'].eq(value
)
204 return self
.fsi
['ZX'].asint(msb0
=True)
208 self
.fsi
['ZX'].eq(value
)
212 return self
.fsi
['XX'].asint(msb0
=True)
216 self
.fsi
['XX'].eq(value
)
220 return self
.fsi
['VXSNAN'].asint(msb0
=True)
223 def VXSNAN(self
, value
):
224 self
.fsi
['VXSNAN'].eq(value
)
228 return self
.fsi
['VXISI'].asint(msb0
=True)
231 def VXISI(self
, value
):
232 self
.fsi
['VXISI'].eq(value
)
236 return self
.fsi
['VXIDI'].asint(msb0
=True)
239 def VXIDI(self
, value
):
240 self
.fsi
['VXIDI'].eq(value
)
244 return self
.fsi
['VXZDZ'].asint(msb0
=True)
247 def VXZDZ(self
, value
):
248 self
.fsi
['VXZDZ'].eq(value
)
252 return self
.fsi
['VXIMZ'].asint(msb0
=True)
255 def VXIMZ(self
, value
):
256 self
.fsi
['VXIMZ'].eq(value
)
260 return self
.fsi
['VXVC'].asint(msb0
=True)
263 def VXVC(self
, value
):
264 self
.fsi
['VXVC'].eq(value
)
268 return self
.fsi
['FR'].asint(msb0
=True)
272 self
.fsi
['FR'].eq(value
)
276 return self
.fsi
['FI'].asint(msb0
=True)
280 self
.fsi
['FI'].eq(value
)
284 return self
.fsi
['FPRF'].asint(msb0
=True)
287 def FPRF(self
, value
):
288 self
.fsi
['FPRF'].eq(value
)
292 return self
.fsi
['C'].asint(msb0
=True)
296 self
.fsi
['C'].eq(value
)
300 return self
.fsi
['FPCC'].asint(msb0
=True)
303 def FPCC(self
, value
):
304 self
.fsi
['FPCC'].eq(value
)
308 return self
.fsi
['FL'].asint(msb0
=True)
312 self
.fsi
['FL'].eq(value
)
316 return self
.fsi
['FG'].asint(msb0
=True)
320 self
.fsi
['FG'].eq(value
)
324 return self
.fsi
['FE'].asint(msb0
=True)
328 self
.fsi
['FE'].eq(value
)
332 return self
.fsi
['FU'].asint(msb0
=True)
336 self
.fsi
['FU'].eq(value
)
340 return self
.fsi
['VXSOFT'].asint(msb0
=True)
343 def VXSOFT(self
, value
):
344 self
.fsi
['VXSOFT'].eq(value
)
348 return self
.fsi
['VXSQRT'].asint(msb0
=True)
351 def VXSQRT(self
, value
):
352 self
.fsi
['VXSQRT'].eq(value
)
356 return self
.fsi
['VXCVI'].asint(msb0
=True)
359 def VXCVI(self
, value
):
360 self
.fsi
['VXCVI'].eq(value
)
364 return self
.fsi
['VE'].asint(msb0
=True)
368 self
.fsi
['VE'].eq(value
)
372 return self
.fsi
['OE'].asint(msb0
=True)
376 self
.fsi
['OE'].eq(value
)
380 return self
.fsi
['UE'].asint(msb0
=True)
384 self
.fsi
['UE'].eq(value
)
388 return self
.fsi
['ZE'].asint(msb0
=True)
392 self
.fsi
['ZE'].eq(value
)
396 return self
.fsi
['XE'].asint(msb0
=True)
400 self
.fsi
['XE'].eq(value
)
404 return self
.fsi
['NI'].asint(msb0
=True)
408 self
.fsi
['NI'].eq(value
)
412 return self
.fsi
['RN'].asint(msb0
=True)
416 self
.fsi
['RN'].eq(value
)
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
)
426 # quick test of setter/getters
429 print (fpscr
.FPCC
, fpscr
.FL
, fpscr
.FG
, fpscr
.FE
, fpscr
.FU
)
431 print (fpscr
.FPCC
, fpscr
.FL
, fpscr
.FG
, fpscr
.FE
, fpscr
.FU
)
433 print (fpscr
.FPRF
, fpscr
.C
)