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

from reggen.validate import val_types, check_keys
# For the reference
# val_types = {
#     'd': ["int", "integer (binary 0b, octal 0o, decimal, hex 0x)"],
#     'x': ["xint", "x for undefined otherwise int"],
#     'b': [
#         "bitrange", "bit number as decimal integer, \
#                     or bit-range as decimal integers msb:lsb"
#     ],
#     'l': ["list", "comma separated list enclosed in `[]`"],
#     'ln': ["name list", 'comma separated list enclosed in `[]` of '\
#            'one or more groups that have just name and dscr keys.'\
#            ' e.g. `{ name: "name", desc: "description"}`'],
#     'lnw': ["name list+", 'name list that optionally contains a width'],
#     'lp': ["parameter list", 'parameter list having default value optionally'],
#     'g': ["group", "comma separated group of key:value enclosed in `{}`"],
#     's': ["string", "string, typically short"],
#     't': ["text", "string, may be multi-line enclosed in `'''` "\
#           "may use `**bold**`, `*italic*` or `!!Reg` markup"],
#     'T': ["tuple", "tuple enclosed in ()"],
#     'pi': ["python int", "Native python type int (generated)"],
#     'pb': ["python Bool", "Native python type Bool (generated)"],
#     'pl': ["python list", "Native python type list (generated)"],
#     'pe': ["python enum", "Native python type enum (generated)"]
# }

# Required/optional field in top hjson
top_required = {
    'name': ['s', 'Top name'],
    'type': ['s', 'type of hjson. Shall be "top" always'],
    'clocks': ['l', 'list of clocks'],
    'module': ['l', 'list of modules to instantiate'],
    'memory': [
        'l', 'list of memories. At least one memory is needed to run \
               the software'
    ],
    'debug_mem_base_addr':
    ['d', 'Base address of RV_DM. Planned to move to \
module'],
    'xbar': ['l', 'List of the xbar used in the top'],
}

top_optional = {
    'interrupt_modules': ['l', 'list of the modules that connects to rv_plic'],
    'interrupt': ['lnw', 'interrupts (generated)'],
    'pinmux': ['g', 'pinmux definition if doesn\'t exist, tool uses defaults'],
    'padctrl':
    ['g', 'PADS instantiation, if doesn\'t exist, tool creates direct output'],
}

top_added = {}

pinmux_required = {}
pinmux_optional = {
    'dio_modules': ['l', 'List of Dedicated IO.'],
    'mio_modules': ['l', 'List of Multiplexing IO'],
    'nc_modules': ['l', 'List of NotConnected IO'],
}
pinmux_added = {
    'inputs': ['l', 'Full list of SoC inputs, `module_name.sig_name`'],
    'outputs': ['l', 'Full list of SoC outputs, `module_name.sig_name`'],
}

padctrl_required = {}
padctrl_optional = {
    'pads': ['l', 'List of pads'],
    'attr_default': ['l', 'List of the attribute']
}
padctrl_added = {}


def check_padctrl(top, prefix):
    error = check_keys(top["padctrl"], padctrl_required, padctrl_optional,
                       padctrl_added, prefix + " PadControl")
    return error


def check_pinmux(top, prefix):
    return 0

def check_resets(top, ipobjs, xbarobjs):
    # all defined reset nets
    reset_nets = [reset['name'] for reset in top['resets']]
    error = 0

    # Check reset port connection for all IPs
    for ipcfg in top['module']:
        log.info("Checking resets for %s" % ipcfg['name'].lower())
        ipdef = [ip for ip in ipobjs if ipcfg['type'] == ip['name'].lower()]
        error += check_rst_def(ipdef, ipcfg['type'])
        error += validate_reset(ipcfg, ipdef[0], reset_nets)

        if error:
            log.error("module reset checking failed")
            break

    # Check reset port connection for all xbars
    for xbarcfg in top['xbar']:
        log.info("Checking resets for %s" % xbarcfg['name'].lower())
        xbardef = [
            xbar for xbar in xbarobjs
            if xbarcfg['name'] == xbar['name'].lower()
        ]
        error += check_rst_def(xbardef, xbarcfg['name'])
        error += validate_reset(xbarcfg, xbardef[0], reset_nets, "xbar")

        if error:
            log.error("xbar reset checking failed")
            break

    return error

def check_rst_def(inst_def, name):
    error = 0
    if not inst_def:
        log.error("Could not find %s.hjson for" % name)
        error += 1

    if len(inst_def) > 1:
        log.error("Duplicate %s.hjson" % name)
        error += 1

    return error

# Checks the following
# For each defined reset connection in top*.hjson, there exists a defined port at the destination
# and defined reset net
# There are the same number of defined connections as there are ports
def validate_reset(top, inst, reset_nets, prefix=""):
    # Gather inst port list
    error = 0
    inst_port_list = []
    if 'reset_primary' not in inst.keys():
        log.info("%s %s does not have a reset_primary defined, default used" %
                 (prefix, inst['name']))
        inst_port_list.append("rst_ni")
    else:
        inst_port_list.append(inst['reset_primary'])

    if 'other_reset_list' in inst.keys():
        inst_port_list.extend(inst['other_reset_list'])
    log.info("%s %s resets are %s" %
             (prefix, inst['name'].lower(), inst_port_list))

    if len(top['reset_connections'].keys()) != len(inst_port_list):
        error += 1
        log.error("%s %s mismatched number of ports and nets" %
                  (prefix, inst['name']))

    missing_port = [
        port for port in top['reset_connections'].keys()
        if port not in inst_port_list
    ]

    if missing_port:
        error += 1
        log.error("%s %s Following reset ports do not exist:" %
                  (prefix, inst['name']))
        [log.error("%s" % port) for port in missing_port]

    missing_net = [
        net for port, net in top['reset_connections'].items()
        if net not in reset_nets
    ]

    if missing_net:
        error += 1
        log.error("%s %s Following reset nets do not exist:" %
                  (prefix, inst['name']))
        [log.error("%s" % net) for net in missing_net]

    return error


def validate_top(top, ipobjs, xbarobjs):
    # return as it is for now
    error = check_keys(top, top_required, top_optional, top_added, "top")

    if error != 0:
        log.error("Top HJSON has top level errors. Aborting")
        return top, error

    component = top['name']

    ## Reset check
    error += check_resets(top, ipobjs, xbarobjs)

    ## MODULE check

    ## MEMORY check

    ## RV_PLIC check

    ## PINMUX & PADS check
    if not "padctrl" in top:
        log.warning("padsctrl field doesn't exist in top. Skipping pads \
                     generation. Top input/output are directly connected from \
                     peripherals.")
    # Pads configuration check
    else:
        error = check_padctrl(top, component)

    if not "pinmux" in top:
        log.warning("Top {} has no 'pinmux' field. Please consider specifying \
                        pinmux and pads configuration")
        top["pinmux"] = {}
    # checking pinmux after pads as dio connects to PAD

    error += check_pinmux(top, component)

    ## XBAR check

    return top, error
