1 // 2 // Copyright (c) 2010-2019 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.Utilities; 11 12 namespace Antmicro.Renode.Peripherals.Timers 13 { 14 public class LiteX_CPUTimer : BasicDoubleWordPeripheral, IKnownSize, IRiscVTimeProvider 15 { LiteX_CPUTimer(IMachine machine, long frequency)16 public LiteX_CPUTimer(IMachine machine, long frequency) : base(machine) 17 { 18 IRQ = new GPIO(); 19 20 innerTimer = new ComparingTimer(machine.ClockSource, frequency, this, "cpu timer", enabled: true, eventEnabled: true); 21 innerTimer.CompareReached += () => 22 { 23 this.Log(LogLevel.Noisy, "Limit reached, setting IRQ"); 24 IRQ.Set(true); 25 }; 26 DefineRegisters(); 27 } 28 29 public long Size => 0x100; 30 31 public GPIO IRQ {get;} 32 33 public ulong TimerValue => innerTimer.Value; 34 Reset()35 public override void Reset() 36 { 37 base.Reset(); 38 39 innerTimer.Reset(); 40 latchedValue = 0; 41 IRQ.Set(false); 42 } 43 DefineRegisters()44 private void DefineRegisters() 45 { 46 Register.Latch.Define(this) 47 .WithFlag(0, name: "latch_bit", writeCallback: (_, val) => 48 { 49 if(!val) 50 { 51 return; 52 } 53 54 latchedValue = innerTimer.Value; 55 }) 56 ; 57 58 Register.Time.DefineMany(this, 8, stepInBytes: 4, setup: (reg, idx) => 59 { 60 // idx=0 - most significant byte 61 // ... 62 // idx=7 - least significant byte 63 reg.WithValueField(0, 8, valueProviderCallback: (_) => 64 { 65 return (uint)(latchedValue >> ((7 - idx) * 8) & 0xff); 66 }); 67 }); 68 69 Register.TimeCompare.DefineMany(this, 8, stepInBytes: 4, setup: (reg, idx) => 70 { 71 // idx=0 - most significant byte 72 // ... 73 // idx=7 - least significant byte 74 75 // this field should by 8-bits long, but it's defined as 32-bits (and the value is ANDed with 0xFF) to avoid unhandled bits warnings 76 reg.WithValueField(0, 32, writeCallback: (_, val) => 77 { 78 innerTimer.Compare = innerTimer.Compare.ReplaceBits((ulong)(val & 0xFF), 8, (7 - idx) * 8); 79 this.Log(LogLevel.Noisy, "Compare value set to 0x{0:X}, dpos: {1}", innerTimer.Compare, (7 - idx) * 8); 80 if(innerTimer.Value < innerTimer.Compare) 81 { 82 this.Log(LogLevel.Noisy, "Current timer value is 0x{0:X} - clearing IRQ", innerTimer.Value); 83 IRQ.Set(false); 84 } 85 }); 86 }); 87 } 88 89 private readonly ComparingTimer innerTimer; 90 private ulong latchedValue; 91 92 private enum Register 93 { 94 Latch = 0x0, 95 Time = 0x4, 96 TimeCompare = 0x24, 97 } 98 } 99 } 100