Use sized integer literals in comparisons. #49
This commit is contained in:
@@ -157,7 +157,7 @@ class DecodeLogicGenerator(RDLForLoopGenerator):
|
|||||||
# Is an external block
|
# Is an external block
|
||||||
addr_str = self._get_address_str(node)
|
addr_str = self._get_address_str(node)
|
||||||
strb = self.addr_decode.get_external_block_access_strobe(node)
|
strb = self.addr_decode.get_external_block_access_strobe(node)
|
||||||
rhs = f"cpuif_req_masked & (cpuif_addr >= {addr_str}) & (cpuif_addr <= {addr_str} + {get_sv_int(node.size - 1)})"
|
rhs = f"cpuif_req_masked & (cpuif_addr >= {addr_str}) & (cpuif_addr <= {addr_str} + {get_sv_int(node.size - 1, self.addr_decode.exp.ds.addr_width)})"
|
||||||
self.add_content(f"{strb} = {rhs};")
|
self.add_content(f"{strb} = {rhs};")
|
||||||
self.add_content(f"is_external |= {rhs};")
|
self.add_content(f"is_external |= {rhs};")
|
||||||
return WalkerAction.SkipDescendants
|
return WalkerAction.SkipDescendants
|
||||||
@@ -166,9 +166,12 @@ class DecodeLogicGenerator(RDLForLoopGenerator):
|
|||||||
|
|
||||||
|
|
||||||
def _get_address_str(self, node: 'AddressableNode', subword_offset: int=0) -> str:
|
def _get_address_str(self, node: 'AddressableNode', subword_offset: int=0) -> str:
|
||||||
a = get_sv_int(node.raw_absolute_address - self.addr_decode.top_node.raw_absolute_address + subword_offset)
|
a = get_sv_int(
|
||||||
|
node.raw_absolute_address - self.addr_decode.top_node.raw_absolute_address + subword_offset,
|
||||||
|
self.addr_decode.exp.ds.addr_width
|
||||||
|
)
|
||||||
for i, stride in enumerate(self._array_stride_stack):
|
for i, stride in enumerate(self._array_stride_stack):
|
||||||
a += f" + i{i}*{get_sv_int(stride)}"
|
a += f" + i{i}*{get_sv_int(stride, self.addr_decode.exp.ds.addr_width)}"
|
||||||
return a
|
return a
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ always_comb begin
|
|||||||
axil_ar_accept = '0;
|
axil_ar_accept = '0;
|
||||||
axil_aw_accept = '0;
|
axil_aw_accept = '0;
|
||||||
|
|
||||||
if(axil_n_in_flight < 'd{{cpuif.max_outstanding}}) begin
|
if(axil_n_in_flight < {{clog2(cpuif.max_outstanding+1)}}'d{{cpuif.max_outstanding}}) begin
|
||||||
// Can safely issue more transactions without overwhelming response buffer
|
// Can safely issue more transactions without overwhelming response buffer
|
||||||
if(axil_arvalid && !axil_prev_was_rd) begin
|
if(axil_arvalid && !axil_prev_was_rd) begin
|
||||||
cpuif_req = '1;
|
cpuif_req = '1;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class Dereferencer:
|
|||||||
def top_node(self) -> AddrmapNode:
|
def top_node(self) -> AddrmapNode:
|
||||||
return self.exp.ds.top_node
|
return self.exp.ds.top_node
|
||||||
|
|
||||||
def get_value(self, obj: Union[int, FieldNode, SignalNode, PropertyReference]) -> str:
|
def get_value(self, obj: Union[int, FieldNode, SignalNode, PropertyReference], width: Optional[int] = None) -> str:
|
||||||
"""
|
"""
|
||||||
Returns the Verilog string that represents the readable value associated
|
Returns the Verilog string that represents the readable value associated
|
||||||
with the object.
|
with the object.
|
||||||
@@ -47,10 +47,12 @@ class Dereferencer:
|
|||||||
|
|
||||||
If obj references a structural systemrdl object, then the corresponding Verilog
|
If obj references a structural systemrdl object, then the corresponding Verilog
|
||||||
expression is returned that represents its value.
|
expression is returned that represents its value.
|
||||||
|
|
||||||
|
The optional width argument can be provided to hint at the expression's desired bitwidth.
|
||||||
"""
|
"""
|
||||||
if isinstance(obj, int):
|
if isinstance(obj, int):
|
||||||
# Is a simple scalar value
|
# Is a simple scalar value
|
||||||
return get_sv_int(obj)
|
return get_sv_int(obj, width)
|
||||||
|
|
||||||
if isinstance(obj, FieldNode):
|
if isinstance(obj, FieldNode):
|
||||||
if obj.implements_storage:
|
if obj.implements_storage:
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from .field_logic import FieldLogic
|
|||||||
from .dereferencer import Dereferencer
|
from .dereferencer import Dereferencer
|
||||||
from .readback import Readback
|
from .readback import Readback
|
||||||
from .identifier_filter import kw_filter as kwf
|
from .identifier_filter import kw_filter as kwf
|
||||||
|
from .utils import clog2
|
||||||
from .scan_design import DesignScanner
|
from .scan_design import DesignScanner
|
||||||
from .validate_design import DesignValidator
|
from .validate_design import DesignValidator
|
||||||
from .cpuif import CpuifBase
|
from .cpuif import CpuifBase
|
||||||
@@ -134,9 +134,6 @@ class RegblockExporter:
|
|||||||
if kwargs:
|
if kwargs:
|
||||||
raise TypeError(f"got an unexpected keyword argument '{list(kwargs.keys())[0]}'")
|
raise TypeError(f"got an unexpected keyword argument '{list(kwargs.keys())[0]}'")
|
||||||
|
|
||||||
# Scan the design for pre-export information
|
|
||||||
DesignScanner(self).do_scan()
|
|
||||||
|
|
||||||
if generate_hwif_report:
|
if generate_hwif_report:
|
||||||
path = os.path.join(output_dir, f"{self.ds.module_name}_hwif.rpt")
|
path = os.path.join(output_dir, f"{self.ds.module_name}_hwif.rpt")
|
||||||
hwif_report_file = open(path, "w", encoding='utf-8') # pylint: disable=consider-using-with
|
hwif_report_file = open(path, "w", encoding='utf-8') # pylint: disable=consider-using-with
|
||||||
@@ -251,9 +248,13 @@ class DesignState:
|
|||||||
# Track any referenced enums
|
# Track any referenced enums
|
||||||
self.user_enums = [] # type: List[Type[UserEnum]]
|
self.user_enums = [] # type: List[Type[UserEnum]]
|
||||||
|
|
||||||
#------------------------
|
# Scan the design to fill in above variables
|
||||||
|
DesignScanner(self).do_scan()
|
||||||
|
|
||||||
|
#------------------------
|
||||||
|
# Min address width encloses the total size AND at least 1 useful address bit
|
||||||
|
self.addr_width = max(clog2(self.top_node.size), clog2(self.cpuif_data_width//8) + 1)
|
||||||
|
|
||||||
self.addr_width = (self.top_node.size - 1).bit_length()
|
|
||||||
if user_addr_width is not None:
|
if user_addr_width is not None:
|
||||||
if user_addr_width < self.addr_width:
|
if user_addr_width < self.addr_width:
|
||||||
msg.fatal(f"User-specified address width shall be greater than or equal to {self.addr_width}.")
|
msg.fatal(f"User-specified address width shall be greater than or equal to {self.addr_width}.")
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ class FieldLogic:
|
|||||||
"""
|
"""
|
||||||
incrvalue = field.get_property('incrvalue')
|
incrvalue = field.get_property('incrvalue')
|
||||||
if incrvalue is not None:
|
if incrvalue is not None:
|
||||||
return self.exp.dereferencer.get_value(incrvalue)
|
return self.exp.dereferencer.get_value(incrvalue, field.width)
|
||||||
if field.get_property('incrwidth'):
|
if field.get_property('incrwidth'):
|
||||||
return self.exp.hwif.get_implied_prop_input_identifier(field, "incrvalue")
|
return self.exp.hwif.get_implied_prop_input_identifier(field, "incrvalue")
|
||||||
return "1'b1"
|
return "1'b1"
|
||||||
@@ -118,8 +118,8 @@ class FieldLogic:
|
|||||||
def get_counter_incrsaturate_value(self, field: 'FieldNode') -> str:
|
def get_counter_incrsaturate_value(self, field: 'FieldNode') -> str:
|
||||||
prop_value = field.get_property('incrsaturate')
|
prop_value = field.get_property('incrsaturate')
|
||||||
if prop_value is True:
|
if prop_value is True:
|
||||||
return self.exp.dereferencer.get_value(2**field.width - 1)
|
return self.exp.dereferencer.get_value(2**field.width - 1, field.width)
|
||||||
return self.exp.dereferencer.get_value(prop_value)
|
return self.exp.dereferencer.get_value(prop_value, field.width)
|
||||||
|
|
||||||
def counter_incrsaturates(self, field: 'FieldNode') -> bool:
|
def counter_incrsaturates(self, field: 'FieldNode') -> bool:
|
||||||
"""
|
"""
|
||||||
@@ -131,8 +131,8 @@ class FieldLogic:
|
|||||||
prop_value = field.get_property('incrthreshold')
|
prop_value = field.get_property('incrthreshold')
|
||||||
if isinstance(prop_value, bool):
|
if isinstance(prop_value, bool):
|
||||||
# No explicit value set. use max
|
# No explicit value set. use max
|
||||||
return self.exp.dereferencer.get_value(2**field.width - 1)
|
return self.exp.dereferencer.get_value(2**field.width - 1, field.width)
|
||||||
return self.exp.dereferencer.get_value(prop_value)
|
return self.exp.dereferencer.get_value(prop_value, field.width)
|
||||||
|
|
||||||
def get_counter_decr_strobe(self, field: 'FieldNode') -> str:
|
def get_counter_decr_strobe(self, field: 'FieldNode') -> str:
|
||||||
"""
|
"""
|
||||||
@@ -151,7 +151,7 @@ class FieldLogic:
|
|||||||
"""
|
"""
|
||||||
decrvalue = field.get_property('decrvalue')
|
decrvalue = field.get_property('decrvalue')
|
||||||
if decrvalue is not None:
|
if decrvalue is not None:
|
||||||
return self.exp.dereferencer.get_value(decrvalue)
|
return self.exp.dereferencer.get_value(decrvalue, field.width)
|
||||||
if field.get_property('decrwidth'):
|
if field.get_property('decrwidth'):
|
||||||
return self.exp.hwif.get_implied_prop_input_identifier(field, "decrvalue")
|
return self.exp.hwif.get_implied_prop_input_identifier(field, "decrvalue")
|
||||||
return "1'b1"
|
return "1'b1"
|
||||||
@@ -159,8 +159,8 @@ class FieldLogic:
|
|||||||
def get_counter_decrsaturate_value(self, field: 'FieldNode') -> str:
|
def get_counter_decrsaturate_value(self, field: 'FieldNode') -> str:
|
||||||
prop_value = field.get_property('decrsaturate')
|
prop_value = field.get_property('decrsaturate')
|
||||||
if prop_value is True:
|
if prop_value is True:
|
||||||
return "'d0"
|
return f"{field.width}'d0"
|
||||||
return self.exp.dereferencer.get_value(prop_value)
|
return self.exp.dereferencer.get_value(prop_value, field.width)
|
||||||
|
|
||||||
def counter_decrsaturates(self, field: 'FieldNode') -> bool:
|
def counter_decrsaturates(self, field: 'FieldNode') -> bool:
|
||||||
"""
|
"""
|
||||||
@@ -172,8 +172,8 @@ class FieldLogic:
|
|||||||
prop_value = field.get_property('decrthreshold')
|
prop_value = field.get_property('decrthreshold')
|
||||||
if isinstance(prop_value, bool):
|
if isinstance(prop_value, bool):
|
||||||
# No explicit value set. use min
|
# No explicit value set. use min
|
||||||
return "'d0"
|
return f"{field.width}'d0"
|
||||||
return self.exp.dereferencer.get_value(prop_value)
|
return self.exp.dereferencer.get_value(prop_value, field.width)
|
||||||
|
|
||||||
def get_swacc_identifier(self, field: 'FieldNode') -> str:
|
def get_swacc_identifier(self, field: 'FieldNode') -> str:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ class FieldLogicGenerator(RDLForLoopGenerator):
|
|||||||
|
|
||||||
reset_value = node.get_property('reset')
|
reset_value = node.get_property('reset')
|
||||||
if reset_value is not None:
|
if reset_value is not None:
|
||||||
reset_value_str = self.exp.dereferencer.get_value(reset_value)
|
reset_value_str = self.exp.dereferencer.get_value(reset_value, node.width)
|
||||||
else:
|
else:
|
||||||
# 5.9.1-g: If no reset value given, the field is not reset, even if it has a resetsignal.
|
# 5.9.1-g: If no reset value given, the field is not reset, even if it has a resetsignal.
|
||||||
reset_value_str = None
|
reset_value_str = None
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
next_c = next_c + {{field_logic.get_counter_incrvalue(node)}};
|
next_c = next_c + {{field_logic.get_counter_incrvalue(node)}};
|
||||||
end
|
end
|
||||||
{%- else %}
|
{%- else %}
|
||||||
{{field_logic.get_field_combo_identifier(node, "overflow")}} = ((({{node.width+1}})'(next_c) + {{field_logic.get_counter_incrvalue(node)}}) > {{get_value(2**node.width - 1)}});
|
{{field_logic.get_field_combo_identifier(node, "overflow")}} = ((({{node.width+1}})'(next_c) + {{field_logic.get_counter_incrvalue(node)}}) > {{get_value(2**node.width - 1, node.width)}});
|
||||||
next_c = next_c + {{field_logic.get_counter_incrvalue(node)}};
|
next_c = next_c + {{field_logic.get_counter_incrvalue(node)}};
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
load_next_c = '1;
|
load_next_c = '1;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from systemrdl.node import SignalNode, RegNode
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from systemrdl.node import Node, FieldNode, AddressableNode, AddrmapNode
|
from systemrdl.node import Node, FieldNode, AddressableNode, AddrmapNode
|
||||||
from .exporter import RegblockExporter
|
from .exporter import DesignState
|
||||||
|
|
||||||
|
|
||||||
class DesignScanner(RDLListener):
|
class DesignScanner(RDLListener):
|
||||||
@@ -15,14 +15,13 @@ class DesignScanner(RDLListener):
|
|||||||
|
|
||||||
Also collects any information that is required prior to the start of the export process.
|
Also collects any information that is required prior to the start of the export process.
|
||||||
"""
|
"""
|
||||||
def __init__(self, exp:'RegblockExporter') -> None:
|
def __init__(self, ds:'DesignState') -> None:
|
||||||
self.exp = exp
|
self.ds = ds
|
||||||
self.ds = exp.ds
|
|
||||||
self.msg = self.top_node.env.msg
|
self.msg = self.top_node.env.msg
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def top_node(self) -> 'AddrmapNode':
|
def top_node(self) -> 'AddrmapNode':
|
||||||
return self.exp.ds.top_node
|
return self.ds.top_node
|
||||||
|
|
||||||
def _get_out_of_hier_field_reset(self) -> None:
|
def _get_out_of_hier_field_reset(self) -> None:
|
||||||
current_node = self.top_node.parent
|
current_node = self.top_node.parent
|
||||||
@@ -93,7 +92,7 @@ class DesignScanner(RDLListener):
|
|||||||
def enter_Reg(self, node: 'RegNode') -> None:
|
def enter_Reg(self, node: 'RegNode') -> None:
|
||||||
# The CPUIF's bus width is sized according to the largest accesswidth in the design
|
# The CPUIF's bus width is sized according to the largest accesswidth in the design
|
||||||
accesswidth = node.get_property('accesswidth')
|
accesswidth = node.get_property('accesswidth')
|
||||||
self.exp.ds.cpuif_data_width = max(self.exp.ds.cpuif_data_width, accesswidth)
|
self.ds.cpuif_data_width = max(self.ds.cpuif_data_width, accesswidth)
|
||||||
|
|
||||||
self.ds.has_buffered_write_regs = self.ds.has_buffered_write_regs or bool(node.get_property('buffer_writes'))
|
self.ds.has_buffered_write_regs = self.ds.has_buffered_write_regs or bool(node.get_property('buffer_writes'))
|
||||||
self.ds.has_buffered_read_regs = self.ds.has_buffered_read_regs or bool(node.get_property('buffer_reads'))
|
self.ds.has_buffered_read_regs = self.ds.has_buffered_read_regs or bool(node.get_property('buffer_reads'))
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import re
|
import re
|
||||||
from typing import Match, Union
|
from typing import Match, Union, Optional
|
||||||
|
|
||||||
from systemrdl.rdltypes.references import PropertyReference
|
from systemrdl.rdltypes.references import PropertyReference
|
||||||
from systemrdl.node import Node, AddrmapNode
|
from systemrdl.node import Node, AddrmapNode
|
||||||
@@ -65,10 +65,13 @@ def ref_is_internal(top_node: AddrmapNode, ref: Union[Node, PropertyReference])
|
|||||||
# This is considerd internal for this exporter
|
# This is considerd internal for this exporter
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_sv_int(n: int) -> str:
|
def get_sv_int(n: int, width: Optional[int]=None) -> str:
|
||||||
if n.bit_length() <= 32:
|
if width is not None:
|
||||||
return f"'h{n:x}"
|
# Explicit width
|
||||||
else:
|
return f"{width}'h{n:x}"
|
||||||
|
elif n.bit_length() > 32:
|
||||||
# SV standard only enforces that unsized literals shall be at least 32-bits
|
# SV standard only enforces that unsized literals shall be at least 32-bits
|
||||||
# To support larger literals, they need to be sized explicitly
|
# To support larger literals, they need to be sized explicitly
|
||||||
return f"{n.bit_length()}'h{n:x}"
|
return f"{n.bit_length()}'h{n:x}"
|
||||||
|
else:
|
||||||
|
return f"'h{n:x}"
|
||||||
|
|||||||
Reference in New Issue
Block a user