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 Antmicro.Renode.Peripherals; 10 using System.Collections.Generic; 11 using Antmicro.Renode.Exceptions; 12 using System.Linq; 13 14 namespace Antmicro.Renode.Core.Structure 15 { 16 public interface ISimpleContainer 17 { 18 Dictionary<int, IPeripheral> ChildCollection { get; } 19 } 20 21 public abstract class SimpleContainerBase<T> : IPeripheralContainer<T, NumberRegistrationPoint<int>>, IDisposable, ISimpleContainer 22 where T : IPeripheral 23 { Register(T peripheral, int address)24 public void Register(T peripheral, int address) 25 { 26 Register(peripheral, new NumberRegistrationPoint<int>(address)); 27 } 28 GetRegistrationPoints(T peripheral)29 public virtual IEnumerable<NumberRegistrationPoint<int>> GetRegistrationPoints(T peripheral) 30 { 31 return ChildCollection.Keys.Select(x => new NumberRegistrationPoint<int>(x)).ToList(); 32 } 33 34 public virtual IEnumerable<IRegistered<T, NumberRegistrationPoint<int>>> Children 35 { 36 get 37 { 38 return ChildCollection.Select(x => Registered.Create(x.Value, new NumberRegistrationPoint<int>(x.Key))).ToList(); 39 } 40 } 41 Register(T peripheral, NumberRegistrationPoint<int> registrationPoint)42 public virtual void Register(T peripheral, NumberRegistrationPoint<int> registrationPoint) 43 { 44 if(ChildCollection.ContainsKey(registrationPoint.Address)) 45 { 46 throw new RegistrationException("The specified registration point is already in use."); 47 } 48 ChildCollection.Add(registrationPoint.Address, peripheral); 49 } 50 Unregister(T peripheral)51 public virtual void Unregister(T peripheral) 52 { 53 var toRemove = ChildCollection.Where(x => x.Value.Equals(peripheral)).Select(x => x.Key).ToList(); //ToList required, as we remove from the source 54 if(toRemove.Count == 0) 55 { 56 throw new RegistrationException("The specified peripheral was never registered."); 57 } 58 foreach(var key in toRemove) 59 { 60 ChildCollection.Remove(key); 61 } 62 } 63 Dispose()64 public virtual void Dispose() 65 { 66 foreach(var child in ChildCollection.Values.OfType<IDisposable>()) 67 { 68 child.Dispose(); 69 } 70 71 ChildCollection.Clear(); 72 } 73 74 Dictionary<int, IPeripheral> ISimpleContainer.ChildCollection => this.ChildCollection.ToDictionary(k => k.Key, v => (IPeripheral)v.Value); 75 GetByAddress(int address)76 protected T GetByAddress(int address) 77 { 78 T peripheral; 79 if(!TryGetByAddress(address, out peripheral)) 80 { 81 throw new KeyNotFoundException(); 82 } 83 return peripheral; 84 } 85 TryGetByAddress(int address, out T peripheral)86 protected bool TryGetByAddress(int address, out T peripheral) 87 { 88 return ChildCollection.TryGetValue(address, out peripheral); 89 } 90 SimpleContainerBase()91 protected SimpleContainerBase() 92 { 93 ChildCollection = new Dictionary<int, T>(); 94 } 95 96 protected Dictionary<int, T> ChildCollection; 97 } 98 99 public abstract class SimpleContainer<T> : SimpleContainerBase<T>, IPeripheral 100 where T : IPeripheral 101 { Reset()102 public abstract void Reset(); 103 Register(T peripheral, NumberRegistrationPoint<int> registrationPoint)104 public override void Register(T peripheral, NumberRegistrationPoint<int> registrationPoint) 105 { 106 base.Register(peripheral, registrationPoint); 107 machine.RegisterAsAChildOf(this, peripheral, registrationPoint); 108 } 109 Unregister(T peripheral)110 public override void Unregister(T peripheral) 111 { 112 base.Unregister(peripheral); 113 machine.UnregisterAsAChildOf(this, peripheral); 114 } 115 SimpleContainer(IMachine machine)116 protected SimpleContainer(IMachine machine) : base() 117 { 118 this.machine = machine; 119 } 120 121 protected readonly IMachine machine; 122 } 123 124 public class SimpleContainerHelper<T> : SimpleContainerBase<T> 125 where T : IPeripheral 126 { SimpleContainerHelper(IMachine machine, IPeripheral parent)127 public SimpleContainerHelper(IMachine machine, IPeripheral parent) : base() 128 { 129 this.machine = machine; 130 this.parent = parent; 131 } 132 GetByAddress(int address)133 public new T GetByAddress(int address) 134 { 135 return base.GetByAddress(address); 136 } 137 TryGetByAddress(int address, out T peripheral)138 public new bool TryGetByAddress(int address, out T peripheral) 139 { 140 return base.TryGetByAddress(address, out peripheral); 141 } 142 Register(T peripheral, NumberRegistrationPoint<int> registrationPoint)143 public override void Register(T peripheral, NumberRegistrationPoint<int> registrationPoint) 144 { 145 base.Register(peripheral, registrationPoint); 146 machine.RegisterAsAChildOf(parent, peripheral, registrationPoint); 147 } 148 Unregister(T peripheral)149 public override void Unregister(T peripheral) 150 { 151 base.Unregister(peripheral); 152 machine.UnregisterAsAChildOf(parent, peripheral); 153 } 154 155 public new Dictionary<int, T> ChildCollection => base.ChildCollection; 156 157 protected readonly IPeripheral parent; 158 protected readonly IMachine machine; 159 } 160 } 161