//
// Copyright (c) 2010-2024 Antmicro
//
// This file is licensed under the MIT License.
// Full license text is available in 'licenses/MIT.txt'.
//
//
// Copyright (c) 2024 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
//

// This file is derived from ReNode plugin sources, but has been modified
// so that it can be used as a plugin that interfaces with an mpact based
// simulator that implement the mpact_renode "C" linkage interface.

using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Collections.Generic;
using System.Collections.Concurrent;
using Antmicro.Renode.Core;
using Antmicro.Renode.Debugging;
using Antmicro.Renode.Exceptions;
using Antmicro.Renode.Hooks;
using Antmicro.Renode.Logging;
using Antmicro.Renode.Peripherals;
using Antmicro.Renode.Peripherals.Bus;
using Antmicro.Renode.Peripherals.CPU;
using Antmicro.Renode.Peripherals.Timers;
using Antmicro.Renode.Peripherals.CPU.Disassembler;
using Antmicro.Renode.Peripherals.CPU.Registers;
using Antmicro.Renode.Utilities;
using Antmicro.Renode.Time;
using Antmicro.Renode.Utilities.Binding;
using ELFSharp.ELF;
using ELFSharp.UImage;

namespace Antmicro.Renode.Peripherals.MpactCPU {

// This interface is implemented by MpactCheriotCPU and used by
// MpactCheriotPeripheral to access memory in mpact_cheriot simulator
public interface IMpactPeripheral :  IBytePeripheral, IWordPeripheral,
                                     IDoubleWordPeripheral,
                                     IQuadWordPeripheral,
                                     IMultibyteWritePeripheral {}


// Struct containing info for loading binary image files.
public struct BinFileLoadInfo {
    public string file_name;
    public UInt64 load_address;
    public UInt64 entry_point;
}

// The MpactCPU class. This class derives from BaseCPU, which implements
// a CPU in ReNode. It is the base implementation of the interface between
// ReNode and the mpact_sim based simulators.
public class MpactBaseCPU : BaseCPU, ICPUWithRegisters,
                            IGPIOReceiver, ITimeSink,
                            IDisposable, IMpactPeripheral {

    // Structure for ReNode register information that is obtained from the
    // simulator.
    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)]
    private struct RegInfo {
        [FieldOffset(0)]
        public Int32 index;
        [FieldOffset(4)]
        public Int32 width;
        [FieldOffset(8)]
        public bool isGeneral;
        [FieldOffset(9)]
        public bool isReadOnly;
    }

    public MpactBaseCPU(uint id, UInt64 memoryBase, UInt64 memorySize,
                    string cpuType, IMachine machine, Endianess endianness,
                    CpuBitness bitness = CpuBitness.Bits32)
        : base(id, cpuType, machine, endianness, bitness) {
        this.cpu_type = cpuType;
        this.memoryBase = memoryBase;
        this.memorySize = memorySize;
        // Allocate space for marshaling data to/from simulator.
        error_ptr = Marshal.AllocHGlobal(4);
        value_ptr = Marshal.AllocHGlobal(8);
        reg_info_ptr = Marshal.AllocHGlobal(Marshal.SizeOf<RegInfo>());
        string_ptr = Marshal.AllocHGlobal(maxStringLen);
    }

    ~MpactBaseCPU() {
        Marshal.FreeHGlobal(error_ptr);
        Marshal.FreeHGlobal(value_ptr);
        Marshal.FreeHGlobal(reg_info_ptr);
        Marshal.FreeHGlobal(string_ptr);
    }


    public override string Architecture { get { return "MpactSim";} }

    public virtual void SetMpactConfig(List<string> config_names,
		               List<string> config_values) {
        config_names.Add("memoryBase");
        config_names.Add("memorySize");
        config_values.Add("0x" + memoryBase.ToString("X"));
        config_values.Add("0x" + memorySize.ToString("X"));
        if (cli_port != 0) {
            config_names.Add("cliPort");
            config_values.Add("0x" + cli_port.ToString("X"));
                config_names.Add("waitForCLI");
            config_values.Add("0x" + (wait_for_cli ? 1 : 0).ToString("X"));
        }
    }

    public override void Start() {
        base.Start();

        // Set up configuration array.
        var config_names = new List<string>();
        var config_values = new List<string>();
	SetMpactConfig(config_names, config_values);
	// Configure mpact sim.
        Int32 cfg_res = set_config(mpact_id, config_names.ToArray(),
                                   config_values.ToArray(), config_names.Count);
        if (cfg_res < 0) {
            LogAndThrowRE("Failed to set configuration information");
        }
        // Load executable file, symbols only from executable file, or bin
	// file if specified. Use symbols load if the executable is loaded
	// by the system.
        this.Log(LogLevel.Info, "symbol_file: '" + symbol_file + "'");
        if (!executable_file.Equals("")) {
            var entry_point = load_elf(mpact_id, executable_file,
                                       /*for_symbols_only=*/false,
                                       error_ptr);
            Int32 result = Marshal.ReadInt32(error_ptr);
            if (result < 0) {
                LogAndThrowRE("Failed to load executable");
            }
            PC = entry_point;
        } else if (!symbol_file.Equals("")) {
            this.Log(LogLevel.Info, "loading symbol_file: '" + symbol_file + "'");
            load_elf(mpact_id, symbol_file, /*for_symbols_only=*/true,
                     error_ptr);
            Int32 result = Marshal.ReadInt32(error_ptr);
            if (result < 0) {
                LogAndThrowRE("Failed to load symbols");
            }
        } else if (!bin_file_info.file_name.Equals("")) {
            Int32 res = load_image(mpact_id, bin_file_info.file_name,
                                   bin_file_info.load_address);
            if (res < 0) {
                LogAndThrowRE("Failed to load binary image");
            }
            PC = bin_file_info.entry_point;
        }
    }

    public override void Reset() {
        base.Reset();
        instructionsExecutedThisRound = 0;
        totalExecutedInstructions = 0;
        // Call simulator to reset.
        reset(mpact_id);
    }

    public override void Dispose() {
        base.Dispose();
        // Cleanup: simulator and any unmanaged resources.
        this.Log(LogLevel.Info, "destruct mpact");
        destruct(mpact_id);
        this.Log(LogLevel.Info, "done");
    }

    public string CpuLibraryPath {
        get {
          return cpu_library_path;
        }
        set {
                this.Log(LogLevel.Info, "Lib: " + value);
            if (String.IsNullOrWhiteSpace(value)) {
                cpu_library_path = value;
                return;
            }
            if (cpu_library_bound) {
                LogAndThrowRE("CPU library already bound to: "
                              + cpu_library_path);
            }
            cpu_library_path = value;
            try {
                binder = new NativeBinder(this, cpu_library_path);
            }
            catch (System.Exception e) {
                LogAndThrowRE("Failed to load CPU library: " + e.Message);
            }
            cpu_library_bound = true;

            // Instantiate the simulator, passing in callbacks to read and write
            // from/to the system bus.
            read_sysmem_delegate =
                    new FuncInt32UInt64IntPtrInt32_(ReadSysMemory);
            write_sysmem_delegate =
                    new FuncInt32UInt64IntPtrInt32_(WriteSysMemory);
            mpact_id = construct_with_sysbus(cpu_type, maxStringLen,
                                             read_sysmem_delegate,
                                             write_sysmem_delegate);
            if (mpact_id < 0) {
                LogAndThrowRE("Failed to create simulator instance");
            }
        }
    }

    public string ExecutableFile {
        get => executable_file;
        set => executable_file = value;
    }

    public string SymbolFile {
        get => symbol_file;
        set => symbol_file = value;
    }

    public BinFileLoadInfo BinFileInfo {
        get => bin_file_info;
        set => bin_file_info = value;
    }

    public ushort CLIPort { get => cli_port; set => cli_port = value; }

    public bool WaitForCLI {
        get => wait_for_cli;
        set => wait_for_cli = value;
    }

    public override ulong ExecutedInstructions => totalExecutedInstructions;

    public override ExecutionMode ExecutionMode {
        get { return executionMode; }
        set {
            lock(singleStepSynchronizer.Guard) {
                if (executionMode == value) return;

                executionMode = value;

                singleStepSynchronizer.Enabled = IsSingleStepMode;
                UpdateHaltedState();
            }
        }
    }

    [Register]
    public override RegisterValue PC {
        get {
            if (registerMap.Count == 0) {
                GetMpactRegisters();
            }
	    return GetRegister(PC_ID);
        }

        set {
            Int32 error = write_register(mpact_id, PC_ID, value);
            if (error < 0) {
                this.Log(LogLevel.Error, "Failed to write PC");
            }
        }
    }

    public override ExecutionResult ExecuteInstructions(
                    ulong numberOfInstructionsToExecute,
                    out ulong numberOfExecutedInstructions) {
        UInt64 instructionsExecutedThisRound = 0UL;
        ExecutionResult result = ExecutionResult.Ok;
        try {
            // Invoke simulator for the number of instructions.
            instructionsExecutedThisRound =
                    step(mpact_id, numberOfInstructionsToExecute, error_ptr);
            // Parse the result.
            Int32 step_result = Marshal.ReadInt32(error_ptr);
            switch (step_result) {
                case -1:
                    result = ExecutionResult.Aborted;
                    break;
                case 0:
                    result = ExecutionResult.Ok;
                    break;
                case 1:
                    result = ExecutionResult.Interrupted;
                    break;
                case 2:
                    result = ExecutionResult.WaitingForInterrupt;
                    break;
                case 3:
                    result = ExecutionResult.StoppedAtBreakpoint;
                    break;
                case 4:
                    result = ExecutionResult.StoppedAtWatchpoint;
                    break;
                case 5:
                    result = ExecutionResult.ExternalMmuFault;
                    break;
                default:
                    LogAndThrowRE("Unknown return value from step - "
                                  + step_result);
                    break;
                }
        }
        catch (Exception) {
            this.NoisyLog("CPU exception detected, halting.");
            InvokeHalted(new HaltArguments(HaltReason.Abort, this));
            return ExecutionResult.Aborted;
            }
        finally {
            numberOfExecutedInstructions = instructionsExecutedThisRound;
            totalExecutedInstructions += instructionsExecutedThisRound;
        }
        return result;
    }

    // ICPUWithRegisters methods implementations.
    public  void SetRegister(int register, RegisterValue value) {
        var status = write_register((Int32)mpact_id, (Int32)register,
                                    (UInt64)value);
        if (status < 0) {
            LogAndThrowRE("Failed to write register " + register);
        }
    }

    public  void SetRegisterUnsafe(int register, RegisterValue value) {
        SetRegister(register, value);
    }

    public  RegisterValue GetRegister(int register) {
        var status = read_register(mpact_id, register, value_ptr);
        if (status < 0) {
            LogAndThrowRE("Failed to read register " + register);
        }
        Int64 value = Marshal.ReadInt64(value_ptr);
        CPURegister cpu_register;
        if (registerMap.TryGetValue(register, out cpu_register)) {
            var width = cpu_register.Width;
            switch (width) {
                case 8: return (byte)value;
                case 16: return (ushort)value;
                case 32: return (uint)value;
                case 64: return (ulong)value;
                default:
                    LogAndThrowRE("Unexpected register width: {width}");
                    break;
            }
        } else {
	    string msg = $"Unknown register id: {register} not found";
            LogAndThrowRE(msg);
        }
        return (ulong)0;
    }

    public  RegisterValue GetRegisterUnsafe(int register) {
        return GetRegister(register);
    }

    protected void GetMpactRegisters() {
        if (registerMap.Count != 0) return;
        Int32 num_regs = get_reg_info_size(mpact_id);
        for (Int32 i = 0; i < num_regs; i++) {
            Int32 result = get_reg_info(mpact_id, i, string_ptr, reg_info_ptr);
            if (result < 0) {
                this.Log(LogLevel.Error,
                         "Failed to get register info for index " + i);
                continue;
            }
            var reg_info = Marshal.PtrToStructure<RegInfo>(reg_info_ptr);
            var cpu_reg = new CPURegister(reg_info.index, reg_info.width,
                                          reg_info.isGeneral,
                                          reg_info.isReadOnly);
            var reg_name = Marshal.PtrToStringAuto(string_ptr);
            registerMap.Add(reg_info.index, cpu_reg);
            registerNamesMap.Add(reg_name, reg_info.index);
        }
    }

    public  IEnumerable<CPURegister> GetRegisters() {
        if (registerMap.Count == 0) {
            GetMpactRegisters();
        }
        return registerMap.Values.OrderBy(x => x.Index);
    }

    public new string[,] GetRegistersValues() {
        if (registerMap.Count == 0) {
            GetMpactRegisters();
        }
        var result = new Dictionary<string, ulong>();
        foreach (var reg in registerNamesMap) {
            var status = read_register(mpact_id, reg.Value, value_ptr);
            if (status < 0) continue;
            Int64 value = Marshal.ReadInt64(value_ptr);
            result.Add(reg.Key, Convert.ToUInt64(value));
        }
        var table = new Table().AddRow("Name", "Value");
        table.AddRows(result, x=> x.Key, x=> "0x{0:X}".FormatWith(x.Value));
        return table.ToArray();
    }

    private void LogAndThrowRE(string info) {
        this.Log(LogLevel.Error, info);
        throw new RecoverableException(info);
    }

    public Int32 LoadImageFile(String file_name, UInt64 address) {
        return load_image(mpact_id, file_name, address);
    }

    public void OnGPIO(int number, bool value) {
        if (mpact_id < 0) {
            this.Log(LogLevel.Noisy,
                     "OnGPIO: no simulator, discard gpio {0}:{1}", number,
                     value);
            return;
        }
        Int32 status = set_irq_value(mpact_id, number, value);
        if (status < 0) {
            Console.Error.WriteLine("Failure in setting irq value");
        }
    }

    public Int32 ReadSysMemory(UInt64 address, IntPtr buffer, Int32 length) {
        // Read from System Bus.
        switch (length) {
            case 1:
                var data8 = new byte[length];
                data8[0] = machine.SystemBus.ReadByte(address, this);
                Marshal.Copy(data8, 0, buffer, length);
                break;
            case 2:
                var data16 = new Int16[1];
                data16[0] = (Int16) machine.SystemBus.ReadWord(address, this);
                Marshal.Copy(data16, 0, buffer, 1);
                break;
            case 4:
                var data32 = new Int32[1];
                data32[0] = (Int32) machine.SystemBus.ReadDoubleWord(address,
                                                                     this);
                Marshal.Copy(data32, 0, buffer, 1);
                break;
            case 8:
                var data64 = new Int64[1];
                data64[0] = (Int64) machine.SystemBus.ReadQuadWord(address,
                                                                   this);
                Marshal.Copy(data64, 0, buffer, 1);
                break;
            default:
                var dataN = new byte[length];
                machine.SystemBus.ReadBytes(address, length, dataN, 0, false,
                                            this);
                Marshal.Copy(dataN, 0, buffer, length);
                break;
        }
        return length;
    }

    public Int32 WriteSysMemory(UInt64 address, IntPtr buffer, Int32 length) {
        switch (length) {
            case 1:
                var data8 = new byte[1];
                Marshal.Copy(buffer, data8, 0, 1);
                machine.SystemBus.WriteByte(address, data8[0], this);
                break;
            case 2:
                var data16 = new Int16[1];
                Marshal.Copy(buffer, data16, 0, 1);
                machine.SystemBus.WriteWord(address, (ushort)data16[0], this);
                break;
            case 4:
                var data32 = new Int32[1];
                Marshal.Copy(buffer, data32, 0, 1);
                machine.SystemBus.WriteDoubleWord(address, (uint)data32[0],
                                                  this);
                break;
            case 8:
                var data64 = new Int64[1];
                Marshal.Copy(buffer, data64, 0, 1);
                machine.SystemBus.WriteQuadWord(address, (ulong)data64[0],
                                                this);
                break;
            default:
                var dataN = new byte[length];
                Marshal.Copy(buffer, dataN, 0, length);
                machine.SystemBus.WriteBytes(dataN, address);
                break;
        }
        return length;
    }

    // IMpactPeripheral methods.
    public void WriteByte(long address, byte value) {
        var data8 = new byte[1];
        data8[0] = (byte) value;
        Marshal.Copy(data8, 0, value_ptr, 1);
        write_memory(mpact_id, (UInt64) address, value_ptr, 1);
    }

    public byte ReadByte(long address) {
        var data8 = new byte[1];
        read_memory(mpact_id, (UInt64) address, value_ptr, 1);
        Marshal.Copy(value_ptr, data8, 0, 1);
        return (byte) data8[0];
    }

    public void WriteWord(long address, ushort value) {
        var data16 = new Int16[1];
        data16[0] = (Int16) value;
        Marshal.Copy(data16, 0, value_ptr, 1);
        write_memory(mpact_id, (UInt64) address, value_ptr, 2);
    }

    public ushort ReadWord(long address) {
        var data16 = new Int16[1];
        read_memory(mpact_id, (UInt64) address, value_ptr, 2);
        Marshal.Copy(value_ptr, data16, 0, 1);
        return (ushort) data16[0];
    }

    public void WriteDoubleWord(long address, uint value) {
        var data32 = new Int32[1];
        data32[0] = (Int32) value;
        Marshal.Copy(data32, 0, value_ptr, 1);
        write_memory(mpact_id, (UInt64) address, value_ptr, 4);
    }

    public uint ReadDoubleWord(long address) {
        var data32 = new Int32[1];
        read_memory(mpact_id, (UInt64) address, value_ptr, 4);
        Marshal.Copy(value_ptr, data32, 0, 1);
        return (uint) data32[0];
    }

    public void WriteQuadWord(long address, ulong value) {
        var data64 = new Int64[1];
        data64[0] = (Int64) value;
        Marshal.Copy(data64, 0, value_ptr, 1);
        write_memory(mpact_id, (UInt64) address, value_ptr, 8);
    }

    public ulong ReadQuadWord(long address) {
        var data64 = new Int64[1];
        read_memory(mpact_id, (UInt64) address, value_ptr, 8);
        Marshal.Copy(value_ptr, data64, 0, 1);
        return (ulong) data64[0];
    }

    public byte[] ReadBytes(long offset, int count, ICPU context = null) {
        var bytes = new byte[count];
        var byte_array_ptr = Marshal.AllocHGlobal(count);
        read_memory(mpact_id, (UInt64) offset, byte_array_ptr, count);
        Marshal.Copy(value_ptr, bytes, 0, count);
        Marshal.FreeHGlobal(byte_array_ptr);
        return bytes;
    }

    public void WriteBytes(long offset, byte[] array, int startingIndex,
                           int count, ICPU context = null) {
        var byte_array_ptr = Marshal.AllocHGlobal(count);
        Marshal.Copy(array, startingIndex, byte_array_ptr, count);
        write_memory(mpact_id, (UInt64) offset, byte_array_ptr, count);
        Marshal.FreeHGlobal(byte_array_ptr);
    }

    // End of IMpactPeripheral methods.
    protected Dictionary<string, Int32>
                registerNamesMap = new Dictionary<string, Int32>();

    private ushort cli_port = 0;
    private bool wait_for_cli = true;
    private UInt64 size = 0;
    private List<GDBFeatureDescriptor>
                gdbFeatures = new List<GDBFeatureDescriptor>();
    private UInt64 memoryBase;
    private UInt64 memorySize;
    private Dictionary<Int32, CPURegister>
                registerMap = new Dictionary<Int32, CPURegister>();
    private string executable_file = "";
    private string symbol_file = "";
    private BinFileLoadInfo
                bin_file_info = new BinFileLoadInfo {file_name = "",
                                                     load_address = 0,
                                                       entry_point = 0};
    private string cpu_library_path = "";
    private bool cpu_library_bound = false;
    private NativeBinder binder;
    private readonly object nativeLock;
    private readonly Int32 maxStringLen = 32;

    // Pointers used in marshaling data to/from the simulator library.
    private IntPtr value_ptr {get; set;}
    private IntPtr error_ptr {get; set;}
    private IntPtr reg_info_ptr {get; set;}
    private IntPtr string_ptr {get; set;}

    // Declare some additional function signatures.
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 WriteRegister(Int32 param0, Int32 param1, UInt64 param2);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 ReadRegister(Int32 param0, Int32 param1, IntPtr param2);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 MemoryAccess(Int32 param0, UInt64 param1, IntPtr param2, Int32 param3);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate UInt64 Step(Int32 param0, UInt64 param1, IntPtr param2);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 LoadImage(Int32 param0, String param1, UInt64 param2);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 GetRegInfoSize(Int32 param0);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 GetRegInfo(Int32 param0, Int32 param1, IntPtr param2, IntPtr param3);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 FuncInt32UInt64IntPtrInt32_(UInt64 param0, IntPtr param1, Int32 param2);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 ConnectWithSysbus(string param0, Int32 param1, Int32 param2,
                                            FuncInt32UInt64IntPtrInt32_ param3,
                                            FuncInt32UInt64IntPtrInt32_ param4);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 ConstructWithSysbus(string param0, Int32 param1,
                                              FuncInt32UInt64IntPtrInt32_ param2,
                                              FuncInt32UInt64IntPtrInt32_ param3);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 SetConfig(Int32 param0, string[] param1,
                                    string[] param2, Int32 param3);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 SetIrqValue(Int32 param0, Int32 param1, bool param2);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate UInt64 LoadElf(Int32 param0, string param1, bool param2,
                                   IntPtr param3);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void ActionInt32_(Int32 param0);

    // Int32 read_sysmem_delegate(UInt64 address, IntPtr buffer, Int32 size)
    private FuncInt32UInt64IntPtrInt32_ read_sysmem_delegate;
    // Int32 write_sysmem_delegate(UInt64 address, IntPtr buffer, Int32 size)
    private FuncInt32UInt64IntPtrInt32_ write_sysmem_delegate;

    // Functions that are imported from the mpact sim library.
