Annotation of nono/vm/device.h, revision 1.1.1.18

1.1       root        1: //
                      2: // nono
1.1.1.4   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.12  root        7: //
                      8: // デバイスの基本クラスなど
                      9: //
                     10: 
1.1       root       11: #pragma once
                     12: 
                     13: #include "object.h"
1.1.1.15  root       14: #include "bus.h"
1.1       root       15: 
                     16: #if BYTE_ORDER == LITTLE_ENDIAN
                     17: #define HB(addr)       ((addr) ^ 1)
                     18: #define HLB(addr)      ((addr) ^ 3)
                     19: #define HLW(addr)      ((addr) ^ 2)
                     20: #else
                     21: #define HB(addr)       (addr)
1.1.1.5   root       22: #define HLB(addr)      (addr)
                     23: #define HLW(addr)      (addr)
1.1       root       24: #endif
                     25: 
1.1.1.15  root       26: // デバイスを作成して代入するマクロ。
                     27: // …だったが今となってはあまり意味がなくなっている。
                     28: #define NEWDV(NAME, NEW_CTOR)  do {    \
                     29:        __CONCAT(p,NAME).reset(NEW_CTOR);       \
1.1.1.16  root       30:        assert((bool)__CONCAT(p,NAME)); \
1.1.1.15  root       31: } while (0)
                     32: 
1.1.1.18! root       33: // ユーザ定義リテラルを使ったサフィックス
        !            34: 
        !            35: // ナノ秒
        !            36: static inline constexpr uint64 operator"" _nsec(unsigned long long ns)
        !            37: {
        !            38:        return ns;
        !            39: }
        !            40: static inline constexpr uint64 operator"" _nsec(long double ns)
        !            41: {
        !            42:        return ns;
        !            43: }
        !            44: 
        !            45: // マイクロ秒
        !            46: static inline constexpr uint64 operator"" _usec(unsigned long long us)
        !            47: {
        !            48:        return us * 1000_nsec;
        !            49: }
        !            50: static inline constexpr uint64 operator"" _usec(long double us)
        !            51: {
        !            52:        return us * 1000_nsec;
        !            53: }
        !            54: 
        !            55: // ミリ秒
        !            56: static inline constexpr uint64 operator"" _msec(unsigned long long ms)
        !            57: {
        !            58:        return ms * 1000_usec;
        !            59: }
        !            60: static inline constexpr uint64 operator"" _msec(long double ms)
        !            61: {
        !            62:        return ms * 1000_usec;
        !            63: }
        !            64: 
        !            65: // 秒
        !            66: static inline constexpr uint64 operator"" _sec(unsigned long long sec)
        !            67: {
        !            68:        return sec * 1000_msec;
        !            69: }
        !            70: static inline constexpr uint64 operator"" _sec(long double sec)
        !            71: {
        !            72:        return sec * 1000_msec;
        !            73: }
        !            74: 
1.1.1.13  root       75: // 前方参照
1.1.1.18! root       76: class Device;
        !            77: class Event;
1.1.1.16  root       78: class MainMPUDevice;
1.1.1.13  root       79: class Scheduler;
                     80: 
1.1.1.18! root       81: using EventCallback_t = void (Device::*)(Event *);
        !            82: 
