// // Copyright (c) 2010-2018 Antmicro // Copyright (c) 2011-2015 Realtime Embedded // // This file is licensed under the MIT License. // Full license text is available in 'licenses/MIT.txt'. // using System; using Antmicro.Renode.Core; using Antmicro.Renode.Peripherals.Bus; using Antmicro.Renode.Time; using Antmicro.Renode.Logging; using System.Threading; namespace Antmicro.Renode.Peripherals.Timers { public class BSOCTickTimer : IDoubleWordPeripheral, IKnownSize { public BSOCTickTimer(ulong periodInMs, Machine machine) { running = true; machine.ClockSource.AddClockEntry(new ClockEntry(periodInMs, ClockEntry.FrequencyToRatio(this, 1000), OnTick, this, String.Empty)); } public long Size { get { return 0x400; } } public virtual uint ReadDoubleWord(long offset) { if (offset == 0) return 0; else if (offset == 4) offset = 40; else if (offset == 8) offset = 32; else if (offset == 12) offset = 24; else if (offset == 16) offset = 16; else if (offset == 20) offset = 8; else if (offset == 24) offset = 0; else { this.LogUnhandledRead(offset); return 0; } return (uint)(Interlocked.CompareExchange(ref counter, 0, 0) >> (int)offset); } public virtual void WriteDoubleWord(long offset, uint value) { if (offset == 0) { if ((value & 1) == 1) Interlocked.Exchange(ref counter, 0); running = ((value & 2) != 2); return; } this.LogUnhandledWrite(offset, value); } public virtual void Reset() { Interlocked.Exchange(ref counter, 0); } private void OnTick() { if (running) Interlocked.Increment(ref counter); } private long counter; private bool running; } }