blob: e885bfa629ec569f43bec35990f9bcffafd542ff [file] [log] [blame]
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