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

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 

11# Standard libraries 

12from typing import TYPE_CHECKING 

13 

14# Local folder libraries 

15from .register import Register 

16 

17if TYPE_CHECKING: 

18 # First party libraries 

19 from hdl_registers.register_mode import RegisterMode 

20 

21 

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

27 

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

32 

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 ) 

46 

47 self.name = name 

48 self.base_index = base_index 

49 self.length = length 

50 self.description = description 

51 

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

53 

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

55 """ 

56 Append a register to this array. 

57 

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. 

64 

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) 

70 

71 self.registers.append(register) 

72 return register 

73 

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

75 """ 

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

77 

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 

86 

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

88 

89 @property 

90 def index(self) -> int: 

91 """ 

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

93 

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

99 

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

101 

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. 

105 

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 ) 

115 

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

117 

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