--- nono/m88xx0/m88200.h 2026/04/29 17:05:30 1.1.1.11 +++ nono/m88xx0/m88200.h 2026/04/29 17:05:56 1.1.1.13 @@ -13,6 +13,8 @@ #include "mainbus.h" #include +#define M88200_STAT + class MPU88xx0Device; class MainbusDevice; @@ -21,6 +23,7 @@ struct m88200APR { bool enable; uint32 addr; + // stat は ACC_STAT_MASK と同じ位置の WT,G,CI のみ使用。APR に WP はない。 uint32 stat; const char *name; // 自分の名前(ログ表示用) }; @@ -90,12 +93,11 @@ class m88200CacheSet IV = 3, // Invalid }; - // // 3 2 1 - // 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 - // +---------------------------------------+---------------+----+---+ - // | tag | set |Word| | - // +---------------------------------------+---------------+----+---+ + // 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 + // +---------------------------------------+---------------+----+-+--+ + // | tag | set |word|0|~V| + // +---------------------------------------+---------------+----+-+--+ // タグはアドレスの上位 20ビット。 // ただし無効なラインかどうかのチェックも一度で済ませるために @@ -106,7 +108,7 @@ class m88200CacheSet // LRU // CSSP の L ビットのロジックに従う。 - int L {}; + uint L {}; // ステータス Status vv[4] {}; @@ -124,15 +126,15 @@ class m88200CacheSet // 引数 L の状態から line を最新にしたらどうなるか、を返す。 // 表示処理で一時変数に対して処理が必要なため static 分離してある。 - static int TryUseLine(int L, int line); + static uint TryUseLine(uint tmpL, int line); // 引数 L の状態から line を最古にしたらどうなるか、を返す。 // 対称性のため static 分離してある。 - static int TryUnuseLine(int L, int line); + static uint TryUnuseLine(uint tmpL, int line); // 引数 L の状態で、最新の line を返す。 // 表示処理で一時変数に対して処理が必要なため static 分離してある。 - static int TryGetOldestLine(int L); + static int TryGetOldestLine(uint tmpL); void Use(int line) { L = TryUseLine(L, line); @@ -162,9 +164,9 @@ class m88200 : public Device void Reset(); private: - DECLARE_MONITOR_CALLBACK(MonitorUpdateReg); - DECLARE_MONITOR_CALLBACK(MonitorUpdateATC); - DECLARE_MONITOR_CALLBACK(MonitorUpdateCache); + DECLARE_MONITOR_SCREEN(MonitorScreenReg); + DECLARE_MONITOR_SCREEN(MonitorScreenATC); + DECLARE_MONITOR_SCREEN(MonitorScreenCache); MPU88xx0Device *parent {}; @@ -188,7 +190,6 @@ class m88200 : public Device // ID はリセット時、下位7ビットはハードウェアで初期化、最上位ビットは // 0 で初期化。その後は全ビット変更可能。 // Type は $5 = 88200、$6 = 88204。ここでは 88200 固定。 - // Version は不明。 uint32 id {}; uint32 version {}; @@ -214,8 +215,8 @@ class m88200 : public Device static const uint32 GG_PAGE = 1; static const uint32 GG_SEG = 2; static const uint32 GG_ALL = 3; - void FlushCache(); - void InvalidatePATC(); + void FlushCacheCmd(); + void InvalidatePATCCmd(); public: // SSR (System Status Register) +$008 @@ -391,27 +392,26 @@ class m88200 : public Device // // 物理バスアクセス // - // XXX size をどうするか - busdata MBusRead(uint32 paddr, int size); - busdata MBusWrite(uint32 paddr, uint32 data, int size); - busdata MBusXmem(uint32 paddr, uint32 data, int size); + busdata MBusRead(busaddr paddr); + busdata MBusWrite(busaddr paddr, uint32 data); + busdata MBusXmem(busaddr paddr, uint32 data); // // アクセス関数 // private: - template uint64 load(uint32 addr); - template uint64 store(uint32 addr, uint32 data); - template uint64 xmem(uint32 addr, uint32 data); + template busdata load(uint32 addr); + template busdata store(uint32 addr, uint32 data); + template busdata xmem(uint32 addr, uint32 data); public: - uint64 load_1(uint32 addr); - uint64 load_2(uint32 addr); - uint64 load_4(uint32 addr); - uint64 store_1(uint32 addr, uint32 data); - uint64 store_2(uint32 addr, uint32 data); - uint64 store_4(uint32 addr, uint32 data); - uint64 xmem_1(uint32 addr, uint32 data); - uint64 xmem_4(uint32 addr, uint32 data); + busdata load_1(uint32 addr); + busdata load_2(uint32 addr); + busdata load_4(uint32 addr); + busdata store_1(uint32 addr, uint32 data); + busdata store_2(uint32 addr, uint32 data); + busdata store_4(uint32 addr, uint32 data); + busdata xmem_1(uint32 addr, uint32 data); + busdata xmem_4(uint32 addr, uint32 data); // // 現在のアクセス中の状態。 @@ -457,14 +457,9 @@ class m88200 : public Device 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 固定。 + uint32 acc_paddr {}; // Physical Address public: // acc_stat は 4 ビットのみ使用。 @@ -479,7 +474,7 @@ class m88200 : public Device // pdaddr ... Page Descriptor Address // の2つに明確に分けて管理することにする。 uint32 acc_sdaddr {}; - uint32 acc_pdaddr {}; + busaddr acc_pdaddr {}; bool acc_read {}; // True if read access bool acc_IsWrite() const { return !acc_read; } // True if write access @@ -512,40 +507,44 @@ class m88200 : public Device 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 = m88200PATC::S; static const uint32 PATC_INVALID = m88200PATC::INVALID; void CreatePATCEntry(); - void InvalidatePATCEntry(m88200PATC&); + 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[N] が空いていればビット N を立てる。 + uint64 patc_free {}; + // 次回追加する位置。 int patc_next {}; - // BATC/PATC 混合のハッシュ。 - // 1エントリが 4KB の1ページを示し、4GB のメモリ空間全体あるので - // 1M 個 (x User/Supervisor で2倍)。 - // 各エントリは1バイトで、内容は以下の通り。 - // 0: BATC/PATC なし - // 0xff-0xf6: BATC #(~n) - // 1-56: PATC #(n-1) - // BATC は重複して設定することも可能だが、してはいけないとマニュアルに - // 書いてあるので、ここでも動作不定でよいことにする。 - // 前半 (0x00'0000..0x0f'ffff) が User モード用、 - // 後半 (0x10'0000..0x1f'ffff) が Supervisor モード用。 - inline uint32 addr2hash(bool issuper, uint32 addr) const; - void DumpATC(); - std::array atc_hash_all {}; - // 現在の特権状態によって atc_hash_all の [0] か [0x10'0000] を指す。 - uint8 *atc_hash {}; - // 統計 uint64 translate_total {}; std::array batc_hit {}; uint64 patc_hit {}; uint64 atc_miss {}; -#define M88200_STAT #if defined(M88200_STAT) // 開発用の統計 uint64 stat_patc_create {}; // エントリ作成回数 @@ -553,27 +552,38 @@ class m88200 : public Device uint64 stat_patc_invcmd_seg {}; // Invalidate Segment 発行回数 uint64 stat_patc_invcmd_page {}; // Invalidate Page 発行回数 uint64 stat_patc_invalidate {}; // 無効にした PATC の総数 + uint64 stat_patc_search {}; // ハッシュを引いた回数 + uint64 stat_patc_miss1 {}; // ハッシュだけでミスした回数 + uint64 stat_patc_miss2 {}; // ビットを調べてミスした回数 + std::array stat_batc_hash_s {}; // BATC.S の衝突状況 + std::array stat_batc_hash_u {}; // BATC.U の衝突状況 #endif // + // 物理アドレスアクセス + // + busdata PhysRead(busaddr paddr, uint32 stat); + busdata PhysWrite(busaddr paddr, uint32 data, uint32 stat); + + // // キャッシュ // private: std::array setarray {}; // キャッシュラインにメモリから読み込む - uint64 ReadLine(m88200CacheSet& set, uint line, uint32 tagaddr); + bool ReadLine(m88200CacheSet& set, uint line, uint32 tagaddr); // キャッシュラインをメモリに書き出す - uint64 CopyBackLine(m88200CacheSet& set, uint line); + bool CopyBackLine(m88200CacheSet& set, uint line); - public: // キャッシュに対して paddr の読み込みを行う - uint64 CacheRead(uint32 paddr); + busdata CacheRead(uint32 paddr); // キャッシュに対して paddr への書き込みを行う - uint64 CacheWrite(uint32 paddr, uint32 data, uint size); - uint64 CacheWriteHit(m88200CacheSet& set, uint line, + busdata CacheWrite(uint32 paddr, uint32 data, uint size); + busdata CacheWriteHit(m88200CacheSet& set, uint line, uint32 paddr, uint32 data, uint size); - uint64 CacheXmem(uint32 paddr, uint32 data, uint size); + busdata CacheXmem(uint32 paddr, uint32 data, uint size); + public: // モニタスクリーン作成用 void MonitorCacheSet(TextScreen&, int y, uint setidx); void MonitorCacheOverview(TextScreen&, int y, uint cursor, bool is_gui); @@ -590,12 +600,14 @@ class m88200 : public Device static m88200 *GetBusMaster() { return mbus_master; } private: + static constexpr bool IM_0 = false; + static constexpr bool IM_1 = true; void MBusAcquire(); void MBusRelease() { } // 他 CMMU にスヌープさせる (バスマスタ側) - void MBusMakeSnoop(uint32, uint); + void MBusMakeSnoop(uint32 addr, bool im); // バススヌープを行う (スレーブ側) - void Snoop(uint32, uint); + void Snoop(uint32 addr, bool im); MainbusDevice *mainbus {};