# 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"]
    f.shadowed = reg.shadowed

    # 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'])
        reg.shadowed = (obj["shadowed"] == "true")

        # 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 []

    block.hier_path = obj["hier_path"] if "hier_path" 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())
