sencha: update for refactoring & profiling support

- add support for instruction & memory profiling.
- refactor Cheriot CPU classes
- update copyright notices

Bypass-Presubmit-Reason: no sencha CI tests

NB: this requires an updated toolchain

Change-Id: I81ee768c2bb39bf9970d2ee0d7373019db51c7dc
diff --git a/cheriot.resc b/cheriot.resc
index bf46c98..1dce9fd 100644
--- a/cheriot.resc
+++ b/cheriot.resc
@@ -16,9 +16,11 @@
 
 mach create "cheriot"
 
+include @sim/config/shodan_infrastructure/MpactCPU.cs
+EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactBaseCPU"
+EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactPeripheral"
 include @sim/config/shodan_infrastructure/MpactCheriotCPU.cs
 EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactCheriotCPU"
-EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactCheriotPeripheral"
 
 $platformfile?=@sim/config/platforms/sail.repl
 
diff --git a/platforms/cheriot.repl b/platforms/cheriot.repl
index 59c12ec..9e82f1a 100644
--- a/platforms/cheriot.repl
+++ b/platforms/cheriot.repl
@@ -21,7 +21,7 @@
     memorySize: 0x10000000
     revocationMemoryBase: 0x83000000
 
-ram_smc : MpactCPU.MpactCheriotPeripheral @ sysbus 0x80000000
+ram_smc : MpactCPU.MpactPeripheral @ sysbus 0x80000000
     size: 0x10000000
     baseAddress: 0x80000000
     mpactCpu: cpu1
diff --git a/sencha.resc b/sencha.resc
index 3ba02e5..2a00994 100644
--- a/sencha.resc
+++ b/sencha.resc
@@ -19,9 +19,11 @@
 using sysbus
 mach create $name
 
+include @sim/config/shodan_infrastructure/MpactCPU.cs
+EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactBaseCPU"
+EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactPeripheral"
 include @sim/config/shodan_infrastructure/MpactCheriotCPU.cs
 EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactCheriotCPU"
-EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactCheriotPeripheral"
 EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.CPU.RiscV32"
 include @sim/config/shodan_infrastructure/KelvinCPU.cs
 EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.CPU.KelvinCPU"
