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