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#" #> 11<#@ import namespace="System.Collections.Generic" #> 12/******************************************************** 13* 14* Warning! 15* This file was generated automatically. 16* Please do not edit. Changes should be made in the 17* appropriate *.tt file. 18* 19*/ 20using System; 21using System.Text; 22using Antmicro.Renode.Logging; 23using Antmicro.Renode.Peripherals; 24using Antmicro.Renode.Peripherals.Bus; 25using Antmicro.Renode.Utilities; 26 27namespace Antmicro.Renode.Core.Extensions 28{ 29 public static class ReadWriteExtensions 30 { 31<# 32 var widthNames = new Dictionary<int, string>() 33 { 34 {8, "Byte"}, 35 {16, "Word"}, 36 {32, "DoubleWord"}, 37 {64, "QuadWord"} 38 }; 39 40 var widthTypes = new Dictionary<int, string>() 41 { 42 {8, "byte"}, 43 {16, "ushort"}, 44 {32, "uint"}, 45 {64, "ulong"} 46 }; 47 48 var swapBytes = new Dictionary<int, string>() 49 { 50 {8, ""}, 51 {16, "Misc.SwapBytesUShort"}, 52 {32, "Misc.SwapBytesUInt"}, 53 {64, "Misc.SwapBytesULong"} 54 }; 55 56 var masks = new Dictionary<int, string>() 57 { 58 {8, "0xFF"}, 59 {16, "0xFFFF"}, 60 {32, "0xFFFFFFFFUL"} 61 }; 62 63 foreach(var inWidth in new int[] {8, 16, 32, 64}) 64 { 65 foreach(var outWidth in new int[] {8, 16, 32, 64}) 66 { 67 if(inWidth == outWidth) 68 { 69 continue; 70 } 71 72 var inType = widthTypes[inWidth]; 73 var outType = widthTypes[outWidth]; 74 var outName = widthNames[outWidth]; 75 var inName = widthNames[inWidth]; 76 var swapFuncIn = swapBytes[inWidth]; 77 var swapFuncOut = swapBytes[outWidth]; 78 79 if(inWidth < outWidth) 80 { 81#> 82 public static <#= outType #> Read<#= outName #>Using<#= inName #>(this I<#= inName #>Peripheral peripheral, long address) 83 { 84 unchecked 85 { 86 return (<#= outType #>)((<#= outType #>)peripheral.Read<#= inName #>(address) 87<# 88 for(var i = inWidth; i < outWidth; i += inWidth) 89 { 90#> 91 | (<#= outType #>)peripheral.Read<#= inName #>(address + <#= i / 8 #>) << <#= i #> 92<# 93 } 94#> 95 ); 96 } 97 } 98 99 public static BusAccess.<#= outName #>ReadMethod Build<#= outName #>ReadUsing(BusAccess.<#= inName #>ReadMethod read) 100 { 101 return address => 102 { 103 unchecked 104 { 105 return (<#= outType #>)((<#= outType #>)read(address) 106<# 107 for(var i = inWidth; i < outWidth; i += inWidth) 108 { 109#> 110 | (<#= outType #>)read(address + <#= i / 8 #>) << <#= i #> 111<# 112 } 113#> 114 ); 115 } 116 }; 117 } 118 119 public static void Write<#= outName #>Using<#= inName #>(this I<#= inName #>Peripheral peripheral, long address, <#= outType #> value) 120 { 121 unchecked 122 { 123<# 124 for(var i = 0; i < outWidth; i += inWidth) 125 { 126#> 127 peripheral.Write<#= inName #>(address + <#= i / 8 #>, (<#= inType #>)(value >> <#= i #>)); 128<# 129 } 130#> 131 } 132 } 133 134 public static BusAccess.<#= outName #>WriteMethod Build<#= outName #>WriteUsing(BusAccess.<#= inName #>ReadMethod read, BusAccess.<#= inName #>WriteMethod write) 135 { 136 return (address, value) => 137 { 138 unchecked 139 { 140<# 141 for(var i = 0; i < outWidth; i += inWidth) 142 { 143#> 144 write(address + <#= i / 8 #>, (<#= inType #>)(value >> <#= i #>)); 145<# 146 } 147#> 148 } 149 }; 150 } 151 152 public static <#= outType #> Read<#= outName #>Using<#= inName #>BigEndian(this I<#= inName #>Peripheral peripheral, long address) 153 { 154 unchecked 155 { 156 return (<#= outType #>)((<#= outType #>)<#= swapFuncIn #>(peripheral.Read<#= inName #>(address + <#= (outWidth - inWidth) / 8 #>)) 157<# 158 for(var i = outWidth - 2 * inWidth; i >= 0; i -= inWidth) 159 { 160#> 161 | (<#= outType #>)<#= swapFuncIn #>(peripheral.Read<#= inName #>(address + <#= i / 8 #>)) << <#= outWidth - inWidth - i #> 162<# 163 } 164#> 165 ); 166 } 167 } 168 169 public static BusAccess.<#= outName #>ReadMethod Build<#= outName #>ReadBigEndianUsing(BusAccess.<#= inName #>ReadMethod read) 170 { 171 return address => 172 { 173 unchecked 174 { 175 return (<#= outType #>)((<#= outType #>)<#= swapFuncIn #>(read(address + <#= (outWidth - inWidth) / 8 #>)) 176<# 177 for(var i = outWidth - 2 * inWidth; i >= 0; i -= inWidth) 178 { 179#> 180 | (<#= outType #>)<#= swapFuncIn #>(read(address + <#= i / 8 #>)) << <#= outWidth - inWidth - i #> 181<# 182 } 183#> 184 ); 185 } 186 }; 187 } 188 189 public static void Write<#= outName #>Using<#= inName #>BigEndian(this I<#= inName #>Peripheral peripheral, long address, <#= outType #> value) 190 { 191 unchecked 192 { 193<# 194 for(var i = outWidth - inWidth; i >= 0; i -= inWidth) 195 { 196#> 197 peripheral.Write<#= inName #>(address + <#= (outWidth - inWidth - i) / 8 #>, <#= swapFuncIn #>((<#= inType #>)(value >> <#= i #>))); 198<# 199 } 200#> 201 } 202 } 203 204 public static BusAccess.<#= outName #>WriteMethod Build<#= outName #>WriteBigEndianUsing(BusAccess.<#= inName #>ReadMethod read, BusAccess.<#= inName #>WriteMethod write) 205 { 206 return (address, value) => 207 { 208 unchecked 209 { 210<# 211 for(var i = outWidth - inWidth; i >= 0; i -= inWidth) 212 { 213#> 214 write(address + <#= (outWidth - inWidth - i) / 8 #>, <#= swapFuncIn #>((<#= inType #>)(value >> <#= i #>))); 215<# 216 } 217#> 218 } 219 }; 220 } 221 222<# 223 } 224 else // inWidth >= outWidth 225 { 226 var mask = masks[outWidth]; 227#> 228 public static <#= outType #> Read<#= outName #>Using<#= inName #>(this I<#= inName #>Peripheral peripheral, long address) 229 { 230 unchecked 231 { 232 var readAddress = address & (~<#= inWidth / 8 - 1 #>); 233 var offset = (int)(address & <#= inWidth / 8 - 1 #>); 234 return (<#= outType #>)(peripheral.Read<#= inName #>(readAddress) >> offset * 8); 235 } 236 } 237 238 public static BusAccess.<#= outName #>ReadMethod Build<#= outName #>ReadUsing(BusAccess.<#= inName #>ReadMethod read) 239 { 240 return address => 241 { 242 unchecked 243 { 244 var readAddress = address & (~<#= inWidth / 8 - 1 #>); 245 var offset = (int)(address & <#= inWidth / 8 - 1 #>); 246 return (<#= outType #>)(read(readAddress) >> offset * 8); 247 } 248 }; 249 } 250 251 public static void Write<#= outName #>Using<#= inName #>(this I<#= inName #>Peripheral peripheral, long address, <#= outType #> value) 252 { 253 unchecked 254 { 255 var writeAddress = address & (~<#= inWidth / 8 - 1 #>); 256 var offset = (int)(address & <#= inWidth / 8 - 1 #>); 257 var oldValue = peripheral.Read<#= inName #>(writeAddress) & ~((<#= inType #>)<#= mask #> << offset * 8); 258 peripheral.Write<#= inName #>(writeAddress, (<#= inType #>)(oldValue | ((<#= inType #>)value << 8 * offset))); 259 } 260 } 261 262 public static BusAccess.<#= outName #>WriteMethod Build<#= outName #>WriteUsing(BusAccess.<#= inName #>ReadMethod read, BusAccess.<#= inName #>WriteMethod write) 263 { 264 return (address, value) => 265 { 266 unchecked 267 { 268 var writeAddress = address & (~<#= inWidth / 8 - 1 #>); 269 var offset = (int)(address & <#= inWidth / 8 - 1 #>); 270 var oldValue = read(writeAddress) & ~((<#= inType #>)<#= mask #> << offset * 8); 271 write(writeAddress, (<#= inType #>)(oldValue | ((<#= inType #>)value << 8 * offset))); 272 } 273 }; 274 } 275 276 public static <#= outType #> Read<#= outName #>Using<#= inName #>BigEndian(this I<#= inName #>Peripheral peripheral, long address) 277 { 278 unchecked 279 { 280 var readAddress = address & (~<#= inWidth / 8 - 1 #>); 281 var offset = <#= (inWidth - outWidth) / 8 #> - (int)(address & <#= inWidth / 8 - 1 #>); 282 return <#= swapFuncOut #>((<#= outType #>)(peripheral.Read<#= inName #>(readAddress) >> offset * 8)); 283 } 284 } 285 286 public static BusAccess.<#= outName #>ReadMethod Build<#= outName #>ReadBigEndianUsing(BusAccess.<#= inName #>ReadMethod read) 287 { 288 return address => 289 { 290 unchecked 291 { 292 var readAddress = address & (~<#= inWidth / 8 - 1 #>); 293 var offset = <#= (inWidth - outWidth) / 8 #> - (int)(address & <#= inWidth / 8 - 1 #>); 294 return <#= swapFuncOut #>((<#= outType #>)(read(readAddress) >> offset * 8)); 295 } 296 }; 297 } 298 299 public static void Write<#= outName #>Using<#= inName #>BigEndian(this I<#= inName #>Peripheral peripheral, long address, <#= outType #> value) 300 { 301 unchecked 302 { 303<# 304 if(outWidth > 8) 305 { 306#> 307 value = <#= swapFuncOut #>(value); 308<# 309 } 310#> 311 var writeAddress = address & (~<#= inWidth / 8 - 1 #>); 312 var offset = <#= (inWidth - outWidth) / 8 #> - (int)(address & <#= inWidth / 8 - 1 #>); 313 var oldValue = peripheral.Read<#= inName #>(writeAddress) & ~((<#= inType #>)<#= mask #> << offset * 8); 314 peripheral.Write<#= inName #>(writeAddress, (<#= inType #>)(oldValue | ((<#= inType #>)value << 8 * offset))); 315 } 316 } 317 318 public static BusAccess.<#= outName #>WriteMethod Build<#= outName #>WriteBigEndianUsing(BusAccess.<#= inName #>ReadMethod read, BusAccess.<#= inName #>WriteMethod write) 319 { 320 return (address, value) => 321 { 322 unchecked 323 { 324<# 325 if(outWidth > 8) 326 { 327#> 328 value = <#= swapFuncOut #>(value); 329<# 330 } 331#> 332 var writeAddress = address & (~<#= inWidth / 8 - 1 #>); 333 var offset = <#= (inWidth - outWidth) / 8 #> - (int)(address & <#= inWidth / 8 - 1 #>); 334 var oldValue = read(writeAddress) & ~((<#= inType #>)<#= mask #> << offset * 8); 335 write(writeAddress, (<#= inType #>)(oldValue | ((<#= inType #>)value << 8 * offset))); 336 } 337 }; 338 } 339<# 340 } // else 341 } // foreach outWidth 342 } // foreach inWidth 343 344 foreach(var width in new int[] {16, 32, 64}) 345 { 346 var type = widthTypes[width]; 347 var name = widthNames[width]; 348 var swapFunc = swapBytes[width]; 349#> 350 351 public static <#= type #> Read<#= name #>BigEndian(this I<#= name #>Peripheral peripheral, long address) 352 { 353 return <#= swapFunc #>(peripheral.Read<#= name #>(address)); 354 } 355 356 public static void Write<#= name #>BigEndian(this I<#= name #>Peripheral peripheral, long address, <#= type #> value) 357 { 358 peripheral.Write<#= name #>(address, <#= swapFunc #>(value)); 359 } 360 361<# 362 } // foreach 363 364 foreach(var width in new int[] {8, 16, 32, 64}) 365 { 366 var type = widthTypes[width]; 367 var name = widthNames[width]; 368#> 369 370 public static <#= type #> Read<#= name #>NotTranslated(this IBusPeripheral peripheral, long address) 371 { 372 LogNotTranslated(peripheral, SysbusAccessWidth.<#= name #>, address); 373 return 0; 374 } 375 376 public static void Write<#= name #>NotTranslated(this IBusPeripheral peripheral, long address, <#= type #> value) 377 { 378 LogNotTranslated(peripheral, SysbusAccessWidth.<#= name #>, address, value); 379 } 380<# 381 } // foreach 382#> 383 384 private static void LogNotTranslated(IBusPeripheral peripheral, SysbusAccessWidth operationWidth, long address, ulong? value = null) 385 { 386 var strBldr = new StringBuilder(); 387 var isWrite = value.HasValue; 388 strBldr.AppendFormat("Attempted {0} {1} isn't supported by the peripheral.", operationWidth, isWrite ? "write" : "read"); 389 strBldr.AppendFormat(" Offset 0x{0:X}", address); 390 if(isWrite) 391 { 392 strBldr.AppendFormat(", value 0x{0:X}", value.Value); 393 } 394 strBldr.Append("."); 395 396 peripheral.Log(LogLevel.Warning, peripheral.GetMachine().GetSystemBus(peripheral).DecorateWithCPUNameAndPC(strBldr.ToString())); 397 } 398 } 399} 400