sv_binutils: use ppc_opindex_t instead of unsigned char
[openpower-isa.git] / src / openpower / sv / sv_binutils.py
1 import abc as _abc
2 import argparse as _argparse
3 import dataclasses as _dataclasses
4 import enum as _enum
5 import operator as _operator
6
7 from openpower.decoder.power_enums import (
8 In1Sel as _In1Sel,
9 In2Sel as _In2Sel,
10 In3Sel as _In3Sel,
11 OutSel as _OutSel,
12 CRInSel as _CRInSel,
13 CROutSel as _CROutSel,
14 SVPtype as _SVPtype,
15 SVEtype as _SVEtype,
16 SVEXTRA as _SVEXTRA,
17 RC as _RC,
18 )
19 from openpower.consts import SVP64MODE as _SVP64MODE
20 from openpower.decoder.power_svp64 import SVP64RM as _SVP64RM
21 from openpower.decoder.isa.caller import SVP64RMFields as _SVP64RMFields
22 from openpower.decoder.isa.caller import SVP64PrefixFields as _SVP64PrefixFields
23 from openpower.decoder.selectable_int import SelectableIntMapping
24
25
26 DISCLAIMER = """\
27 /* {path} -- {desc}
28 Copyright (C) 2022 Free Software Foundation, Inc.
29 Written by Dmitry Selyutin (ghostmansd).
30 Sponsored by NLnet and NGI POINTER under EU Grants 871528 and 957073.
31
32 This file is part of the GNU opcodes library.
33
34 This library is free software; you can redistribute it and/or modify
35 it under the terms of the GNU General Public License as published by
36 the Free Software Foundation; either version 3, or (at your option)
37 any later version.
38
39 It is distributed in the hope that it will be useful, but WITHOUT
40 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
41 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
42 License for more details.
43
44 You should have received a copy of the GNU General Public License
45 along with this file; see the file COPYING. If not, write to the
46 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
47 MA 02110-1301, USA. */\
48 """
49
50
51 def indent(strings):
52 return map(lambda string: (" " + string), strings)
53
54
55 class CTypeMeta(type):
56 def __new__(metacls, name, bases, attrs, typedef=None):
57 cls = super().__new__(metacls, name, bases, attrs)
58 cls.__typedef = typedef
59
60 return cls
61
62 def __getitem__(cls, size):
63 name = f"{cls.__name__}[{'' if size is Ellipsis else size}]"
64 return type(name, (Array,), {}, type=cls, size=size)
65
66 @property
67 def c_typedef(cls):
68 return cls.__typedef
69
70 @_abc.abstractmethod
71 def c_decl(cls):
72 yield from ()
73
74 def c_var(cls, name, prefix="", suffix=""):
75 return f"{prefix}{cls.c_typedef} {name}{suffix}"
76
77
78 class ArrayMeta(CTypeMeta):
79 def __new__(metacls, name, bases, attrs, type, size, **kwargs):
80 cls = super().__new__(metacls, name, bases, attrs, **kwargs)
81 cls.__type = type
82 cls.__ellipsis = (size is Ellipsis)
83 cls.__size = 0 if cls.__ellipsis else size
84
85 return cls
86
87 def __len__(cls):
88 return cls.__size
89
90 def c_decl(cls):
91 size = "" if cls.__ellipsis else f"{cls.__size}"
92 yield f"{cls.__type.c_typedef}[{size}]"
93
94 def c_var(cls, name, prefix="", suffix=""):
95 size = "" if cls.__ellipsis else f"{cls.__size}"
96 return f"{prefix}{cls.__type.c_typedef} {name}[{size}]{suffix}"
97
98
99 class BitmapMeta(CTypeMeta):
100 def __new__(metacls, name, bases, attrs,
101 typedef="uint64_t", bits=0, **kwargs):
102 cls = super().__new__(metacls, name, bases, attrs,
103 typedef=typedef, **kwargs)
104 cls.__bits = bits
105 return cls
106
107 def __len__(cls):
108 return cls.__bits
109
110 def c_var(cls, name, prefix="", suffix=""):
111 return f"{prefix}{cls.c_typedef} {name} : {cls.__bits}{suffix}"
112
113
114 class CType(metaclass=CTypeMeta):
115 @_abc.abstractmethod
116 def c_value(self, *, prefix="", suffix="", **kwargs):
117 yield from ()
118
119
120 class Array(CType, tuple, metaclass=ArrayMeta, type=CType, size=...):
121 def c_value(self, *, prefix="", suffix="", **kwargs):
122 yield f"{prefix}{{"
123 for (index, item) in enumerate(self):
124 yield from indent(item.c_value(suffix=","))
125 yield f"}}{suffix}"
126
127
128 class Bitmap(metaclass=BitmapMeta):
129 pass
130
131
132 class Void(CType, typedef="void"):
133 def c_var(cls, name, prefix="", suffix=""):
134 raise NotImplementedError
135
136
137 class EnumMeta(_enum.EnumMeta, CTypeMeta):
138 def __call__(metacls, name, entries, tag=None, **kwargs):
139 if isinstance(entries, type) and issubclass(entries, _enum.Enum):
140 # Use __members__, not __iter__, otherwise aliases are lost.
141 entries = dict(entries.__members__)
142 if isinstance(entries, dict):
143 entries = tuple(entries.items())
144 if tag is None:
145 tag = f"svp64_{name.lower()}"
146
147 cls = super().__call__(value=name, names=entries, **kwargs)
148 cls.__tag = tag
149
150 return cls
151
152 @property
153 def c_typedef(cls):
154 return f"enum {cls.c_tag}"
155
156 @property
157 def c_tag(cls):
158 return cls.__tag
159
160 def c_decl(cls):
161 yield f"{cls.c_typedef} {{"
162 for item in cls:
163 yield from indent(item.c_value(suffix=","))
164 yield f"}};"
165
166 def c_var(cls, name, prefix="", suffix=""):
167 return f"{prefix}{cls.c_typedef} {name}{suffix}"
168
169
170 class Enum(CType, _enum.Enum, metaclass=EnumMeta):
171 @property
172 def c_name(self):
173 return f"{self.__class__.c_tag.upper()}_{self.name.upper()}"
174
175 def c_value(self, *, prefix="", suffix="", **kwargs):
176 yield f"{prefix}{self.c_name}{suffix}"
177
178
179 In1Sel = Enum("In1Sel", _In1Sel, tag="svp64_in1_sel")
180 In2Sel = Enum("In2Sel", _In2Sel, tag="svp64_in2_sel")
181 In3Sel = Enum("In3Sel", _In3Sel, tag="svp64_in3_sel")
182 OutSel = Enum("OutSel", _OutSel, tag="svp64_out_sel")
183 CRInSel = Enum("CRInSel", _CRInSel, tag="svp64_cr_in_sel")
184 CROutSel = Enum("CROutSel", _CROutSel, tag="svp64_cr_out_sel")
185 SVPType = Enum("SVPType", _SVPtype, tag="svp64_sv_ptype")
186 SVEType = Enum("SVEType", _SVEtype, tag="svp64_sv_etype")
187 SVEXTRA = Enum("SVEXTRA", _SVEXTRA, tag="svp64_sv_extra")
188
189
190 class Constant(CType, _enum.Enum, metaclass=EnumMeta):
191 @classmethod
192 def c_decl(cls):
193 yield f"/* {cls.c_tag.upper()} constants */"
194 # Use __members__, not __iter__, otherwise aliases are lost.
195 for (key, item) in cls.__members__.items():
196 key = f"{cls.c_tag.upper()}_{key.upper()}"
197 value = f"0x{item.value:08x}U"
198 yield f"#define {key} {value}"
199
200 def c_value(self, *, prefix="", suffix="", **kwargs):
201 yield f"{prefix}{self.__class__.c_tag.upper()}_{self.c_name.upper()}{suffix}"
202
203
204 Mode = Constant("Mode", _SVP64MODE)
205
206
207 class StructMeta(CTypeMeta):
208 def __new__(metacls, name, bases, attrs, tag=None, **kwargs):
209 if tag is None:
210 tag = f"svp64_{name.lower()}"
211 if "typedef" not in kwargs:
212 kwargs["typedef"] = f"struct {tag}"
213
214 cls = super().__new__(metacls, name, bases, attrs, **kwargs)
215 cls.__tag = tag
216
217 return cls
218
219 @property
220 def c_tag(cls):
221 return cls.__tag
222
223 def c_decl(cls):
224 yield f"{cls.c_typedef} {{"
225 for field in _dataclasses.fields(cls):
226 yield from indent([field.type.c_var(name=f"{field.name}",
227 suffix=";")])
228 yield f"}};"
229
230
231 @_dataclasses.dataclass(eq=True, frozen=True)
232 class Struct(CType, metaclass=StructMeta):
233 def c_value(self, *, prefix="", suffix="", **kwargs):
234 yield f"{prefix}{{"
235 for field in _dataclasses.fields(self):
236 name = field.name
237 attr = getattr(self, name)
238 yield from indent(attr.c_value(prefix=f".{name} = ", suffix=","))
239 yield f"}}{suffix}"
240
241
242 class Integer(CType, str):
243 def c_value(self, *, prefix="", suffix="", **kwargs):
244 yield f"{prefix}{self}{suffix}"
245
246
247 class Byte(Integer, typedef="uint8_t"):
248 pass
249
250
251 class Size(Integer, typedef="size_t"):
252 pass
253
254
255 class UInt32(Integer, typedef="uint32_t"):
256 pass
257
258
259 class Name(CType, str):
260 def __repr__(self):
261 escaped = self.replace("\"", "\\\"")
262 return f"\"{escaped}\""
263
264 def c_value(self, *, prefix="", suffix="", **kwargs):
265 yield f"{prefix}{self!r}{suffix}"
266
267 @classmethod
268 def c_var(cls, name, prefix="", suffix=""):
269 return f"{prefix}const char *{name}{suffix}"
270
271
272 @_dataclasses.dataclass(eq=True, frozen=True)
273 class Record(Struct):
274 in1: In1Sel
275 in2: In2Sel
276 in3: In3Sel
277 out: OutSel
278 out2: OutSel
279 cr_in: CRInSel
280 cr_out: CROutSel
281 sv_ptype: SVPType
282 sv_etype: SVEType
283 sv_in1: SVEXTRA
284 sv_in2: SVEXTRA
285 sv_in3: SVEXTRA
286 sv_out: SVEXTRA
287 sv_out2: SVEXTRA
288 sv_cr_in: SVEXTRA
289 sv_cr_out: SVEXTRA
290
291 @classmethod
292 def c_decl(cls):
293 bits_all = 0
294 yield f"struct svp64_record {{"
295 for field in _dataclasses.fields(cls):
296 bits = len(field.type).bit_length()
297 yield from indent([f"uint64_t {field.name} : {bits};"])
298 bits_all += bits
299 bits_rsvd = (64 - (bits_all % 64))
300 if bits_rsvd:
301 yield from indent([f"uint64_t : {bits_rsvd};"])
302 yield f"}};"
303
304
305 @_dataclasses.dataclass(eq=True, frozen=True)
306 class Entry(Struct):
307 name: Name
308 record: Record
309
310 def __lt__(self, other):
311 if not isinstance(other, self.__class__):
312 return NotImplemented
313
314 return self.name < other.name
315
316
317 class FunctionMeta(CTypeMeta):
318 def __new__(metacls, name, bases, attrs, rv, args):
319 cls = super().__new__(metacls, name, bases, attrs)
320 cls.__rv = rv
321 cls.__args = args
322
323 return cls
324
325 def c_var(cls, name, prefix="", suffix=""):
326 rv = cls.__rv.c_typedef
327 args = ", ".join(arg_cls.c_var(arg_name) \
328 for (arg_name, arg_cls) in cls.__args)
329 return f"{prefix}{rv} {name}({args}){suffix}"
330
331
332 class FieldsMappingMeta(EnumMeta):
333 class HelperMeta(FunctionMeta):
334 def __new__(metacls, name, bases, attrs, rv, args, enum):
335 cls = super().__new__(metacls, name, bases, attrs, rv=rv, args=args)
336 cls.__enum = enum
337 return cls
338
339 def __iter__(cls):
340 short_c_tag = cls.__enum.c_tag[:-len("_field")]
341 # Use __members__, not __iter__, otherwise aliases are lost.
342 for (name, value) in cls.__enum.__members__.items():
343 yield (f"{short_c_tag}_{name}".upper(), value)
344
345 class GetterMeta(HelperMeta):
346 def __new__(metacls, name, bases, attrs, enum, struct):
347 return super().__new__(metacls, name, bases, attrs,
348 enum=enum, rv=UInt32, args=(
349 ("storage", struct),
350 ("field", enum),
351 ))
352
353 class SetterMeta(HelperMeta):
354 def __new__(metacls, name, bases, attrs, enum, struct):
355 return super().__new__(metacls, name, bases, attrs, enum=enum,
356 rv=Void, args=(
357 ("*storage", struct),
358 ("field", enum),
359 ("value", UInt32),
360 ))
361
362 def __call__(metacls, name, base=SelectableIntMapping, **kwargs):
363 def flatten(mapping, parent=""):
364 for (key, value) in mapping.items():
365 key = f"{parent}_{key}" if parent else key
366 if isinstance(value, dict):
367 yield from flatten(mapping=value, parent=key)
368 else:
369 value = map(lambda bit: bit, reversed(value))
370 # value = map(lambda bit: ((base.bits - 1) - bit),
371 # reversed(value))
372 yield (key.upper(), tuple(value))
373
374 tag = f"svp64_{name.lower()}"
375 fields = dict(flatten(mapping=dict(base)))
376 bitmap = type(name, (Bitmap,), {}, typedef="uint32_t", bits=base.bits)
377 struct = _dataclasses.make_dataclass(name, (("value", bitmap),),
378 bases=(Struct,), frozen=True, eq=True)
379
380 cls = super().__call__(name=name, entries=fields, tag=f"{tag}_field",
381 **kwargs)
382
383 def c_value(fields, stmt):
384 yield "switch (field) {"
385 for (field_name, field_value) in fields:
386 yield from indent([f"case {field_name}:"])
387 yield from indent(indent(map(stmt,
388 enumerate(field_value.value))))
389 yield from indent(indent(["break;"]))
390 yield "}"
391
392 class Getter(metaclass=FieldsMappingMeta.GetterMeta,
393 enum=cls, struct=struct):
394 def c_value(self, prefix="", suffix=""):
395 yield f"{prefix}{{"
396 yield from indent([
397 UInt32.c_var(name="result", suffix=" = UINT32_C(0);"),
398 UInt32.c_var(name="origin", suffix=" = storage.value;"),
399 ])
400 yield ""
401 yield from indent(c_value(fields=self.__class__,
402 stmt=lambda kv: f"result |= SVP64_FIELD_GET(origin, {kv[1]}, {kv[0]});"))
403 yield ""
404 yield from indent(["return result;"])
405 yield f"}}{suffix}"
406
407 class Setter(metaclass=FieldsMappingMeta.SetterMeta,
408 enum=cls, struct=struct):
409 def c_value(self, prefix="", suffix=""):
410 yield f"{prefix}{{"
411 yield from indent([
412 UInt32.c_var(name="result", suffix=" = storage->value;"),
413 ])
414 yield ""
415 yield from indent(c_value(fields=self.__class__,
416 stmt=lambda kv: f"SVP64_FIELD_SET(&result, value, {kv[0]}, {kv[1]});"))
417 yield ""
418 yield from indent(["storage->value = result;"])
419 yield f"}}{suffix}"
420
421 cls.__tag = tag
422 cls.__struct = struct
423 cls.__getter = Getter()
424 cls.__setter = Setter()
425
426 return cls
427
428 @property
429 def c_getter(cls):
430 return cls.__getter
431
432 @property
433 def c_setter(cls):
434 return cls.__setter
435
436 def c_decl(cls):
437 yield f"{cls.c_typedef} {{"
438 for field_name in cls.__members__.keys():
439 short_c_tag = cls.c_tag[:-len("_field")]
440 yield from indent([f"{short_c_tag}_{field_name},".upper()])
441 yield f"}};"
442 yield from cls.__struct.c_decl()
443 yield cls.__getter.__class__.c_var(name=f"{cls.__tag}_get", suffix=";")
444 yield cls.__setter.__class__.c_var(name=f"{cls.__tag}_set", suffix=";")
445
446
447 class FieldsMapping(Enum, metaclass=FieldsMappingMeta):
448 @property
449 def c_name(self):
450 short_c_tag = self.__class__.c_tag[:-len("_field")]
451 return f"{short_c_tag}_{self.name}".upper()
452
453
454 Prefix = FieldsMapping("Prefix", base=_SVP64PrefixFields)
455 RM = FieldsMapping("RM", base=_SVP64RMFields)
456
457
458 class Codegen(_enum.Enum):
459 PPC_SVP64_H = _enum.auto()
460 PPC_SVP64_OPC_C = _enum.auto()
461
462 @classmethod
463 def _missing_(cls, value):
464 return {
465 "ppc-svp64.h": Codegen.PPC_SVP64_H,
466 "ppc-svp64-opc.c": Codegen.PPC_SVP64_OPC_C,
467 }.get(value)
468
469 def __str__(self):
470 return {
471 Codegen.PPC_SVP64_H: "ppc-svp64.h",
472 Codegen.PPC_SVP64_OPC_C: "ppc-svp64-opc.c",
473 }[self]
474
475 def generate(self, entries):
476 def ppc_svp64_h(entries, num_entries):
477 disclaimer = DISCLAIMER.format(path=str(self),
478 desc="Header file for PowerPC opcode table (SVP64 extensions)")
479 yield from disclaimer.splitlines()
480 yield ""
481
482 yield f"#ifndef {self.name}"
483 yield f"#define {self.name}"
484 yield ""
485
486 yield "#include <stdint.h>"
487 yield ""
488
489 yield "#ifdef __cplusplus"
490 yield "extern \"C\" {"
491 yield "#endif"
492 yield ""
493
494 enums = (
495 In1Sel, In2Sel, In3Sel, OutSel,
496 CRInSel, CROutSel,
497 SVPType, SVEType, SVEXTRA,
498 Mode,
499 )
500 for enum in enums:
501 yield from enum.c_decl()
502 yield ""
503
504 for cls in (Record, Entry, Prefix, RM):
505 yield from cls.c_decl()
506 yield ""
507
508 for name in ("in1", "in2", "in3", "out", "out2", "cr_in", "cr_out"):
509 yield "ppc_opindex_t"
510 yield f"svp64_record_{name}_opindex(const struct svp64_record *record);"
511 yield ""
512
513 yield entries.__class__.c_var("svp64_entries",
514 prefix="extern const ", suffix=";")
515 yield num_entries.__class__.c_var("svp64_num_entries",
516 prefix="extern const ", suffix=";")
517 yield ""
518
519 yield f"#define SVP64_NAME_MAX {max(map(lambda entry: len(entry.name), entries))}"
520 yield ""
521
522 yield "#ifdef __cplusplus"
523 yield "}"
524 yield "#endif"
525 yield ""
526
527 yield f"#endif /* {self.name} */"
528 yield ""
529
530 def ppc_svp64_opc_c(entries, num_entries):
531 disclaimer = DISCLAIMER.format(path=str(self),
532 desc="PowerPC opcode list (SVP64 extensions)")
533 yield from disclaimer.splitlines()
534 yield ""
535
536 yield "#include \"opcode/ppc-svp64.h\""
537 yield ""
538
539 def opindex(enum, name, table):
540 sep = (max(map(len, list(table.values()) + ["UNUSED"])) + 1)
541 c_tag = f"svp64_{enum.__name__.lower()}"
542 yield "ppc_opindex_t"
543 yield f"svp64_record_{name}_opindex(const struct svp64_record *record)"
544 yield "{"
545 yield from indent(["static const ppc_opindex_t table[] = {"])
546 for key in enum:
547 value = table.get(key, "UNUSED")
548 c_value = f"{c_tag.upper()}_{key.name.upper()}"
549 yield from indent(indent([f"{value:{sep}}, /* {c_value} */"]))
550 yield from indent(["};"])
551 yield ""
552 yield from indent([f"return table[record->{name}];"])
553 yield "}"
554 yield ""
555
556 yield from opindex(In1Sel, "in1", {
557 In1Sel.RA: "RA",
558 In1Sel.RA_OR_ZERO: "RA",
559 In1Sel.SPR: "SPR",
560 In1Sel.RS: "RS",
561 In1Sel.FRA: "FRA",
562 In1Sel.FRS: "FRS",
563 })
564 yield from opindex(In2Sel, "in2", {
565 In2Sel.RB: "RB",
566 In2Sel.SPR: "SPR",
567 In2Sel.RS: "RS",
568 In2Sel.FRB: "FRB",
569 })
570 yield from opindex(In3Sel, "in3", {
571 In3Sel.RS: "RS",
572 In3Sel.RB: "RB",
573 In3Sel.FRS: "FRS",
574 In3Sel.FRC: "FRC",
575 In3Sel.RC: "RC",
576 In3Sel.RT: "RT",
577 })
578 for name in ("out", "out2"):
579 yield from opindex(OutSel, name, {
580 OutSel.RT: "RT",
581 OutSel.RA: "RA",
582 OutSel.SPR: "SPR",
583 OutSel.RT_OR_ZERO: "RT",
584 OutSel.FRT: "FRT",
585 OutSel.FRS: "FRS",
586 })
587 yield from opindex(CRInSel, "cr_in", {
588 CRInSel.BI: "BI",
589 CRInSel.BFA: "BFA",
590 CRInSel.BC: "BC",
591 CRInSel.WHOLE_REG: "FXM",
592 })
593 yield from opindex(CROutSel, "cr_out", {
594 CROutSel.BF: "BF",
595 CROutSel.BT: "BT",
596 CROutSel.WHOLE_REG: "FXM",
597 })
598
599 yield entries.__class__.c_var("svp64_entries",
600 prefix="const ", suffix=" = \\")
601 yield from entries.c_value(prefix="", suffix=";")
602 yield ""
603 yield num_entries.__class__.c_var("svp64_num_entries",
604 prefix="const ", suffix=" = \\")
605 yield from indent(num_entries.c_value(suffix=";"))
606 yield ""
607
608 bit_shl = lambda val, pos: f"({val} << UINT32_C({pos}))"
609 bit_shr = lambda val, pos: f"({val} >> UINT32_C({pos}))"
610 bit_get = lambda val, pos: f"({bit_shr(val, pos)} & UINT32_C(1))"
611 bit_or = lambda lhs, rhs: f"({lhs} | {rhs})"
612 bit_and = lambda lhs, rhs: f"({lhs} & {rhs})"
613 bit_not = lambda val: f"~({val})"
614
615 macros = (
616 (
617 "SVP64_FIELD_CLEAR",
618 ("VALUE", "BIT"),
619 bit_and("VALUE", bit_not(bit_shl("UINT32_C(1)", "BIT"))),
620 ),
621 (
622 "SVP64_FIELD_REMAP",
623 ("VALUE", "SRC", "DST"),
624 bit_shl(bit_get("VALUE", "SRC"), "DST"),
625 ),
626 (
627 "SVP64_FIELD_GET",
628 ("ORIGIN", "SRC", "DST"),
629 "SVP64_FIELD_REMAP(ORIGIN, SRC, DST)",
630 ),
631 (
632 "SVP64_FIELD_SET",
633 ("RESULT", "VALUE", "SRC", "DST"),
634 ("do { (*RESULT) = " + bit_or(
635 lhs="SVP64_FIELD_CLEAR(*(RESULT), DST)",
636 rhs="SVP64_FIELD_REMAP(VALUE, SRC, DST)",
637 ) + "; } while (0)"),
638 ),
639 )
640 for (name, args, body) in macros:
641 yield f"#define {name}({', '.join(args)}) \\"
642 yield from indent([body])
643 yield ""
644
645 for cls in (Prefix, RM):
646 table = {
647 "get": cls.c_getter,
648 "set": cls.c_setter,
649 }
650 for (mode, subcls) in table.items():
651 yield subcls.__class__.c_var(name=f"svp64_{cls.__name__.lower()}_{mode}")
652 yield from subcls.c_value()
653 yield ""
654
655 for name in map(_operator.itemgetter(0), macros):
656 yield f"#undef {name}"
657 yield ""
658
659
660 entries = Entry[...](entries)
661 num_entries = Size("(sizeof (svp64_entries) / sizeof (svp64_entries[0]))")
662
663 return {
664 Codegen.PPC_SVP64_H: ppc_svp64_h,
665 Codegen.PPC_SVP64_OPC_C: ppc_svp64_opc_c,
666 }[self](entries, num_entries)
667
668
669 ISA = _SVP64RM()
670 FIELDS = {field.name:field.type for field in _dataclasses.fields(Record)}
671 FIELDS.update({field.name:field.type for field in _dataclasses.fields(Entry)})
672
673 def parse(path):
674 visited = set()
675
676 def name_filter(name):
677 if name.startswith("l") and name.endswith("br"):
678 return False
679 if name in {"mcrxr", "mcrxrx", "darn"}:
680 return False
681 if name in {"bctar", "bcctr"}:
682 return False
683 if "rfid" in name:
684 return False
685 if name in {"setvl"}:
686 return False
687 if name in visited:
688 return False
689
690 visited.add(name)
691
692 return True
693
694 def item_mapper(item):
695 (key, value) = item
696 key = key.lower().replace(" ", "_")
697 cls = FIELDS.get(key, object)
698 if not isinstance(value, cls):
699 if issubclass(cls, _enum.Enum):
700 value = {item.name:item for item in cls}[value]
701 else:
702 value = cls(value)
703 return (key, value)
704
705 def item_filter(item):
706 (key, _) = item
707 return (key in FIELDS)
708
709 for record in ISA.get_svp64_csv(path):
710 names = record.pop("comment").split("=")[-1].split("/")
711 names = set(filter(name_filter, names))
712 if names:
713 rc = _RC[record["rc"] if record["rc"] else "NONE"]
714 if rc is _RC.RC:
715 names.update({f"{name}." for name in names})
716 record = dict(filter(item_filter, map(item_mapper, record.items())))
717 for name in map(Name, names):
718 yield Entry(name=name, record=Record(**record))
719
720
721 def main(codegen):
722 entries = []
723 paths = (
724 "minor_19.csv",
725 "minor_30.csv",
726 "minor_31.csv",
727 "minor_58.csv",
728 "minor_62.csv",
729 "minor_22.csv",
730 "minor_5.csv",
731 "minor_63.csv",
732 "minor_59.csv",
733 "major.csv",
734 "extra.csv",
735 )
736 for path in paths:
737 entries.extend(parse(path))
738 entries = sorted(frozenset(entries))
739
740 for line in codegen.generate(entries):
741 print(line)
742
743
744 if __name__ == "__main__":
745 parser = _argparse.ArgumentParser()
746 parser.add_argument("codegen",
747 type=Codegen, choices=Codegen,
748 help="code generator")
749
750 args = vars(parser.parse_args())
751 main(**args)