fix: handle error response for overlapped registers with read-only and write-only attributes (#178)
This commit is contained in:
committed by
Alex Mykyta
parent
e1d7b3aa38
commit
efbddccc54
@@ -141,23 +141,26 @@ class DecodeLogicGenerator(RDLForLoopGenerator):
|
||||
readable = node.is_sw_readable
|
||||
writable = node.is_sw_writable
|
||||
if readable and writable:
|
||||
rhs_invalid_rw = "'0"
|
||||
pass
|
||||
elif readable and not writable:
|
||||
rhs = f"{addr_decoding_str} & !cpuif_req_is_wr"
|
||||
rhs_invalid_rw = f"{addr_decoding_str} & cpuif_req_is_wr"
|
||||
elif not readable and writable:
|
||||
rhs = f"{addr_decoding_str} & cpuif_req_is_wr"
|
||||
rhs_invalid_rw = f"{addr_decoding_str} & !cpuif_req_is_wr"
|
||||
else:
|
||||
raise RuntimeError
|
||||
# Add decoding flags
|
||||
self.add_content(f"{self.addr_decode.get_external_block_access_strobe(node)} = {rhs};")
|
||||
self.add_content(f"is_external |= {rhs};")
|
||||
if self.addr_decode.exp.ds.err_if_bad_addr:
|
||||
# Also assign is_valid_adddr when err_if_bad_rw is set so that it can be used to catch
|
||||
# invalid RW accesses on existing registers only.
|
||||
if self.addr_decode.exp.ds.err_if_bad_addr or self.addr_decode.exp.ds.err_if_bad_rw:
|
||||
self.add_content(f"is_valid_addr |= {rhs_valid_addr};")
|
||||
if isinstance(node, MemNode):
|
||||
if self.addr_decode.exp.ds.err_if_bad_rw:
|
||||
self.add_content(f"is_invalid_rw |= {rhs_invalid_rw};")
|
||||
self.add_content(f"is_valid_rw |= {rhs};")
|
||||
else:
|
||||
# For external register blocks, all accesses are valid RW
|
||||
self.add_content(f"is_valid_rw |= {rhs_valid_addr};")
|
||||
|
||||
|
||||
def enter_AddressableComponent(self, node: 'AddressableNode') -> Optional[WalkerAction]:
|
||||
@@ -206,13 +209,10 @@ class DecodeLogicGenerator(RDLForLoopGenerator):
|
||||
writable = node.has_sw_writable
|
||||
if readable and writable:
|
||||
rhs = addr_decoding_str
|
||||
rhs_invalid_rw = "'0"
|
||||
elif readable and not writable:
|
||||
rhs = f"{addr_decoding_str} & !cpuif_req_is_wr"
|
||||
rhs_invalid_rw = f"{addr_decoding_str} & cpuif_req_is_wr"
|
||||
elif not readable and writable:
|
||||
rhs = f"{addr_decoding_str} & cpuif_req_is_wr"
|
||||
rhs_invalid_rw = f"{addr_decoding_str} & !cpuif_req_is_wr"
|
||||
else:
|
||||
raise RuntimeError
|
||||
# Add decoding flags
|
||||
@@ -222,10 +222,12 @@ class DecodeLogicGenerator(RDLForLoopGenerator):
|
||||
self.add_content(f"{self.addr_decode.get_access_strobe(node)}[{subword_index}] = {rhs};")
|
||||
if node.external:
|
||||
self.add_content(f"is_external |= {rhs};")
|
||||
if self.addr_decode.exp.ds.err_if_bad_addr:
|
||||
# Also assign is_valid_adddr when err_if_bad_rw is set so that it can be used to catch
|
||||
# invalid RW accesses on existing registers only.
|
||||
if self.addr_decode.exp.ds.err_if_bad_addr or self.addr_decode.exp.ds.err_if_bad_rw:
|
||||
self.add_content(f"is_valid_addr |= {rhs_valid_addr};")
|
||||
if self.addr_decode.exp.ds.err_if_bad_rw:
|
||||
self.add_content(f"is_invalid_rw |= {rhs_invalid_rw};")
|
||||
self.add_content(f"is_valid_rw |= {rhs};")
|
||||
|
||||
def enter_Reg(self, node: RegNode) -> None:
|
||||
regwidth = node.get_property('regwidth')
|
||||
|
||||
@@ -121,19 +121,31 @@ module {{ds.module_name}}
|
||||
|
||||
always_comb begin
|
||||
automatic logic is_valid_addr;
|
||||
automatic logic is_invalid_rw;
|
||||
automatic logic is_valid_rw;
|
||||
{%- if ds.has_external_addressable %}
|
||||
automatic logic is_external;
|
||||
is_external = '0;
|
||||
{%- endif %}
|
||||
{%- if ds.err_if_bad_addr %}
|
||||
{%- if ds.err_if_bad_addr or ds.err_if_bad_rw %}
|
||||
is_valid_addr = '0;
|
||||
{%- else %}
|
||||
is_valid_addr = '1; // No error checking on valid address access
|
||||
is_valid_addr = '1; // No valid address check
|
||||
{%- endif %}
|
||||
{%- if ds.err_if_bad_rw %}
|
||||
is_valid_rw = '0;
|
||||
{%- else %}
|
||||
is_valid_rw = '1; // No valid RW check
|
||||
{%- endif %}
|
||||
is_invalid_rw = '0;
|
||||
{{address_decode.get_implementation()|indent(8)}}
|
||||
decoded_err = (~is_valid_addr | is_invalid_rw) & decoded_req;
|
||||
{%- if ds.err_if_bad_addr and ds.err_if_bad_rw %}
|
||||
decoded_err = (~is_valid_addr | (is_valid_addr & ~is_valid_rw)) & decoded_req;
|
||||
{%- elif ds.err_if_bad_addr %}
|
||||
decoded_err = ~is_valid_addr & decoded_req;
|
||||
{%- elif ds.err_if_bad_rw %}
|
||||
decoded_err = (is_valid_addr & ~is_valid_rw) & decoded_req;
|
||||
{%- else %}
|
||||
decoded_err = '0;
|
||||
{%- endif %}
|
||||
{%- if ds.has_external_addressable %}
|
||||
decoded_strb_is_external = is_external;
|
||||
external_req = is_external;
|
||||
|
||||
Reference in New Issue
Block a user