#!/usr/bin/env python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

'''Wrapper script to run the OTBN random instruction generator'''

import argparse
import json
import os
import random
import sys
from typing import Optional, cast

# Ensure that the OTBN utils directory is on sys.path. This means that RIG code
# can import modules like "shared.foo" and get the OTBN shared code.
_RIG_DIR = os.path.dirname(__file__)
_OTBN_DIR = os.path.normpath(os.path.join(_RIG_DIR, '../..'))
_OTBN_UTIL_DIR = os.path.join(_OTBN_DIR, 'util')
sys.path.append(_OTBN_UTIL_DIR)

from shared.insn_yaml import InsnsFile, load_insns_yaml  # noqa: E402

from rig.config import Config  # noqa: E402
from rig.init_data import InitData  # noqa: E402
from rig.rig import gen_program  # noqa: E402
from rig.snippet import Snippet  # noqa: E402


def get_insns_file() -> Optional[InsnsFile]:
    '''Load up insns.yml'''
    try:
        return load_insns_yaml()
    except RuntimeError as err:
        print(err, file=sys.stderr)
        return None


def get_named_config(name: str) -> Optional[Config]:
    cfg_dir = os.path.join(_RIG_DIR, 'rig/configs')
    try:
        return Config.load(cfg_dir, name)
    except RuntimeError as err:
        print(err, file=sys.stderr)
        return None


def gen_main(args: argparse.Namespace) -> int:
    '''Entry point for the gen subcommand'''
    random.seed(args.seed)

    insns_file = get_insns_file()
    if insns_file is None:
        return 1

    config = get_named_config(args.config)
    if config is None:
        return 1

    # Run the generator
    try:
        init_data, snippet, end_addr = gen_program(config,
                                                   args.size,
                                                   insns_file)
    except RuntimeError as err:
        print(err, file=sys.stderr)
        return 1

    # Write out the data and snippets to a JSON file
    ser_data = init_data.as_json()
    ser_snippet = snippet.to_json()
    ser = [ser_data, ser_snippet, end_addr]
    json.dump(ser, args.output)
    # Add a newline at end of output: json.dump doesn't, and it makes a
    # bit of a mess of some consoles.
    args.output.write('\n')

    return 0


def asm_main(args: argparse.Namespace) -> int:
    '''Entry point for the asm subcommand'''

    insns_file = get_insns_file()
    if insns_file is None:
        return 1

    # Load JSON
    try:
        json_data = json.load(args.snippets)
    except json.JSONDecodeError as err:
        print('Snippets file at {!r} is not valid JSON: {}.'
              .format(args.snippets.name, err),
              file=sys.stderr)
        return 1

    # Parse these to proper init data and snippet objects.
    try:
        if not (isinstance(json_data, list) and len(json_data) == 3):
            raise ValueError('Top-level structure should be a length 3 list.')

        json_init_data, json_snippet, json_end_addr = json_data
        init_data = InitData.read(json_init_data)
        snippet = Snippet.from_json(insns_file, [], json_snippet)
        if not isinstance(json_end_addr, int) or json_end_addr < 0:
            raise ValueError('end_addr should be an integer.')
        end_addr = json_end_addr
    except ValueError as err:
        print('Failed to parse snippets from {!r}: {}'
              .format(args.snippets.name, err),
              file=sys.stderr)
        return 1

    program = snippet.to_program()
    dsegs = init_data.as_segs()

    # Dump the assembly output, and the linker script too if we're writing to
    # something other than stdout.
    if args.output is None or args.output == '-':
        program.dump_asm(sys.stdout, dsegs)
    else:
        try:
            asm_path = args.output + '.s'
            with open(asm_path, 'w') as out_file:
                program.dump_asm(out_file, dsegs)
        except OSError as err:
            print('Failed to open asm output file {!r}: {}.'
                  .format(args.output, err),
                  file=sys.stderr)
            return 1

        try:
            ld_path = args.output + '.ld'
            with open(ld_path, 'w') as out_file:
                program.dump_linker_script(out_file, dsegs, end_addr)
        except OSError as err:
            print('Failed to open ld script output file {!r}: {}.'
                  .format(ld_path, err),
                  file=sys.stderr)
            return 1

    return 0


def main() -> int:
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(dest='cmd')
    subparsers.required = True

    gen = subparsers.add_parser('gen', help='Generate a random program')
    asm = subparsers.add_parser('asm', help='Convert snippets to assembly')

    gen.add_argument('--seed', type=int, default=0,
                     help='Random seed. Defaults to 0.')
    gen.add_argument('--size', type=int, default=100,
                     help=('Max number of instructions in stream. '
                           'Defaults to 100.'))
    gen.add_argument('--config', type=str, default='default',
                     help='Configuration to use')
    gen.add_argument('--output', '-o',
                     metavar='out',
                     type=argparse.FileType('w', encoding='UTF-8'),
                     default=sys.stdout,
                     help='Output filename')
    gen.set_defaults(func=gen_main)

    asm.add_argument('--output', '-o',
                     metavar='out',
                     help=('Base path for output filenames. Will generate '
                           'out.s with an assembly listing and out.ld with '
                           'a linker script. If this is not supplied, the '
                           'assembly (but no linker script) will be dumped '
                           'to stdout.'))
    asm.add_argument('snippets', metavar='path.json',
                     type=argparse.FileType('r'), nargs='?', default=sys.stdin,
                     help=('A JSON file of snippets, as generated by '
                           'otbn-rig gen.'))
    asm.set_defaults(func=asm_main)

    args = parser.parse_args()
    return cast(int, args.func(args))


if __name__ == '__main__':
    sys.exit(main())