#pragma warning disable 649
    [Import(UseExceptionWrapper = false)]
    // Int32 construct_with_sysbus(string cpu_type, Int32 id,
    //                             Int32 read_callback(UInt64, IntPtr, Int32),
    //                             Int32 write_callback(UInt64, IntPtr, Int32));
    private ConstructWithSysbus construct_with_sysbus;

    [Import(UseExceptionWrapper = false)]
    // Int32 connect_with_sybsus(string cpu_type, Int32 id,
    //                           Int32 read_callback(UInt64, IntPtr, Int32),
    //                           Int32 write_callback(UInt64, IntPtr, Int32));
    private ConnectWithSysbus connect_with_sysbus;

    [Import(UseExceptionWrapper = false)]
    // void destruct(Int32 id);
    private ActionInt32_ destruct;

    [Import(UseExceptionWrapper = false)]
    // void reset(Int32 id);
    private ActionInt32_ reset;

    [Import(UseExceptionWrapper = false)]
    // Int32 get_reg_info_size(Int32 id)
    private GetRegInfoSize get_reg_info_size;

    [Import(UseExceptionWrapper = false)]
    // Int32 get_reg_info(Int32 id, IntPtr *name, IntPtr *struct);
    private GetRegInfo get_reg_info;

    [Import(UseExceptionWrapper = false)]
    // UInt64 load_elf(Int32 id, String file_name,
    //                 bool for_symbols_only, Int32* error_ptr);
    private LoadElf load_elf;

    [Import(UseExceptionWrapper = false)]
    // Int32 load_image(Int32 id, String file_name, UInt64 address);
    private LoadImage load_image;

    [Import(UseExceptionWrapper = false)]
    // UInt64 step(Int32 id, UInt64 step, IntPtr *error);
    private Step step;

    [Import(UseExceptionWrapper = false)]
    // Int32 read_register(Int32 id, Int32 reg_id, IntPtr *value);
    private ReadRegister read_register;

    [Import(UseExceptionWrapper = false)]
    // Int32 write_register(Int32 id, Int32 reg_id, UInt64 value);
    private WriteRegister write_register;

    [Import(UseExceptionWrapper = false)]
    // Int32 read_memory(Int32 id, UInt64 address, IntPtr buffer, Int32 size);
    private MemoryAccess read_memory;

    [Import(UseExceptionWrapper = false)]
    // Int32 write_memory(Int32 id, UInt64 address, IntPtr buffer, Int32 size);
    private MemoryAccess write_memory;

    [Import(UseExceptionWrapper = false)]
    // Int32 set_config(Int32 id, string[] names string[] values, Int32 size);
    private SetConfig set_config;

    [Import(UseExceptionWrapper = false)]
    // Int32 set_irq_value(Int32 id, Int32 irq_no, bool value);
    private SetIrqValue set_irq_value;

