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 
9 using System;
10 using System.Collections.Generic;
11 
12 namespace Antmicro.Renode.Peripherals.Bus
13 {
14     public class BusAccess
15     {
BusAccess()16         static BusAccess()
17         {
18             Delegates = new []
19             {
20                 typeof(QuadWordReadMethod), typeof(QuadWordWriteMethod),
21                 typeof(DoubleWordReadMethod), typeof(DoubleWordWriteMethod),
22                 typeof(WordReadMethod), typeof(WordWriteMethod),
23                 typeof(ByteReadMethod), typeof(ByteWriteMethod)
24             };
25 
26             accessMethods = new Dictionary<Type, Method>();
27             accessOperations = new Dictionary<Type, Operation>();
28 
29             foreach(var delegateType in Delegates)
30             {
31                 Method accessMethod;
32                 var delegateMethodInfo = delegateType.GetMethod("Invoke");
33                 var parameters = delegateMethodInfo.GetParameters();
34                 if(delegateMethodInfo.ReturnType == typeof(void))
35                 {
36                     if(parameters.Length != 2
37                         || parameters[0].ParameterType != typeof(long)
38                         || !TryGetMethodFromType(parameters[1].ParameterType, out accessMethod))
39                     {
40                         throw new ArgumentException("Wrong method signature");
41                     }
42                     accessOperations[delegateType] = Operation.Write;
43                 }
44                 else
45                 {
46                     if(parameters.Length != 1
47                         || parameters[0].ParameterType != typeof(long)
48                         || !TryGetMethodFromType(delegateMethodInfo.ReturnType, out accessMethod))
49                     {
50                         throw new ArgumentException("Wrong method signature");
51                     }
52                     accessOperations[delegateType] = Operation.Read;
53                 }
54 
55                 accessMethods[delegateType] = accessMethod;
56             }
57         }
58 
TryGetMethodFromType(Type type, out Method method)59         private static bool TryGetMethodFromType(Type type, out Method method)
60         {
61             foreach(var member in typeof(Method).GetMembers())
62             {
63                 var interestingAttributes = member.GetCustomAttributes(typeof(ReferencedTypeAttribute), false);
64                 if(interestingAttributes.Length == 0)
65                 {
66                     continue;
67                 }
68 
69                 if(((ReferencedTypeAttribute)interestingAttributes[0]).ReferencedType == type)
70                 {
71                     method = (Method)Enum.Parse(typeof(Method), member.Name);
72                     return true;
73                 }
74             }
75 
76             method = Method.Byte;
77             return false;
78         }
79 
GetOperationFromSignature(Type t)80         public static Operation GetOperationFromSignature(Type t)
81         {
82             return accessOperations[t];
83         }
84 
GetMethodFromSignature(Type t)85         public static Method GetMethodFromSignature(Type t)
86         {
87             return accessMethods[t];
88         }
89 
GetComplementingOperation(Operation operation)90         public static Operation GetComplementingOperation(Operation operation)
91         {
92             return operation == Operation.Read ? Operation.Write : Operation.Read;
93         }
94 
95         public static Type[] Delegates { get; private set; }
96 
97         private static readonly Dictionary<Type, Method> accessMethods;
98         private static readonly Dictionary<Type, Operation> accessOperations;
99 
QuadWordReadMethod(long offset)100         public delegate ulong QuadWordReadMethod(long offset);
QuadWordWriteMethod(long offset, ulong value)101         public delegate void QuadWordWriteMethod(long offset, ulong value);
DoubleWordReadMethod(long offset)102         public delegate uint DoubleWordReadMethod(long offset);
DoubleWordWriteMethod(long offset, uint value)103         public delegate void DoubleWordWriteMethod(long offset, uint value);
WordReadMethod(long offset)104         public delegate ushort WordReadMethod(long offset);
WordWriteMethod(long offset, ushort value)105         public delegate void WordWriteMethod(long offset, ushort value);
ByteReadMethod(long offset)106         public delegate byte ByteReadMethod(long offset);
ByteWriteMethod(long offset, byte value)107         public delegate void ByteWriteMethod(long offset, byte value);
108 
109         public enum Operation
110         {
111             Read,
112             Write
113         }
114 
115         public enum Method
116         {
117             [ReferencedType(typeof(byte))]
118             Byte,
119             [ReferencedType(typeof(ushort))]
120             Word,
121             [ReferencedType(typeof(uint))]
122             DoubleWord,
123             [ReferencedType(typeof(ulong))]
124             QuadWord
125         }
126 
127         private class ReferencedTypeAttribute : Attribute
128         {
ReferencedTypeAttribute(Type t)129             public ReferencedTypeAttribute(Type t)
130             {
131                 ReferencedType = t;
132             }
133 
134             public Type ReferencedType { get; private set; }
135         }
136     }
137 }
138