mirror of
https://github.com/Silicon1602/srdl2sv.git
synced 2024-11-13 02:53:37 +00:00
Change way the order of RTL is determined
By using a dictionary, it will be easier to mix & match the RTL order dependend on the properties of the field. This commit also adds anded/ored/xored properties.
This commit is contained in:
parent
861a020aff
commit
f1d9ba2656
@ -1,10 +1,10 @@
|
||||
import yaml
|
||||
import math
|
||||
import yaml
|
||||
|
||||
from systemrdl import RDLCompiler, RDLCompileError, RDLWalker, RDLListener, node
|
||||
from systemrdl.node import FieldNode
|
||||
from systemrdl.rdltypes import PrecedenceType, AccessType
|
||||
|
||||
from itertools import chain
|
||||
|
||||
TAB = " "
|
||||
|
||||
@ -18,6 +18,10 @@ class Field:
|
||||
self.rtl = []
|
||||
self.bytes = math.ceil(obj.width / 8)
|
||||
|
||||
# Make a list of I/O that shall be added to the addrmap
|
||||
self.input_ports = []
|
||||
self.output_ports = []
|
||||
|
||||
##################################################################################
|
||||
# LIMITATION:
|
||||
# v1.x of the systemrdl-compiler does not support non-homogeneous arrays.
|
||||
@ -43,7 +47,6 @@ class Field:
|
||||
rst_negl = ""
|
||||
rst_active = "active_high"
|
||||
|
||||
print(obj.get_property('reset'))
|
||||
# Value of reset?
|
||||
rst_value = '\'x' if obj.get_property("reset") == None else obj.get_property('reset')
|
||||
except:
|
||||
@ -104,12 +107,23 @@ class Field:
|
||||
|
||||
indent_lvl += 1
|
||||
|
||||
# Define hardware access (if applicable)
|
||||
hw_access_rtl = []
|
||||
# Not all access types are required and the order might differ
|
||||
# depending on what types are defined and what precedence is
|
||||
# set. Therefore, first add all RTL into a dictionary and
|
||||
# later place it in the right order.
|
||||
#
|
||||
# The following RTL blocks are defined:
|
||||
# - hw_write --> write access for the hardware interface
|
||||
# - sw_write --> write access for the software interface
|
||||
#
|
||||
access_rtl = dict([])
|
||||
|
||||
if hw_access == AccessType.rw or hw_access == AccessType.w:
|
||||
# Define hardware access (if applicable)
|
||||
access_rtl['hw_write'] = []
|
||||
|
||||
if hw_access in (AccessType.rw, AccessType.w):
|
||||
if obj.get_property('we') or obj.get_property('wel'):
|
||||
hw_access_rtl.append(
|
||||
access_rtl['hw_write'].append(
|
||||
Field.templ_dict['hw_access_we_wel'].format(
|
||||
negl = '!' if obj.get_property('wel') else '',
|
||||
reg_name = obj.parent.inst_name,
|
||||
@ -117,7 +131,7 @@ class Field:
|
||||
genvars = genvars_str,
|
||||
indent = self.indent(indent_lvl)))
|
||||
|
||||
hw_access_rtl.append(
|
||||
access_rtl['hw_write'].append(
|
||||
Field.templ_dict['hw_access_field'].format(
|
||||
reg_name = obj.parent.inst_name,
|
||||
field_name = obj.inst_name,
|
||||
@ -125,45 +139,52 @@ class Field:
|
||||
indent = self.indent(indent_lvl)))
|
||||
|
||||
# Define software access (if applicable)
|
||||
sw_access_rtl = []
|
||||
access_rtl['sw_write'] = []
|
||||
|
||||
# TODO: if sw_access_enabled
|
||||
sw_access_rtl.append(
|
||||
Field.templ_dict['sw_access_field'].format(
|
||||
reg_name = obj.parent.inst_name,
|
||||
field_name = obj.inst_name,
|
||||
genvars = genvars_str,
|
||||
indent = self.indent(indent_lvl)))
|
||||
|
||||
indent_lvl += 1
|
||||
|
||||
# If field spans multiple bytes, every byte shall have a seperate enable!
|
||||
for i in range(self.bytes):
|
||||
sw_access_rtl.append(
|
||||
Field.templ_dict['sw_access_byte'].format(
|
||||
if sw_access in (AccessType.rw, AccessType.w):
|
||||
access_rtl['sw_write'].append(
|
||||
Field.templ_dict['sw_access_field'].format(
|
||||
reg_name = obj.parent.inst_name,
|
||||
field_name = obj.inst_name,
|
||||
genvars = genvars_str,
|
||||
i = i,
|
||||
indent = self.indent(indent_lvl)))
|
||||
|
||||
sw_access_rtl.append("")
|
||||
indent_lvl += 1
|
||||
|
||||
indent_lvl -= 1
|
||||
# If field spans multiple bytes, every byte shall have a seperate enable!
|
||||
for i in range(self.bytes):
|
||||
access_rtl['sw_write'].append(
|
||||
Field.templ_dict['sw_access_byte'].format(
|
||||
reg_name = obj.parent.inst_name,
|
||||
field_name = obj.inst_name,
|
||||
genvars = genvars_str,
|
||||
i = i,
|
||||
indent = self.indent(indent_lvl)))
|
||||
|
||||
sw_access_rtl.append("{}end".format(self.indent(indent_lvl)))
|
||||
indent_lvl -= 1
|
||||
|
||||
access_rtl['sw_write'].append("{}end".format(self.indent(indent_lvl)))
|
||||
|
||||
# Define else with correct indentation and add to dictionary
|
||||
access_rtl['else'] = ["{}else".format(self.indent(indent_lvl))]
|
||||
|
||||
# Add empty string
|
||||
access_rtl[''] = ['']
|
||||
|
||||
# Check if hardware has precedence (default `precedence = sw`)
|
||||
if precedence == 'PrecedenceType.sw':
|
||||
self.rtl = [*self.rtl,
|
||||
*sw_access_rtl,
|
||||
'{}else'.format(self.indent(indent_lvl)),
|
||||
*hw_access_rtl]
|
||||
rtl_order = ['sw_write',
|
||||
'else' if len(access_rtl['hw_write']) > 0 else '',
|
||||
'hw_write']
|
||||
else:
|
||||
self.rtl = [*self.rtl,
|
||||
*sw_access_rtl,
|
||||
'{}else'.format(self.indent(indent_lvl)),
|
||||
*hw_access_rtl]
|
||||
rtl_order = ['hw_write',
|
||||
'else' if len(access_rtl['sw_write']) > 0 else '',
|
||||
'sw_write']
|
||||
|
||||
# Add dictionary to main RTL list in correct order
|
||||
self.rtl = [
|
||||
*self.rtl,
|
||||
*chain.from_iterable([access_rtl[i] for i in rtl_order])]
|
||||
|
||||
indent_lvl -= 1
|
||||
|
||||
@ -173,6 +194,36 @@ class Field:
|
||||
field_name = obj.inst_name,
|
||||
indent = self.indent(indent_lvl)))
|
||||
|
||||
#####################
|
||||
# Add combo logic
|
||||
#####################
|
||||
operations = []
|
||||
if obj.get_property('anded'):
|
||||
operations.append(['anded', '&'])
|
||||
if obj.get_property('ored'):
|
||||
operations.append(['ored', '|'])
|
||||
if obj.get_property('xored'):
|
||||
operations.append(['xored', '^'])
|
||||
|
||||
if len(operations) > 0:
|
||||
self.rtl.append(
|
||||
Field.templ_dict['combo_operation_comment'].format(
|
||||
reg_name = obj.parent.inst_name,
|
||||
field_name = obj.inst_name,
|
||||
indent = self.indent(indent_lvl)))
|
||||
|
||||
self.rtl = [
|
||||
*self.rtl,
|
||||
*[Field.templ_dict['assign_combo_operation'].format(
|
||||
field_name = obj.inst_name,
|
||||
reg_name = obj.parent.inst_name,
|
||||
genvars = genvars_str,
|
||||
op_name = i[0],
|
||||
op_verilog = i[1],
|
||||
indent = self.indent(indent_lvl)) for i in operations]]
|
||||
|
||||
# TODO: Set sanity checks. For example, having no we but precedence = hw
|
||||
# will cause weird behavior.
|
||||
|
||||
|
||||
@staticmethod
|
||||
|
@ -13,6 +13,7 @@ sw_access_field: |-
|
||||
sw_access_byte: |-
|
||||
{indent}if (byte_enable[{i}])
|
||||
{indent} {reg_name}_{field_name}_q{genvars}[8*({i}+1)-1 -: 8] <= sw_wr_bus[8*({i}+1)-1 -: 8];
|
||||
|
||||
hw_access_we_wel: |-
|
||||
{indent}if ({negl}{reg_name}_{field_name}_hw_wr{genvars})
|
||||
hw_access_field: |-
|
||||
@ -29,3 +30,9 @@ field_comment: |-
|
||||
{indent}// sw = {sw_access} {sw_precedence}
|
||||
{indent}// reset : {rst_active} / {rst_type}
|
||||
{indent}//-----------------------------------------------
|
||||
combo_operation_comment: |-
|
||||
|
||||
{indent}// Combinational logic for {reg_name}_{field_name}
|
||||
assign_combo_operation: |-
|
||||
{indent}assign {reg_name}_{field_name}_{op_name}{genvars} = {op_verilog}{reg_name}_{field_name}_q{genvars}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user