#pragma warning restore 649

    private Int32 mpact_id = -1;
    private string cpu_type;
    private ulong instructionsExecutedThisRound {get; set;}
    private ulong totalExecutedInstructions {get; set;}
    private const int PC_ID = 0x07b1;
}  // class MpactCheriotCPU


// Peripheral interface class.
public class MpactPeripheral : IKnownSize, IBytePeripheral,
                               IWordPeripheral, IDoubleWordPeripheral,
                               IQuadWordPeripheral,
                               IMultibyteWritePeripheral, IDisposable {

    public MpactPeripheral(IMachine machine, long baseAddress,
                           long size, IMpactPeripheral mpactCpu) {
        if (size == 0) {
            throw new ConstructionException("Memory size cannot be 0");
        }
        this.machine = machine;
        this.size = size;
        this.base_address = baseAddress;
        this.mpact_cpu = mpactCpu;
    }

    public void Reset() {}

    public void Dispose() {}

    // All memory accesses are forwarded to the mpactCpu with the base_address
    // added to the address field.
    public void WriteByte(long address, byte value) {
        mpact_cpu.WriteByte(address + base_address, value);
    }

    public byte ReadByte(long address) {
        return mpact_cpu.ReadByte(address + base_address);
    }

    public void WriteWord(long address, ushort value) {
        mpact_cpu.WriteWord(address + base_address, value);
    }

    public ushort ReadWord(long address) {
        return mpact_cpu.ReadWord(address + base_address);
    }

    public void WriteDoubleWord(long address, uint value) {
        mpact_cpu.WriteDoubleWord(address + base_address, value);
    }

    public uint ReadDoubleWord(long address) {
        return mpact_cpu.ReadDoubleWord(address + base_address);
    }

    public void WriteQuadWord(long address, ulong value) {
        mpact_cpu.WriteQuadWord(address + base_address, value);
    }

    public ulong ReadQuadWord(long address) {
        return mpact_cpu.ReadQuadWord(address + base_address);
    }

    public byte[] ReadBytes(long offset, int count, ICPU context = null) {
        return mpact_cpu.ReadBytes(offset + base_address, count, context);
    }

    public void WriteBytes(long offset, byte[] array, int startingIndex,
                           int count, ICPU context = null) {
        mpact_cpu.WriteBytes(offset + base_address, array, startingIndex,
                             count, context);
    }

    public long Size { get { return size;} }
    private IMpactPeripheral mpact_cpu;
    private long size;
    private long base_address = 0;
    private IMachine machine;

}  // class MpactPeripheral

}  // namespace Antmicro.Renode.Peripherals.MpactCPU

