1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using System.Collections.Generic; 10 using System.Linq; 11 using Antmicro.Renode.Core; 12 using Antmicro.Renode.Core.Structure; 13 using Antmicro.Renode.Peripherals.Bus; 14 using Antmicro.Renode.UserInterface; 15 16 using Endianess = ELFSharp.ELF.Endianess; 17 18 namespace Antmicro.Renode.Peripherals 19 { 20 [Icon("box")] 21 public interface IPeripheral : IEmulationElement, IAnalyzable 22 { Reset()23 void Reset(); 24 } 25 26 public static class IPeripheralExtensions 27 { HasGPIO(this IPeripheral peripheral)28 public static bool HasGPIO(this IPeripheral peripheral) 29 { 30 return peripheral is INumberedGPIOOutput || peripheral.GetType().GetProperties().Any(x => x.PropertyType == typeof(GPIO)); 31 } 32 33 /// <summary> 34 /// This method returns connected GPIO endpoints of a given peripheral. 35 /// </summary> 36 /// <returns>Collection of tuples: local GPIO name maped on endpoint to which it is connected. In case of INumberedGPIOOutput name is local number</returns> 37 /// <param name="peripheral">Peripheral.</param> GetGPIOs(this IPeripheral peripheral)38 public static IEnumerable<Tuple<string, IGPIO>> GetGPIOs(this IPeripheral peripheral) 39 { 40 IEnumerable<Tuple<string, IGPIO>> result = null; 41 var numberGPIOOuput = peripheral as INumberedGPIOOutput; 42 if(numberGPIOOuput != null) 43 { 44 result = numberGPIOOuput.Connections.Select(x => Tuple.Create(x.Key.ToString(), x.Value)); 45 } 46 47 var local = peripheral.GetType().GetProperties().Where(x => x.PropertyType == typeof(GPIO)).Select(x => Tuple.Create(x.Name, (IGPIO)((GPIO)x.GetValue(peripheral)))); 48 return result == null ? local : result.Union(local); 49 } 50 TryGetMachine(this IPeripheral @this, out IMachine machine)51 public static bool TryGetMachine(this IPeripheral @this, out IMachine machine) 52 { 53 if(EmulationManager.Instance.CurrentEmulation.TryGetMachineForPeripheral(@this, out machine)) 54 { 55 return true; 56 } 57 58 // let's try a fallback: 59 // check if the provided object is not a container of peripherals - 60 // in such case if and only if all peripherals belong to the same machine we can return it 61 var simpleContainer = @this as ISimpleContainer; 62 if(simpleContainer != null) 63 { 64 try 65 { 66 var allMachines = simpleContainer.ChildCollection.Select(x => x.Value.GetMachine()).Distinct().ToArray(); 67 if(allMachines.Length == 1) 68 { 69 machine = allMachines[0]; 70 return true; 71 } 72 } 73 catch(Exception) 74 { 75 // the try/catch here is to obtain a more readable stack trace; 76 // do nothing, we'll throw in a second anyway 77 } 78 } 79 return false; 80 } 81 GetMachine(this IPeripheral @this)82 public static IMachine GetMachine(this IPeripheral @this) 83 { 84 if(@this.TryGetMachine(out var machine)) 85 { 86 return machine; 87 } 88 throw new ArgumentException($"Couldn't find machine for a given peripheral of type {@this.GetType().FullName}."); 89 } 90 GetEndianness(this IPeripheral @this, Endianess? defaultEndianness = null)91 public static Endianess GetEndianness(this IPeripheral @this, Endianess? defaultEndianness = null) 92 { 93 if(@this is IEndiannessAware endiannessAwarePeripheral) 94 { 95 return endiannessAwarePeripheral.Endianness; 96 } 97 if(defaultEndianness != null) 98 { 99 return defaultEndianness.Value; 100 } 101 if(@this is IBusPeripheral busPeripheral) 102 { 103 return @this.GetMachine().GetSystemBus(busPeripheral).Endianess; 104 } 105 return @this.GetMachine().SystemBus.Endianess; 106 } 107 IsHostEndian(this IPeripheral @this)108 public static bool IsHostEndian(this IPeripheral @this) 109 { 110 return (@this.GetEndianness() == Endianess.LittleEndian) == BitConverter.IsLittleEndian; 111 } 112 GetName(this IPeripheral @this)113 public static string GetName(this IPeripheral @this) 114 { 115 var machine = @this.GetMachine(); 116 var machineName = EmulationManager.Instance.CurrentEmulation[machine]; 117 return $"{machineName}.{machine.GetLocalName(@this)}"; 118 } 119 } 120 } 121