1 //
2 // Copyright (c) 2010-2024 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using Antmicro.Renode.Core;
9 using Antmicro.Renode.Core.Structure;
10 using Antmicro.Renode.Exceptions;
11 using Antmicro.Renode.Peripherals.CPU;
12 
13 namespace Antmicro.Renode.Peripherals.Bus
14 {
15     public abstract class BusRegistration : IBusRegistration, IConditionalRegistration
16     {
BusRegistration(ulong startingPoint, ulong offset = 0, IPeripheral cpu = null, ICluster<ICPU> cluster = null, StateMask? stateMask = null, string condition = null)17         protected BusRegistration(ulong startingPoint, ulong offset = 0, IPeripheral cpu = null, ICluster<ICPU> cluster = null, StateMask? stateMask = null, string condition = null)
18         {
19             if(cpu != null && cluster != null)
20             {
21                 throw new ConstructionException("CPU and cluster cannot be specified at the same time");
22             }
23 
24             if(stateMask != null && condition != null)
25             {
26                 throw new ConstructionException("State mask and condition cannot be specified at the same time");
27             }
28 
29             Initiator = cpu;
30             Cluster = cluster;
31             StateMask = stateMask;
32             Condition = condition;
33             Offset = offset;
34             StartingPoint = startingPoint;
35         }
36 
37         public IPeripheral Initiator { get; }
38         public ICluster<ICPU> Cluster { get; }
39         public StateMask? StateMask { get; }
40         public string Condition { get; }
41         public ulong Offset { get; set; }
42         public ulong StartingPoint { get; set; }
43 
44         public virtual string PrettyString
45         {
46             get
47             {
48                 return ToString();
49             }
50         }
51 
Equals(object obj)52         public override bool Equals(object obj)
53         {
54             var other = obj as BusRegistration;
55             if(other == null)
56                 return false;
57             if(ReferenceEquals(this, obj))
58                 return true;
59 
60             return StartingPoint == other.StartingPoint && Offset == other.Offset && Initiator == other.Initiator && Cluster == other.Cluster
61                 && StateMask.Equals(other.StateMask) && Condition == other.Condition;
62         }
63 
GetHashCode()64         public override int GetHashCode()
65         {
66             return 17 * StartingPoint.GetHashCode() + 23 * Offset.GetHashCode() + 101 * (Initiator?.GetHashCode() ?? 0) + 397 * (Cluster?.GetHashCode() ?? 0)
67                 + 401 * (StateMask?.GetHashCode() ?? 0) + 409 * (Condition?.GetHashCode() ?? 0);
68         }
69 
WithInitiatorAndStateMask(IPeripheral initiator, StateMask mask)70         public abstract IConditionalRegistration WithInitiatorAndStateMask(IPeripheral initiator, StateMask mask);
71 
72         protected void RegisterForEachContextInner<T>(Action<T> register, Func<ICPU, T> registrationForCpuGetter)
73             where T : BusRegistration
74         {
75             if(Cluster != null)
76             {
77                 foreach(var cpu in Cluster.Clustered)
78                 {
79                     register(registrationForCpuGetter(cpu));
80                 }
81             }
82             else
83             {
84                 register((T)this);
85             }
86         }
87     }
88 }
89