// // Copyright (c) 2010-2024 Antmicro // Copyright (c) 2011-2015 Realtime Embedded // // This file is licensed under the MIT License. // Full license text is available in 'licenses/MIT.txt'. // using System; using System.Collections.Generic; using System.Linq; using Antmicro.Renode.Core; using Antmicro.Renode.Core.Structure; using Antmicro.Renode.Peripherals.Bus; using Antmicro.Renode.UserInterface; using Endianess = ELFSharp.ELF.Endianess; namespace Antmicro.Renode.Peripherals { [Icon("box")] public interface IPeripheral : IEmulationElement, IAnalyzable { void Reset(); } public static class IPeripheralExtensions { public static bool HasGPIO(this IPeripheral peripheral) { return peripheral is INumberedGPIOOutput || peripheral.GetType().GetProperties().Any(x => x.PropertyType == typeof(GPIO)); } /// /// This method returns connected GPIO endpoints of a given peripheral. /// /// Collection of tuples: local GPIO name maped on endpoint to which it is connected. In case of INumberedGPIOOutput name is local number /// Peripheral. public static IEnumerable> GetGPIOs(this IPeripheral peripheral) { IEnumerable> result = null; var numberGPIOOuput = peripheral as INumberedGPIOOutput; if(numberGPIOOuput != null) { result = numberGPIOOuput.Connections.Select(x => Tuple.Create(x.Key.ToString(), x.Value)); } var local = peripheral.GetType().GetProperties().Where(x => x.PropertyType == typeof(GPIO)).Select(x => Tuple.Create(x.Name, (IGPIO)((GPIO)x.GetValue(peripheral)))); return result == null ? local : result.Union(local); } public static bool TryGetMachine(this IPeripheral @this, out IMachine machine) { if(EmulationManager.Instance.CurrentEmulation.TryGetMachineForPeripheral(@this, out machine)) { return true; } // let's try a fallback: // check if the provided object is not a container of peripherals - // in such case if and only if all peripherals belong to the same machine we can return it var simpleContainer = @this as ISimpleContainer; if(simpleContainer != null) { try { var allMachines = simpleContainer.ChildCollection.Select(x => x.Value.GetMachine()).Distinct().ToArray(); if(allMachines.Length == 1) { machine = allMachines[0]; return true; } } catch(Exception) { // the try/catch here is to obtain a more readable stack trace; // do nothing, we'll throw in a second anyway } } return false; } public static IMachine GetMachine(this IPeripheral @this) { if(@this.TryGetMachine(out var machine)) { return machine; } throw new ArgumentException($"Couldn't find machine for a given peripheral of type {@this.GetType().FullName}."); } public static Endianess GetEndianness(this IPeripheral @this, Endianess? defaultEndianness = null) { if(@this is IEndiannessAware endiannessAwarePeripheral) { return endiannessAwarePeripheral.Endianness; } if(defaultEndianness != null) { return defaultEndianness.Value; } if(@this is IBusPeripheral busPeripheral) { return @this.GetMachine().GetSystemBus(busPeripheral).Endianess; } return @this.GetMachine().SystemBus.Endianess; } public static bool IsHostEndian(this IPeripheral @this) { return (@this.GetEndianness() == Endianess.LittleEndian) == BitConverter.IsLittleEndian; } public static string GetName(this IPeripheral @this) { var machine = @this.GetMachine(); var machineName = EmulationManager.Instance.CurrentEmulation[machine]; return $"{machineName}.{machine.GetLocalName(@this)}"; } } }