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