xous-core/emulation/peripherals/susres.cs
Sean Cross 4b3d1503e7 renode: place all peripherals under "Betrusted" ns
Give a "Betrusted" namespace to all of the peripherals. This will enable
us to upstream various modules without breaking compatibility with our
own versions of these peripherals.

Signed-off-by: Sean Cross <sean@xobs.io>
2022-10-20 22:19:40 +08:00

187 lines
5.9 KiB
C#

//
// Copyright (c) 2010-2019 Antmicro
//
// This file is licensed under the MIT License.
// Full license text is available in 'licenses/MIT.txt'.
//
using Antmicro.Renode.Core;
using Antmicro.Renode.Core.Structure.Registers;
using Antmicro.Renode.Logging;
using Antmicro.Renode.Peripherals.Bus;
namespace Antmicro.Renode.Peripherals.Timers.Betrusted
{
// this is a model of LiteX timer in the Betrusted configuration:
// * width: 32 bits
// * csr data width: 32 bit
[AllowedTranslations(AllowedTranslation.ByteToDoubleWord)]
public class SusRes : BasicDoubleWordPeripheral, IKnownSize
{
public SusRes(Machine machine, ulong periodInMs = 1) : base(machine)
{
this.IRQ = new GPIO();
DefineRegisters();
}
private TickTimer EnsureTickTimer()
{
if (MainTimer != null)
{
return MainTimer;
}
foreach (var element in machine.ClockSource.GetAllClockEntries())
{
if (element.LocalName == "TickTimer")
{
MainTimer = (TickTimer)element.Owner;
this.Log(LogLevel.Info, "Found TickTimer object!");
return MainTimer;
}
}
this.Log(LogLevel.Error, "Did not find TickTimer object");
return null;
}
public override void Reset()
{
base.Reset();
irqPending.Value = false;
RegistersCollection.Reset();
}
private void UpdateInterrupts()
{
IRQ.Set(this.irqPending.Value && this.irqEnabled.Value);
}
public long Size { get { return 4096; } }
private void DefineRegisters()
{
Registers.Control.Define32(this)
.WithFlag(0, FieldMode.Read | FieldMode.Write, writeCallback: (_, val) =>
{
if (EnsureTickTimer() == null)
{
return;
}
MainTimer.paused = val;
}
)
.WithFlag(1, writeCallback: (_, val) =>
{
// Don't update the timer if it's not paused.
if ((!EnsureTickTimer()?.paused) ?? false)
{
return;
}
if (val) {
MainTimer.tickValue = ((long)resumeTime0.Value) | (((long)resumeTime1.Value) << 32);
}
})
;
Registers.Time1.Define32(this)
.WithValueField(0, 32, FieldMode.Read, name: "Time1", valueProviderCallback: _ =>
{
return EnsureTickTimer()?.Time1() ?? 0;
})
;
Registers.Time0.Define32(this)
.WithValueField(0, 32, FieldMode.Read, name: "Time0", valueProviderCallback: _ =>
{
return EnsureTickTimer()?.Time0() ?? 0;
})
;
Registers.ResumeTime0.Define32(this)
.WithValueField(0, 32, out resumeTime0)
;
Registers.ResumeTime1.Define32(this)
.WithValueField(0, 32, out resumeTime1)
;
Registers.Status.Define32(this)
.WithFlag(0, FieldMode.Read, valueProviderCallback: _ => EnsureTickTimer()?.paused ?? false, name: "paused")
;
Registers.State.Define32(this)
.WithFlag(0, out isResume)
.WithFlag(1, out wasForced)
;
Registers.Powerdown.Define32(this)
.WithFlag(0, FieldMode.Read | FieldMode.Write, changeCallback: (_, val) => {
if (val) {
this.Log(LogLevel.Info, "Pausing and resetting machine");
machine.LocalTimeSource.ExecuteInNearestSyncedState(ts => {
machine.Pause();
machine.Reset();
});
}
})
;
Registers.Wfi.Define32(this)
.WithFlag(0, name: "override")
;
Registers.Interrupt.Define32(this)
.WithFlag(0, FieldMode.Write, writeCallback: (_, val) =>
{
if (val)
{
irqPending.Value = true;
}
UpdateInterrupts();
})
;
Registers.EventStatus.Define32(this)
.WithFlag(0, FieldMode.Read, name: "EV_STATUS", valueProviderCallback: _ => false)
;
Registers.EventPending.Define32(this)
.WithFlag(0, out irqPending, FieldMode.Read | FieldMode.WriteOneToClear, name: "EV_PENDING", changeCallback: (_, __) => UpdateInterrupts())
;
Registers.EventEnable.Define32(this)
.WithFlag(0, out irqEnabled, name: "EV_ENABLE", changeCallback: (_, __) => UpdateInterrupts())
;
}
TickTimer MainTimer;
private IFlagRegisterField irqEnabled;
private IFlagRegisterField irqPending;
private IValueRegisterField resumeTime0;
private IValueRegisterField resumeTime1;
private IFlagRegisterField timerPaused;
private IFlagRegisterField isResume;
private IFlagRegisterField wasForced;
public GPIO IRQ { get; private set; }
private enum Registers
{
Control = 0x00,
ResumeTime1 = 0x04,
ResumeTime0 = 0x08,
Time1 = 0x0c,
Time0 = 0x10,
Status = 0x14,
State = 0x18,
Powerdown = 0x1c,
Wfi = 0x20,
Interrupt = 0x24,
EventStatus = 0x28,
EventPending = 0x2c,
EventEnable = 0x30,
}
}
}