Coverage for hdl_registers/register_field.py: 87%
45 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# Standard libraries
11from abc import ABC, abstractmethod
13# Local folder libraries
14from .register_field_type import FieldType, Unsigned
16DEFAULT_FIELD_TYPE = Unsigned()
19class RegisterField(ABC):
21 """
22 Meta class for all register fields (bits, bit vectors, integers, ...).
23 Lists a few methods that must be implemented.
24 """
26 @property
27 def max_binary_value(self) -> int:
28 """
29 Get the maximum value, represented as a positive integer, that this
30 field can hold given its width.
32 Returns:
33 int: The maximum value.
34 """
35 return 2**self.width - 1
37 @property
38 def field_type(self) -> FieldType:
39 """
40 The field type (Unsigned, Signed, UnsignedFixedPoint, SignedFixedPoint...)
41 used to interpret the bits of the field.
43 Returns:
44 FieldType: The instanced FieldType subclass.
45 """
46 return DEFAULT_FIELD_TYPE # Default for all RegisterFields
48 @property
49 @abstractmethod
50 def width(self):
51 """
52 Return the width, in number of bits, that this field occupies.
54 Returns:
55 int: The width.
56 """
57 raise NotImplementedError("Must be implemented in child class")
59 @property
60 @abstractmethod
61 def base_index(self):
62 """
63 The index within the register for the lowest bit of this Field.
65 Returns:
66 int: The index.
67 """
68 raise NotImplementedError("Must be implemented in child class")
70 @property
71 @abstractmethod
72 def range(self):
73 """
74 Return the bits that this field occupies in a readable format.
75 The way it shall appear in documentation.
77 Returns:
78 str: The bit range.
79 """
80 raise NotImplementedError("Must be implemented in child class")
82 @property
83 @abstractmethod
84 def default_value_str(self):
85 """
86 Return a formatted string of the default value. The way it shall appear
87 in documentation.
89 Returns:
90 str: The default value.
91 """
92 raise NotImplementedError("Must be implemented in child class")
94 @property
95 @abstractmethod
96 def default_value_uint(self):
97 """
98 Return a the default value as an unsigned int.
100 Returns:
101 int: The default value.
102 """
103 raise NotImplementedError("Must be implemented in child class")
105 def get_value(self, register_value: int) -> float:
106 """
107 Get the value of this field, given the supplied register value.
108 Child classes might implement sanity checks on the value.
110 Arguments:
111 register_value (int): Value of the register that this field belongs to.
113 Returns:
114 float: The value of the field.
115 """
116 shift = self.base_index
118 mask_at_base = (1 << self.width) - 1
119 mask = mask_at_base << shift
121 value_unsigned = (register_value & mask) >> shift
122 field_value = self.field_type.convert_from_unsigned_binary(self.width, value_unsigned)
124 return field_value
126 def set_value(self, field_value: float) -> int:
127 """
128 Convert the supplied value into the bit-shifted unsigned integer ready
129 to be written to the register. The bits of the other fields in the
130 register are masked out and will be set to zero.
132 Arguments:
133 field_value (float) : Desired value to set the field to.
135 Returns:
136 int: the register value
137 """
138 value_unsigned = self.field_type.convert_to_unsigned_binary(self.width, field_value)
139 max_value = self.max_binary_value
140 if not 0 <= value_unsigned <= max_value:
141 raise ValueError(
142 f"Value: {value_unsigned} is invalid for unsigned of width {self.width}"
143 )
145 mask = max_value << self.base_index
146 value_shifted = value_unsigned << self.base_index
148 return value_shifted & mask