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 Antmicro.Renode.Core;
11 using Antmicro.Renode.Peripherals;
12 using Antmicro.Renode.Peripherals.Bus;
13 using Antmicro.Renode.Peripherals.CPU;
14 using Antmicro.Renode.Utilities;
15 using NUnit.Framework;
16 using Moq;
17 using System.Linq;
18 using System.Collections.Generic;
19 using Antmicro.Renode.Peripherals.Memory;
20 using Antmicro.Renode.Core.Structure.Registers;
21 using Antmicro.Renode.Peripherals.Mocks;
22 
23 namespace Antmicro.Renode.UnitTests
24 {
25     [TestFixture]
26     public class SystemBusTests
27     {
28         [SetUp]
SetUp()29         public void SetUp()
30         {
31             var machine = new Machine();
32             EmulationManager.Instance.CurrentEmulation.AddMachine(machine);
33             sysbus = machine.SystemBus;
34             bytes = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
35         }
36 
37         [Test]
ShouldReturnZeroAtNonExistingDevice()38         public void ShouldReturnZeroAtNonExistingDevice()
39         {
40             var read = sysbus.ReadByte(0xABCD1234);
41             Assert.AreEqual(0, read);
42         }
43 
44         [Test]
ShouldFindAfterRegistration()45         public void ShouldFindAfterRegistration()
46         {
47             var peripheral = new Mock<IDoubleWordPeripheral>();
48             peripheral.Setup(x => x.ReadDoubleWord(0)).Returns(0x666);
49             sysbus.Register(peripheral.Object, 1000.By(1000));
50             Assert.AreEqual(0x666, sysbus.ReadDoubleWord(1000));
51         }
52 
53         [Test]
ShouldFindAfterManyRegistrations()54         public void ShouldFindAfterManyRegistrations()
55         {
56             var peri1 = new Mock<IDoubleWordPeripheral>();
57             var peri2 = new Mock<IDoubleWordPeripheral>();
58             var peri3 = new Mock<IDoubleWordPeripheral>();
59             peri1.Setup(x => x.ReadDoubleWord(0)).Returns(0x666);
60             peri2.Setup(x => x.ReadDoubleWord(0)).Returns(0x667);
61             peri3.Setup(x => x.ReadDoubleWord(0)).Returns(0x668);
62             sysbus.Register(peri1.Object, 1000.By(100));
63             sysbus.Register(peri2.Object, 2000.By(100));
64             sysbus.Register(peri3.Object, 3000.By(100));
65             Assert.AreEqual(0x666, sysbus.ReadDoubleWord(1000));
66             Assert.AreEqual(0x667, sysbus.ReadDoubleWord(2000));
67             Assert.AreEqual(0x668, sysbus.ReadDoubleWord(3000));
68         }
69 
70         [Test, Ignore("Ignored")]
ShouldFindAfterManyRegistrationsAndRemoves()71         public void ShouldFindAfterManyRegistrationsAndRemoves()
72         {
73             const int NumberOfPeripherals = 100;
74             var MaximumPeripheralSize = 16.KB();
75 
76             var regPoints = new ulong[NumberOfPeripherals];
77             var unregisteredPoints = new HashSet<ulong>();
78             var random = EmulationManager.Instance.CurrentEmulation.RandomGenerator;
79             var lastPoint = 4u;
80             for(var i = 0; i < NumberOfPeripherals; i++)
81             {
82                 // gap
83                 lastPoint += (uint)random.Next(MaximumPeripheralSize);
84                 var size = (uint)random.Next(1, MaximumPeripheralSize + 1);
85                 regPoints[i] = lastPoint;
86                 var mock = new Mock<IDoubleWordPeripheral>();
87                 mock.Setup(x => x.ReadDoubleWord(0)).Returns((uint)regPoints[i]);
88                 sysbus.Register(mock.Object, lastPoint.By(size));
89                 // peripheral
90                 lastPoint += size;
91             }
92 
93             // now remove random devices
94             for(var i = 0; i < NumberOfPeripherals; i++)
95             {
96                 if(random.Next(100) < 10)
97                 {
98                     sysbus.UnregisterFromAddress(regPoints[i], context: null);
99                     unregisteredPoints.Add(regPoints[i]);
100                 }
101             }
102 
103             // finally some assertions
104             for(var i = 0; i < NumberOfPeripherals; i++)
105             {
106                 var value = sysbus.ReadDoubleWord(regPoints[i]);
107                 if(unregisteredPoints.Contains(regPoints[i]))
108                 {
109                     Assert.AreEqual(0, value);
110                 }
111                 else
112                 {
113                     Assert.AreEqual(regPoints[i], value);
114                 }
115             }
116         }
117 
118         [Test]
ShouldPauseAndResumeOnlyOnce()119         public void ShouldPauseAndResumeOnlyOnce()
120         {
121             using(var emulation = new Emulation())
122             using(var machine = new Machine())
123             {
124                 emulation.AddMachine(machine);
125                 var sb = machine.SystemBus;
126                 var mock = new Mock<IHasOwnLife>();
127                 sb.Register(mock.As<IDoubleWordPeripheral>().Object, 0.To(100));
128 
129                 var cpuMock = new Mock<ICPU>();
130                 cpuMock.Setup(cpu => cpu.Architecture).Returns("mock");  // Required by InitializeInvalidatedAddressesList.
131                 sb.Register(cpuMock.Object, new CPURegistrationPoint());
132 
133                 machine.Start();
134                 PauseResumeRetries.Times(machine.Pause);
135                 mock.Verify(x => x.Pause(), Times.Once());
136                 PauseResumeRetries.Times(machine.Start);
137                 mock.Verify(x => x.Resume(), Times.Once());
138             }
139         }
140 
141         [Test]
ShouldRegisterMultiFunctionPeripheral()142         public void ShouldRegisterMultiFunctionPeripheral()
143         {
144             var multiRegistration1 = new BusMultiRegistration(0, 100, "region1");
145             var multiRegistration2 = new BusMultiRegistration(100, 200, "region2");
146             var peripheral = new MultiRegistrationPeripheral();
147             sysbus.Register(peripheral, multiRegistration1);
148             sysbus.Register(peripheral, multiRegistration2);
149             sysbus.Register(peripheral, new BusRangeRegistration(300, 100));
150 
151             Assert.AreEqual(false, peripheral.ByteRead1);
152             Assert.AreEqual(false, peripheral.ByteRead2);
153             Assert.AreEqual(false, peripheral.ByteWritten1);
154             Assert.AreEqual(false, peripheral.ByteWritten2);
155             Assert.AreEqual(false, peripheral.DoubleWordRead);
156             Assert.AreEqual(false, peripheral.DoubleWordWritten);
157 
158             sysbus.ReadByte(10);
159 
160             Assert.AreEqual(true, peripheral.ByteRead1);
161             Assert.AreEqual(false, peripheral.ByteRead2);
162             Assert.AreEqual(false, peripheral.ByteWritten1);
163             Assert.AreEqual(false, peripheral.ByteWritten2);
164             Assert.AreEqual(false, peripheral.DoubleWordRead);
165             Assert.AreEqual(false, peripheral.DoubleWordWritten);
166 
167             sysbus.ReadByte(110);
168 
169             Assert.AreEqual(true, peripheral.ByteRead1);
170             Assert.AreEqual(true, peripheral.ByteRead2);
171             Assert.AreEqual(false, peripheral.ByteWritten1);
172             Assert.AreEqual(false, peripheral.ByteWritten2);
173             Assert.AreEqual(false, peripheral.DoubleWordRead);
174             Assert.AreEqual(false, peripheral.DoubleWordWritten);
175 
176             sysbus.WriteByte(10, 0);
177 
178             Assert.AreEqual(true, peripheral.ByteRead1);
179             Assert.AreEqual(true, peripheral.ByteRead2);
180             Assert.AreEqual(true, peripheral.ByteWritten1);
181             Assert.AreEqual(false, peripheral.ByteWritten2);
182             Assert.AreEqual(false, peripheral.DoubleWordRead);
183             Assert.AreEqual(false, peripheral.DoubleWordWritten);
184 
185             sysbus.WriteByte(110, 0);
186 
187             Assert.AreEqual(true, peripheral.ByteRead1);
188             Assert.AreEqual(true, peripheral.ByteRead2);
189             Assert.AreEqual(true, peripheral.ByteWritten1);
190             Assert.AreEqual(true, peripheral.ByteWritten2);
191             Assert.AreEqual(false, peripheral.DoubleWordRead);
192             Assert.AreEqual(false, peripheral.DoubleWordWritten);
193 
194             sysbus.ReadDoubleWord(310);
195 
196             Assert.AreEqual(true, peripheral.ByteRead1);
197             Assert.AreEqual(true, peripheral.ByteRead2);
198             Assert.AreEqual(true, peripheral.ByteWritten1);
199             Assert.AreEqual(true, peripheral.ByteWritten2);
200             Assert.AreEqual(true, peripheral.DoubleWordRead);
201             Assert.AreEqual(false, peripheral.DoubleWordWritten);
202 
203             sysbus.WriteDoubleWord(310, 0);
204 
205             Assert.AreEqual(true, peripheral.ByteRead1);
206             Assert.AreEqual(true, peripheral.ByteRead2);
207             Assert.AreEqual(true, peripheral.ByteWritten1);
208             Assert.AreEqual(true, peripheral.ByteWritten2);
209             Assert.AreEqual(true, peripheral.DoubleWordRead);
210             Assert.AreEqual(true, peripheral.DoubleWordWritten);
211         }
212 
213         [Test]
ShouldRegisterParametrizedPeripheral()214         public void ShouldRegisterParametrizedPeripheral()
215         {
216             var parametrizedRegistration = new ParametrizedRegistrationPeripheral.Registration(0, 100);
217             var peripheral = new ParametrizedRegistrationPeripheral();
218             sysbus.Register(peripheral, parametrizedRegistration);
219             sysbus.Register(peripheral, new BusRangeRegistration(200, 100));
220 
221             Assert.AreEqual(false, peripheral.ByteRead);
222             Assert.AreEqual(false, peripheral.ByteWritten);
223             Assert.AreEqual(false, peripheral.DoubleWordRead);
224             Assert.AreEqual(false, peripheral.DoubleWordWritten);
225 
226             sysbus.ReadByte(10);
227 
228             Assert.AreEqual(true, peripheral.ByteRead);
229             Assert.AreEqual(false, peripheral.ByteWritten);
230             Assert.AreEqual(false, peripheral.DoubleWordRead);
231             Assert.AreEqual(false, peripheral.DoubleWordWritten);
232 
233             sysbus.WriteByte(10, 0);
234 
235             Assert.AreEqual(true, peripheral.ByteRead);
236             Assert.AreEqual(true, peripheral.ByteWritten);
237             Assert.AreEqual(false, peripheral.DoubleWordRead);
238             Assert.AreEqual(false, peripheral.DoubleWordWritten);
239 
240             sysbus.ReadDoubleWord(10);
241 
242             Assert.AreEqual(true, peripheral.ByteRead);
243             Assert.AreEqual(true, peripheral.ByteWritten);
244             Assert.AreEqual(true, peripheral.DoubleWordRead);
245             Assert.AreEqual(false, peripheral.DoubleWordWritten);
246 
247             sysbus.WriteDoubleWord(10, 0);
248 
249             Assert.AreEqual(true, peripheral.ByteRead);
250             Assert.AreEqual(true, peripheral.ByteWritten);
251             Assert.AreEqual(true, peripheral.DoubleWordRead);
252             Assert.AreEqual(true, peripheral.DoubleWordWritten);
253         }
254 
255         [Test]
ShouldTestEnableAllTranslations()256         public void ShouldTestEnableAllTranslations()
257         {
258             var testData = new Tuple<int, IBusPeripheral> []
259             {
260                 Tuple.Create(64, (IBusPeripheral)new MockQuadWordPeripheralWithoutTranslations()),
261                 Tuple.Create(32, (IBusPeripheral)new MockDoubleWordPeripheralWithoutTranslations()),
262                 Tuple.Create(16, (IBusPeripheral)new MockWordPeripheralWithoutTranslations()),
263                 Tuple.Create(8, (IBusPeripheral)new MockBytePeripheralWithoutTranslations())
264             };
265 
266             ulong address = 0;
267             foreach(var data in testData)
268             {
269                 var implementedWidth = data.Item1;
270                 var peripheral = data.Item2;
271                 sysbus.Register(peripheral, new BusRangeRegistration(address, 8));
272                 sysbus.Register(peripheral, new BusMultiRegistration(address + 8, 8, "region"));
273                 address += 16;
274             }
275 
276             var testValue = 0xdeadc0de12345678;
277             for(var i = 0; i < testData.Length; i += 1)
278             {
279                 var implementedWidth = testData[i].Item1;
280                 testAllTranslatedAccesses((ulong)i * 16, testValue, implementedWidth);
281                 testAllTranslatedAccesses((ulong)i * 16 + 8, testValue, implementedWidth);
282             }
283         }
284 
285         [Test]
ShouldHandleWriteToMemorySegment()286         public void ShouldHandleWriteToMemorySegment()
287         {
288             CreateMachineAndExecute(sysbus =>
289             {
290                 // bytes fit into memory segment
291                 sysbus.WriteBytes(bytes, 4);
292                 Assert.AreEqual(bytes, sysbus.ReadBytes(4, 8));
293             });
294         }
295 
296         [Test]
ShouldHandlePartialWriteToMemorySegmentAtTheBeginning()297         public void ShouldHandlePartialWriteToMemorySegmentAtTheBeginning()
298         {
299             CreateMachineAndExecute(sysbus =>
300             {
301                 // beginning of bytes fits into memory segment
302                 sysbus.WriteBytes(bytes, 10);
303                 Assert.AreEqual(bytes.Take(6).Concat(Enumerable.Repeat((byte)0, 2)).ToArray(), sysbus.ReadBytes(10, 8));
304             });
305         }
306 
307         [Test]
ShouldReadBytes([Values(true, false)] bool isFirstMemory, [Values(true, false)] bool isSecondMemory)308         public void ShouldReadBytes([Values(true, false)] bool isFirstMemory, [Values(true, false)] bool isSecondMemory)
309         {
310             var peri1Values = new Dictionary<long, byte>();
311             var peri2Values = new Dictionary<long, byte>();
312             var machine = new Machine();
313             if(isFirstMemory)
314             {
315                 machine.SystemBus.Register(new MappedMemory(machine, 100), new BusPointRegistration(50));
316             }
317             else
318             {
319                 var mock = new Mock<IBytePeripheral>();
320                 mock.Setup(x => x.WriteByte(It.IsAny<long>(), It.IsAny<byte>())).Callback<long, byte>((x, y) => peri1Values.Add(x, y));
321                 mock.Setup(x => x.ReadByte(It.IsAny<long>())).Returns<long>(x => peri1Values[x]);
322                 machine.SystemBus.Register(mock.Object, new BusRangeRegistration(50, 100));
323             }
324 
325             if(isSecondMemory)
326             {
327                 machine.SystemBus.Register(new MappedMemory(machine, 100), new BusPointRegistration(200));
328             }
329             else
330             {
331                 var mock = new Mock<IBytePeripheral>();
332                 mock.Setup(x => x.WriteByte(It.IsAny<long>(), It.IsAny<byte>())).Callback<long, byte>((x, y) => peri2Values.Add(x, y));
333                 mock.Setup(x => x.ReadByte(It.IsAny<long>())).Returns<long>(x => peri2Values[x]);
334                 machine.SystemBus.Register(mock.Object, new BusRangeRegistration(200, 100));
335             }
336             var testArray = Enumerable.Range(0, 350).Select(x => (byte)(x % byte.MaxValue)).ToArray();
337             machine.SystemBus.WriteBytes(testArray, 0);
338             var resultArray = machine.SystemBus.ReadBytes(0, 350);
339             int i = 0;
340             for(; i < 50; ++i)
341             {
342                 Assert.AreEqual(0, resultArray[i]);
343             }
344             for(; i < 150; ++i)
345             {
346                 Assert.AreEqual(testArray[i], resultArray[i]);
347             }
348             for(; i < 200; ++i)
349             {
350                 Assert.AreEqual(0, resultArray[i]);
351             }
352             for(; i < 300; ++i)
353             {
354                 Assert.AreEqual(testArray[i], resultArray[i]);
355             }
356             for(; i < 350; ++i)
357             {
358                 Assert.AreEqual(0, resultArray[i]);
359             }
360         }
361 
362         [Test]
ShouldHandlePartialWriteToMemorySegmentAtTheEnd()363         public void ShouldHandlePartialWriteToMemorySegmentAtTheEnd()
364         {
365             CreateMachineAndExecute(sysbus =>
366             {
367                 // beginning of bytes fits into memory segment
368                 sysbus.WriteBytes(bytes, 0xC0000000 - 4);
369                 Assert.AreEqual(Enumerable.Repeat((byte)0, 4).Concat(bytes.Skip(4).Take(4)).ToArray(), sysbus.ReadBytes(0xC0000000 - 4, 8));
370             });
371         }
372 
373         [Test]
ShouldHandleWriteToAHoleBetweenMemorySegments()374         public void ShouldHandleWriteToAHoleBetweenMemorySegments()
375         {
376             CreateMachineAndExecute(sb =>
377             {
378                 // bytes do not fit into memory segment
379                 sb.WriteBytes(bytes, 100);
380                 Assert.AreEqual(Enumerable.Repeat((byte)0, 8).ToArray(), sb.ReadBytes(100, 8));
381             });
382         }
383 
384         [Test]
ShouldHandleWriteOverlappingMemorySegment()385         public void ShouldHandleWriteOverlappingMemorySegment()
386         {
387             CreateMachineAndExecute(sysbus =>
388             {
389                 // bytes overlap memory segment
390                 var hugeBytes = Enumerable.Range(0, 32).Select(i => (byte)i).ToArray();
391                 sysbus.WriteBytes(hugeBytes, 0xC0000000 - 4);
392                 Assert.AreEqual(Enumerable.Repeat((byte)0, 4).Concat(hugeBytes.Skip(4).Take(16)).Concat(Enumerable.Repeat((byte)0, 12)).ToArray(), sysbus.ReadBytes(0xC0000000 - 4, 32));
393             });
394         }
395 
CreateMachineAndExecute(Action<IBusController> action)396         private void CreateMachineAndExecute(Action<IBusController> action)
397         {
398             using(var machine = new Machine())
399             {
400                 var sb = machine.SystemBus;
401                 var memory = new MappedMemory(machine, 16);
402                 sb.Register(memory, 0.By(16));
403                 sb.Register(memory, 0xC0000000.By(16));
404 
405                 action(sb);
406             }
407         }
408 
testAllTranslatedAccesses(ulong address, ulong testValue, int implementedWidth)409         private void testAllTranslatedAccesses(ulong address, ulong testValue, int implementedWidth)
410         {
411             var widths = new int [] { 8, 16, 32, 64 };
412             var types = new dynamic []
413             {
414                 (Func<ulong, byte>)Convert.ToByte,
415                 (Func<ulong, ushort>)Convert.ToUInt16,
416                 (Func<ulong, uint>)Convert.ToUInt32,
417                 (Func<ulong, ulong>)Convert.ToUInt64,
418             };
419 
420             var accessMethods = new dynamic []
421             {
422                 Tuple.Create((Func<ulong, IPeripheral, ulong?, byte>)sysbus.ReadByte, (Action<ulong, byte, IPeripheral, ulong?>)sysbus.WriteByte),
423                 Tuple.Create((Func<ulong, IPeripheral, ulong?, ushort>)sysbus.ReadWord, (Action<ulong, ushort, IPeripheral, ulong?>)sysbus.WriteWord),
424                 Tuple.Create((Func<ulong, IPeripheral, ulong?, uint>)sysbus.ReadDoubleWord, (Action<ulong, uint, IPeripheral, ulong?>)sysbus.WriteDoubleWord),
425                 Tuple.Create((Func<ulong, IPeripheral, ulong?, ulong>)sysbus.ReadQuadWord, (Action<ulong, ulong, IPeripheral, ulong?>)sysbus.WriteQuadWord),
426             };
427 
428             for(var i = 0; i < accessMethods.Length; i++)
429             {
430                 var width = widths[i];
431                 var type = types[i];
432                 var read = accessMethods[i].Item1;
433                 var write = accessMethods[i].Item2;
434 
435                 if(width == implementedWidth)
436                     continue;
437 
438                 sysbus.EnableAllTranslations();
439 
440                 for(var offset = 0; offset < 64; offset += width)
441                 {
442                     var value = type(BitHelper.GetValue(testValue, offset, width));
443                     write(address + (ulong)offset / 8, value, null, null);
444                     Assert.AreEqual(value, read(address + (ulong)offset / 8, null, null));
445                 }
446 
447                 sysbus.EnableAllTranslations(false);
448 
449                 for(var offset = 0; offset < 64; offset += width)
450                 {
451                     Assert.AreEqual(0x0, read(address + (ulong)offset / 8, null, null));
452                 }
453 
454                 sysbus.EnableAllTranslations();
455                 sysbus.WriteQuadWord(address, 0x0);
456                 Assert.AreEqual(0x0, sysbus.ReadQuadWord(address));
457             }
458         }
459 
460         private IBusController sysbus;
461         private byte[] bytes;
462         private const int PauseResumeRetries = 5;
463 
464         private class MultiRegistrationPeripheral : IBusPeripheral, IDoubleWordPeripheral
465         {
Reset()466             public void Reset()
467             {
468                 throw new NotImplementedException();
469             }
470 
471             public bool ByteRead1 { get; private set; }
472 
473             public bool ByteRead2 { get; private set; }
474 
475             public bool ByteWritten1 { get; private set; }
476 
477             public bool ByteWritten2 { get; private set; }
478 
479             public bool DoubleWordRead { get; private set; }
480 
481             public bool DoubleWordWritten { get; private set; }
482 
ReadDoubleWord(long offset)483             public uint ReadDoubleWord(long offset)
484             {
485                 DoubleWordRead = true;
486                 return 0;
487             }
488 
WriteDoubleWord(long offset, uint value)489             public void WriteDoubleWord(long offset, uint value)
490             {
491                 DoubleWordWritten = true;
492             }
493 
494             [ConnectionRegion("region1")]
ReadByte1(long offset)495             public byte ReadByte1(long offset)
496             {
497                 ByteRead1 = true;
498                 return 0;
499             }
500 
501             [ConnectionRegion("region2")]
ReadByte2(long offset)502             public byte ReadByte2(long offset)
503             {
504                 ByteRead2 = true;
505                 return 0;
506             }
507 
508             [ConnectionRegion("region1")]
WriteByte1(long offset, byte value)509             public void WriteByte1(long offset, byte value)
510             {
511                 ByteWritten1 = true;
512             }
513 
514             [ConnectionRegion("region2")]
WriteByte2(long offset, byte value)515             public void WriteByte2(long offset, byte value)
516             {
517                 ByteWritten2 = true;
518             }
519         }
520 
521         private class ParametrizedRegistrationPeripheral : IBusPeripheral, IDoubleWordPeripheral
522         {
Reset()523             public void Reset()
524             {
525                 throw new NotImplementedException();
526             }
527 
528             public bool ByteRead { get; private set; }
529 
530             public bool ByteWritten { get; private set; }
531 
532             public bool DoubleWordRead { get; private set; }
533 
534             public bool DoubleWordWritten { get; private set; }
535 
ReadDoubleWord(long offset)536             public uint ReadDoubleWord(long offset)
537             {
538                 DoubleWordRead = true;
539                 return 0;
540             }
541 
WriteDoubleWord(long offset, uint value)542             public void WriteDoubleWord(long offset, uint value)
543             {
544                 DoubleWordWritten = true;
545             }
546 
547             public class Registration : BusParametrizedRegistration
548             {
Registration(ulong address, ulong size)549                 public Registration(ulong address, ulong size) : base(address, size, null)
550                 {
551                 }
552 
GetReadByteMethod(IBusPeripheral peripheral)553                 public override Func<long, byte> GetReadByteMethod(IBusPeripheral peripheral)
554                 {
555                     var parent = peripheral as ParametrizedRegistrationPeripheral;
556                     return (offset) =>
557                     {
558                         parent.ByteRead = true;
559                         return 0;
560                     };
561                 }
562 
GetWriteByteMethod(IBusPeripheral peripheral)563                 public override Action<long, byte> GetWriteByteMethod(IBusPeripheral peripheral)
564                 {
565                     var parent = peripheral as ParametrizedRegistrationPeripheral;
566                     return (offset, value) =>
567                     {
568                         parent.ByteWritten = true;
569                     };
570                 }
571 
RegisterForEachContext(Action<BusParametrizedRegistration> register)572                 public override void RegisterForEachContext(Action<BusParametrizedRegistration> register)
573                 {
574                     RegisterForEachContextInner(register, _ => new Registration(Range.StartAddress, Range.Size));
575                 }
576             }
577         }
578     }
579 
580     public static class SysbusExtensions
581     {
Register(this SystemBus sysbus, IBusPeripheral peripheral, Antmicro.Renode.Core.Range range)582         public static void Register(this SystemBus sysbus, IBusPeripheral peripheral, Antmicro.Renode.Core.Range range)
583         {
584             sysbus.Register(peripheral, new BusRangeRegistration(range));
585         }
586     }
587 }
588