1 //
2 // Copyright (c) 2010-2023 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 
8 using System;
9 using NUnit.Framework;
10 using Antmicro.Renode.Core;
11 using Antmicro.Renode.Time;
12 using Antmicro.Renode.Peripherals.Timers;
13 
14 namespace Antmicro.Renode.UnitTests
15 {
16     [TestFixture]
17     public class Cadence_TTCTests
18     {
19         [OneTimeSetUp]
CreatePeripheral()20         public void CreatePeripheral()
21         {
22             machine = new Machine();
23             timer = new Cadence_TTC(machine, TimerFrequency);
24         }
25 
26         [SetUp]
PreparePeripheral()27         public void PreparePeripheral()
28         {
29             timer.Reset();
30         }
31 
32         [Test]
ShouldResetCounter()33         public void ShouldResetCounter()
34         {
35             var index = 0;
36             timer.SetCounterValue(0, TicksPerSecond);
37             WriteTimerRegister(index, Registers.InterruptEnable, InterruptMaskAll);
38             Assert.AreEqual(TicksPerSecond, ReadTimerRegister(index, Registers.CounterValue));
39             Assert.False(timer.Connections[0].IsSet);
40 
41             WriteTimerRegister(index, Registers.CounterControl, CounterControlResetFlag);
42             Assert.AreEqual(0, ReadTimerRegister(index, Registers.CounterValue));
43             Assert.False(timer.Connections[0].IsSet);
44         }
45 
46         [Test]
ShouldCountIndependently()47         public void ShouldCountIndependently()
48         {
49             WriteTimerRegister(0, Registers.ClockControl, ClockControlPrescaler1024);
50             WriteTimerRegister(1, Registers.ClockControl, ClockControlPrescaler2048);
51             WriteTimerRegister(2, Registers.ClockControl, ClockControlPrescaler4096);
52             for(var index = 0; index < TimersCount; index++)
53             {
54                 WriteTimerRegister(index, Registers.CounterControl, CounterControlCountUpOverflow);
55                 Assert.AreEqual(0, ReadTimerRegister(index, Registers.CounterValue));
56             }
57             AdvanceBySeconds(1);
58 
59             Assert.AreEqual(TicksPerSecond / 1, ReadTimerRegister(0, Registers.CounterValue));
60             Assert.AreEqual(TicksPerSecond / 2, ReadTimerRegister(1, Registers.CounterValue));
61             Assert.AreEqual(TicksPerSecond / 4, ReadTimerRegister(2, Registers.CounterValue));
62         }
63 
64         [TestCase(CounterControlCountUpOverflow, InterruptMaskOverflow, UInt32.MaxValue - TicksPerSecond - 1, 0u, 0u,
65             TestName = "ShouldCountUpInOverflowMode")]
66         [TestCase(CounterControlCountDownOverflow, InterruptMaskOverflow, TicksPerSecond + 1, UInt32.MaxValue, 0u,
67             TestName = "ShouldCountDownInOverflowMode")]
68         [TestCase(CounterControlCountUpInterval, InterruptMaskInterval, 2 * TicksPerSecond - 1, 0u, 3 * TicksPerSecond,
69             TestName = "ShouldCountUpInIntervalMode")]
70         [TestCase(CounterControlCountDownInterval, InterruptMaskInterval, TicksPerSecond + 1, 3 * TicksPerSecond, 3 * TicksPerSecond,
71             TestName = "ShouldCountDownInIntervalMode")]
ShouldOverflowInOneSecond(uint counterControl, uint interruptMask, uint initValue, uint overflowValue, uint interval = 0)72         public void ShouldOverflowInOneSecond(uint counterControl, uint interruptMask, uint initValue, uint overflowValue, uint interval = 0)
73         {
74             var index = 0;
75             WriteTimerRegister(index, Registers.ClockControl, ClockControlPrescaler);
76             WriteTimerRegister(index, Registers.CounterControl, counterControl);
77             WriteTimerRegister(index, Registers.CounterInterval, interval);
78             WriteTimerRegister(index, Registers.InterruptEnable, interruptMask);
79             ReadTimerRegister(index, Registers.InterruptStatus);
80 
81             timer.SetCounterValue(0, initValue);
82             AdvanceBySeconds(1);
83 
84             Assert.False(timer.Connections[index].IsSet);
85             AdvanceBySeconds(1 / (double)TicksPerSecond);
86 
87             Assert.AreEqual(overflowValue, ReadTimerRegister(index, Registers.CounterValue));
88             Assert.True(timer.Connections[index].IsSet);
89 
90             Assert.AreEqual(interruptMask, ReadTimerRegister(index, Registers.InterruptStatus));
91             Assert.False(timer.Connections[index].IsSet);
92         }
93 
AdvanceBySeconds(double seconds)94         private void AdvanceBySeconds(double seconds)
95         {
96             ((BaseClockSource)machine.ClockSource).Advance(TimeInterval.FromSeconds(seconds));
97         }
98 
WriteTimerRegister(int index, Registers register, uint value)99         private void WriteTimerRegister(int index, Registers register, uint value)
100         {
101             timer.WriteDoubleWord(index * RegisterSize + (long)register, value);
102         }
103 
ReadTimerRegister(int index, Registers register)104         private uint ReadTimerRegister(int index, Registers register)
105         {
106             return timer.ReadDoubleWord(index * RegisterSize + (long)register);
107         }
108 
109         private Cadence_TTC timer;
110         private IMachine machine;
111 
112         private const int TimersCount = 3;
113         private const int RegisterSize = 0x4;
114 
115         private const uint TicksPerSecond = 0x100;
116         private const uint ClockControlPrescaler1024 = (9 << 1) | 0x1;
117         private const uint ClockControlPrescaler2048 = (10 << 1) | 0x1;
118         private const uint ClockControlPrescaler4096 = (11 << 1) | 0x1;
119         private const uint ClockControlPrescaler = ClockControlPrescaler1024;
120         private const uint TimerFrequency = TicksPerSecond * 1024;
121         private const double TimeDelta = 0.1;
122 
123         private const uint CounterControlResetFlag = 0x10;
124         private const uint CounterControlCountUpOverflow = 0x0;
125         private const uint CounterControlCountUpInterval = 0x02;
126         private const uint CounterControlCountDownOverflow = 0x4;
127         private const uint CounterControlCountDownInterval = 0x4 | 0x2;
128         private const uint InterruptMaskOverflow = 0x10;
129         private const uint InterruptMaskInterval = 0x1;
130         private const uint InterruptMaskAll = 0xff;
131 
132         private enum Registers : long
133         {
134             ClockControl = 0x00,
135             CounterControl = 0x0C,
136             CounterValue = 0x18,
137             CounterInterval = 0x24,
138             Match1Counter = 0x30,
139             Match2Counter = 0x3C,
140             Match3Counter = 0x48,
141             InterruptStatus = 0x54,
142             InterruptEnable = 0x60,
143             EventControlTimer = 0x6C,
144             EventRegister = 0x78,
145         }
146     }
147 }
148