--- nono/vm/device.h 2026/04/29 17:05:29 1.1.1.16 +++ nono/vm/device.h 2026/04/29 17:05:51 1.1.1.18 @@ -30,10 +30,56 @@ assert((bool)__CONCAT(p,NAME)); \ } while (0) +// ユーザ定義リテラルを使ったサフィックス + +// ナノ秒 +static inline constexpr uint64 operator"" _nsec(unsigned long long ns) +{ + return ns; +} +static inline constexpr uint64 operator"" _nsec(long double ns) +{ + return ns; +} + +// マイクロ秒 +static inline constexpr uint64 operator"" _usec(unsigned long long us) +{ + return us * 1000_nsec; +} +static inline constexpr uint64 operator"" _usec(long double us) +{ + return us * 1000_nsec; +} + +// ミリ秒 +static inline constexpr uint64 operator"" _msec(unsigned long long ms) +{ + return ms * 1000_usec; +} +static inline constexpr uint64 operator"" _msec(long double ms) +{ + return ms * 1000_usec; +} + +// 秒 +static inline constexpr uint64 operator"" _sec(unsigned long long sec) +{ + return sec * 1000_msec; +} +static inline constexpr uint64 operator"" _sec(long double sec) +{ + return sec * 1000_msec; +} + // 前方参照 +class Device; +class Event; class MainMPUDevice; class Scheduler; +using EventCallback_t = void (Device::*)(Event *); + class Device : public Object { using inherited = Object; @@ -57,26 +103,35 @@ class Device : public Object // Create() もこのフェーズで呼ばれる。 // ここでも gConfig の参照および内部変数の登録は可能、エラー終了する // 可能性のあるものも処理できる。 - // Init() とは異なりこちらは、継承クラスの Create() が Device::Create() - // を呼ぶ必要はない + // 継承クラスの Create() は Device::Create() を呼ぶ必要はない。 // putmsg() は使えない。 // - // 3. parse_logopt() ... -L オプションの処理 - // この時点でログの割り当てを受ける Object 由来のオブジェクトはすべて - // 出揃っている必要がある。 - // またここで --show-config も行うため、この時点で gConfig の内容は確定し - // 以降 gConfig の変更は出来ない。 + // 3. EarlyInit() ... ログ出力の初期化 + // ここですべての Device に対してログ出力のための変数を初期化する。 + // ただし putmsg() が使えるのは 4. 以降。 + // これは override しない。 + // + // 4. 設定とログの締め切り。 + // これ以降 gConfig の変更は出来ない。 + // またログの割り当てを受ける Object 由来のオブジェクトはすべて出揃って + // いる必要がある。 + // 4.1 この時点で gConfig の内容は確定したので、--show-config を行う。 + // 4.2 ParseLogopt() ... -L オプションの処理。 + // + // 5. Create2() ... 動的コンストラクションその2 + // 作成にあたってログ出力をしたいホストドライバのためのフェーズ。 + // ログは既存のものから従属するしか出来ない。 + // putmsg() は使える。 + // EarlyInit() は Create2() のループ後に改めて呼ばれる。 // - // (4.) ParseMonitors() ... -M オプションの処理 - // (GUI 版のみ) この時点で Monitor がすべて登録されている必要がある。 + // 6. ParseMonitors() ... -M オプションの処理 + // (GUI 版のみ) この時点で Monitor はすべて登録されている必要がある。 // - // 5. Init() ... 初期化 + // 7. Init() ... 初期化 // この時点で Object 由来のオブジェクトはすべて出揃っているため、他の - // Object はすべてアクセス可能。また、ログレベルも確定しているのでこれ - // 以降 putmsg() は使える。 - // 基底クラスの Device::Init() がログ出力に必要なメンバ変数を初期化して - // いるため、派生クラスで Init() を用意した場合は必ず inherited::Init() - // を呼ぶこと。 + // Object はすべてアクセス可能。 + // 継承クラスは Device::Init() を呼ぶ必要はないが、子クラスが親クラスの + // Init() を呼ぶことを要求することはあるかもしれない。 // gConfig の設定項目のうち内容によってエラー終了する可能性があるものは // ここまでに処理する。 // 複数のオブジェクトが同じ設定項目を処理しないようにすること (複数で @@ -85,37 +140,29 @@ class Device : public Object // (A::Init() で設定した値を B::Init() が参照する必要があるケース) に // ついては vm.cpp (などコンテナデバイス) 内のコンストラクタの順序で // 手動調整すること (循環参照不可)。 - // ホストデバイスの個別ドライバはここで起動する。本来 Create() で行いたい - // ところだが、ネットワークドライバの選択などは複雑なので putmsg() を - // 使いたい。そうするとここまで遅延せざるを得ない。そのため 3. を過ぎて - // からオブジェクトが増えることになるが、個別ドライバは新たなログ名を - // 増やさず、ホストドライバのログレベルを継承するため、ぎりぎり大丈夫。 - // スレッドはまだ起動していない。 - // - // 6. StartThread() ... スレッド起動 - // - // 7. Apply() ... 動的設定の適用 - // 実行中に変更可能なパラメータもここで一度適用する。 - // ここで適用するのは実行中に変更可能なパラメータのみ。 - // 適用内容を表示したい時は putlog(1) が妥当か。 // - // 8. ResetHard(true) ... 電源オン + // 8. StartThread() ... スレッド起動 + // + // 9. ResetHard(true) ... 電源オン + + // ログの初期化。 + void EarlyInit(); // 動的コンストラクション。 // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err() // 系でエラーメッセージを表示して false を返すこと。 virtual bool Create(); - // 初期化。 + // 動的コンストラクションその2。 // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err() // 系でエラーメッセージを表示して false を返すこと。 - virtual bool Init(); + // putmsg() は使える。 + virtual bool Create2(); - // 現在の設定を VM に反映させる。 + // 初期化。 // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err() // 系でエラーメッセージを表示して false を返すこと。 - // といっても false が返されたらどうするんだろうか。 - virtual bool Apply(); + virtual bool Init(); // 電源オンもしくはリセット。 // true なら電源オン、false ならリセット。 @@ -144,8 +191,6 @@ class IODevice : public Device public: ~IODevice() override; - bool Init() override; - public: // メイン CPU からのデバイスの読み込み。 // busaddr.Addr にアドレス、busaddr.Size に要求バイト数がセットされている。 @@ -188,40 +233,3 @@ class IODevice : public Device // 書き込み可能なら true、書き込み不可能なら false を返す。 virtual bool Poke1(uint32 addr, uint32 data); }; - -class BusErrDevice : public IODevice -{ - using inherited = IODevice; - public: - BusErrDevice(); - ~BusErrDevice() override; - - public: - busdata Read(busaddr addr) override; - busdata Write(busaddr addr, uint32 data) override; - busdata Peek1(uint32 addr) override; -}; - -// 何もしないデバイス。 -// 読み込むと全域で 0xff が読めて、書き込んでも何も起きない。 -class NopIODevice : public IODevice -{ - using inherited = IODevice; - public: - NopIODevice(); - ~NopIODevice() override; - - public: - busdata Read(busaddr addr) override; - busdata Write(busaddr addr, uint32 data) override; - busdata Read1(uint32 addr) override; - busdata Write1(uint32 addr, uint32 data) override; - busdata Peek1(uint32 addr) override; -}; - -static inline BusErrDevice *GetBusErrDevice() { - return Object::GetObject(OBJ_BUSERR); -} -static inline NopIODevice *GetNopIODevice() { - return Object::GetObject(OBJ_NOPIO); -}