{%- macro field_class(node) %}
    {% if node.is_sw_readable and node.is_sw_writable %}
class {{get_fully_qualified_type_name(node)}}_cls({%- if 'encode' in node.list_properties() -%}FieldEnumReadWrite{%- else -%}FieldReadWrite{%- endif -%}):
    {% elif node.is_sw_readable and not node.is_sw_writable %}
class {{get_fully_qualified_type_name(node)}}_cls({%- if 'encode' in node.list_properties() -%}FieldEnumReadOnly{%- else -%}FieldReadOnly{%- endif -%}):
    {% elif not node.is_sw_readable and node.is_sw_writable %}
class {{get_fully_qualified_type_name(node)}}_cls({%- if 'encode' in node.list_properties() -%}FieldEnumWriteOnly{%- else -%}FieldWriteOnly{%- endif -%}):
    {% endif %}
    """
    Class to represent a register field in the register model

    {{get_table_block(node) | indent}}
    """

    {%- if 'encode' in node.list_properties() %}
    __enum_cls = {{get_fully_qualified_enum_type(node.get_property('encode'), top_node.parent)}}_enumcls
    {% endif %}

    __slots__ : List[str] = []

    {%- if 'encode' in node.list_properties() %}
    @property
    def enum_cls(self):
        """
        The enumeration class for this field
        """
        return self.__enum_cls

        {% if node.is_sw_readable %}
    def decode_read_value(self, value: int) -> {{get_fully_qualified_enum_type(node.get_property('encode'), top_node.parent)}}_enumcls:
        """
        extracts the field value from a register value, by applying the bit
        mask and shift needed and conversion to the enum associated with the
        field

        Args:
            value: value to decode, normally read from a register

        Returns:
            field value

        Raises:
            ValueError - if the value read back for the field can not be matched to the enum
        """
        field_value = super().decode_read_value(value)

        return self.enum_cls(field_value)

    def read(self) -> {{get_fully_qualified_enum_type(node.get_property('encode'), top_node.parent)}}_enumcls:
        """
        read the register and then perform the necessary actions, to report the
        value as the enumeration including:

        * application of bit mask
        * bit shifting
        * converting integer value to enum

        Returns:
            field value
        """
        reg_value = self.parent_register.read()
        return self.decode_read_value(reg_value)
        {% endif %}

        {% if node.is_sw_writable %}
    def encode_write_value(self, value: {{get_fully_qualified_enum_type(node.get_property('encode'), top_node.parent)}}_enumcls) -> int: # type: ignore[override]

        if not isinstance(value, self.enum_cls):
            raise TypeError('value must be an {{get_fully_qualified_enum_type(node.get_property('encode'), top_node.parent)}}_enumcls but got %s' % type(value))

        return super().encode_write_value(value.value)

    def write(self, value : {{get_fully_qualified_enum_type(node.get_property('encode'), top_node.parent)}}_enumcls) -> None: # type: ignore[override]

        if not isinstance(value, self.enum_cls):
            raise TypeError('value must be an {{get_fully_qualified_enum_type(node.get_property('encode'), top_node.parent)}}_enumcls but got %s' % type(value))

        super().write(value.value)
        {% endif %}

    @property
    def default(self) -> Optional[{{get_fully_qualified_enum_type(node.get_property('encode'), top_node.parent)}}_enumcls]:
        """
        The default value of the field

        This returns None:
        - if the field is not reset.
        - if the register resets to a signal value tht can not be determined
        """
        int_default = super().default

        if int_default is not None:
            return {{get_fully_qualified_enum_type(node.get_property('encode'), top_node.parent)}}_enumcls(int_default)

        return None
    {% endif %}

{%- endmacro -%}
