// // 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 Antmicro.Renode.Peripherals; using System.Collections.Generic; using Antmicro.Renode.Exceptions; using System.Linq; namespace Antmicro.Renode.Core.Structure { public interface ISimpleContainer { Dictionary ChildCollection { get; } } public abstract class SimpleContainerBase : IPeripheralContainer>, IDisposable, ISimpleContainer where T : IPeripheral { public void Register(T peripheral, int address) { Register(peripheral, new NumberRegistrationPoint(address)); } public virtual IEnumerable> GetRegistrationPoints(T peripheral) { return ChildCollection.Keys.Select(x => new NumberRegistrationPoint(x)).ToList(); } public virtual IEnumerable>> Children { get { return ChildCollection.Select(x => Registered.Create(x.Value, new NumberRegistrationPoint(x.Key))).ToList(); } } public virtual void Register(T peripheral, NumberRegistrationPoint registrationPoint) { if(ChildCollection.ContainsKey(registrationPoint.Address)) { throw new RegistrationException("The specified registration point is already in use."); } ChildCollection.Add(registrationPoint.Address, peripheral); } public virtual void Unregister(T peripheral) { var toRemove = ChildCollection.Where(x => x.Value.Equals(peripheral)).Select(x => x.Key).ToList(); //ToList required, as we remove from the source if(toRemove.Count == 0) { throw new RegistrationException("The specified peripheral was never registered."); } foreach(var key in toRemove) { ChildCollection.Remove(key); } } public virtual void Dispose() { foreach(var child in ChildCollection.Values.OfType()) { child.Dispose(); } ChildCollection.Clear(); } Dictionary ISimpleContainer.ChildCollection => this.ChildCollection.ToDictionary(k => k.Key, v => (IPeripheral)v.Value); protected T GetByAddress(int address) { T peripheral; if(!TryGetByAddress(address, out peripheral)) { throw new KeyNotFoundException(); } return peripheral; } protected bool TryGetByAddress(int address, out T peripheral) { return ChildCollection.TryGetValue(address, out peripheral); } protected SimpleContainerBase() { ChildCollection = new Dictionary(); } protected Dictionary ChildCollection; } public abstract class SimpleContainer : SimpleContainerBase, IPeripheral where T : IPeripheral { public abstract void Reset(); public override void Register(T peripheral, NumberRegistrationPoint registrationPoint) { base.Register(peripheral, registrationPoint); machine.RegisterAsAChildOf(this, peripheral, registrationPoint); } public override void Unregister(T peripheral) { base.Unregister(peripheral); machine.UnregisterAsAChildOf(this, peripheral); } protected SimpleContainer(IMachine machine) : base() { this.machine = machine; } protected readonly IMachine machine; } public class SimpleContainerHelper : SimpleContainerBase where T : IPeripheral { public SimpleContainerHelper(IMachine machine, IPeripheral parent) : base() { this.machine = machine; this.parent = parent; } public new T GetByAddress(int address) { return base.GetByAddress(address); } public new bool TryGetByAddress(int address, out T peripheral) { return base.TryGetByAddress(address, out peripheral); } public override void Register(T peripheral, NumberRegistrationPoint registrationPoint) { base.Register(peripheral, registrationPoint); machine.RegisterAsAChildOf(parent, peripheral, registrationPoint); } public override void Unregister(T peripheral) { base.Unregister(peripheral); machine.UnregisterAsAChildOf(parent, peripheral); } public new Dictionary ChildCollection => base.ChildCollection; protected readonly IPeripheral parent; protected readonly IMachine machine; } }