1<# 2// 3// Copyright (c) 2010-2025 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#" hostspecific="true" #> 11<#@ parameter type="System.String" name="BASE_PATH" #> 12<#@ assembly name="System.Core" #> 13<#@ import namespace="System.IO" #> 14<#@ import namespace="System.Linq" #> 15<#@ import namespace="System.Text" #> 16<#@ import namespace="System.Collections.Generic" #> 17<#@ include file="RegisterEnumParserContent.tt" #> 18<# 19 if(CLASS_NAME == null) 20 { 21 throw new ArgumentException("CLASS_NAME variable not set"); 22 } 23 if(HEADER_FILE == null) 24 { 25 throw new ArgumentException("HEADER_FILE variable not set"); 26 } 27 if(ACCESSOR_PREFIX == null) 28 { 29 // Assume tlibs by default 30 ACCESSOR_PREFIX = "tlib_"; 31 } 32 33 RegistersEnumParser parser; 34 var baseDirectoryPath = Directory.GetParent(BASE_PATH).Parent.Parent.Parent.FullName; 35 var fullPath = Path.Combine(baseDirectoryPath, HEADER_FILE); 36 using(var stream = File.OpenRead(fullPath)) 37 { 38 parser = new RegistersEnumParser(stream, DEFINES); 39 } 40 41 if(PC_REGISTER != null) 42 { 43 parser.Map("PC", PC_REGISTER); 44 } 45 46 foreach(var ignored in REGISTERS_FROM_BASE_CLASS) 47 { 48 parser.Ignore(ignored); 49 } 50 51 var virtualRegisters = new HashSet<string> { "PC" }; 52 53 var OVERRIDE = ""; 54 55 if(OVERRIDE_DEFINITIONS) 56 { 57 OVERRIDE = "override "; 58 } 59#> 60/******************************************************** 61* 62* Warning! 63* This file was generated automatically. 64* Please do not edit. Changes should be made in the 65* appropriate *.tt file. 66* 67*/ 68using System; 69using System.Linq; 70using System.Collections.Generic; 71using Antmicro.Renode.Peripherals.CPU.Registers; 72using Antmicro.Renode.Utilities.Binding; 73using Antmicro.Renode.Exceptions; 74 75namespace Antmicro.Renode.Peripherals.CPU 76{ 77 public partial class <#=CLASS_NAME#> 78 { 79<# 80 var widths = parser.Registers 81 .Union(parser.RegisterGroups.SelectMany(x => x.GetRegisters())) 82 .Select(x => x.Width) 83 .OrderBy(x => x) 84 .Distinct() 85 .ToArray(); 86#> 87 public <#=OVERRIDE#>void SetRegister(int register, RegisterValue value) 88 { 89 if(!mapping.TryGetValue((<#=CLASS_NAME#>Registers)register, out var r)) 90 { 91<# 92 if(FALLBACK_SET_REGISTER != null) 93 { 94#> 95 if(<#=FALLBACK_SET_REGISTER#>(register, value)) 96 { 97 return; 98 } 99<# 100 } 101#> 102 throw new RecoverableException($"Wrong register index: {register}"); 103 } 104<# 105 if(UNSETTABLE_REGISTERS.Any()) 106 { 107#> 108 if(r.IsReadonly) 109 { 110 throw new RecoverableException($"The '{(<#=CLASS_NAME#>Registers)register}' register is read-only."); 111 } 112<# 113 } 114#> 115 116<# 117 if(widths.Length == 1) 118 { 119#> 120 SetRegisterValue<#=widths[0]#>(r.Index, checked((<#=RegisterTypeHelper.GetTypeName(widths[0])#>)value)); 121<# 122 } 123 else 124 { 125#> 126 switch(r.Width) 127 { 128<# 129 foreach(var width in widths) 130 { 131#> 132 case <#=width#>: 133 SetRegisterValue<#=width#>(r.Index, checked((<#=RegisterTypeHelper.GetTypeName(width)#>)value)); 134 break; 135<# 136 } 137#> 138 default: 139 throw new ArgumentException($"Unsupported register width: {r.Width}"); 140 } 141<# 142 } 143#> 144 } 145 146 public <#=OVERRIDE#>RegisterValue GetRegister(int register) 147 { 148 if(!mapping.TryGetValue((<#=CLASS_NAME#>Registers)register, out var r)) 149 { 150<# 151 if(FALLBACK_GET_REGISTER != null) 152 { 153#> 154 if(<#=FALLBACK_GET_REGISTER#>(register, out var value)) 155 { 156 return value; 157 } 158<# 159 } 160#> 161 throw new RecoverableException($"Wrong register index: {register}"); 162 } 163<# 164 if(widths.Length == 1) 165 { 166#> 167 return GetRegisterValue<#=widths[0]#>(r.Index); 168<# 169 } 170 else 171 { 172#> 173 switch(r.Width) 174 { 175<# 176 foreach(var width in widths) 177 { 178#> 179 case <#=width#>: 180 return GetRegisterValue<#=width#>(r.Index); 181<# 182 } 183#> 184 default: 185 throw new ArgumentException($"Unsupported register width: {r.Width}"); 186 } 187<# 188 } 189#> 190 } 191 192 public <#=OVERRIDE#>IEnumerable<CPURegister> GetRegisters() 193 { 194<# 195 if(FALLBACK_REGISTERS != null) 196 { 197#> 198 return mapping.Values.Concat(<#=FALLBACK_REGISTERS#>()).OrderBy(x => x.Index); 199<# 200 } 201 else 202 { 203#> 204 return mapping.Values.OrderBy(x => x.Index); 205<# 206 } 207#> 208 } 209 210<# 211 foreach(var register in parser.Registers.Where(x => !x.IsIgnored)) 212 { 213#> 214 [Register] 215 public <#= virtualRegisters.Contains(register.Name) ? "override " : "" #>RegisterValue <#=register.Name#> 216 { 217 get 218 { 219<# 220 if(BEFORE_READ_HOOKS.ContainsKey(register.Name)) 221 { 222#> 223 <#=BEFORE_READ_HOOKS[register.Name]#>(); 224<# 225 } 226#> 227 return GetRegisterValue<#=register.Width#>((int)<#=CLASS_NAME#>Registers.<#=register.Name#>); 228 } 229 set 230 { 231<# 232 if(BEFORE_WRITE_HOOKS.ContainsKey(register.Name)) 233 { 234#> 235 value = <#=BEFORE_WRITE_HOOKS[register.Name]#>(value); 236<# 237 } 238#> 239 SetRegisterValue<#=register.Width#>((int)<#=CLASS_NAME#>Registers.<#=register.Name#>, value); 240<# 241 if(AFTER_WRITE_HOOKS.ContainsKey(register.Name)) 242 { 243#> 244 <#=AFTER_WRITE_HOOKS[register.Name]#>(value); 245<# 246 } 247#> 248 } 249 } 250<# 251 } 252 253 foreach(var registerGroup in parser.RegisterGroups.Where(x => !x.IsIgnored)) 254 { 255#> 256 public RegistersGroup <#=registerGroup.Name#> { get; private set; } 257<# 258 } 259#> 260 261 protected <#=OVERRIDE#>void InitializeRegisters() 262 { 263<# 264 if(REGISTERS_FROM_BASE_CLASS.Count > 0) 265 { 266#> 267 base.InitializeRegisters(); 268<# 269 } 270 foreach(var registerGroup in parser.RegisterGroups.Where(x => !x.IsIgnored)) 271 {#> 272 var indexValueMap<#=registerGroup.Name#> = new Dictionary<int, <#=CLASS_NAME#>Registers> 273 { 274<# 275 foreach(var elem in registerGroup.IndexValueMap) 276 { 277#> 278 { <#=elem.Key#>, <#=CLASS_NAME#>Registers.<#=registerGroup.Name#><#=elem.Key#> }, 279<# 280 } 281#> 282 }; 283 <#=registerGroup.Name#> = new RegistersGroup( 284 indexValueMap<#=registerGroup.Name#>.Keys, 285 i => GetRegister((int)indexValueMap<#=registerGroup.Name#>[i]), 286 (i, v) => SetRegister((int)indexValueMap<#=registerGroup.Name#>[i], v)); 287 288<# 289 } 290#> 291 } 292 293<# 294 var ignoredWidths = parser.RegisterGroups.Where(x => x.IsIgnored).Select(x => x.Width).Union(parser.Registers.Where(x => x.IsIgnored).Select(x => x.Width)).Distinct(); 295 foreach(var width in parser.RegisterGroups.Select(x => x.Width).Union(parser.Registers.Select(x => x.Width)).Except(ignoredWidths).Distinct()) 296 { 297#> 298 // 649: Field '...' is never assigned to, and will always have its default value null 299 #pragma warning disable 649 300 301 [Import(Name = "<#=ACCESSOR_PREFIX#>set_register_value_<#=width#>")] 302 protected Action<int, <#=RegisterTypeHelper.GetTypeName(width)#>> SetRegisterValue<#=width#>; 303 [Import(Name = "<#=ACCESSOR_PREFIX#>get_register_value_<#=width#>")] 304 protected Func<int, <#=RegisterTypeHelper.GetTypeName(width)#>> GetRegisterValue<#=width#>; 305 306 #pragma warning restore 649 307 308<# 309 } 310#> 311 private static readonly Dictionary<<#=CLASS_NAME#>Registers, CPURegister> mapping = new Dictionary<<#=CLASS_NAME#>Registers, CPURegister> 312 { 313<# 314 foreach(var register in 315 parser.Registers 316 .Union(parser.RegisterGroups.SelectMany(x => x.GetRegisters())) 317 .GroupBy(x => x.Value) 318 .OrderBy(x => x.Key)) 319 { 320 var firstName = register.First().Name; 321 var id = register.Key; 322 var width = register.Select(x => x.Width).First(); 323 var isGeneral = register.Any(x => GENERAL_REGISTERS.Contains(x.Name)) ? "true" : "false"; 324 var isReadonly = register.Any(x => UNSETTABLE_REGISTERS.Contains(x.Name)) ? "true" : "false"; 325 var names = String.Join(", ", register.Select(x => $"\"{x.Name}\"")); 326 var aliases = $"new [] {{ {names} }}"; 327#> 328 { <#=CLASS_NAME#>Registers.<#=firstName#>, new CPURegister(<#=id#>, <#=width#>, isGeneral: <#=isGeneral#>, isReadonly: <#=isReadonly#>, aliases: <#=aliases#>) }, 329<# 330 } 331#> 332 }; 333 } 334 335 public enum <#=CLASS_NAME#>Registers 336 { 337<# 338 foreach(var register in parser.Registers) 339 { 340#> 341 <#=register.Name#> = <#=register.Value#>, 342<# 343 } 344 345 foreach(var registerGroup in parser.RegisterGroups) 346 { 347 foreach(var index in registerGroup.IndexValueMap.OrderBy(x => x.Key)) 348 { 349#> 350 <#=registerGroup.Name#><#=index.Key#> = <#=index.Value#>, 351<# 352 } 353 } 354#> 355 } 356} 357