1<# 2// 3// Copyright (c) 2010-2024 Antmicro 4// Copyright (c) 2011-2015 Realtime Embedded 5// 6// This file is licensed under the MIT License. 7// Full license text is available in 'licenses/MIT.txt'. 8// 9#> 10<#@ template language="C#v3.5" debug="True"#> 11<#@ import namespace="System.Collections.Generic" #> 12<# 13 Dictionary<string, string> types = new Dictionary<string, string>(); 14 types.Add("byte", "Byte"); 15 types.Add("ushort", "Word"); 16 types.Add("uint", "DoubleWord"); 17 types.Add("ulong", "QuadWord"); 18#> 19/******************************************************** 20* 21* Warning! 22* This file was generated automatically. 23* Please do not edit. Changes should be made in the 24* appropriate *.tt file. 25* 26*/ 27 28using System; 29using Antmicro.Renode.Core; 30using Antmicro.Renode.Exceptions; 31using Antmicro.Renode.Logging; 32using Antmicro.Renode.Peripherals.Bus.Wrappers; 33using Antmicro.Renode.Peripherals.CPU; 34 35using Range = Antmicro.Renode.Core.Range; 36 37namespace Antmicro.Renode.Peripherals.Bus 38{ 39 public partial class SystemBus 40 { 41<# 42 foreach(var entry in types) 43 { 44 var type = entry.Key; 45 var name = entry.Value; 46#> 47 public <#= type #> Read<#= name #>(ulong address, IPeripheral context = null, ulong? cpuState = null) 48 { 49 var accessWidth = SysbusAccessWidth.<#=name#>; 50 if(IsAddressRangeLocked(address.By((ulong)accessWidth), context)) 51 { 52 this.Log(LogLevel.Warning, "Tried to read {0} bytes at 0x{1:X} which is inside a locked address range, returning 0", 53 (uint)accessWidth, address); 54 return 0; 55 } 56 57 using(SetLocalContext(context, cpuState)) 58 { 59 if(!TryFindPeripheralAccessMethods(address, context, out var accessMethods, out var startAddress, cpuState)) 60 { 61 return (<#= type #>)ReportNonExistingRead(address, accessWidth); 62 } 63 if(!IsPeripheralEnabled(accessMethods.Peripheral)) 64 { 65 this.Log(LogLevel.Warning, "Tried to read a locked peripheral: {0}. Address 0x{1:X}.", accessMethods.Peripheral, address); 66 return 0; 67 } 68 var lockTaken = false; 69 try 70 { 71 if(!accessMethods.Lock.IsHeldByCurrentThread) 72 { 73 accessMethods.Lock.Enter(ref lockTaken); 74 } 75 if(accessMethods.SetAbsoluteAddress != null) 76 { 77 accessMethods.SetAbsoluteAddress(address); 78 } 79 return accessMethods.Read<#=name#>(checked((long)(address - startAddress))); 80 } 81 finally 82 { 83 if(lockTaken) 84 { 85 accessMethods.Lock.Exit(); 86 } 87 } 88 } 89 } 90 91 public <#= type #> Read<#= name #>WithState(ulong address, IPeripheral context, IContextState stateObj) 92 { 93 var accessWidth = SysbusAccessWidth.<#=name#>; 94 if(!TryConvertStateToUlongForContext(context, stateObj, out ulong? state)) 95 { 96 this.Log(LogLevel.Warning, "Tried to read {0} bytes at 0x{1:X} but failed on context state conversion, returning 0", 97 (uint)accessWidth, address); 98 return 0; 99 } 100 return Read<#=name#>(address, context, state); 101 } 102 103 public void Write<#=name#>(ulong address, <#=type#> value, IPeripheral context = null, ulong? cpuState = null) 104 { 105 var accessWidth = SysbusAccessWidth.<#=name#>; 106 if(IsAddressRangeLocked(address.By((ulong)accessWidth), context)) 107 { 108 this.Log(LogLevel.Warning, "Tried to write {0} bytes (0x{1:X}) at 0x{2:X} which is inside a locked address range, write ignored", 109 (uint)accessWidth, value, address); 110 return; 111 } 112 113 using(SetLocalContext(context, cpuState)) 114 { 115 if(!TryFindPeripheralAccessMethods(address, context, out var accessMethods, out var startAddress, cpuState)) 116 { 117 ReportNonExistingWrite(address, value, accessWidth); 118 return; 119 } 120 if(!IsPeripheralEnabled(accessMethods.Peripheral)) 121 { 122 this.Log(LogLevel.Warning, "Tried to write a locked peripheral: {0}. Address 0x{1:X}, value 0x{2:X}", accessMethods.Peripheral, address, value); 123 return; 124 } 125 126 var lockTaken = false; 127 try 128 { 129 if(!accessMethods.Lock.IsHeldByCurrentThread) 130 { 131 accessMethods.Lock.Enter(ref lockTaken); 132 } 133 if(accessMethods.SetAbsoluteAddress != null) 134 { 135 accessMethods.SetAbsoluteAddress(address); 136 } 137 accessMethods.Write<#=name#>(checked((long)(address - startAddress)), value); 138 } 139 finally 140 { 141 if(lockTaken) 142 { 143 accessMethods.Lock.Exit(); 144 } 145 } 146 } 147 } 148 149 public void Write<#=name#>WithState(ulong address, <#=type#> value, IPeripheral context, IContextState stateObj) 150 { 151 var accessWidth = SysbusAccessWidth.<#=name#>; 152 if(!TryConvertStateToUlongForContext(context, stateObj, out ulong? state)) 153 { 154 this.Log(LogLevel.Warning, "Tried to write {0} bytes (0x{1:X}) at 0x{2:X} but failed on context state conversion, write ignored", 155 (uint)accessWidth, value, address); 156 return; 157 } 158 Write<#=name#>(address, value, context, state); 159 } 160 161<# } 162#> 163<# 164 foreach(var operation in new [] { "Read", "Write" }) 165 { 166 var when = operation == "Read" ? "After" : "Before"; 167 var actionOrFunc = operation == "Read" ? "Func" : "Action"; 168#> 169 public void ClearHook<#=when#>Peripheral<#=operation#><T>(IBusPeripheral peripheral) 170 { 171 SetHook<#=when#>Peripheral<#=operation#><T>(peripheral, null); 172 } 173 174 public void SetHook<#=when#>Peripheral<#=operation#><T>(IBusPeripheral peripheral, Func<T, long, T> hook, Range? subrange = null) 175 { 176 if(!Machine.IsRegistered(peripheral)) 177 { 178 throw new RecoverableException(string.Format("Cannot set hook on peripheral {0}, it is not registered.", peripheral)); 179 } 180 var type = typeof(T); 181<# 182 foreach(var entry in types) 183 { 184 var type = entry.Key; 185 var name = entry.Value; 186#> 187 if(type == typeof(<#=type#>)) 188 { 189 foreach(var peripherals in allPeripherals) 190 { 191 peripherals.VisitAccessMethods(peripheral, pam => 192 { 193 if(pam.<#=operation#><#=name#>.Target is <#=operation#>HookWrapper<<#=type#>>) 194 { 195 pam.<#=operation#><#=name#> = new BusAccess.<#=name#><#=operation#>Method(((<#=operation#>HookWrapper<<#=type#>>)pam.<#=operation#><#=name#>.Target).OriginalMethod); 196 } 197 if(hook != null) 198 { 199 pam.<#=operation#><#=name#> = new BusAccess.<#=name#><#=operation#>Method(new <#=operation#>HookWrapper<<#=type#>>(peripheral, new <#=actionOrFunc#><long, <#=type#>>(pam.<#=operation#><#=name#>), (Func<<#=type#>, long, <#=type#>>)(object)hook, subrange).<#=operation#>); 200 } 201 return pam; 202 }); 203 } 204 return; 205 } 206<# 207 } 208#> 209 } 210 211<# 212 } 213#> 214 private bool TryFindPeripheralAccessMethods(ulong address, IPeripheral context, out PeripheralAccessMethods accessMethods, out ulong startAddress, ulong? cpuState = null) 215 { 216 if(context == null) 217 { 218 TryGetCurrentCPU(out var cpu); 219 context = cpu; 220 } 221 if(context != null) 222 { 223 if(peripheralsCollectionByContext.TryGetValue(context, cpuState, out var collection)) 224 { 225 accessMethods = collection.FindAccessMethods(address, out startAddress, out var _); 226 if(accessMethods != null) 227 { 228 return true; 229 } 230 } 231 } 232 accessMethods = peripheralsCollectionByContext[null].FindAccessMethods(address, out startAddress, out _); 233 return accessMethods != null; 234 } 235 } 236} 237