1 //
2 // Copyright (c) 2010-2024 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using Antmicro.Renode.Core;
8 using Antmicro.Renode.Core.Structure.Registers;
9 using Antmicro.Renode.Logging;
10 using Antmicro.Renode.Peripherals.Bus;
11 using System.Collections.Generic;
12 
13 namespace Antmicro.Renode.Peripherals.Timers
14 {
15     [AllowedTranslations(AllowedTranslation.DoubleWordToQuadWord)]
16     public class NEORV32_MachineSystemTimer : IQuadWordPeripheral, IKnownSize
17     {
NEORV32_MachineSystemTimer(IMachine machine, long frequency)18         public NEORV32_MachineSystemTimer(IMachine machine, long frequency)
19         {
20             mTimer = new ComparingTimer(machine.ClockSource, frequency, this, nameof(mTimer), direction: Time.Direction.Ascending, workMode: Time.WorkMode.Periodic, eventEnabled: true, enabled: true);
21             mTimer.CompareReached += () =>
22             {
23                 UpdateInterrupts();
24             };
25 
26             var registersMap = new Dictionary<long, QuadWordRegister>();
27 
28             registersMap.Add((long)Registers.Time, new QuadWordRegister(this)
29                 .WithValueField(0, 64, name: "TIME",
30                     valueProviderCallback: _ => TimerValue,
31                     writeCallback: (_, value) => mTimer.Value = value)
32                 .WithWriteCallback((_, __) => UpdateInterrupts()));
33 
34             registersMap.Add((long)Registers.Compare, new QuadWordRegister(this)
35                 .WithValueField(0, 64, name: "COMPARE",
36                     valueProviderCallback: _ => mTimer.Compare,
37                     writeCallback: (_, value) => mTimer.Compare = value)
38                 .WithWriteCallback((_, __) => UpdateInterrupts()));
39 
40             RegistersCollection = new QuadWordRegisterCollection(this, registersMap);
41 
42             this.machine = machine;
43         }
44 
Reset()45         public void Reset()
46         {
47             mTimer.Reset();
48             UpdateInterrupts();
49         }
50 
ReadQuadWord(long offset)51         public ulong ReadQuadWord(long offset)
52         {
53             return RegistersCollection.Read(offset);
54         }
55 
WriteQuadWord(long offset, ulong val)56         public void WriteQuadWord(long offset, ulong val)
57         {
58             RegistersCollection.Write(offset, val);
59         }
60 
61         public QuadWordRegisterCollection RegistersCollection { get; }
62         public GPIO IRQ { get; } = new GPIO();
63         public long Size => 0x10;
64 
UpdateInterrupts()65         private void UpdateInterrupts()
66         {
67             bool shouldInterrupt = mTimer.Value >= mTimer.Compare;
68             this.Log(LogLevel.Noisy, "Setting IRQ: {0}", shouldInterrupt);
69             IRQ.Set(shouldInterrupt);
70         }
71 
72         private ulong TimerValue
73         {
74             get
75             {
76                 if(machine.GetSystemBus(this).TryGetCurrentCPU(out var cpu))
77                 {
78                     cpu.SyncTime();
79                 }
80                 return mTimer.Value;
81             }
82         }
83 
84         private readonly IMachine machine;
85 
86         private readonly ComparingTimer mTimer;
87 
88         enum Registers
89         {
90             Time = 0x00,
91             Compare = 0x08,
92         }
93     }
94 }
95 
96 
97