mirror of
https://github.com/Silicon1602/srdl2sv.git
synced 2024-12-22 06:58:41 +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
|
||||
# by name (for example, in case of aliases)
|
||||
self.registers = dict()
|
||||
self.rdl_nodes = dict()
|
||||
|
||||
# Traverse through children
|
||||
for child in obj.children():
|
||||
@ -61,24 +62,26 @@ class AddrMap(Component):
|
||||
# Input ports
|
||||
input_ports_rtl = [
|
||||
AddrMap.templ_dict['input_port'].format(
|
||||
name = x.name,
|
||||
packed_dim = x.packed_dim,
|
||||
name = key,
|
||||
signal_type = value[0],
|
||||
unpacked_dim = '[{}]'.format(
|
||||
']['.join(
|
||||
[str(y) for y in x.unpacked_dim]))
|
||||
if x.unpacked_dim else '')
|
||||
for x in self.get_ports('input')]
|
||||
[str(y) for y in value[1]]))
|
||||
if value[1] else '')
|
||||
for (key, value) in self.get_ports('input').items()
|
||||
]
|
||||
|
||||
# Output ports
|
||||
output_ports_rtl = [
|
||||
AddrMap.templ_dict['output_port'].format(
|
||||
name = x.name,
|
||||
packed_dim = x.packed_dim,
|
||||
name = key,
|
||||
signal_type = value[0],
|
||||
unpacked_dim = '[{}]'.format(
|
||||
']['.join(
|
||||
[str(y) for y in x.unpacked_dim]))
|
||||
if x.unpacked_dim else '')
|
||||
for x in self.get_ports('output')]
|
||||
[str(y) for y in value[1]]))
|
||||
if value[1] else '')
|
||||
for (key, value) in self.get_ports('output').items()
|
||||
]
|
||||
|
||||
# Remove comma from last port entry
|
||||
output_ports_rtl[-1] = output_ports_rtl[-1].rstrip(',')
|
||||
|
@ -7,10 +7,13 @@ from systemrdl import node
|
||||
from log.log import create_logger
|
||||
|
||||
# Define NamedTuple
|
||||
class Port(NamedTuple):
|
||||
class TypeDefMembers(NamedTuple):
|
||||
name: str
|
||||
packed_dim: str
|
||||
unpacked_dim: list
|
||||
member_type: str
|
||||
|
||||
class TypeDef(NamedTuple):
|
||||
name: str
|
||||
members: list[TypeDefMembers]
|
||||
|
||||
class Component():
|
||||
def __init__(self):
|
||||
@ -18,9 +21,10 @@ class Component():
|
||||
self.rtl_footer = []
|
||||
self.children = []
|
||||
self.ports = dict()
|
||||
self.ports['input'] = []
|
||||
self.ports['output'] = []
|
||||
self.ports['inout'] = []
|
||||
self.signals = dict()
|
||||
self.ports['input'] = dict()
|
||||
self.ports['output'] = dict()
|
||||
self.field_type = ''
|
||||
|
||||
def create_logger(self, name: str, config: dict):
|
||||
self.logger = create_logger(
|
||||
@ -32,10 +36,19 @@ class Component():
|
||||
|
||||
def get_ports(self, port_type: str):
|
||||
self.logger.debug("Return port list")
|
||||
return [
|
||||
*self.ports[port_type],
|
||||
*list(chain(*[x.get_ports(port_type) for x in self.children]))
|
||||
]
|
||||
|
||||
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:
|
||||
self.logger.debug("Return RTL")
|
||||
@ -102,25 +115,60 @@ class Component():
|
||||
|
||||
@staticmethod
|
||||
def split_dimensions(path: str):
|
||||
new_path = re.match(r'(.*?)(\[.*\])?(.*)', path)
|
||||
return (''.join([new_path.group(1), new_path.group(3)]),
|
||||
new_path.group(2) if new_path.group(2) else '[0]')
|
||||
re_dimensions = re.compile('(\[[^]]\])')
|
||||
new_path = re_dimensions.sub('', path)
|
||||
return (new_path, ''.join(re_dimensions.findall(path)))
|
||||
|
||||
@staticmethod
|
||||
def get_ref_name(obj):
|
||||
def get_signal_name(obj):
|
||||
name = []
|
||||
|
||||
try:
|
||||
child_obj = obj.node
|
||||
except AttributeError:
|
||||
child_obj = obj
|
||||
|
||||
split_name = Component.split_dimensions(
|
||||
Component.get_underscored_path(
|
||||
obj.get_path(),
|
||||
obj.owning_addrmap.inst_name)
|
||||
child_obj.get_path(),
|
||||
child_obj.owning_addrmap.inst_name)
|
||||
)
|
||||
|
||||
name.append(split_name[0])
|
||||
|
||||
if isinstance(obj, (node.FieldNode)):
|
||||
if isinstance(obj, node.FieldNode):
|
||||
name.append('_q')
|
||||
elif isinstance(obj, node.SignalNode):
|
||||
pass
|
||||
else:
|
||||
name.append('_')
|
||||
name.append(obj.name)
|
||||
|
||||
name.append(split_name[1])
|
||||
|
||||
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
|
||||
|
||||
# Local modules
|
||||
from components.component import Component, Port
|
||||
from components.component import Component
|
||||
from . import templates
|
||||
|
||||
class Field(Component):
|
||||
@ -16,11 +16,11 @@ class Field(Component):
|
||||
pkg_resources.read_text(templates, 'fields.yaml'),
|
||||
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__()
|
||||
|
||||
# Save and/or process important variables
|
||||
self.__process_variables(obj, dimensions)
|
||||
self.__process_variables(obj, array_dimensions)
|
||||
|
||||
# Create logger object
|
||||
self.create_logger("{}.{}".format(self.owning_addrmap, self.path), config)
|
||||
@ -40,49 +40,55 @@ class Field(Component):
|
||||
self.__add_access_rtl()
|
||||
self.__add_combo()
|
||||
self.__add_ports()
|
||||
self.__prepend_signal_declarations()
|
||||
|
||||
def __add_combo(self):
|
||||
operations = []
|
||||
if self.obj.get_property('anded'):
|
||||
operations.append(['anded', '&'])
|
||||
operations.append(['&', 'assign_anded_operation'])
|
||||
if self.obj.get_property('ored'):
|
||||
operations.append(['ored', '|'])
|
||||
operations.append(['|', 'assign_ored_operation'])
|
||||
if self.obj.get_property('xored'):
|
||||
operations.append(['xored', '^'])
|
||||
operations.append(['^', 'assign_xored_operation'])
|
||||
|
||||
if len(operations) > 0:
|
||||
self.rtl_header.append(
|
||||
Field.templ_dict['combo_operation_comment'].format(
|
||||
Field.templ_dict['combo_operation_comment']['rtl'].format(
|
||||
path = self.path_underscored))
|
||||
|
||||
self.rtl_header = [
|
||||
*self.rtl_header,
|
||||
*[Field.templ_dict['assign_combo_operation'].format(
|
||||
*[Field.templ_dict[i[1]]['rtl'].format(
|
||||
path = self.path_underscored,
|
||||
genvars = self.genvars_str,
|
||||
op_name = i[0],
|
||||
op_verilog = i[1]) for i in operations]
|
||||
op_verilog = i[0]) 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
|
||||
self.obj = obj
|
||||
|
||||
# Create full 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('{}.'.format(self.owning_addrmap), '')
|
||||
|
||||
self.path_underscored = self.path.replace('.', '_')
|
||||
self.path_wo_field = '.'.join(self.path.split('.', -1)[0:-1])
|
||||
|
||||
# Field type
|
||||
self.field_type = 'logic'
|
||||
|
||||
# Save dimensions of unpacked dimension
|
||||
self.dimensions = dimensions
|
||||
self.array_dimensions = array_dimensions
|
||||
|
||||
# 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)
|
||||
|
||||
# Write enable
|
||||
@ -138,7 +144,7 @@ class Field(Component):
|
||||
|
||||
# Add comment with summary on field's properties
|
||||
return \
|
||||
Field.templ_dict['field_comment'].format(
|
||||
Field.templ_dict['field_comment']['rtl'].format(
|
||||
name = self.obj.inst_name,
|
||||
hw_access = str(self.hw_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'
|
||||
|
||||
self.rtl_header.append(
|
||||
Field.templ_dict[sense_list].format(
|
||||
Field.templ_dict[sense_list]['rtl'].format(
|
||||
clk_name = "clk",
|
||||
rst_edge = self.rst['edge'],
|
||||
rst_name = self.rst['name']))
|
||||
@ -164,15 +170,24 @@ class Field(Component):
|
||||
# Add actual reset line
|
||||
if self.rst['name']:
|
||||
self.rtl_header.append(
|
||||
Field.templ_dict['rst_field_assign'].format(
|
||||
Field.templ_dict['rst_field_assign']['rtl'].format(
|
||||
path = self.path_underscored,
|
||||
rst_name = self.rst['name'],
|
||||
rst_negl = "!" if self.rst['active'] == "active_high" else "",
|
||||
rst_value = self.rst['value'],
|
||||
genvars = self.genvars_str))
|
||||
|
||||
self.yaml_signals_to_list(Field.templ_dict['rst_field_assign'])
|
||||
|
||||
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):
|
||||
# Not all access types are required and the order might differ
|
||||
# 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.we_or_wel:
|
||||
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 '',
|
||||
path = self.path_underscored,
|
||||
genvars = self.genvars_str))
|
||||
else:
|
||||
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(
|
||||
Field.templ_dict['hw_access_field'].format(
|
||||
Field.templ_dict['hw_access_field']['rtl'].format(
|
||||
path = self.path_underscored,
|
||||
genvars = self.genvars_str))
|
||||
|
||||
self.yaml_signals_to_list(Field.templ_dict['hw_access_field'])
|
||||
|
||||
# Define software access (if applicable)
|
||||
access_rtl['sw_write'] = []
|
||||
|
||||
@ -213,19 +230,19 @@ class Field(Component):
|
||||
|
||||
if isinstance(swwe, (node.FieldNode, node.SignalNode)):
|
||||
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,
|
||||
genvars = self.genvars_str,
|
||||
swwe = Component.get_ref_name(swwe)))
|
||||
swwe = Component.get_signal_name(swwe)))
|
||||
elif isinstance(swwel, (node.FieldNode, node.SignalNode)):
|
||||
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,
|
||||
genvars = self.genvars_str,
|
||||
swwel = Component.get_ref_name(swwel)))
|
||||
swwel = Component.get_signal_name(swwel)))
|
||||
else:
|
||||
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,
|
||||
genvars = self.genvars_str))
|
||||
|
||||
@ -237,7 +254,7 @@ class Field(Component):
|
||||
self.logger.warning("The OnReadType.wuser is not yet supported!")
|
||||
elif onwrite in (OnWriteType.wclr, OnWriteType.wset):
|
||||
access_rtl['sw_write'].append(
|
||||
Field.templ_dict[str(onwrite)].format(
|
||||
Field.templ_dict[str(onwrite)]['rtl'].format(
|
||||
path = self.path_underscored,
|
||||
genvars = self.genvars_str,
|
||||
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!
|
||||
for j, i in enumerate(range(self.lsbyte, self.msbyte+1)):
|
||||
access_rtl['sw_write'].append(
|
||||
Field.templ_dict[str(onwrite)].format(
|
||||
Field.templ_dict[str(onwrite)]['rtl'].format(
|
||||
path = self.path_underscored,
|
||||
genvars = self.genvars_str,
|
||||
i = i,
|
||||
@ -260,7 +277,7 @@ class Field(Component):
|
||||
# If field spans multiple bytes, every byte shall have a seperate enable!
|
||||
for j, i in enumerate(range(self.lsbyte, self.msbyte+1)):
|
||||
access_rtl['sw_write'].append(
|
||||
Field.templ_dict['sw_access_byte'].format(
|
||||
Field.templ_dict['sw_access_byte']['rtl'].format(
|
||||
path = self.path_underscored,
|
||||
genvars = self.genvars_str,
|
||||
i = i,
|
||||
@ -279,7 +296,7 @@ class Field(Component):
|
||||
self.logger.warning("The OnReadType.ruser is not yet supported!")
|
||||
else:
|
||||
access_rtl['sw_read'].append(
|
||||
Field.templ_dict[str(onread)].format(
|
||||
Field.templ_dict[str(onread)]['rtl'].format(
|
||||
path = self.path_underscored,
|
||||
genvars = self.genvars_str,
|
||||
path_wo_field = self.path_wo_field
|
||||
@ -289,7 +306,7 @@ class Field(Component):
|
||||
# Add singlepulse property
|
||||
if self.obj.get_property('singlepulse'):
|
||||
access_rtl['singlepulse'] = [
|
||||
Field.templ_dict['singlepulse'].format(
|
||||
Field.templ_dict['singlepulse']['rtl'].format(
|
||||
path = self.path_underscored,
|
||||
genvars = self.genvars_str)
|
||||
]
|
||||
@ -335,40 +352,19 @@ class Field(Component):
|
||||
self.rtl_header = [*self.rtl_header, *order_list_rtl]
|
||||
|
||||
self.rtl_header.append(
|
||||
Field.templ_dict['end_field_ff'].format(
|
||||
Field.templ_dict['end_field_ff']['rtl'].format(
|
||||
path = self.path_underscored))
|
||||
|
||||
|
||||
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):
|
||||
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
|
||||
self.rtl_header.append(
|
||||
Field.templ_dict['out_port_assign'].format(
|
||||
Field.templ_dict['out_port_assign']['rtl'].format(
|
||||
genvars = self.genvars_str,
|
||||
path = self.path_underscored))
|
||||
|
||||
self.yaml_signals_to_list(Field.templ_dict['out_port_assign'])
|
||||
|
||||
def sanity_checks(self):
|
||||
# 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 "\
|
||||
"write property useless since hardware will "\
|
||||
"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.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
|
||||
# Fields should be in order in RTL,therefore, use list
|
||||
for field in obj.fields():
|
||||
@ -57,6 +35,15 @@ class Register(Component):
|
||||
|
||||
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
|
||||
for i in range(self.dimensions-1, -1, -1):
|
||||
self.rtl_footer.append(
|
||||
@ -72,7 +59,7 @@ class Register(Component):
|
||||
rw_wire_assign_field = 'rw_wire_assign_1_dim'
|
||||
|
||||
self.rtl_header.append(
|
||||
Register.templ_dict[rw_wire_assign_field].format(
|
||||
Register.templ_dict[rw_wire_assign_field]['rtl'].format(
|
||||
path = self.path,
|
||||
addr = self.obj.absolute_address,
|
||||
genvars = self.genvars_str,
|
||||
@ -80,6 +67,34 @@ class Register(Component):
|
||||
stride = self.obj.array_stride,
|
||||
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):
|
||||
# Save object
|
||||
self.obj = obj
|
||||
|
@ -11,6 +11,6 @@ module_declaration: |-
|
||||
{outputs}
|
||||
);
|
||||
input_port: |-
|
||||
input {packed_dim:15s}{name:25s} {unpacked_dim},
|
||||
input {signal_type:15s}{name:25s} {unpacked_dim},
|
||||
output_port: |-
|
||||
output {packed_dim:15s}{name:25s} {unpacked_dim},
|
||||
output {signal_type:15s}{name:25s} {unpacked_dim},
|
||||
|
@ -1,99 +1,192 @@
|
||||
---
|
||||
sense_list_rst: |-
|
||||
always_ff @(posedge {clk_name} or {rst_edge} {rst_name})
|
||||
sense_list_no_rst: |-
|
||||
always_ff @(posedge {clk_name})
|
||||
rst_field_assign: |-
|
||||
if ({rst_negl}{rst_name})
|
||||
begin
|
||||
{path}_q{genvars} <= {rst_value};
|
||||
end
|
||||
else
|
||||
sw_access_field: |-
|
||||
if ({path_wo_field}_sw_wr{genvars})
|
||||
begin
|
||||
sw_access_field_swwe: |-
|
||||
if ({path_wo_field}_sw_wr{genvars} && {swwe}) // swwe property
|
||||
begin
|
||||
sw_access_field_swwel: |-
|
||||
if ({path_wo_field}_sw_wr{genvars} && !{swwel}) // swwel property
|
||||
begin
|
||||
sw_access_byte: |-
|
||||
if (byte_enable[{i}])
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||
end
|
||||
sense_list_rst:
|
||||
rtl: |-
|
||||
always_ff @(posedge {clk_name} or {rst_edge} {rst_name})
|
||||
sense_list_no_rst:
|
||||
rtl: |-
|
||||
always_ff @(posedge {clk_name})
|
||||
rst_field_assign:
|
||||
rtl: |-
|
||||
if ({rst_negl}{rst_name})
|
||||
begin
|
||||
{path}_q{genvars} <= {rst_value};
|
||||
end
|
||||
else
|
||||
signals:
|
||||
- name: '{path}_q'
|
||||
signal_type: '{field_type}'
|
||||
sw_access_field:
|
||||
rtl: |-
|
||||
if ({path_wo_field}_sw_wr{genvars})
|
||||
begin
|
||||
sw_access_field_swwe:
|
||||
rtl: |-
|
||||
if ({path_wo_field}_sw_wr{genvars} && {swwe}) // swwe property
|
||||
begin
|
||||
sw_access_field_swwel:
|
||||
rtl: |-
|
||||
if ({path_wo_field}_sw_wr{genvars} && !{swwel}) // swwel property
|
||||
begin
|
||||
sw_access_byte:
|
||||
rtl: |-
|
||||
if (byte_enable[{i}])
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||
end
|
||||
|
||||
hw_access_we_wel:
|
||||
rtl: |-
|
||||
if ({negl}{path}_hw_wr{genvars})
|
||||
hw_access_no_we_wel:
|
||||
rtl: |-
|
||||
// we or wel property not set
|
||||
hw_access_field:
|
||||
rtl: |-
|
||||
begin
|
||||
{path}_q{genvars} <= {path}_in{genvars};
|
||||
end
|
||||
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
|
||||
OnWriteType.woset:
|
||||
rtl: |-
|
||||
if (byte_enable[{i}]) // woset property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] | sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||
end
|
||||
OnWriteType.woclr:
|
||||
rtl: |-
|
||||
if (byte_enable[{i}]) // woclr property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] & ~sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||
end
|
||||
OnWriteType.wot:
|
||||
rtl: |-
|
||||
if (byte_enable[{i}]) // wot property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] ^ sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||
end
|
||||
OnWriteType.wzs:
|
||||
rtl: |-
|
||||
if (byte_enable[{i}]) // wzs property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] & sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||
end
|
||||
OnWriteType.wzt:
|
||||
rtl: |-
|
||||
if (byte_enable[{i}]) // wzt property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] ~^ sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||
end
|
||||
OnWriteType.wclr:
|
||||
rtl: |-
|
||||
{path}_q{genvars} <= {{width{{1'b0}}}};
|
||||
OnWriteType.wset:
|
||||
rtl: |-
|
||||
{path}_q{genvars} <= {{width{{1'b1}}}};
|
||||
OnReadType.rclr:
|
||||
rtl: |-
|
||||
if ({path_wo_field}_sw_rd{genvars}) // rclr property
|
||||
begin
|
||||
{path}_q{genvars} <= {{width{{1'b0}}}};
|
||||
end
|
||||
OnReadType.rset:
|
||||
rtl: |-
|
||||
if ({path_wo_field}_sw_rd{genvars}) // rset property
|
||||
begin
|
||||
{path}_q{genvars} <= {{width{{1'b1}}}};
|
||||
end
|
||||
|
||||
field_comment:
|
||||
rtl: |-
|
||||
|
||||
//-----------------FIELD SUMMARY-----------------
|
||||
// name : {name} ({path_wo_field}[{msb}:{lsb}])
|
||||
// access : hw = {hw_access} {hw_precedence}
|
||||
// sw = {sw_access} {sw_precedence}
|
||||
// reset : {rst_active} / {rst_type}
|
||||
// flags : {misc_flags}
|
||||
//-----------------------------------------------
|
||||
combo_operation_comment:
|
||||
rtl: |-
|
||||
|
||||
// Combinational logic for {path}
|
||||
assign_anded_operation:
|
||||
rtl: |-
|
||||
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
|
||||
{path}{genvars}_q <= 0;
|
||||
end
|
||||
out_port_assign:
|
||||
rtl: |-
|
||||
// Connect register to hardware output port
|
||||
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})
|
||||
|
||||
hw_access_we_wel: |-
|
||||
if ({negl}{path}_hw_wr{genvars})
|
||||
hw_access_no_we_wel: |-
|
||||
// we or wel property not set
|
||||
hw_access_field: |-
|
||||
begin
|
||||
{path}_q{genvars} <= {path}_in{genvars};
|
||||
end
|
||||
end_field_ff: |-
|
||||
end // of {path}'s always_ff
|
||||
OnWriteType.woset: |-
|
||||
if (byte_enable[{i}]) // woset property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] | sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||
end
|
||||
OnWriteType.woclr: |-
|
||||
if (byte_enable[{i}]) // woclr property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] & ~sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||
end
|
||||
OnWriteType.wot: |-
|
||||
if (byte_enable[{i}]) // wot property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] ^ sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||
end
|
||||
OnWriteType.wzs: |-
|
||||
if (byte_enable[{i}]) // wzs property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] & sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||
end
|
||||
OnWriteType.wzt: |-
|
||||
if (byte_enable[{i}]) // wzt property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] ~^ sw_wr_bus[{msb_bus}-:{bus_w}];
|
||||
end
|
||||
OnWriteType.wclr: |-
|
||||
{path}_q{genvars} <= {{width{{1'b0}}}};
|
||||
OnWriteType.wset: |-
|
||||
{path}_q{genvars} <= {{width{{1'b1}}}};
|
||||
OnReadType.rclr: |-
|
||||
if ({path_wo_field}_sw_rd{genvars}) // rclr property
|
||||
begin
|
||||
{path}_q{genvars} <= {{width{{1'b0}}}};
|
||||
end
|
||||
OnReadType.rset: |-
|
||||
if ({path_wo_field}_sw_rd{genvars}) // rset property
|
||||
begin
|
||||
{path}_q{genvars} <= {{width{{1'b1}}}};
|
||||
end
|
||||
|
||||
field_comment: |-
|
||||
|
||||
//-----------------FIELD SUMMARY-----------------
|
||||
// name : {name} ({path_wo_field}[{msb}:{lsb}])
|
||||
// access : hw = {hw_access} {hw_precedence}
|
||||
// sw = {sw_access} {sw_precedence}
|
||||
// reset : {rst_active} / {rst_type}
|
||||
// flags : {misc_flags}
|
||||
//-----------------------------------------------
|
||||
combo_operation_comment: |-
|
||||
|
||||
// Combinational logic for {path}
|
||||
assign_combo_operation: |-
|
||||
assign {path}_{op_name}{genvars} = {op_verilog}{path}_q{genvars}
|
||||
singlepulse: |-
|
||||
begin
|
||||
{path}{genvars} <= 0;
|
||||
end
|
||||
out_port_assign: |-
|
||||
|
||||
// Connect register to hardware output port
|
||||
assign {path}_r{genvars} = {path}_q{genvars};
|
||||
|
||||
|
@ -1,14 +1,39 @@
|
||||
---
|
||||
rw_wire_declare: |
|
||||
logic {path}_sw_wr {depth};
|
||||
logic {path}_sw_rd {depth};
|
||||
rw_wire_assign_1_dim: |
|
||||
assign {path}_sw_wr{genvars} = addr == {addr} && r_vld;
|
||||
assign {path}_sw_rd{genvars} = addr == {addr} && w_vld;
|
||||
rw_wire_assign_multi_dim: |
|
||||
assign {path}_sw_wr{genvars} = addr == ({addr}+({genvars_sum})*{stride}) && r_vld;
|
||||
assign {path}_sw_rd{genvars} = addr == ({addr}+({genvars_sum})*{stride}) && w_vld;
|
||||
rw_wire_assign_1_dim:
|
||||
rtl: |
|
||||
// Assign register-activation signals
|
||||
assign {path}_reg_active{genvars} = addr == {addr};
|
||||
|
||||
assign {path}_sw_wr = {path}_reg_active && r_vld;
|
||||
assign {path}_sw_rd = {path}_reg_active && 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:
|
||||
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: |-
|
||||
|
||||
/*******************************************************************
|
||||
*******************************************************************
|
||||
* REGISTER : {name}
|
||||
@ -21,3 +46,5 @@ generate_for_start: |-
|
||||
begin
|
||||
generate_for_end: |-
|
||||
end // of for loop with iterator {dimension}
|
||||
signal_declaration: |-
|
||||
{type:10s}{name:20s} {unpacked_dim};
|
||||
|
Loading…
Reference in New Issue
Block a user