--- nono/m680x0/m68030mmu.h 2026/04/29 17:05:22 1.1.1.7 +++ nono/m680x0/m68030mmu.h 2026/04/29 17:05:35 1.1.1.10 @@ -6,12 +6,11 @@ #pragma once -class MPU680x0Device; +#include +#include +#include "fixedqueue.h" -// ATC_SINGLE は過去との比較のために残してある、双方向リストによる -// FC 混合 22 エントリ実装。 -// 定義しない場合(デフォルト)は、FC 別の世代付き配列みたいなもの。 -//#define ATC_SINGLE 1 +class MPU68030Device; // SRP, CRP class m68030RP @@ -34,7 +33,7 @@ class m68030RP }; // TT レジスタの各フィールドを束ねた構造体のようなもの。 -// MPU680x0Device::SetTT(), GetTT() で読み書きする。 +// MPU68030Device::SetTT(), GetTT() で読み書きする。 class m68030TT { // 3 2 1 0 @@ -127,10 +126,11 @@ class m68030MMUSR struct m68030ATCLine { // tag - // LLLLLLLL_LLLLLLLL_LLLLLLLL_0000000I : L は論理アドレス - // +-- invalid (%1で無効) + // LLLLLLLL'LLLLLLLL'LLLLLLLL'0000FFFI // - // FC はテーブル選択の時点で確定しているのでタグには不要。 + // I は Invalid (%1で無効) + // L は論理アドレス + // F は busaddr 形式の FC (3ビット) だが、FC 別のテーブルなので未使用 // // paddr // PPPPPPPP_PPPPPPPP_PPPPPPPP_00000000 : P は物理アドレス @@ -151,11 +151,9 @@ struct m68030ATCLine static const uint32 MODIFIED = 0x00000001; uint32 tag; -#if defined(ATC_SINGLE) - uint32 fc; -#endif uint32 paddr; uint32 data; + uint32 age; uint32 GetTag() const { return tag; } @@ -169,17 +167,14 @@ struct m68030ATCLine bool IsCInhibit() const { return data & CINHIBIT; } bool IsWProtect() const { return data & WPROTECT; } bool IsModified() const { return data & MODIFIED; } +}; -#if !defined(ATC_SINGLE) - // LRU 用カウンタ - uint32 age; -#else - m68030ATCLine *prev; - m68030ATCLine *next; -#endif - - // デバッグ表示 - std::string fill_print(uint fc); +// ATC の統計情報 +struct m68030ATCStat +{ + uint32 total {}; + uint32 tthit {}; + uint32 miss {}; }; // ATC のテーブル @@ -188,100 +183,91 @@ class m68030ATCTable final public: static const int LINES = 22; - m68030ATCTable(); - ~m68030ATCTable(); + // ATC ハッシュ + enum : uint8 { + HASH_ATC_BASE = 0, // ATC #0- + HASH_NONE = 0xff, // 対応なし + HASH_TT = 0xfe, // TT + HASH_SUB = 0xfd, // PS<4KB + }; -#if !defined(ATC_SINGLE) - // 空きエントリを取得。 - m68030ATCLine *Lookup(); - // a をエントリの先頭に - m68030ATCLine *MoveHead(m68030ATCLine *a); -#else - // 空きエントリを取得。 - m68030ATCLine *lookup(); - // LRU の先頭、2番目に追加 - void insert_head(m68030ATCLine *); - void insert_second(m68030ATCLine *); - // LRU の先頭、2番目に移動 - void move_head(m68030ATCLine *); - void move_second(m68030ATCLine *); - // LRU の末尾に追加 - void insert_tail(m68030ATCLine *); - // LRU から削除 - void remove(m68030ATCLine *); -#endif + m68030ATCTable(MPU68030Device *cpu_, uint fc_); + ~m68030ATCTable(); // フラッシュ - // flush() はこのテーブルのすべてのエントリが対象。 - // flush(addr) はこのテーブルのアドレスが一致するエントリが対象。 - // flush_fc(fc) はこのテーブルの FC が fc であるエントリが対象。 - // flush(fc, addr) はこのテーブルの fc と addr が一致するエントリが対象。 - // いずれも ATC クラスから呼ばれるが、ATC_SINGLE によって、一致する FC が - // 呼び出し前に決定されているかこちらで比較しないといけないかが変わる。 - void flush(); -#if !defined(ATC_SINGLE) - void flush(uint32 addr); -#else - void flush_fc(uint32 fc); - void flush(uint32 fc, uint32 addr); -#endif + // Flush() はこのテーブルのすべてのエントリが対象。 + // Flush(addr) はこのテーブルのアドレスが一致するエントリが対象。 + void Flush(); + void Flush(uint32 addr); + + // PS<4KB の時に ATC を検索。 + m68030ATCLine *FindSub(const busaddr laddr); + + // テーブルサーチ。 + // テーブルという用語がぶつかってしまったので MMU サーチと呼ぶ。 + m68030ATCLine *MMUSearch(busaddr laddr); + + void Invalidate(m68030ATCLine *a); + void InvalidateSub(const m68030ATCLine *); + + void MakeHash(const m68030ATCLine *); + void MoveHead(m68030ATCLine *); + m68030ATCLine *RemoveTail(); + + // デバッグ表示 + std::string LineToStr(const m68030ATCLine *a) const; // ATC 実体 m68030ATCLine line[LINES] {}; - // 先頭から何エントリ目でヒットしたかの統計。最後の +1 はキャッシュミス。 - uint64 hit[LINES + 1] {}; + uint32 latest_age {}; + + // このテーブルの FC + uint fc {}; + + // PS(ページのビット長) - 12。負数なら PS<4KB + int ps4k {}; + + // 統計 + m68030ATCStat atcstat {}; - // ATC_SINGLE ならリストの先頭。 - // !ATC_SINGLE なら注目エントリ。 - m68030ATCLine *head {}; - -#if !defined(ATC_SINGLE) - // LRU 用の更新カウンタ - uint32 counter {}; - // head のヒット回数。 - uint64 hit_head {}; -#endif + // 移動平均用バッファ。(こっちは排他制御が必要) + FixedQueue atchist {}; + bool atchist_tt_once_hit {}; + std::mutex atchist_mtx {}; int loglevel {}; - MPU680x0Device *cpu {}; + MPU68030Device *cpu {}; + + // ATC ハッシュ (他のメンバより後ろに置く?) + std::array hash {}; }; // ATC (Address Translation Cache) class m68030ATC final { - friend class MPU680x0Device; public: - m68030ATC(MPU680x0Device *); + explicit m68030ATC(MPU68030Device *); ~m68030ATC(); // ログレベルを設定する。Object のとは同じ使い方だけど別物。 void SetLogLevel(int loglevel_); - // エントリをサーチ&更新 - const m68030ATCLine& fill_fetch(busaddr addr); - const m68030ATCLine& fill_read(busaddr addr); - const m68030ATCLine& fill_write(busaddr addr); - // デバッグ用にエントリを検索 - const m68030ATCLine *fill_peek(uint32 laddr, uint fc); - // フラッシュ (pflush* 命令から呼ばれる) void flush(); void flush(uint32 fc, uint32 mask); void flush(uint32 fc, uint32 mask, uint32 addr); - private: -#if !defined(ATC_SINGLE) + // テーブルの実体。 + std::unique_ptr tables[4] {}; + // FC ごとのテーブル。 - // 8個確保してあるが実際に使うのはこのうち4つだけ。 - m68030ATCTable tables[8] {}; -#else - // FC 混合のテーブル。 - m68030ATCTable tables[1] {}; -#endif + // 実際に使うのはこのうち4つだけ。 + std::array fctables {}; int loglevel {}; - MPU680x0Device *cpu {}; + private: + MPU68030Device *cpu {}; };