--- nono/vm/syncer.cpp 2026/04/29 17:05:17 1.1 +++ nono/vm/syncer.cpp 2026/04/29 17:05:37 1.1.1.5 @@ -10,9 +10,8 @@ #include "syncer.h" #include "config.h" -#include "mainapp.h" -#include "mainbus.h" -#include "mainram.h" +#include "monitor.h" +#include "mpu680x0.h" #include "scheduler.h" //#define DEBUG @@ -33,10 +32,6 @@ Syncer::Syncer() for (int i = 0; i < perfq.Capacity(); i++) { perfq.Enqueue(1000); } - - sync_event.func = ToEventCallback(&Syncer::SyncCallback); - sync_event.time = 50_msec; - sync_event.Regist("Sync"); } // デストラクタ @@ -48,22 +43,23 @@ Syncer::~Syncer() bool Syncer::Init() { - if (inherited::Init() == false) { - return false; - } + mpu680x0 = dynamic_cast(mpu); - mainbus = GetMainbusDevice(); - mainram = GetMainRAMDevice(); - - mode = SCHED_POWEROFF; + mode = SYNCMODE_POWEROFF; overslept = 0; + dmac_idle = 1; // 高速モード指定 bool fast_mode = gConfig->Find("fast-mode").AsInt(); RequestFullSpeed(fast_mode); scheduler->ConnectMessage(MessageID::SCHEDULER_SYNCMODE, this, - ToMessageCallback(&Syncer::ChangeModeCallback)); + ToMessageCallback(&Syncer::ChangeModeMessage)); + + sync_event.func = ToEventCallback(&Syncer::SyncCallback); + sync_event.time = 50_msec; + sync_event.SetName("Sync"); + scheduler->RegistEvent(sync_event); return true; } @@ -111,7 +107,23 @@ Syncer::RequestCPUMode(uint32 cpumode) { uint32 newmode; - newmode = (mode & ~SCHED_CPU_MASK) | cpumode; + halt = cpumode & SYNCMODE_CPU_HALT; + cpu_idle = cpumode & SYNCMODE_CPU_STOP; + + newmode = (mode & ~SYNCMODE_CPU_MASK) | halt | (cpu_idle & dmac_idle); + + ChangeMode(newmode); +} + +// DMAC のアクティブ状態を指示する。 +void +Syncer::RequestDMACActive(bool active) +{ + uint32 newmode; + + dmac_idle = active ? 0 : SYNCMODE_IDLE; + + newmode = (mode & ~SYNCMODE_IDLE) | (cpu_idle & dmac_idle); ChangeMode(newmode); } @@ -126,16 +138,16 @@ Syncer::RequestFullSpeed(bool enable) } // ブートページモードの変更を指示する。 -// (VM::SwitchBootPage から呼ぶので個別には呼ばないこと) +// (MainbusBaseDevice::SwitchBootPage から呼ぶので個別には呼ばないこと) void Syncer::RequestBootPageMode(bool isrom) { uint32 newmode; if (isrom) { - newmode = mode | SCHED_BOOT; + newmode = mode | SYNCMODE_BOOT; } else { - newmode = mode & ~SCHED_BOOT; + newmode = mode & ~SYNCMODE_BOOT; } ChangeMode(newmode); @@ -148,9 +160,9 @@ Syncer::RequestKeyPressed(bool pressed) uint32 newmode; if (pressed) { - newmode = mode | SCHED_KEY; + newmode = mode | SYNCMODE_KEY; } else { - newmode = mode & ~SCHED_KEY; + newmode = mode & ~SYNCMODE_KEY; } ChangeMode(newmode); @@ -163,9 +175,9 @@ Syncer::RequestPowerOffMode(bool powerof uint32 newmode; if (poweroff) { - newmode = mode | SCHED_POWEROFF; + newmode = mode | SYNCMODE_POWEROFF; } else { - newmode = mode & ~SCHED_POWEROFF; + newmode = mode & ~SYNCMODE_POWEROFF; } ChangeMode(newmode); @@ -173,22 +185,22 @@ Syncer::RequestPowerOffMode(bool powerof // 動作状態変更のメッセージコールバック void -Syncer::ChangeModeCallback(MessageID msgid, uint32 arg) +Syncer::ChangeModeMessage(MessageID msgid, uint32 arg) { uint32 newmode; if (msgid == MessageID::SCHEDULER_SYNCMODE) { if (arg) { - newmode = mode & ~SCHED_SYNC; + newmode = mode & ~SYNCMODE_SYNC; } else { - newmode = mode | SCHED_SYNC; + newmode = mode | SYNCMODE_SYNC; } ChangeMode(newmode); } } -// メンバ変数 mode_request に従ってスケジューラの動作状態を変更。 +// newmode に従ってスケジューラの動作状態を変更。 // 自スレッドから呼ぶこと。 void Syncer::ChangeMode(uint32 newmode) @@ -205,17 +217,10 @@ Syncer::ChangeMode(uint32 newmode) if (newmode == 0) { // 高速モードに putlog(2, "Fast mode"); - - // 高速モードでは RAM は直接アクセス - mainbus->direct_ram_size = mainram->GetSize(); - } else { // 同期モードに putlog(2, "Sync mode"); - // 同期モードでは RAM アクセスはデバイス経由 - mainbus->direct_ram_size = 0; - // 同期用の基準点を設置。 // ゲストが STOP 命令による定常状態にいる時は // 割り込みなど短期間だけ高速モードになるのを繰り返す。 @@ -326,9 +331,9 @@ Syncer::CalcPerf() // 百分率で小数以下1桁分までとなるよう整数で計算する perfq.EnqueueForce((uint32)(vperf * 1000 / rperf)); // 移動平均を求める (perfq は常に要素数分埋めてある) - int ma = 0; - int qlen = perfq.Length(); - __assume(qlen > 0); + uint ma = 0; + uint qlen = perfq.Length(); + __assume(qlen != 0); for (int i = 0; i < qlen; i++) { auto v = perfq.Peek(i); ma += v; @@ -342,6 +347,11 @@ Syncer::CalcPerf() last_sync_count = sync_count; sync_count = 0; + // 関係ないけど、ついでにここで MPU 内の各種移動平均をとる。 + if (mpu680x0) { + mpu680x0->CalcStat(); + } + last_perf_rtime = rtime; last_perf_vtime = vtime; next_perf_rtime = rtime + PERF_INTERVAL; @@ -354,9 +364,9 @@ Syncer::PutlogRealtime() uint64 vtime = scheduler->GetVirtTime(); // 電源オン時からここまでの時間を表示するだけでリセット等はしない。 - putlog(0, "Elapsed time since power-on: %d.%03d sec, %6.2f%%", - (int)(rtime / (1000 * 1000 * 1000)), - (int)((rtime / (1000 * 1000)) % 1000), + putlog(0, "Elapsed since power-on: %u.%03u sec, %6.2f%%", + (uint)(rtime / (1000 * 1000 * 1000)), + (uint)((rtime / (1000 * 1000)) % 1000), (double)vtime / rtime * 100); #if 0 @@ -376,25 +386,25 @@ Syncer::MonitorUpdateSub(TextScreen& scr int y = 0; screen.Print(0, y, "Mode: 0x%04x (", mode); - switch (mode & SCHED_CPU_MASK) { - case SCHED_CPU_NORMAL: + switch (mode & SYNCMODE_CPU_MASK) { + case SYNCMODE_CPU_NORMAL: screen.Puts(14, y, TA::Off, "Run"); break; - case SCHED_CPU_STOP: + case SYNCMODE_CPU_STOP: screen.Puts(14, y, TA::On, "STOP"); break; - case SCHED_CPU_HALT: + case SYNCMODE_CPU_HALT: screen.Puts(14, y, TA::On, "HALT"); break; } - if ((mode & SCHED_SYNC)) { + if ((mode & SYNCMODE_SYNC)) { screen.Puts(19, y, TA::On, "Sync"); } else { screen.Puts(19, y, TA::Off, "Full"); } - screen.Puts(24, y, TA::OnOff((mode & SCHED_BOOT)), "Boot"); - screen.Puts(29, y, TA::OnOff((mode & SCHED_KEY)), "Key"); - screen.Puts(34, y, TA::OnOff((mode & SCHED_POWEROFF)), "POff"); + screen.Puts(24, y, TA::OnOff((mode & SYNCMODE_BOOT)), "Boot"); + screen.Puts(29, y, TA::OnOff((mode & SYNCMODE_KEY)), "Key"); + screen.Puts(34, y, TA::OnOff((mode & SYNCMODE_POWEROFF)), "POff"); screen.Puts(38, y, ")"); y++; uint64 rt = rtime; @@ -418,7 +428,18 @@ Syncer::MonitorUpdateSub(TextScreen& scr screen.Print(0, y++, "Sync Real Time: %*s", width, s_sync_rt.c_str()); screen.Print(4, y++, "Virtual Time: %*s", width, s_sync_vt.c_str()); - screen.Print(0, y++, "Performance : %4d%%", perf_counter); + screen.Puts(0, y, "Rating MPU Speed :"); + uint clock_khz = mpu->GetClockSpeed(); + if (__predict_true((clock_khz % 1000) == 0)) { + screen.Print(21, y++, "%4u.%1uMHz", + clock_khz / 1000, (clock_khz / 100) % 10); + } else { + screen.Print(21, y++, "%4u.%03uMHz", + clock_khz / 1000, clock_khz % 1000); + } + uint eff_khz = clock_khz * perf_counter / 100; + screen.Print(0, y++, "Effective MPU Speed: %4u.%1uMHz (%4u%%)", + (eff_khz / 1000), (eff_khz / 100) % 10, perf_counter); int x = 52; int y1 = 0;