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 System.Runtime.InteropServices;
11 using Antmicro.Renode.Core.Extensions;
12 using Antmicro.Renode.Peripherals.Bus;
13 using NUnit.Framework;
14 using Moq;
15 
16 namespace Antmicro.Renode.UnitTests
17 {
18     [TestFixture]
19     public class WriteExtensionsTest
20     {
21         [SetUp]
SetUp()22         public void SetUp()
23         {
24             bytePeriMock = new Mock<IBytePeripheral>();
25             wordPeriMock = new Mock<IWordPeripheral>();
26             dwordPeriMock = new Mock<IDoubleWordPeripheral>();
27             qwordPeriMock = new Mock<IQuadWordPeripheral>();
28         }
29 
30         [Test]
ShouldWriteWordUsingByte()31         public void ShouldWriteWordUsingByte()
32         {
33             var bytePeripheral = bytePeriMock.Object;
34             bytePeripheral.WriteWordUsingByte(0, 0x3412);
35             bytePeripheral.WriteWordUsingByte(2, 0x7856);
36             bytePeriMock.Verify(x => x.WriteByte(0, 0x12), Times.Once());
37             bytePeriMock.Verify(x => x.WriteByte(1, 0x34), Times.Once());
38             bytePeriMock.Verify(x => x.WriteByte(2, 0x56), Times.Once());
39             bytePeriMock.Verify(x => x.WriteByte(3, 0x78), Times.Once());
40         }
41 
42         [Test]
ShouldWriteWordUsingByteBigEndian()43         public void ShouldWriteWordUsingByteBigEndian()
44         {
45             var bytePeripheral = bytePeriMock.Object;
46             bytePeripheral.WriteWordUsingByteBigEndian(0, 0x3412);
47             bytePeripheral.WriteWordUsingByteBigEndian(2, 0x7856);
48             bytePeriMock.Verify(x => x.WriteByte(0, 0x34), Times.Once());
49             bytePeriMock.Verify(x => x.WriteByte(1, 0x12), Times.Once());
50             bytePeriMock.Verify(x => x.WriteByte(2, 0x78), Times.Once());
51             bytePeriMock.Verify(x => x.WriteByte(3, 0x56), Times.Once());
52         }
53 
54         [Test]
ShouldWriteDoubleWordUsingByte()55         public void ShouldWriteDoubleWordUsingByte()
56         {
57             var bytePeripheral = bytePeriMock.Object;
58             bytePeripheral.WriteDoubleWordUsingByte(0, 0x78563412);
59             bytePeriMock.Verify(x => x.WriteByte(0, 0x12), Times.Once());
60             bytePeriMock.Verify(x => x.WriteByte(1, 0x34), Times.Once());
61             bytePeriMock.Verify(x => x.WriteByte(2, 0x56), Times.Once());
62             bytePeriMock.Verify(x => x.WriteByte(3, 0x78), Times.Once());
63         }
64 
65         [Test]
ShouldWriteDoubleWordUsingByteBigEndian()66         public void ShouldWriteDoubleWordUsingByteBigEndian()
67         {
68             var bytePeripheral = bytePeriMock.Object;
69             bytePeripheral.WriteDoubleWordUsingByteBigEndian(0, 0x78563412);
70             bytePeriMock.Verify(x => x.WriteByte(0, 0x78), Times.Once());
71             bytePeriMock.Verify(x => x.WriteByte(1, 0x56), Times.Once());
72             bytePeriMock.Verify(x => x.WriteByte(2, 0x34), Times.Once());
73             bytePeriMock.Verify(x => x.WriteByte(3, 0x12), Times.Once());
74         }
75 
76         [Test]
ShouldWriteQuadWordUsingByte()77         public void ShouldWriteQuadWordUsingByte()
78         {
79             var bytePeripheral = bytePeriMock.Object;
80             bytePeripheral.WriteQuadWordUsingByte(0, 0x7856341221436587);
81             bytePeriMock.Verify(x => x.WriteByte(0, 0x87), Times.Once());
82             bytePeriMock.Verify(x => x.WriteByte(1, 0x65), Times.Once());
83             bytePeriMock.Verify(x => x.WriteByte(2, 0x43), Times.Once());
84             bytePeriMock.Verify(x => x.WriteByte(3, 0x21), Times.Once());
85             bytePeriMock.Verify(x => x.WriteByte(4, 0x12), Times.Once());
86             bytePeriMock.Verify(x => x.WriteByte(5, 0x34), Times.Once());
87             bytePeriMock.Verify(x => x.WriteByte(6, 0x56), Times.Once());
88             bytePeriMock.Verify(x => x.WriteByte(7, 0x78), Times.Once());
89         }
90 
91         [Test]
ShouldWriteQuadWordUsingByteBigEndian()92         public void ShouldWriteQuadWordUsingByteBigEndian()
93         {
94             var bytePeripheral = bytePeriMock.Object;
95             bytePeripheral.WriteQuadWordUsingByteBigEndian(0, 0x7856341221436587);
96             bytePeriMock.Verify(x => x.WriteByte(0, 0x78), Times.Once());
97             bytePeriMock.Verify(x => x.WriteByte(1, 0x56), Times.Once());
98             bytePeriMock.Verify(x => x.WriteByte(2, 0x34), Times.Once());
99             bytePeriMock.Verify(x => x.WriteByte(3, 0x12), Times.Once());
100             bytePeriMock.Verify(x => x.WriteByte(4, 0x21), Times.Once());
101             bytePeriMock.Verify(x => x.WriteByte(5, 0x43), Times.Once());
102             bytePeriMock.Verify(x => x.WriteByte(6, 0x65), Times.Once());
103             bytePeriMock.Verify(x => x.WriteByte(7, 0x87), Times.Once());
104         }
105 
106         [Test]
ShouldWriteByteUsingWord()107         public void ShouldWriteByteUsingWord()
108         {
109             var wordPeripheral = wordPeriMock.Object;
110             wordPeripheral.WriteByteUsingWord(0, 0x12);
111             wordPeriMock.Verify(x => x.WriteWord(0, 0x0012));
112             wordPeriMock.Setup(x => x.ReadWord(0)).Returns(0x0012);
113             wordPeripheral.WriteByteUsingWord(1, 0x34);
114             wordPeriMock.Verify(x => x.WriteWord(0, 0x3412));
115             wordPeripheral.WriteByteUsingWord(2, 0x56);
116             wordPeriMock.Verify(x => x.WriteWord(2, 0x0056));
117             wordPeriMock.Setup(x => x.ReadWord(2)).Returns(0x0056);
118             wordPeripheral.WriteByteUsingWord(3, 0x78);
119             wordPeriMock.Verify(x => x.WriteWord(2, 0x7856));
120         }
121 
122         [Test]
ShouldWriteByteUsingWordBigEndian()123         public void ShouldWriteByteUsingWordBigEndian()
124         {
125             var wordPeripheral = wordPeriMock.Object;
126             wordPeripheral.WriteByteUsingWordBigEndian(0, 0x12);
127             wordPeriMock.Verify(x => x.WriteWord(0, 0x1200));
128             wordPeriMock.Setup(x => x.ReadWord(0)).Returns(0x1200);
129             wordPeripheral.WriteByteUsingWordBigEndian(1, 0x34);
130             wordPeriMock.Verify(x => x.WriteWord(0, 0x1234));
131             wordPeripheral.WriteByteUsingWordBigEndian(2, 0x56);
132             wordPeriMock.Verify(x => x.WriteWord(2, 0x5600));
133             wordPeriMock.Setup(x => x.ReadWord(2)).Returns(0x5600);
134             wordPeripheral.WriteByteUsingWordBigEndian(3, 0x78);
135             wordPeriMock.Verify(x => x.WriteWord(2, 0x5678));
136         }
137 
138         [Test]
ShouldWriteDoubleWordUsingWord()139         public void ShouldWriteDoubleWordUsingWord()
140         {
141             var wordPeripheral = wordPeriMock.Object;
142             wordPeripheral.WriteDoubleWordUsingWord(0, 0x78563412);
143             wordPeriMock.Verify(x => x.WriteWord(0, 0x3412));
144             wordPeriMock.Verify(x => x.WriteWord(2, 0x7856));
145         }
146 
147         [Test]
ShouldWriteDoubleWordUsingWordBigEndian()148         public void ShouldWriteDoubleWordUsingWordBigEndian()
149         {
150             var wordPeripheral = wordPeriMock.Object;
151             wordPeripheral.WriteDoubleWordUsingWordBigEndian(0, 0x78563412);
152             wordPeriMock.Verify(x => x.WriteWord(0, 0x5678));
153             wordPeriMock.Verify(x => x.WriteWord(2, 0x1234));
154         }
155 
156         [Test]
ShouldWriteQuadWordUsingWord()157         public void ShouldWriteQuadWordUsingWord()
158         {
159             var wordPeripheral = wordPeriMock.Object;
160             wordPeripheral.WriteQuadWordUsingWord(0, 0x7856341221436587);
161             wordPeriMock.Verify(x => x.WriteWord(0, 0x6587));
162             wordPeriMock.Verify(x => x.WriteWord(2, 0x2143));
163             wordPeriMock.Verify(x => x.WriteWord(4, 0x3412));
164             wordPeriMock.Verify(x => x.WriteWord(6, 0x7856));
165         }
166 
167         [Test]
ShouldWriteQuadWordUsingWordBigEndian()168         public void ShouldWriteQuadWordUsingWordBigEndian()
169         {
170             var wordPeripheral = wordPeriMock.Object;
171             wordPeripheral.WriteQuadWordUsingWordBigEndian(0, 0x7856341221436587);
172             wordPeriMock.Verify(x => x.WriteWord(0, 0x5678));
173             wordPeriMock.Verify(x => x.WriteWord(2, 0x1234));
174             wordPeriMock.Verify(x => x.WriteWord(4, 0x4321));
175             wordPeriMock.Verify(x => x.WriteWord(6, 0x8765));
176         }
177 
178         [Test]
ShouldWriteByteUsingDoubleWord()179         public void ShouldWriteByteUsingDoubleWord()
180         {
181             var dwordPeripheral = dwordPeriMock.Object;
182             dwordPeripheral.WriteByteUsingDoubleWord(0, 0x12);
183             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x12));
184             dwordPeriMock.Setup(x => x.ReadDoubleWord(0)).Returns(0x12);
185             dwordPeripheral.WriteByteUsingDoubleWord(1, 0x34);
186             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x3412));
187             dwordPeriMock.Setup(x => x.ReadDoubleWord(0)).Returns(0x3412);
188             dwordPeripheral.WriteByteUsingDoubleWord(2, 0x56);
189             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x563412));
190             dwordPeriMock.Setup(x => x.ReadDoubleWord(0)).Returns(0x563412);
191             dwordPeripheral.WriteByteUsingDoubleWord(3, 0x78);
192             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x78563412));
193         }
194 
195         [Test]
ShouldWriteByteUsingDoubleWordBigEndian()196         public void ShouldWriteByteUsingDoubleWordBigEndian()
197         {
198             var dwordPeripheral = dwordPeriMock.Object;
199             dwordPeripheral.WriteByteUsingDoubleWordBigEndian(0, 0x12);
200             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x12000000));
201             dwordPeriMock.Setup(x => x.ReadDoubleWord(0)).Returns(0x12000000);
202             dwordPeripheral.WriteByteUsingDoubleWordBigEndian(1, 0x34);
203             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x12340000));
204             dwordPeriMock.Setup(x => x.ReadDoubleWord(0)).Returns(0x12340000);
205             dwordPeripheral.WriteByteUsingDoubleWordBigEndian(2, 0x56);
206             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x12345600));
207             dwordPeriMock.Setup(x => x.ReadDoubleWord(0)).Returns(0x12345600);
208             dwordPeripheral.WriteByteUsingDoubleWordBigEndian(3, 0x78);
209             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x12345678));
210         }
211 
212         [Test]
ShouldWriteWordUsingDoubleWord()213         public void ShouldWriteWordUsingDoubleWord()
214         {
215             var dwordPeripheral = dwordPeriMock.Object;
216             dwordPeripheral.WriteWordUsingDoubleWord(0, 0x3412);
217             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x3412));
218             dwordPeriMock.Setup(x => x.ReadDoubleWord(0)).Returns(0x3412);
219             dwordPeripheral.WriteWordUsingDoubleWord(2, 0x7856);
220             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x78563412));
221         }
222 
223         [Test]
ShouldWriteWordUsingDoubleWordBigEndian()224         public void ShouldWriteWordUsingDoubleWordBigEndian()
225         {
226             var dwordPeripheral = dwordPeriMock.Object;
227             dwordPeripheral.WriteWordUsingDoubleWordBigEndian(0, 0x3412);
228             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x12340000));
229             dwordPeriMock.Setup(x => x.ReadDoubleWord(0)).Returns(0x12340000);
230             dwordPeripheral.WriteWordUsingDoubleWordBigEndian(2, 0x7856);
231             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x12345678));
232         }
233 
234         [Test]
ShouldWriteQuadWordUsingDoubleWord()235         public void ShouldWriteQuadWordUsingDoubleWord()
236         {
237             var dwordPeripheral = dwordPeriMock.Object;
238             dwordPeripheral.WriteQuadWordUsingDoubleWord(0, 0x7856341221436587);
239             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x21436587));
240             dwordPeriMock.Verify(x => x.WriteDoubleWord(4, 0x78563412));
241         }
242 
243         [Test]
ShouldWriteQuadWordUsingDoubleWordBigEndian()244         public void ShouldWriteQuadWordUsingDoubleWordBigEndian()
245         {
246             var dwordPeripheral = dwordPeriMock.Object;
247             dwordPeripheral.WriteQuadWordUsingDoubleWordBigEndian(0, 0x7856341221436587);
248             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x12345678));
249             dwordPeriMock.Verify(x => x.WriteDoubleWord(4, 0x87654321));
250         }
251 
252         [Test]
ShouldWriteWordUsingDoubleWordNotAligned1()253         public void ShouldWriteWordUsingDoubleWordNotAligned1()
254         {
255             var dwordPeripheral = dwordPeriMock.Object;
256             PrepareOldData();
257             dwordPeripheral.WriteWordUsingDoubleWord(1, 0xDFEF);
258             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x78DFEF12), Times.Once());
259         }
260 
261         [Test]
ShouldWriteWordUsingDoubleWordNotAligned1BigEndian()262         public void ShouldWriteWordUsingDoubleWordNotAligned1BigEndian()
263         {
264             var dwordPeripheral = dwordPeriMock.Object;
265             PrepareOldData();
266             dwordPeripheral.WriteWordUsingDoubleWordBigEndian(1, 0xDFEF);
267             dwordPeriMock.Verify(x => x.WriteDoubleWord(0, 0x78EFDF12), Times.Once());
268         }
269 
270         [Test]
ShouldWriteByteUsingQuadWord()271         public void ShouldWriteByteUsingQuadWord()
272         {
273             byte[] bytes = {0x12, 0x34, 0x56, 0x78, 0x87, 0x65, 0x43, 0x21};
274             var qwordPeripheral = qwordPeriMock.Object;
275             ulong act = 0;
276             for(var i = 0; i < 7; i++)
277             {
278                 qwordPeripheral.WriteByteUsingQuadWord(i, bytes[i]);
279                 act |= (ulong)bytes[i] << (8 * i);
280                 qwordPeriMock.Verify(x => x.WriteQuadWord(0, act));
281                 qwordPeriMock.Setup(x => x.ReadQuadWord(0)).Returns(act);
282             }
283         }
284 
285         [Test]
ShouldWriteByteUsingQuadWordBigEndian()286         public void ShouldWriteByteUsingQuadWordBigEndian()
287         {
288             byte[] bytes = {0x12, 0x34, 0x56, 0x78, 0x87, 0x65, 0x43, 0x21};
289             var qwordPeripheral = qwordPeriMock.Object;
290             ulong act = 0;
291             for(var i = 0; i < 7; i++)
292             {
293                 qwordPeripheral.WriteByteUsingQuadWordBigEndian(i, bytes[i]);
294                 act |= (ulong)bytes[i] << (7 - i) * 8;
295                 qwordPeriMock.Verify(x => x.WriteQuadWord(0, act));
296                 qwordPeriMock.Setup(x => x.ReadQuadWord(0)).Returns(act);
297             }
298         }
299 
300         [Test]
ShouldWriteWordUsingQuadWord()301         public void ShouldWriteWordUsingQuadWord()
302         {
303             var qwordPeripheral = qwordPeriMock.Object;
304             qwordPeripheral.WriteWordUsingQuadWord(0, 0x3412);
305             qwordPeriMock.Verify(x => x.WriteQuadWord(0, 0x3412));
306             qwordPeriMock.Setup(x => x.ReadQuadWord(0)).Returns(0x3412);
307             qwordPeripheral.WriteWordUsingQuadWord(2, 0x7856);
308             qwordPeriMock.Verify(x => x.WriteQuadWord(0, 0x78563412));
309             qwordPeriMock.Setup(x => x.ReadQuadWord(0)).Returns(0x78563412);
310             qwordPeripheral.WriteWordUsingQuadWord(4, 0x5678);
311             qwordPeriMock.Verify(x => x.WriteQuadWord(0, 0x567878563412));
312             qwordPeriMock.Setup(x => x.ReadQuadWord(0)).Returns(0x567878563412);
313             qwordPeripheral.WriteWordUsingQuadWord(6, 0x1234);
314             qwordPeriMock.Verify(x => x.WriteQuadWord(0, 0x1234567878563412));
315         }
316 
317         [Test]
ShouldWriteWordUsingQuadWordBigEndian()318         public void ShouldWriteWordUsingQuadWordBigEndian()
319         {
320             var qwordPeripheral = qwordPeriMock.Object;
321             qwordPeripheral.WriteWordUsingQuadWordBigEndian(0, 0x3412);
322             qwordPeriMock.Verify(x => x.WriteQuadWord(0, 0x1234000000000000));
323             qwordPeriMock.Setup(x => x.ReadQuadWord(0)).Returns(0x1234000000000000);
324             qwordPeripheral.WriteWordUsingQuadWordBigEndian(2, 0x7856);
325             qwordPeriMock.Verify(x => x.WriteQuadWord(0, 0x1234567800000000));
326             qwordPeriMock.Setup(x => x.ReadQuadWord(0)).Returns(0x1234567800000000);
327             qwordPeripheral.WriteWordUsingQuadWordBigEndian(4, 0x6587);
328             qwordPeriMock.Verify(x => x.WriteQuadWord(0, 0x1234567887650000));
329             qwordPeriMock.Setup(x => x.ReadQuadWord(0)).Returns(0x1234567887650000);
330             qwordPeripheral.WriteWordUsingQuadWordBigEndian(6, 0x2143);
331             qwordPeriMock.Verify(x => x.WriteQuadWord(0, 0x1234567887654321));
332         }
333 
334         [Test]
ShouldWriteDoubleWordUsingQuadWord()335         public void ShouldWriteDoubleWordUsingQuadWord()
336         {
337             var qwordPeripheral = qwordPeriMock.Object;
338             qwordPeripheral.WriteDoubleWordUsingQuadWord(0, 0x78563412);
339             qwordPeriMock.Verify(x => x.WriteQuadWord(0, 0x78563412));
340             qwordPeriMock.Setup(x => x.ReadQuadWord(0)).Returns(0x78563412);
341             qwordPeripheral.WriteDoubleWordUsingQuadWord(4, 0x12345678);
342             qwordPeriMock.Verify(x => x.WriteQuadWord(0, 0x1234567878563412));
343         }
344 
345         [Test]
ShouldWriteDoubleWordUsingQuadWordBigEndian()346         public void ShouldWriteDoubleWordUsingQuadWordBigEndian()
347         {
348             var qwordPeripheral = qwordPeriMock.Object;
349             qwordPeripheral.WriteDoubleWordUsingQuadWordBigEndian(0, 0x78563412);
350             qwordPeriMock.Verify(x => x.WriteQuadWord(0, 0x1234567800000000));
351             qwordPeriMock.Setup(x => x.ReadQuadWord(0)).Returns(0x1234567800000000);
352             qwordPeripheral.WriteDoubleWordUsingQuadWordBigEndian(4, 0x21436587);
353             qwordPeriMock.Verify(x => x.WriteQuadWord(0, 0x1234567887654321));
354         }
355 
PrepareOldData()356         private void PrepareOldData()
357         {
358             dwordPeriMock.Setup(x => x.ReadDoubleWord(0)).Returns(0x78563412);
359             dwordPeriMock.Setup(x => x.ReadDoubleWord(4)).Returns(0xCCBBAA90);
360             wordPeriMock.Setup(x => x.ReadWord(0)).Returns(0x3412);
361             wordPeriMock.Setup(x => x.ReadWord(2)).Returns(0x7856);
362             wordPeriMock.Setup(x => x.ReadWord(4)).Returns(0xAA90);
363             wordPeriMock.Setup(x => x.ReadWord(6)).Returns(0xCCBB);
364         }
365 
366         private Mock<IBytePeripheral> bytePeriMock;
367         private Mock<IWordPeripheral> wordPeriMock;
368         private Mock<IDoubleWordPeripheral> dwordPeriMock;
369         private Mock<IQuadWordPeripheral> qwordPeriMock;
370     }
371 }
372