Coverage for hdl_registers/register_array.py: 97%
34 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-07 20:51 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-07 20:51 +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# --------------------------------------------------------------------------------------------------
11# Standard libraries
12from typing import TYPE_CHECKING
14# Local folder libraries
15from .register import Register
17if TYPE_CHECKING:
18 # First party libraries
19 from hdl_registers.register_mode import RegisterMode
22class RegisterArray:
23 """
24 Represent an array of registers.
25 That is, a sequence of registers that shall be repeated a number of times in
26 a :class:`.RegisterList`.
28 Note that every register array must have at least one register added to it via
29 the :meth:`.append_register` method.
30 Empty register arrays will result in errors.
31 """
33 def __init__(self, name: str, base_index: int, length: int, description: str):
34 """
35 Arguments:
36 name: The name of this register array.
37 base_index: The zero-based index of the first register of this array in the
38 register list.
39 length: The number of times the register sequence shall be repeated.
40 description: Textual register array description.
41 """
42 if length < 1:
43 raise ValueError(
44 f'Register array "{name}" length must be greater than 0. Got "{length}".'
45 )
47 self.name = name
48 self.base_index = base_index
49 self.length = length
50 self.description = description
52 self.registers: list[Register] = []
54 def append_register(self, name: str, mode: "RegisterMode", description: str) -> Register:
55 """
56 Append a register to this array.
58 Arguments:
59 name: The name of the register.
60 mode: A mode that decides the behavior of the register.
61 See https://hdl-registers.com/rst/basic_feature/basic_feature_register_modes.html
62 for more information about the different modes.
63 description: Textual register description.
65 Return:
66 The register object that was created.
67 """
68 index = len(self.registers)
69 register = Register(name=name, index=index, mode=mode, description=description)
71 self.registers.append(register)
72 return register
74 def get_register(self, name: str) -> Register:
75 """
76 Get a register from this array. Will raise exception if no register matches.
78 Arguments:
79 name: The name of the register.
80 Return:
81 The register.
82 """
83 for register in self.registers:
84 if register.name == name:
85 return register
87 raise ValueError(f'Could not find register "{name}" within register array "{self.name}"')
89 @property
90 def index(self) -> int:
91 """
92 Property exists to be used analogously with ``Register.index``.
94 Return:
95 The highest index occupied by this array.
96 """
97 if len(self.registers) == 0:
98 raise ValueError(f'Register array "{self.name}" must contain at least one register.')
100 return self.base_index + self.length * len(self.registers) - 1
102 def get_start_index(self, array_index: int) -> int:
103 """
104 The index within the register list where array iteration number ``array_index`` starts.
106 Arguments:
107 array_index: The array iteration index.
108 Must be less than the array ``length``.
109 """
110 if not 0 <= array_index < self.length:
111 raise ValueError(
112 f'Index {array_index} out of range for register array "{self.name}" '
113 f"of length {self.length}."
114 )
116 return self.base_index + array_index * len(self.registers)
118 def __repr__(self) -> str:
119 return f"""{self.__class__.__name__}(\
120name={self.name},\
121base_index={self.base_index},\
122length={self.length},\
123description={self.description},\
124registers={','.join([repr(register) for register in self.registers])},\
125)"""