Add identifier filter. closes #14

This commit is contained in:
Alex Mykyta
2022-07-20 23:35:17 -07:00
parent 34d2f7740c
commit 135b717486
9 changed files with 90 additions and 20 deletions

View File

@@ -5,6 +5,7 @@ from systemrdl.node import AddrmapNode, AddressableNode, RegNode, FieldNode
from .utils import get_indexed_path
from .struct_generator import RDLStructGenerator
from .forloop_generator import RDLForLoopGenerator
from .identifier_filter import kw_filter as kwf
if TYPE_CHECKING:
from .exporter import RegblockExporter
@@ -43,7 +44,7 @@ class AddressDecode:
class DecodeStructGenerator(RDLStructGenerator):
def enter_Reg(self, node: 'RegNode') -> None:
self.add_member(node.inst_name, array_dimensions=node.array_dimensions)
self.add_member(kwf(node.inst_name), array_dimensions=node.array_dimensions)
# Stub out
def exit_Reg(self, node: 'RegNode') -> None:

View File

@@ -8,6 +8,7 @@ from .addr_decode import AddressDecode
from .field_logic import FieldLogic
from .dereferencer import Dereferencer
from .readback import Readback
from .identifier_filter import kw_filter as kwf
from .cpuif import CpuifBase
from .cpuif.apb3 import APB3_Cpuif
@@ -100,7 +101,7 @@ class RegblockExporter:
cpuif_cls = kwargs.pop("cpuif_cls", None) or APB3_Cpuif # type: Type[CpuifBase]
module_name = kwargs.pop("module_name", None) or self.top_node.inst_name # type: str
module_name = kwargs.pop("module_name", None) or kwf(self.top_node.inst_name) # type: str
package_name = kwargs.pop("package_name", None) or (module_name + "_pkg") # type: str
reuse_hwif_typedefs = kwargs.pop("reuse_hwif_typedefs", True) # type: bool
@@ -158,6 +159,7 @@ class RegblockExporter:
"retime_read_response": retime_read_response,
"min_read_latency": self.min_read_latency,
"min_write_latency": self.min_write_latency,
"kwf": kwf,
}
# Write out design

View File

@@ -5,6 +5,7 @@ from collections import OrderedDict
from ..struct_generator import RDLStructGenerator
from ..forloop_generator import RDLForLoopGenerator
from ..utils import get_always_ff_event
from ..identifier_filter import kw_filter as kwf
if TYPE_CHECKING:
from . import FieldLogic
@@ -34,7 +35,7 @@ class CombinationalStructGenerator(RDLStructGenerator):
else:
extra_combo_signals[signal.name] = signal
self.push_struct(node.inst_name)
self.push_struct(kwf(node.inst_name))
self.add_member("next", node.width)
self.add_member("load_next")
for signal in extra_combo_signals.values():
@@ -67,7 +68,7 @@ class FieldStorageStructGenerator(RDLStructGenerator):
self.field_logic = field_logic
def enter_Field(self, node: 'FieldNode') -> None:
self.push_struct(node.inst_name)
self.push_struct(kwf(node.inst_name))
if node.implements_storage:
self.add_member("value", node.width)

View File

@@ -4,6 +4,7 @@ from systemrdl.node import AddrmapNode, Node, SignalNode, FieldNode, Addressable
from systemrdl.rdltypes import PropertyReference
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
@@ -141,7 +142,7 @@ class Hwif:
return "hwif_in." + path + ".next"
elif isinstance(obj, SignalNode):
if obj.get_path() in self.out_of_hier_signals:
return obj.inst_name
return kwf(obj.inst_name)
path = get_indexed_path(self.top_node, obj)
return "hwif_in." + path
elif isinstance(obj, PropertyReference):

View File

@@ -3,6 +3,7 @@ from typing import TYPE_CHECKING
from systemrdl.node import FieldNode
from ..struct_generator import RDLFlatStructGenerator
from ..identifier_filter import kw_filter as kwf
if TYPE_CHECKING:
from systemrdl.node import Node, SignalNode, RegNode
@@ -27,11 +28,11 @@ class InputStructGenerator_Hier(RDLFlatStructGenerator):
# only emit the signal if design scanner detected it is actually being used
path = node.get_path()
if path in self.hwif.in_hier_signal_paths:
self.add_member(node.inst_name, node.width)
self.add_member(kwf(node.inst_name), node.width)
def enter_Field(self, node: 'FieldNode') -> None:
type_name = self.get_typdef_name(node)
self.push_struct(type_name, node.inst_name)
self.push_struct(type_name, kwf(node.inst_name))
# Provide input to field's next value if it is writable by hw, and it
# was not overridden by the 'next' property
@@ -87,7 +88,7 @@ class OutputStructGenerator_Hier(RDLFlatStructGenerator):
def enter_Field(self, node: 'FieldNode') -> None:
type_name = self.get_typdef_name(node)
self.push_struct(type_name, node.inst_name)
self.push_struct(type_name, kwf(node.inst_name))
# Expose field's value if it is readable by hw
if node.is_hw_readable:

View File

@@ -0,0 +1,52 @@
# All SystemVerilog 2017 keywords
SV_KEYWORDS = {
'accept_on', 'alias', 'always', 'always_comb', 'always_ff', 'always_latch',
'and', 'assert', 'assign', 'assume', 'automatic', 'before', 'begin', 'bind',
'bins', 'binsof', 'bit', 'break', 'buf', 'bufif0', 'bufif1', 'byte', 'case',
'casex', 'casez', 'cell', 'chandle', 'checker', 'class', 'clocking', 'cmos',
'config', 'const', 'constraint', 'context', 'continue', 'cover', 'covergroup',
'coverpoint', 'cross', 'deassign', 'default', 'defparam', 'design', 'disable',
'dist', 'do', 'edge', 'else', 'end', 'endcase', 'endchecker', 'endclass',
'endclocking', 'endconfig', 'endfunction', 'endgenerate', 'endgroup',
'endinterface', 'endmodule', 'endpackage', 'endprimitive', 'endprogram',
'endproperty', 'endspecify', 'endsequence', 'endtable', 'endtask', 'enum',
'event', 'eventually', 'expect', 'export', 'extends', 'extern', 'final',
'first_match', 'for', 'force', 'foreach', 'forever', 'fork', 'forkjoin',
'function', 'generate', 'genvar', 'global', 'highz0', 'highz1', 'if', 'iff',
'ifnone', 'ignore_bins', 'illegal_bins', 'implements', 'implies', 'import',
'incdir', 'include', 'initial', 'inout', 'input', 'inside', 'instance',
'int', 'integer', 'interconnect', 'interface', 'intersect', 'join',
'join_any', 'join_none', 'large', 'let', 'liblist', 'library', 'local',
'localparam', 'logic', 'longint', 'macromodule', 'matches', 'medium',
'modport', 'module', 'nand', 'negedge', 'nettype', 'new', 'nexttime', 'nmos',
'nor', 'noshowcancelled', 'not', 'notif0', 'notif1', 'null', 'or', 'output',
'package', 'packed', 'parameter', 'pmos', 'posedge', 'primitive', 'priority',
'program', 'property', 'protected', 'pull0', 'pull1', 'pulldown', 'pullup',
'pulsestyle_ondetect', 'pulsestyle_onevent', 'pure', 'rand', 'randc',
'randcase', 'randsequence', 'rcmos', 'real', 'realtime', 'ref', 'reg',
'reject_on', 'release', 'repeat', 'restrict', 'return', 'rnmos', 'rpmos',
'rtran', 'rtranif0', 'rtranif1', 's_always', 's_eventually', 's_nexttime',
's_until', 's_until_with', 'scalared', 'sequence', 'shortint', 'shortreal',
'showcancelled', 'signed', 'small', 'soft', 'solve', 'specify', 'specparam',
'static', 'string', 'strong', 'strong0', 'strong1', 'struct', 'super',
'supply0', 'supply1', 'sync_accept_on', 'sync_reject_on', 'table', 'tagged',
'task', 'this', 'throughout', 'time', 'timeprecision', 'timeunit', 'tran',
'tranif0', 'tranif1', 'tri', 'tri0', 'tri1', 'triand', 'trior', 'trireg',
'type', 'typedef', 'union', 'unique', 'unique0', 'unsigned', 'until',
'until_with', 'untyped', 'use', 'uwire', 'var', 'vectored', 'virtual', 'void',
'wait', 'wait_order', 'wand', 'weak', 'weak0', 'weak1', 'while', 'wildcard',
'wire', 'with', 'within', 'wor', 'xnor', 'xor'
}
def kw_filter(s: str) -> str:
"""
Make all user identifiers 'safe' and ensure they do not collide with
SystemVerilog keywords.
If an SV keyword is encountered, add an underscore suffix
"""
if s in SV_KEYWORDS:
s += "_"
return s