diff --git a/shodan_infrastructure/MpactCPU.cs b/shodan_infrastructure/MpactCPU.cs
new file mode 100644
index 0000000..01241ab
--- /dev/null
+++ b/shodan_infrastructure/MpactCPU.cs
@@ -0,0 +1,771 @@
+//
+// 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 implemenation 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.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(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 {
+            Int32 error = read_register(mpact_id, PC_ID, value_ptr);
+            if (error < 0) {
+                this.Log(LogLevel.Error, "Failed to read PC");
+            }
+            Int64 value = Marshal.ReadInt64(value_ptr);
+            return Convert.ToUInt32(value);
+        }
+
+        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, Id));
+            return ExecutionResult.Aborted;
+            }
+        finally {
+            numberOfExecutedInstructions = instructionsExecutedThisRound;
+            totalExecutedInstructions += instructionsExecutedThisRound;
+        }
+        return result;
+    }
+
+    // ICPUWithRegisters methods implementations.
+    public  void SetRegisterUnsafe(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  RegisterValue GetRegisterUnsafe(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 {
+            LogAndThrowRE("Unknown register id: {register}");
+        }
+        return (ulong)0;
+    }
+
+    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 ConnectWithSysbus(Int32 param0, Int32 param1,
+                                            FuncInt32UInt64IntPtrInt32 param2,
+                                            FuncInt32UInt64IntPtrInt32 param3);
+
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    public delegate Int32 ConstructWithSysbus(Int32 param0,
+                                              FuncInt32UInt64IntPtrInt32 param1,
+                                              FuncInt32UInt64IntPtrInt32 param2);
+
+    [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);
+
+    // 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(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(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 FuncInt32Int32 get_reg_info_size;
+
+    [Import(UseExceptionWrapper = false)]
+    // Int32 get_reg_info(Int32 id, IntPtr *name, IntPtr *struct);
+    private FuncInt32Int32Int32IntPtrIntPtr 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 FuncInt32Int32StringUInt64 load_image;
+
+    [Import(UseExceptionWrapper = false)]
+    // UInt64 step(Int32 id, UInt64 step, IntPtr *error);
+    private FuncUInt64Int32UInt64IntPtr step;
+
+    [Import(UseExceptionWrapper = false)]
+    // Int32 read_register(Int32 id, Int32 reg_id, IntPtr *value);
+    private FuncInt32Int32Int32IntPtr read_register;
+
+    [Import(UseExceptionWrapper = false)]
+    // Int32 write_register(Int32 id, Int32 reg_id, UInt64 value);
+    private FuncInt32Int32Int32UInt64 write_register;
+
+    [Import(UseExceptionWrapper = false)]
+    // Int32 read_memory(Int32 id, UInt64 address, IntPtr buffer, Int32 size);
+    private FuncInt32Int32UInt64IntPtrInt32 read_memory;
+
+    [Import(UseExceptionWrapper = false)]
+    // Int32 write_memory(Int32 id, UInt64 address, IntPtr buffer, Int32 size);
+    private FuncInt32Int32UInt64IntPtrInt32 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 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
+
diff --git a/shodan_infrastructure/MpactCheriotCPU.cs b/shodan_infrastructure/MpactCheriotCPU.cs
index 3c5960e..dbb7afb 100644
--- a/shodan_infrastructure/MpactCheriotCPU.cs
+++ b/shodan_infrastructure/MpactCheriotCPU.cs
@@ -1,17 +1,19 @@
 //
+// 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
 //
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
+// 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.
 //
-//     https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+
+// This file specializes the MpactCPU class to add custom interfaces and
+// properties required for the mpact_cheriot simulator.
 
 using System;
 using System.Linq;
@@ -33,435 +35,54 @@
 using Antmicro.Renode.Utilities;
 using Antmicro.Renode.Time;
 using Antmicro.Renode.Utilities.Binding;
+using Antmicro.Renode.Peripherals.MpactCPU;
 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 MpactCheriotCPU class. This class derives from BaseCPU, which implements
 // a CPU in ReNode. It is the interface between ReNode and the mpact_cheriot
 // simulator library.
-public class MpactCheriotCPU : BaseCPU, ICpuSupportingGdb, ICPUWithRegisters,
-                               ICPUWithHooks, 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 class MpactCheriotCPU : MpactBaseCPU, ICpuSupportingGdb {
 
     public MpactCheriotCPU(uint id, UInt64 memoryBase, UInt64 memorySize,
-		           UInt64 revocationMemoryBase, string cpuType,
-			   IMachine machine, Endianess endianness,
+                           UInt64 revocationMemoryBase, string cpuType,
+                           IMachine machine, Endianess endianness,
                            CpuBitness bitness = CpuBitness.Bits32)
-        : base(id, cpuType, machine, endianness, bitness) {
-        this.memoryBase = memoryBase;
-        this.memorySize = memorySize;
+        : base(id, memoryBase, memorySize, cpuType, machine, endianness,
+               bitness) {
         revocationMemBase = revocationMemoryBase;
-        // 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);
     }
 
     ~MpactCheriotCPU() {
-        Marshal.FreeHGlobal(error_ptr);
-        Marshal.FreeHGlobal(value_ptr);
-        Marshal.FreeHGlobal(reg_info_ptr);
-        Marshal.FreeHGlobal(string_ptr);
     }
 
 
     public override string Architecture { get { return "MpactCheriot";} }
 
-    public override void Start() {
-        base.Start();
-
-        // Set up configuration array.
-        var config_names = new List<string>();
-        var config_values = new List<string>();
-        config_names.Add("memoryBase");
-        config_names.Add("memorySize");
-        config_names.Add("revocationMemoryBase");
-        config_values.Add("0x" + memoryBase.ToString("X"));
-        config_values.Add("0x" + memorySize.ToString("X"));
-        config_values.Add("0x" + revocationMemBase.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 SetMpactConfig(List<string> config_names,
+                                        List<string> config_values) {
+        base.SetMpactConfig(config_names, config_values);
+        if (inst_profile) {
+            config_names.Add("instProfile");
+            config_values.Add("0x1");
         }
-        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");
-        }
-        if (mpact_id < 0) {
-            LogAndThrowRE("Failed to create simulator instance");
-            return;
-        }
-        // Load executable file or bin file if specified. Otherwise it is
-        // handled 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;
+        if (mem_profile) {
+            config_names.Add("memProfile");
+            config_values.Add("0x1");
         }
     }
 
-    public override void Reset() {
-        base.Reset();
-        instructionsExecutedThisRound = 0;
-        totalExecutedInstructions = 0;
-        // Call simulator to reset.
-        reset(mpact_id);
+    public bool InstProfile {
+        get => inst_profile;
+        set => inst_profile = value;
     }
 
-    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(maxStringLen,
-			                     read_sysmem_delegate,
-                                             write_sysmem_delegate);
-        }
-    }
-
-    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 {
-            Int32 error = read_register(mpact_id, PC_ID, value_ptr);
-            if (error < 0) {
-                this.Log(LogLevel.Error, "Failed to read PC");
-            }
-            Int64 value = Marshal.ReadInt64(value_ptr);
-            return Convert.ToUInt64(value);
-        }
-
-        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, Id));
-            return ExecutionResult.Aborted;
-            }
-        finally {
-            numberOfExecutedInstructions = instructionsExecutedThisRound;
-            totalExecutedInstructions += instructionsExecutedThisRound;
-        }
-        return result;
-    }
-
-    // ICPUWithRegisters methods implementations.
-    public  void SetRegisterUnsafe(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  RegisterValue GetRegisterUnsafe(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);
-        return (UInt32)value;
-    }
-
-    private 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;
+    public bool MemProfile {
+        get => mem_profile;
+        set => mem_profile = value;
     }
 
     // ICPUWithHooks methods.