1.1       root       83: class Device : public Object
                     84: {
1.1.1.4   root       85:        using inherited = Object;
1.1       root       86:  protected:
1.1.1.16  root       87:        explicit Device(uint objid_);
1.1       root       88:  public:
1.1.1.15  root       89:        ~Device() override;
1.1       root       90: 
                     91:  public:
                     92:        // 初期化は以下の手順で行う。
                     93:        // 1. コンストラクタ
                     94:        //      メンバ変数の初期値代入などを行う。失敗するケースは考慮していない。
1.1.1.4   root       95:        //      gConfig の内部変数の追加はここ(か2.の動的コンストラクション)で
                     96:        //      行うこと。この時点ですでに gConfig の設定内容の参照は可能だが、
1.1.1.14  root       97:        //      エラーが出るものはここではなく Create() か Init() で処理すること。
1.1.1.12  root       98:        //      putmsg() は使えない。
1.1       root       99:        //
                    100:        // 2. Create() ... 動的コンストラクション
                    101:        //      必要なら設定ファイルによって可変なオブジェクトのコンストラクトを行う。
1.1.1.14  root      102:        //      例えば SCSI ドライブなどが該当する。Create() で作成したインスタンスの
                    103:        //      Create() もこのフェーズで呼ばれる。
                    104:        //      ここでも gConfig の参照および内部変数の登録は可能、エラー終了する
                    105:        //      可能性のあるものも処理できる。
1.1.1.17  root      106:        //      継承クラスの Create() は Device::Create() を呼ぶ必要はない。
1.1.1.14  root      107:        //      putmsg() は使えない。
1.1       root      108:        //
1.1.1.17  root      109:        // 3. EarlyInit() ... ログ出力の初期化
                    110:        //      ここですべての Device に対してログ出力のための変数を初期化する。
                    111:        //      ただし putmsg() が使えるのは 4. 以降。
                    112:        //      これは override しない。
                    113:        //
                    114:        // 4. 設定とログの締め切り。
                    115:        //      これ以降 gConfig の変更は出来ない。
                    116:        //      またログの割り当てを受ける Object 由来のオブジェクトはすべて出揃って
                    117:        //      いる必要がある。
                    118:        //      4.1 この時点で gConfig の内容は確定したので、--show-config を行う。
                    119:        //      4.2 ParseLogopt() ... -L オプションの処理。
                    120:        //
                    121:        // 5. Create2() ... 動的コンストラクションその2
                    122:        //      作成にあたってログ出力をしたいホストドライバのためのフェーズ。
                    123:        //      ログは既存のものから従属するしか出来ない。
                    124:        //      putmsg() は使える。
                    125:        //      EarlyInit() は Create2() のループ後に改めて呼ばれる。
1.1       root      126:        //
1.1.1.17  root      127:        // 6. ParseMonitors() ... -M オプションの処理
                    128:        //      (GUI 版のみ) この時点で Monitor はすべて登録されている必要がある。
1.1.1.10  root      129:        //
1.1.1.17  root      130:        // 7. Init() ... 初期化
1.1.1.13  root      131:        //      この時点で Object 由来のオブジェクトはすべて出揃っているため、他の
1.1.1.17  root      132:        //      Object はすべてアクセス可能。
                    133:        //      継承クラスは Device::Init() を呼ぶ必要はないが、子クラスが親クラスの
                    134:        //      Init() を呼ぶことを要求することはあるかもしれない。
1.1.1.12  root      135:        //      gConfig の設定項目のうち内容によってエラー終了する可能性があるものは
1.1.1.14  root      136:        //      ここまでに処理する。
1.1.1.15  root      137:        //      複数のオブジェクトが同じ設定項目を処理しないようにすること (複数で
                    138:        //      別々に読んでその際の範囲チェックに齟齬が発生するとかを避けるため)。
1.1.1.13  root      139:        //      Object 同士は完全に相互アクセス可能だが、Init() 自身の依存関係
                    140:        //      (A::Init() で設定した値を B::Init() が参照する必要があるケース) に
                    141:        //      ついては vm.cpp (などコンテナデバイス) 内のコンストラクタの順序で
                    142:        //      手動調整すること (循環参照不可)。
1.1.1.12  root      143:        //
1.1.1.17  root      144:        // 8. StartThread() ... スレッド起動
1.1       root      145:        //
1.1.1.18! root      146:        // 9. ResetHard(true) ... 電源オン
1.1.1.17  root      147: 
                    148:        // ログの初期化。
                    149:        void EarlyInit();
1.1       root      150: 
                    151:        // 動的コンストラクション。
1.1.1.12  root      152:        // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err()
                    153:        // 系でエラーメッセージを表示して false を返すこと。
1.1       root      154:        virtual bool Create();
                    155: 
1.1.1.17  root      156:        // 動的コンストラクションその2。
                    157:        // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err()
                    158:        // 系でエラーメッセージを表示して false を返すこと。
                    159:        // putmsg() は使える。
                    160:        virtual bool Create2();
                    161: 
1.1       root      162:        // 初期化。
1.1.1.12  root      163:        // 成功すれば true を返す。失敗なら warn() 系、あるいは gConfig->Err()
                    164:        // 系でエラーメッセージを表示して false を返すこと。
1.1       root      165:        virtual bool Init();
                    166: 
1.1.1.12  root      167:        // 電源オンもしくはリセット。
                    168:        // true なら電源オン、false ならリセット。
1.1.1.8   root      169:        // このデバイスがどのタイミングでリセットされるかは VM による。
                    170:        // X68030 なら vm_x68k.cpp 内のコメント参照。
                    171:        // LUNA は詳細不明。
1.1.1.12  root      172:        virtual void ResetHard(bool poweron);
                    173: 
                    174:        // 電源オフ
                    175:        virtual void PowerOff();
                    176: 
                    177:        // ログ出力
                    178:        void putlogn(const char *fmt, ...) const override __printflike(2, 3);
1.1.1.13  root      179: 
                    180:  protected:
                    181:        // ログに時刻と PPC を出すために必要
1.1.1.16  root      182:        MainMPUDevice *mpu {};
1.1.1.13  root      183:        Scheduler *scheduler {};
1.1       root      184: };
                    185: 
                    186: class IODevice : public Device
                    187: {
1.1.1.4   root      188:        using inherited = Device;
1.1       root      189:  protected:
1.1.1.16  root      190:        explicit IODevice(uint objid_);
1.1       root      191:  public:
1.1.1.15  root      192:        ~IODevice() override;
1.1       root      193: 
                    194:  public:
1.1.1.16  root      195:        // メイン CPU からのデバイスの読み込み。
                    196:        // busaddr.Addr にアドレス、busaddr.Size に要求バイト数がセットされている。
                    197:        // busdata.Size にはポートサイズ (応答バイト数) を返す。
                    198:        // 戻り値 busdata.Data は下詰めし、不要な上位バイトはクリアして返すこと。
                    199:        virtual busdata Read(busaddr addr);
                    200: 
                    201:        // メイン CPU からのデバイスへの書き込み。
                    202:        // busaddr.Addr にアドレス、busaddr.Size に要求バイト数がセットされている。
                    203:        // data は Size バイト分が下詰めされており、上位の不要バイトはクリア済み。
                    204:        // 戻り値の busdata.Size にはポートサイズを返すこと。
                    205:        virtual busdata Write(busaddr addr, uint32 data);
                    206: 
                    207:        // メイン CPU からのバーストアクセス。
                    208:        // addr (16バイト境界) からの 16 バイトを転送してウェイトと OK を返す。
                    209:        // dst/src の uint32 はホストエンディアン。
                    210:        // バースト転送をサポートしてなければ BusData::BusErr を返す。
                    211:        virtual busdata ReadBurst16(busaddr addr, uint32 *dst);
                    212:        virtual busdata WriteBurst16(busaddr addr, const uint32 *src);
                    213: 
                    214:        // XP からのデバイスの読み込み。
                    215:        // 戻り値は busdata.Data の1バイトと必要なら Wait。他は使用しない。
                    216:        virtual busdata Read1(uint32 addr);
                    217: 
                    218:        // XP からのデバイスへの書き込み。
                    219:        // data は1バイト。
                    220:        // 戻り値は busdata.Wait のみ。他は使用しない。
                    221:        virtual busdata Write1(uint32 addr, uint32 data);
1.1.1.13  root      222: 
1.1.1.16  root      223:        // Peek1() はデバッガアクセスで読み込んだ値を (uint32) で返す。
1.1.1.13  root      224:        // バイトアクセスした時に読める値ではなく、現在このアドレスに見えている
1.1.1.16  root      225:        // であろう値。バスエラーなら BusData::BusErr を返す。
                    226:        virtual busdata Peek1(uint32 addr);
1.1       root      227: 
1.1.1.16  root      228:        // Poke1() はデバッガからこのアドレス(メモリ)へ書き込む。
1.1.1.13  root      229:        // メモリでない領域 (レジスタなど) は書き込み不可。
1.1.1.15  root      230:        // data が (int32 で) 非負なら data の下位8ビットを書き込む。
                    231:        // 書き込めれば true、書き込めなければ false を返す。
1.1.1.13  root      232:        // data が (int32 で) 負なら addr への書き込み可否の問い合わせで、
1.1.1.15  root      233:        // 書き込み可能なら true、書き込み不可能なら false を返す。
1.1.1.16  root      234:        virtual bool Poke1(uint32 addr, uint32 data);
1.1       root      235: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.