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