Skip to content

Commit

Permalink
Add support for user defined enums in field encode property. #29
Browse files Browse the repository at this point in the history
  • Loading branch information
hughjackson authored and amykyta3 committed Apr 13, 2023
1 parent 80f670b commit 0c7e493
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 5 deletions.
5 changes: 4 additions & 1 deletion docs/props/field.rst
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,10 @@ Misc

encode
^^^^^^
|NO|
If assigned a user-defined enumeration, the resulting package file will include
its definition. Due to limitations from type-strictness rules in SystemVerilog,
the field will remain as a ``logic`` datatype.


next
^^^^
Expand Down
1 change: 1 addition & 0 deletions src/peakrdl_regblock/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ def export(self, node: Union[RootNode, AddrmapNode], output_dir:str, **kwargs: A
package_name=package_name,
in_hier_signal_paths=scanner.in_hier_signal_paths,
out_of_hier_signals=scanner.out_of_hier_signals,
user_enums=scanner.user_enums,
reuse_typedefs=reuse_hwif_typedefs,
hwif_report_file=hwif_report_file,
)
Expand Down
14 changes: 12 additions & 2 deletions src/peakrdl_regblock/hwif/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from typing import TYPE_CHECKING, Union, Set, Dict, Optional, TextIO
from typing import TYPE_CHECKING, Union, Set, Dict, Optional, TextIO, Type, List

from systemrdl.node import AddrmapNode, SignalNode, FieldNode, RegNode
from systemrdl.rdltypes import PropertyReference
from systemrdl.rdltypes import PropertyReference, UserEnum

from ..utils import get_indexed_path
from ..identifier_filter import kw_filter as kwf

from .generators import InputStructGenerator_Hier, OutputStructGenerator_Hier
from .generators import InputStructGenerator_TypeScope, OutputStructGenerator_TypeScope
from .generators import EnumGenerator

if TYPE_CHECKING:
from ..exporter import RegblockExporter
Expand All @@ -22,6 +23,7 @@ class Hwif:

def __init__(
self, exp: 'RegblockExporter', package_name: str,
user_enums: List[Type[UserEnum]],
in_hier_signal_paths: Set[str], out_of_hier_signals: Dict[str, SignalNode],
reuse_typedefs: bool, hwif_report_file: Optional[TextIO]
):
Expand All @@ -33,6 +35,7 @@ def __init__(

self.in_hier_signal_paths = in_hier_signal_paths
self.out_of_hier_signals = out_of_hier_signals
self.user_enums = user_enums

self.hwif_report_file = hwif_report_file

Expand Down Expand Up @@ -76,6 +79,13 @@ def get_package_contents(self) -> str:
else:
self.has_output_struct = False

gen_enum = EnumGenerator()
enums = gen_enum.get_enums(
self.user_enums
)
if enums is not None:
lines.append(enums)

return "\n\n".join(lines)


Expand Down
40 changes: 39 additions & 1 deletion src/peakrdl_regblock/hwif/generators.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import TYPE_CHECKING, Optional, List
from typing import TYPE_CHECKING, Optional, List, Type

from systemrdl.node import FieldNode

Expand All @@ -8,6 +8,7 @@
if TYPE_CHECKING:
from systemrdl.node import Node, SignalNode, RegNode
from . import Hwif
from systemrdl.rdltypes import UserEnum

class HWIFStructGenerator(RDLFlatStructGenerator):
def __init__(self, hwif: 'Hwif', hwif_name: str) -> None:
Expand Down Expand Up @@ -178,6 +179,43 @@ def get_typdef_name(self, node:'Node') -> str:

return f'{scope_path}__{node.type_name}{extra_suffix}__out_t'

#-------------------------------------------------------------------------------
class EnumGenerator:
"""
Generator for user-defined enum definitions
"""

def get_enums(self, user_enums: List[Type['UserEnum']]) -> Optional[str]:
if not user_enums:
return None

lines = []
for user_enum in user_enums:
lines.append(self._enum_typedef(user_enum))

return '\n\n'.join(lines)

@staticmethod
def _get_prefix(user_enum: Type['UserEnum']) -> str:
scope = user_enum.get_scope_path("__")
if scope:
return f"{scope}__{user_enum.type_name}"
else:
return user_enum.type_name

def _enum_typedef(self, user_enum: Type['UserEnum']) -> str:
prefix = self._get_prefix(user_enum)

lines = []
for enum_member in user_enum:
lines.append(f" {prefix}__{enum_member.name} = 'd{enum_member.value}")

return (
"typedef enum {\n"
+ ",\n".join(lines)
+ f"\n}} {prefix}_e;"
)


def get_field_type_name_suffix(field: FieldNode) -> str:
"""
Expand Down
10 changes: 9 additions & 1 deletion src/peakrdl_regblock/scan_design.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import TYPE_CHECKING, Set, Optional
from typing import TYPE_CHECKING, Set, Optional, Type, List
from collections import OrderedDict

from systemrdl.walker import RDLListener, RDLWalker, WalkerAction
Expand All @@ -7,6 +7,7 @@
if TYPE_CHECKING:
from systemrdl.node import Node, RegNode, FieldNode
from .exporter import RegblockExporter
from systemrdl.rdltypes import UserEnum


class DesignScanner(RDLListener):
Expand All @@ -29,6 +30,9 @@ def __init__(self, exp:'RegblockExporter') -> None:
self.has_buffered_write_regs = False
self.has_buffered_read_regs = False

# Track any referenced enums
self.user_enums = [] # type: List[Type[UserEnum]]

def _get_out_of_hier_field_reset(self) -> None:
current_node = self.exp.top_node.parent
while current_node is not None:
Expand Down Expand Up @@ -83,6 +87,10 @@ def enter_Component(self, node: 'Node') -> Optional[WalkerAction]:
else:
self.in_hier_signal_paths.add(path)

if prop_name == "encode":
if value not in self.user_enums:
self.user_enums.append(value)

return None

def enter_Reg(self, node: 'RegNode') -> None:
Expand Down
Empty file added tests/test_enum/__init__.py
Empty file.
12 changes: 12 additions & 0 deletions tests/test_enum/regblock.rdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
addrmap top {
enum my_enum {
val_1 = 3 {name = "Value 1";};
val_2 = 4 {desc = "Second value";};
};
reg {
field {
encode = my_enum;
sw=rw; hw=na;
} f[2:0] = my_enum::val_2;
} r0;
};
22 changes: 22 additions & 0 deletions tests/test_enum/tb_template.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{% extends "lib/tb_base.sv" %}

{% block seq %}
{% sv_line_anchor %}
##1;
cb.rst <= '0;
##1;

// check enum values
assert(regblock_pkg::top__my_enum__val_1 == 'd3);
assert(regblock_pkg::top__my_enum__val_2 == 'd4);

// check initial conditions
cpuif.assert_read('h0, regblock_pkg::top__my_enum__val_2);

//---------------------------------
// set r0 = val_1
cpuif.write('h0, regblock_pkg::top__my_enum__val_1);

cpuif.assert_read('h0, regblock_pkg::top__my_enum__val_1);

{% endblock %}
5 changes: 5 additions & 0 deletions tests/test_enum/testcase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from ..lib.sim_testcase import SimTestCase

class Test(SimTestCase):
def test_dut(self):
self.run_test()

0 comments on commit 0c7e493

Please sign in to comment.