sencha: track changes to MpactCheriotCPU.cs - MpactCheriotPeripheral is now bundled with and bound to the MpactCherioCPU class; this includes combining the code in one file - no more need to setup ram_smc; mpact sim is not shared any more - CliPort -> CLIPort and WaitForCli -> WaitForCLI - renode LoadELF now works (LoadBinary should too but not tested) - constructors changed; adjust the c# code to match - massive style changes to MpactCheriotCPU.cs NB: this requires an update cheriot toolchain Change-Id: I9034e06c7ffecf78312b38b59ef971256f78107d
diff --git a/platforms/sencha_smc.repl b/platforms/sencha_smc.repl index c457b35..94937c5 100644 --- a/platforms/sencha_smc.repl +++ b/platforms/sencha_smc.repl
@@ -25,11 +25,11 @@ memoryBase: 0x80000000 memorySize: 0x04000000 revocationMemoryBase: 0x83000000 // Shadow bitmap - clintMMRBase: 0 // NB: disables simulator built-in impl -ram_smc: MpactPeripheral.MpactCheriotPeripheral @ sysbus 0x80000000 +ram_smc: MpactCPU.MpactCheriotPeripheral @ sysbus 0x80000000 size: 0x04000000 - id: 1 // NB: must match MpactCheriotCPU.id + baseAddress: 0x80000000 + mpactCpu: cpu1 // Control block for the SMC, lets us pause/restart the core at an arbitrary PC. smc_control: MpactCPU.SmcCheriot_ControlBlock @ sysbus 0x54020000
diff --git a/sencha.resc b/sencha.resc index b77b779..ceae2c4 100644 --- a/sencha.resc +++ b/sencha.resc
@@ -21,8 +21,7 @@ include @sim/config/shodan_infrastructure/MpactCheriotCPU.cs EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactCheriotCPU" -include @sim/config/shodan_infrastructure/MpactCheriotPeripheral.cs -EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactPeripheral.MpactCheriotPeripheral" +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" @@ -62,12 +61,8 @@ # Override cli_port to enable the command line interface on the specified port. $cli_port?= -1 -sysbus.cpu1 CliPort $cli_port -sysbus.cpu1 WaitForCli true - -# Setup ram_smc to coordinate with cpu1 -sysbus.ram_smc CpuLibraryPath $cheriotLibrary -sysbus.ram_smc Start +sysbus.cpu1 CLIPort $cli_port +sysbus.cpu1 WaitForCLI true $tar ?= @out/cantrip/shodan/release/ext_flash.tar $spi_flash_load_address ?= 0x44000000
diff --git a/shodan_infrastructure/MpactCheriotCPU.cs b/shodan_infrastructure/MpactCheriotCPU.cs index 072ddaa..b814cd6 100644 --- a/shodan_infrastructure/MpactCheriotCPU.cs +++ b/shodan_infrastructure/MpactCheriotCPU.cs
@@ -38,518 +38,758 @@ namespace Antmicro.Renode.Peripherals.MpactCPU { - // Declare some additional function signatures. - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Int32 FuncInt32Int32ActionInt32(Int32 param0, ActionInt32 param1); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Int32 FuncInt32Int32Int32FuncInt32UInt64IntPtrInt32FuncInt32UInt64IntPtrInt32(Int32 param0, Int32 param1, FuncInt32UInt64IntPtrInt32 param2, - FuncInt32UInt64IntPtrInt32 param3); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Int32 FuncInt32Int32FuncInt32UInt64IntPtrInt32FuncInt32UInt64IntPtrInt32(Int32 param0, FuncInt32UInt64IntPtrInt32 param1, - FuncInt32UInt64IntPtrInt32 param2); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Int32 FuncInt32Int32StringArrStringArrInt32(Int32 param0, string[] param1, string[] param2, Int32 param3); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Int32 FuncInt32Int32Int32Bool(Int32 param0, Int32 param1, bool param2); - public class MpactCheriotCPU : BaseCPU, ICpuSupportingGdb, ICPUWithRegisters, ICPUWithHooks, IGPIOReceiver, ITimeSink, IDisposable { - [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; - } +// 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 {} - public MpactCheriotCPU(uint id, UInt64 memoryBase, UInt64 memorySize, - UInt64 revocationMemoryBase, UInt64 clintMMRBase, - string cpuType, IMachine machine, Endianess endianness, - CpuBitness bitness = CpuBitness.Bits32) - : base(id, cpuType, machine, endianness, bitness) - { - this.memoryBase = memoryBase; - this.memorySize = memorySize; - revocationMemBase = revocationMemoryBase; - clintBase = clintMMRBase; - error_ptr = Marshal.AllocHGlobal(4); - value_ptr = Marshal.AllocHGlobal(8); - reg_info_ptr = Marshal.AllocHGlobal(Marshal.SizeOf<RegInfo>()); - string_ptr = Marshal.AllocHGlobal(maxStringLen); - read_sysmem_delegate = new FuncInt32UInt64IntPtrInt32(ReadSysMemory); - write_sysmem_delegate = new FuncInt32UInt64IntPtrInt32(WriteSysMemory); - cpuLibraryRegistered = false; - } - ~MpactCheriotCPU() { - Marshal.FreeHGlobal(error_ptr); - Marshal.FreeHGlobal(value_ptr); - Marshal.FreeHGlobal(reg_info_ptr); - Marshal.FreeHGlobal(string_ptr); - } +// Struct containing info for loading binary image files. +public struct BinFileLoadInfo { + public string file_name; + public UInt64 load_address; + public UInt64 entry_point; +} - public override string Architecture { get { return "MpactCheriot";} } +// 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 { - public override void Start() - { - if (!cpuLibraryRegistered) - { - LogAndThrowRE("Failed to register cpu library"); - return; - } - base.Start(); + // 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; + } - // Simulator initialization code goes here. - mpact_id = connect_with_sysbus((Int32)Id, maxStringLen, read_sysmem_delegate, write_sysmem_delegate); - if (mpact_id < 0) { - LogAndThrowRE("Failed to create simulator instance"); - return; - } - // 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_names.Add("clintMMRBase"); - config_values.Add("0x" + memoryBase.ToString("X")); - config_values.Add("0x" + memorySize.ToString("X")); - config_values.Add("0x" + revocationMemBase.ToString("X")); - config_values.Add("0x" + clintBase.ToString("X")); + public MpactCheriotCPU(uint id, UInt64 memoryBase, UInt64 memorySize, + UInt64 revocationMemoryBase, string cpuType, + IMachine machine, Endianess endianness, + CpuBitness bitness = CpuBitness.Bits32) + : base(id, cpuType, machine, endianness, bitness) { + this.memoryBase = memoryBase; + this.memorySize = memorySize; + 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); + } - if (cli_port != -1) { - config_names.Add("cliPort"); - config_values.Add("0x" + cli_port.ToString("X")); - config_names.Add("waitForCLI"); - config_values.Add("0x" + Convert.ToInt32(wait_for_cli).ToString("X")); - } + ~MpactCheriotCPU() { + Marshal.FreeHGlobal(error_ptr); + Marshal.FreeHGlobal(value_ptr); + Marshal.FreeHGlobal(reg_info_ptr); + Marshal.FreeHGlobal(string_ptr); + } - 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"); - } - } - public override void Reset() - { - base.Reset(); - instructionsExecutedThisRound = 0; - totalExecutedInstructions = 0; - // Call simulator to reset. - reset(mpact_id); - } + public override string Architecture { get { return "MpactCheriot";} } - public override void Dispose() - { - base.Dispose(); - destruct(mpact_id); - } + public override void Start() { + base.Start(); - public string CpuLibraryPath - { - get - { - return cpuLibraryPath; - } - set - { - if (!String.IsNullOrWhiteSpace(value)) - { - if (cpuLibraryRegistered) - { - this.WarningLog("cpu library already registerd and " + - "should not be updated again."); - return; - } - cpuLibraryPath = value; - try - { - binder = new NativeBinder(this, cpuLibraryPath); - } - catch (System.Exception e) - { - LogAndThrowRE("Failed to load CPU library: " + e.Message); - } - cpuLibraryRegistered = true; - } - else - { - return; - } - } - } + // 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) { + this.Log(LogLevel.Info, "Adding cli port"); + 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")); + } + 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. + if (!executable_file.Equals("")) { + var entry_point = load_executable(mpact_id, executable_file, + error_ptr); + Int32 result = Marshal.ReadInt32(error_ptr); + if (result < 0) { + LogAndThrowRE("Failed to load executable"); + } + PC = entry_point; + } 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 int CliPort { get => cli_port; set => cli_port = value; } - public bool WaitForCli - { - get => wait_for_cli; - set => wait_for_cli = value; - } + public override void Reset() { + base.Reset(); + instructionsExecutedThisRound = 0; + totalExecutedInstructions = 0; + // Call simulator to reset. + reset(mpact_id); + } - public override ulong ExecutedInstructions => totalExecutedInstructions; + 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 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); - // TODO(torerik): Check for error. - 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); - // TODO(torerik): Check for error. - if (error < 0) { - this.Log(LogLevel.Error, "Failed to write PC"); - } - } - } - - protected 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 (UInt64)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 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; - public void OnGPIO(int number, bool value) { + // 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 BinFileLoadInfo BinFileInfo { + get => bin_file_info; + set => bin_file_info = value; + } + + public int 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"); + } + } + } + + protected 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 (UInt64)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"); - } - } + 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 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) { - // Create a managed buffer for the store data. - // Copy the store data to the managed buffer. - // Write the data to the system bus. - 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 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; + } - // ICPUWithHooks methods. + // 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 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) { - } - public void RemoveHooksAt(ulong addr) { - } - public void RemoveAllHooks() { - } + 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 */ } - // ICpuSuportingGdb methods. + // ICpuSuportingGdb methods. - public void EnterSingleStepModeSafely(HaltArguments args, bool? blocking = null) { - CheckCpuThreadId(); - ChangeExecutionModeToSingleStep(blocking); - UpdateHaltedState(); - InvokeHalted(args); - } + public void EnterSingleStepModeSafely(HaltArguments args, + bool? blocking = null) { + CheckCpuThreadId(); + ChangeExecutionModeToSingleStep(blocking); + UpdateHaltedState(); + InvokeHalted(args); + } - public string GDBArchitecture { get { return "riscv:cheriot"; } } + public string GDBArchitecture { get { return "riscv:cheriot"; } } - public List<GDBFeatureDescriptor> GDBFeatures { - get { - if (gdbFeatures.Any()) return gdbFeatures; + 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); + // 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; - } - } + return gdbFeatures; + } + } - // End of ICpuSupportingGdb methods. + // End of ICpuSupportingGdb methods. - private List<GDBFeatureDescriptor> gdbFeatures = new List<GDBFeatureDescriptor>(); - private UInt64 memoryBase; - private UInt64 memorySize; - private UInt64 revocationMemBase; - private UInt64 clintBase; - private Dictionary<Int32, CPURegister> registerMap = new Dictionary<Int32, CPURegister>(); - private Dictionary<string, Int32> registerNamesMap = new Dictionary<string, Int32>(); - private string cpuLibraryPath; - private bool cpuLibraryRegistered; - private int cli_port = -1; - private bool wait_for_cli = false; - private NativeBinder binder; - private readonly object nativeLock; - private readonly Int32 maxStringLen = 32; - 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;} - private FuncInt32UInt64IntPtrInt32 read_sysmem_delegate; - private FuncInt32UInt64IntPtrInt32 write_sysmem_delegate; + // 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 int cli_port = -1; + private bool wait_for_cli = false; + private UInt64 base_address = 0; + private UInt64 size = 0; + private List<GDBFeatureDescriptor> + gdbFeatures = new List<GDBFeatureDescriptor>(); + private UInt64 memoryBase; + private UInt64 memorySize; + 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 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); + + // 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)] - private FuncInt32Int32FuncInt32UInt64IntPtrInt32FuncInt32UInt64IntPtrInt32 construct_with_sysbus; // (Int32 id, Int32 callback(Uint64, IntPtr, Int32), Int32 callback(Uint64, IntPtr, Int32)); - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32Int32FuncInt32UInt64IntPtrInt32FuncInt32UInt64IntPtrInt32 connect_with_sysbus; // (Int32 id, Int32 callback(Uint64, IntPtr, Int32), Int32 callback(Uint64, IntPtr, Int32)); - [Import(UseExceptionWrapper = false)] - private ActionInt32 destruct; // (Int32 id); - [Import(UseExceptionWrapper = false)] - private ActionInt32 reset; // (Int32 id); - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32 get_reg_info_size; // (Int32 id) - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32Int32IntPtrIntPtr get_reg_info; // (Int32 id, IntPtr *name, IntPtr *struct); - [Import(UseExceptionWrapper = false)] - private FuncUInt64Int32StringIntPtr load_executable; // (Int32 id, String file_name); - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32StringUInt64 load_image; // (Int32 id, String file_name, UInt64 address); - [Import(UseExceptionWrapper = false)] - private FuncUInt64Int32UInt64IntPtr step; // (Int32 id, UInt64 step, IntPtr *error); - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32Int32IntPtr read_register; // (Int32 id, Int32 reg_id, IntPtr *value); - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32Int32UInt64 write_register; // (Int32 id, Int32 reg_id, UInt64 value); - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32UInt64IntPtrInt32 read_memory; // (Int32 id, UInt64 address, IntPtr buffer, Int32 size); - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32UInt64IntPtrInt32 write_memory; // (Int32 id, UInt64 address, IntPtr buffer, Int32 size); - // Set config. - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32StringArrStringArrInt32 set_config; // Int32 set_config(Int32 id, string[] names string[] values, Int32 size); - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32Int32Bool set_irq_value; // Int32 set_irq_value(Int32 id, Int32 irq_no, bool value); + [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_executable(Int32 id, String file_name); + private FuncUInt64Int32StringIntPtr load_executable; + + [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 {get; set;} - private ulong instructionsExecutedThisRound {get; set;} - private ulong totalExecutedInstructions {get; set;} - private const int PC_ID = 0x07b1; + private Int32 mpact_id {get; set;} + private ulong instructionsExecutedThisRound {get; set;} + private ulong totalExecutedInstructions {get; set;} + private const int PC_ID = 0x07b1; +} // 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
diff --git a/shodan_infrastructure/MpactCheriotPeripheral.cs b/shodan_infrastructure/MpactCheriotPeripheral.cs deleted file mode 100644 index e885bfa..0000000 --- a/shodan_infrastructure/MpactCheriotPeripheral.cs +++ /dev/null
@@ -1,180 +0,0 @@ -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; - -namespace Antmicro.Renode.Peripherals.MpactPeripheral { - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Int32 FuncInt32Int32Int32FuncInt32UInt64IntPtrInt32FuncInt32UInt64IntPtrInt32(Int32 param0, Int32 param1, - FuncInt32UInt64IntPtrInt32 param2, FuncInt32UInt64IntPtrInt32 param3); - - public class MpactCheriotPeripheral : IKnownSize, IBytePeripheral, IWordPeripheral, IDoubleWordPeripheral, IQuadWordPeripheral, IMultibyteWritePeripheral, IDisposable { - - public MpactCheriotPeripheral(IMachine machine, long size, int id) { - if (size == 0) throw new ConstructionException("Memory size cannot be 0"); - this.machine = machine; - this.size = size; - this.id = id; - cpuLibraryRegistered = false; - error_ptr = Marshal.AllocHGlobal(4); - value_ptr = Marshal.AllocHGlobal(8); - string_ptr = Marshal.AllocHGlobal(maxStringLen); - } - - public string CpuLibraryPath { - get { - return cpuLibraryPath; - } - set { - if (!String.IsNullOrWhiteSpace(value)) { - if (cpuLibraryRegistered) { - this.WarningLog("cpu library already registerd and " + - "should not be updated again."); - return; - } - cpuLibraryPath = value; - try { - binder = new NativeBinder(this, cpuLibraryPath); - } catch (System.Exception e) { - LogAndThrowRE("Failed to load CPU library: " + e.Message); - } - cpuLibraryRegistered = true; - } else { - return; - } - } - } - - public void Start() { - if (!cpuLibraryRegistered) { - LogAndThrowRE("Failed to register cpu library"); - return; - } - this.Log(LogLevel.Noisy, "Start simulator with id {0}", id); - mpact_id = connect_with_sysbus(id, maxStringLen, null, null); - if (mpact_id < 0) { - LogAndThrowRE("Failed to create simulator instance"); - return; - } - } - - public void Reset() {} - public void Dispose() {} - - 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); - } - - public long Size { get { return size;} } - private Int32 mpact_id; - private Int32 id {get; set;} - private long size; - private NativeBinder binder; - private string cpuLibraryPath; - private bool cpuLibraryRegistered; - private IMachine machine; - private readonly Int32 maxStringLen = 32; - private IntPtr value_ptr {get; set;} - private IntPtr error_ptr {get; set;} - private IntPtr string_ptr {get; set;} - - private void LogAndThrowRE(string info) { - this.Log(LogLevel.Error, info); - throw new RecoverableException(info); - } - - #pragma warning disable 649 - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32Int32FuncInt32UInt64IntPtrInt32FuncInt32UInt64IntPtrInt32 connect_with_sysbus; // (Int32 id, Int32 callback(Uint64, IntPtr, Int32), Int32 callback(Uint64, IntPtr, Int32)); - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32UInt64IntPtrInt32 read_memory; // (Int32 id, UInt64 address, IntPtr buffer, Int32 size); - [Import(UseExceptionWrapper = false)] - private FuncInt32Int32UInt64IntPtrInt32 write_memory; // (Int32 id, UInt64 address, IntPtr buffer, Int32 size); - } - -} // namespace Antmicro.Renode.Peripherals.MpactPeripheral