# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

from .field_enums import HwAccess, SwAccess, SwRdAccess, SwWrAccess


# helper funtion that strips trailing _number (used as multireg suffix) from name
# TODO: this is a workaround, should solve this in validate.py
def _get_basename(name):
    for (k, c) in enumerate(name[::-1]):
        if not str.isdigit(c):
            if c == "_":
                return name[0:len(name) - (k+1)]
            else:
                break;
    return ""


class Field():
    """Field in a register.

    Field class contains necessary info to generate RTL code.
    It has two additional (tool generated) fields, swrdaccess and swwraccess,
    which represent read and write type. This makes RTL generation code simpler.
    """
    name = ""  # required
    msb = 31  # required
    lsb = 0  # required
    resval = 0  # optional
    swaccess = SwAccess.NONE  # optional
    swrdaccess = SwRdAccess.NONE
    swwraccess = SwWrAccess.NONE
    hwaccess = HwAccess.HRO
    hwqe = False
    hwre = False
    hwext = False
    tags = []
    shadowed = False

    def __init__(self):
        self.name = ""  # required
        self.msb = 31  # required
        self.lsb = 0  # required
        self.resval = 0  # optional
        self.swaccess = SwAccess.NONE  # optional
        self.swrdaccess = SwRdAccess.NONE
        self.swwraccess = SwWrAccess.NONE
        self.hwaccess = HwAccess.HRO
        self.hwqe = False
        self.hwre = False
        self.hwext = False
        self.tags = []
        self.shadowed = False

    def get_n_bits(self, bittype=["q"]):
        n_bits = 0
        if "q" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HRO]:
            n_bits += self.msb - self.lsb + 1
        if "d" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HWO]:
            n_bits += self.msb - self.lsb + 1
        if "qe" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HRO]:
            n_bits += self.hwqe
        if "re" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HRO]:
            n_bits += self.hwre
        if "de" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HWO]:
            n_bits += not self.hwext
        return n_bits

    def get_fields_flat(self):
        return [self]

    def get_basename(self):
        return _get_basename(self.name)


class Reg():
    name = ""
    offset = 0
    hwqe = False
    hwre = False
    hwext = False  # External register
    resval = 0
    dvrights = "RO"  # Used by UVM REG only
    regwen = ""
    fields = []
    width = 0  # indicate register size
    ishomog = 0
    tags = []
    shadowed = False

    def __init__(self, name=""):
        self.name = name
        self.offset = 0
        self.hwqe = False
        self.hwre = False
        self.hwext = False  # External register
        self.resval = 0
        self.dvrights = "RO"  # Used by UVM REG only
        self.regwen = ""
        self.fields = []
        self.width = 0
        self.ishomog = 0
        self.tags = []
        self.shadowed = False

    def is_multi_reg(self):
        """Returns true if this is a multireg"""
        return False

    def get_n_bits(self, bittype=["q"]):
        """Returns number of bits in this register (including all multiregs and
        fields). By default this function counts read data bits (bittype "q"),
        but other bits such as "d", qe", "re", "de" can be counted as well by
        specifying them in the bittype list argument.
        """
        n_bits = 0
        for f in self.fields:
            n_bits += f.get_n_bits(bittype)
        return n_bits

    def get_fields_flat(self):
        """Returns a flat list of all the fields in this register"""
        fields = []
        for f in self.fields:
            fields += f.get_fields_flat()
        return fields

    def get_field_flat(self, linear_idx):
        """Returns a specific field at a linear index position in
        the flattened field list"""
        fields_flat = self.get_fields_flat()
        return fields_flat[linear_idx]

    def get_n_fields_flat(self):
        """Returns the number of fields contained in the flat field list"""
        return len(self.get_fields_flat())

    def get_regs_flat(self):
        """Returns a flat list containing all
        registers and subregisters"""
        if isinstance(self.fields[0], Field):
            return [self]
        else:
            regs = []
            for r in self.fields:
                regs += r.get_regs_flat()
            return regs

    def get_reg_flat(self, linear_index):
        """Returns a specific register at a linear index position in
        the flattened regiser list"""
        regs_flat = self.get_regs_flat()
        return regs_flat[linear_index]

    def get_n_regs_flat(self):
        """Returns the number of registers contained in
        the flat register list"""
        return len(self.get_regs_flat())

    def get_nested_dims(self):
        """Recursively get dimensions of nested registers (outputs a list)"""
        # return length of flattened field array if this is a regular register,
        # or if this is the last multiregister level in a nested multiregister
        if not isinstance(self, MultiReg):
            dims = [len(self.get_fields_flat())]
        if isinstance(self, MultiReg) and\
           not isinstance(self.fields[0], MultiReg):
            if self.ishomog:
                dims = [len(self.get_fields_flat())]
            else:
                dims = [len(self.fields)]
        else:
            # nested multiregister case
            dims = [len(self.fields)] + self.fields[0].get_nested_dims()
        return dims

    def get_nested_params(self):
        """Recursively get parameters of nested registers (outputs a list)"""
        params = []
        if isinstance(self, MultiReg):
            params += [self.param]
        if isinstance(self.fields[0], MultiReg):
            params += self.fields[0].get_nested_params()
        return params

    def get_basename(self):
        return _get_basename(self.name)


class MultiReg(Reg):
    param = ""

    def __init__(self, name):
        Reg.__init__(self, name)
        self.param = ""

    def is_multi_reg(self):
        """Returns true if this is a multireg"""
        return True


class Window():
    base_addr = 0
    limit_addr = 0
    n_bits = 0
    tags = []

    def __init__(self):
        self.base_addr = 0
        self.limit_addr = 0
        self.n_bits = 0
        self.tags = []


class Block():
    width = 32
    addr_width = 12
    base_addr = 0
    name = ""
    hier_path = ""
    regs = []
    wins = []
    blocks = []
    params = []
    tags = []

    def __init__(self):
        self.width = 32
        self.addr_width = 12
        self.base_addr = 0
        self.name = ""
        self.hier_path = ""
        self.regs = []
        self.wins = []
        self.blocks = []
        self.params = []
        self.tags = []

    def get_regs_flat(self):
        """Returns flattened register list
        """
        regs = []
        for r in self.regs:
            regs += r.get_regs_flat()
        return regs

    def get_n_bits(self, bittype=["q"]):
        """Returns number of bits in this block (including all multiregs and
        fields). By default this function counts read data bits (bittype "q"),
        but other bits such as "d", qe", "re", "de" can be counted as well by
        specifying them in the bittype list argument.
        """
        n_bits = 0
        for r in self.regs:
            n_bits += r.get_n_bits(bittype)
        return n_bits

    def get_n_regs_flat(self):
        return len(self.get_regs_flat())

    def contains_multiregs(self):
        """Returns true if there are multiregs in this block
        """
        for r in self.regs:
            if isinstance(r, MultiReg):
                return True
        return False
