Coverage for hdl_registers/register.py: 100%
54 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-01-29 22:03 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-01-29 22:03 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the hdl_registers project, a HDL register generator fast enough to be run
5# in real time.
6# https://hdl-registers.com
7# https://gitlab.com/hdl_registers/hdl_registers
8# --------------------------------------------------------------------------------------------------
10# Local folder libraries
11from .bit import Bit
12from .bit_vector import BitVector
13from .register_field import DEFAULT_FIELD_TYPE, FieldType
16class RegisterMode:
17 def __init__(self, mode_readable, description):
18 """
19 Arguments:
20 mode_readable (str): The readable representation of this mode. E.g. "r" -> "Read-only".
21 description (str): Textual description of mode.
22 """
23 self.mode_readable = mode_readable
24 self.description = description
27REGISTER_MODES = dict(
28 r=RegisterMode("Read", "Bus can read a value that fabric provides."),
29 w=RegisterMode("Write", "Bus can write a value that is available for fabric usage."),
30 r_w=RegisterMode(
31 "Read, Write",
32 "Bus can write a value and read it back. The written value is available for fabric usage.",
33 ),
34 wpulse=RegisterMode(
35 "Write-pulse", "Bus can write a value that is asserted for one clock cycle in fabric."
36 ),
37 r_wpulse=RegisterMode(
38 "Read, Write-pulse",
39 "Bus can read a value that fabric provides. "
40 "Bus can write a value that is asserted for one clock cycle in fabric.",
41 ),
42)
45class Register:
47 """
48 Used to represent a register and its fields.
49 """
51 def __init__(self, name, index, mode, description):
52 """
53 Arguments:
54 name (str): The name of the register.
55 index (int): The zero-based index of this register.
56 If this register is part of a register array, the index shall be relative to the
57 start of the array. I.e. the index is zero for the first register in the array.
58 If the register is a plain register, the index shall be relative to the start of
59 the register list.
60 mode (str): A valid register mode.
61 description (str): Textual register description.
62 """
63 if mode not in REGISTER_MODES:
64 raise ValueError(f'Invalid mode "{mode}" for register "{name}"')
66 self.name = name
67 self.index = index
68 self.mode = mode
69 self.description = description
70 self.fields = []
71 self.bit_index = 0
73 def append_bit(self, name, description, default_value):
74 """
75 Append a bit field to this register.
77 Arguments:
78 name (str): The name of the bit.
79 description (str): Description of the bit.
80 default_value (str): Default value. Either "1" or "0".
82 Return:
83 :class:`.Bit`: The bit object that was created.
84 """
85 bit = Bit(
86 name=name, index=self.bit_index, description=description, default_value=default_value
87 )
88 self.fields.append(bit)
90 self.bit_index += bit.width
91 if self.bit_index > 32:
92 raise ValueError(f'Maximum width exceeded for register "{self.name}"')
94 return bit
96 def append_bit_vector(
97 self, name, description, width, default_value, field_type: FieldType = DEFAULT_FIELD_TYPE
98 ):
99 """
100 Append a bit vector field to this register.
102 Arguments:
103 name (str): The name of the bit vector.
104 width (int) : The width of the bit vector.
105 description (str): Description of the bit vector.
106 default_value (str): Default value as a string. Must be of length ``width`` and contain
107 only "1" and "0".
108 field_type (FieldType): The field type used to interpret the bits of the field.
110 Return:
111 :class:`.BitVector`: The bit vector object that was created.
112 """
113 bit_vector = BitVector(
114 name=name,
115 base_index=self.bit_index,
116 description=description,
117 width=width,
118 default_value=default_value,
119 field_type=field_type,
120 )
121 self.fields.append(bit_vector)
123 self.bit_index += bit_vector.width
124 if self.bit_index > 32:
125 raise ValueError(f'Maximum width exceeded for register "{self.name}"')
127 return bit_vector
129 @property
130 def default_value(self):
131 """
132 The default value of the register. Depends on the default values of it's fields.
134 Returns:
135 int: The default value.
136 """
137 default_value = 0
138 for field in self.fields:
139 default_value += field.default_value_uint * 2**field.base_index
140 return default_value
142 def get_field(self, name):
143 """
144 Get the field within this register that has the given name. Will raise exception if no
145 field matches.
147 Arguments:
148 name (str): The name of the field.
150 Returns:
151 :class:`.RegisterField`: The field.
152 """
153 for field in self.fields:
154 if field.name == name:
155 return field
157 raise ValueError(f'Could not find field "{name}" within register "{self.name}"')
159 @property
160 def address(self):
161 """
162 int: Byte address, within the register list, of this register.
163 """
164 return 4 * self.index
166 @property
167 def is_bus_readable(self):
168 """
169 True if the register is readable by bus. Based on the register type.
170 """
171 return self.mode in ["r", "r_w", "r_wpulse"]
173 @property
174 def is_bus_writeable(self):
175 """
176 True if the register is writeable by bus. Based on the register type.
177 """
178 return self.mode in ["w", "r_w", "wpulse", "r_wpulse"]
180 def __repr__(self):
181 return f"""{self.__class__.__name__}(\
182name={self.name},\
183index={self.index},\
184mode={self.mode},\
185description={self.description},\
186default_value={self.default_value},\
187fields={','.join([repr(field) for field in self.fields])},\
188)"""