# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
"""Generate SystemVerilog designs from validated register JSON tree
"""

import logging as log

from mako.template import Template
from mako import exceptions
from pkg_resources import resource_filename

from .data import Field, Reg, MultiReg, Window, Block
from .field_enums import HwAccess, SwRdAccess, SwWrAccess


def escape_name(name):
    return name.lower().replace(' ', '_')


def check_field_bool(obj, field, default):
    if field in obj:
        return True if obj[field] == "true" else False
    else:
        return default


def parse_field(obj, reg, nfields):
    """Convert OrderedDict field into Field class
    """
    f = Field()
    f.name = escape_name(obj["name"])
    # if name doesn't exist and only one field in a reg
    if f.name == "" and nfields == 1:
        f.name = reg.name

    # MSB, LSB
    f.lsb = obj["bitinfo"][2]
    f.msb = f.lsb + obj["bitinfo"][1] - 1

    f.swaccess = obj["genswaccess"]
    f.swrdaccess = obj["genswrdaccess"]
    f.swwraccess = obj["genswwraccess"]
    f.hwaccess = obj["genhwaccess"]
    f.hwqe = obj["genhwqe"]
    f.hwre = obj["genhwre"]
    f.hwext = reg.hwext
    f.tags = obj["tags"]

    # resval handling. `genresval` has zero value if `resval` field is defined
    # as unknown 'x'
    f.resval = obj["genresval"]

    return f


def parse_reg(obj):
    """Convert OrderedDict register into Register or MultiRegister object.
    Supports nested MultiRegisters.
    """
    if 'multireg' in obj:
        regs = []
        for genr in obj['multireg']['genregs']:
            regs += [parse_reg(genr)]
        # get register properties of the first register in the multireg and
        # copy them to the parent
        # since all regs in a multireg have the same props
        reg = MultiReg(regs[0].get_reg_flat(0))
        # since this is a multireg, the list of fields can
        # contain regs or multiregs
        reg.fields = regs
        # a homogenous multireg contains only one single field that is replicated
        reg.ishomog = len(obj['multireg']['fields']) == 1
        # TODO: need to rework this once the underlying JSON has been changed
        reg.name = escape_name(obj['multireg']['name'])
        # TODO: need to reference proper param here such that it can be used
        # in the package template for the array declaration
        # reg.param = ...
    else:
        reg = Reg(escape_name(obj['name']))
        reg.offset = obj["genoffset"]
        reg.fields = []

        reg.hwext = (obj['hwext'] == "true")
        reg.hwqe = (obj["hwqe"] == "true")
        reg.hwre = (obj["hwre"] == "true")
        reg.resval = obj["genresval"]
        reg.dvrights = obj["gendvrights"]
        reg.regwen = obj["regwen"].lower()
        reg.ishomog = len(obj['fields']) == 1
        reg.tags = (obj['tags'])

        # Parsing Fields
        for f in obj["fields"]:
            field = parse_field(f, reg, len(obj["fields"]))
            if field is not None:
                reg.fields.append(field)
                reg.width = max(reg.width, field.msb + 1)

        # TODO: Field bitfield overlapping check
        log.info("R[0x%04x]: %s ", reg.offset, reg.name)
        for f in reg.fields:
            log.info("  F[%2d:%2d]: %s", f.msb, f.lsb, f.name)

    return reg


def parse_win(obj, width):
    # Convert register window fields into Window class
    # base_addr : genoffset
    # limit_addr : genoffset + items*width
    win = Window()
    win.name = obj["name"]
    win.base_addr = obj["genoffset"]
    win.limit_addr = obj["genoffset"] + int(obj["items"]) * (width // 8)
    win.dvrights = obj["swaccess"]
    win.n_bits = obj["genvalidbits"]

    # TODO: Generate warnings of `noalign` or `unusual`
    return win


def json_to_reg(obj):
    """Converts JSON OrderedDict into structure having useful information for
    Template to use.

    Main purpose of this function is:
        - Add Offset value based on auto calculation
        - Prepare Systemverilog data structure to generate _pkg file
    """
    block = Block()

    # Name
    block.name = escape_name(obj["name"])
    log.info("Processing module: %s", block.name)

    block.width = int(obj["regwidth"], 0)

    if block.width != 32 and block.width != 64:
        log.error(
            "Current reggen tool doesn't support field width that is not 32 nor 64"
        )

    log.info("Data Width is set to %d bits", block.width)

    block.params = obj["param_list"] if "param_list" in obj else []

    for r in obj["registers"]:
        # Check if any exception condition hit
        if 'reserved' in r:
            continue
        elif 'skipto' in r:
            continue
        elif 'sameaddr' in r:
            log.error("Current tool doesn't support 'sameaddr' type")
            continue
        elif 'window' in r:
            win = parse_win(r['window'], block.width)
            if win is not None:
                block.wins.append(win)
            continue

        block.regs += [parse_reg(r)]

    # Last offset and calculate space
    #  Later on, it could use block.regs[-1].genoffset
    if "space" in obj:
        block.addr_width = int(obj["space"], 0).bit_length()
    else:
        block.addr_width = (obj["gensize"] - 1).bit_length()

    return block


def gen_rtl(obj, outdir):
    # obj: OrderedDict

    block = json_to_reg(obj)

    # Read Register templates
    reg_top_tpl = Template(
        filename=resource_filename('reggen', 'reg_top.sv.tpl'))
    reg_pkg_tpl = Template(
        filename=resource_filename('reggen', 'reg_pkg.sv.tpl'))

    # Generate pkg.sv with block name
    with open(outdir + "/" + block.name + "_reg_pkg.sv", 'w',
              encoding='UTF-8') as fout:
        try:
            fout.write(
                reg_pkg_tpl.render(block=block,
                                   HwAccess=HwAccess,
                                   SwRdAccess=SwRdAccess,
                                   SwWrAccess=SwWrAccess))
        except:  # noqa: F722 for template Exception handling
            log.error(exceptions.text_error_template().render())

    # Generate top.sv
    with open(outdir + "/" + block.name + "_reg_top.sv", 'w',
              encoding='UTF-8') as fout:
        try:
            fout.write(
                reg_top_tpl.render(block=block,
                                   HwAccess=HwAccess,
                                   SwRdAccess=SwRdAccess,
                                   SwWrAccess=SwWrAccess))
        except:  # noqa: F722 for template Exception handling
            log.error(exceptions.text_error_template().render())
