--- nono/m88xx0/m88200.h 2026/04/29 17:04:41 1.1.1.3 +++ nono/m88xx0/m88200.h 2026/04/29 17:05:07 1.1.1.7 @@ -9,6 +9,7 @@ #pragma once #include "bus.h" +#include "monitor.h" #include class m88kcpu; @@ -31,29 +32,43 @@ struct m88200BATC // +-------------------------+-------------------------+-+-------+--+ // | LBA | 0 |S| 0 |~V| // +-------------------------+-------------------------+-+-------+--+ - uint32 lba; // LBA,S,V + static const uint32 S = 0x00000020; + static const uint32 INVALID = 0x00000001; + uint32 lba; // LBA,S,~V uint32 pba; // PBA // stat は ACC_STAT_MASK と同じ WT,G,CI,WP のみ使用。 - // BATC (BWP レジスタ) のビット位置とは違うので注意。 + // BWP (BATC Write Port) のビット位置とは違うので注意。 uint32 stat; bool wp; // WP (比較で使うのでこれだけ抜き出しておく) + + // このエントリが有効なら true を返す + bool IsValid() const { return (lba & INVALID) == 0; } + // S ビットが立っていれば true を返す + bool IsS() const { return (lba & S); } }; // PATC struct m88200PATC { - // LPA には S ビットと有効/無効情報を混ぜておく。比較を1回で済ませるため。 + // LPA には S, V ビットを混ぜておく。比較を1回で済ませるため。 // V ビットは invalid なら %1 にして一致しなくしておく。実際の // PATC エントリの有効/無効は 46ビットの PATC 構造の外で管理されている? // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 // +---------------------------------------+-----------+-+-------+--+ - // | LPA | |S| 0 |~V| + // | LPA | 0 |S| 0 |~V| // +---------------------------------------+-----------+-+-------+--+ - uint32 lpa; // LPA,S,(V) + static const uint32 S = 0x00000020; + static const uint32 INVALID = 0x00000001; + uint32 lpa; // LPA,S,~V uint32 pfa; // PFA uint32 stat; // ACC_STAT_MASK と同じ WT,G,CI,WP のみ使用。 bool m; // Modified bool wp; // Write Protect (比較で使うのでこれだけ抜き出しておく) + + // このエントリが有効なら true を返す + bool IsValid() const { return (lpa & INVALID) == 0; } + // S ビットが立っていれば true を返す + bool IsS() const { return (lpa & S); } }; // キャッシュの1セット @@ -128,6 +143,7 @@ class m88200CacheSet class m88200 : public Object { + using inherited = Object; public: m88200(); ~m88200() override; @@ -138,9 +154,16 @@ class m88200 : public Object // リセット void Reset(); - void MonitorUpdate(TextScreen&) override; + // モニター + Monitor reg_monitor { this }; + Monitor atc_monitor { this }; + Monitor cache_monitor { this }; private: + DECLARE_MONITOR_CALLBACK(MonitorUpdateReg); + DECLARE_MONITOR_CALLBACK(MonitorUpdateATC); + DECLARE_MONITOR_CALLBACK(MonitorUpdateCache); + m88kcpu *parent {}; public: @@ -254,11 +277,12 @@ class m88200 : public Object private: uint32 GetAPR(const m88200APR&) const; void SetAPR(m88200APR&, uint32 data); + // 現在の xAPR + const m88200APR *acc_apr {}; public: uint32 GetAPR(uint issuper) const; uint32 GetUAPR() const { return GetAPR(uapr); } uint32 GetSAPR() const { return GetAPR(sapr); } - void SetAPR(uint issuper, uint32 data); void SetUAPR(uint32 data) { SetAPR(uapr, data); } void SetSAPR(uint32 data) { SetAPR(sapr, data); } @@ -300,17 +324,15 @@ class m88200 : public Object // | | |S|W|G|C|W|V| // | Logical Block Address | Physical Block Address | |T| |I|P| | // +---------------------------------------------------------------+ - static const uint32 BATC_LBA_MASK = 0xfff80000; - static const uint32 BATC_PBA_MASK = 0x0007ffc0; - static const uint32 BATC_S = 0x00000020; // Address Space - static const uint32 BATC_WT = 0x00000010; // WriteThrough - static const uint32 BATC_G = 0x00000008; // Global - static const uint32 BATC_CI = 0x00000004; // Cache Inhibit - static const uint32 BATC_WP = 0x00000002; // Write Protect - static const uint32 BATC_V = 0x00000001; // Valid - std::array batc {}; - uint32 GetBATC(uint n) const; - void SetBATC(uint n, uint32 val); + static const uint32 BWP_LBA_MASK = 0xfff80000; + static const uint32 BWP_PBA_MASK = 0x0007ffc0; + static const uint32 BWP_S = 0x00000020; // Address Space + static const uint32 BWP_WT = 0x00000010; // WriteThrough + static const uint32 BWP_G = 0x00000008; // Global + static const uint32 BWP_CI = 0x00000004; // Cache Inhibit + static const uint32 BWP_WP = 0x00000002; // Write Protect + static const uint32 BWP_V = 0x00000001; // Valid + void SetBWP(uint n, uint32 val); // CDP0-3 (Cache Data Ports 0..3) +$800..+$80c // 3 2 1 @@ -424,12 +446,16 @@ class m88200 : public Object static const uint32 DESC_WP = 0x00000004; // Write Protect static const uint32 DESC_V = 0x00000001; // Valid + uint32 GetLaddr() const { return acc_laddr; } + uint32 GetPaddr() const { return acc_paddrH | acc_paddrL; } + private: uint32 acc_laddr {}; // Logical Address uint32 acc_paddrH {}; // Physical Address 上位30ビット。 // 下位2ビットは 0 固定。 uint32 acc_paddrL {}; // paddr の下位2ビット // 上位30ビットは 0 固定。 + public: // acc_stat は 4 ビットのみ使用。 // それ以外のビットは代入時にマスクすること。 static const uint32 ACC_STAT_MASK = DESC_WT | DESC_G | DESC_CI | DESC_WP; @@ -451,9 +477,7 @@ class m88200 : public Object // そうそう変わらないので状態変化を通知してもらう方式。 // true なら super, false なら user。 bool acc_super {}; - void SetSuper(bool super) { - acc_super = super; - } + void SetSuper(bool super); m88200PATC *acc_patc {}; // ヒットした PATC エントリ uint32 tmp_desc {}; // TEMP_DESCR @@ -470,13 +494,64 @@ class m88200 : public Object bool FetchSegmentDesc(); bool FetchPageDesc(); bool UpdatePageDesc(); - void CreatePATCEntry(); - public: + // BATC + static const uint32 BATC_LBA_MASK = BWP_LBA_MASK; + static const uint32 BATC_S = m88200BATC::S; + static const uint32 BATC_INVALID = m88200BATC::INVALID; + void MakeBATCHash(); + std::array batc {}; + // 検索用のハッシュ。値のビットN (0..9) が立っていれば batc[N] がこの + // ハッシュに当たることを示している (この後完全一致で比較する必要はある)。 + // [0x00] => 0b00'0000'0000; + std::array batc_hash_s {}; + std::array batc_hash_u {}; + // 現在の特権状態によって batc_hash_{s,u} のいずれかを指す + uint16 *batc_hash {}; + static int batc_hash_func(uint32 a) { + return (a >> 19) & 0x0f; + } + // PATC - static const uint32 PATC_S = 0x00000020; // Supervisor + static const uint32 PATC_S = m88200PATC::S; + static const uint32 PATC_INVALID = m88200PATC::INVALID; + void CreatePATCEntry(); + void InvalidatePATCHash(int); std::array patc {}; - + // 検索用のハッシュ。値のビット N (0..55) が立っていれば patc[N] がこの + // ハッシュに当たることを示している (この後完全一致で比較する必要はある)。 + std::array patc_hash_s {}; + std::array patc_hash_u {}; + // 現在の特権状態によって patc_hash_{s,u} のいずれかを指す + uint64 *patc_hash {}; + static int patc_hash_func(uint32 a) { + return (a >> 12) & 0xff; + } + // patc[] のうち空きエントリはビットを立てて示す + uint64 patc_free_map {}; + // 次回追加する位置 + int patc_next {}; + + // 統計 + uint64 translate_total {}; + std::array batc_hit {}; + uint64 patc_hit {}; + uint64 atc_miss {}; +#define M88200_STAT 1 +#if defined(M88200_STAT) + // 開発用の統計 + uint64 stat_patc_search {}; // ハッシュを引いた回数 + uint64 stat_patc_hit {}; // ヒットした回数 + uint64 stat_patc_miss1 {}; // ハッシュだけでミスした回数 + uint64 stat_patc_miss2 {}; // ビットを調べてミスした回数 + uint64 stat_patc_create {}; // エントリ作成回数 + uint64 stat_patc_invcmd_all {}; // Invalidate ALL 発行回数 + uint64 stat_patc_invcmd_seg {}; // Invalidate Segment 発行回数 + uint64 stat_patc_invcmd_page {}; // Invalidate Page 発行回数 + uint64 stat_patc_invalidate {}; // 無効にした PATC の総数 + std::array stat_batc_hash_s {}; // BATC.S の衝突状況 + std::array stat_batc_hash_u {}; // BATC.U の衝突状況 +#endif // // キャッシュ @@ -508,18 +583,25 @@ class m88200 : public Object // MBus // public: - // MBus を所有している CMMU ID を返す。誰も持っていなければ -1。 + // MBus を所有している CMMU を返す。誰も持っていなければ NULL。 // これは static 関数 static m88200 *GetBusMaster() { return mbus_master; } // この CMMU からのアクセスにウェイトを加算する (VM から使う) - void AddCycle(uint64 cycle); + void AddCycle(int32 cycle); private: void MBusAcquire(); void MBusRelease() { } + // 他 CMMU にスヌープさせる (バスマスタ側) + void MBusMakeSnoop(uint32, int); + // バススヌープを行う (スレーブ側) + void Snoop(uint32, int); // MBus を所有してる CMMU を指す。NULL なら解放。 // これは static 変数で全 m88200 で共有している static m88200 *mbus_master; + + // スヌープ相手の CMMU リスト + std::vector other_cmmu {}; };