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