1 // Copyright (C) 2024 Antmicro 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // SPDX-License-Identifier: Apache-2.0 16 17 using System; 18 using System.Reflection; 19 using System.Collections.Generic; 20 using System.Linq; 21 using NUnit.Framework; 22 using Antmicro.Renode.Core.Structure.Registers; 23 using Antmicro.Renode.Peripherals.Bus; 24 using Antmicro.Renode.Utilities; 25 using System.Text.Json; 26 using System.Text.Json.Serialization; 27 using System.IO; 28 using Mono.Cecil; 29 30 namespace Antmicro.Renode.PeripheralsTests 31 { 32 [TestFixture] 33 public class SystemRDLGenTest 34 { 35 private class LoadedAssemblies 36 { LoadedAssemblies()37 private LoadedAssemblies() 38 { 39 Assemblies = new Dictionary<string, AssemblyDefinition>(); 40 compiler = new AdHocCompiler(); 41 } 42 43 static public LoadedAssemblies Instance 44 { 45 get 46 { 47 if(instance == null) 48 { 49 instance = new LoadedAssemblies(); 50 } 51 return instance; 52 } 53 } 54 55 public IDictionary<string, AssemblyDefinition> Assemblies { get; set; } 56 LoadAssembly(RdlMeta meta)57 public AssemblyDefinition LoadAssembly(RdlMeta meta) 58 { 59 var adhocPath = Path.Join(Assembly.GetExecutingAssembly().Location, "../../../../", meta.File); 60 if(!Assemblies.TryGetValue(adhocPath, out var assembly)) 61 { 62 var assemblyPath = compiler.Compile(adhocPath); 63 assembly = AssemblyDefinition.ReadAssembly(assemblyPath); 64 Assemblies[adhocPath] = assembly; 65 TypeManager.Instance.ScanFile(assemblyPath); 66 } 67 return assembly; 68 } 69 70 private static LoadedAssemblies instance; 71 private readonly AdHocCompiler compiler; 72 } 73 74 static private IEnumerable<RdlMeta> GetTestCases 75 { 76 get 77 { 78 var assembly = Assembly.GetExecutingAssembly(); 79 if(!assembly.TryFromResourceToTemporaryFile(SystemRDLResource, out var file)) 80 { 81 Console.WriteLine($"Couldn't load the {SystemRDLResource} resource"); 82 yield break; 83 } 84 var fstream = File.OpenRead(file); 85 86 var options = new JsonSerializerOptions 87 { 88 PropertyNameCaseInsensitive = true, 89 }; 90 options.Converters.Add(new TestFieldModeFlagConverter()); 91 92 var metas = (List<RdlMeta>)JsonSerializer.Deserialize(fstream, typeof(List<RdlMeta>), options); 93 94 foreach(var meta in metas) 95 { 96 yield return meta; 97 } 98 } 99 } 100 101 [OneTimeSetUp] Setup()102 public void Setup() 103 { 104 var peripheralRegisterClasses = typeof(PeripheralRegister).GetTypeInfo().DeclaredNestedTypes.ToDictionary(ti => ti.Name); 105 this.ValueRegisterField = peripheralRegisterClasses["ValueRegisterField"]; 106 Assert.NotNull(this.ValueRegisterField); 107 this.FlagRegisterField = peripheralRegisterClasses["FlagRegisterField"]; 108 Assert.NotNull(this.FlagRegisterField); 109 this.RegisterField = peripheralRegisterClasses["RegisterField"]; 110 Assert.NotNull(this.RegisterField); 111 } 112 113 public class TestFieldModeFlagConverter : JsonConverter<FieldMode> { Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)114 public override FieldMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 115 { 116 FieldMode flags = 0; 117 118 if(reader.TokenType != JsonTokenType.StartArray) 119 { 120 throw new JsonException("Expected a start of a flag array"); 121 } 122 123 while(reader.Read()) 124 { 125 if(reader.TokenType == JsonTokenType.EndArray) 126 { 127 return flags; 128 } 129 130 var flagStr = reader.GetString(); 131 foreach(var flag in Enum.GetValues(typeof(FieldMode))) 132 { 133 if(flagStr == flag.ToString()) 134 { 135 flags |= (FieldMode)flag; 136 } 137 } 138 } 139 140 throw new JsonException("Unexpected end of stream"); 141 } 142 Write(Utf8JsonWriter writer, FieldMode fieldMode, JsonSerializerOptions options)143 public override void Write(Utf8JsonWriter writer, FieldMode fieldMode, JsonSerializerOptions options) 144 { 145 throw new JsonException("Write not supported"); 146 } 147 } 148 149 public class RdlField 150 { 151 public string Name { get; set; } 152 public uint Low { get; set; } 153 public uint High { get; set; } 154 public FieldMode Mode { get; set; } 155 public string FieldType { get; set; } 156 GetFieldType()157 public Type GetFieldType() => 158 Type.GetType("Antmicro.Renode.Core.Structure.Registers." + FieldType + ", Infrastructure"); 159 } 160 161 public class RdlRegister 162 { 163 public string ClassName { get; set; } 164 public string InstanceName { get; set; } 165 public ulong Offset { get; set; } 166 public ulong ResetValue { get; set; } 167 public List<RdlField> Fields { get; set; } 168 } 169 170 public class RdlMeta 171 { 172 public string File { get; set; } 173 public string Class { get; set; } 174 public string RegisterContainerClass { get; set; } 175 public List<RdlRegister> Registers { get; set; } 176 GetClass()177 public Type GetClass() 178 { 179 return TypeManager.Instance.GetTypeByName(Class); 180 } 181 GetRegisterContainerClass()182 public Type GetRegisterContainerClass() => 183 Type.GetType("Antmicro.Renode.Core.Structure.Registers." + RegisterContainerClass + ", Infrastructure"); 184 } 185 186 public List<RdlMeta> TestCases { get; set; } 187 InitPeripheral(RdlMeta meta)188 private void InitPeripheral(RdlMeta meta) 189 { 190 if(meta.File != "") 191 { 192 var assembly = LoadedAssemblies.Instance.LoadAssembly(meta); 193 Console.WriteLine("Loaded extra peripheral code, assembly: " + assembly.FullName); 194 } 195 pType = meta.GetClass(); 196 Assert.IsNotNull(pType); 197 peripheral = (IDoubleWordPeripheral)Activator.CreateInstance(pType); 198 Assert.IsNotNull(peripheral); 199 } 200 201 [Test, TestCaseSource(nameof(GetTestCases))] TestStaticMeta(RdlMeta meta)202 public void TestStaticMeta(RdlMeta meta) 203 { 204 Console.WriteLine("Checking structure of " + meta.Class + "..."); 205 InitPeripheral(meta); 206 207 var classes = pType.GetTypeInfo().DeclaredNestedTypes.ToDictionary(ti => ti.Name); 208 var cFields = pType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) 209 .ToDictionary(fi => fi.Name); 210 211 Assert.AreEqual(meta.Registers.Count, classes.Count); 212 213 var registersCollection = pType.GetProperty("RegistersCollection"); 214 Assert.NotNull(registersCollection); 215 Assert.AreEqual(meta.GetRegisterContainerClass(), registersCollection.PropertyType); 216 217 foreach(var register in meta.Registers) 218 { 219 Console.WriteLine("- Checking register " + register.InstanceName + "..."); 220 221 222 Assert.IsTrue(classes.ContainsKey(register.ClassName)); 223 Assert.IsTrue(cFields.ContainsKey(register.InstanceName)); 224 225 var rClass = classes[register.ClassName]; 226 var rInstance = cFields[register.InstanceName]; 227 228 Assert.AreEqual(rClass, rInstance.FieldType); 229 230 foreach(var field in register.Fields) 231 { 232 Console.WriteLine(" - Checking field " + register.InstanceName + "." + field.Name + "..."); 233 var rField = rClass.GetField(field.Name); 234 Assert.IsNotNull(rField); 235 Assert.AreEqual(field.GetFieldType(), rField.FieldType); 236 } 237 } 238 } 239 240 [Test, TestCaseSource(nameof(GetTestCases))] TestDynamicMeta(RdlMeta meta)241 public void TestDynamicMeta(RdlMeta meta) 242 { 243 Console.WriteLine("Checking behavior of " + meta.Class + "..."); 244 245 var getPrivateFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField; 246 247 InitPeripheral(meta); 248 249 foreach(var register in meta.Registers) 250 { 251 var regInst = pType.GetField(register.InstanceName, getPrivateFlags).GetValue(peripheral); 252 253 foreach(var field in register.Fields) 254 { 255 Console.WriteLine("Testing " + pType.ToString() + "." + register.InstanceName + "." + field.Name + "..."); 256 257 var fieldField = regInst.GetType().GetField(field.Name, getPrivateFlags); 258 Assert.AreEqual(field.GetFieldType(), fieldField.FieldType); 259 260 var fieldInst = fieldField.GetValue(regInst); 261 262 var fieldMode = this.RegisterField.GetField("fieldMode").GetValue(fieldInst); 263 var position = this.RegisterField.GetField("position").GetValue(fieldInst); 264 var width = this.RegisterField.GetField("width").GetValue(fieldInst); 265 Assert.AreEqual(field.Mode, fieldMode); 266 Assert.AreEqual(field.Low, position); 267 Assert.AreEqual(field.High - field.Low + 1, width); 268 269 270 271 if(fieldInst.GetType() == this.ValueRegisterField) 272 { 273 TestFieldMode((IValueRegisterField)fieldInst, register.Offset, (int)field.Low, field.Mode); 274 TestFieldReset((IValueRegisterField)fieldInst, (int)field.Low, register.ResetValue); 275 } 276 else if(fieldInst.GetType() == this.FlagRegisterField) 277 { 278 TestFieldMode((IFlagRegisterField)fieldInst, register.Offset, (int)field.Low, field.Mode); 279 TestFieldReset((IFlagRegisterField)fieldInst, (int)field.Low, register.ResetValue); 280 } 281 else 282 { 283 Assert.Fail("Unhandled underlying field type: " + fieldInst.GetType()); 284 } 285 } 286 } 287 } 288 TestPattern(uint width = sizeof(ulong) * 8)289 static private IEnumerable<ulong> TestPattern(uint width = sizeof(ulong) * 8) 290 { 291 yield return 0; 292 for(int i = 0; i < width; ++i) 293 { 294 yield return 1UL << i; 295 } 296 } 297 TestPatternMask(uint width = sizeof(ulong) * 8)298 static private IEnumerable<ulong> TestPatternMask(uint width = sizeof(ulong) * 8) 299 { 300 ulong l = 0; 301 for(int i = 0; i < width; i += 2) 302 { 303 l |= 1UL << i; 304 } 305 yield return l; 306 yield return l << 1; 307 } 308 TestFieldModeRead(IRegisterField<ulong> field, ulong offset, int low)309 private void TestFieldModeRead(IRegisterField<ulong> field, ulong offset, int low) 310 { 311 foreach(var pat in TestPattern((uint)field.Width)) 312 { 313 ReportPattern(pat); 314 315 field.Value = pat; 316 var read = peripheral.ReadDoubleWord((long)offset); 317 Assert.AreEqual(pat, BitHelper.GetMaskedValue(read, low, field.Width) >> low); 318 read = peripheral.ReadDoubleWord((long)offset); // Another check to ensure that the value was not modified by the read. 319 Assert.AreEqual(pat, BitHelper.GetMaskedValue(read, low, field.Width) >> low); 320 } 321 } 322 TestFieldModeRead(IRegisterField<bool> field, ulong offset, int low)323 private void TestFieldModeRead(IRegisterField<bool> field, ulong offset, int low) 324 { 325 field.Value = false; 326 var read = peripheral.ReadDoubleWord((long)offset); 327 Assert.AreEqual(0, BitHelper.GetMaskedValue(read, low, field.Width)); 328 read = peripheral.ReadDoubleWord((long)offset); 329 Assert.AreEqual(0, BitHelper.GetMaskedValue(read, low, field.Width)); 330 331 field.Value = true; 332 read = peripheral.ReadDoubleWord((long)offset); 333 Assert.AreEqual(1, BitHelper.GetMaskedValue(read, low, field.Width) >> low); 334 read = peripheral.ReadDoubleWord((long)offset); 335 Assert.AreEqual(1, BitHelper.GetMaskedValue(read, low, field.Width) >> low); 336 } 337 TestFieldModeReadToClear(IRegisterField<ulong> field, ulong offset)338 private void TestFieldModeReadToClear(IRegisterField<ulong> field, ulong offset) 339 { 340 field.Value = BitHelper.GetMaskedValue(~0UL, 0, field.Width) ; 341 peripheral.ReadDoubleWord((long)offset); 342 Assert.AreEqual(0, field.Value); 343 } 344 TestFieldModeReadToClear(IRegisterField<bool> field, ulong offset)345 private void TestFieldModeReadToClear(IRegisterField<bool> field, ulong offset) 346 { 347 field.Value = false; 348 peripheral.ReadDoubleWord((long)offset); 349 Assert.AreEqual(false, field.Value); 350 351 field.Value = true; 352 peripheral.ReadDoubleWord((long)offset); 353 Assert.AreEqual(false, field.Value); 354 } 355 TestFieldModeReadToSet(IRegisterField<ulong> field, ulong offset)356 private void TestFieldModeReadToSet(IRegisterField<ulong> field, ulong offset) 357 { 358 field.Value = 0UL; 359 peripheral.ReadDoubleWord((long)offset); 360 Assert.AreEqual(~0UL, field.Value); 361 } 362 TestFieldModeReadToSet(IRegisterField<bool> field, ulong offset)363 private void TestFieldModeReadToSet(IRegisterField<bool> field, ulong offset) 364 { 365 field.Value = false; 366 peripheral.ReadDoubleWord((long)offset); 367 Assert.AreEqual(true, field.Value); 368 369 field.Value = true; 370 peripheral.ReadDoubleWord((long)offset); 371 Assert.AreEqual(true, field.Value); 372 } 373 TestFieldModeWrite(IRegisterField<ulong> field, ulong offset, int low, bool negate = false)374 private void TestFieldModeWrite(IRegisterField<ulong> field, ulong offset, int low, bool negate = false) 375 { 376 foreach(var pat in TestPattern((uint)field.Width)) 377 { 378 ReportPattern(pat); 379 380 var v = (negate ? ~(uint)pat : (uint)pat) << low; 381 peripheral.WriteDoubleWord((long)offset, v); 382 Assert.AreEqual(pat, field.Value); 383 peripheral.WriteDoubleWord((long)offset, v); 384 Assert.AreEqual(pat, field.Value); 385 } 386 } 387 TestFieldModeWrite(IRegisterField<bool> field, ulong offset, int low, bool negate = false)388 private void TestFieldModeWrite(IRegisterField<bool> field, ulong offset, int low, bool negate = false) 389 { 390 field.Value = false; 391 peripheral.WriteDoubleWord((long)offset, negate ? (1U << low) : 0U); 392 Assert.AreEqual(false, field.Value); 393 394 peripheral.WriteDoubleWord((long)offset, negate ? 0 : (1U << low)); 395 Assert.AreEqual(true, field.Value); 396 peripheral.WriteDoubleWord((long)offset, negate ? 0 : (1U << low)); 397 Assert.AreEqual(true, field.Value); 398 } 399 TestFieldModeSet(IRegisterField<ulong> field, ulong offset, int low, bool negate = false)400 private void TestFieldModeSet(IRegisterField<ulong> field, ulong offset, int low, bool negate = false) 401 { 402 foreach(var mask in TestPatternMask((uint)field.Width)) 403 { 404 foreach(var pat in TestPattern((uint)field.Width)) 405 { 406 ReportMaskAndPattern(mask, pat); 407 408 var v = (negate ? ~(uint)pat : (uint)pat) << low; 409 field.Value = mask; 410 peripheral.WriteDoubleWord((long)offset, v); 411 Assert.AreEqual(mask | pat, field.Value); 412 peripheral.WriteDoubleWord((long)offset, v); 413 Assert.AreEqual(mask | pat, field.Value); 414 peripheral.WriteDoubleWord((long)offset, 0U); 415 Assert.AreEqual(mask | pat, field.Value); 416 } 417 } 418 } 419 TestFieldModeSet(IRegisterField<bool> field, ulong offset, int low, bool negate = false)420 private void TestFieldModeSet(IRegisterField<bool> field, ulong offset, int low, bool negate = false) 421 { 422 field.Value = false; 423 peripheral.WriteDoubleWord((long)offset, negate ? (1U << low) : 0U); 424 Assert.AreEqual(false, field.Value); 425 426 peripheral.WriteDoubleWord((long)offset, negate ? 0 : (1U << low)); 427 Assert.AreEqual(true, field.Value); 428 peripheral.WriteDoubleWord((long)offset, negate ? 0 : (1U << low)); 429 Assert.AreEqual(true, field.Value); 430 peripheral.WriteDoubleWord((long)offset, negate ? (1U << low) : 0); 431 Assert.AreEqual(true, field.Value); 432 } 433 TestFieldModeToggle(IRegisterField<ulong> field, ulong offset, int low, bool negate = false)434 private void TestFieldModeToggle(IRegisterField<ulong> field, ulong offset, int low, bool negate = false) 435 { 436 foreach(var mask in TestPatternMask((uint)field.Width)) 437 { 438 field.Value = mask; 439 foreach(var pat in TestPattern((uint)field.Width)) 440 { 441 ReportMaskAndPattern(mask, pat); 442 443 var v = (negate ? ~(uint)pat : (uint)pat) << low; 444 peripheral.WriteDoubleWord((long)offset, v); 445 Assert.AreEqual((mask | pat) & ~(mask & pat), field.Value); 446 peripheral.WriteDoubleWord((long)offset, v); 447 Assert.AreEqual(mask, field.Value); 448 } 449 } 450 } 451 TestFieldModeToggle(IRegisterField<bool> field, ulong offset, int low, bool negate = false)452 private void TestFieldModeToggle(IRegisterField<bool> field, ulong offset, int low, bool negate = false) 453 { 454 field.Value = false; 455 peripheral.WriteDoubleWord((long)offset, negate ? (1U << low) : 0U); 456 Assert.AreEqual(false, field.Value); 457 458 peripheral.WriteDoubleWord((long)offset, negate ? 0 : (1U << low)); 459 Assert.AreEqual(true, field.Value); 460 peripheral.WriteDoubleWord((long)offset, negate ? (1U << low) : 0U); 461 Assert.AreEqual(true, field.Value); 462 463 peripheral.WriteDoubleWord((long)offset, negate ? 0 : (1U << low)); 464 Assert.AreEqual(false, field.Value); 465 } 466 TestFieldModeWriteOneToClear(IRegisterField<ulong> field, ulong offset, int low, bool negate = false)467 private void TestFieldModeWriteOneToClear(IRegisterField<ulong> field, ulong offset, int low, bool negate = false) 468 { 469 foreach(var mask in TestPatternMask((uint)field.Width)) 470 { 471 foreach(var pat in TestPattern((uint)field.Width)) 472 { 473 ReportMaskAndPattern(mask, pat); 474 475 var v = (negate ? ~(uint)pat : (uint)pat) << low; 476 field.Value = mask; 477 peripheral.WriteDoubleWord((long)offset, v); 478 Assert.AreEqual(mask & ~pat, field.Value); 479 } 480 481 } 482 } 483 TestFieldModeWriteOneToClear(IRegisterField<bool> field, ulong offset, int low, bool negate = false)484 private void TestFieldModeWriteOneToClear(IRegisterField<bool> field, ulong offset, int low, bool negate = false) 485 { 486 field.Value = true; 487 peripheral.WriteDoubleWord((long)offset, negate ? (1U << low) : 0U); 488 Assert.AreEqual(true, field.Value); 489 490 peripheral.WriteDoubleWord((long)offset, negate ? 0U : (1U << low)); 491 Assert.AreEqual(false, field.Value); 492 493 peripheral.WriteDoubleWord((long)offset, negate ? 0U : (1U << low)); 494 Assert.AreEqual(false, field.Value); 495 } 496 ReportPattern(ulong pat)497 private static void ReportPattern(ulong pat) 498 { 499 Console.WriteLine(" - Test pattern: " + FormatBits(pat)); 500 } 501 ReportMaskAndPattern(ulong mask, ulong pat)502 private static void ReportMaskAndPattern(ulong mask, ulong pat) 503 { 504 Console.WriteLine(" - Test Mask: " + FormatBits(mask)); 505 Console.WriteLine(" Test pattern: " + FormatBits(pat)); 506 } 507 TestFieldMode(IRegisterField<ulong> field, ulong offset, int low, FieldMode mode)508 private void TestFieldMode(IRegisterField<ulong> field, ulong offset, int low, FieldMode mode) 509 { 510 if(FieldModeHelper.ReadBits(mode) != 0) 511 { 512 Console.WriteLine(" Performing read test..."); 513 } 514 switch(FieldModeHelper.ReadBits(mode)) 515 { 516 case FieldMode.Read: TestFieldModeRead(field, offset, low); break; 517 case FieldMode.ReadToClear: TestFieldModeReadToClear(field, offset); break; 518 case FieldMode.ReadToSet: TestFieldModeReadToSet(field, offset); break; 519 } 520 521 if(FieldModeHelper.WriteBits(mode) != 0) 522 { 523 Console.WriteLine(" Performing write test..."); 524 } 525 switch(FieldModeHelper.WriteBits(mode)) 526 { 527 case FieldMode.Write: TestFieldModeWrite(field, offset, low); break; 528 case FieldMode.Set: TestFieldModeSet(field, offset, low); break; 529 case FieldMode.Toggle: TestFieldModeToggle(field, offset, low); break; 530 case FieldMode.WriteOneToClear: TestFieldModeWriteOneToClear(field, offset, low); break; 531 case FieldMode.WriteZeroToClear: TestFieldModeWriteOneToClear(field, offset, low, negate: true); break; 532 case FieldMode.WriteZeroToSet: TestFieldModeSet(field, offset, low, negate: true); break; 533 case FieldMode.WriteZeroToToggle: TestFieldModeToggle(field, offset, low, negate: true); break; 534 } 535 } 536 TestFieldMode(IRegisterField<bool> field, ulong offset, int low, FieldMode mode)537 private void TestFieldMode(IRegisterField<bool> field, ulong offset, int low, FieldMode mode) 538 { 539 if(FieldModeHelper.ReadBits(mode) != 0) 540 { 541 Console.WriteLine(" Performing read test..."); 542 } 543 switch(FieldModeHelper.ReadBits(mode)) 544 { 545 case FieldMode.Read: TestFieldModeRead(field, offset, low); break; 546 case FieldMode.ReadToClear: TestFieldModeReadToClear(field, offset); break; 547 case FieldMode.ReadToSet: TestFieldModeReadToSet(field, offset); break; 548 } 549 550 if(FieldModeHelper.WriteBits(mode) != 0) 551 { 552 Console.WriteLine(" Performing write test..."); 553 } 554 switch(FieldModeHelper.WriteBits(mode)) 555 { 556 case FieldMode.Write: TestFieldModeWrite(field, offset, low); break; 557 case FieldMode.Set: TestFieldModeSet(field, offset, low); break; 558 case FieldMode.Toggle: TestFieldModeToggle(field, offset, low); break; 559 case FieldMode.WriteOneToClear: TestFieldModeWriteOneToClear(field, offset, low); break; 560 case FieldMode.WriteZeroToClear: TestFieldModeWriteOneToClear(field, offset, low, negate: true); break; 561 case FieldMode.WriteZeroToSet: TestFieldModeSet(field, offset, low, negate: true); break; 562 case FieldMode.WriteZeroToToggle: TestFieldModeToggle(field, offset, low, negate: true); break; 563 } 564 } 565 TestFieldReset(IRegisterField<ulong> field, int low, ulong registerResetValue)566 void TestFieldReset(IRegisterField<ulong> field, int low, ulong registerResetValue) 567 { 568 var expect = registerResetValue >> low; 569 field.Value = BitHelper.GetMaskedValue(~expect, 0, field.Width); 570 571 var registers = (peripheral as IProvidesRegisterCollection<DoubleWordRegisterCollection>).RegistersCollection; 572 registers.Reset(); 573 574 Assert.AreEqual(field.Value, expect); 575 } 576 TestFieldReset(IRegisterField<bool> field, int low, ulong registerResetValue)577 void TestFieldReset(IRegisterField<bool> field, int low, ulong registerResetValue) 578 { 579 var expect = BitHelper.GetMaskedValue(registerResetValue >> low, 0, 1) == 1; 580 field.Value = !expect; 581 582 var registers = (peripheral as IProvidesRegisterCollection<DoubleWordRegisterCollection>).RegistersCollection; 583 registers.Reset(); 584 585 Assert.AreEqual(field.Value, expect); 586 } 587 588 // Older .NET versions do not support "b" format specifier FormatBits(ulong value)589 static string FormatBits(ulong value) 590 { 591 string res = ""; 592 foreach(var bit in BitHelper.GetBits(value).Reverse()) 593 { 594 res += bit ? '1' : '0'; 595 } 596 return res; 597 } 598 599 private IDoubleWordPeripheral peripheral; 600 private Type pType; 601 602 private Type ValueRegisterField; 603 private Type FlagRegisterField; 604 private Type RegisterField; 605 606 private const string SystemRDLResource = "Antmicro.Renode.PeripheralsTests.SystemRDLJson"; 607 } 608 } 609