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