|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: // MC88200(CMMU)
8:
9: #pragma once
10:
1.1.1.8 root 11: #include "device.h"
1.1.1.9 root 12: #include "bus.h"
1.1.1.8 root 13: #include "mainbus.h"
1.1 root 14: #include <array>
15:
1.1.1.12 root 16: #define M88200_STAT
17:
1.1.1.8 root 18: class MPU88xx0Device;
19: class MainbusDevice;
1.1 root 20:
21: // SAPR, UAPR レジスタ
22: struct m88200APR
23: {
24: bool enable;
25: uint32 addr;
1.1.1.12 root 26: // stat は ACC_STAT_MASK と同じ位置の WT,G,CI のみ使用。APR に WP はない。
1.1 root 27: uint32 stat;
28: const char *name; // 自分の名前(ログ表示用)
29: };
30:
31: // BATC
32: struct m88200BATC
33: {
34: // LBA には S, V ビットを混ぜておく。比較を1回で済ませるため。
35: // V ビットは invalid なら %1 にして一致しなくしておく。
36: // 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
37: // +-------------------------+-------------------------+-+-------+--+
38: // | LBA | 0 |S| 0 |~V|
39: // +-------------------------+-------------------------+-+-------+--+
1.1.1.9 root 40: static const uint32 LBAMASK = 0xfff80000;
1.1.1.7 root 41: static const uint32 S = 0x00000020;
42: static const uint32 INVALID = 0x00000001;
43: uint32 lba; // LBA,S,~V
1.1 root 44: uint32 pba; // PBA
45: // stat は ACC_STAT_MASK と同じ WT,G,CI,WP のみ使用。
1.1.1.7 root 46: // BWP (BATC Write Port) のビット位置とは違うので注意。
1.1 root 47: uint32 stat;
48: bool wp; // WP (比較で使うのでこれだけ抜き出しておく)
1.1.1.7 root 49:
50: // このエントリが有効なら true を返す
51: bool IsValid() const { return (lba & INVALID) == 0; }
52: // S ビットが立っていれば true を返す
53: bool IsS() const { return (lba & S); }
1.1.1.9 root 54: // 論理アドレス(32ビット)を返す
55: uint32 Laddr() const { return (lba & LBAMASK); }
1.1 root 56: };
57:
58: // PATC
59: struct m88200PATC
60: {
1.1.1.7 root 61: // LPA には S, V ビットを混ぜておく。比較を1回で済ませるため。
1.1 root 62: // V ビットは invalid なら %1 にして一致しなくしておく。実際の
63: // PATC エントリの有効/無効は 46ビットの PATC 構造の外で管理されている?
64: // 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
65: // +---------------------------------------+-----------+-+-------+--+
1.1.1.7 root 66: // | LPA | 0 |S| 0 |~V|
1.1 root 67: // +---------------------------------------+-----------+-+-------+--+
1.1.1.9 root 68: static const uint32 LPAMASK = 0xfffff000;
1.1.1.7 root 69: static const uint32 S = 0x00000020;
70: static const uint32 INVALID = 0x00000001;
71: uint32 lpa; // LPA,S,~V
1.1 root 72: uint32 pfa; // PFA
73: uint32 stat; // ACC_STAT_MASK と同じ WT,G,CI,WP のみ使用。
74: bool m; // Modified
75: bool wp; // Write Protect (比較で使うのでこれだけ抜き出しておく)
1.1.1.7 root 76:
77: // このエントリが有効なら true を返す
78: bool IsValid() const { return (lpa & INVALID) == 0; }
79: // S ビットが立っていれば true を返す
80: bool IsS() const { return (lpa & S); }
1.1.1.9 root 81: // 論理アドレス(32ビット)を返す
82: uint32 Laddr() const { return (lpa & LPAMASK); }
1.1 root 83: };
84:
85: // キャッシュの1セット
86: class m88200CacheSet
87: {
88: public:
89: enum Status {
90: EU = 0, // Exclusive Unmodified
91: EM = 1, // Exclusive Modified
92: SU = 2, // Shared Unmodified
93: IV = 3, // Invalid
94: };
95:
96: // 3 2 1
1.1.1.12 root 97: // 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
98: // +---------------------------------------+---------------+----+-+--+
99: // | tag | set |word|0|~V|
100: // +---------------------------------------+---------------+----+-+--+
1.1 root 101:
102: // タグはアドレスの上位 20ビット。
103: // ただし無効なラインかどうかのチェックも一度で済ませるために
104: // 無効(vv[]==IV)ならビット 0 を 1 にしておく。比較対象の paddr は
105: // 下位12ビットを落としているため、これで絶対に一致しなくなる。
106: static const uint32 TAG_INVALID = 0x00000001;
1.1.1.3 root 107: uint32 tag[4] {};
1.1 root 108:
109: // LRU
110: // CSSP の L ビットのロジックに従う。
1.1.1.12 root 111: uint L {};
1.1 root 112:
113: // ステータス
1.1.1.3 root 114: Status vv[4] {};
1.1 root 115:
116: // データ。word[] は以下の順
117: // Word
118: // +0 +1 +2 +3
119: // line0 [ 0] [ 1] [ 2] [ 3]
120: // line1 [ 4] [ 5] [ 6] [ 7]
121: // :
1.1.1.3 root 122: uint32 word[16] {};
1.1 root 123:
124: // 自身のセットインデックス
1.1.1.3 root 125: uint32 setidx {};
1.1 root 126:
127: // 引数 L の状態から line を最新にしたらどうなるか、を返す。
128: // 表示処理で一時変数に対して処理が必要なため static 分離してある。
1.1.1.12 root 129: static uint TryUseLine(uint tmpL, int line);
1.1 root 130:
131: // 引数 L の状態から line を最古にしたらどうなるか、を返す。
132: // 対称性のため static 分離してある。
1.1.1.12 root 133: static uint TryUnuseLine(uint tmpL, int line);
1.1 root 134:
135: // 引数 L の状態で、最新の line を返す。
136: // 表示処理で一時変数に対して処理が必要なため static 分離してある。
1.1.1.12 root 137: static int TryGetOldestLine(uint tmpL);
1.1 root 138:
139: void Use(int line) {
140: L = TryUseLine(L, line);
141: }
142:
143: // 更新用に最も古いラインを選んで差し出す
144: int SelectOldestLine() const;
145:
1.1.1.10 root 146: void Update(uint line, Status status);
1.1 root 147:
1.1.1.10 root 148: void Write(uint line, uint32 paddr, uint32 data, uint size);
1.1 root 149:
150: // キャッシュを検索して、ヒットした line を返す。
151: int Lookup(uint32 tagaddr) const;
152: };
153:
1.1.1.8 root 154: class m88200 : public Device
1.1 root 155: {
1.1.1.8 root 156: using inherited = Device;
1.1 root 157: public:
1.1.1.8 root 158: m88200(MPU88xx0Device *parent_, uint id_);
1.1 root 159: ~m88200() override;
160:
1.1.1.8 root 161: bool Init() override;
1.1 root 162:
1.1.1.8 root 163: // リセット (ResetHard() ではない)
1.1 root 164: void Reset();
165:
166: private:
1.1.1.13! root 167: DECLARE_MONITOR_SCREEN(MonitorScreenReg);
! 168: DECLARE_MONITOR_SCREEN(MonitorScreenATC);
! 169: DECLARE_MONITOR_SCREEN(MonitorScreenCache);
1.1.1.6 root 170:
1.1.1.8 root 171: MPU88xx0Device *parent {};
172:
173: // モニター
1.1.1.11 root 174: Monitor *reg_monitor {};
175: Monitor *atc_monitor {};
176: Monitor *cache_monitor {};
1.1 root 177:
178: public:
179: //
180: // レジスタ
181: //
182:
183: // IDR (ID Register) +$000
184: // 3 2 1
185: // 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
186: // +---------------+-----+---------+-------------------------------+
187: // | ID | Type| Version | reserved |
188: // +---------------+-----+---------+-------------------------------+
189: //
190: // ID はリセット時、下位7ビットはハードウェアで初期化、最上位ビットは
191: // 0 で初期化。その後は全ビット変更可能。
192: // Type は $5 = 88200、$6 = 88204。ここでは 88200 固定。
1.1.1.3 root 193: uint32 id {};
194: uint32 version {};
1.1 root 195:
196: // IDR レジスタの内容を返す
197: uint32 GetIDR() const {
1.1.1.8 root 198: return (id << 24) | (0x5 << 21) | (version << 16);
1.1 root 199: }
200: // Version フィールドを設定する
201: void SetVersion(uint version_);
202:
203: // SCR (System Command Register) +$004
204: // 3 2 1
205: // 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
206: // +---------------------------------------------------+-----------+
207: // | reserved |CommandCode|
208: // +---------------------------------------------------+-----------+
1.1.1.3 root 209: uint32 command {};
1.1 root 210: uint32 GetSCR() const;
211: void SetSCR(uint32 val);
212: private:
213: static const char * const commandname[];
214: static const uint32 GG_LINE = 0;
215: static const uint32 GG_PAGE = 1;
216: static const uint32 GG_SEG = 2;
217: static const uint32 GG_ALL = 3;
1.1.1.12 root 218: void FlushCacheCmd();
219: void InvalidatePATCCmd();
1.1 root 220:
221: public:
222: // SSR (System Status Register) +$008
223: // 3 2 1
224: // 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
225: // +---------------------------------------------------------------+
226: // | |C|B| |W|S|G|C| |M|U|W|B|V|
227: // | reserved |E|E| res |T|P| |I|r| | |P|H| |
228: // +---------------------------------------------------------------+
229: static const uint32 SSR_CE = 0x00008000; // Copyback Error
230: static const uint32 SSR_BE = 0x00004000; // Bus Error
231: static const uint32 SSR_WT = 0x00000200; // WriteThrough
232: static const uint32 SSR_SP = 0x00000100; // Supervisor Privilege
233: static const uint32 SSR_G = 0x00000080; // Global
234: static const uint32 SSR_CI = 0x00000040; // Cache Inhibit
235: static const uint32 SSR_M = 0x00000010; // Modified
236: static const uint32 SSR_U = 0x00000008; // Used
237: static const uint32 SSR_WP = 0x00000004; // Write Protection
238: static const uint32 SSR_BH = 0x00000002; // BATC Hit
239: static const uint32 SSR_V = 0x00000001; // Valid
1.1.1.3 root 240: uint32 ssr {};
1.1 root 241: uint32 GetSSR() const { return ssr; }
242: void SetSSR(uint32 val) { ssr = val; }
243:
244: // SAR (System Address Register) +$00c
245: // 3 2 1
246: // 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
247: // +---------------------------------------------------------------+
248: // | Address |
249: // +---------------------------------------------------------------+
1.1.1.3 root 250: uint32 sar {};
1.1 root 251: uint32 GetSAR() const { return sar; }
252: void SetSAR(uint32 val) { sar = val; }
253:
254: // SCTR (System Control Register) +$104
255: // 3 2 1
256: // 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
257: // +-------------------------------+-+-+-+-------------------------+
258: // | |P|S|P| |
259: // | reserved |E|E|R| reserved |
260: // +-------------------------------+-+-+-+-------------------------+
261: static const uint32 SCTR_PE = 0x00008000; // Parity Enable
262: static const uint32 SCTR_SE = 0x00004000; // Snoop Enable
263: static const uint32 SCTR_PR = 0x00002000; // Priority Arbitration
1.1.1.3 root 264: uint32 sctr {};
1.1 root 265: uint32 GetSCTR() const { return sctr; }
266: void SetSCTR(uint32 val);
267:
268: // SAPR (Supervisor Area Pointer Register) +$200
269: // UAPR (User Area Pointer Register) +$204
270: // 3 2 1
271: // 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
272: // +---------------------------------------+---+-+-+-+-+---------+-+
273: // | Supervisor Segment Table Base Address | |W| |G|C| |T|
274: // | or User Segment Table Base Address |0 0|T|0| |I|0 0 0 0 0|E|
275: // +---------------------------------------+---+-+-+-+-+---------+-+
276: static const uint32 APR_ADDR_MASK = 0xfffff000; // Base Address
277: static const uint32 APR_WT = 0x00000200; // WriteThrough
278: static const uint32 APR_G = 0x00000080; // Global
279: static const uint32 APR_CI = 0x00000040; // Cache Inhibit
280: static const uint32 APR_TE = 0x00000001; // Translation Enable
281: m88200APR uapr {};
282: m88200APR sapr {};
283: private:
284: uint32 GetAPR(const m88200APR&) const;
285: void SetAPR(m88200APR&, uint32 data);
1.1.1.7 root 286: // 現在の xAPR
287: const m88200APR *acc_apr {};
1.1 root 288: public:
289: uint32 GetAPR(uint issuper) const;
290: uint32 GetUAPR() const { return GetAPR(uapr); }
291: uint32 GetSAPR() const { return GetAPR(sapr); }
292: void SetUAPR(uint32 data) { SetAPR(uapr, data); }
293: void SetSAPR(uint32 data) { SetAPR(sapr, data); }
294:
295: // PFSR (P Bus Fault Status Register) +$108
296: // 3 2 1
297: // 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
298: // +-------------------------+-----+-------------------------------+
299: // | |Fault| |
300: // | reserved | Code| reserved |
301: // +-------------------------+-----+-------------------------------+
302: static const uint32 FAULT_CODE_SUCCESS = 0; // Success (No fault)
303: static const uint32 FAULT_CODE_BUSERR = 3; // Bus Error
304: static const uint32 FAULT_CODE_SEGMENT = 4; // Segment Fault
305: static const uint32 FAULT_CODE_PAGE = 5; // Page Fault
306: static const uint32 FAULT_CODE_SUPERVISOR = 6; // Supervisor Violation
307: static const uint32 FAULT_CODE_WRITE = 7; // Write Violation
1.1.1.3 root 308: uint32 fault_code {};
1.1 root 309: uint32 GetPFSR() const {
310: return fault_code << 16;
311: }
312: void SetPFSR(uint32 data) {
313: fault_code = (data >> 16) & 7;
314: }
315:
316: // PFAR (P Bus Fault Address Register) +$10c
317: // 3 2 1
318: // 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
319: // +---------------------------------------------------------------+
320: // | Address |
321: // +---------------------------------------------------------------+
1.1.1.3 root 322: uint32 fault_addr {};
1.1 root 323: uint32 GetPFAR() const { return fault_addr; }
324: void SetPFAR(uint32 val) { fault_addr = val; }
325:
1.1.1.9 root 326: void SetFault(uint32 code_, uint32 addr_) {
327: fault_code = code_;
328: fault_addr = addr_;
329: }
330:
1.1 root 331: // BWP0-7 (BATC Write Ports 0..7) +$400..+$41c
332: // 3 2 1
333: // 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
334: // +---------------------------------------------------------------+
335: // | | |S|W|G|C|W|V|
336: // | Logical Block Address | Physical Block Address | |T| |I|P| |
337: // +---------------------------------------------------------------+
1.1.1.7 root 338: static const uint32 BWP_LBA_MASK = 0xfff80000;
339: static const uint32 BWP_PBA_MASK = 0x0007ffc0;
1.1.1.9 root 340: static const uint32 BWP_FLAG_MASK = 0x0000003f;
1.1.1.7 root 341: static const uint32 BWP_S = 0x00000020; // Address Space
342: static const uint32 BWP_WT = 0x00000010; // WriteThrough
343: static const uint32 BWP_G = 0x00000008; // Global
344: static const uint32 BWP_CI = 0x00000004; // Cache Inhibit
345: static const uint32 BWP_WP = 0x00000002; // Write Protect
346: static const uint32 BWP_V = 0x00000001; // Valid
347: void SetBWP(uint n, uint32 val);
1.1.1.9 root 348: void SetBATC(uint n, uint32 laddr, uint32 paddr, uint32 flags);
1.1 root 349:
350: // CDP0-3 (Cache Data Ports 0..3) +$800..+$80c
351: // 3 2 1
352: // 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
353: // +---------------------------------------------------------------+
354: // | Data Word |
355: // +---------------------------------------------------------------+
356:
357: // CTP0-3 (Cache Tag Ports 0..3) +$840..+$84c
358: // 3 2 1
359: // 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
360: // +---------------------------------------+-----------------------+
361: // | Physical Address | reserved |
362: // +---------------------------------------+-----------------------+
363:
364: // CSSP (Cache Set Status Port) +$880
365: // 3 2 1
366: // 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
367: // +---------------------------------------------------------------+
368: // | |L|L|L|L|L|L|D|D|D|D|VV3|VV2|VV1|VV0| |
369: // |res|5|4|3|2|1|0|3|2|1|0| | | | | reserved |
370: // +---------------------------------------------------------------+
371: static const uint32 CSSP_L5 = 0x20000000; // Line5
372: static const uint32 CSSP_L4 = 0x10000000; // Line4
373: static const uint32 CSSP_L3 = 0x08000000; // Line3
374: static const uint32 CSSP_L2 = 0x04000000; // Line2
375: static const uint32 CSSP_L1 = 0x02000000; // Line1
376: static const uint32 CSSP_L0 = 0x01000000; // Line0
377: static const uint32 CSSP_D3 = 0x00800000; // Line Disable
378: static const uint32 CSSP_D2 = 0x00400000; // Line Disable
379: static const uint32 CSSP_D1 = 0x00200000; // Line Disable
380: static const uint32 CSSP_D0 = 0x00100000; // Line Disable
381: static const uint32 CSSP_VV3 = 0x000c0000; // Line Valid
382: static const uint32 CSSP_VV2 = 0x00030000; // Line Valid
383: static const uint32 CSSP_VV1 = 0x0000c000; // Line Valid
384: static const uint32 CSSP_VV0 = 0x00003000; // Line Valid
385: static const uint32 CSSP_VV3_OFFSET = 18;
386: static const uint32 CSSP_VV2_OFFSET = 16;
387: static const uint32 CSSP_VV1_OFFSET = 14;
388: static const uint32 CSSP_VV0_OFFSET = 12;
389: uint32 GetCSSP() const;
390: void SetCSSP(uint32 val);
391:
392: //
393: // 物理バスアクセス
394: //
1.1.1.12 root 395: busdata MBusRead(busaddr paddr);
396: busdata MBusWrite(busaddr paddr, uint32 data);
397: busdata MBusXmem(busaddr paddr, uint32 data);
1.1 root 398:
399: //
400: // アクセス関数
401: //
402: private:
1.1.1.12 root 403: template <uint size> busdata load(uint32 addr);
404: template <uint size> busdata store(uint32 addr, uint32 data);
405: template <uint size> busdata xmem(uint32 addr, uint32 data);
1.1 root 406: public:
1.1.1.12 root 407: busdata load_1(uint32 addr);
408: busdata load_2(uint32 addr);
409: busdata load_4(uint32 addr);
410: busdata store_1(uint32 addr, uint32 data);
411: busdata store_2(uint32 addr, uint32 data);
412: busdata store_4(uint32 addr, uint32 data);
413: busdata xmem_1(uint32 addr, uint32 data);
414: busdata xmem_4(uint32 addr, uint32 data);
1.1 root 415:
416: //
417: // 現在のアクセス中の状態。
418: //
419: // アドレス変換およびデータキャッシュルーチンではこれらの値を
420: // グローバルに状態変数として使う。
421:
422: // ディスクリプタの下位にあるフラグは全部ビット位置が同じ。
423: // Area descriptor (SAPR or UAPR)
424: // 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
425: // +---------------------------------------+---+-+-+-+-+---------+-+
426: // | Supervisor Segment Table Base Address | |W| |G|C| |T|
427: // | or User Segment Table Base Address |0 0|T|0| |I|0 0 0 0 0|E|
428: // +---------------------------------------+---+-+-+-+-+---------+-+
429: //
430: // Segment Descriptor
431: // 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
432: // +---------------------------------------+---+-+-+-+-+-----+-+-+-+
433: // | Page Table Base Address (PTBA) | |W|S|G|C| |W| |V|
434: // | |0 0|T|P| |I|0 0 0|P|0| |
435: // +---------------------------------------+---+-+-+-+-+-----+-+-+-+
436: //
437: // Page Descriptor
438: // 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
439: // +---------------------------------------+---+-+-+-+-+-+-+-+-+-+-+
440: // | Page Frame Address (PFA) | |W|S|G|C| |M|U|W| |V|
441: // | |0 0|T|P| |I|0| | |P|0| |
442: // +---------------------------------------+---+-+-+-+-+-+-+-+-+-+-+
443: //
444: // acc_stat も同じビット位置を使う。
445: // 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
446: // +---------------------------------------+---+-+-+-+-+-----+-+---+
447: // | | |W| |G|C| |W| |
448: // | |0 0|T|0| |I| 0 |P| 0 |
449: // +---------------------------------------+---+-+-+-+-+-----+-+---+
450: //
451: static const uint32 DESC_WT = 0x00000200; // Write Through
452: static const uint32 DESC_SP = 0x00000100; // Supervisor Protect
453: static const uint32 DESC_G = 0x00000080; // Global
454: static const uint32 DESC_CI = 0x00000040; // Cache Inhibit
455: static const uint32 DESC_M = 0x00000010; // Modified
456: static const uint32 DESC_U = 0x00000008; // Used
457: static const uint32 DESC_WP = 0x00000004; // Write Protect
458: static const uint32 DESC_V = 0x00000001; // Valid
459:
1.1.1.5 root 460: private:
1.1 root 461: uint32 acc_laddr {}; // Logical Address
1.1.1.12 root 462: uint32 acc_paddr {}; // Physical Address
1.1 root 463:
1.1.1.5 root 464: public:
1.1 root 465: // acc_stat は 4 ビットのみ使用。
466: // それ以外のビットは代入時にマスクすること。
467: static const uint32 ACC_STAT_MASK = DESC_WT | DESC_G | DESC_CI | DESC_WP;
468: uint32 acc_stat {};
469: // Table Address. とマニュアルには書いてあるけど、テーブル先頭と
470: // 紛らわしいし 88200 のアドレス変換ツリーは2段固定で、今何段目か
471: // しらんけど現在のテーブルアドレス…みたいなのを持つ必要はないので、
472: // ここでは
473: // sdaddr ... Segment Descriptor Address
474: // pdaddr ... Page Descriptor Address
475: // の2つに明確に分けて管理することにする。
476: uint32 acc_sdaddr {};
1.1.1.12 root 477: busaddr acc_pdaddr {};
1.1.1.3 root 478: bool acc_read {}; // True if read access
1.1 root 479: bool acc_IsWrite() const { return !acc_read; } // True if write access
480:
481: // S/U 信号線
482: // 実際には P Bus の Address フェーズで毎回送られてくるが
483: // そうそう変わらないので状態変化を通知してもらう方式。
1.1.1.9 root 484: // acc_super は S か U のみ。
485: busaddr acc_super {};
1.1.1.7 root 486: void SetSuper(bool super);
1.1.1.9 root 487: bool IsSuper() const { return acc_super.IsSuper(); }
488: bool IsUser() const { return !IsSuper(); }
1.1 root 489:
490: m88200PATC *acc_patc {}; // ヒットした PATC エントリ
1.1.1.3 root 491: uint32 tmp_desc {}; // TEMP_DESCR
1.1 root 492:
493: //
494: // アドレス変換
495: //
496: bool Translate();
1.1.1.9 root 497: busaddr TranslatePeek(busaddr laddr) const;
1.1 root 498: private:
499: static std::string stat2str(uint32 stat);
500: bool SelectAreaDesc();
501: bool TableSearch();
502: bool FetchSegmentDesc();
503: bool FetchPageDesc();
504: bool UpdatePageDesc();
505:
1.1.1.7 root 506: // BATC
507: static const uint32 BATC_LBA_MASK = BWP_LBA_MASK;
508: static const uint32 BATC_S = m88200BATC::S;
509: static const uint32 BATC_INVALID = m88200BATC::INVALID;
1.1.1.12 root 510: void MakeBATCHash();
1.1.1.7 root 511: std::array<m88200BATC, 10> batc {};
1.1.1.12 root 512: // 検索用のハッシュ。値のビットN (0..9) が立っていれば batc[N] がこの
513: // ハッシュに当たることを示している (この後完全一致で比較する必要はある)。
514: // [0x00] => 0b00'0000'0000;
515: std::array<uint16, 16> batc_hash_s {};
516: std::array<uint16, 16> batc_hash_u {};
517: // 現在の特権状態によって batc_hash_{s,u} のいずれかを指す。
518: uint16 *batc_hash {};
519: static int batc_hash_func(uint32 a) {
520: return (a >> 19) & 0x0f;
521: }
1.1.1.7 root 522:
1.1 root 523: // PATC
1.1.1.7 root 524: static const uint32 PATC_S = m88200PATC::S;
525: static const uint32 PATC_INVALID = m88200PATC::INVALID;
526: void CreatePATCEntry();
1.1.1.12 root 527: void InvalidatePATCHash(int);
1.1 root 528: std::array<m88200PATC, 56> patc {};
1.1.1.12 root 529: // 検索用のハッシュ。値のビット N (0..55) が立っていれば patc[N] がこの
530: // ハッシュに当たることを示している (この後完全一致で比較する必要はある)。
531: std::array<uint64, 256> patc_hash_s {};
532: std::array<uint64, 256> patc_hash_u {};
533: // 現在の特権状態によって patc_hash_{s,u} のいずれかを指す。
534: uint64 *patc_hash {};
535: static int patc_hash_func(uint32 a) {
536: return (a >> 12) & 0xff;
537: }
538: // 空きエントリ。patc[N] が空いていればビット N を立てる。
539: uint64 patc_free {};
540: // 次回追加する位置。
1.1.1.7 root 541: int patc_next {};
542:
543: // 統計
544: uint64 translate_total {};
545: std::array<uint64, 10> batc_hit {};
546: uint64 patc_hit {};
547: uint64 atc_miss {};
548: #if defined(M88200_STAT)
549: // 開発用の統計
550: uint64 stat_patc_create {}; // エントリ作成回数
551: uint64 stat_patc_invcmd_all {}; // Invalidate ALL 発行回数
552: uint64 stat_patc_invcmd_seg {}; // Invalidate Segment 発行回数
553: uint64 stat_patc_invcmd_page {}; // Invalidate Page 発行回数
554: uint64 stat_patc_invalidate {}; // 無効にした PATC の総数
1.1.1.12 root 555: uint64 stat_patc_search {}; // ハッシュを引いた回数
556: uint64 stat_patc_miss1 {}; // ハッシュだけでミスした回数
557: uint64 stat_patc_miss2 {}; // ビットを調べてミスした回数
558: std::array<int, 8> stat_batc_hash_s {}; // BATC.S の衝突状況
559: std::array<int, 8> stat_batc_hash_u {}; // BATC.U の衝突状況
1.1.1.7 root 560: #endif
1.1 root 561:
562: //
1.1.1.12 root 563: // 物理アドレスアクセス
564: //
565: busdata PhysRead(busaddr paddr, uint32 stat);
566: busdata PhysWrite(busaddr paddr, uint32 data, uint32 stat);
567:
568: //
1.1 root 569: // キャッシュ
570: //
1.1.1.3 root 571: private:
1.1 root 572: std::array<m88200CacheSet,256> setarray {};
1.1.1.3 root 573: // キャッシュラインにメモリから読み込む
1.1.1.12 root 574: bool ReadLine(m88200CacheSet& set, uint line, uint32 tagaddr);
1.1.1.3 root 575: // キャッシュラインをメモリに書き出す
1.1.1.12 root 576: bool CopyBackLine(m88200CacheSet& set, uint line);
1.1 root 577:
578: // キャッシュに対して paddr の読み込みを行う
1.1.1.12 root 579: busdata CacheRead(uint32 paddr);
1.1 root 580: // キャッシュに対して paddr への書き込みを行う
1.1.1.12 root 581: busdata CacheWrite(uint32 paddr, uint32 data, uint size);
582: busdata CacheWriteHit(m88200CacheSet& set, uint line,
1.1.1.10 root 583: uint32 paddr, uint32 data, uint size);
1.1.1.12 root 584: busdata CacheXmem(uint32 paddr, uint32 data, uint size);
1.1 root 585:
1.1.1.12 root 586: public:
1.1 root 587: // モニタスクリーン作成用
1.1.1.10 root 588: void MonitorCacheSet(TextScreen&, int y, uint setidx);
589: void MonitorCacheOverview(TextScreen&, int y, uint cursor, bool is_gui);
1.1 root 590: void MonitorCacheOverview(TextScreen& s, int y, bool is_gui) {
591: MonitorCacheOverview(s, y, -1, is_gui);
592: }
593:
1.1.1.3 root 594: //
595: // MBus
596: //
597: public:
1.1.1.7 root 598: // MBus を所有している CMMU を返す。誰も持っていなければ NULL。
1.1.1.3 root 599: // これは static 関数
600: static m88200 *GetBusMaster() { return mbus_master; }
601:
1.1 root 602: private:
1.1.1.12 root 603: static constexpr bool IM_0 = false;
604: static constexpr bool IM_1 = true;
1.1.1.3 root 605: void MBusAcquire();
1.1 root 606: void MBusRelease() { }
1.1.1.7 root 607: // 他 CMMU にスヌープさせる (バスマスタ側)
1.1.1.12 root 608: void MBusMakeSnoop(uint32 addr, bool im);
1.1.1.7 root 609: // バススヌープを行う (スレーブ側)
1.1.1.12 root 610: void Snoop(uint32 addr, bool im);
1.1.1.3 root 611:
1.1.1.8 root 612: MainbusDevice *mainbus {};
613:
1.1.1.3 root 614: // MBus を所有してる CMMU を指す。NULL なら解放。
615: // これは static 変数で全 m88200 で共有している
616: static m88200 *mbus_master;
1.1.1.7 root 617:
618: // スヌープ相手の CMMU リスト
619: std::vector<m88200*> other_cmmu {};
1.1 root 620: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.