@@ -476,7 +97,7 @@
     }
     public void AddHookAtWfiStateChange(Action<bool> hook) {
         throw new RecoverableException(
-			"Wfi state change hook not currently supported");
+                        "Wfi state change hook not currently supported");
     }
 
     public void AddHook(ulong addr, Action<ICpuSupportingGdb, ulong> hook) {
@@ -488,10 +109,10 @@
     public void RemoveHooksAt(ulong addr) { /* empty */ }
     public void RemoveAllHooks() { /* empty */ }
 
-    // ICpuSuportingGdb methods.
+    // ICPUSupportingGdb methods.
 
     public void EnterSingleStepModeSafely(HaltArguments args,
-		                          bool? blocking = null) {
+                                          bool? blocking = null) {
         CheckCpuThreadId();
         ChangeExecutionModeToSingleStep(blocking);
         UpdateHaltedState();
@@ -513,13 +134,13 @@
             var c0_index = registerNamesMap["c0"];
             for (var i = 0u; i < 16; ++i) {
                 cpuGroup.Registers.Add(
-		        new GDBRegisterDescriptor((uint)c0_index + i, 32u,
-				                  $"c{i}", intType, "general"));
+                        new GDBRegisterDescriptor((uint)c0_index + i, 32u,
+                                                  $"c{i}", intType, "general"));
             }
             var pcc_index = registerNamesMap["pcc"];
             cpuGroup.Registers.Add(
-		        new GDBRegisterDescriptor((uint)pcc_index, 32u, "pcc",
-				                  "code_ptr", "general"));
+                        new GDBRegisterDescriptor((uint)pcc_index, 32u, "pcc",
+                                                  "code_ptr", "general"));
             gdbFeatures.Add(cpuGroup);
 
             return gdbFeatures;
@@ -528,290 +149,12 @@
 
     // End of ICpuSupportingGdb methods.
 
