1 from collections
import namedtuple
6 from openpower
.decoder
.power_enums
import find_wiki_file
7 from openpower
.decoder
.selectable_int
import (
15 class RemapError(ValueError):
20 def __init__(self
, cls
):
22 return super().__init
__()
24 def __get__(self
, instance
, owner
):
27 return self
.__cls
(storage
=instance
.storage
)
29 def __set__(self
, instance
, value
):
31 raise AttributeError("read-only attribute")
32 self
.__cls
(storage
=instance
.storage
).assign(value
)
35 @functools.total_ordering
37 def __init__(self
, storage
, *args
, **kwargs
):
38 if not isinstance(storage
, SelectableInt
):
39 raise ValueError(storage
)
41 self
.storage
= storage
46 def __post_init__(self
, *args
, **kwargs
):
49 def __binary_operator(self
, op
, other
):
50 span
= dict.fromkeys(self
.__class
__.span
).keys()
51 lhs
= selectconcat(*(self
.storage
[bit
] for bit
in span
))
53 if isinstance(other
, Reference
):
54 span
= dict.fromkeys(other
.__class
__.span
).keys()
55 rhs
= selectconcat(*(other
.storage
[bit
] for bit
in span
))
56 elif isinstance(other
, int):
57 bits
= len(self
.__class
__)
58 if other
.bit_length() > bits
:
59 raise OverflowError(other
)
60 rhs
= SelectableInt(value
=other
, bits
=bits
)
61 elif isinstance(other
, SelectableInt
):
64 raise ValueError(other
)
68 def __lt__(self
, other
):
69 return self
.__binary
_operator
(selectltu
, other
)
71 def __eq__(self
, other
):
72 return self
.__binary
_operator
(operator
.eq
, other
)
75 return bool(int(self
))
78 span
= dict.fromkeys(self
.__class
__.span
).keys()
79 return int(selectconcat(*(self
.storage
[bit
] for bit
in span
)))
82 return int(self
).__index
__()
89 def storage(self
, storage
):
90 if not isinstance(storage
, SelectableInt
):
91 raise ValueError(storage
)
93 self
.__storage
= storage
95 def assign(self
, value
, bits
=None):
97 bits
= range(len(self
.__class
__))
98 elif isinstance(bits
, int):
100 elif isinstance(bits
, slice):
101 assert bits
.step
is None or bits
.step
== 1
102 bits
= range(bits
.start
, bits
.stop
)
105 if isinstance(value
, (int, self
.__class
__)):
107 if value
.bit_length() > len(bits
):
108 raise OverflowError(value
)
109 value
= SelectableInt(value
=value
, bits
=len(bits
))
110 if not isinstance(value
, SelectableInt
):
111 raise ValueError(value
)
112 if value
.bits
!= len(bits
):
113 raise OverflowError(value
)
115 span
= tuple(self
.__class
__.span
)
116 mapping
= dict(enumerate(span
))
117 for (src
, bit
) in enumerate(bits
):
118 if src
>= value
.bits
:
119 raise OverflowError(src
)
120 dst
= mapping
.get(bit
)
122 raise OverflowError(bit
)
123 self
.storage
[dst
] = value
[src
]
126 class FieldMeta(type):
127 def __new__(metacls
, clsname
, bases
, ns
, items
=()):
128 assert "__members__" not in ns
132 if not isinstance(item
, int):
133 raise ValueError(item
)
135 raise ValueError(item
)
138 ns
["__members__"] = tuple(members
)
140 return super().__new
__(metacls
, clsname
, bases
, ns
)
143 if not cls
.__members
__:
145 return f
"{cls.__name__}{cls.__members__!r}"
148 yield from cls
.__members
__
151 return len(cls
.__members
__)
153 def __getitem__(cls
, selector
):
154 if isinstance(selector
, int):
155 selector
= (selector
,)
159 if not isinstance(idx
, int):
160 raise ValueError(selector
)
161 item
= cls
.__members
__[idx
]
164 return cls
.__class
__(cls
.__name
__, (Field
,), {}, items
=items
)
166 def remap(cls
, scheme
):
167 if isinstance(scheme
, type) and issubclass(scheme
, Mapping
):
168 scheme
= range(len(scheme
))
169 scheme
= cls
.__class
__(cls
.__name
__, (cls
,), {}, items
=scheme
)
173 elif len(cls
) > len(scheme
):
174 llen
= f
"len(scheme)"
175 rlen
= f
"len({cls.__name__})"
176 raise RemapError(f
"{llen} != {rlen}")
179 ns
["__doc__"] = cls
.__doc
__
180 items
= map(lambda item
: scheme
.__members
__[item
], cls
)
182 return cls
.__class
__(cls
.__name
__, (cls
,), ns
, items
=items
)
186 return cls
.__members
__
189 class Field(Reference
, metaclass
=FieldMeta
):
191 return f
"[{len(self.__class__)}]0x{int(self):x}"
194 for bit
in self
.__class
__:
195 yield self
.storage
[bit
]
197 def __getitem__(self
, key
):
198 if isinstance(key
, int):
199 bit
= self
.storage
[self
.__class
__.__members
__[key
]]
200 return SelectableInt(value
=bit
, bits
=1)
201 if isinstance(key
, slice):
202 assert key
.step
is None or key
.step
== 1
203 key
= range(key
.start
, key
.stop
)
205 return selectconcat(*(self
[bit
] for bit
in key
))
207 def __setitem__(self
, key
, value
):
208 return self
.assign(value
=value
, bits
=key
)
211 def traverse(cls
, path
):
212 yield (path
, cls
.__members
__)
215 class MappingMeta(type):
216 def __new__(metacls
, clsname
, bases
, ns
):
220 if isinstance(cls
, metacls
):
221 members
.update(cls
.__members
__)
223 for (name
, cls
) in ns
.get("__annotations__", {}).items():
224 if not (isinstance(cls
, type) and
225 issubclass(cls
, (Mapping
, Field
))):
226 raise ValueError(f
"{clsname}.{name}: {cls!r}")
230 members
[name
] = cls
.remap(ns
[name
])
231 except RemapError
as error
:
232 raise RemapError(f
"{name}: {error}")
235 raise ValueError(f
"{clsname}.{name}: missing initializer")
238 ns
["__members__"] = members
239 for (name
, cls
) in members
.items():
240 ns
[name
] = Descriptor(cls
)
242 return super().__new
__(metacls
, clsname
, bases
, ns
)
245 return f
"{cls.__name__}({cls.__members__!r})"
248 yield from cls
.__members
__.items()
252 for field
in cls
.__members
__.values():
253 length
= max(length
, len(field
))
256 def __getitem__(cls
, selector
):
257 return cls
.__members
__["_"][selector
]
259 def remap(cls
, scheme
):
263 for (name
, field
) in cls
:
264 annotations
[name
] = field
.remap(scheme
)
265 ns
["__annotations__"] = annotations
266 ns
["__doc__"] = cls
.__doc
__
268 return cls
.__class
__(cls
.__name
__, (cls
,), ns
)
272 for field
in cls
.__members
__.values():
273 yield from field
.span
276 class Mapping(Reference
, metaclass
=MappingMeta
):
277 def __init__(self
, storage
, **kwargs
):
279 for (name
, cls
) in self
.__class
__:
280 members
[name
] = cls(storage
)
282 self
.__members
= members
284 return super().__init
__(storage
, **kwargs
)
287 items
= tuple(f
"{name}={field!r}" for (name
, field
) in self
)
288 return f
"{{{', '.join(items)}}}"
291 yield from self
.__members
.items()
293 def __getitem__(self
, key
):
294 if isinstance(key
, (int, slice, list, tuple, range)):
295 return self
["_"].__getitem
__(key
)
297 return self
.__members
.__getitem
__(key
)
299 def __setitem__(self
, key
, value
):
300 if isinstance(key
, (int, slice, list, tuple, range)):
301 return self
["_"].assign(value
=value
, bits
=key
)
303 return self
.assign(value
=value
, bits
=key
)
305 def __getattr__(self
, key
):
306 raise AttributeError(key
)
309 def traverse(cls
, path
):
310 for (name
, member
) in cls
.__members
__.items():
312 yield from member
.traverse(path
=path
)
314 yield from member
.traverse(path
=name
)
316 yield from member
.traverse(path
=f
"{path}.{name}")
319 def decode_instructions(form
):
323 if l
.strip().startswith("Formats"):
324 l
= l
.strip().split(":")[-1]
325 l
= l
.replace(" ", "")
329 res
[fmt
] = [accum
[0]]
331 res
[fmt
].append(accum
[0])
334 accum
.append(l
.strip())
338 def decode_form_header(hdr
):
342 for f
in hdr
.split("|"):
346 idx
= int(f
.strip().split(' ')[0])
352 def find_unique(d
, key
):
356 while "%s_%d" % (key
, idx
) in d
:
358 return "%s_%d" % (key
, idx
)
361 def decode_line(header
, line
):
365 prev_fieldname
= None
366 for f
in line
.split("|"):
369 end
= count
+ len(f
) + 1
370 fieldname
= f
.strip()
371 if not fieldname
or fieldname
.startswith('/'):
372 if prev_fieldname
is not None:
373 res
[prev_fieldname
] = (res
[prev_fieldname
], header
[count
])
374 prev_fieldname
= None
377 bitstart
= header
[count
]
378 if prev_fieldname
is not None:
379 res
[prev_fieldname
] = (res
[prev_fieldname
], bitstart
)
380 res
[fieldname
] = bitstart
382 prev_fieldname
= fieldname
383 res
[prev_fieldname
] = (bitstart
, 32)
387 def decode_form(form
):
388 header
= decode_form_header(form
[0])
390 for line
in form
[1:]:
391 dec
= decode_line(header
, line
)
397 for k
, (start
, end
) in l
.items():
399 if (start
, end
) == fields
[k
]:
400 continue # already in and matching for this Form
402 alternate
= "%s_%d" % (k
, falternate
[k
])
403 if (start
, end
) == fields
[alternate
]:
405 falternate
[k
] = fidx
= falternate
.get(k
, 0) + 1
406 fields
["%s_%d" % (k
, fidx
)] = (start
, end
)
408 fields
[k
] = (start
, end
)
414 def __init__(self
, bitkls
=BitRange
, bitargs
=(), fname
=None,
417 self
.bitargs
= bitargs
419 assert name_on_wiki
is None
421 name_on_wiki
= "fields.text"
422 self
.fname
= find_wiki_file(name_on_wiki
)
425 def form_names(self
):
426 return self
.instrs
.keys()
428 def create_specs(self
):
429 self
.forms
, self
.instrs
= self
.decode_fields()
430 forms
= self
.form_names
431 #print ("specs", self.forms, forms)
433 fields
= self
.instrs
[form
]
435 Fields
= namedtuple("Fields", fk
)
436 instr
= Fields(**fields
)
437 setattr(self
, "Form%s" % form
, instr
)
438 # now add in some commonly-used fields (should be done automatically)
439 # note that these should only be ones which are the same on all Forms
440 # note: these are from microwatt insn_helpers.vhdl
441 self
.common_fields
= {
442 "PO": self
.Formall
.PO
,
443 "FRS": self
.FormX
.FRS
,
444 "FRT": self
.FormX
.FRT
,
445 "FRA": self
.FormX
.FRA
,
446 "FRB": self
.FormX
.FRB
,
447 "FRC": self
.FormA
.FRC
,
452 "RC": self
.FormVA
.RC
,
456 "SH32": self
.FormM
.SH
,
457 "sh": self
.FormMD
.sh
,
458 "MB32": self
.FormM
.MB
,
459 "ME32": self
.FormM
.ME
,
464 "OE": self
.FormXO
.OE
,
467 "CR": self
.FormXL
.XO
,
468 "BB": self
.FormXL
.BB
,
469 "BA": self
.FormXL
.BA
,
470 "BT": self
.FormXL
.BT
,
471 "FXM": self
.FormXFX
.FXM
,
472 "BO": self
.FormXL
.BO
,
473 "BI": self
.FormXL
.BI
,
474 "BH": self
.FormXL
.BH
,
476 "DS": self
.FormDS
.DS
,
482 "SPR": self
.FormXFX
.SPR
}
483 for k
, v
in self
.common_fields
.items():
486 def decode_fields(self
):
487 with
open(self
.fname
) as f
:
489 #print ("decode", txt)
492 for lineno
, l
in enumerate(txt
):
500 form
= forms
[heading
]
504 # check separators line up with header
505 for i
, ch
in enumerate(l
):
508 if i
>= len(form
[0]) or form
[0][i
] != '|':
509 col
= len(txt
[lineno
]) - len(txt
[lineno
].lstrip())
511 raise SyntaxError("form line field separator ('|') "
512 "with no corresponding separator in header",
513 (self
.fname
, lineno
+ 1, col
, txt
[lineno
]))
516 heading
= l
[1:].strip()
517 # if heading.startswith('1.6.28'): # skip instr fields for now
519 heading
= heading
.split(' ')[-1]
526 for hdr
, form
in forms
.items():
527 if heading
== 'Fields':
528 i
= decode_instructions(form
)
529 for form
, field
in i
.items():
530 inst
[form
] = self
.decode_instruction_fields(field
)
532 # res[hdr] = decode_form(form)
535 def decode_instruction_fields(self
, fields
):
538 f
, spec
= field
.strip().split(" ")
539 ss
= spec
[1:-1].split(",")
542 individualfields
= []
543 for f0
, s0
in zip(fs
, ss
):
544 txt
= "%s (%s)" % (f0
, s0
)
545 individualfields
.append(txt
)
547 res
.update(self
.decode_instruction_fields(
549 d
= self
.bitkls(*self
.bitargs
)
563 f
= f
.replace(",", "_")
564 unique
= find_unique(res
, f
)
570 if __name__
== '__main__':
573 forms
, instrs
= dec
.forms
, dec
.instrs
574 for form
, fields
in instrs
.items():
576 for field
, bits
in fields
.items():
577 print("\tfield", field
, bits
)