sencha: track mpact-cheriot changes

- support for built-in clint
- support for stock risc-v core

Change-Id: I4c77b70e7158b10a55402cfffea4228ad4ea7d29
diff --git a/shodan_infrastructure/MpactCPU.cs b/shodan_infrastructure/MpactCPU.cs
index 35eb53f..981cbe3 100644
--- a/shodan_infrastructure/MpactCPU.cs
+++ b/shodan_infrastructure/MpactCPU.cs
@@ -57,7 +57,7 @@
 }
 
 // The MpactCPU class. This class derives from BaseCPU, which implements
-// a CPU in ReNode. It is the base implemenation of the interface between
+// 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,
@@ -253,12 +253,10 @@
     [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");
+            if (registerMap.Count == 0) {
+                GetMpactRegisters();
             }
-            Int64 value = Marshal.ReadInt64(value_ptr);
-            return Convert.ToUInt32(value);
+	    return GetRegisterUnsafe(PC_ID);
         }
 
         set {
@@ -348,7 +346,8 @@
                     break;
             }
         } else {
-            LogAndThrowRE("Unknown register id: {register}");
+	    string msg = $"Unknown register id: {register} not found";
+            LogAndThrowRE(msg);
         }
         return (ulong)0;
     }
diff --git a/shodan_infrastructure/MpactCheriotCPU.cs b/shodan_infrastructure/MpactCheriotCPU.cs
index f9e2ef8..c75db30 100644
--- a/shodan_infrastructure/MpactCheriotCPU.cs
+++ b/shodan_infrastructure/MpactCheriotCPU.cs
@@ -73,6 +73,14 @@
             config_names.Add("memProfile");
             config_values.Add("0x1");
         }
+        if (clint_mmr_base != 0) {
+            config_names.Add("clintMMRBase");
+            config_values.Add(clint_mmr_base.ToString("X"));
+        }
+        if (clint_period != 0) {
+            config_names.Add("clintPeriod");
+            config_values.Add(clint_period.ToString("X"));
+        }
     }
 
     public bool InstProfile {
@@ -85,6 +93,16 @@
         set => mem_profile = value;
     }
 
+    public UInt64 ClintMMRBase {
+        get => clint_mmr_base;
+        set => clint_mmr_base = value;
+    }
+
+    public UInt64 ClintPeriod {
+        get => clint_period;
+        set => clint_period = value;
+    }
+
     // ICPUWithHooks methods.
 
     public void AddHookAtInterruptBegin(Action<ulong> hook) {
@@ -155,6 +173,8 @@
     private bool inst_profile = false;
     private bool mem_profile = false;
     private UInt64 revocationMemBase;
+    private UInt64 clint_mmr_base = 0x0;
+    private UInt64 clint_period = 0;
     private List<GDBFeatureDescriptor>
                 gdbFeatures = new List<GDBFeatureDescriptor>();
 }  // class MpactCheriotCPU
