1 //
2 // Copyright (c) 2010-2023 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 using Antmicro.Renode.Core;
9 using Antmicro.Renode.Core.Structure;
10 using NUnit.Framework;
11 using System.Collections.Generic;
12 using System.Linq;
13 using Antmicro.Renode.UnitTests.Mocks;
14 using Antmicro.Renode.Peripherals.Bus;
15 
16 namespace Antmicro.Renode.UnitTests
17 {
18     [TestFixture]
19     public class GPIODetachingTests
20     {
21         IMachine machine;
22 
23         [SetUp]
SetUp()24         public void SetUp()
25         {
26             machine = new Machine();
27         }
28 
29         [Test]
ShouldGetAllGPIOConnections()30         public void ShouldGetAllGPIOConnections()
31         {
32             //init
33             var gpioByNumberConnectorPeripheralMock = new MockGPIOByNumberConnectorPeripheral(1);
34             var gpioReceiverMock = new MockReceiver();
35 
36             gpioByNumberConnectorPeripheralMock.Connections[0].Connect(gpioReceiverMock, 1);
37             machine.SystemBus.Register(gpioByNumberConnectorPeripheralMock, new BusRangeRegistration(0x0, 0x10));
38             machine.SystemBus.Register(gpioReceiverMock, new BusRangeRegistration(0x10, 0x10));
39 
40             //act
41             var connections = gpioByNumberConnectorPeripheralMock.Connections;
42 
43             //assert
44             Assert.AreEqual(1, connections.Count);
45         }
46 
47         [Test]
ShouldDetachConnectionFromGPIOByNumberConnection()48         public void ShouldDetachConnectionFromGPIOByNumberConnection()
49         {
50             //init
51             var gpioByNumberConnectorPeripheralMock = new MockGPIOByNumberConnectorPeripheral(1);
52             var gpioReceiverMock = new MockReceiver();
53 
54             gpioByNumberConnectorPeripheralMock.Connections[0].Connect(gpioReceiverMock, 1);
55             machine.SystemBus.Register(gpioByNumberConnectorPeripheralMock, new BusRangeRegistration(0x0, 0x10));
56             machine.SystemBus.Register(gpioReceiverMock, new BusRangeRegistration(0x10, 0x10));
57 
58             //act
59             ((IPeripheralRegister<IBusPeripheral, BusRangeRegistration>)machine.SystemBus).Unregister(gpioReceiverMock);
60 
61             //assert
62             var connections = gpioByNumberConnectorPeripheralMock.Connections;
63             Assert.IsEmpty(connections[0].Endpoints);
64         }
65 
66 
67         [Test]
ShouldDetachOnlyOneConnectionFromGPIOByNumberConnection()68         public void ShouldDetachOnlyOneConnectionFromGPIOByNumberConnection()
69         {
70             //init
71             var gpioByNumberConnectorPeripheralMock = new MockGPIOByNumberConnectorPeripheral(3);
72             var gpioReceiverMock = new MockReceiver();
73             var gpioReceiverMock2 = new MockReceiver();
74             var gpioReceiverMock3 = new MockReceiver();
75 
76             gpioByNumberConnectorPeripheralMock.Connections[0].Connect(gpioReceiverMock, 1);
77             gpioByNumberConnectorPeripheralMock.Connections[1].Connect(gpioReceiverMock2, 2);
78             gpioByNumberConnectorPeripheralMock.Connections[2].Connect(gpioReceiverMock3, 3);
79             machine.SystemBus.Register(gpioByNumberConnectorPeripheralMock, new BusRangeRegistration(0x00, 0x10));
80             machine.SystemBus.Register(gpioReceiverMock, new BusRangeRegistration(0x10, 0x10));
81             machine.SystemBus.Register(gpioReceiverMock2, new BusRangeRegistration(0x20, 0x10));
82             machine.SystemBus.Register(gpioReceiverMock3, new BusRangeRegistration(0x30, 0x10));
83 
84             //act
85             ((IPeripheralRegister<IBusPeripheral, BusRangeRegistration>)machine.SystemBus).Unregister(gpioReceiverMock);
86 
87             //assert
88             var connections = gpioByNumberConnectorPeripheralMock.Connections;
89             Assert.IsEmpty(connections[0].Endpoints);
90             Assert.IsNotEmpty(connections[1].Endpoints);
91             Assert.IsNotEmpty(connections[2].Endpoints);
92 
93         }
94 
95         [Test]
ShoulDisconnectGPIOSenderAttachedToGPIOReceiver()96         public void ShoulDisconnectGPIOSenderAttachedToGPIOReceiver()
97         {
98             //init
99             var gpioReceiverMock = new MockReceiver();
100             var gpioSender = new MockIrqSender();
101 
102             machine.SystemBus.Register(gpioReceiverMock, new BusRangeRegistration(0x0, 0x10));
103             machine.SystemBus.Register(gpioSender, new BusRangeRegistration(0x10, 0x10));
104             gpioSender.Irq.Connect(gpioReceiverMock, 1);
105 
106             //act
107             ((IPeripheralRegister<IBusPeripheral, BusRangeRegistration>)machine.SystemBus).Unregister(gpioReceiverMock);
108             //assert
109             Assert.IsFalse(gpioSender.Irq.IsConnected);
110         }
111 
112         [Test]
ShouldUnregisterChainedPeripheralsOnBDisconnect()113         public void ShouldUnregisterChainedPeripheralsOnBDisconnect()
114         {
115             //A -> B -> C, B -> D and A -> C
116             //B is disconnected
117 
118             //init
119             var A = new MockGPIOByNumberConnectorPeripheral(2);
120             var B = new MockGPIOByNumberConnectorPeripheral(2);
121             var C = new MockReceiver();
122             var D = new MockReceiver();
123 
124             machine.SystemBus.Register(A, new BusRangeRegistration(0x0, 0x10));
125             machine.SystemBus.Register(B, new BusRangeRegistration(0x10, 0x10));
126             machine.SystemBus.Register(C, new BusRangeRegistration(0x20, 0x10));
127             machine.SystemBus.Register(D, new BusRangeRegistration(0x30, 0x10));
128 
129             A.Connections[0].Connect(B, 1);
130             B.Connections[0].Connect(C, 1);
131             B.Connections[1].Connect(D, 1);
132             A.Connections[1].Connect(C, 2);
133 
134             //act
135             ((IPeripheralRegister<IBusPeripheral, BusRangeRegistration>)machine.SystemBus).Unregister(B);
136             var AConnections = A.Connections;
137             var BConnections = B.Connections;
138 
139             //assert
140             Assert.IsEmpty(AConnections[0].Endpoints);
141             Assert.IsEmpty(BConnections[0].Endpoints);
142             Assert.IsEmpty(BConnections[1].Endpoints);
143             Assert.IsNotEmpty(AConnections[1].Endpoints);
144         }
145 
146         [Test]
ShouldDisconnectEndpointOfUnregisteredPeripheral()147         public void ShouldDisconnectEndpointOfUnregisteredPeripheral()
148         {
149             // init
150             var A = new MockGPIOByNumberConnectorPeripheral(1);
151             var B = new MockGPIOByNumberConnectorPeripheral(1);
152             var C = new MockReceiver();
153 
154             machine.SystemBus.Register(A, new BusRangeRegistration(0x0, 0x10));
155             machine.SystemBus.Register(B, new BusRangeRegistration(0x10, 0x10));
156             machine.SystemBus.Register(C, new BusRangeRegistration(0x20, 0x10));
157 
158             // act
159             A.Connections[0].Connect(B, 1);
160             A.Connections[0].Connect(C, 1);
161             B.Connections[0].Connect(C, 1);
162             Assert.True(A.Connections[0].Endpoints.Count == 2);
163             Assert.True(B.Connections[0].Endpoints.Count == 1);
164 
165             // try to connect the same endpoint as before
166             A.Connections[0].Connect(C, 1);
167             Assert.True(A.Connections[0].Endpoints.Count(x => x.Receiver == C && x.Number == 1) == 1);
168 
169             ((IPeripheralRegister<IBusPeripheral, BusRangeRegistration>)machine.SystemBus).Unregister(C);
170 
171             Assert.True(A.Connections[0].Endpoints.Count == 1);
172             Assert.True(A.Connections[0].Endpoints[0].Receiver == B);
173             Assert.IsEmpty(B.Connections[0].Endpoints);
174         }
175 
176         [Test]
ShouldConnectGPIOToReceiverAndReturnTheSameReceiver()177         public void ShouldConnectGPIOToReceiverAndReturnTheSameReceiver()
178         {
179             //init
180             var gpioByNumberConnectorPeripheralMock = new MockGPIOByNumberConnectorPeripheral(3);
181             var gpioReceiverMock = new MockReceiver();
182 
183             machine.SystemBus.Register(gpioByNumberConnectorPeripheralMock, new BusRangeRegistration(0x0, 0x10));
184             machine.SystemBus.Register(gpioReceiverMock, new BusRangeRegistration(0x10, 0x10));
185             gpioByNumberConnectorPeripheralMock.Connections[0].Connect(gpioReceiverMock, 1);
186 
187             //act
188             var gpioConnections = gpioByNumberConnectorPeripheralMock.Connections;
189             var receiver = gpioConnections[0].Endpoints[0].Receiver;
190 
191             Assert.True(gpioConnections[0].Endpoints.Count == 1);
192             Assert.IsEmpty(gpioConnections[1].Endpoints);
193             Assert.IsEmpty(gpioConnections[2].Endpoints);
194             Assert.True(gpioReceiverMock == receiver);
195         }
196     }
197 }
198