notes: make FPSCR definition more like MSR (see openpower/consts.py)
[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 FPSCRState(SelectableInt):
94 def __init__(self, value=0):
95 SelectableInt.__init__(self, value, 64)
96 self.fsi = {}
97 offs = 0
98 # set up sub-fields from Record layout
99 self.fsi = {}
100 l = deepcopy(FPSCRRecord.layout)
101 l.reverse()
102 for field, width in l:
103 end = offs+width
104 fs = tuple(range(offs, end))
105 v = FieldSelectableInt(self, fs)
106 self.fsi[field] = v
107 log("SVSTATE setup field", field, offs, end)
108 offs = end
109 # extra fields, temporarily explicitly added. TODO nested layout above
110 extras = [(47, "C"),
111 (48, "FL"),
112 (49, "FG"),
113 (50, "FE"),
114 (51, "FU"),
115 ]
116 for offs, field in extras:
117 end = offs+1
118 fs = tuple(range(offs, end))
119 v = FieldSelectableInt(self, fs)
120 self.fsi[field] = v
121 log("SVSTATE extra field", field, offs, end)
122
123 @property
124 def DRN(self):
125 return self.fsi['DRN'].asint(msb0=True)
126
127 @DRN.setter
128 def DRN(self, value):
129 self.fsi['DRN'].eq(value)
130
131 @property
132 def FX(self):
133 return self.fsi['FX'].asint(msb0=True)
134
135 @FX.setter
136 def FX(self, value):
137 self.fsi['FX'].eq(value)
138
139 @property
140 def FEX(self):
141 return self.fsi['FEX'].asint(msb0=True)
142
143 @FEX.setter
144 def FEX(self, value):
145 self.fsi['FEX'].eq(value)
146
147 @property
148 def VX(self):
149 return self.fsi['VX'].asint(msb0=True)
150
151 @VX.setter
152 def VX(self, value):
153 self.fsi['VX'].eq(value)
154
155 @property
156 def OX(self):
157 return self.fsi['OX'].asint(msb0=True)
158
159 @OX.setter
160 def OX(self, value):
161 self.fsi['OX'].eq(value)
162
163 @property
164 def UX(self):
165 return self.fsi['UX'].asint(msb0=True)
166
167 @UX.setter
168 def UX(self, value):
169 self.fsi['UX'].eq(value)
170
171 @property
172 def ZX(self):
173 return self.fsi['ZX'].asint(msb0=True)
174
175 @ZX.setter
176 def ZX(self, value):
177 self.fsi['ZX'].eq(value)
178
179 @property
180 def XX(self):
181 return self.fsi['XX'].asint(msb0=True)
182
183 @XX.setter
184 def XX(self, value):
185 self.fsi['XX'].eq(value)
186
187 @property
188 def VXSNAN(self):
189 return self.fsi['VXSNAN'].asint(msb0=True)
190
191 @VXSNAN.setter
192 def VXSNAN(self, value):
193 self.fsi['VXSNAN'].eq(value)
194
195 @property
196 def VXISI(self):
197 return self.fsi['VXISI'].asint(msb0=True)
198
199 @VXISI.setter
200 def VXISI(self, value):
201 self.fsi['VXISI'].eq(value)
202
203 @property
204 def VXIDI(self):
205 return self.fsi['VXIDI'].asint(msb0=True)
206
207 @VXIDI.setter
208 def VXIDI(self, value):
209 self.fsi['VXIDI'].eq(value)
210
211 @property
212 def VXZDZ(self):
213 return self.fsi['VXZDZ'].asint(msb0=True)
214
215 @VXZDZ.setter
216 def VXZDZ(self, value):
217 self.fsi['VXZDZ'].eq(value)
218
219 @property
220 def VXIMZ(self):
221 return self.fsi['VXIMZ'].asint(msb0=True)
222
223 @VXIMZ.setter
224 def VXIMZ(self, value):
225 self.fsi['VXIMZ'].eq(value)
226
227 @property
228 def VXVC(self):
229 return self.fsi['VXVC'].asint(msb0=True)
230
231 @VXVC.setter
232 def VXVC(self, value):
233 self.fsi['VXVC'].eq(value)
234
235 @property
236 def FR(self):
237 return self.fsi['FR'].asint(msb0=True)
238
239 @FR.setter
240 def FR(self, value):
241 self.fsi['FR'].eq(value)
242
243 @property
244 def FI(self):
245 return self.fsi['FI'].asint(msb0=True)
246
247 @FI.setter
248 def FI(self, value):
249 self.fsi['FI'].eq(value)
250
251 @property
252 def FPRF(self):
253 return self.fsi['FPRF'].asint(msb0=True)
254
255 @FPRF.setter
256 def FPRF(self, value):
257 self.fsi['FPRF'].eq(value)
258
259 @property
260 def C(self):
261 return self.fsi['C'].asint(msb0=True)
262
263 @C.setter
264 def C(self, value):
265 self.fsi['C'].eq(value)
266
267 @property
268 def FPCC(self):
269 return self.fsi['FPCC'].asint(msb0=True)
270
271 @FPCC.setter
272 def FPCC(self, value):
273 self.fsi['FPCC'].eq(value)
274
275 @property
276 def FL(self):
277 return self.fsi['FL'].asint(msb0=True)
278
279 @FL.setter
280 def FL(self, value):
281 self.fsi['FL'].eq(value)
282
283 @property
284 def FG(self):
285 return self.fsi['FG'].asint(msb0=True)
286
287 @FG.setter
288 def FG(self, value):
289 self.fsi['FG'].eq(value)
290
291 @property
292 def FE(self):
293 return self.fsi['FE'].asint(msb0=True)
294
295 @FE.setter
296 def FE(self, value):
297 self.fsi['FE'].eq(value)
298
299 @property
300 def FU(self):
301 return self.fsi['FU'].asint(msb0=True)
302
303 @FU.setter
304 def FU(self, value):
305 self.fsi['FU'].eq(value)
306
307 @property
308 def VXSOFT(self):
309 return self.fsi['VXSOFT'].asint(msb0=True)
310
311 @VXSOFT.setter
312 def VXSOFT(self, value):
313 self.fsi['VXSOFT'].eq(value)
314
315 @property
316 def VXSQRT(self):
317 return self.fsi['VXSQRT'].asint(msb0=True)
318
319 @VXSQRT.setter
320 def VXSQRT(self, value):
321 self.fsi['VXSQRT'].eq(value)
322
323 @property
324 def VXCVI(self):
325 return self.fsi['VXCVI'].asint(msb0=True)
326
327 @VXCVI.setter
328 def VXCVI(self, value):
329 self.fsi['VXCVI'].eq(value)
330
331 @property
332 def VE(self):
333 return self.fsi['VE'].asint(msb0=True)
334
335 @VE.setter
336 def VE(self, value):
337 self.fsi['VE'].eq(value)
338
339 @property
340 def OE(self):
341 return self.fsi['OE'].asint(msb0=True)
342
343 @OE.setter
344 def OE(self, value):
345 self.fsi['OE'].eq(value)
346
347 @property
348 def UE(self):
349 return self.fsi['UE'].asint(msb0=True)
350
351 @UE.setter
352 def UE(self, value):
353 self.fsi['UE'].eq(value)
354
355 @property
356 def ZE(self):
357 return self.fsi['ZE'].asint(msb0=True)
358
359 @ZE.setter
360 def ZE(self, value):
361 self.fsi['ZE'].eq(value)
362
363 @property
364 def XE(self):
365 return self.fsi['XE'].asint(msb0=True)
366
367 @XE.setter
368 def XE(self, value):
369 self.fsi['XE'].eq(value)
370
371 @property
372 def NI(self):
373 return self.fsi['NI'].asint(msb0=True)
374
375 @NI.setter
376 def NI(self, value):
377 self.fsi['NI'].eq(value)
378
379 @property
380 def RN(self):
381 return self.fsi['RN'].asint(msb0=True)
382
383 @RN.setter
384 def RN(self, value):
385 self.fsi['RN'].eq(value)
386
387
388 if __name__ == "__main__":
389 from pprint import pprint
390 print("FPSCRRecord.layout:")
391 pprint(FPSCRRecord.layout)
392 print("FPSCRState.fsi:")
393 pprint(FPSCRState().fsi)
394
395 # quick test of setter/getters
396 fpscr = FPSCRState()
397 fpscr.FPCC = 0b001
398 print (fpscr.FPCC, fpscr.FL, fpscr.FG, fpscr.FE, fpscr.FU)
399 fpscr.FG = 0b1
400 print (fpscr.FPCC, fpscr.FL, fpscr.FG, fpscr.FE, fpscr.FU)
401 fpscr.FPRF = 0b11
402 print (fpscr.FPRF, fpscr.C)
403 fpscr[63] = 1
404 print (fpscr.RN)