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