# 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
import operator
import sys

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

from .data import *
from .field_enums import HwAccess, SwAccess, 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

    #assert not 'swaccess' in obj, "R[%s] F[%s]: SwAccess in Field not supported" % (reg.name, f.name)
    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

    # 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

        # Parsing Fields
        for f in obj["fields"]:
            field = parse_field(f, reg, len(obj["fields"]))
            if field != 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 != 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:
            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:
            log.error(exceptions.text_error_template().render())
