--- nono/m88xx0/m88200.h 2026/04/29 17:04:34 1.1.1.1 +++ 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セット @@ -79,14 +94,14 @@ class m88200CacheSet // 無効(vv[]==IV)ならビット 0 を 1 にしておく。比較対象の paddr は // 下位12ビットを落としているため、これで絶対に一致しなくなる。 static const uint32 TAG_INVALID = 0x00000001; - uint32 tag[4]; + uint32 tag[4] {}; // LRU // CSSP の L ビットのロジックに従う。 int L {}; // ステータス - Status vv[4]; + Status vv[4] {}; // データ。word[] は以下の順 // Word @@ -94,10 +109,10 @@ class m88200CacheSet // line0 [ 0] [ 1] [ 2] [ 3] // line1 [ 4] [ 5] [ 6] [ 7] // : - uint32 word[16]; + uint32 word[16] {}; // 自身のセットインデックス - uint32 setidx; + uint32 setidx {}; // 引数 L の状態から line を最新にしたらどうなるか、を返す。 // 表示処理で一時変数に対して処理が必要なため static 分離してある。 @@ -120,18 +135,15 @@ class m88200CacheSet void Update(int line, Status status); - uint64 ReadLine(int line, uint32 tagaddr); - void Write(int line, uint32 paddr, uint32 data, int size); - uint64 CopyBackLine(int line); - // キャッシュを検索して、ヒットした line を返す。 int Lookup(uint32 tagaddr) const; }; class m88200 : public Object { + using inherited = Object; public: m88200(); ~m88200() override; @@ -142,10 +154,17 @@ class m88200 : public Object // リセット void Reset(); - bool MonitorUpdate() override; + // モニター + Monitor reg_monitor { this }; + Monitor atc_monitor { this }; + Monitor cache_monitor { this }; private: - m88kcpu *parent; + DECLARE_MONITOR_CALLBACK(MonitorUpdateReg); + DECLARE_MONITOR_CALLBACK(MonitorUpdateATC); + DECLARE_MONITOR_CALLBACK(MonitorUpdateCache); + + m88kcpu *parent {}; public: // @@ -163,8 +182,8 @@ class m88200 : public Object // 0 で初期化。その後は全ビット変更可能。 // Type は $5 = 88200、$6 = 88204。ここでは 88200 固定。 // Version は不明。 - uint32 id; - uint32 version; + uint32 id {}; + uint32 version {}; // IDR レジスタの内容を返す uint32 GetIDR() const { @@ -181,7 +200,7 @@ class m88200 : public Object // +---------------------------------------------------+-----------+ // | reserved |CommandCode| // +---------------------------------------------------+-----------+ - uint32 command; + uint32 command {}; uint32 GetSCR() const; void SetSCR(uint32 val); private: @@ -212,7 +231,7 @@ class m88200 : public Object static const uint32 SSR_WP = 0x00000004; // Write Protection static const uint32 SSR_BH = 0x00000002; // BATC Hit static const uint32 SSR_V = 0x00000001; // Valid - uint32 ssr; + uint32 ssr {}; uint32 GetSSR() const { return ssr; } void SetSSR(uint32 val) { ssr = val; } @@ -222,7 +241,7 @@ class m88200 : public Object // +---------------------------------------------------------------+ // | Address | // +---------------------------------------------------------------+ - uint32 sar; + uint32 sar {}; uint32 GetSAR() const { return sar; } void SetSAR(uint32 val) { sar = val; } @@ -236,7 +255,7 @@ class m88200 : public Object static const uint32 SCTR_PE = 0x00008000; // Parity Enable static const uint32 SCTR_SE = 0x00004000; // Snoop Enable static const uint32 SCTR_PR = 0x00002000; // Priority Arbitration - uint32 sctr; + uint32 sctr {}; uint32 GetSCTR() const { return sctr; } void SetSCTR(uint32 val); @@ -258,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); } @@ -279,7 +299,7 @@ class m88200 : public Object static const uint32 FAULT_CODE_PAGE = 5; // Page Fault static const uint32 FAULT_CODE_SUPERVISOR = 6; // Supervisor Violation static const uint32 FAULT_CODE_WRITE = 7; // Write Violation - uint32 fault_code; + uint32 fault_code {}; uint32 GetPFSR() const { return fault_code << 16; } @@ -293,7 +313,7 @@ class m88200 : public Object // +---------------------------------------------------------------+ // | Address | // +---------------------------------------------------------------+ - uint32 fault_addr; + uint32 fault_addr {}; uint32 GetPFAR() const { return fault_addr; } void SetPFAR(uint32 val) { fault_addr = val; } @@ -304,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 @@ -428,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; @@ -447,20 +469,18 @@ class m88200 : public Object // の2つに明確に分けて管理することにする。 uint32 acc_sdaddr {}; uint32 acc_pdaddr {}; - bool acc_read; // True if read access + bool acc_read {}; // True if read access bool acc_IsWrite() const { return !acc_read; } // True if write access // S/U 信号線 // 実際には P Bus の Address フェーズで毎回送られてくるが // そうそう変わらないので状態変化を通知してもらう方式。 // true なら super, false なら user。 - bool acc_super; - void SetSuper(bool super) { - acc_super = super; - } + bool acc_super {}; + void SetSuper(bool super); m88200PATC *acc_patc {}; // ヒットした PATC エントリ - uint32 tmp_desc; // TEMP_DESCR + uint32 tmp_desc {}; // TEMP_DESCR // // アドレス変換 @@ -474,20 +494,76 @@ 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 // // キャッシュ // - + private: std::array setarray {}; + // キャッシュラインにメモリから読み込む + uint64 ReadLine(m88200CacheSet& set, int line, uint32 tagaddr); + // キャッシュラインをメモリに書き出す + uint64 CopyBackLine(m88200CacheSet& set, int line); + public: // キャッシュに対して paddr の読み込みを行う uint64 CacheRead(uint32 paddr); // キャッシュに対して paddr への書き込みを行う @@ -503,8 +579,29 @@ class m88200 : public Object MonitorCacheOverview(s, y, -1, is_gui); } + // + // MBus + // + public: + // MBus を所有している CMMU を返す。誰も持っていなければ NULL。 + // これは static 関数 + static m88200 *GetBusMaster() { return mbus_master; } + + // この CMMU からのアクセスにウェイトを加算する (VM から使う) + void AddCycle(int32 cycle); + private: - // まだない - void MBusAcquire() { } + 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 {}; };