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, *, auto_update_summary_bits
=True):
133 self
.__do
_update
_summary
_bits
= False
134 SelectableInt
.__init
__(self
, value
, 64)
137 # set up sub-fields from Record layout
139 for field
, width
in reversed(FPSCRRecord
.layout
):
141 v
= FPSCR_FPRF(self
, tuple(range(47, 52)))
145 fs
= tuple(range(offs
, end
))
146 v
= FieldSelectableInt(self
, fs
)
149 # extra fields, temporarily explicitly added. TODO nested layout above
152 (range(48, 52), "FPCC"),
158 for offs
, field
in extras
:
159 if isinstance(offs
, int):
163 v
= FieldSelectableInt(self
, fs
)
165 if auto_update_summary_bits
:
166 self
.__update
_summary
_bits
()
173 def value(self
, value
):
175 if self
.__do
_update
_summary
_bits
:
176 self
.__update
_summary
_bits
()
178 def __update_summary_bits(self
):
179 self
.__do
_update
_summary
_bits
= False
181 # update summary bits -- FX is manually handled by pseudo-code,
182 # so we don't update it here
183 self
.VX
= (self
.VXSNAN |
192 self
.FEX
= ((self
.VX
& self
.VE
) |
193 (self
.OX
& self
.OE
) |
194 (self
.UX
& self
.UE
) |
195 (self
.ZX
& self
.ZE
) |
198 self
.__do
_update
_summary
_bits
= True
202 return self
.fsi
['DRN'].asint(msb0
=True)
205 def DRN(self
, value
):
206 self
.fsi
['DRN'].eq(value
)
210 return self
.fsi
['FX'].asint(msb0
=True)
214 self
.fsi
['FX'].eq(value
)
218 return self
.fsi
['FEX'].asint(msb0
=True)
221 def FEX(self
, value
):
222 self
.fsi
['FEX'].eq(value
)
226 return self
.fsi
['VX'].asint(msb0
=True)
230 self
.fsi
['VX'].eq(value
)
234 return self
.fsi
['OX'].asint(msb0
=True)
238 self
.fsi
['OX'].eq(value
)
242 return self
.fsi
['UX'].asint(msb0
=True)
246 self
.fsi
['UX'].eq(value
)
250 return self
.fsi
['ZX'].asint(msb0
=True)
254 self
.fsi
['ZX'].eq(value
)
258 return self
.fsi
['XX'].asint(msb0
=True)
262 self
.fsi
['XX'].eq(value
)
266 return self
.fsi
['VXSNAN'].asint(msb0
=True)
269 def VXSNAN(self
, value
):
270 self
.fsi
['VXSNAN'].eq(value
)
274 return self
.fsi
['VXISI'].asint(msb0
=True)
277 def VXISI(self
, value
):
278 self
.fsi
['VXISI'].eq(value
)
282 return self
.fsi
['VXIDI'].asint(msb0
=True)
285 def VXIDI(self
, value
):
286 self
.fsi
['VXIDI'].eq(value
)
290 return self
.fsi
['VXZDZ'].asint(msb0
=True)
293 def VXZDZ(self
, value
):
294 self
.fsi
['VXZDZ'].eq(value
)
298 return self
.fsi
['VXIMZ'].asint(msb0
=True)
301 def VXIMZ(self
, value
):
302 self
.fsi
['VXIMZ'].eq(value
)
306 return self
.fsi
['VXVC'].asint(msb0
=True)
309 def VXVC(self
, value
):
310 self
.fsi
['VXVC'].eq(value
)
314 return self
.fsi
['FR'].asint(msb0
=True)
318 self
.fsi
['FR'].eq(value
)
322 return self
.fsi
['FI'].asint(msb0
=True)
326 self
.fsi
['FI'].eq(value
)
330 return self
.fsi
['FPRF'].asint(msb0
=True)
333 def FPRF(self
, value
):
334 self
.fsi
['FPRF'].eq(value
)
338 return self
.fsi
['C'].asint(msb0
=True)
342 self
.fsi
['C'].eq(value
)
346 return self
.fsi
['FPCC'].asint(msb0
=True)
349 def FPCC(self
, value
):
350 self
.fsi
['FPCC'].eq(value
)
354 return self
.fsi
['FL'].asint(msb0
=True)
358 self
.fsi
['FL'].eq(value
)
362 return self
.fsi
['FG'].asint(msb0
=True)
366 self
.fsi
['FG'].eq(value
)
370 return self
.fsi
['FE'].asint(msb0
=True)
374 self
.fsi
['FE'].eq(value
)
378 return self
.fsi
['FU'].asint(msb0
=True)
382 self
.fsi
['FU'].eq(value
)
386 return self
.fsi
['VXSOFT'].asint(msb0
=True)
389 def VXSOFT(self
, value
):
390 self
.fsi
['VXSOFT'].eq(value
)
394 return self
.fsi
['VXSQRT'].asint(msb0
=True)
397 def VXSQRT(self
, value
):
398 self
.fsi
['VXSQRT'].eq(value
)
402 return self
.fsi
['VXCVI'].asint(msb0
=True)
405 def VXCVI(self
, value
):
406 self
.fsi
['VXCVI'].eq(value
)
410 return self
.fsi
['VE'].asint(msb0
=True)
414 self
.fsi
['VE'].eq(value
)
418 return self
.fsi
['OE'].asint(msb0
=True)
422 self
.fsi
['OE'].eq(value
)
426 return self
.fsi
['UE'].asint(msb0
=True)
430 self
.fsi
['UE'].eq(value
)
434 return self
.fsi
['ZE'].asint(msb0
=True)
438 self
.fsi
['ZE'].eq(value
)
442 return self
.fsi
['XE'].asint(msb0
=True)
446 self
.fsi
['XE'].eq(value
)
450 return self
.fsi
['NI'].asint(msb0
=True)
454 self
.fsi
['NI'].eq(value
)
458 return self
.fsi
['RN'].asint(msb0
=True)
462 self
.fsi
['RN'].eq(value
)
465 if __name__
== "__main__":
466 from pprint
import pprint
467 print("FPSCRRecord.layout:")
468 pprint(FPSCRRecord
.layout
)
469 print("FPSCRState.fsi:")
470 pprint(FPSCRState().fsi
)
472 # quick test of setter/getters
475 print(fpscr
.FPCC
, fpscr
.FL
, fpscr
.FG
, fpscr
.FE
, fpscr
.FU
)
477 print(fpscr
.FPCC
, fpscr
.FL
, fpscr
.FG
, fpscr
.FE
, fpscr
.FU
)
479 print(fpscr
.FPRF
, fpscr
.C
)