diff --git a/shodan_infrastructure/MpactRiscVCPU.cs b/shodan_infrastructure/MpactRiscVCPU.cs
new file mode 100644
index 0000000..ca93625
--- /dev/null
+++ b/shodan_infrastructure/MpactRiscVCPU.cs
@@ -0,0 +1,190 @@
+//
+// 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 specializes the MpactCPU class to add custom interfaces and
+// properties required for the mpact_cheriot simulator.
+
+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 Antmicro.Renode.Peripherals.MpactCPU;
+using ELFSharp.ELF;
+using ELFSharp.UImage;
+
+namespace Antmicro.Renode.Peripherals.MpactCPU
+{
+
+// The MpactRiscvCPU class. This class derives from BaseCPU, which implements
+// a CPU in ReNode. It is the interface between ReNode and the mpact_riscv32/64
+// simulator libraries.
+public class MpactRiscVCPU : MpactBaseCPU, ICpuSupportingGdb {
+
+    public MpactRiscVCPU(uint id, UInt64 memoryBase, UInt64 memorySize,
+                         string cpuType, IMachine machine,
+                         Endianess endianness,
+                         CpuBitness bitness = CpuBitness.Bits32)
+        : base(id, memoryBase, memorySize, cpuType, machine, endianness,
+               bitness) {
+    }
+
+    ~MpactRiscVCPU() {
+    }
+
+
+    public override string Architecture { get { return "MpactRiscV";} }
+
+    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");
+        }
+        if (mem_profile) {
+            config_names.Add("memProfile");
+            config_values.Add("0x1");
+        }
+        // Stack
+        if (stack_size_set) {
+            config_names.Add("stackSize");
+            config_values.Add(stack_size.ToString("X"));
+        }
+        if (stack_end_set) {
+            config_names.Add("stackEnd");
+            config_values.Add(stack_end.ToString("X"));
+        }
+    }
+
+    public bool InstProfile {
+        get => inst_profile;
+        set => inst_profile = value;
+    }
+
+    public bool MemProfile {
+        get => mem_profile;
+        set => mem_profile = value;
+    }
+
+    public ulong StackSize {
+        get => stack_size;
+        set {
+            stack_size = value;
+            stack_size_set = true;
+        }
+    }
+
+    public ulong StackEnd {
+        get => stack_end;
+        set {
+            stack_end = value;
+            stack_end_set = true;
+        }
+    }
+
+    // ICPUWithHooks methods.
+
+    public void AddHookAtInterruptBegin(Action<ulong> hook) {
+        throw new RecoverableException(
+                        "Interrupt hooks not currently supported");
+    }
+    public void AddHookAtInterruptEnd(Action<ulong> hook) {
+        throw new RecoverableException(
+                        "Interrupt hooks not currently supported");
+    }
+    public void AddHookAtWfiStateChange(Action<bool> hook) {
+        throw new RecoverableException(
+                        "Wfi state change hook not currently supported");
+    }
+
+    public void AddHook(ulong addr, Action<ICpuSupportingGdb, ulong> hook) {
+        throw new RecoverableException("Hooks not currently supported");
+    }
+    public void RemoveHook(ulong addr, Action<ICpuSupportingGdb, ulong> hook) {
+        /* empty */
+    }
+    public void RemoveHooksAt(ulong addr) { /* empty */ }
+    public void RemoveAllHooks() { /* empty */ }
+
+    // ICPUSupportingGdb methods.
+
+    public void EnterSingleStepModeSafely(HaltArguments args) {
+        // this method should only be called from CPU thread,
+        // but we should check it anyway
+        CheckCpuThreadId();
+
+        ExecutionMode = ExecutionMode.SingleStep;
+
+        UpdateHaltedState();
+        InvokeHalted(args);
+    }
+
+    public string GDBArchitecture { get { return "riscv:riscv"; } }
+
+    public List<GDBFeatureDescriptor> GDBFeatures {
+        get {
+            if (gdbFeatures.Any()) return gdbFeatures;
+
+            // Populate the register map if it hasn't been done yet.
+            if (registerNamesMap.Count == 0) {
+                GetMpactRegisters();
+            }
+            var cpuGroup = new GDBFeatureDescriptor("org.gnu.gdb.riscv.cpu");
+            var intType = $"uint32";
+            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"));
+            }
+            var pcc_index = registerNamesMap["pcc"];
+            cpuGroup.Registers.Add(
+                        new GDBRegisterDescriptor((uint)pcc_index, 32u, "pcc",
+                                                  "code_ptr", "general"));
+            gdbFeatures.Add(cpuGroup);
+
+            return gdbFeatures;
+        }
+    }
+
+    // End of ICpuSupportingGdb methods.
+
+    private bool inst_profile = false;
+    private bool mem_profile = false;
+    private ulong stack_size;
+    private bool stack_size_set = false;
+    private ulong stack_end;
+    private bool stack_end_set = false;
+    private List<GDBFeatureDescriptor>
+                gdbFeatures = new List<GDBFeatureDescriptor>();
+}  // class MpactRiscVCPU
+
+}  // namespace Antmicro.Renode.Peripherals.MpactCPU
+