diff --git a/src/peakrdl_regblock/addr_decode.py b/src/peakrdl_regblock/addr_decode.py index 9c14f17..3710660 100644 --- a/src/peakrdl_regblock/addr_decode.py +++ b/src/peakrdl_regblock/addr_decode.py @@ -3,10 +3,11 @@ from typing import TYPE_CHECKING, Union, List, Optional from systemrdl.node import FieldNode, RegNode from systemrdl.walker import WalkerAction -from .utils import get_indexed_path, get_sv_int +from .utils import get_indexed_path from .struct_generator import RDLStructGenerator from .forloop_generator import RDLForLoopGenerator from .identifier_filter import kw_filter as kwf +from .sv_int import SVInt if TYPE_CHECKING: from .exporter import RegblockExporter @@ -149,7 +150,7 @@ class DecodeLogicGenerator(RDLForLoopGenerator): # Is an external block addr_str = self._get_address_str(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, self.addr_decode.exp.ds.addr_width)})" + rhs = f"cpuif_req_masked & (cpuif_addr >= {addr_str}) & (cpuif_addr <= {addr_str} + {SVInt(node.size - 1, self.addr_decode.exp.ds.addr_width)})" self.add_content(f"{strb} = {rhs};") self.add_content(f"is_external |= {rhs};") return WalkerAction.SkipDescendants @@ -158,12 +159,12 @@ class DecodeLogicGenerator(RDLForLoopGenerator): def _get_address_str(self, node: 'AddressableNode', subword_offset: int=0) -> str: - a = get_sv_int( + a = str(SVInt( 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): - a += f" + i{i}*{get_sv_int(stride, self.addr_decode.exp.ds.addr_width)}" + a += f" + i{i}*{SVInt(stride, self.addr_decode.exp.ds.addr_width)}" return a diff --git a/src/peakrdl_regblock/dereferencer.py b/src/peakrdl_regblock/dereferencer.py index 7a10482..d80e6ed 100644 --- a/src/peakrdl_regblock/dereferencer.py +++ b/src/peakrdl_regblock/dereferencer.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Union, Optional from systemrdl.node import AddrmapNode, FieldNode, SignalNode, RegNode, AddressableNode from systemrdl.rdltypes import PropertyReference -from .utils import get_sv_int +from .sv_int import SVInt if TYPE_CHECKING: from .exporter import RegblockExporter, DesignState @@ -38,7 +38,7 @@ class Dereferencer: def top_node(self) -> AddrmapNode: return self.exp.ds.top_node - def get_value(self, obj: Union[int, FieldNode, SignalNode, PropertyReference], width: Optional[int] = None) -> str: + def get_value(self, obj: Union[int, FieldNode, SignalNode, PropertyReference], width: Optional[int] = None) -> Union[SVInt, str]: """ Returns the Verilog string that represents the readable value associated with the object. @@ -52,20 +52,20 @@ class Dereferencer: """ if isinstance(obj, int): # Is a simple scalar value - return get_sv_int(obj, width) + return SVInt(obj, width) if isinstance(obj, FieldNode): if obj.implements_storage: return self.field_logic.get_storage_identifier(obj) if self.hwif.has_value_input(obj): - return self.hwif.get_input_identifier(obj) + return self.hwif.get_input_identifier(obj, width) # Field does not have a storage element, nor does it have a HW input # must be a constant value as defined by its reset value reset_value = obj.get_property('reset') if reset_value is not None: - return self.get_value(reset_value) + return self.get_value(reset_value, obj.width) else: # No reset value defined! obj.env.msg.warning( @@ -76,11 +76,11 @@ class Dereferencer: if isinstance(obj, SignalNode): # Signals are always inputs from the hwif - return self.hwif.get_input_identifier(obj) + return self.hwif.get_input_identifier(obj, width) if isinstance(obj, PropertyReference): if isinstance(obj.node, FieldNode): - return self.get_field_propref_value(obj.node, obj.name) + return self.get_field_propref_value(obj.node, obj.name, width) elif isinstance(obj.node, RegNode): return self.get_reg_propref_value(obj.node, obj.name) else: @@ -89,7 +89,12 @@ class Dereferencer: raise RuntimeError(f"Unhandled reference to: {obj}") - def get_field_propref_value(self, field: FieldNode, prop_name: str) -> str: + def get_field_propref_value( + self, + field: FieldNode, + prop_name: str, + width: Optional[int] = None, + ) -> Union[SVInt, str]: # Value reduction properties. # Wrap with the appropriate Verilog reduction operator if prop_name == "anded": @@ -115,7 +120,7 @@ class Dereferencer: 'reset', 'resetsignal', }: - return self.get_value(field.get_property(prop_name)) + return self.get_value(field.get_property(prop_name), width) # Field Next if prop_name == "next": @@ -124,7 +129,7 @@ class Dereferencer: # unset by the user, points to the implied internal signal return self.field_logic.get_field_combo_identifier(field, "next") else: - return self.get_value(prop_value) + return self.get_value(prop_value, width) # References to another component value, or an implied input if prop_name in {'hwclr', 'hwset'}: @@ -163,7 +168,7 @@ class Dereferencer: else: return f"!({self.get_value(prop_value)})" else: - return self.get_value(prop_value) + return self.get_value(prop_value, width) if prop_name == "swacc": return self.field_logic.get_swacc_identifier(field) @@ -232,7 +237,7 @@ class Dereferencer: if isinstance(obj, SignalNode): s = self.get_value(obj) if obj.get_property('activehigh'): - return s + return str(s) else: return f"~{s}" diff --git a/src/peakrdl_regblock/field_logic/__init__.py b/src/peakrdl_regblock/field_logic/__init__.py index c1fcb12..8b362aa 100644 --- a/src/peakrdl_regblock/field_logic/__init__.py +++ b/src/peakrdl_regblock/field_logic/__init__.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Union from systemrdl.rdltypes import PrecedenceType, InterruptType @@ -11,6 +11,7 @@ from . import hw_set_clr from . import hw_interrupts from ..utils import get_indexed_path +from ..sv_int import SVInt from .generators import CombinationalStructGenerator, FieldStorageStructGenerator, FieldLogicGenerator @@ -99,12 +100,12 @@ class FieldLogic: """ prop_value = field.get_property('incr') if prop_value: - return self.exp.dereferencer.get_value(prop_value) + return str(self.exp.dereferencer.get_value(prop_value)) # unset by the user, points to the implied input signal return self.exp.hwif.get_implied_prop_input_identifier(field, "incr") - def get_counter_incrvalue(self, field: 'FieldNode') -> str: + def get_counter_incrvalue(self, field: 'FieldNode') -> Union[SVInt, str]: """ Return the string that represents the field's increment value """ @@ -115,7 +116,7 @@ class FieldLogic: return self.exp.hwif.get_implied_prop_input_identifier(field, "incrvalue") return "1'b1" - def get_counter_incrsaturate_value(self, field: 'FieldNode') -> str: + def get_counter_incrsaturate_value(self, field: 'FieldNode') -> Union[SVInt, str]: prop_value = field.get_property('incrsaturate') if prop_value is True: return self.exp.dereferencer.get_value(2**field.width - 1, field.width) @@ -127,7 +128,7 @@ class FieldLogic: """ return field.get_property('incrsaturate') is not False - def get_counter_incrthreshold_value(self, field: 'FieldNode') -> str: + def get_counter_incrthreshold_value(self, field: 'FieldNode') -> Union[SVInt, str]: prop_value = field.get_property('incrthreshold') if isinstance(prop_value, bool): # No explicit value set. use max @@ -140,12 +141,12 @@ class FieldLogic: """ prop_value = field.get_property('decr') if prop_value: - return self.exp.dereferencer.get_value(prop_value) + return str(self.exp.dereferencer.get_value(prop_value)) # unset by the user, points to the implied input signal return self.exp.hwif.get_implied_prop_input_identifier(field, "decr") - def get_counter_decrvalue(self, field: 'FieldNode') -> str: + def get_counter_decrvalue(self, field: 'FieldNode') -> Union[SVInt, str]: """ Return the string that represents the field's decrement value """ @@ -156,7 +157,7 @@ class FieldLogic: return self.exp.hwif.get_implied_prop_input_identifier(field, "decrvalue") return "1'b1" - def get_counter_decrsaturate_value(self, field: 'FieldNode') -> str: + def get_counter_decrsaturate_value(self, field: 'FieldNode') -> Union[SVInt, str]: prop_value = field.get_property('decrsaturate') if prop_value is True: return f"{field.width}'d0" @@ -168,7 +169,7 @@ class FieldLogic: """ return field.get_property('decrsaturate') is not False - def get_counter_decrthreshold_value(self, field: 'FieldNode') -> str: + def get_counter_decrthreshold_value(self, field: 'FieldNode') -> Union[SVInt, str]: prop_value = field.get_property('decrthreshold') if isinstance(prop_value, bool): # No explicit value set. use min diff --git a/src/peakrdl_regblock/field_logic/hw_set_clr.py b/src/peakrdl_regblock/field_logic/hw_set_clr.py index 2c19cc8..982f1b3 100644 --- a/src/peakrdl_regblock/field_logic/hw_set_clr.py +++ b/src/peakrdl_regblock/field_logic/hw_set_clr.py @@ -17,7 +17,7 @@ class HWSet(NextStateConditional): identifier = self.exp.hwif.get_implied_prop_input_identifier(field, "hwset") else: # signal or field - identifier = self.exp.dereferencer.get_value(prop) + identifier = str(self.exp.dereferencer.get_value(prop)) return identifier def get_assignments(self, field: 'FieldNode') -> List[str]: @@ -50,7 +50,7 @@ class HWClear(NextStateConditional): identifier = self.exp.hwif.get_implied_prop_input_identifier(field, "hwclr") else: # signal or field - identifier = self.exp.dereferencer.get_value(prop) + identifier = str(self.exp.dereferencer.get_value(prop)) return identifier def get_assignments(self, field: 'FieldNode') -> List[str]: diff --git a/src/peakrdl_regblock/field_logic/hw_write.py b/src/peakrdl_regblock/field_logic/hw_write.py index 003cd68..0ab3860 100644 --- a/src/peakrdl_regblock/field_logic/hw_write.py +++ b/src/peakrdl_regblock/field_logic/hw_write.py @@ -24,7 +24,7 @@ class AlwaysWrite(NextStateConditional): def get_assignments(self, field: 'FieldNode') -> List[str]: hwmask = field.get_property('hwmask') hwenable = field.get_property('hwenable') - I = self.exp.hwif.get_input_identifier(field) + I = str(self.exp.hwif.get_input_identifier(field)) R = self.exp.field_logic.get_storage_identifier(field) if hwmask is not None: M = self.exp.dereferencer.get_value(hwmask) @@ -55,7 +55,7 @@ class WEWrite(AlwaysWrite): identifier = self.exp.hwif.get_implied_prop_input_identifier(field, "we") else: # signal or field - identifier = self.exp.dereferencer.get_value(prop) + identifier = str(self.exp.dereferencer.get_value(prop)) return identifier class WELWrite(AlwaysWrite): @@ -73,5 +73,5 @@ class WELWrite(AlwaysWrite): identifier = self.exp.hwif.get_implied_prop_input_identifier(field, "wel") else: # signal or field - identifier = self.exp.dereferencer.get_value(prop) + identifier = str(self.exp.dereferencer.get_value(prop)) return f"!{identifier}" diff --git a/src/peakrdl_regblock/hwif/__init__.py b/src/peakrdl_regblock/hwif/__init__.py index 7b50e5f..3583afe 100644 --- a/src/peakrdl_regblock/hwif/__init__.py +++ b/src/peakrdl_regblock/hwif/__init__.py @@ -1,10 +1,11 @@ -from typing import TYPE_CHECKING, Union, Set, Dict, Optional, TextIO, Type, List +from typing import TYPE_CHECKING, Union, Optional, TextIO from systemrdl.node import AddrmapNode, SignalNode, FieldNode, RegNode, AddressableNode -from systemrdl.rdltypes import PropertyReference, UserEnum +from systemrdl.rdltypes import PropertyReference from ..utils import get_indexed_path from ..identifier_filter import kw_filter as kwf +from ..sv_int import SVInt from .generators import InputStructGenerator_Hier, OutputStructGenerator_Hier from .generators import InputStructGenerator_TypeScope, OutputStructGenerator_TypeScope @@ -127,7 +128,11 @@ class Hwif: return obj.is_hw_readable - def get_input_identifier(self, obj: Union[FieldNode, SignalNode, PropertyReference]) -> str: + def get_input_identifier( + self, + obj: Union[FieldNode, SignalNode, PropertyReference], + width: Optional[int] = None, + ) -> Union[SVInt, str]: """ Returns the identifier string that best represents the input object. @@ -143,7 +148,7 @@ class Hwif: next_value = obj.get_property('next') if next_value is not None: # 'next' property replaces the inferred input signal - return self.exp.dereferencer.get_value(next_value) + return self.exp.dereferencer.get_value(next_value, width) # Otherwise, use inferred path = get_indexed_path(self.top_node, obj) return "hwif_in." + path + ".next" diff --git a/src/peakrdl_regblock/hwif/generators.py b/src/peakrdl_regblock/hwif/generators.py index 68ac0c2..a56f0ac 100644 --- a/src/peakrdl_regblock/hwif/generators.py +++ b/src/peakrdl_regblock/hwif/generators.py @@ -5,7 +5,7 @@ from systemrdl.walker import WalkerAction from ..struct_generator import RDLFlatStructGenerator from ..identifier_filter import kw_filter as kwf -from ..utils import get_sv_int +from ..sv_int import SVInt if TYPE_CHECKING: from systemrdl.node import Node, SignalNode, AddressableNode, RegfileNode @@ -289,7 +289,7 @@ class EnumGenerator: lines = [] for enum_member in user_enum: - lines.append(f" {prefix}__{enum_member.name} = {get_sv_int(enum_member.value)}") + lines.append(f" {prefix}__{enum_member.name} = {SVInt(enum_member.value)}") return ( "typedef enum {\n" diff --git a/src/peakrdl_regblock/read_buffering/__init__.py b/src/peakrdl_regblock/read_buffering/__init__.py index 6aee6b2..63af6ed 100644 --- a/src/peakrdl_regblock/read_buffering/__init__.py +++ b/src/peakrdl_regblock/read_buffering/__init__.py @@ -1,10 +1,11 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Union -from systemrdl.node import AddrmapNode, RegNode, FieldNode, SignalNode +from systemrdl.node import AddrmapNode, RegNode, SignalNode from .storage_generator import RBufStorageStructGenerator from .implementation_generator import RBufLogicGenerator from ..utils import get_indexed_path +from ..sv_int import SVInt if TYPE_CHECKING: from ..exporter import RegblockExporter @@ -47,12 +48,12 @@ class ReadBuffering: elif isinstance(trigger, SignalNode): s = self.exp.dereferencer.get_value(trigger) if trigger.get_property('activehigh'): - return s + return str(s) else: return f"~{s}" else: # Trigger is a field or propref bit - return self.exp.dereferencer.get_value(trigger) + return str(self.exp.dereferencer.get_value(trigger)) def get_rbuf_data(self, node: RegNode) -> str: return "rbuf_storage." + get_indexed_path(self.top_node, node) + ".data" diff --git a/src/peakrdl_regblock/readback/generators.py b/src/peakrdl_regblock/readback/generators.py index 59e8426..4c8981b 100644 --- a/src/peakrdl_regblock/readback/generators.py +++ b/src/peakrdl_regblock/readback/generators.py @@ -5,6 +5,8 @@ from systemrdl.walker import WalkerAction from ..forloop_generator import RDLForLoopGenerator, LoopBody +from ..utils import do_bitswap, do_slice + if TYPE_CHECKING: from ..exporter import RegblockExporter @@ -147,7 +149,7 @@ class ReadbackAssignmentGenerator(RDLForLoopGenerator): value = self.exp.dereferencer.get_value(field) if field.msb < field.lsb: # Field gets bitswapped since it is in [low:high] orientation - value = f"{{<<{{{value}}}}}" + value = do_bitswap(value) self.add_content(f"assign readback_array[{self.current_offset_str}][{field.high}:{field.low}] = {rd_strb} ? {value} : '0;") @@ -223,9 +225,9 @@ class ReadbackAssignmentGenerator(RDLForLoopGenerator): f_low = field.width - 1 - f_low f_high = field.width - 1 - f_high f_low, f_high = f_high, f_low - value = f"{{<<{{{self.exp.dereferencer.get_value(field)}[{f_high}:{f_low}]}}}}" + value = do_bitswap(do_slice(self.exp.dereferencer.get_value(field), f_high, f_low)) else: - value = self.exp.dereferencer.get_value(field) + f"[{f_high}:{f_low}]" + value = do_slice(self.exp.dereferencer.get_value(field), f_high, f_low) self.add_content(f"assign readback_array[{self.current_offset_str}][{r_high}:{r_low}] = {rd_strb} ? {value} : '0;") bidx = accesswidth @@ -234,7 +236,7 @@ class ReadbackAssignmentGenerator(RDLForLoopGenerator): value = self.exp.dereferencer.get_value(field) if field.msb < field.lsb: # Field gets bitswapped since it is in [low:high] orientation - value = f"{{<<{{{value}}}}}" + value = do_bitswap(value) self.add_content(f"assign readback_array[{self.current_offset_str}][{field.high}:{field.low}] = {rd_strb} ? {value} : '0;") bidx = field.high + 1 @@ -299,7 +301,7 @@ class ReadbackAssignmentGenerator(RDLForLoopGenerator): value = self.exp.dereferencer.get_value(field) if field.msb < field.lsb: # Field gets bitswapped since it is in [low:high] orientation - value = f"{{<<{{{value}}}}}" + value = do_bitswap(value) self.add_content(f"assign readback_array[{self.current_offset_str}][{high}:{low}] = {rd_strb} ? {value} : '0;") @@ -328,9 +330,9 @@ class ReadbackAssignmentGenerator(RDLForLoopGenerator): f_high = field.width - 1 - f_high f_low, f_high = f_high, f_low - value = f"{{<<{{{self.exp.dereferencer.get_value(field)}[{f_high}:{f_low}]}}}}" + value = do_bitswap(do_slice(self.exp.dereferencer.get_value(field), f_high, f_low)) else: - value = self.exp.dereferencer.get_value(field) + f"[{f_high}:{f_low}]" + value = do_slice(self.exp.dereferencer.get_value(field), f_high, f_low) self.add_content(f"assign readback_array[{self.current_offset_str}][{r_high}:{r_low}] = {rd_strb} ? {value} : '0;") @@ -358,9 +360,9 @@ class ReadbackAssignmentGenerator(RDLForLoopGenerator): f_high = field.width - 1 - f_high f_low, f_high = f_high, f_low - value = f"{{<<{{{self.exp.dereferencer.get_value(field)}[{f_high}:{f_low}]}}}}" + value = do_bitswap(do_slice(self.exp.dereferencer.get_value(field), f_high, f_low)) else: - value = self.exp.dereferencer.get_value(field) + f"[{f_high}:{f_low}]" + value = do_slice(self.exp.dereferencer.get_value(field), f_high, f_low) self.add_content(f"assign readback_array[{self.current_offset_str}][{r_high}:{r_low}] = {rd_strb} ? {value} : '0;") diff --git a/src/peakrdl_regblock/sv_int.py b/src/peakrdl_regblock/sv_int.py new file mode 100644 index 0000000..496eacf --- /dev/null +++ b/src/peakrdl_regblock/sv_int.py @@ -0,0 +1,17 @@ +from typing import Optional + +class SVInt: + def __init__(self, value: int, width: Optional[int] = None) -> None: + self.value = value + self.width = width + + def __str__(self) -> str: + if self.width is not None: + # Explicit width + return f"{self.width}'h{self.value:x}" + elif self.value.bit_length() > 32: + # SV standard only enforces that unsized literals shall be at least 32-bits + # To support larger literals, they need to be sized explicitly + return f"{self.value.bit_length()}'h{self.value:x}" + else: + return f"'h{self.value:x}" diff --git a/src/peakrdl_regblock/utils.py b/src/peakrdl_regblock/utils.py index 3dd7f3b..1074f89 100644 --- a/src/peakrdl_regblock/utils.py +++ b/src/peakrdl_regblock/utils.py @@ -1,10 +1,11 @@ import re -from typing import Match, Union, Optional +from typing import Match, Union from systemrdl.rdltypes.references import PropertyReference from systemrdl.node import Node, AddrmapNode from .identifier_filter import kw_filter as kwf +from .sv_int import SVInt def get_indexed_path(top_node: Node, target_node: Node) -> str: """ @@ -65,13 +66,36 @@ def ref_is_internal(top_node: AddrmapNode, ref: Union[Node, PropertyReference]) # This is considerd internal for this exporter return True -def get_sv_int(n: int, width: Optional[int]=None) -> str: - if width is not None: - # Explicit width - return f"{width}'h{n:x}" - elif n.bit_length() > 32: - # SV standard only enforces that unsized literals shall be at least 32-bits - # To support larger literals, they need to be sized explicitly - return f"{n.bit_length()}'h{n:x}" + +def do_slice(value: Union[SVInt, str], high: int, low: int) -> Union[SVInt, str]: + if isinstance(value, str): + # If string, assume this is an identifier. Append bit-slice + if high == low: + return f"{value}[{low}]" + else: + return f"{value}[{high}:{low}]" else: - return f"'h{n:x}" + # it is an SVInt literal. Slice it down + mask = (1 << (high + 1)) - 1 + v = (value.value & mask) >> low + + if value.width is not None: + w = high - low + 1 + else: + w = None + + return SVInt(v, w) + +def do_bitswap(value: Union[SVInt, str]) -> Union[SVInt, str]: + if isinstance(value, str): + # If string, assume this is an identifier. Wrap in a streaming operator + return "{<<{" + value + "}}" + else: + # it is an SVInt literal. bitswap it + assert value.width is not None # width must be known! + v = value.value + vswap = 0 + for _ in range(value.width): + vswap = (vswap << 1) + (v & 1) + v >>= 1 + return SVInt(vswap, value.width) diff --git a/src/peakrdl_regblock/write_buffering/__init__.py b/src/peakrdl_regblock/write_buffering/__init__.py index 06ae55c..3efb0f8 100644 --- a/src/peakrdl_regblock/write_buffering/__init__.py +++ b/src/peakrdl_regblock/write_buffering/__init__.py @@ -5,6 +5,7 @@ from systemrdl.node import AddrmapNode, RegNode, FieldNode, SignalNode from .storage_generator import WBufStorageStructGenerator from .implementation_generator import WBufLogicGenerator from ..utils import get_indexed_path +from ..sv_int import SVInt if TYPE_CHECKING: from ..exporter import RegblockExporter @@ -42,7 +43,7 @@ class WriteBuffering: prefix = self.get_wbuf_prefix(node) return f"{prefix}.pending && {self.get_trigger(node)}" - def get_raw_trigger(self, node: 'RegNode') -> str: + def get_raw_trigger(self, node: 'RegNode') -> Union[SVInt, str]: trigger = node.get_property('wbuffer_trigger') if isinstance(trigger, RegNode): @@ -67,7 +68,7 @@ class WriteBuffering: # Trigger is a field or propref bit return self.exp.dereferencer.get_value(trigger) - def get_trigger(self, node: Union[RegNode, FieldNode]) -> str: + def get_trigger(self, node: Union[RegNode, FieldNode]) -> Union[SVInt, str]: if isinstance(node, FieldNode): node = node.parent trigger = node.get_property('wbuffer_trigger') diff --git a/tests/test_wide_regs/regblock.rdl b/tests/test_wide_regs/regblock.rdl index 32b54f0..b3d4ca4 100644 --- a/tests/test_wide_regs/regblock.rdl +++ b/tests/test_wide_regs/regblock.rdl @@ -90,4 +90,22 @@ addrmap top { } counter_reg; counter_reg.f1_cnt->incr = r_reg2.f1->swacc; counter_reg.f2_cnt->incr = r_reg2.f2->swacc; + + reg { + regwidth = 32; + accesswidth = 16; + default sw=r; + default hw=r; + + field {} f1[31:0] = 0x1234_5678; + } r_reg3; + + reg { + regwidth = 32; + accesswidth = 16; + default sw=r; + default hw=r; + + field {} f1[0:31] = 0x1234_5678; + } r_reg4; }; diff --git a/tests/test_wide_regs/tb_template.sv b/tests/test_wide_regs/tb_template.sv index 005608a..8c261c6 100644 --- a/tests/test_wide_regs/tb_template.sv +++ b/tests/test_wide_regs/tb_template.sv @@ -108,4 +108,14 @@ // counter_reg cpuif.assert_read('h30, 16'h0204); + // r_reg3 + cpuif.assert_read('h34, 16'h5678); + cpuif.assert_read('h36, 16'h1234); + assert(cb.hwif_out.r_reg3.f1.value == 32'h12345678); + + // r_reg4 + cpuif.assert_read('h38, 16'h2C48); + cpuif.assert_read('h3A, 16'h1E6A); + assert(cb.hwif_out.r_reg4.f1.value == 32'h12345678); + {% endblock %}