| 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 |