--- nono/vm/sysclk.cpp 2026/04/29 17:04:56 1.1.1.9 +++ nono/vm/sysclk.cpp 2026/04/29 17:05:10 1.1.1.10 @@ -4,6 +4,10 @@ // Licensed under nono-license.txt // +// +// LUNA システムクロック +// + // システムクロックは実時間または仮想時間のいずれかに同期するため、 // システムクロック独自の時刻 stime を持つ。 // stime は、割り込みを発生させるごとに、LUNA-I なら 16.67msec、 @@ -12,9 +16,14 @@ #include "sysclk.h" #include "config.h" #include "interrupt.h" +#include "rtc.h" +#include "scheduler.h" +#include "sync.h" -std::unique_ptr gSysClk; +// グローバル参照用 +SysClkDevice *gSysClk; +// コンストラクタ SysClkDevice::SysClkDevice() : inherited("SystemClock") { @@ -22,16 +31,19 @@ SysClkDevice::SysClkDevice() devaddr = 0x63000000; - monitor.func = (MonitorCallback_t)&SysClkDevice::MonitorUpdate; + monitor.func = ToMonitorCallback(&SysClkDevice::MonitorUpdate); monitor.SetSize(31, 2); monitor.Regist(ID_MONITOR_SYSCLK); + event.func = ToEventCallback(&SysClkDevice::Callback); event.code = 0; - event.SetName("System Clock"); + event.Regist("System Clock"); } +// デストラクタ SysClkDevice::~SysClkDevice() { + gSysClk = NULL; } bool @@ -43,38 +55,25 @@ SysClkDevice::Init() event.time = period; // クロックの同期方法 - const ConfigItem& item_sync = gConfig->Find("clock-sync"); - auto clock_sync = item_sync.AsString(); - if (clock_sync == "real") { - sync_rt = true; - } else if (clock_sync == "virtual") { - sync_rt = false; - } else { - item_sync.Err(); - return false; - } - if (sync_rt) { - event.func = (DeviceCallback_t)&SysClkDevice::Callback_rt; - } else { - event.func = (DeviceCallback_t)&SysClkDevice::Callback; - } + sync_rt = gRTC->GetSyncRealtime(); return true; } -bool -SysClkDevice::PowerOn() +// 電源オン/リセット +void +SysClkDevice::ResetHard(bool poweron) { - if (sync_rt) { - stime = gRealtime.Elapsed(); + // XXX たぶん電源オンだけで作用する? + if (poweron) { + if (sync_rt) { + stime = gSync->GetRealTime(); + } + + // 電源オンですぐ起動 + sysint = false; + gScheduler->RestartEvent(event); } - // XXX スーパーリセット時にスケジューラの時刻が再初期化されないので - // ここでどうするかはそのときまた再検討すること。 - - // 電源オンですぐ起動 - sysint = false; - event.Start(); - return true; } uint64 @@ -130,43 +129,17 @@ void SysClkDevice::Callback(Event& ev) { putlog(3, "システムクロック割り込み発生"); - stime += period; - sysint = true; - gInterrupt->AssertINT(this); - ev.Start(); -} -void -SysClkDevice::Callback_rt(Event& ev) -{ - putlog(3, "システムクロック割り込み発生"); // システムクロックとしての現在時刻。 - // 足す前は前回の割り込み発生時刻なので - // period を足すと現在時刻。 + // 足す前は前回の割り込み発生時刻なので period を足すと現在時刻。 stime += period; - uint64 now = gRealtime.Elapsed(); + sysint = true; + gInterrupt->AssertINT(this); - // +- period 時間範囲で処理する - if (now > stime + period) { - // 実時間がさらに 1 period 以上進んでいる - // 実時間に追いつかないといけないので、システムクロックの - // 周期を短くして回復運転させる。 - // 周期を短くしすぎるとゲストが処理できなくなるので、 - // 10% カットに留める。 - ev.time = period - period / 10; - } else if (now < stime - period) { - // システムクロックがさらに 1 period 以上進んでいる - // 実時間を追い越してしまっているので、システムクロックの - // 周期を長くして待つ。長くする方はいくらでも長くしていいので、 - // 連続した場合はどんどん長くしていく。 - ev.time += period; + if (sync_rt) { + gScheduler->StartRealtimeEvent(ev, stime, period); } else { - // おおむね同期している - ev.time = period; + gScheduler->StartEvent(ev); } - - sysint = true; - gInterrupt->AssertINT(this); - ev.Start(); }