|
|
nono 1.7.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
// MC88200(CMMU)
#pragma once
#include "device.h"
#include "bus.h"
#include "mainbus.h"
#include <array>
#define M88200_STAT
class MPU88xx0Device;
class MainbusDevice;
// SAPR, UAPR レジスタ
struct m88200APR
{
bool enable;
uint32 addr;
// stat は ACC_STAT_MASK と同じ位置の WT,G,CI のみ使用。APR に WP はない。
uint32 stat;
const char *name; // 自分の名前(ログ表示用)
};
// BATC
struct m88200BATC
{
// LBA には S, V ビットを混ぜておく。比較を1回で済ませるため。
// V ビットは invalid なら %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
// +-------------------------+-------------------------+-+-------+--+
// | LBA | 0 |S| 0 |~V|
// +-------------------------+-------------------------+-+-------+--+
static const uint32 LBAMASK = 0xfff80000;
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 のみ使用。
// 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); }
// 論理アドレス(32ビット)を返す
uint32 Laddr() const { return (lba & LBAMASK); }
};
// PATC
struct m88200PATC
{
// 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 | 0 |S| 0 |~V|
// +---------------------------------------+-----------+-+-------+--+
static const uint32 LPAMASK = 0xfffff000;
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); }
// 論理アドレス(32ビット)を返す
uint32 Laddr() const { return (lpa & LPAMASK); }
};
// キャッシュの1セット
class m88200CacheSet
{
public:
enum Status {
EU = 0, // Exclusive Unmodified
EM = 1, // Exclusive Modified
SU = 2, // Shared Unmodified
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|0|~V|
// +---------------------------------------+---------------+----+-+--+
// タグはアドレスの上位 20ビット。
// ただし無効なラインかどうかのチェックも一度で済ませるために
// 無効(vv[]==IV)ならビット 0 を 1 にしておく。比較対象の paddr は
// 下位12ビットを落としているため、これで絶対に一致しなくなる。
static const uint32 TAG_INVALID = 0x00000001;
uint32 tag[4] {};
// LRU
// CSSP の L ビットのロジックに従う。
uint L {};
// ステータス
Status vv[4] {};
// データ。word[] は以下の順
// Word
// +0 +1 +2 +3
// line0 [ 0] [ 1] [ 2] [ 3]
// line1 [ 4] [ 5] [ 6] [ 7]
// :
uint32 word[16] {};
// 自身のセットインデックス
uint32 setidx {};
// 引数 L の状態から line を最新にしたらどうなるか、を返す。
// 表示処理で一時変数に対して処理が必要なため static 分離してある。
static uint TryUseLine(uint tmpL, int line);
// 引数 L の状態から line を最古にしたらどうなるか、を返す。
// 対称性のため static 分離してある。
static uint TryUnuseLine(uint tmpL, int line);
// 引数 L の状態で、最新の line を返す。
// 表示処理で一時変数に対して処理が必要なため static 分離してある。
static int TryGetOldestLine(uint tmpL);
void Use(int line) {
L = TryUseLine(L, line);
}
// 更新用に最も古いラインを選んで差し出す
int SelectOldestLine() const;
void Update(uint line, Status status);
void Write(uint line, uint32 paddr, uint32 data, uint size);
// キャッシュを検索して、ヒットした line を返す。
int Lookup(uint32 tagaddr) const;
};
class m88200 : public Device
{
using inherited = Device;
public:
m88200(MPU88xx0Device *parent_, uint id_);
~m88200() override;
bool Init() override;
// リセット (ResetHard() ではない)
void Reset();
private:
DECLARE_MONITOR_SCREEN(MonitorScreenReg);
DECLARE_MONITOR_SCREEN(MonitorScreenATC);
DECLARE_MONITOR_SCREEN(MonitorScreenCache);
MPU88xx0Device *parent {};
// モニター
Monitor *reg_monitor {};
Monitor *atc_monitor {};
Monitor *cache_monitor {};
public:
//
// レジスタ
//
// IDR (ID Register) +$000
// 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
// +---------------+-----+---------+-------------------------------+
// | ID | Type| Version | reserved |
// +---------------+-----+---------+-------------------------------+
//
// ID はリセット時、下位7ビットはハードウェアで初期化、最上位ビットは
// 0 で初期化。その後は全ビット変更可能。
// Type は $5 = 88200、$6 = 88204。ここでは 88200 固定。
uint32 id {};
uint32 version {};
// IDR レジスタの内容を返す
uint32 GetIDR() const {
return (id << 24) | (0x5 << 21) | (version << 16);
}
// Version フィールドを設定する
void SetVersion(uint version_);
// SCR (System Command Register) +$004
// 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
// +---------------------------------------------------+-----------+
// | reserved |CommandCode|
// +---------------------------------------------------+-----------+
uint32 command {};
uint32 GetSCR() const;
void SetSCR(uint32 val);
private:
static const char * const commandname[];
static const uint32 GG_LINE = 0;
static const uint32 GG_PAGE = 1;
static const uint32 GG_SEG = 2;
static const uint32 GG_ALL = 3;
void FlushCacheCmd();
void InvalidatePATCCmd();
public:
// SSR (System Status Register) +$008
// 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
// +---------------------------------------------------------------+
// | |C|B| |W|S|G|C| |M|U|W|B|V|
// | reserved |E|E| res |T|P| |I|r| | |P|H| |
// +---------------------------------------------------------------+
static const uint32 SSR_CE = 0x00008000; // Copyback Error
static const uint32 SSR_BE = 0x00004000; // Bus Error
static const uint32 SSR_WT = 0x00000200; // WriteThrough
static const uint32 SSR_SP = 0x00000100; // Supervisor Privilege
static const uint32 SSR_G = 0x00000080; // Global
static const uint32 SSR_CI = 0x00000040; // Cache Inhibit
static const uint32 SSR_M = 0x00000010; // Modified
static const uint32 SSR_U = 0x00000008; // Used
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 GetSSR() const { return ssr; }
void SetSSR(uint32 val) { ssr = val; }
// SAR (System Address Register) +$00c
// 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
// +---------------------------------------------------------------+
// | Address |
// +---------------------------------------------------------------+
uint32 sar {};
uint32 GetSAR() const { return sar; }
void SetSAR(uint32 val) { sar = val; }
// SCTR (System Control Register) +$104
// 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
// +-------------------------------+-+-+-+-------------------------+
// | |P|S|P| |
// | reserved |E|E|R| reserved |
// +-------------------------------+-+-+-+-------------------------+
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 GetSCTR() const { return sctr; }
void SetSCTR(uint32 val);
// SAPR (Supervisor Area Pointer Register) +$200
// UAPR (User Area Pointer Register) +$204
// 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
// +---------------------------------------+---+-+-+-+-+---------+-+
// | Supervisor Segment Table Base Address | |W| |G|C| |T|
// | or User Segment Table Base Address |0 0|T|0| |I|0 0 0 0 0|E|
// +---------------------------------------+---+-+-+-+-+---------+-+
static const uint32 APR_ADDR_MASK = 0xfffff000; // Base Address
static const uint32 APR_WT = 0x00000200; // WriteThrough
static const uint32 APR_G = 0x00000080; // Global
static const uint32 APR_CI = 0x00000040; // Cache Inhibit
static const uint32 APR_TE = 0x00000001; // Translation Enable
m88200APR uapr {};
m88200APR sapr {};
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 SetUAPR(uint32 data) { SetAPR(uapr, data); }
void SetSAPR(uint32 data) { SetAPR(sapr, data); }
// PFSR (P Bus Fault Status Register) +$108
// 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
// +-------------------------+-----+-------------------------------+
// | |Fault| |
// | reserved | Code| reserved |
// +-------------------------+-----+-------------------------------+
static const uint32 FAULT_CODE_SUCCESS = 0; // Success (No fault)
static const uint32 FAULT_CODE_BUSERR = 3; // Bus Error
static const uint32 FAULT_CODE_SEGMENT = 4; // Segment Fault
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 GetPFSR() const {
return fault_code << 16;
}
void SetPFSR(uint32 data) {
fault_code = (data >> 16) & 7;
}
// PFAR (P Bus Fault Address Register) +$10c
// 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
// +---------------------------------------------------------------+
// | Address |
// +---------------------------------------------------------------+
uint32 fault_addr {};
uint32 GetPFAR() const { return fault_addr; }
void SetPFAR(uint32 val) { fault_addr = val; }
void SetFault(uint32 code_, uint32 addr_) {
fault_code = code_;
fault_addr = addr_;
}
// BWP0-7 (BATC Write Ports 0..7) +$400..+$41c
// 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
// +---------------------------------------------------------------+
// | | |S|W|G|C|W|V|
// | Logical Block Address | Physical Block Address | |T| |I|P| |
// +---------------------------------------------------------------+
static const uint32 BWP_LBA_MASK = 0xfff80000;
static const uint32 BWP_PBA_MASK = 0x0007ffc0;
static const uint32 BWP_FLAG_MASK = 0x0000003f;
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);
void SetBATC(uint n, uint32 laddr, uint32 paddr, uint32 flags);
// CDP0-3 (Cache Data Ports 0..3) +$800..+$80c
// 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
// +---------------------------------------------------------------+
// | Data Word |
// +---------------------------------------------------------------+
// CTP0-3 (Cache Tag Ports 0..3) +$840..+$84c
// 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
// +---------------------------------------+-----------------------+
// | Physical Address | reserved |
// +---------------------------------------+-----------------------+
// CSSP (Cache Set Status Port) +$880
// 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
// +---------------------------------------------------------------+
// | |L|L|L|L|L|L|D|D|D|D|VV3|VV2|VV1|VV0| |
// |res|5|4|3|2|1|0|3|2|1|0| | | | | reserved |
// +---------------------------------------------------------------+
static const uint32 CSSP_L5 = 0x20000000; // Line5
static const uint32 CSSP_L4 = 0x10000000; // Line4
static const uint32 CSSP_L3 = 0x08000000; // Line3
static const uint32 CSSP_L2 = 0x04000000; // Line2
static const uint32 CSSP_L1 = 0x02000000; // Line1
static const uint32 CSSP_L0 = 0x01000000; // Line0
static const uint32 CSSP_D3 = 0x00800000; // Line Disable
static const uint32 CSSP_D2 = 0x00400000; // Line Disable
static const uint32 CSSP_D1 = 0x00200000; // Line Disable
static const uint32 CSSP_D0 = 0x00100000; // Line Disable
static const uint32 CSSP_VV3 = 0x000c0000; // Line Valid
static const uint32 CSSP_VV2 = 0x00030000; // Line Valid
static const uint32 CSSP_VV1 = 0x0000c000; // Line Valid
static const uint32 CSSP_VV0 = 0x00003000; // Line Valid
static const uint32 CSSP_VV3_OFFSET = 18;
static const uint32 CSSP_VV2_OFFSET = 16;
static const uint32 CSSP_VV1_OFFSET = 14;
static const uint32 CSSP_VV0_OFFSET = 12;
uint32 GetCSSP() const;
void SetCSSP(uint32 val);
//
// 物理バスアクセス
//
busdata MBusRead(busaddr paddr);
busdata MBusWrite(busaddr paddr, uint32 data);
busdata MBusXmem(busaddr paddr, uint32 data);
//
// アクセス関数
//
private:
template <uint size> busdata load(uint32 addr);
template <uint size> busdata store(uint32 addr, uint32 data);
template <uint size> busdata xmem(uint32 addr, uint32 data);
public:
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);
//
// 現在のアクセス中の状態。
//
// アドレス変換およびデータキャッシュルーチンではこれらの値を
// グローバルに状態変数として使う。
// ディスクリプタの下位にあるフラグは全部ビット位置が同じ。
// Area descriptor (SAPR or UAPR)
// 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
// +---------------------------------------+---+-+-+-+-+---------+-+
// | Supervisor Segment Table Base Address | |W| |G|C| |T|
// | or User Segment Table Base Address |0 0|T|0| |I|0 0 0 0 0|E|
// +---------------------------------------+---+-+-+-+-+---------+-+
//
// Segment Descriptor
// 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
// +---------------------------------------+---+-+-+-+-+-----+-+-+-+
// | Page Table Base Address (PTBA) | |W|S|G|C| |W| |V|
// | |0 0|T|P| |I|0 0 0|P|0| |
// +---------------------------------------+---+-+-+-+-+-----+-+-+-+
//
// Page Descriptor
// 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
// +---------------------------------------+---+-+-+-+-+-+-+-+-+-+-+
// | Page Frame Address (PFA) | |W|S|G|C| |M|U|W| |V|
// | |0 0|T|P| |I|0| | |P|0| |
// +---------------------------------------+---+-+-+-+-+-+-+-+-+-+-+
//
// acc_stat も同じビット位置を使う。
// 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
// +---------------------------------------+---+-+-+-+-+-----+-+---+
// | | |W| |G|C| |W| |
// | |0 0|T|0| |I| 0 |P| 0 |
// +---------------------------------------+---+-+-+-+-+-----+-+---+
//
static const uint32 DESC_WT = 0x00000200; // Write Through
static const uint32 DESC_SP = 0x00000100; // Supervisor Protect
static const uint32 DESC_G = 0x00000080; // Global
static const uint32 DESC_CI = 0x00000040; // Cache Inhibit
static const uint32 DESC_M = 0x00000010; // Modified
static const uint32 DESC_U = 0x00000008; // Used
static const uint32 DESC_WP = 0x00000004; // Write Protect
static const uint32 DESC_V = 0x00000001; // Valid
private:
uint32 acc_laddr {}; // Logical Address
uint32 acc_paddr {}; // Physical Address
public:
// acc_stat は 4 ビットのみ使用。
// それ以外のビットは代入時にマスクすること。
static const uint32 ACC_STAT_MASK = DESC_WT | DESC_G | DESC_CI | DESC_WP;
uint32 acc_stat {};
// Table Address. とマニュアルには書いてあるけど、テーブル先頭と
// 紛らわしいし 88200 のアドレス変換ツリーは2段固定で、今何段目か
// しらんけど現在のテーブルアドレス…みたいなのを持つ必要はないので、
// ここでは
// sdaddr ... Segment Descriptor Address
// pdaddr ... Page Descriptor Address
// の2つに明確に分けて管理することにする。
uint32 acc_sdaddr {};
busaddr acc_pdaddr {};
bool acc_read {}; // True if read access
bool acc_IsWrite() const { return !acc_read; } // True if write access
// S/U 信号線
// 実際には P Bus の Address フェーズで毎回送られてくるが
// そうそう変わらないので状態変化を通知してもらう方式。
// acc_super は S か U のみ。
busaddr acc_super {};
void SetSuper(bool super);
bool IsSuper() const { return acc_super.IsSuper(); }
bool IsUser() const { return !IsSuper(); }
m88200PATC *acc_patc {}; // ヒットした PATC エントリ
uint32 tmp_desc {}; // TEMP_DESCR
//
// アドレス変換
//
bool Translate();
busaddr TranslatePeek(busaddr laddr) const;
private:
static std::string stat2str(uint32 stat);
bool SelectAreaDesc();
bool TableSearch();
bool FetchSegmentDesc();
bool FetchPageDesc();
bool UpdatePageDesc();
// 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<m88200BATC, 10> batc {};
// 検索用のハッシュ。値のビットN (0..9) が立っていれば batc[N] がこの
// ハッシュに当たることを示している (この後完全一致で比較する必要はある)。
// [0x00] => 0b00'0000'0000;
std::array<uint16, 16> batc_hash_s {};
std::array<uint16, 16> 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 InvalidatePATCHash(int);
std::array<m88200PATC, 56> patc {};
// 検索用のハッシュ。値のビット N (0..55) が立っていれば patc[N] がこの
// ハッシュに当たることを示している (この後完全一致で比較する必要はある)。
std::array<uint64, 256> patc_hash_s {};
std::array<uint64, 256> 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 {};
// 統計
uint64 translate_total {};
std::array<uint64, 10> batc_hit {};
uint64 patc_hit {};
uint64 atc_miss {};
#if defined(M88200_STAT)
// 開発用の統計
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 の総数
uint64 stat_patc_search {}; // ハッシュを引いた回数
uint64 stat_patc_miss1 {}; // ハッシュだけでミスした回数
uint64 stat_patc_miss2 {}; // ビットを調べてミスした回数
std::array<int, 8> stat_batc_hash_s {}; // BATC.S の衝突状況
std::array<int, 8> stat_batc_hash_u {}; // BATC.U の衝突状況
#endif
//
// 物理アドレスアクセス
//
busdata PhysRead(busaddr paddr, uint32 stat);
busdata PhysWrite(busaddr paddr, uint32 data, uint32 stat);
//
// キャッシュ
//
private:
std::array<m88200CacheSet,256> setarray {};
// キャッシュラインにメモリから読み込む
bool ReadLine(m88200CacheSet& set, uint line, uint32 tagaddr);
// キャッシュラインをメモリに書き出す
bool CopyBackLine(m88200CacheSet& set, uint line);
// キャッシュに対して paddr の読み込みを行う
busdata CacheRead(uint32 paddr);
// キャッシュに対して paddr への書き込みを行う
busdata CacheWrite(uint32 paddr, uint32 data, uint size);
busdata CacheWriteHit(m88200CacheSet& set, uint line,
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);
void MonitorCacheOverview(TextScreen& s, int y, bool is_gui) {
MonitorCacheOverview(s, y, -1, is_gui);
}
//
// MBus
//
public:
// MBus を所有している CMMU を返す。誰も持っていなければ NULL。
// これは static 関数
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 addr, bool im);
// バススヌープを行う (スレーブ側)
void Snoop(uint32 addr, bool im);
MainbusDevice *mainbus {};
// MBus を所有してる CMMU を指す。NULL なら解放。
// これは static 変数で全 m88200 で共有している
static m88200 *mbus_master;
// スヌープ相手の CMMU リスト
std::vector<m88200*> other_cmmu {};
};
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.