mirror of
https://github.com/Silicon1602/srdl2sv.git
synced 2024-11-14 11:03:36 +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 math
|
||||||
|
import yaml
|
||||||
|
|
||||||
from systemrdl import RDLCompiler, RDLCompileError, RDLWalker, RDLListener, node
|
from systemrdl import RDLCompiler, RDLCompileError, RDLWalker, RDLListener, node
|
||||||
from systemrdl.node import FieldNode
|
from systemrdl.node import FieldNode
|
||||||
from systemrdl.rdltypes import PrecedenceType, AccessType
|
from systemrdl.rdltypes import PrecedenceType, AccessType
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
TAB = " "
|
TAB = " "
|
||||||
|
|
||||||
@ -18,6 +18,10 @@ class Field:
|
|||||||
self.rtl = []
|
self.rtl = []
|
||||||
self.bytes = math.ceil(obj.width / 8)
|
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:
|
# LIMITATION:
|
||||||
# v1.x of the systemrdl-compiler does not support non-homogeneous arrays.
|
# v1.x of the systemrdl-compiler does not support non-homogeneous arrays.
|
||||||
@ -43,7 +47,6 @@ class Field:
|
|||||||
rst_negl = ""
|
rst_negl = ""
|
||||||
rst_active = "active_high"
|
rst_active = "active_high"
|
||||||
|
|
||||||
print(obj.get_property('reset'))
|
|
||||||
# Value of reset?
|
# Value of reset?
|
||||||
rst_value = '\'x' if obj.get_property("reset") == None else obj.get_property('reset')
|
rst_value = '\'x' if obj.get_property("reset") == None else obj.get_property('reset')
|
||||||
except:
|
except:
|
||||||
@ -104,12 +107,23 @@ class Field:
|
|||||||
|
|
||||||
indent_lvl += 1
|
indent_lvl += 1
|
||||||
|
|
||||||
# Define hardware access (if applicable)
|
# Not all access types are required and the order might differ
|
||||||
hw_access_rtl = []
|
# 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'):
|
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(
|
Field.templ_dict['hw_access_we_wel'].format(
|
||||||
negl = '!' if obj.get_property('wel') else '',
|
negl = '!' if obj.get_property('wel') else '',
|
||||||
reg_name = obj.parent.inst_name,
|
reg_name = obj.parent.inst_name,
|
||||||
@ -117,7 +131,7 @@ class Field:
|
|||||||
genvars = genvars_str,
|
genvars = genvars_str,
|
||||||
indent = self.indent(indent_lvl)))
|
indent = self.indent(indent_lvl)))
|
||||||
|
|
||||||
hw_access_rtl.append(
|
access_rtl['hw_write'].append(
|
||||||
Field.templ_dict['hw_access_field'].format(
|
Field.templ_dict['hw_access_field'].format(
|
||||||
reg_name = obj.parent.inst_name,
|
reg_name = obj.parent.inst_name,
|
||||||
field_name = obj.inst_name,
|
field_name = obj.inst_name,
|
||||||
@ -125,45 +139,52 @@ class Field:
|
|||||||
indent = self.indent(indent_lvl)))
|
indent = self.indent(indent_lvl)))
|
||||||
|
|
||||||
# Define software access (if applicable)
|
# Define software access (if applicable)
|
||||||
sw_access_rtl = []
|
access_rtl['sw_write'] = []
|
||||||
|
|
||||||
# TODO: if sw_access_enabled
|
if sw_access in (AccessType.rw, AccessType.w):
|
||||||
sw_access_rtl.append(
|
access_rtl['sw_write'].append(
|
||||||
Field.templ_dict['sw_access_field'].format(
|
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(
|
|
||||||
reg_name = obj.parent.inst_name,
|
reg_name = obj.parent.inst_name,
|
||||||
field_name = obj.inst_name,
|
field_name = obj.inst_name,
|
||||||
genvars = genvars_str,
|
genvars = genvars_str,
|
||||||
i = i,
|
|
||||||
indent = self.indent(indent_lvl)))
|
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`)
|
# Check if hardware has precedence (default `precedence = sw`)
|
||||||
if precedence == 'PrecedenceType.sw':
|
if precedence == 'PrecedenceType.sw':
|
||||||
self.rtl = [*self.rtl,
|
rtl_order = ['sw_write',
|
||||||
*sw_access_rtl,
|
'else' if len(access_rtl['hw_write']) > 0 else '',
|
||||||
'{}else'.format(self.indent(indent_lvl)),
|
'hw_write']
|
||||||
*hw_access_rtl]
|
|
||||||
else:
|
else:
|
||||||
self.rtl = [*self.rtl,
|
rtl_order = ['hw_write',
|
||||||
*sw_access_rtl,
|
'else' if len(access_rtl['sw_write']) > 0 else '',
|
||||||
'{}else'.format(self.indent(indent_lvl)),
|
'sw_write']
|
||||||
*hw_access_rtl]
|
|
||||||
|
# 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
|
indent_lvl -= 1
|
||||||
|
|
||||||
@ -173,6 +194,36 @@ class Field:
|
|||||||
field_name = obj.inst_name,
|
field_name = obj.inst_name,
|
||||||
indent = self.indent(indent_lvl)))
|
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
|
@staticmethod
|
||||||
|
@ -13,6 +13,7 @@ sw_access_field: |-
|
|||||||
sw_access_byte: |-
|
sw_access_byte: |-
|
||||||
{indent}if (byte_enable[{i}])
|
{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];
|
{indent} {reg_name}_{field_name}_q{genvars}[8*({i}+1)-1 -: 8] <= sw_wr_bus[8*({i}+1)-1 -: 8];
|
||||||
|
|
||||||
hw_access_we_wel: |-
|
hw_access_we_wel: |-
|
||||||
{indent}if ({negl}{reg_name}_{field_name}_hw_wr{genvars})
|
{indent}if ({negl}{reg_name}_{field_name}_hw_wr{genvars})
|
||||||
hw_access_field: |-
|
hw_access_field: |-
|
||||||
@ -29,3 +30,9 @@ field_comment: |-
|
|||||||
{indent}// sw = {sw_access} {sw_precedence}
|
{indent}// sw = {sw_access} {sw_precedence}
|
||||||
{indent}// reset : {rst_active} / {rst_type}
|
{indent}// reset : {rst_active} / {rst_type}
|
||||||
{indent}//-----------------------------------------------
|
{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