Skip to content

Commit af56d28

Browse files
committed
Add support for enums
1 parent db696fc commit af56d28

File tree

3 files changed

+60
-3
lines changed

3 files changed

+60
-3
lines changed

src/peakrdl_cheader/__peakrdl__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ def add_exporter_arguments(self, arg_group: 'argparse._ActionsContainer') -> Non
4343
"""
4444
)
4545

46+
arg_group.add_argument(
47+
"-e", "--generate-enums",
48+
action="store_true",
49+
default=False,
50+
help="""
51+
Enable generation of enum definitions.
52+
"""
53+
)
54+
4655
arg_group.add_argument(
4756
"-x", "--explode-top",
4857
action="store_true",

src/peakrdl_cheader/design_state.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ def __init__(self, top_node: AddrmapNode, kwargs: Any) -> None:
4545
self.bitfield_order_ltoh: bool
4646
self.bitfield_order_ltoh = kwargs.pop("bitfield_order_ltoh", True)
4747

48+
self.generate_enums: bool
49+
self.generate_enums = kwargs.pop("generate_enums", False)
50+
4851
# If a register is wider than 64-bits, it cannot be represented by a stdint
4952
# type. Therefore it must be represented by an array of subwords
5053
self.wide_reg_subword_size: int

src/peakrdl_cheader/header_generator.py

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import TextIO, Set, Optional, List
1+
from typing import Type, TextIO, Set, Optional, List
22
import os
33
import re
44

@@ -39,6 +39,10 @@ def run(self, path: str, top_nodes: List[AddrmapNode]) -> None:
3939
template.stream(context).dump(f)
4040
f.write("\n")
4141

42+
# Write enums
43+
if self.ds.generate_enums:
44+
self.write_enums(top_nodes)
45+
4246
# Generate definitions
4347
for node in top_nodes:
4448
self.root_node = node
@@ -102,14 +106,19 @@ def write_bitfields(self, grp_name: str, regwidth: int, fields: List[FieldNode])
102106
self.write("struct __attribute__ ((__packed__)) {\n")
103107
self.push_indent()
104108

109+
def get_field_type(field: FieldNode) -> str:
110+
encode = field.get_property("encode")
111+
return f"uint{regwidth}_t" if not self.ds.generate_enums or encode is None else \
112+
f"{self.get_enum_prefix(encode)}_e"
113+
105114
if self.ds.bitfield_order_ltoh:
106115
# Bits are packed in struct LSb --> MSb
107116
current_offset = 0
108117
for field in fields:
109118
if field.low > current_offset:
110119
self.write(f"uint{regwidth}_t :{field.low - current_offset:d};\n")
111120
current_offset = field.low
112-
self.write(f"uint{regwidth}_t {kwf(field.inst_name)} :{field.width:d};\n")
121+
self.write(f"{get_field_type(field)} {kwf(field.inst_name)} :{field.width:d};\n")
113122
current_offset += field.width
114123

115124
if current_offset < regwidth:
@@ -121,7 +130,7 @@ def write_bitfields(self, grp_name: str, regwidth: int, fields: List[FieldNode])
121130
if field.high < current_offset:
122131
self.write(f"uint{regwidth}_t :{current_offset - field.high:d};\n")
123132
current_offset = field.high
124-
self.write(f"uint{regwidth}_t {kwf(field.inst_name)} :{field.width:d};\n")
133+
self.write(f"{get_field_type(field)} {kwf(field.inst_name)} :{field.width:d};\n")
125134
current_offset -= field.width
126135

127136
if current_offset > -1:
@@ -343,3 +352,39 @@ def write_group_struct_member(self, node: AddressableNode) -> None:
343352

344353
struct_name = self.get_struct_name(node)
345354
self.write(f"{struct_name} {kwf(node.inst_name)}{array_suffix};\n")
355+
356+
@staticmethod
357+
def get_enum_prefix(user_enum: Type['UserEnum']) -> str:
358+
scope = user_enum.get_scope_path("__")
359+
if scope:
360+
return f"{scope}__{user_enum.type_name}"
361+
else:
362+
return user_enum.type_name
363+
364+
def write_enum(self, user_enum: Type['UserEnum']) -> None:
365+
prefix = self.get_enum_prefix(user_enum)
366+
lines = []
367+
for enum_member in user_enum:
368+
lines.append(f" {prefix}__{enum_member.name} = {enum_member.value}")
369+
370+
self.write("typedef enum {\n"
371+
+ ",\n".join(lines)
372+
+ f"\n}} {prefix}_e;\n")
373+
374+
def write_enums(self, top_nodes: List[AddrmapNode]) -> None:
375+
user_enums = set()
376+
377+
class Listener(RDLListener):
378+
def enter_Field(self, node: FieldNode) -> Optional[WalkerAction]:
379+
encode = node.get_property("encode")
380+
if encode is not None:
381+
user_enums.add(encode)
382+
return None
383+
384+
for node in top_nodes:
385+
self.root_node = node
386+
RDLWalker().walk(node, Listener())
387+
388+
for user_enum in user_enums:
389+
self.write("\n")
390+
self.write_enum(user_enum)

0 commit comments

Comments
 (0)