Files
simulation_Peripheral/LC3233_Timer_InterruptController_NO4.cs

442 lines
15 KiB
C#
Raw Normal View History

2026-04-01 11:03:44 +08:00
//============================================================================
// 作者liuwenbo
// 日期2026-03-24-2026-03-25
//============================================================================
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Antmicro.Renode.Core;
using Antmicro.Renode.Core.Structure.Registers;
using Antmicro.Renode.Logging;
using Antmicro.Renode.Peripherals.Bus;
using Antmicro.Renode.Time;
using Antmicro.Renode.Peripherals;
using Antmicro.Renode.Peripherals.Timers;
using Antmicro.Renode.Peripherals.IRQControllers;
namespace Antmicro.Renode.Peripherals.Timers
{
public class LC3233_TaskTimer : BasicDoubleWordPeripheral, IKnownSize
{
public LC3233_TaskTimer(IMachine machine) : base(machine)
{
this.machine = machine;
DefineRegisters();
Reset();
this.Log(LogLevel.Info, "LC3233 定时器已初始化 @ 0x80000000");
this.Log(LogLevel.Info, " 周期: 250ms (4Hz), 用于VxWorks任务调度");
}
private void ScheduleNextTick()
{
if(timerScheduled || (timerCtrl & TIMER_CTRL_T0_EN) == 0)
{
return;
}
timerScheduled = true;
var generation = timerGeneration;
machine.ScheduleAction(TimeInterval.FromMilliseconds(250), _ =>
{
timerScheduled = false;
if(generation != timerGeneration || (timerCtrl & TIMER_CTRL_T0_EN) == 0)
{
return;
}
OnTimerExpired();
});
}
private void OnTimerExpired()
{
timerExpiredCount++;
//isPending = true;
this.Log(LogLevel.Info, "========== 定时器溢出 #{0} ==========", timerExpiredCount);
this.Log(LogLevel.Info, "准备触发中断线4...");
IRQ.Set(true);
this.Log(LogLevel.Info, "已调用 IRQ.Set(true),信号应发送到 lc3233IntCtrl@4");
machine.ScheduleAction(TimeInterval.FromMicroseconds(1),
_ => {
IRQ.Set(false);
this.Log(LogLevel.Debug, "中断脉冲结束");
});
if ((timerCtrl & TIMER_CTRL_T0_LOEN) != 0)
{
timer0Cntr = timer0Reld;
ScheduleNextTick();
}
}
private void DefineRegisters()
{
Registers.TimerCtrl.Define(this)
.WithValueField(0, 32, name: "timer_ctrl",
writeCallback: (_, val) =>
{
timerCtrl = (uint)val;
// Bit 0: Timer0 Enable
bool t0Enable = (val & TIMER_CTRL_T0_EN) != 0;
if(!t0Enable)
{
timerGeneration++;
timerScheduled = false;
}
else
{
timerGeneration++;
timerScheduled = false;
ScheduleNextTick();
}
this.Log(LogLevel.Info, "TIMER_CTRL 写入: 0x{0:X8}", val);
this.Log(LogLevel.Info, " Timer0 Enable: {0}", t0Enable);
this.Log(LogLevel.Info, " Auto Reload: {0}", (val & TIMER_CTRL_T0_LOEN) != 0);
},
valueProviderCallback: _ => timerCtrl);
Registers.Timer0Cntr.Define(this)
.WithValueField(0, 32, name: "timer0_cntr",
writeCallback: (_, val) =>
{
timer0Cntr = (uint)val;
this.Log(LogLevel.Debug, "TIMER0_CNTR 写入: 0x{0:X8}", val);
},
valueProviderCallback: _ => timer0Cntr);
Registers.Timer0Reld.Define(this)
.WithValueField(0, 32, name: "timer0_reld",
writeCallback: (_, val) =>
{
timer0Reld = (uint)val;
this.Log(LogLevel.Debug, "TIMER0_RELD 写入: 0x{0:X8}", val);
},
valueProviderCallback: _ => timer0Reld);
Registers.Timer0DivFreq.Define(this)
.WithValueField(0, 32, name: "timer0_divfreq",
writeCallback: (_, val) =>
{
timer0DivFreq = (uint)val;
this.Log(LogLevel.Debug, "TIMER0_DIVFREQ 写入: 0x{0:X8}", val);
},
valueProviderCallback: _ => timer0DivFreq);
Registers.Timer0DfReld.Define(this)
.WithValueField(0, 32, name: "timer0_df_reld",
writeCallback: (_, val) =>
{
timer0DfReld = (uint)val;
this.Log(LogLevel.Debug, "TIMER0_DF_RELD 写入: 0x{0:X8}", val);
},
valueProviderCallback: _ => timer0DfReld);
}
public override void Reset()
{
base.Reset();
timerCtrl = TIMER_CTRL_T0_EN | TIMER_CTRL_T0_LOEN;
timer0Cntr = 0;
timer0Reld = 0;
timer0DivFreq = 0;
timer0DfReld = 0;
isPending = false;
timerExpiredCount = 0;
timerGeneration++;
timerScheduled = false;
ScheduleNextTick();
}
public long Size => 0x100;
public GPIO IRQ { get; } = new GPIO();
private enum Registers
{
TimerCtrl = 0x00,
Timer0Cntr = 0x04,
Timer0Reld = 0x08,
WdgCntr = 0x0C,
Timer1Cntr = 0x10,
Timer1Reld = 0x14,
Timer0DivFreq = 0x18,
Timer0DfReld = 0x1C,
}
private const uint TIMER_CTRL_T0_EN = 0x00000001;
private const uint TIMER_CTRL_T0_LOEN = 0x00000002;
private const uint TIMER_CTRL_T0_RSTA = 0x00000004;
private readonly IMachine machine;
private uint timerCtrl;
private uint timer0Cntr;
private uint timer0Reld;
private uint timer0DivFreq;
private uint timer0DfReld;
private bool isPending;
private bool timerScheduled;
private ulong timerGeneration;
private ulong timerExpiredCount;
}
}
namespace Antmicro.Renode.Peripherals.IRQControllers
{
public class LC3233_InterruptController : BasicDoubleWordPeripheral, IKnownSize, INumberedGPIOOutput, IGPIOReceiver
{
public LC3233_InterruptController(IMachine machine) : base(machine)
{
this.machine = machine;
connections = new Dictionary<int, IGPIO>();
for (int i = 0; i <= 15; i++)
{
connections[i] = new GPIO();
}
Connections = new ReadOnlyDictionary<int, IGPIO>(connections);
DefineRegisters();
Reset();
this.Log(LogLevel.Info, "LC3233 中断控制器已初始化 @ 0x80020000");
this.Log(LogLevel.Info, " 管理15个中断源 (1-15)");
}
/// <summary>
/// 定义寄存器映射
/// </summary>
private void DefineRegisters()
{
// Registers.IntMaskPriority.Define(this)
// .WithValueField(0, 32, name: "int_mask_priority",
// writeCallback: (_, val) =>
// {
// intMaskPriority = (uint)val;
// this.Log(LogLevel.Info, "INT_MASK_PRIORITY 写入: 0x{0:X8}", val);
// this.Log(LogLevel.Info, " 临时兼容: IRQ4 强制视为使能");
// for (int i = 1; i <= 15; i++)
// {
// if ((val & (uint)(1 << i)) != 0)
// {
// this.Log(LogLevel.Debug, " 中断 {0} 已使能", i);
// }
// }
// UpdateInterrupts();
// },
// valueProviderCallback: _ => intMaskPriority);
// Registers.IntFTP.Define(this)
// .WithValueField(0, 32, name: "int_f_t_p",
// writeCallback: (_, val) =>
// {
// intFTP |= (uint)val;
// this.Log(LogLevel.Debug, "INT_F_T_P 写入: 0x{0:X8}, 当前值: 0x{1:X8}", val, intFTP);
// UpdateInterrupts();
// },
// valueProviderCallback: _ => intFTP);
// Registers.IntForce.Define(this)
// .WithValueField(0, 32, FieldMode.Write, name: "int_force",
// writeCallback: (_, val) =>
// {
// this.Log(LogLevel.Info, "INT_FORCE 写入: 0x{0:X8}", val);
// intFTP |= (uint)val;
// UpdateInterrupts();
// });
// Registers.IntClr.Define(this)
// .WithValueField(0, 32, FieldMode.Write, name: "int_clr",
// writeCallback: (_, val) =>
// {
// this.Log(LogLevel.Debug, "INT_CLR 写入: 0x{0:X8}", val);
// intFTP &= ~(uint)val;
// UpdateInterrupts();
// });
}
public void OnGPIO(int irq, bool value)
{
if (irq < 0 || irq > 15)
{
this.Log(LogLevel.Error, "无效的中断号: {0}", irq);
return;
}
if(value)
{
this.Log(LogLevel.Info, "*** 中断控制器接收到信号 IRQ{0}: {1} ***", irq, value ? "拉高" : "拉低");
// 自动使能中断
intMaskPriority |= (uint)(1 << irq);
this.Log(LogLevel.Info, "自动使能中断 {0}: INT_MASK_PRIORITY = 0x{1:X8}",
irq, intMaskPriority);
//设置挂起寄存器
intFTP |= (uint)(1 << irq);
this.Log(LogLevel.Info, "设置挂起位: INT_F_T_P = 0x{0:X8}", intFTP);
UpdateInterrupts();
}
else
{
}
//this.Log(LogLevel.Info, "调用 UpdateInterrupts() 检查是否转发到CPU...");
//UpdateInterrupts();
// if (irq < 0 || irq > 15)
// {
// this.Log(LogLevel.Error, "无效的中断号: {0}", irq);
// return;
// }
// this.Log(LogLevel.Info, "*** 中断控制器接收到信号 IRQ{0}: {1} ***", irq, value ? "拉高" : "拉低");
// if (value)
// {
// intFTP |= (uint)(1 << irq);
// this.Log(LogLevel.Info, "设置挂起位: INT_F_T_P = 0x{0:X8}", intFTP);
// }
// else
// {
// }
// this.Log(LogLevel.Info, "调用 UpdateInterrupts() 检查是否转发到CPU...");
// UpdateInterrupts();
}
private void UpdateInterrupts()
{
this.Log(LogLevel.Info, "调用 UpdateInterrupts() 检查是否转发到CPU...");
this.Log(LogLevel.Debug, "UpdateInterrupts: MASK=0x{0:X8}, PENDING=0x{1:X8}",
intMaskPriority, intFTP);
for (int i = 15; i > 0; i--)
{
//bool masked = ((intMaskPriority & (uint)(1 << i)) != 0) || (forceEnableIRQ4 && i == 4);
bool masked = ((intMaskPriority & (uint)(1 << i)) != 0);
bool pending = (intFTP & (uint)(1 << i)) != 0;
if (i == 5)
{
this.Log(LogLevel.Info, "IRQ{0} 状态检查: masked={1}, pending={2}", i, masked, pending);
}
if (i == 4)
{
this.Log(LogLevel.Info, "IRQ{0} 状态检查: masked={1}, pending={2}", i, masked, pending);
}
if (masked && pending)
{
if (Connections.TryGetValue(i, out var gpio))
{
gpio.Set(true);
this.Log(LogLevel.Info, "===> 转发中断 {0} 到MIC@{0} (CPU中断线{0})", i);
var localI = i;
machine.ScheduleAction(TimeInterval.FromMicroseconds(1),
_ => {
if (Connections.TryGetValue(localI, out var g))
{
g.Set(false);
machine.ScheduleAction(TimeInterval.FromMicroseconds(10),
_ => {
intFTP &= ~(uint)(1 << localI);
this.Log(LogLevel.Info, "*** 10us 安全期已过,自动清除中断 {0} 的挂起位 ***", localI);
UpdateInterrupts();
});
}
});
}
else
{
this.Log(LogLevel.Warning, "中断 {0} 无法转发: 连接未找到!", i);
}
}
}
}
public override void Reset()
{
base.Reset();
intMaskPriority = 0;
intFTP = 0;
intClr = 0;
}
public long Size => 0x10;
public IReadOnlyDictionary<int, IGPIO> Connections { get; }
private readonly IMachine machine;
private readonly Dictionary<int, IGPIO> connections;
private readonly Dictionary<IGPIO, int> gpioToIrqMap; // 字段声明
private readonly bool forceEnableIRQ4 = true;
private uint intMaskPriority;
private uint intFTP;
private uint intClr;
// 寄存器定义
private enum Registers
{
IntMaskPriority = 0x00,
IntFTP = 0x04,
IntForce = 0x08,
IntClr = 0x0C,
}
}
}