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
):
97 def __init__(self
, name
=None):
98 super().__init
__(name
=name
, layout
=FPSCRRecord
.layout
)
101 class FPSCR_FPRF(FieldSelectableInt
):
102 """ special FieldSelectableInt instance to handle assigning strings to
105 Translation Table from:
106 PowerISA v3.1B Book I Section 4.2.2 Page 139(165)
107 Figure 47 Floating-Point Result Flags
109 TRANSLATION_TABLE
= (
110 ("Quiet NaN", 0b10001),
112 ("- Infinity", 0b01001),
113 ("- Normalized Number", 0b01000),
114 ("- Normal Number", 0b01000),
115 ("- Denormalized Number", 0b11000),
118 ("+ Denormalized Number", 0b10100),
119 ("+ Normalized Number", 0b00100),
120 ("+ Normal Number", 0b00100),
121 ("+ Infinity", 0b00101),
123 TRANSLATION_TABLE_DICT
= {k
.casefold(): v
for k
, v
in TRANSLATION_TABLE
}
126 if isinstance(b
, str):
127 b
= FPSCR_FPRF
.TRANSLATION_TABLE_DICT
[b
.casefold()]
131 class FPSCRState(SelectableInt
):
132 def __init__(self
, value
=0):
133 SelectableInt
.__init
__(self
, value
, 64)
136 # set up sub-fields from Record layout
138 l
= deepcopy(FPSCRRecord
.layout
)
140 for field
, width
in l
:
142 v
= FPSCR_FPRF(self
, tuple(range(47, 52)))
146 fs
= tuple(range(offs
, end
))
147 v
= FieldSelectableInt(self
, fs
)
150 # extra fields, temporarily explicitly added. TODO nested layout above
153 (range(48, 52), "FPCC"),
159 for offs
, field
in extras
:
160 if isinstance(offs
, int):
164 v
= FieldSelectableInt(self
, fs
)
169 return self
.fsi
['DRN'].asint(msb0
=True)
172 def DRN(self
, value
):
173 self
.fsi
['DRN'].eq(value
)
177 return self
.fsi
['FX'].asint(msb0
=True)
181 self
.fsi
['FX'].eq(value
)
185 return self
.fsi
['FEX'].asint(msb0
=True)
188 def FEX(self
, value
):
189 self
.fsi
['FEX'].eq(value
)
193 return self
.fsi
['VX'].asint(msb0
=True)
197 self
.fsi
['VX'].eq(value
)
201 return self
.fsi
['OX'].asint(msb0
=True)
205 self
.fsi
['OX'].eq(value
)
209 return self
.fsi
['UX'].asint(msb0
=True)
213 self
.fsi
['UX'].eq(value
)
217 return self
.fsi
['ZX'].asint(msb0
=True)
221 self
.fsi
['ZX'].eq(value
)
225 return self
.fsi
['XX'].asint(msb0
=True)
229 self
.fsi
['XX'].eq(value
)
233 return self
.fsi
['VXSNAN'].asint(msb0
=True)
236 def VXSNAN(self
, value
):
237 self
.fsi
['VXSNAN'].eq(value
)
241 return self
.fsi
['VXISI'].asint(msb0
=True)
244 def VXISI(self
, value
):
245 self
.fsi
['VXISI'].eq(value
)
249 return self
.fsi
['VXIDI'].asint(msb0
=True)
252 def VXIDI(self
, value
):
253 self
.fsi
['VXIDI'].eq(value
)
257 return self
.fsi
['VXZDZ'].asint(msb0
=True)
260 def VXZDZ(self
, value
):
261 self
.fsi
['VXZDZ'].eq(value
)
265 return self
.fsi
['VXIMZ'].asint(msb0
=True)
268 def VXIMZ(self
, value
):
269 self
.fsi
['VXIMZ'].eq(value
)
273 return self
.fsi
['VXVC'].asint(msb0
=True)
276 def VXVC(self
, value
):
277 self
.fsi
['VXVC'].eq(value
)
281 return self
.fsi
['FR'].asint(msb0
=True)
285 self
.fsi
['FR'].eq(value
)
289 return self
.fsi
['FI'].asint(msb0
=True)
293 self
.fsi
['FI'].eq(value
)
297 return self
.fsi
['FPRF'].asint(msb0
=True)
300 def FPRF(self
, value
):
301 self
.fsi
['FPRF'].eq(value
)
305 return self
.fsi
['C'].asint(msb0
=True)
309 self
.fsi
['C'].eq(value
)
313 return self
.fsi
['FPCC'].asint(msb0
=True)
316 def FPCC(self
, value
):
317 self
.fsi
['FPCC'].eq(value
)
321 return self
.fsi
['FL'].asint(msb0
=True)
325 self
.fsi
['FL'].eq(value
)
329 return self
.fsi
['FG'].asint(msb0
=True)
333 self
.fsi
['FG'].eq(value
)
337 return self
.fsi
['FE'].asint(msb0
=True)
341 self
.fsi
['FE'].eq(value
)
345 return self
.fsi
['FU'].asint(msb0
=True)
349 self
.fsi
['FU'].eq(value
)
353 return self
.fsi
['VXSOFT'].asint(msb0
=True)
356 def VXSOFT(self
, value
):
357 self
.fsi
['VXSOFT'].eq(value
)
361 return self
.fsi
['VXSQRT'].asint(msb0
=True)
364 def VXSQRT(self
, value
):
365 self
.fsi
['VXSQRT'].eq(value
)
369 return self
.fsi
['VXCVI'].asint(msb0
=True)
372 def VXCVI(self
, value
):
373 self
.fsi
['VXCVI'].eq(value
)
377 return self
.fsi
['VE'].asint(msb0
=True)
381 self
.fsi
['VE'].eq(value
)
385 return self
.fsi
['OE'].asint(msb0
=True)
389 self
.fsi
['OE'].eq(value
)
393 return self
.fsi
['UE'].asint(msb0
=True)
397 self
.fsi
['UE'].eq(value
)
401 return self
.fsi
['ZE'].asint(msb0
=True)
405 self
.fsi
['ZE'].eq(value
)
409 return self
.fsi
['XE'].asint(msb0
=True)
413 self
.fsi
['XE'].eq(value
)
417 return self
.fsi
['NI'].asint(msb0
=True)
421 self
.fsi
['NI'].eq(value
)
425 return self
.fsi
['RN'].asint(msb0
=True)
429 self
.fsi
['RN'].eq(value
)
432 if __name__
== "__main__":
433 from pprint
import pprint
434 print("FPSCRRecord.layout:")
435 pprint(FPSCRRecord
.layout
)
436 print("FPSCRState.fsi:")
437 pprint(FPSCRState().fsi
)
439 # quick test of setter/getters
442 print(fpscr
.FPCC
, fpscr
.FL
, fpscr
.FG
, fpscr
.FE
, fpscr
.FU
)
444 print(fpscr
.FPCC
, fpscr
.FL
, fpscr
.FG
, fpscr
.FE
, fpscr
.FU
)
446 print(fpscr
.FPRF
, fpscr
.C
)