# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
"""Enumerated types for fields
Generated by validation, used by backends
"""

from enum import Enum

from reggen.lib import check_str


class JsonEnum(Enum):
    def for_json(x) -> str:
        return str(x)


class SwWrAccess(JsonEnum):
    WR = 1
    NONE = 2


class SwRdAccess(JsonEnum):
    RD = 1
    RC = 2  # Special handling for port
    NONE = 3


class SwAccess(JsonEnum):
    RO = 1
    RW = 2
    WO = 3
    W1C = 4
    W1S = 5
    W0C = 6
    RC = 7
    R0W1C = 8
    NONE = 9


class HwAccess(JsonEnum):
    HRO = 1
    HRW = 2
    HWO = 3
    NONE = 4  # No access allowed


# swaccess permitted values
# text description, access enum, wr access enum, rd access enum, ok in window
SWACCESS_PERMITTED = {
    'none':  ("No access",                                              # noqa: E241
              SwAccess.NONE, SwWrAccess.NONE, SwRdAccess.NONE, False),  # noqa: E241
    'ro':    ("Read Only",                                              # noqa: E241
              SwAccess.RO,   SwWrAccess.NONE, SwRdAccess.RD,   True),   # noqa: E241
    'rc':    ("Read Only, reading clears",                              # noqa: E241
              SwAccess.RC,   SwWrAccess.WR,   SwRdAccess.RC,   False),  # noqa: E241
    'rw':    ("Read/Write",                                             # noqa: E241
              SwAccess.RW,   SwWrAccess.WR,   SwRdAccess.RD,   True),   # noqa: E241
    'r0w1c': ("Read zero, Write with 1 clears",                         # noqa: E241
              SwAccess.W1C,  SwWrAccess.WR,   SwRdAccess.NONE, False),  # noqa: E241
    'rw1s':  ("Read, Write with 1 sets",                                # noqa: E241
              SwAccess.W1S,  SwWrAccess.WR,   SwRdAccess.RD,   False),  # noqa: E241
    'rw1c':  ("Read, Write with 1 clears",                              # noqa: E241
              SwAccess.W1C,  SwWrAccess.WR,   SwRdAccess.RD,   False),  # noqa: E241
    'rw0c':  ("Read, Write with 0 clears",                              # noqa: E241
              SwAccess.W0C,  SwWrAccess.WR,   SwRdAccess.RD,   False),  # noqa: E241
    'wo':    ("Write Only",                                             # noqa: E241
              SwAccess.WO,   SwWrAccess.WR,   SwRdAccess.NONE, True)    # noqa: E241
}

# hwaccess permitted values
HWACCESS_PERMITTED = {
    'hro': ("Read Only", HwAccess.HRO),
    'hrw': ("Read/Write", HwAccess.HRW),
    'hwo': ("Write Only", HwAccess.HWO),
    'none': ("No Access Needed", HwAccess.NONE)
}


class SWAccess:
    def __init__(self, where: str, raw: object):
        self.key = check_str(raw, 'swaccess for {}'.format(where))
        try:
            self.value = SWACCESS_PERMITTED[self.key]
        except KeyError:
            raise ValueError('Unknown swaccess key, {}, for {}.'
                             .format(self.key, where)) from None

    def dv_rights(self) -> str:
        '''Return a UVM access string as used by uvm_field::set_access().'''
        if self.key == 'r0w1c':
            return 'W1C'
        return self.value[1].name

    def swrd(self) -> SwRdAccess:
        return self.value[3]

    def allows_read(self) -> bool:
        return self.value[3] != SwRdAccess.NONE

    def allows_write(self) -> bool:
        return self.value[2] == SwWrAccess.WR

    def needs_we(self) -> bool:
        '''Should the register for this field have a write-enable signal?

        This is almost the same as allows_write(), but doesn't return true for
        RC registers, which should use a read-enable signal (connected to their
        prim_subreg's we port).

        '''
        return self.value[1] != SwAccess.RC and self.allows_write()

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, SWAccess):
            return NotImplemented
        return (self.key == other.key) and (self.value == other.value)

    def __str__(self) -> str:
        return '{}: {}'.format(self.key, self.value)


class HWAccess:
    def __init__(self, where: str, raw: object):
        self.key = check_str(raw, 'hwaccess for {}'.format(where))
        try:
            self.value = HWACCESS_PERMITTED[self.key]
        except KeyError:
            raise ValueError('Unknown hwaccess key, {}, for {}.'
                             .format(self.key, where)) from None

    def allows_read(self) -> bool:
        return self.key in ['hro', 'hrw']

    def allows_write(self) -> bool:
        return self.key in ['hrw', 'hwo']

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, HWAccess):
            return NotImplemented
        return (self.key == other.key) and (self.value == other.value)

    def __str__(self) -> str:
        return '{}: {}'.format(self.key, self.value)
