# 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 pkg_resources import resource_filename

from .field_enums import HwAccess, SwAccess, SwRdAccess, SwWrAccess


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

    Field class contains necessary info to generate RTL code.
    It has two additional (tool generated) feidls, 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

    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


class Register():
    name = ""
    offset = 0
    hwqe = False
    hwre = False
    hwext = False  # External register
    resval = 0
    dvrights = "RO"  # Used by UVM REG only
    regwen = ""
    fields = []

    def __init__(self):
        self.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 = []


class Window():
    base_addr = 0
    limit_addr = 0
    n_bits = 0

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

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

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

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"]

    # 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 class
    """

    reg = Register()
    reg.name = 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()

    # Parsing Fields
    for f in obj["fields"]:
        field = parse_field(f, reg, len(obj["fields"]))
        if field != None:
            reg.fields.append(field)

    # TODO(eunchan): 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)

    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
        elif 'multireg' in r:
            for genr in r['multireg']['genregs']:
                reg = parse_reg(genr)
                if reg != None:
                    block.regs.append(reg)
            continue
        reg = parse_reg(r)
        if reg != None:
            block.regs.append(reg)
        # mdhayter -- moved logging into parse_regs

    # 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.tpl.sv'))
    reg_pkg_tpl = Template(
        filename=resource_filename('reggen', 'reg_pkg.tpl.sv'))

    # Generate pkg.sv with block name
    with open(outdir + "/" + block.name + "_reg_pkg.sv", 'w',
              encoding='UTF-8') as fout:
        fout.write(
            reg_pkg_tpl.render(block=block,
                               HwAccess=HwAccess,
                               SwRdAccess=SwRdAccess,
                               SwWrAccess=SwWrAccess))

    # Generate top.sv
    with open(outdir + "/" + block.name + "_reg_top.sv", 'w',
              encoding='UTF-8') as fout:
        fout.write(
            reg_top_tpl.render(block=block,
                               HwAccess=HwAccess,
                               SwRdAccess=SwRdAccess,
                               SwWrAccess=SwWrAccess))
