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

'''Simple code that understands enough of otbn.hjson to get a memory layout

Each memory will have an associated "window" entry, which has an offset from
the start of the IP block's register space. This offset will be treated as an
LMA for this memory and these memory LMAs will be used uniformly in
OTBN-specific tooling. This avoids the result depending on the address layout
of the wider chip.

In particular, note that OTBN ELF binaries will use these LMAs (the VMAs are in
OTBN's address space, with both IMEM and DMEM starting at 0). A tool that takes
such binaries and incorporates them into a top-level image will need to do
address translation (essentially, just adding the base address of the OTBN IP
block).

'''

import os
import sys
from typing import Dict, List, Mapping, Tuple

import hjson  # type: ignore

# We use reggen to read the hjson file. Since that lives somewhere completely
# different from this script (and there aren't __init__.py files scattered all
# over the OpenTitan repository), we have to do sys.path hacks to find it.
_OLD_SYS_PATH = sys.path
try:
    _UTIL_PATH = os.path.join(os.path.dirname(__file__),
                              '..', '..', '..', '..', 'util')
    sys.path = [_UTIL_PATH] + _OLD_SYS_PATH
    from reggen.validate import checking_dict, validate   # type: ignore
finally:
    sys.path = _OLD_SYS_PATH


# An hjson dict is actually an OrderedDict, but typing/mypy support for that is
# a little spotty, so we'll use a generic Mapping type.
_HjsonDict = Mapping[str, object]

# A window is represented as (offset, size)
_Window = Tuple[int, int]


def load_registers(path: str) -> Tuple[int, List[_HjsonDict]]:
    '''Load hjson file at path with reggen

    Return its register width and list of registers.

    '''
    try:
        with open(path, 'r') as handle:
            obj = hjson.loads(handle.read(),
                              use_decimal=True,
                              object_pairs_hook=checking_dict)
    except ValueError as err:
        raise RuntimeError('Failed to parse {!r}: {}'.format(path, err))

    # Unconditionally run second validation pass
    num_errs = validate(obj)
    if num_errs:
        raise RuntimeError('Reggen second validation pass failed for {!r} '
                           '({} errors).'
                           .format(path, num_errs))

    reg_bit_width = int(obj.get('regwidth', 32))
    assert isinstance(reg_bit_width, int) and reg_bit_width >= 0
    reg_byte_width = reg_bit_width // 8

    # obj should be an OrderedDict and should contain a registers entry
    # (checked by validate). This is a list of registers which we'll return.
    # The validation code would also have exploded if it wasn't a list of
    # dictionaries, so we can assert the type safely.
    registers = obj['registers']
    assert isinstance(registers, list)
    return (reg_byte_width, registers)


def extract_windows(reg_byte_width: int,
                    registers: List[_HjsonDict]) -> Dict[str, _Window]:
    '''Make sense of the list of register definitions and extract memories'''

    # Conveniently, reggen's validate method stores 'genoffset' (the offset to
    # the start) for each window, so we can just look that up.
    windows = {}

    for reg in registers:
        assert isinstance(reg, dict)
        window = reg.get('window')
        if window is None:
            continue

        assert isinstance(window, dict)

        offset = window['genoffset']
        assert isinstance(offset, int)

        items = int(window['items'])
        window_name = window.get('name', 'Window at +{:#x}'.format(offset))
        assert isinstance(window_name, str)
        if window_name in windows:
            raise ValueError('Duplicate window entry with name {!r}.'
                             .format(window_name))

        windows[window_name] = (offset, items * reg_byte_width)

    return windows


def get_memory_layout() -> Dict[str, Tuple[int, int]]:
    '''Read otbn.hjson to get IMEM / DMEM layout

    Returns a dictionary with two entries, keyed 'IMEM' and 'DMEM'. The value
    at each entry is a pair (offset, size_in_bytes).

    '''
    hjson_path = os.path.join(os.path.dirname(__file__),
                              '..', 'data', 'otbn.hjson')
    reg_byte_width, registers = load_registers(hjson_path)
    windows = extract_windows(reg_byte_width, registers)

    xmem_names = {'IMEM', 'DMEM'}
    for name in xmem_names:
        if name not in windows:
            raise RuntimeError("otbn.hjson doesn't have a window called {}."
                               .format(name))
    if len(windows) != 2:
        raise RuntimeError("Unexpected windows in otbn.hjson: {}"
                           .format(list(set(windows.keys()) - xmem_names)))

    return windows


if __name__ == '__main__':
    for name, (off, width) in get_memory_layout().items():
        print('{}: {} bytes; LMA {:#x}'.format(name, width, off))