View File

@@ -7,9 +7,9 @@ module {{module_name}} (
{%- for signal in user_out_of_hier_signals %}
{%- if signal.width == 1 %}
input wire {{signal.inst_name}},
input wire {{kwf(signal.inst_name)}},
{%- else %}
input wire [{{signal.width-1}}:0] {{signal.inst_name}},
input wire [{{signal.width-1}}:0] {{kwf(signal.inst_name)}},
{%- endif %}
{%- endfor %}

View File

@@ -4,6 +4,8 @@ from collections import OrderedDict
from systemrdl.walker import RDLListener, RDLWalker
from .identifier_filter import kw_filter as kwf
if TYPE_CHECKING:
from typing import Union
@@ -131,25 +133,25 @@ class RDLStructGenerator(StructGenerator, RDLListener):
def enter_Addrmap(self, node: 'AddrmapNode') -> None:
self.push_struct(node.inst_name, node.array_dimensions)
self.push_struct(kwf(node.inst_name), node.array_dimensions)
def exit_Addrmap(self, node: 'AddrmapNode') -> None:
self.pop_struct()
def enter_Regfile(self, node: 'RegfileNode') -> None:
self.push_struct(node.inst_name, node.array_dimensions)
self.push_struct(kwf(node.inst_name), node.array_dimensions)
def exit_Regfile(self, node: 'RegfileNode') -> None:
self.pop_struct()
def enter_Reg(self, node: 'RegNode') -> None:
self.push_struct(node.inst_name, node.array_dimensions)
self.push_struct(kwf(node.inst_name), node.array_dimensions)
def exit_Reg(self, node: 'RegNode') -> None:
self.pop_struct()
def enter_Field(self, node: 'FieldNode') -> None:
self.add_member(node.inst_name, node.width)
self.add_member(kwf(node.inst_name), node.width)
#-------------------------------------------------------------------------------
@@ -214,24 +216,24 @@ class RDLFlatStructGenerator(FlatStructGenerator, RDLListener):
def enter_Addrmap(self, node: 'AddrmapNode') -> None:
type_name = self.get_typdef_name(node)
self.push_struct(type_name, node.inst_name, node.array_dimensions)
self.push_struct(type_name, kwf(node.inst_name), node.array_dimensions)
def exit_Addrmap(self, node: 'AddrmapNode') -> None:
self.pop_struct()
def enter_Regfile(self, node: 'RegfileNode') -> None:
type_name = self.get_typdef_name(node)
self.push_struct(type_name, node.inst_name, node.array_dimensions)
self.push_struct(type_name, kwf(node.inst_name), node.array_dimensions)
def exit_Regfile(self, node: 'RegfileNode') -> None:
self.pop_struct()
def enter_Reg(self, node: 'RegNode') -> None:
type_name = self.get_typdef_name(node)
self.push_struct(type_name, node.inst_name, node.array_dimensions)
self.push_struct(type_name, kwf(node.inst_name), node.array_dimensions)
def exit_Reg(self, node: 'RegNode') -> None:
self.pop_struct()
def enter_Field(self, node: 'FieldNode') -> None:
self.add_member(node.inst_name, node.width)
self.add_member(kwf(node.inst_name), node.width)

View File

@@ -1,6 +1,8 @@
import re
from typing import TYPE_CHECKING, Match
from .identifier_filter import kw_filter as kwf
if TYPE_CHECKING:
from systemrdl.node import Node, SignalNode
from typing import Optional
@@ -11,15 +13,23 @@ def get_indexed_path(top_node: 'Node', target_node: 'Node') -> str:
TODO: Add words about indexing and why i'm doing this. Copy from logbook
"""
path = target_node.get_rel_path(top_node, empty_array_suffix="[!]")
# replace unknown indexes with incrementing iterators i0, i1, ...
class repl:
class ReplaceUnknown:
def __init__(self) -> None:
self.i = 0
def __call__(self, match: Match) -> str:
s = f'i{self.i}'
self.i += 1
return s
return re.sub(r'!', repl(), path)
path = re.sub(r'!', ReplaceUnknown(), path)
# Sanitize any SV keywords
def kw_filter_repl(m: Match) -> str:
return kwf(m.group(0))
path = re.sub(r'\w+', kw_filter_repl, path)
return path
def get_always_ff_event(dereferencer: 'Dereferencer', resetsignal: 'Optional[SignalNode]') -> str: