|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2020 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: // ! 8: // 実時間同期 ! 9: // ! 10: ! 11: #pragma once ! 12: ! 13: #include "event.h" ! 14: #include "fixedqueue.h" ! 15: #include "message.h" ! 16: #include "monitor.h" ! 17: #include "stopwatch.h" ! 18: ! 19: class MainbusDevice; ! 20: class MainRAMDevice; ! 21: ! 22: class Syncer : public Device ! 23: { ! 24: using inherited = Device; ! 25: ! 26: public: ! 27: // 動作モード ! 28: // 動作モード変数 (mode) はスケジューラの走行状態を表している。以下の ! 29: // ビットがすべて %0 なら高速モード、どれかでも %1 なら通常モードになる。 ! 30: // ! 31: // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | ! 32: // mode | |POFF|KEY |BOOT|SYNC| CPUSTAT | ! 33: // | | | | +---+---- CPU の状態 ! 34: // | | | +-------------- 高速モード抑制 ! 35: // | | +------------------- ブートページ実行中 ! 36: // | +------------------------ キー入力中 ! 37: // +----------------------------- 電源オフ ! 38: // ! 39: // bit1,0 (CPUSTAT) は CPU の状態を示す。%00 の時だけ高速走行が可能。 ! 40: // これは RequestCPUMode() の引数で指定する。 ! 41: // b1 b0 ! 42: // 0 0 通常状態 ! 43: // 0 1 STOP 状態 (m88k なら擬似 STOP 状態) ! 44: // 1 0 HALT 状態 (ダブルバスフォールト) ! 45: // 1 1 HALT 状態だがこちらのビットパターンは使わない ! 46: ! 47: static const uint32 SCHED_CPU_STOP = 0x0001; // CPU が STOP 状態 ! 48: static const uint32 SCHED_CPU_HALT = 0x0002; // CPU が HALT 状態 ! 49: static const uint32 SCHED_SYNC = 0x0004; // 高速モード抑制指示(UI) ! 50: static const uint32 SCHED_BOOT = 0x0008; // ブートページ実行中 ! 51: static const uint32 SCHED_KEY = 0x0010; // キー入力中 ! 52: static const uint32 SCHED_POWEROFF = 0x0020; // 電源オフ ! 53: ! 54: // 便宜上用意しておく ! 55: static const uint32 SCHED_CPU_NORMAL= 0x0000; // CPU が通常状態 ! 56: static const uint32 SCHED_CPU_MASK = (SCHED_CPU_STOP | SCHED_CPU_HALT); ! 57: ! 58: public: ! 59: Syncer(); ! 60: ~Syncer() override; ! 61: ! 62: bool Init() override; ! 63: ! 64: void StartTime(); // 時間の始まり ! 65: ! 66: void StartRealTime(); // 実時間を再開 ! 67: void StopRealTime(); // 実時間を停止 ! 68: ! 69: uint64 GetRealTime() const { return rtime; } ! 70: ! 71: // 現在の実行モードを返す。 ! 72: uint32 GetRunMode() const { return mode; } ! 73: ! 74: // CPU 状態変更を指示する。 ! 75: void RequestCPUMode(uint32 mode_); ! 76: ! 77: // 高速モード(UIによる指示)なら true を返す。 ! 78: // ここでいう高速モードは STOP 状態中でも高速モード。 ! 79: bool GetFullSpeed() const { return ((mode & SCHED_SYNC) == 0); } ! 80: ! 81: // 高速モードを指示する。 ! 82: // true なら高速モード、false なら同期モード。 ! 83: void RequestFullSpeed(bool enable); ! 84: ! 85: // ブートページモードの変更を指示する。 ! 86: void RequestBootPageMode(bool isrom); ! 87: ! 88: // キー入力状態の変更を指示する。 ! 89: void RequestKeyPressed(bool pressed); ! 90: ! 91: // 電源オフの状態の変更を指示する。オフになったとき true。 ! 92: void RequestPowerOffMode(bool poweroff); ! 93: ! 94: // パフォーマンス測定用に実時間をログ出力 ! 95: void PutlogRealtime(); ! 96: ! 97: // パフォーマンスカウンタの値取得 (UI 表示用) ! 98: int GetPerfCounter() const { return perf_counter; } ! 99: ! 100: // モニタ更新の下請け ! 101: int MonitorUpdateSub(TextScreen& screen, uint64 vtime); ! 102: ! 103: private: ! 104: void ChangeMode(uint32 newmode); ! 105: ! 106: // 同期イベント ! 107: void SyncCallback(Event& ev); ! 108: ! 109: // 動作モード変更メッセージ ! 110: void ChangeModeCallback(MessageID, uint32); ! 111: ! 112: // 同期処理 ! 113: void DoSync(); ! 114: ! 115: void CalcPerf(); ! 116: ! 117: // スケジューラの動作モード。SCHED_* ! 118: uint32 mode {}; ! 119: ! 120: // 実時間の基準となるストップウォッチ ! 121: Stopwatch realtime {}; ! 122: ! 123: // 同期した時点の実経過時間 ! 124: uint64 rtime {}; ! 125: ! 126: // 同期調整用 ! 127: uint64 rtime_epoch {}; ! 128: uint64 vtime_epoch {}; ! 129: ! 130: // sleep しすぎた時間の最大値 ! 131: uint64 overslept {}; ! 132: ! 133: // 同期回数 ! 134: uint sync_count {}; // 現在の1秒間での同期回数 ! 135: uint last_sync_count {}; // 前回の1秒間での同期回数 ! 136: ! 137: // パフォーマンスカウンタ ! 138: // perfq が移動平均用のバッファ。四捨五入用に10倍値を持っておく ! 139: // (100% なら 1000)。perf_counter は perfq から求めた実行率で ! 140: // 小数以下を四捨五入する (のでこっちは 100% なら 100)。 ! 141: int perf_counter {}; // 実行率 [%] ! 142: FixedQueue<uint32, 3> perfq {}; // 移動平均用のバッファ ! 143: uint64 next_perf_rtime {}; // 次回測定予定の実経過時間 ! 144: uint64 last_perf_rtime {}; // 前回測定時の実経過時間 ! 145: uint64 last_perf_vtime {}; // 前回測定時の仮想経過時間 ! 146: ! 147: MainbusDevice *mainbus {}; ! 148: MainRAMDevice *mainram {}; ! 149: ! 150: // 同期イベント ! 151: Event sync_event { this }; ! 152: }; ! 153: ! 154: static inline Syncer *GetSyncer() { ! 155: return Object::GetObject<Syncer>(OBJ_SYNCER); ! 156: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.