mirror of
https://github.com/Silicon1602/srdl2sv.git
synced 2024-11-13 02:53:37 +00:00
Add proper support for rdy & error indication in read multiplexer
The error indication is generated if: - A non-existent register gets read - An existent register gets read but not a single bit can be succesfully read or written. As soon as 1 bit succeeds don't return an error.
This commit is contained in:
parent
2f38d30d76
commit
c689190080
@ -194,21 +194,39 @@ class AddrMap(Component):
|
||||
|
||||
def __create_mux_string(self):
|
||||
# TODO: Add variable for bus width
|
||||
# Define default case
|
||||
list_of_cases = [AddrMap.templ_dict['default_mux_case']['rtl']]
|
||||
|
||||
# Add an entry for each version of a register
|
||||
for child in self.children.values():
|
||||
for mux_entry in child.create_mux_string():
|
||||
# Data structure of mux_entry:
|
||||
# mux_entry[0] --> names of data/rdy/err wire and start addr
|
||||
# [0] --> data_mux (str)
|
||||
# [1] --> rdy_mux (str)
|
||||
# [2] --> err_mux (str)
|
||||
# [3] --> start_addr (int)
|
||||
# mux_entry[1] --> offsets from start
|
||||
# [0] --> Offset from start_addr of current entry (int)
|
||||
# [1] --> String of array index that represents offset (str)
|
||||
|
||||
r2b_data = ''.join([mux_entry[0][0], mux_entry[1][1]])
|
||||
r2b_rdy = ''.join([mux_entry[0][1], mux_entry[1][1]])
|
||||
r2b_err = ''.join([mux_entry[0][2], mux_entry[1][1]])
|
||||
index = mux_entry[0][3] + mux_entry[1][0]
|
||||
|
||||
list_of_cases.append(
|
||||
AddrMap.templ_dict['list_of_mux_cases']['rtl'].format(
|
||||
index = index,
|
||||
r2b_data = r2b_data,
|
||||
r2b_rdy = r2b_rdy,
|
||||
r2b_err = r2b_err)
|
||||
)
|
||||
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
AddrMap.templ_dict['read_mux'],
|
||||
{'list_of_cases':
|
||||
'\n'.join([
|
||||
AddrMap.templ_dict['default_mux_case']['rtl'],
|
||||
*[AddrMap.templ_dict['list_of_mux_cases']['rtl']
|
||||
.format(x[0][1]+x[1][0],
|
||||
''.join(
|
||||
[x[0][0],
|
||||
x[1][1]])) for y in self.children.values() \
|
||||
for x in y.create_mux_string()
|
||||
]
|
||||
])
|
||||
}
|
||||
{'list_of_cases': '\n'.join(list_of_cases)}
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -68,6 +68,9 @@ class Field(Component):
|
||||
access_rtl['sw_write'] = ([], False)
|
||||
|
||||
if obj.get_property('sw') in (AccessType.rw, AccessType.w):
|
||||
# Append to list of registers that can write
|
||||
self.writable_by.add(path_wo_field)
|
||||
|
||||
swwe = obj.get_property('swwe')
|
||||
swwel = obj.get_property('swwel')
|
||||
|
||||
@ -1005,8 +1008,9 @@ class Field(Component):
|
||||
self.msb = obj.inst.msb
|
||||
self.lsb = obj.inst.lsb
|
||||
|
||||
# Set that tells which hierarchies can read this field
|
||||
# Set that tells which hierarchies can read/write this field
|
||||
self.readable_by = set()
|
||||
self.writable_by = set()
|
||||
|
||||
# Determine resets. This includes checking for async/sync resets,
|
||||
# the reset value, and whether the field actually has a reset
|
||||
|
@ -73,7 +73,7 @@ class Register(Component):
|
||||
self.rtl_footer.append("endgenerate\n")
|
||||
|
||||
# Add assignment of read-wires
|
||||
self.__add_sw_read_assignments()
|
||||
self.__add_sw_mux_assignments()
|
||||
|
||||
# Add wire instantiation
|
||||
if not self.generate_active:
|
||||
@ -90,22 +90,36 @@ class Register(Component):
|
||||
*self.rtl_header
|
||||
]
|
||||
|
||||
def __add_sw_read_assignments(self):
|
||||
def __add_sw_mux_assignments(self):
|
||||
accesswidth = self.obj.get_property('accesswidth') - 1
|
||||
self.rtl_footer.append("")
|
||||
|
||||
for x in self.name_addr_mappings:
|
||||
for na_map in self.name_addr_mappings:
|
||||
current_bit = 0
|
||||
|
||||
# Start tracking errors
|
||||
|
||||
# Handle fields
|
||||
list_of_fields = []
|
||||
for y in self.children.values():
|
||||
if x[0] in y.readable_by:
|
||||
empty_bits = y.lsb - current_bit
|
||||
current_bit = y.msb + 1
|
||||
bytes_read = set()
|
||||
bytes_written = set()
|
||||
|
||||
for field in self.children.values():
|
||||
if na_map[0] in field.readable_by:
|
||||
empty_bits = field.lsb - current_bit
|
||||
current_bit = field.msb + 1
|
||||
|
||||
if empty_bits > 0:
|
||||
list_of_fields.append("{}'b0".format(empty_bits))
|
||||
|
||||
list_of_fields.append("{}_q".format(y.path_underscored))
|
||||
list_of_fields.append("{}_q".format(field.path_underscored))
|
||||
|
||||
# Add to appropriate bytes
|
||||
[bytes_read.add(x) for x in range(field.lsbyte, field.msbyte+1)]
|
||||
|
||||
if na_map[0] in field.writable_by:
|
||||
# Add to appropriate bytes
|
||||
[bytes_written.add(x) for x in range(field.lsbyte, field.msbyte+1)]
|
||||
|
||||
empty_bits = accesswidth - current_bit + 1
|
||||
|
||||
@ -113,28 +127,55 @@ class Register(Component):
|
||||
list_of_fields.append("{}'b0".format(empty_bits))
|
||||
|
||||
# Create list of mux-inputs to later be picked up by carrying addrmap
|
||||
self.sw_read_assignment_var_name.append(
|
||||
self.sw_mux_assignment_var_name.append(
|
||||
(
|
||||
self.process_yaml(
|
||||
Register.templ_dict['sw_read_assignment_var_name'],
|
||||
{'path': x[0],
|
||||
Register.templ_dict['sw_data_assignment_var_name'],
|
||||
{'path': na_map[0],
|
||||
'accesswidth': accesswidth}
|
||||
),
|
||||
x[1], # Start addr
|
||||
self.process_yaml(
|
||||
Register.templ_dict['sw_rdy_assignment_var_name'],
|
||||
{'path': na_map[0]}
|
||||
),
|
||||
self.process_yaml(
|
||||
Register.templ_dict['sw_err_assignment_var_name'],
|
||||
{'path': na_map[0]}
|
||||
),
|
||||
na_map[1], # Start addr
|
||||
)
|
||||
)
|
||||
|
||||
# Return an error if *no* read or *no* write can be succesful.
|
||||
# If some bits cannot be read/write but others are succesful, don't return
|
||||
# an error.
|
||||
bytes_read_format = ["b2r.byte_en[{}]".format(x) for x in list(map(str, bytes_read))]
|
||||
bytes_written_format = ["b2r.byte_en[{}]".format(x) for x in list(map(str, bytes_written))]
|
||||
|
||||
sw_err_condition = self.process_yaml(
|
||||
Register.templ_dict['sw_err_condition'],
|
||||
{'rd_byte_list_ored':
|
||||
' || '.join(bytes_read_format) if bytes_read else "1'b0",
|
||||
'wr_byte_list_ored':
|
||||
' || '.join(bytes_written_format) if bytes_written else "1'b0"}
|
||||
)
|
||||
|
||||
# Assign all values
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
Register.templ_dict['sw_read_assignment'],
|
||||
{'sw_read_assignment_var_name': self.sw_read_assignment_var_name[-1][0],
|
||||
Register.templ_dict['sw_data_assignment'],
|
||||
{'sw_data_assignment_var_name': self.sw_mux_assignment_var_name[-1][0],
|
||||
'sw_rdy_assignment_var_name': self.sw_mux_assignment_var_name[-1][1],
|
||||
'sw_err_assignment_var_name': self.sw_mux_assignment_var_name[-1][2],
|
||||
'genvars': self.genvars_str,
|
||||
'rdy_condition': "1'b1",
|
||||
'err_condition': sw_err_condition,
|
||||
'list_of_fields': ', '.join(reversed(list_of_fields))}
|
||||
)
|
||||
)
|
||||
|
||||
def create_mux_string(self):
|
||||
for mux_tuple in self.sw_read_assignment_var_name:
|
||||
for mux_tuple in self.sw_mux_assignment_var_name:
|
||||
# Loop through lowest dimension and add stride of higher
|
||||
# dimension once everything is processed
|
||||
if self.total_array_dimensions:
|
||||
@ -270,7 +311,7 @@ class Register(Component):
|
||||
self.generate_active = glbl_settings['generate_active']
|
||||
|
||||
# Empty array for mux-input signals
|
||||
self.sw_read_assignment_var_name = []
|
||||
self.sw_mux_assignment_var_name = []
|
||||
|
||||
# Determine dimensions of register
|
||||
if obj.is_array:
|
||||
|
@ -119,7 +119,18 @@ read_mux:
|
||||
end
|
||||
default_mux_case:
|
||||
rtl: |-
|
||||
default: r2b.data = 0;
|
||||
default:
|
||||
begin
|
||||
// In case the address is not found, return an error
|
||||
r2b.data = 0;
|
||||
r2b.err = 1;
|
||||
r2b.rdy = b2r.r_vld || b2r.w_vld;
|
||||
end
|
||||
list_of_mux_cases:
|
||||
rtl: |-
|
||||
32'd{}: r2b.data = {};
|
||||
32'd{index}:
|
||||
begin
|
||||
r2b.data = {r2b_data};
|
||||
r2b.err = {r2b_err};
|
||||
r2b.rdy = {r2b_rdy};
|
||||
end
|
||||
|
@ -55,15 +55,40 @@ generate_for_end: |-
|
||||
end // of for loop with iterator {dimension}
|
||||
signal_declaration: |-
|
||||
{type:{signal_width}} {name:{name_width}}{unpacked_dim};
|
||||
sw_read_assignment_var_name:
|
||||
sw_data_assignment_var_name:
|
||||
rtl: |-
|
||||
{path}_rd_mux_in
|
||||
{path}_data_mux_in
|
||||
signals:
|
||||
- name: '{path}_rd_mux_in'
|
||||
- name: '{path}_data_mux_in'
|
||||
signal_type: 'logic [{accesswidth}:0]'
|
||||
sw_read_assignment:
|
||||
sw_err_assignment_var_name:
|
||||
rtl: |-
|
||||
{path}_err_mux_in
|
||||
signals:
|
||||
- name: '{path}_err_mux_in'
|
||||
signal_type: 'logic'
|
||||
sw_rdy_assignment_var_name:
|
||||
rtl: |-
|
||||
{path}_rdy_mux_in
|
||||
signals:
|
||||
- name: '{path}_rdy_mux_in'
|
||||
signal_type: 'logic'
|
||||
sw_err_condition:
|
||||
rtl: |-
|
||||
!((b2r.r_vld && ({rd_byte_list_ored})) || (b2r.w_vld && ({wr_byte_list_ored})))
|
||||
sw_data_assignment:
|
||||
rtl: |-
|
||||
/**************************************
|
||||
* Assign all fields to signal to Mux *
|
||||
**************************************/
|
||||
assign {sw_read_assignment_var_name}{genvars} = {{{list_of_fields}{genvars}}};
|
||||
// Assign all fields. Fields that are not readable are tied to 0.
|
||||
assign {sw_data_assignment_var_name}{genvars} = {{{list_of_fields}{genvars}}};
|
||||
|
||||
// Internal registers are ready immediately
|
||||
assign {sw_rdy_assignment_var_name}{genvars} = {rdy_condition};
|
||||
|
||||
// Return an error if *no* read and *no* write wa be succesful.
|
||||
// If some bits cannot be read/write but others are succesful, don't return
|
||||
// an error. Hence, as long as one action can be succesful, no error will be
|
||||
// returned.
|
||||
assign {sw_err_assignment_var_name}{genvars} = {err_condition};
|
||||
|
17
srdl2sv/components/widgets/widget_package.sv
Normal file
17
srdl2sv/components/widgets/widget_package.sv
Normal file
@ -0,0 +1,17 @@
|
||||
package srdl2sv_widget_pkg;
|
||||
|
||||
typedef struct {
|
||||
logic [31:0] addr;
|
||||
logic [31:0] data;
|
||||
logic w_vld;
|
||||
logic r_vld;
|
||||
logic [ 3:0] byte_en;
|
||||
} b2r_t;
|
||||
|
||||
typedef struct {
|
||||
logic [31:0] data;
|
||||
logic rdy;
|
||||
logic err;
|
||||
} r2b_t;
|
||||
|
||||
endpackage
|
Loading…
Reference in New Issue
Block a user