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

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# -------------------------------------------------------------------------------------------------- 

9 

10 

11from typing import TYPE_CHECKING 

12 

13from .register import Register 

14 

15if TYPE_CHECKING: 

16 from hdl_registers.register_mode import RegisterMode 

17 

18 

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`. 

24 

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 """ 

29 

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 ) 

43 

44 self.name = name 

45 self.base_index = base_index 

46 self.length = length 

47 self.description = description 

48 

49 self.registers: list[Register] = [] 

50 

51 def append_register(self, name: str, mode: "RegisterMode", description: str) -> Register: 

52 """ 

53 Append a register to this array. 

54 

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. 

61 

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) 

67 

68 self.registers.append(register) 

69 return register 

70 

71 def get_register(self, name: str) -> Register: 

72 """ 

73 Get a register from this array. Will raise exception if no register matches. 

74 

75 Arguments: 

76 name: The name of the register. 

77 

78 Return: 

79 The register. 

80 """ 

81 for register in self.registers: 

82 if register.name == name: 

83 return register 

84 

85 raise ValueError(f'Could not find register "{name}" within register array "{self.name}"') 

86 

87 @property 

88 def index(self) -> int: 

89 """ 

90 Property exists to be used analogously with ``Register.index``. 

91 

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.') 

97 

98 return self.base_index + self.length * len(self.registers) - 1 

99 

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. 

103 

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 ) 

113 

114 return self.base_index + array_index * len(self.registers) 

115 

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)"""