-    // 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 + base_address, value_ptr, 1);
-    }
-
-    public byte ReadByte(long address) {
-        var data8 = new byte[1];
-        read_memory(mpact_id, (UInt64) address + base_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 + base_address, value_ptr, 2);
-    }
-
-    public ushort ReadWord(long address) {
-        var data16 = new Int16[1];
-        read_memory(mpact_id, (UInt64) address + base_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 + base_address, value_ptr, 4);
-    }
-
-    public uint ReadDoubleWord(long address) {
-        var data32 = new Int32[1];
-        read_memory(mpact_id, (UInt64) address + base_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 + base_address, value_ptr, 8);
-    }
-
-    public ulong ReadQuadWord(long address) {
-        var data64 = new Int64[1];
-        read_memory(mpact_id, (UInt64) address + base_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 + base_address, 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 + base_address, byte_array_ptr,
-		     count);
-        Marshal.FreeHGlobal(byte_array_ptr);
-    }
-
-    // End of IMpactPeripheral methods.
-
-    private ushort cli_port = 0;
-    private bool wait_for_cli = true;
-    private UInt64 base_address = 0;
-    private UInt64 size = 0;
-    private List<GDBFeatureDescriptor>
-	        gdbFeatures = new List<GDBFeatureDescriptor>();
-    private UInt64 memoryBase;
-    private UInt64 memorySize;
+    private bool inst_profile = false;
+    private bool mem_profile = false;
     private UInt64 revocationMemBase;
-    private Dictionary<Int32, CPURegister>
-	        registerMap = new Dictionary<Int32, CPURegister>();
-    private Dictionary<string, Int32>
-	        registerNamesMap = new Dictionary<string, Int32>();
-    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 ConnectWithSysbus(Int32 param0, Int32 param1,
-                                            FuncInt32UInt64IntPtrInt32 param2,
-                                            FuncInt32UInt64IntPtrInt32 param3);
-
-    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
-    public delegate Int32 ConstructWithSysbus(Int32 param0,
-                                              FuncInt32UInt64IntPtrInt32 param1,
-                                              FuncInt32UInt64IntPtrInt32 param2);
-
-    [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);
-
-    // 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(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(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 FuncInt32Int32 get_reg_info_size;
-
-    [Import(UseExceptionWrapper = false)]
-    // Int32 get_reg_info(Int32 id, IntPtr *name, IntPtr *struct);
-    private FuncInt32Int32Int32IntPtrIntPtr 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 FuncInt32Int32StringUInt64 load_image;
-
-    [Import(UseExceptionWrapper = false)]
-    // UInt64 step(Int32 id, UInt64 step, IntPtr *error);
-    private FuncUInt64Int32UInt64IntPtr step;
-
-    [Import(UseExceptionWrapper = false)]
-    // Int32 read_register(Int32 id, Int32 reg_id, IntPtr *value);
-    private FuncInt32Int32Int32IntPtr read_register;
-
-    [Import(UseExceptionWrapper = false)]
-    // Int32 write_register(Int32 id, Int32 reg_id, UInt64 value);
-    private FuncInt32Int32Int32UInt64 write_register;
-
-    [Import(UseExceptionWrapper = false)]
-    // Int32 read_memory(Int32 id, UInt64 address, IntPtr buffer, Int32 size);
-    private FuncInt32Int32UInt64IntPtrInt32 read_memory;
-
-    [Import(UseExceptionWrapper = false)]
-    // Int32 write_memory(Int32 id, UInt64 address, IntPtr buffer, Int32 size);
-    private FuncInt32Int32UInt64IntPtrInt32 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 ulong instructionsExecutedThisRound {get; set;}
-    private ulong totalExecutedInstructions {get; set;}
-    private const int PC_ID = 0x07b1;
+    private List<GDBFeatureDescriptor>
+                gdbFeatures = new List<GDBFeatureDescriptor>();
 }  // class MpactCheriotCPU
 
-
-// Peripheral interface class.
-public class MpactCheriotPeripheral : IKnownSize, IBytePeripheral,
-	                              IWordPeripheral, IDoubleWordPeripheral,
-				      IQuadWordPeripheral,
-				      IMultibyteWritePeripheral, IDisposable {
-
-    public MpactCheriotPeripheral(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 MpactCheriotPeripheral
-
 }  // namespace Antmicro.Renode.Peripherals.MpactCPU