Coverage for hdl_registers/register_array.py: 97%
34 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 11:11 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 11:11 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the hdl-registers project, an HDL register generator fast enough to run
5# in real time.
6# https://hdl-registers.com
7# https://github.com/hdl-registers/hdl-registers
8# --------------------------------------------------------------------------------------------------
11from typing import TYPE_CHECKING
13from .register import Register
15if TYPE_CHECKING:
16 from hdl_registers.register_mode import RegisterMode
19class RegisterArray:
20 """
21 Represent an array of registers.
22 That is, a sequence of registers that shall be repeated a number of times in
23 a :class:`.RegisterList`.
25 Note that every register array must have at least one register added to it via
26 the :meth:`.append_register` method.
27 Empty register arrays will result in errors.
28 """
30 def __init__(self, name: str, base_index: int, length: int, description: str) -> None:
31 """
32 Arguments:
33 name: The name of this register array.
34 base_index: The zero-based index of the first register of this array in the
35 register list.
36 length: The number of times the register sequence shall be repeated.
37 description: Textual register array description.
38 """
39 if length < 1:
40 raise ValueError(
41 f'Register array "{name}" length must be greater than 0. Got "{length}".'
42 )
44 self.name = name
45 self.base_index = base_index
46 self.length = length
47 self.description = description
49 self.registers: list[Register] = []
51 def append_register(self, name: str, mode: "RegisterMode", description: str) -> Register:
52 """
53 Append a register to this array.
55 Arguments:
56 name: The name of the register.
57 mode: A mode that decides the behavior of the register.
58 See https://hdl-registers.com/rst/basic_feature/basic_feature_register_modes.html
59 for more information about the different modes.
60 description: Textual register description.
62 Return:
63 The register object that was created.
64 """
65 index = len(self.registers)
66 register = Register(name=name, index=index, mode=mode, description=description)
68 self.registers.append(register)
69 return register
71 def get_register(self, name: str) -> Register:
72 """
73 Get a register from this array. Will raise exception if no register matches.
75 Arguments:
76 name: The name of the register.
78 Return:
79 The register.
80 """
81 for register in self.registers:
82 if register.name == name:
83 return register
85 raise ValueError(f'Could not find register "{name}" within register array "{self.name}"')
87 @property
88 def index(self) -> int:
89 """
90 Property exists to be used analogously with ``Register.index``.
92 Return:
93 The highest index occupied by this array.
94 """
95 if len(self.registers) == 0:
96 raise ValueError(f'Register array "{self.name}" must contain at least one register.')
98 return self.base_index + self.length * len(self.registers) - 1
100 def get_start_index(self, array_index: int) -> int:
101 """
102 The index within the register list where array iteration number ``array_index`` starts.
104 Arguments:
105 array_index: The array iteration index.
106 Must be less than the array ``length``.
107 """
108 if not 0 <= array_index < self.length:
109 raise ValueError(
110 f'Index {array_index} out of range for register array "{self.name}" '
111 f"of length {self.length}."
112 )
114 return self.base_index + array_index * len(self.registers)
116 def __repr__(self) -> str:
117 return f"""{self.__class__.__name__}(\
118name={self.name},\
119base_index={self.base_index},\
120length={self.length},\
121description={self.description},\
122registers={",".join([repr(register) for register in self.registers])},\
123)"""