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 using System;
9 using Antmicro.Renode.Peripherals.Timers;
10 using NUnit.Framework;
11 using System.Threading;
12 using System.Diagnostics;
13 using Antmicro.Renode.Time;
14 using Antmicro.Renode.Core;
15 using Antmicro.Renode.Peripherals;
16 
17 namespace Antmicro.Renode.UnitTests
18 {
19     [TestFixture]
20     public class CoreTimerTest
21     {
22         [Test]
ShouldBeAscending()23         public void ShouldBeAscending()
24         {
25             var manualClockSource = new ManualClockSource();
26             var timer = new LimitTimer(manualClockSource, 100, null, String.Empty, 100000, Direction.Ascending, true);
27             var oldValue = 0UL;
28             for(var i = 0; i < 100; i++)
29             {
30                 manualClockSource.AdvanceBySeconds(1);
31                 var value = timer.Value;
32                 Assert.Greater(value, oldValue, "Timer is not monotonic.");
33                 oldValue = value;
34             }
35         }
36 
37         [Test]
ShouldBeDescending()38         public void ShouldBeDescending()
39         {
40             var manualClockSource = new ManualClockSource();
41             var timer = new LimitTimer(manualClockSource, 100, null, String.Empty, 100000, Direction.Descending, true);
42             var oldValue = timer.Limit;
43             for(var i = 0; i < 100; i++)
44             {
45                 manualClockSource.AdvanceBySeconds(1);
46                 var value = timer.Value;
47                 Assert.Less(value, oldValue, "Timer is not monotonic.");
48                 oldValue = value;
49             }
50         }
51 
52         [Test]
ShouldNotExceedLimitAscending()53         public void ShouldNotExceedLimitAscending()
54         {
55             var limit = 100UL;
56             var manualClockSource = new ManualClockSource();
57             var timer = new LimitTimer(manualClockSource, 1, null, String.Empty, limit, Direction.Ascending, true);
58             manualClockSource.AdvanceBySeconds(limit - 1);
59             for(var i = 0; i < 3; ++i)
60             {
61                 var value = timer.Value;
62                 Assert.LessOrEqual(value, limit, "Timer exceeded given limit.");
63                 Assert.GreaterOrEqual(value, 0, "Timer returned negative value.");
64                 manualClockSource.AdvanceBySeconds(1);
65             }
66         }
67 
68         [Test]
ShouldNotExceedLimitDescending()69         public void ShouldNotExceedLimitDescending()
70         {
71             var limit = 100UL;
72             var manualClockSource = new ManualClockSource();
73             var timer = new LimitTimer(manualClockSource, 1, null, String.Empty, limit, Direction.Descending, true);
74             manualClockSource.AdvanceBySeconds(limit - 1);
75             for(var i = 0; i < 3; i++)
76             {
77                 var value = timer.Value;
78                 Assert.LessOrEqual(value, limit, "Timer exceeded given limit.");
79                 Assert.GreaterOrEqual(value, 0, "Timer returned negative value.");
80                 manualClockSource.AdvanceBySeconds(1);
81             }
82         }
83 
84         [Test]
ShouldHandleMicrosecondPrecisionTimerEvents()85         public void ShouldHandleMicrosecondPrecisionTimerEvents()
86         {
87             uint activationCounter = 0;
88 
89             var limit = 4UL;
90             var manualClockSource = new ManualClockSource();
91             var timer = new LimitTimer(manualClockSource, 1000000, null, String.Empty, limit, Direction.Descending, true);
92             timer.EventEnabled = true;
93             timer.LimitReached += () => activationCounter++;
94             manualClockSource.Advance(TimeInterval.FromMicroseconds(10));
95 
96             Assert.AreEqual(2, activationCounter, "Timer did not go off twice.");
97             Assert.AreEqual(2, timer.Value, "Timer value is not expected.");
98         }
99 
100         [Test]
ShouldHandleSubMicrosecondPrecisionTimerEvents()101         public void ShouldHandleSubMicrosecondPrecisionTimerEvents()
102         {
103             uint activationCounter = 0;
104 
105             var limit = 4UL;
106             var manualClockSource = new ManualClockSource();
107             var timer = new LimitTimer(manualClockSource, 10000000, null, String.Empty, limit, Direction.Descending, true);
108             timer.EventEnabled = true;
109             timer.LimitReached += () => activationCounter++;
110             manualClockSource.Advance(TimeInterval.FromMicroseconds(1));
111 
112             Assert.AreEqual(2, activationCounter, "Timer did not go off twice.");
113             Assert.AreEqual(2, timer.Value, "Timer value is not expected.");
114         }
115 
116         [Test]
ShouldSwitchDirectionProperly()117         public void ShouldSwitchDirectionProperly()
118         {
119             var manualClockSource = new ManualClockSource();
120             var timer = new LimitTimer(manualClockSource, 100, null, String.Empty, 100000, Direction.Ascending, true);
121             timer.EventEnabled = true;
122             var ticked = false;
123             timer.LimitReached += () => ticked = true;
124             manualClockSource.AdvanceBySeconds(2);
125             timer.Direction = Direction.Descending; // and then change the direction
126             manualClockSource.AdvanceBySeconds(2);
127             Assert.IsTrue(ticked);
128         }
129 
130         [Test]
ShouldNotFireAlarmWhenInterruptsAreDisabled()131         public void ShouldNotFireAlarmWhenInterruptsAreDisabled()
132         {
133             var manualClockSource = new ManualClockSource();
134             var timer = new LimitTimer(manualClockSource, 1, null, String.Empty, 10, Direction.Descending, true);
135             var ticked = false;
136             timer.LimitReached += () => ticked = true;
137             manualClockSource.AdvanceBySeconds(11);
138             Assert.IsFalse(ticked);
139         }
140 
141         [Test]
ShouldFireAlarmWhenInterruptsAreEnabled()142         public void ShouldFireAlarmWhenInterruptsAreEnabled()
143         {
144             var manualClockSource = new ManualClockSource();
145             var timer = new LimitTimer(manualClockSource, 1, null, String.Empty, 10, Direction.Descending, true);
146             timer.EventEnabled = true;
147             var ticked = false;
148             timer.LimitReached += () => ticked = true;
149             // var val =timer.Value;
150             manualClockSource.AdvanceBySeconds(10);
151             Assert.IsTrue(ticked);
152         }
153 
154         private class ManualClockSource : BaseClockSource
155         {
AdvanceBySeconds(ulong seconds)156             public void AdvanceBySeconds(ulong seconds)
157             {
158                 Advance(TimeInterval.FromSeconds(seconds));
159             }
160         }
161     }
162 }
163 
164