#!/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

'''A simulator that runs one instruction at a time, reading from a REPL

The input language is simple (and intended to be generated by another program).
Input should appear with one command per line.

The valid commands are as follows. All arguments are shown here as <argname>.
The integer arguments are read with Python's int() function, so should be
prefixed with "0x" if they are hexadecimal.

    start <addr>         Set the PC to <addr> and start OTBN

    step                 Run one instruction. Print trace information to
                         stdout.

    run                  Run instructions until ecall or error. No trace
                         information.

    load_elf <path>      Load the ELF file at <path>, replacing current
                         contents of DMEM and IMEM.

    load_d <path>        Replace the current contents of DMEM with <path>
                         (read as an array of 32-bit little-endian words)

    load_i <path>        Replace the current contents of IMEM with <path>
                         (read as an array of 32-bit little-endian words)

    dump_d <path>        Write the current contents of DMEM to <path> (same
                         format as for load).

    print_regs           Write the contents of all registers to stdout (in hex)

'''

import sys
from typing import List

from sim.decode import decode_file
from sim.elf import load_elf
from sim.sim import OTBNSim


def read_word(arg_name: str, word_data: str, bits: int) -> int:
    '''Try to read an unsigned word of the specified bit length'''
    try:
        value = int(word_data, 0)
    except ValueError:
        raise ValueError('Failed to read {!r} as an integer for <{}> argument.'
                         .format(word_data, arg_name)) from None

    if value < 0 or value >> bits:
        raise ValueError('<{}> argument is {!r}: not representable in {!r} bits.'
                         .format(arg_name, word_data, bits))

    return value


def end_command() -> None:
    '''Print a single '.' to stdout and flush, ending the output for command'''
    print('.')
    sys.stdout.flush()


def on_start(sim: OTBNSim, args: List[str]) -> None:
    '''Jump to an address given as the (only) argument and start running'''
    if len(args) != 1:
        raise ValueError('start expects exactly 1 argument. Got {}.'
                         .format(args))

    addr = read_word('addr', args[0], 32)
    if addr & 3:
        raise ValueError('start address must be word-aligned. Got {:#08x}.'
                         .format(addr))
    print('START {:#08x}'.format(addr))
    sim.state.ext_regs.write('START_ADDR', addr, False)
    sim.state.ext_regs.commit()
    sim.start()


def on_step(sim: OTBNSim, args: List[str]) -> None:
    '''Step one instruction'''
    if len(args):
        raise ValueError('step expects zero arguments. Got {}.'
                         .format(args))

    pc = sim.state.pc
    assert 0 == pc & 3

    insn, changes = sim.step(verbose=False, collect_stats=False)

    if insn is None:
        print('STALL')
    else:
        print(f'E PC: {pc:#010x}, insn: {insn.raw:#010x}')
        print(f'# @{pc:#010x}: {insn.insn.mnemonic}')

    for change in changes:
        entry = change.rtl_trace()
        if entry is not None:
            print(entry)


def on_run(sim: OTBNSim, args: List[str]) -> None:
    '''Run until ecall or error'''
    if len(args):
        raise ValueError('run expects zero arguments. Got {}.'
                         .format(args))

    num_cycles = sim.run(verbose=False, collect_stats=False)
    print(' ran for {} cycles'.format(num_cycles))


def on_load_elf(sim: OTBNSim, args: List[str]) -> None:
    '''Load contents of ELF at path given by only argument'''
    if len(args) != 1:
        raise ValueError('load_elf expects exactly 1 argument. Got {}.'
                         .format(args))
    path = args[0]

    print('LOAD_ELF {!r}'.format(path))
    load_elf(sim, path)


def on_load_d(sim: OTBNSim, args: List[str]) -> None:
    '''Load contents of data memory from file at path given by only argument'''
    if len(args) != 1:
        raise ValueError('load_d expects exactly 1 argument. Got {}.'
                         .format(args))
    path = args[0]

    print('LOAD_D {!r}'.format(path))
    with open(path, 'rb') as handle:
        sim.load_data(handle.read())


def on_load_i(sim: OTBNSim, args: List[str]) -> None:
    '''Load contents of insn memory from file at path given by only argument'''
    if len(args) != 1:
        raise ValueError('load_i expects exactly 1 argument. Got {}.'
                         .format(args))
    path = args[0]

    print('LOAD_I {!r}'.format(path))
    sim.load_program(decode_file(0, path))


def on_dump_d(sim: OTBNSim, args: List[str]) -> None:
    '''Dump contents of data memory to file at path given by only argument'''
    if len(args) != 1:
        raise ValueError('dump_d expects exactly 1 argument. Got {}.'
                         .format(args))
    path = args[0]

    print('DUMP_D {!r}'.format(path))

    with open(path, 'wb') as handle:
        handle.write(sim.state.dmem.dump_le_words())


def on_print_regs(sim: OTBNSim, args: List[str]) -> None:
    '''Print registers to stdout'''
    if len(args):
        raise ValueError('print_regs expects zero arguments. Got {}.'
                         .format(args))

    print('PRINT_REGS')
    for idx, value in enumerate(sim.state.gprs.peek_unsigned_values()):
        print(' x{:<2} = 0x{:08x}'.format(idx, value))
    for idx, value in enumerate(sim.state.wdrs.peek_unsigned_values()):
        print(' w{:<2} = 0x{:064x}'.format(idx, value))


def on_print_call_stack(sim: OTBNSim, args: List[str]) -> None:
    '''Print call stack to stdout. First element is the bottom of the stack'''
    if len(args):
        raise ValueError('print_call_stack expects zero arguments. Got {}.'
                         .format(args))

    print('PRINT_CALL_STACK')
    for value in sim.state.peek_call_stack():
        print('0x{:08x}'.format(value))


def on_edn_rnd_data(sim: OTBNSim, args: List[str]) -> None:
    if len(args) != 1:
        raise ValueError('edn_rnd_data expects exactly 1 argument. Got {}.'
                         .format(args))

    edn_rnd_data = read_word('edn_rnd_data', args[0], 256)
    sim.state.set_rnd_data(edn_rnd_data)


def on_edn_urnd_reseed_complete(sim: OTBNSim, args: List[str]) -> None:
    if args:
        raise ValueError('edn_urnd_reseed_complete expects zero arguments. Got {}.'
                         .format(args))

    sim.state.set_urnd_reseed_complete()


_HANDLERS = {
    'start': on_start,
    'step': on_step,
    'run': on_run,
    'load_elf': on_load_elf,
    'load_d': on_load_d,
    'load_i': on_load_i,
    'dump_d': on_dump_d,
    'print_regs': on_print_regs,
    'print_call_stack': on_print_call_stack,
    'edn_rnd_data': on_edn_rnd_data,
    'edn_urnd_reseed_complete': on_edn_urnd_reseed_complete
}


def on_input(sim: OTBNSim, line: str) -> None:
    '''Process an input command'''
    words = line.split()

    # Just ignore empty lines
    if not words:
        return

    verb = words[0]
    handler = _HANDLERS.get(verb)
    if handler is None:
        raise RuntimeError('Unknown command: {!r}'.format(verb))

    handler(sim, words[1:])
    print('.')
    sys.stdout.flush()


def main() -> int:
    sim = OTBNSim()
    try:
        for line in sys.stdin:
            on_input(sim, line)
    except KeyboardInterrupt:
        print("Received shutdown request, ending OTBN simulation.")
        return 0
    return 0


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