Add identifier filter. closes #14
This commit is contained in:
@@ -5,6 +5,7 @@ from systemrdl.node import AddrmapNode, AddressableNode, RegNode, FieldNode
|
|||||||
from .utils import get_indexed_path
|
from .utils import get_indexed_path
|
||||||
from .struct_generator import RDLStructGenerator
|
from .struct_generator import RDLStructGenerator
|
||||||
from .forloop_generator import RDLForLoopGenerator
|
from .forloop_generator import RDLForLoopGenerator
|
||||||
|
from .identifier_filter import kw_filter as kwf
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .exporter import RegblockExporter
|
from .exporter import RegblockExporter
|
||||||
@@ -43,7 +44,7 @@ class AddressDecode:
|
|||||||
class DecodeStructGenerator(RDLStructGenerator):
|
class DecodeStructGenerator(RDLStructGenerator):
|
||||||
|
|
||||||
def enter_Reg(self, node: 'RegNode') -> None:
|
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
|
# Stub out
|
||||||
def exit_Reg(self, node: 'RegNode') -> None:
|
def exit_Reg(self, node: 'RegNode') -> None:
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from .addr_decode import AddressDecode
|
|||||||
from .field_logic import FieldLogic
|
from .field_logic import FieldLogic
|
||||||
from .dereferencer import Dereferencer
|
from .dereferencer import Dereferencer
|
||||||
from .readback import Readback
|
from .readback import Readback
|
||||||
|
from .identifier_filter import kw_filter as kwf
|
||||||
|
|
||||||
from .cpuif import CpuifBase
|
from .cpuif import CpuifBase
|
||||||
from .cpuif.apb3 import APB3_Cpuif
|
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]
|
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
|
package_name = kwargs.pop("package_name", None) or (module_name + "_pkg") # type: str
|
||||||
reuse_hwif_typedefs = kwargs.pop("reuse_hwif_typedefs", True) # type: bool
|
reuse_hwif_typedefs = kwargs.pop("reuse_hwif_typedefs", True) # type: bool
|
||||||
|
|
||||||
@@ -158,6 +159,7 @@ class RegblockExporter:
|
|||||||
"retime_read_response": retime_read_response,
|
"retime_read_response": retime_read_response,
|
||||||
"min_read_latency": self.min_read_latency,
|
"min_read_latency": self.min_read_latency,
|
||||||
"min_write_latency": self.min_write_latency,
|
"min_write_latency": self.min_write_latency,
|
||||||
|
"kwf": kwf,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Write out design
|
# Write out design
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from collections import OrderedDict
|
|||||||
from ..struct_generator import RDLStructGenerator
|
from ..struct_generator import RDLStructGenerator
|
||||||
from ..forloop_generator import RDLForLoopGenerator
|
from ..forloop_generator import RDLForLoopGenerator
|
||||||
from ..utils import get_always_ff_event
|
from ..utils import get_always_ff_event
|
||||||
|
from ..identifier_filter import kw_filter as kwf
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from . import FieldLogic
|
from . import FieldLogic
|
||||||
@@ -34,7 +35,7 @@ class CombinationalStructGenerator(RDLStructGenerator):
|
|||||||
else:
|
else:
|
||||||
extra_combo_signals[signal.name] = signal
|
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("next", node.width)
|
||||||
self.add_member("load_next")
|
self.add_member("load_next")
|
||||||
for signal in extra_combo_signals.values():
|
for signal in extra_combo_signals.values():
|
||||||
@@ -67,7 +68,7 @@ class FieldStorageStructGenerator(RDLStructGenerator):
|
|||||||
self.field_logic = field_logic
|
self.field_logic = field_logic
|
||||||
|
|
||||||
def enter_Field(self, node: 'FieldNode') -> None:
|
def enter_Field(self, node: 'FieldNode') -> None:
|
||||||
self.push_struct(node.inst_name)
|
self.push_struct(kwf(node.inst_name))
|
||||||
|
|
||||||
if node.implements_storage:
|
if node.implements_storage:
|
||||||
self.add_member("value", node.width)
|
self.add_member("value", node.width)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from systemrdl.node import AddrmapNode, Node, SignalNode, FieldNode, Addressable
|
|||||||
from systemrdl.rdltypes import PropertyReference
|
from systemrdl.rdltypes import PropertyReference
|
||||||
|
|
||||||
from ..utils import get_indexed_path
|
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_Hier, OutputStructGenerator_Hier
|
||||||
from .generators import InputStructGenerator_TypeScope, OutputStructGenerator_TypeScope
|
from .generators import InputStructGenerator_TypeScope, OutputStructGenerator_TypeScope
|
||||||
@@ -141,7 +142,7 @@ class Hwif:
|
|||||||
return "hwif_in." + path + ".next"
|
return "hwif_in." + path + ".next"
|
||||||
elif isinstance(obj, SignalNode):
|
elif isinstance(obj, SignalNode):
|
||||||
if obj.get_path() in self.out_of_hier_signals:
|
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)
|
path = get_indexed_path(self.top_node, obj)
|
||||||
return "hwif_in." + path
|
return "hwif_in." + path
|
||||||
elif isinstance(obj, PropertyReference):
|
elif isinstance(obj, PropertyReference):
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from typing import TYPE_CHECKING
|
|||||||
from systemrdl.node import FieldNode
|
from systemrdl.node import FieldNode
|
||||||
|
|
||||||
from ..struct_generator import RDLFlatStructGenerator
|
from ..struct_generator import RDLFlatStructGenerator
|
||||||
|
from ..identifier_filter import kw_filter as kwf
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from systemrdl.node import Node, SignalNode, RegNode
|
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
|
# only emit the signal if design scanner detected it is actually being used
|
||||||
path = node.get_path()
|
path = node.get_path()
|
||||||
if path in self.hwif.in_hier_signal_paths:
|
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:
|
def enter_Field(self, node: 'FieldNode') -> None:
|
||||||
type_name = self.get_typdef_name(node)
|
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
|
# Provide input to field's next value if it is writable by hw, and it
|
||||||
# was not overridden by the 'next' property
|
# was not overridden by the 'next' property
|
||||||
@@ -87,7 +88,7 @@ class OutputStructGenerator_Hier(RDLFlatStructGenerator):
|
|||||||
|
|
||||||
def enter_Field(self, node: 'FieldNode') -> None:
|
def enter_Field(self, node: 'FieldNode') -> None:
|
||||||
type_name = self.get_typdef_name(node)
|
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
|
# Expose field's value if it is readable by hw
|
||||||
if node.is_hw_readable:
|
if node.is_hw_readable:
|
||||||
|
|||||||
52
src/peakrdl_regblock/identifier_filter.py
Normal file
52
src/peakrdl_regblock/identifier_filter.py
Normal 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
|
||||||
@@ -7,9 +7,9 @@ module {{module_name}} (
|
|||||||
|
|
||||||
{%- for signal in user_out_of_hier_signals %}
|
{%- for signal in user_out_of_hier_signals %}
|
||||||
{%- if signal.width == 1 %}
|
{%- if signal.width == 1 %}
|
||||||
input wire {{signal.inst_name}},
|
input wire {{kwf(signal.inst_name)}},
|
||||||
{%- else %}
|
{%- else %}
|
||||||
input wire [{{signal.width-1}}:0] {{signal.inst_name}},
|
input wire [{{signal.width-1}}:0] {{kwf(signal.inst_name)}},
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ from collections import OrderedDict
|
|||||||
|
|
||||||
from systemrdl.walker import RDLListener, RDLWalker
|
from systemrdl.walker import RDLListener, RDLWalker
|
||||||
|
|
||||||
|
from .identifier_filter import kw_filter as kwf
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
@@ -131,25 +133,25 @@ class RDLStructGenerator(StructGenerator, RDLListener):
|
|||||||
|
|
||||||
|
|
||||||
def enter_Addrmap(self, node: 'AddrmapNode') -> None:
|
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:
|
def exit_Addrmap(self, node: 'AddrmapNode') -> None:
|
||||||
self.pop_struct()
|
self.pop_struct()
|
||||||
|
|
||||||
def enter_Regfile(self, node: 'RegfileNode') -> None:
|
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:
|
def exit_Regfile(self, node: 'RegfileNode') -> None:
|
||||||
self.pop_struct()
|
self.pop_struct()
|
||||||
|
|
||||||
def enter_Reg(self, node: 'RegNode') -> None:
|
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:
|
def exit_Reg(self, node: 'RegNode') -> None:
|
||||||
self.pop_struct()
|
self.pop_struct()
|
||||||
|
|
||||||
def enter_Field(self, node: 'FieldNode') -> None:
|
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:
|
def enter_Addrmap(self, node: 'AddrmapNode') -> None:
|
||||||
type_name = self.get_typdef_name(node)
|
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:
|
def exit_Addrmap(self, node: 'AddrmapNode') -> None:
|
||||||
self.pop_struct()
|
self.pop_struct()
|
||||||
|
|
||||||
def enter_Regfile(self, node: 'RegfileNode') -> None:
|
def enter_Regfile(self, node: 'RegfileNode') -> None:
|
||||||
type_name = self.get_typdef_name(node)
|
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:
|
def exit_Regfile(self, node: 'RegfileNode') -> None:
|
||||||
self.pop_struct()
|
self.pop_struct()
|
||||||
|
|
||||||
def enter_Reg(self, node: 'RegNode') -> None:
|
def enter_Reg(self, node: 'RegNode') -> None:
|
||||||
type_name = self.get_typdef_name(node)
|
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:
|
def exit_Reg(self, node: 'RegNode') -> None:
|
||||||
self.pop_struct()
|
self.pop_struct()
|
||||||
|
|
||||||
def enter_Field(self, node: 'FieldNode') -> None:
|
def enter_Field(self, node: 'FieldNode') -> None:
|
||||||
self.add_member(node.inst_name, node.width)
|
self.add_member(kwf(node.inst_name), node.width)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import re
|
import re
|
||||||
from typing import TYPE_CHECKING, Match
|
from typing import TYPE_CHECKING, Match
|
||||||
|
|
||||||
|
from .identifier_filter import kw_filter as kwf
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from systemrdl.node import Node, SignalNode
|
from systemrdl.node import Node, SignalNode
|
||||||
from typing import Optional
|
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
|
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="[!]")
|
path = target_node.get_rel_path(top_node, empty_array_suffix="[!]")
|
||||||
|
|
||||||
# replace unknown indexes with incrementing iterators i0, i1, ...
|
# replace unknown indexes with incrementing iterators i0, i1, ...
|
||||||
class repl:
|
class ReplaceUnknown:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.i = 0
|
self.i = 0
|
||||||
def __call__(self, match: Match) -> str:
|
def __call__(self, match: Match) -> str:
|
||||||
s = f'i{self.i}'
|
s = f'i{self.i}'
|
||||||
self.i += 1
|
self.i += 1
|
||||||
return s
|
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:
|
def get_always_ff_event(dereferencer: 'Dereferencer', resetsignal: 'Optional[SignalNode]') -> str:
|
||||||
|
|||||||
Reference in New Issue
Block a user