mirror of
https://github.com/Silicon1602/srdl2sv.git
synced 2024-11-14 11:03:36 +00:00
Provide more advanced way of adding internal signals or ports
Now, every snippet of RTL in the YAML file can also hold internal variables (i.e., signals), input or output ports. Furthermore, the input/output port lists are replaced by a dictionary to prevent duplicate entries.
This commit is contained in:
parent
c5755bf104
commit
085e2ea2dc
@ -33,6 +33,7 @@ class AddrMap(Component):
|
|||||||
# We need a dictionary since it might be required to access the objects later
|
# We need a dictionary since it might be required to access the objects later
|
||||||
# by name (for example, in case of aliases)
|
# by name (for example, in case of aliases)
|
||||||
self.registers = dict()
|
self.registers = dict()
|
||||||
|
self.rdl_nodes = dict()
|
||||||
|
|
||||||
# Traverse through children
|
# Traverse through children
|
||||||
for child in obj.children():
|
for child in obj.children():
|
||||||
@ -61,24 +62,26 @@ class AddrMap(Component):
|
|||||||
# Input ports
|
# Input ports
|
||||||
input_ports_rtl = [
|
input_ports_rtl = [
|
||||||
AddrMap.templ_dict['input_port'].format(
|
AddrMap.templ_dict['input_port'].format(
|
||||||
name = x.name,
|
name = key,
|
||||||
packed_dim = x.packed_dim,
|
signal_type = value[0],
|
||||||
unpacked_dim = '[{}]'.format(
|
unpacked_dim = '[{}]'.format(
|
||||||
']['.join(
|
']['.join(
|
||||||
[str(y) for y in x.unpacked_dim]))
|
[str(y) for y in value[1]]))
|
||||||
if x.unpacked_dim else '')
|
if value[1] else '')
|
||||||
for x in self.get_ports('input')]
|
for (key, value) in self.get_ports('input').items()
|
||||||
|
]
|
||||||
|
|
||||||
# Output ports
|
# Output ports
|
||||||
output_ports_rtl = [
|
output_ports_rtl = [
|
||||||
AddrMap.templ_dict['output_port'].format(
|
AddrMap.templ_dict['output_port'].format(
|
||||||
name = x.name,
|
name = key,
|
||||||
packed_dim = x.packed_dim,
|
signal_type = value[0],
|
||||||
unpacked_dim = '[{}]'.format(
|
unpacked_dim = '[{}]'.format(
|
||||||
']['.join(
|
']['.join(
|
||||||
[str(y) for y in x.unpacked_dim]))
|
[str(y) for y in value[1]]))
|
||||||
if x.unpacked_dim else '')
|
if value[1] else '')
|
||||||
for x in self.get_ports('output')]
|
for (key, value) in self.get_ports('output').items()
|
||||||
|
]
|
||||||
|
|
||||||
# Remove comma from last port entry
|
# Remove comma from last port entry
|
||||||
output_ports_rtl[-1] = output_ports_rtl[-1].rstrip(',')
|
output_ports_rtl[-1] = output_ports_rtl[-1].rstrip(',')
|
||||||
|
@ -7,10 +7,13 @@ from systemrdl import node
|
|||||||
from log.log import create_logger
|
from log.log import create_logger
|
||||||
|
|
||||||
# Define NamedTuple
|
# Define NamedTuple
|
||||||
class Port(NamedTuple):
|
class TypeDefMembers(NamedTuple):
|
||||||
name: str
|
name: str
|
||||||
packed_dim: str
|
member_type: str
|
||||||
unpacked_dim: list
|
|
||||||
|
class TypeDef(NamedTuple):
|
||||||
|
name: str
|
||||||
|
members: list[TypeDefMembers]
|
||||||
|
|
||||||
class Component():
|
class Component():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -18,9 +21,10 @@ class Component():
|
|||||||
self.rtl_footer = []
|
self.rtl_footer = []
|
||||||
self.children = []
|
self.children = []
|
||||||
self.ports = dict()
|
self.ports = dict()
|
||||||
self.ports['input'] = []
|
self.signals = dict()
|
||||||
self.ports['output'] = []
|
self.ports['input'] = dict()
|
||||||
self.ports['inout'] = []
|
self.ports['output'] = dict()
|
||||||
|
self.field_type = ''
|
||||||
|
|
||||||
def create_logger(self, name: str, config: dict):
|
def create_logger(self, name: str, config: dict):
|
||||||
self.logger = create_logger(
|
self.logger = create_logger(
|
||||||
@ -32,10 +36,19 @@ class Component():
|
|||||||
|
|
||||||
def get_ports(self, port_type: str):
|
def get_ports(self, port_type: str):
|
||||||
self.logger.debug("Return port list")
|
self.logger.debug("Return port list")
|
||||||
return [
|
|
||||||
*self.ports[port_type],
|
for x in self.children:
|
||||||
*list(chain(*[x.get_ports(port_type) for x in self.children]))
|
self.ports[port_type] |= x.get_ports(port_type)
|
||||||
]
|
|
||||||
|
return self.ports[port_type]
|
||||||
|
|
||||||
|
def get_signals(self):
|
||||||
|
self.logger.debug("Return signal list")
|
||||||
|
|
||||||
|
for x in self.children:
|
||||||
|
self.signals |= x.get_signals()
|
||||||
|
|
||||||
|
return self.signals
|
||||||
|
|
||||||
def get_rtl(self, tab_width: int = 0, real_tabs: bool = False) -> str:
|
def get_rtl(self, tab_width: int = 0, real_tabs: bool = False) -> str:
|
||||||
self.logger.debug("Return RTL")
|
self.logger.debug("Return RTL")
|
||||||
@ -102,25 +115,60 @@ class Component():
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def split_dimensions(path: str):
|
def split_dimensions(path: str):
|
||||||
new_path = re.match(r'(.*?)(\[.*\])?(.*)', path)
|
re_dimensions = re.compile('(\[[^]]\])')
|
||||||
return (''.join([new_path.group(1), new_path.group(3)]),
|
new_path = re_dimensions.sub('', path)
|
||||||
new_path.group(2) if new_path.group(2) else '[0]')
|
return (new_path, ''.join(re_dimensions.findall(path)))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_ref_name(obj):
|
def get_signal_name(obj):
|
||||||
name = []
|
name = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
child_obj = obj.node
|
||||||
|
except AttributeError:
|
||||||
|
child_obj = obj
|
||||||
|
|
||||||
split_name = Component.split_dimensions(
|
split_name = Component.split_dimensions(
|
||||||
Component.get_underscored_path(
|
Component.get_underscored_path(
|
||||||
obj.get_path(),
|
child_obj.get_path(),
|
||||||
obj.owning_addrmap.inst_name)
|
child_obj.owning_addrmap.inst_name)
|
||||||
)
|
)
|
||||||
|
|
||||||
name.append(split_name[0])
|
name.append(split_name[0])
|
||||||
|
|
||||||
if isinstance(obj, (node.FieldNode)):
|
if isinstance(obj, node.FieldNode):
|
||||||
name.append('_q')
|
name.append('_q')
|
||||||
|
elif isinstance(obj, node.SignalNode):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
name.append('_')
|
||||||
|
name.append(obj.name)
|
||||||
|
|
||||||
name.append(split_name[1])
|
name.append(split_name[1])
|
||||||
|
|
||||||
return ''.join(name)
|
return ''.join(name)
|
||||||
|
|
||||||
|
def yaml_signals_to_list(self, yaml_obj):
|
||||||
|
try:
|
||||||
|
for x in yaml_obj['signals']:
|
||||||
|
self.signals[x['name'].format(path = self.path_underscored)] =\
|
||||||
|
(x['signal_type'].format(field_type = self.field_type),
|
||||||
|
self.array_dimensions)
|
||||||
|
except (TypeError, KeyError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
for x in yaml_obj['input_ports']:
|
||||||
|
self.ports['input'][x['name'].format(path = self.path_underscored)] =\
|
||||||
|
(x['signal_type'].format(field_type = self.field_type),
|
||||||
|
self.array_dimensions)
|
||||||
|
except (TypeError, KeyError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
for x in yaml_obj['output_ports']:
|
||||||
|
self.ports['output'][x['name'].format(path = self.path_underscored)] =\
|
||||||
|
(x['signal_type'].format(field_type = self.field_type),
|
||||||
|
self.array_dimensions)
|
||||||
|
except (TypeError, KeyError):
|
||||||
|
pass
|
||||||
|
@ -7,7 +7,7 @@ from systemrdl.node import FieldNode
|
|||||||
from systemrdl.rdltypes import PrecedenceType, AccessType, OnReadType, OnWriteType
|
from systemrdl.rdltypes import PrecedenceType, AccessType, OnReadType, OnWriteType
|
||||||
|
|
||||||
# Local modules
|
# Local modules
|
||||||
from components.component import Component, Port
|
from components.component import Component
|
||||||
from . import templates
|
from . import templates
|
||||||
|
|
||||||
class Field(Component):
|
class Field(Component):
|
||||||
@ -16,11 +16,11 @@ class Field(Component):
|
|||||||
pkg_resources.read_text(templates, 'fields.yaml'),
|
pkg_resources.read_text(templates, 'fields.yaml'),
|
||||||
Loader=yaml.FullLoader)
|
Loader=yaml.FullLoader)
|
||||||
|
|
||||||
def __init__(self, obj: node.FieldNode, dimensions: list, config:dict):
|
def __init__(self, obj: node.FieldNode, array_dimensions: list, config:dict):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
# Save and/or process important variables
|
# Save and/or process important variables
|
||||||
self.__process_variables(obj, dimensions)
|
self.__process_variables(obj, array_dimensions)
|
||||||
|
|
||||||
# Create logger object
|
# Create logger object
|
||||||
self.create_logger("{}.{}".format(self.owning_addrmap, self.path), config)
|
self.create_logger("{}.{}".format(self.owning_addrmap, self.path), config)
|
||||||
@ -40,49 +40,55 @@ class Field(Component):
|
|||||||
self.__add_access_rtl()
|
self.__add_access_rtl()
|
||||||
self.__add_combo()
|
self.__add_combo()
|
||||||
self.__add_ports()
|
self.__add_ports()
|
||||||
|
self.__prepend_signal_declarations()
|
||||||
|
|
||||||
def __add_combo(self):
|
def __add_combo(self):
|
||||||
operations = []
|
operations = []
|
||||||
if self.obj.get_property('anded'):
|
if self.obj.get_property('anded'):
|
||||||
operations.append(['anded', '&'])
|
operations.append(['&', 'assign_anded_operation'])
|
||||||
if self.obj.get_property('ored'):
|
if self.obj.get_property('ored'):
|
||||||
operations.append(['ored', '|'])
|
operations.append(['|', 'assign_ored_operation'])
|
||||||
if self.obj.get_property('xored'):
|
if self.obj.get_property('xored'):
|
||||||
operations.append(['xored', '^'])
|
operations.append(['^', 'assign_xored_operation'])
|
||||||
|
|
||||||
if len(operations) > 0:
|
if len(operations) > 0:
|
||||||
self.rtl_header.append(
|
self.rtl_header.append(
|
||||||
Field.templ_dict['combo_operation_comment'].format(
|
Field.templ_dict['combo_operation_comment']['rtl'].format(
|
||||||
path = self.path_underscored))
|
path = self.path_underscored))
|
||||||
|
|
||||||
self.rtl_header = [
|
self.rtl_header = [
|
||||||
*self.rtl_header,
|
*self.rtl_header,
|
||||||
*[Field.templ_dict['assign_combo_operation'].format(
|
*[Field.templ_dict[i[1]]['rtl'].format(
|
||||||
path = self.path_underscored,
|
path = self.path_underscored,
|
||||||
genvars = self.genvars_str,
|
genvars = self.genvars_str,
|
||||||
op_name = i[0],
|
op_verilog = i[0]) for i in operations]
|
||||||
op_verilog = i[1]) for i in operations]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[self.yaml_signals_to_list(Field.templ_dict[i[1]]) for i in operations]
|
||||||
|
|
||||||
def __process_variables(self, obj: node.RootNode, dimensions: list):
|
|
||||||
|
def __process_variables(self, obj: node.RootNode, array_dimensions: list):
|
||||||
# Save object
|
# Save object
|
||||||
self.obj = obj
|
self.obj = obj
|
||||||
|
|
||||||
# Create full name
|
# Create full name
|
||||||
self.owning_addrmap = obj.owning_addrmap.inst_name
|
self.owning_addrmap = obj.owning_addrmap.inst_name
|
||||||
self.path = obj.get_path()\
|
self.full_path = obj.get_path().replace('[]', '')
|
||||||
|
self.path = self.full_path\
|
||||||
.replace('[]', '')\
|
.replace('[]', '')\
|
||||||
.replace('{}.'.format(self.owning_addrmap), '')
|
.replace('{}.'.format(self.owning_addrmap), '')
|
||||||
|
|
||||||
self.path_underscored = self.path.replace('.', '_')
|
self.path_underscored = self.path.replace('.', '_')
|
||||||
self.path_wo_field = '.'.join(self.path.split('.', -1)[0:-1])
|
self.path_wo_field = '.'.join(self.path.split('.', -1)[0:-1])
|
||||||
|
|
||||||
|
# Field type
|
||||||
|
self.field_type = 'logic'
|
||||||
|
|
||||||
# Save dimensions of unpacked dimension
|
# Save dimensions of unpacked dimension
|
||||||
self.dimensions = dimensions
|
self.array_dimensions = array_dimensions
|
||||||
|
|
||||||
# Calculate how many genvars shall be added
|
# Calculate how many genvars shall be added
|
||||||
genvars = ['[{}]'.format(chr(97+i)) for i in range(len(dimensions))]
|
genvars = ['[{}]'.format(chr(97+i)) for i in range(len(array_dimensions))]
|
||||||
self.genvars_str = ''.join(genvars)
|
self.genvars_str = ''.join(genvars)
|
||||||
|
|
||||||
# Write enable
|
# Write enable
|
||||||
@ -138,7 +144,7 @@ class Field(Component):
|
|||||||
|
|
||||||
# Add comment with summary on field's properties
|
# Add comment with summary on field's properties
|
||||||
return \
|
return \
|
||||||
Field.templ_dict['field_comment'].format(
|
Field.templ_dict['field_comment']['rtl'].format(
|
||||||
name = self.obj.inst_name,
|
name = self.obj.inst_name,
|
||||||
hw_access = str(self.hw_access)[11:],
|
hw_access = str(self.hw_access)[11:],
|
||||||
sw_access = str(self.sw_access)[11:],
|
sw_access = str(self.sw_access)[11:],
|
||||||
@ -156,7 +162,7 @@ class Field(Component):
|
|||||||
sense_list = 'sense_list_rst' if self.rst['async'] else 'sense_list_no_rst'
|
sense_list = 'sense_list_rst' if self.rst['async'] else 'sense_list_no_rst'
|
||||||
|
|
||||||
self.rtl_header.append(
|
self.rtl_header.append(
|
||||||
Field.templ_dict[sense_list].format(
|
Field.templ_dict[sense_list]['rtl'].format(
|
||||||
clk_name = "clk",
|
clk_name = "clk",
|
||||||
rst_edge = self.rst['edge'],
|
rst_edge = self.rst['edge'],
|
||||||
rst_name = self.rst['name']))
|
rst_name = self.rst['name']))
|
||||||
@ -164,15 +170,24 @@ class Field(Component):
|
|||||||
# Add actual reset line
|
# Add actual reset line
|
||||||
if self.rst['name']:
|
if self.rst['name']:
|
||||||
self.rtl_header.append(
|
self.rtl_header.append(
|
||||||
Field.templ_dict['rst_field_assign'].format(
|
Field.templ_dict['rst_field_assign']['rtl'].format(
|
||||||
path = self.path_underscored,
|
path = self.path_underscored,
|
||||||
rst_name = self.rst['name'],
|
rst_name = self.rst['name'],
|
||||||
rst_negl = "!" if self.rst['active'] == "active_high" else "",
|
rst_negl = "!" if self.rst['active'] == "active_high" else "",
|
||||||
rst_value = self.rst['value'],
|
rst_value = self.rst['value'],
|
||||||
genvars = self.genvars_str))
|
genvars = self.genvars_str))
|
||||||
|
|
||||||
|
self.yaml_signals_to_list(Field.templ_dict['rst_field_assign'])
|
||||||
|
|
||||||
self.rtl_header.append("begin")
|
self.rtl_header.append("begin")
|
||||||
|
|
||||||
|
# Add name of actual field to Signal field
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
def __prepend_signal_declarations(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def __add_access_rtl(self):
|
def __add_access_rtl(self):
|
||||||
# Not all access types are required and the order might differ
|
# Not all access types are required and the order might differ
|
||||||
# depending on what types are defined and what precedence is
|
# depending on what types are defined and what precedence is
|
||||||
@ -191,19 +206,21 @@ class Field(Component):
|
|||||||
if self.hw_access in (AccessType.rw, AccessType.w):
|
if self.hw_access in (AccessType.rw, AccessType.w):
|
||||||
if self.we_or_wel:
|
if self.we_or_wel:
|
||||||
access_rtl['hw_write'].append(
|
access_rtl['hw_write'].append(
|
||||||
Field.templ_dict['hw_access_we_wel'].format(
|
Field.templ_dict['hw_access_we_wel']['rtl'].format(
|
||||||
negl = '!' if self.obj.get_property('wel') else '',
|
negl = '!' if self.obj.get_property('wel') else '',
|
||||||
path = self.path_underscored,
|
path = self.path_underscored,
|
||||||
genvars = self.genvars_str))
|
genvars = self.genvars_str))
|
||||||
else:
|
else:
|
||||||
access_rtl['hw_write'].append(
|
access_rtl['hw_write'].append(
|
||||||
Field.templ_dict['hw_access_no_we_wel'])
|
Field.templ_dict['hw_access_no_we_wel']['rtl'])
|
||||||
|
|
||||||
access_rtl['hw_write'].append(
|
access_rtl['hw_write'].append(
|
||||||
Field.templ_dict['hw_access_field'].format(
|
Field.templ_dict['hw_access_field']['rtl'].format(
|
||||||
path = self.path_underscored,
|
path = self.path_underscored,
|
||||||
genvars = self.genvars_str))
|
genvars = self.genvars_str))
|
||||||
|
|
||||||
|
self.yaml_signals_to_list(Field.templ_dict['hw_access_field'])
|
||||||
|
|
||||||
# Define software access (if applicable)
|
# Define software access (if applicable)
|
||||||
access_rtl['sw_write'] = []
|
access_rtl['sw_write'] = []
|
||||||
|
|
||||||
@ -213,19 +230,19 @@ class Field(Component):
|
|||||||
|
|
||||||
if isinstance(swwe, (node.FieldNode, node.SignalNode)):
|
if isinstance(swwe, (node.FieldNode, node.SignalNode)):
|
||||||
access_rtl['sw_write'].append(
|
access_rtl['sw_write'].append(
|
||||||
Field.templ_dict['sw_access_field_swwe'].format(
|
Field.templ_dict['sw_access_field_swwe']['rtl'].format(
|
||||||
path_wo_field = self.path_wo_field,
|
path_wo_field = self.path_wo_field,
|
||||||
genvars = self.genvars_str,
|
genvars = self.genvars_str,
|
||||||
swwe = Component.get_ref_name(swwe)))
|
swwe = Component.get_signal_name(swwe)))
|
||||||
elif isinstance(swwel, (node.FieldNode, node.SignalNode)):
|
elif isinstance(swwel, (node.FieldNode, node.SignalNode)):
|
||||||
access_rtl['sw_write'].append(
|
access_rtl['sw_write'].append(
|
||||||
Field.templ_dict['sw_access_field_swwel'].format(
|
Field.templ_dict['sw_access_field_swwel']['rtl'].format(
|
||||||
path_wo_field = self.path_wo_field,
|
path_wo_field = self.path_wo_field,
|
||||||
genvars = self.genvars_str,
|
genvars = self.genvars_str,
|
||||||
swwel = Component.get_ref_name(swwel)))
|
swwel = Component.get_signal_name(swwel)))
|
||||||
else:
|
else:
|
||||||
access_rtl['sw_write'].append(
|
access_rtl['sw_write'].append(
|
||||||
Field.templ_dict['sw_access_field'].format(
|
Field.templ_dict['sw_access_field']['rtl'].format(
|
||||||
path_wo_field = self.path_wo_field,
|
path_wo_field = self.path_wo_field,
|
||||||
genvars = self.genvars_str))
|
genvars = self.genvars_str))
|
||||||
|
|
||||||
@ -237,7 +254,7 @@ class Field(Component):
|
|||||||
self.logger.warning("The OnReadType.wuser is not yet supported!")
|
self.logger.warning("The OnReadType.wuser is not yet supported!")
|
||||||
elif onwrite in (OnWriteType.wclr, OnWriteType.wset):
|
elif onwrite in (OnWriteType.wclr, OnWriteType.wset):
|
||||||
access_rtl['sw_write'].append(
|
access_rtl['sw_write'].append(
|
||||||
Field.templ_dict[str(onwrite)].format(
|
Field.templ_dict[str(onwrite)]['rtl'].format(
|
||||||
path = self.path_underscored,
|
path = self.path_underscored,
|
||||||
genvars = self.genvars_str,
|
genvars = self.genvars_str,
|
||||||
path_wo_field = self.path_wo_field
|
path_wo_field = self.path_wo_field
|
||||||
@ -247,7 +264,7 @@ class Field(Component):
|
|||||||
# If field spans multiple bytes, every byte shall have a seperate enable!
|
# If field spans multiple bytes, every byte shall have a seperate enable!
|
||||||
for j, i in enumerate(range(self.lsbyte, self.msbyte+1)):
|
for j, i in enumerate(range(self.lsbyte, self.msbyte+1)):
|
||||||
access_rtl['sw_write'].append(
|
access_rtl['sw_write'].append(
|
||||||
Field.templ_dict[str(onwrite)].format(
|
Field.templ_dict[str(onwrite)]['rtl'].format(
|
||||||
path = self.path_underscored,
|
path = self.path_underscored,
|
||||||
genvars = self.genvars_str,
|
genvars = self.genvars_str,
|
||||||
i = i,
|
i = i,
|
||||||
@ -260,7 +277,7 @@ class Field(Component):
|
|||||||
# If field spans multiple bytes, every byte shall have a seperate enable!
|
# If field spans multiple bytes, every byte shall have a seperate enable!
|
||||||
for j, i in enumerate(range(self.lsbyte, self.msbyte+1)):
|
for j, i in enumerate(range(self.lsbyte, self.msbyte+1)):
|
||||||
access_rtl['sw_write'].append(
|
access_rtl['sw_write'].append(
|
||||||
Field.templ_dict['sw_access_byte'].format(
|
Field.templ_dict['sw_access_byte']['rtl'].format(
|
||||||
path = self.path_underscored,
|
path = self.path_underscored,
|
||||||
genvars = self.genvars_str,
|
genvars = self.genvars_str,
|
||||||
i = i,
|
i = i,
|
||||||
@ -279,7 +296,7 @@ class Field(Component):
|
|||||||
self.logger.warning("The OnReadType.ruser is not yet supported!")
|
self.logger.warning("The OnReadType.ruser is not yet supported!")
|
||||||
else:
|
else:
|
||||||
access_rtl['sw_read'].append(
|
access_rtl['sw_read'].append(
|
||||||
Field.templ_dict[str(onread)].format(
|
Field.templ_dict[str(onread)]['rtl'].format(
|
||||||
path = self.path_underscored,
|
path = self.path_underscored,
|
||||||
genvars = self.genvars_str,
|
genvars = self.genvars_str,
|
||||||
path_wo_field = self.path_wo_field
|
path_wo_field = self.path_wo_field
|
||||||
@ -289,7 +306,7 @@ class Field(Component):
|
|||||||
# Add singlepulse property
|
# Add singlepulse property
|
||||||
if self.obj.get_property('singlepulse'):
|
if self.obj.get_property('singlepulse'):
|
||||||
access_rtl['singlepulse'] = [
|
access_rtl['singlepulse'] = [
|
||||||
Field.templ_dict['singlepulse'].format(
|
Field.templ_dict['singlepulse']['rtl'].format(
|
||||||
path = self.path_underscored,
|
path = self.path_underscored,
|
||||||
genvars = self.genvars_str)
|
genvars = self.genvars_str)
|
||||||
]
|
]
|
||||||
@ -335,40 +352,19 @@ class Field(Component):
|
|||||||
self.rtl_header = [*self.rtl_header, *order_list_rtl]
|
self.rtl_header = [*self.rtl_header, *order_list_rtl]
|
||||||
|
|
||||||
self.rtl_header.append(
|
self.rtl_header.append(
|
||||||
Field.templ_dict['end_field_ff'].format(
|
Field.templ_dict['end_field_ff']['rtl'].format(
|
||||||
path = self.path_underscored))
|
path = self.path_underscored))
|
||||||
|
|
||||||
|
|
||||||
def __add_ports(self):
|
def __add_ports(self):
|
||||||
# Port is writable by hardware --> Input port from hardware
|
|
||||||
if self.hw_access in (AccessType.rw, AccessType.w):
|
|
||||||
self.ports['input'].append(
|
|
||||||
Port("{}_in".format(self.path_underscored),
|
|
||||||
"",
|
|
||||||
self.dimensions
|
|
||||||
))
|
|
||||||
|
|
||||||
# Port has enable signal --> create such an enable
|
|
||||||
if self.we_or_wel:
|
|
||||||
self.ports['input'].append(
|
|
||||||
Port("{}_hw_wr".format(self.path_underscored),
|
|
||||||
"",
|
|
||||||
self.dimensions
|
|
||||||
))
|
|
||||||
|
|
||||||
if self.hw_access in (AccessType.rw, AccessType.r):
|
if self.hw_access in (AccessType.rw, AccessType.r):
|
||||||
self.ports['output'].append(
|
|
||||||
Port("{}_r".format(self.path_underscored),
|
|
||||||
"[{}:0]".format(self.obj.width-1) if self.obj.width > 1 else "",
|
|
||||||
self.dimensions
|
|
||||||
))
|
|
||||||
|
|
||||||
# Connect flops to output port
|
# Connect flops to output port
|
||||||
self.rtl_header.append(
|
self.rtl_header.append(
|
||||||
Field.templ_dict['out_port_assign'].format(
|
Field.templ_dict['out_port_assign']['rtl'].format(
|
||||||
genvars = self.genvars_str,
|
genvars = self.genvars_str,
|
||||||
path = self.path_underscored))
|
path = self.path_underscored))
|
||||||
|
|
||||||
|
self.yaml_signals_to_list(Field.templ_dict['out_port_assign'])
|
||||||
|
|
||||||
def sanity_checks(self):
|
def sanity_checks(self):
|
||||||
# If hw=rw/sw=[r]w and hw has no we/wel, sw will never be able to write
|
# If hw=rw/sw=[r]w and hw has no we/wel, sw will never be able to write
|
||||||
@ -381,3 +377,6 @@ class Field(Component):
|
|||||||
"precedence for hardware will render software's "\
|
"precedence for hardware will render software's "\
|
||||||
"write property useless since hardware will "\
|
"write property useless since hardware will "\
|
||||||
"write every cycle.")
|
"write every cycle.")
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: Counter & hw=r shouldn't work
|
||||||
|
@ -25,28 +25,6 @@ class Register(Component):
|
|||||||
self.create_logger("{}.{}".format(self.owning_addrmap, self.path), config)
|
self.create_logger("{}.{}".format(self.owning_addrmap, self.path), config)
|
||||||
self.logger.debug('Starting to process register "{}"'.format(obj.inst_name))
|
self.logger.debug('Starting to process register "{}"'.format(obj.inst_name))
|
||||||
|
|
||||||
# Create comment and provide user information about register he/she
|
|
||||||
# is looking at.
|
|
||||||
self.rtl_header.append(
|
|
||||||
Register.templ_dict['reg_comment'].format(
|
|
||||||
name = obj.inst_name,
|
|
||||||
dimensions = self.dimensions,
|
|
||||||
depth = self.depth))
|
|
||||||
|
|
||||||
# Create wires every register
|
|
||||||
self.rtl_header.append(
|
|
||||||
Register.templ_dict['rw_wire_declare'].format(
|
|
||||||
path = self.path,
|
|
||||||
depth = self.depth))
|
|
||||||
|
|
||||||
# Create generate block for register and add comment
|
|
||||||
self.rtl_header.append("generate")
|
|
||||||
for i in range(self.dimensions):
|
|
||||||
self.rtl_header.append(
|
|
||||||
Register.templ_dict['generate_for_start'].format(
|
|
||||||
iterator = chr(97+i),
|
|
||||||
limit = self.array_dimensions[i]))
|
|
||||||
|
|
||||||
# Create RTL for fields
|
# Create RTL for fields
|
||||||
# Fields should be in order in RTL,therefore, use list
|
# Fields should be in order in RTL,therefore, use list
|
||||||
for field in obj.fields():
|
for field in obj.fields():
|
||||||
@ -57,6 +35,15 @@ class Register(Component):
|
|||||||
|
|
||||||
self.children.append(field_obj)
|
self.children.append(field_obj)
|
||||||
|
|
||||||
|
# Create generate block for register and add comment
|
||||||
|
self.rtl_header.append("generate")
|
||||||
|
for i in range(self.dimensions):
|
||||||
|
self.rtl_header.append(
|
||||||
|
Register.templ_dict['generate_for_start'].format(
|
||||||
|
iterator = chr(97+i),
|
||||||
|
limit = self.array_dimensions[i]))
|
||||||
|
|
||||||
|
|
||||||
# End loops
|
# End loops
|
||||||
for i in range(self.dimensions-1, -1, -1):
|
for i in range(self.dimensions-1, -1, -1):
|
||||||
self.rtl_footer.append(
|
self.rtl_footer.append(
|
||||||
@ -72,7 +59,7 @@ class Register(Component):
|
|||||||
rw_wire_assign_field = 'rw_wire_assign_1_dim'
|
rw_wire_assign_field = 'rw_wire_assign_1_dim'
|
||||||
|
|
||||||
self.rtl_header.append(
|
self.rtl_header.append(
|
||||||
Register.templ_dict[rw_wire_assign_field].format(
|
Register.templ_dict[rw_wire_assign_field]['rtl'].format(
|
||||||
path = self.path,
|
path = self.path,
|
||||||
addr = self.obj.absolute_address,
|
addr = self.obj.absolute_address,
|
||||||
genvars = self.genvars_str,
|
genvars = self.genvars_str,
|
||||||
@ -80,6 +67,34 @@ class Register(Component):
|
|||||||
stride = self.obj.array_stride,
|
stride = self.obj.array_stride,
|
||||||
depth = self.depth))
|
depth = self.depth))
|
||||||
|
|
||||||
|
self.yaml_signals_to_list(Register.templ_dict[rw_wire_assign_field])
|
||||||
|
|
||||||
|
# Add wire/register instantiations
|
||||||
|
self.rtl_header = [
|
||||||
|
*[
|
||||||
|
Register.templ_dict['signal_declaration'].format(
|
||||||
|
name = key,
|
||||||
|
type = value[0],
|
||||||
|
unpacked_dim = '[{}]'.format(
|
||||||
|
']['.join(
|
||||||
|
[str(y) for y in value[1]]))
|
||||||
|
if value[1] else '')
|
||||||
|
for (key, value) in self.get_signals().items()],
|
||||||
|
'',
|
||||||
|
*self.rtl_header,
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create comment and provide user information about register he/she
|
||||||
|
# is looking at.
|
||||||
|
self.rtl_header = [
|
||||||
|
Register.templ_dict['reg_comment'].format(
|
||||||
|
name = obj.inst_name,
|
||||||
|
dimensions = self.dimensions,
|
||||||
|
depth = self.depth),
|
||||||
|
*self.rtl_header
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def __process_variables(self, obj: node.RootNode):
|
def __process_variables(self, obj: node.RootNode):
|
||||||
# Save object
|
# Save object
|
||||||
self.obj = obj
|
self.obj = obj
|
||||||
|
@ -11,6 +11,6 @@ module_declaration: |-
|
|||||||
{outputs}
|
{outputs}
|
||||||
);
|
);
|
||||||
input_port: |-
|
input_port: |-
|
||||||
input {packed_dim:15s}{name:25s} {unpacked_dim},
|
input {signal_type:15s}{name:25s} {unpacked_dim},
|
||||||
output_port: |-
|
output_port: |-
|
||||||
output {packed_dim:15s}{name:25s} {unpacked_dim},
|
output {signal_type:15s}{name:25s} {unpacked_dim},
|
||||||
|
@ -1,80 +1,110 @@
|
|||||||
---
|
---
|
||||||
sense_list_rst: |-
|
sense_list_rst:
|
||||||
|
rtl: |-
|
||||||
always_ff @(posedge {clk_name} or {rst_edge} {rst_name})
|
always_ff @(posedge {clk_name} or {rst_edge} {rst_name})
|
||||||
sense_list_no_rst: |-
|
sense_list_no_rst:
|
||||||
|
rtl: |-
|
||||||
always_ff @(posedge {clk_name})
|
always_ff @(posedge {clk_name})
|
||||||
rst_field_assign: |-
|
rst_field_assign:
|
||||||
|
rtl: |-
|
||||||
if ({rst_negl}{rst_name})
|
if ({rst_negl}{rst_name})
|
||||||
begin
|
begin
|
||||||
{path}_q{genvars} <= {rst_value};
|
{path}_q{genvars} <= {rst_value};
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
sw_access_field: |-
|
signals:
|
||||||
|
- name: '{path}_q'
|
||||||
|
signal_type: '{field_type}'
|
||||||
|
sw_access_field:
|
||||||
|
rtl: |-
|
||||||
if ({path_wo_field}_sw_wr{genvars})
|
if ({path_wo_field}_sw_wr{genvars})
|
||||||
begin
|
begin
|
||||||
sw_access_field_swwe: |-
|
sw_access_field_swwe:
|
||||||
|
rtl: |-
|
||||||
if ({path_wo_field}_sw_wr{genvars} && {swwe}) // swwe property
|
if ({path_wo_field}_sw_wr{genvars} && {swwe}) // swwe property
|
||||||
begin
|
begin
|
||||||
sw_access_field_swwel: |-
|
sw_access_field_swwel:
|
||||||
|
rtl: |-
|
||||||
if ({path_wo_field}_sw_wr{genvars} && !{swwel}) // swwel property
|
if ({path_wo_field}_sw_wr{genvars} && !{swwel}) // swwel property
|
||||||
begin
|
begin
|
||||||
sw_access_byte: |-
|
sw_access_byte:
|
||||||
|
rtl: |-
|
||||||
if (byte_enable[{i}])
|
if (byte_enable[{i}])
|
||||||
begin
|
begin
|
||||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= sw_wr_bus[{msb_bus}-:{bus_w}];
|
{path}_q{genvars}[{msb_field}-:{field_w}] <= sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||||
end
|
end
|
||||||
|
|
||||||
hw_access_we_wel: |-
|
hw_access_we_wel:
|
||||||
|
rtl: |-
|
||||||
if ({negl}{path}_hw_wr{genvars})
|
if ({negl}{path}_hw_wr{genvars})
|
||||||
hw_access_no_we_wel: |-
|
hw_access_no_we_wel:
|
||||||
|
rtl: |-
|
||||||
// we or wel property not set
|
// we or wel property not set
|
||||||
hw_access_field: |-
|
hw_access_field:
|
||||||
|
rtl: |-
|
||||||
begin
|
begin
|
||||||
{path}_q{genvars} <= {path}_in{genvars};
|
{path}_q{genvars} <= {path}_in{genvars};
|
||||||
end
|
end
|
||||||
end_field_ff: |-
|
signals:
|
||||||
|
- name: '{path}_q'
|
||||||
|
signal_type: '{field_type}'
|
||||||
|
input_ports:
|
||||||
|
- name: '{path}_in'
|
||||||
|
signal_type: '{field_type}'
|
||||||
|
end_field_ff:
|
||||||
|
rtl: |-
|
||||||
end // of {path}'s always_ff
|
end // of {path}'s always_ff
|
||||||
OnWriteType.woset: |-
|
OnWriteType.woset:
|
||||||
|
rtl: |-
|
||||||
if (byte_enable[{i}]) // woset property
|
if (byte_enable[{i}]) // woset property
|
||||||
begin
|
begin
|
||||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] | sw_wr_bus[{msb_bus}-:{bus_w}];
|
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] | sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||||
end
|
end
|
||||||
OnWriteType.woclr: |-
|
OnWriteType.woclr:
|
||||||
|
rtl: |-
|
||||||
if (byte_enable[{i}]) // woclr property
|
if (byte_enable[{i}]) // woclr property
|
||||||
begin
|
begin
|
||||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] & ~sw_wr_bus[{msb_bus}-:{bus_w}];
|
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] & ~sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||||
end
|
end
|
||||||
OnWriteType.wot: |-
|
OnWriteType.wot:
|
||||||
|
rtl: |-
|
||||||
if (byte_enable[{i}]) // wot property
|
if (byte_enable[{i}]) // wot property
|
||||||
begin
|
begin
|
||||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] ^ sw_wr_bus[{msb_bus}-:{bus_w}];
|
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] ^ sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||||
end
|
end
|
||||||
OnWriteType.wzs: |-
|
OnWriteType.wzs:
|
||||||
|
rtl: |-
|
||||||
if (byte_enable[{i}]) // wzs property
|
if (byte_enable[{i}]) // wzs property
|
||||||
begin
|
begin
|
||||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] & sw_wr_bus[{msb_bus}-:{bus_w}];
|
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] & sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||||
end
|
end
|
||||||
OnWriteType.wzt: |-
|
OnWriteType.wzt:
|
||||||
|
rtl: |-
|
||||||
if (byte_enable[{i}]) // wzt property
|
if (byte_enable[{i}]) // wzt property
|
||||||
begin
|
begin
|
||||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] ~^ sw_wr_bus[{msb_bus}-:{bus_w}];
|
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] ~^ sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||||
end
|
end
|
||||||
OnWriteType.wclr: |-
|
OnWriteType.wclr:
|
||||||
|
rtl: |-
|
||||||
{path}_q{genvars} <= {{width{{1'b0}}}};
|
{path}_q{genvars} <= {{width{{1'b0}}}};
|
||||||
OnWriteType.wset: |-
|
OnWriteType.wset:
|
||||||
|
rtl: |-
|
||||||
{path}_q{genvars} <= {{width{{1'b1}}}};
|
{path}_q{genvars} <= {{width{{1'b1}}}};
|
||||||
OnReadType.rclr: |-
|
OnReadType.rclr:
|
||||||
|
rtl: |-
|
||||||
if ({path_wo_field}_sw_rd{genvars}) // rclr property
|
if ({path_wo_field}_sw_rd{genvars}) // rclr property
|
||||||
begin
|
begin
|
||||||
{path}_q{genvars} <= {{width{{1'b0}}}};
|
{path}_q{genvars} <= {{width{{1'b0}}}};
|
||||||
end
|
end
|
||||||
OnReadType.rset: |-
|
OnReadType.rset:
|
||||||
|
rtl: |-
|
||||||
if ({path_wo_field}_sw_rd{genvars}) // rset property
|
if ({path_wo_field}_sw_rd{genvars}) // rset property
|
||||||
begin
|
begin
|
||||||
{path}_q{genvars} <= {{width{{1'b1}}}};
|
{path}_q{genvars} <= {{width{{1'b1}}}};
|
||||||
end
|
end
|
||||||
|
|
||||||
field_comment: |-
|
field_comment:
|
||||||
|
rtl: |-
|
||||||
|
|
||||||
//-----------------FIELD SUMMARY-----------------
|
//-----------------FIELD SUMMARY-----------------
|
||||||
// name : {name} ({path_wo_field}[{msb}:{lsb}])
|
// name : {name} ({path_wo_field}[{msb}:{lsb}])
|
||||||
@ -83,17 +113,80 @@ field_comment: |-
|
|||||||
// reset : {rst_active} / {rst_type}
|
// reset : {rst_active} / {rst_type}
|
||||||
// flags : {misc_flags}
|
// flags : {misc_flags}
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
combo_operation_comment: |-
|
combo_operation_comment:
|
||||||
|
rtl: |-
|
||||||
|
|
||||||
// Combinational logic for {path}
|
// Combinational logic for {path}
|
||||||
assign_combo_operation: |-
|
assign_anded_operation:
|
||||||
assign {path}_{op_name}{genvars} = {op_verilog}{path}_q{genvars}
|
rtl: |-
|
||||||
singlepulse: |-
|
assign {path}_anded{genvars} = {op_verilog}{path}_q{genvars};
|
||||||
|
output_ports:
|
||||||
|
- name: '{path}_anded'
|
||||||
|
signal_type: 'logic'
|
||||||
|
assign_ored_operation:
|
||||||
|
rtl: |-
|
||||||
|
assign {path}_ored{genvars} = {op_verilog}{path}_q{genvars};
|
||||||
|
output_ports:
|
||||||
|
- name: '{path}_ored'
|
||||||
|
signal_type: 'logic'
|
||||||
|
assign_xored_operation:
|
||||||
|
rtl: |-
|
||||||
|
assign {path}_xored{genvars} = {op_verilog}{path}_q{genvars};
|
||||||
|
output_ports:
|
||||||
|
- name: '{path}_xored'
|
||||||
|
signal_type: 'logic'
|
||||||
|
singlepulse:
|
||||||
|
rtl: |-
|
||||||
begin
|
begin
|
||||||
{path}{genvars} <= 0;
|
{path}{genvars}_q <= 0;
|
||||||
end
|
end
|
||||||
out_port_assign: |-
|
out_port_assign:
|
||||||
|
rtl: |-
|
||||||
// Connect register to hardware output port
|
// Connect register to hardware output port
|
||||||
assign {path}_r{genvars} = {path}_q{genvars};
|
assign {path}_r{genvars} = {path}_q{genvars};
|
||||||
|
output_ports:
|
||||||
|
- name: '{path}_r'
|
||||||
|
signal_type: '{field_type}'
|
||||||
|
counter:
|
||||||
|
rtl: |-
|
||||||
|
always_comb
|
||||||
|
begin
|
||||||
|
{path}_next{genvars} = {path}_q{genvars};
|
||||||
|
{path}_update_cnt{genvars} = 0;
|
||||||
|
|
||||||
|
{incr_counter}
|
||||||
|
|
||||||
|
{decr_counter}
|
||||||
|
end
|
||||||
|
incr_counter:
|
||||||
|
rtl: |-
|
||||||
|
{incr_counter_condition}
|
||||||
|
begin
|
||||||
|
{path}_next{genvars} += {path}_{operation_str}_val{genvars};
|
||||||
|
{path}_update_cnt{genvars} = 1;
|
||||||
|
end
|
||||||
|
decr_counter:
|
||||||
|
rtl: |-
|
||||||
|
{incr_counter_condition}
|
||||||
|
begin
|
||||||
|
{path}_next{genvars} += {path}_{operation_str}_val{genvars};
|
||||||
|
{path}_update_cnt{genvars} = 1;
|
||||||
|
end
|
||||||
|
incr_counter_condition:
|
||||||
|
rtl: |-
|
||||||
|
if ({path}_incr{genvars})
|
||||||
|
incr_sat_counter_condition:
|
||||||
|
rtl: |-
|
||||||
|
if ({path}_incr{genvars} && {path}_next{genvars} + {path}_incr_val{genvars} <= {sat_value})
|
||||||
|
decr_counter_condition:
|
||||||
|
rtl: |-
|
||||||
|
if ({path}_decr{genvars})
|
||||||
|
decr_sat_counter_condition:
|
||||||
|
rtl: |-
|
||||||
|
if ({path}_decr{genvars} && {path}_next{genvars} - {path}_decr_val{genvars} >= {sat_value})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,14 +1,39 @@
|
|||||||
---
|
---
|
||||||
rw_wire_declare: |
|
rw_wire_assign_1_dim:
|
||||||
logic {path}_sw_wr {depth};
|
rtl: |
|
||||||
logic {path}_sw_rd {depth};
|
// Assign register-activation signals
|
||||||
rw_wire_assign_1_dim: |
|
assign {path}_reg_active{genvars} = addr == {addr};
|
||||||
assign {path}_sw_wr{genvars} = addr == {addr} && r_vld;
|
|
||||||
assign {path}_sw_rd{genvars} = addr == {addr} && w_vld;
|
assign {path}_sw_wr = {path}_reg_active && r_vld;
|
||||||
rw_wire_assign_multi_dim: |
|
assign {path}_sw_rd = {path}_reg_active && w_vld;
|
||||||
assign {path}_sw_wr{genvars} = addr == ({addr}+({genvars_sum})*{stride}) && r_vld;
|
signals:
|
||||||
assign {path}_sw_rd{genvars} = addr == ({addr}+({genvars_sum})*{stride}) && w_vld;
|
- name: '{path}_sw_wr'
|
||||||
|
signal_type: 'logic'
|
||||||
|
- name: '{path}_sw_rd'
|
||||||
|
signal_type: 'logic'
|
||||||
|
- name: '{path}_reg_active'
|
||||||
|
signal_type: 'logic'
|
||||||
|
input_ports:
|
||||||
|
output_ports:
|
||||||
|
rw_wire_assign_multi_dim:
|
||||||
|
rtl: |
|
||||||
|
|
||||||
|
// Assign register-activation signals
|
||||||
|
assign {path}_reg_active{genvars} = addr == ({addr}+({genvars_sum})*{stride});
|
||||||
|
|
||||||
|
assign {path}_sw_wr{genvars} = {path}_reg_active{genvars} && r_vld;
|
||||||
|
assign {path}_sw_rd{genvars} = {path}_reg_active{genvars} && w_vld;
|
||||||
|
signals:
|
||||||
|
- name: '{path}_sw_wr'
|
||||||
|
signal_type: 'logic'
|
||||||
|
- name: '{path}_sw_rd'
|
||||||
|
signal_type: 'logic'
|
||||||
|
- name: '{path}_reg_active'
|
||||||
|
signal_type: 'logic'
|
||||||
|
input_ports:
|
||||||
|
output_ports:
|
||||||
reg_comment: |-
|
reg_comment: |-
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
*******************************************************************
|
*******************************************************************
|
||||||
* REGISTER : {name}
|
* REGISTER : {name}
|
||||||
@ -21,3 +46,5 @@ generate_for_start: |-
|
|||||||
begin
|
begin
|
||||||
generate_for_end: |-
|
generate_for_end: |-
|
||||||
end // of for loop with iterator {dimension}
|
end // of for loop with iterator {dimension}
|
||||||
|
signal_declaration: |-
|
||||||
|
{type:10s}{name:20s} {unpacked_dim};
|
||||||
|
Loading…
Reference in New Issue
Block a user