|
|
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.1.6 root 14: #include "monitor.h"
1.1 root 15: #include <array>
16:
1.1.1.8 root 17: class MPU88xx0Device;
18: class MainbusDevice;
1.1 root 19:
20: // SAPR, UAPR レジスタ
21: struct m88200APR
22: {
23: bool enable;
24: uint32 addr;
25: uint32 stat;
26: const char *name; // 自分の名前(ログ表示用)
27: };
28:
29: // BATC
30: struct m88200BATC
31: {
32: // LBA には S, V ビットを混ぜておく。比較を1回で済ませるため。
33: // V ビットは invalid なら %1 にして一致しなくしておく。
34: // 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
35: // +-------------------------+-------------------------+-+-------+--+
36: // | LBA | 0 |S| 0 |~V|
37: // +-------------------------+-------------------------+-+-------+--+
1.1.1.9 ! root 38: static const uint32 LBAMASK = 0xfff80000;
1.1.1.7 root 39: static const uint32 S = 0x00000020;
40: static const uint32 INVALID = 0x00000001;
41: uint32 lba; // LBA,S,~V
1.1 root 42: uint32 pba; // PBA
43: // stat は ACC_STAT_MASK と同じ WT,G,CI,WP のみ使用。
1.1.1.7 root 44: // BWP (BATC Write Port) のビット位置とは違うので注意。
1.1 root 45: uint32 stat;
46: bool wp; // WP (比較で使うのでこれだけ抜き出しておく)
1.1.1.7 root 47:
48: // このエントリが有効なら true を返す
49: bool IsValid() const { return (lba & INVALID) == 0; }
50: // S ビットが立っていれば true を返す
51: bool IsS() const { return (lba & S); }
1.1.1.9 ! root 52: // 論理アドレス(32ビット)を返す
! 53: uint32 Laddr() const { return (lba & LBAMASK); }
1.1 root 54: };
55:
56: // PATC
57: struct m88200PATC
58: {
1.1.1.7 root 59: // LPA には S, V ビットを混ぜておく。比較を1回で済ませるため。
1.1 root 60: // V ビットは invalid なら %1 にして一致しなくしておく。実際の
61: // PATC エントリの有効/無効は 46ビットの PATC 構造の外で管理されている?
62: // 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
63: // +---------------------------------------+-----------+-+-------+--+
1.1.1.7 root 64: // | LPA | 0 |S| 0 |~V|
1.1 root 65: // +---------------------------------------+-----------+-+-------+--+
1.1.1.9 ! root 66: static const uint32 LPAMASK = 0xfffff000;
1.1.1.7 root 67: static const uint32 S = 0x00000020;
68: static const uint32 INVALID = 0x00000001;
69: uint32 lpa; // LPA,S,~V
1.1 root 70: uint32 pfa; // PFA
71: uint32 stat; // ACC_STAT_MASK と同じ WT,G,CI,WP のみ使用。
72: bool m; // Modified
73: bool wp; // Write Protect (比較で使うのでこれだけ抜き出しておく)
1.1.1.7 root 74:
75: // このエントリが有効なら true を返す
76: bool IsValid() const { return (lpa & INVALID) == 0; }
77: // S ビットが立っていれば true を返す
78: bool IsS() const { return (lpa & S); }
1.1.1.9 ! root 79: // 論理アドレス(32ビット)を返す
! 80: uint32 Laddr() const { return (lpa & LPAMASK); }
1.1 root 81: };
82:
83: // キャッシュの1セット
84: class m88200CacheSet
85: {
86: public:
87: enum Status {
88: EU = 0, // Exclusive Unmodified
89: EM = 1, // Exclusive Modified
90: SU = 2, // Shared Unmodified
91: IV = 3, // Invalid
92: };
93:
94: //
95: // 3 2 1
96: // 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
97: // +---------------------------------------+---------------+----+---+
98: // | tag | set |Word| |
99: // +---------------------------------------+---------------+----+---+
100:
101: // タグはアドレスの上位 20ビット。
102: // ただし無効なラインかどうかのチェックも一度で済ませるために
103: // 無効(vv[]==IV)ならビット 0 を 1 にしておく。比較対象の paddr は
104: // 下位12ビットを落としているため、これで絶対に一致しなくなる。
105: static const uint32 TAG_INVALID = 0x00000001;
1.1.1.3 root 106: uint32 tag[4] {};
1.1 root 107:
108: // LRU
109: // CSSP の L ビットのロジックに従う。
110: int L {};
111:
112: // ステータス
1.1.1.3 root 113: Status vv[4] {};
1.1 root 114:
115: // データ。word[] は以下の順
116: // Word
117: // +0 +1 +2 +3
118: // line0 [ 0] [ 1] [ 2] [ 3]
119: // line1 [ 4] [ 5] [ 6] [ 7]
120: // :
1.1.1.3 root 121: uint32 word[16] {};
1.1 root 122:
123: // 自身のセットインデックス
1.1.1.3 root 124: uint32 setidx {};
1.1 root 125:
126: // 引数 L の状態から line を最新にしたらどうなるか、を返す。
127: // 表示処理で一時変数に対して処理が必要なため static 分離してある。
128: static int TryUseLine(int L, int line);
129:
130: // 引数 L の状態から line を最古にしたらどうなるか、を返す。
131: // 対称性のため static 分離してある。
132: static int TryUnuseLine(int L, int line);
133:
134: // 引数 L の状態で、最新の line を返す。
135: // 表示処理で一時変数に対して処理が必要なため static 分離してある。
136: static int TryGetOldestLine(int L);
137:
138: void Use(int line) {
139: L = TryUseLine(L, line);
140: }
141:
142: // 更新用に最も古いラインを選んで差し出す
143: int SelectOldestLine() const;
144:
145: void Update(int line, Status status);
146:
147: void Write(int line, uint32 paddr, uint32 data, int size);
148:
149: // キャッシュを検索して、ヒットした line を返す。
150: int Lookup(uint32 tagaddr) const;
151: };
152:
1.1.1.8 root 153: class m88200 : public Device
1.1 root 154: {
1.1.1.8 root 155: using inherited = Device;
1.1 root 156: public:
1.1.1.8 root 157: m88200(MPU88xx0Device *parent_, uint id_);
1.1 root 158: ~m88200() override;
159:
1.1.1.8 root 160: bool Init() override;
1.1 root 161:
1.1.1.8 root 162: // リセット (ResetHard() ではない)
1.1 root 163: void Reset();
164:
165: private:
1.1.1.6 root 166: DECLARE_MONITOR_CALLBACK(MonitorUpdateReg);
167: DECLARE_MONITOR_CALLBACK(MonitorUpdateATC);
168: DECLARE_MONITOR_CALLBACK(MonitorUpdateCache);
169:
1.1.1.8 root 170: MPU88xx0Device *parent {};
171:
172: // モニター
173: Monitor reg_monitor { this };
174: Monitor atc_monitor { this };
175: Monitor cache_monitor { this };
1.1 root 176:
177: public:
178: //
179: // レジスタ
180: //
181:
182: // IDR (ID Register) +$000
183: // 3 2 1
184: // 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
185: // +---------------+-----+---------+-------------------------------+
186: // | ID | Type| Version | reserved |
187: // +---------------+-----+---------+-------------------------------+
188: //
189: // ID はリセット時、下位7ビットはハードウェアで初期化、最上位ビットは
190: // 0 で初期化。その後は全ビット変更可能。
191: // Type は $5 = 88200、$6 = 88204。ここでは 88200 固定。
192: // Version は不明。
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;
218: void FlushCache();
219: void InvalidatePATC();
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: //
395: // XXX size をどうするか
1.1.1.9 ! root 396: busdata MBusRead(uint32 paddr, int size);
! 397: busdata MBusWrite(uint32 paddr, uint32 data, int size);
! 398: busdata MBusXmem(uint32 paddr, uint32 data, int size);
1.1 root 399:
400: //
401: // アクセス関数
402: //
403: private:
404: template <int bits> uint64 load(uint32 addr);
405: template <int bits> uint64 store(uint32 addr, uint32 data);
406: template <int bits> uint64 xmem(uint32 addr, uint32 data);
407: public:
408: uint64 load_8(uint32 addr);
409: uint64 load_16(uint32 addr);
410: uint64 load_32(uint32 addr);
411: uint64 store_8(uint32 addr, uint32 data);
412: uint64 store_16(uint32 addr, uint32 data);
413: uint64 store_32(uint32 addr, uint32 data);
414: uint64 xmem_8(uint32 addr, uint32 data);
415: uint64 xmem_16(uint32 addr, uint32 data);
416: uint64 xmem_32(uint32 addr, uint32 data);
417:
418: //
419: // 現在のアクセス中の状態。
420: //
421: // アドレス変換およびデータキャッシュルーチンではこれらの値を
422: // グローバルに状態変数として使う。
423:
424: // ディスクリプタの下位にあるフラグは全部ビット位置が同じ。
425: // Area descriptor (SAPR or UAPR)
426: // 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
427: // +---------------------------------------+---+-+-+-+-+---------+-+
428: // | Supervisor Segment Table Base Address | |W| |G|C| |T|
429: // | or User Segment Table Base Address |0 0|T|0| |I|0 0 0 0 0|E|
430: // +---------------------------------------+---+-+-+-+-+---------+-+
431: //
432: // Segment Descriptor
433: // 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
434: // +---------------------------------------+---+-+-+-+-+-----+-+-+-+
435: // | Page Table Base Address (PTBA) | |W|S|G|C| |W| |V|
436: // | |0 0|T|P| |I|0 0 0|P|0| |
437: // +---------------------------------------+---+-+-+-+-+-----+-+-+-+
438: //
439: // Page Descriptor
440: // 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
441: // +---------------------------------------+---+-+-+-+-+-+-+-+-+-+-+
442: // | Page Frame Address (PFA) | |W|S|G|C| |M|U|W| |V|
443: // | |0 0|T|P| |I|0| | |P|0| |
444: // +---------------------------------------+---+-+-+-+-+-+-+-+-+-+-+
445: //
446: // acc_stat も同じビット位置を使う。
447: // 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
448: // +---------------------------------------+---+-+-+-+-+-----+-+---+
449: // | | |W| |G|C| |W| |
450: // | |0 0|T|0| |I| 0 |P| 0 |
451: // +---------------------------------------+---+-+-+-+-+-----+-+---+
452: //
453: static const uint32 DESC_WT = 0x00000200; // Write Through
454: static const uint32 DESC_SP = 0x00000100; // Supervisor Protect
455: static const uint32 DESC_G = 0x00000080; // Global
456: static const uint32 DESC_CI = 0x00000040; // Cache Inhibit
457: static const uint32 DESC_M = 0x00000010; // Modified
458: static const uint32 DESC_U = 0x00000008; // Used
459: static const uint32 DESC_WP = 0x00000004; // Write Protect
460: static const uint32 DESC_V = 0x00000001; // Valid
461:
1.1.1.5 root 462: uint32 GetLaddr() const { return acc_laddr; }
463: uint32 GetPaddr() const { return acc_paddrH | acc_paddrL; }
464: private:
1.1 root 465: uint32 acc_laddr {}; // Logical Address
466: uint32 acc_paddrH {}; // Physical Address 上位30ビット。
467: // 下位2ビットは 0 固定。
468: uint32 acc_paddrL {}; // paddr の下位2ビット
469: // 上位30ビットは 0 固定。
470:
1.1.1.5 root 471: public:
1.1 root 472: // acc_stat は 4 ビットのみ使用。
473: // それ以外のビットは代入時にマスクすること。
474: static const uint32 ACC_STAT_MASK = DESC_WT | DESC_G | DESC_CI | DESC_WP;
475: uint32 acc_stat {};
476: // Table Address. とマニュアルには書いてあるけど、テーブル先頭と
477: // 紛らわしいし 88200 のアドレス変換ツリーは2段固定で、今何段目か
478: // しらんけど現在のテーブルアドレス…みたいなのを持つ必要はないので、
479: // ここでは
480: // sdaddr ... Segment Descriptor Address
481: // pdaddr ... Page Descriptor Address
482: // の2つに明確に分けて管理することにする。
483: uint32 acc_sdaddr {};
484: uint32 acc_pdaddr {};
1.1.1.3 root 485: bool acc_read {}; // True if read access
1.1 root 486: bool acc_IsWrite() const { return !acc_read; } // True if write access
487:
488: // S/U 信号線
489: // 実際には P Bus の Address フェーズで毎回送られてくるが
490: // そうそう変わらないので状態変化を通知してもらう方式。
1.1.1.9 ! root 491: // acc_super は S か U のみ。
! 492: busaddr acc_super {};
1.1.1.7 root 493: void SetSuper(bool super);
1.1.1.9 ! root 494: bool IsSuper() const { return acc_super.IsSuper(); }
! 495: bool IsUser() const { return !IsSuper(); }
1.1 root 496:
497: m88200PATC *acc_patc {}; // ヒットした PATC エントリ
1.1.1.3 root 498: uint32 tmp_desc {}; // TEMP_DESCR
1.1 root 499:
500: //
501: // アドレス変換
502: //
503: bool Translate();
1.1.1.9 ! root 504: busaddr TranslatePeek(busaddr laddr) const;
1.1 root 505: private:
506: static std::string stat2str(uint32 stat);
507: bool SelectAreaDesc();
508: bool TableSearch();
509: bool FetchSegmentDesc();
510: bool FetchPageDesc();
511: bool UpdatePageDesc();
512:
1.1.1.7 root 513: // BATC
514: static const uint32 BATC_LBA_MASK = BWP_LBA_MASK;
515: static const uint32 BATC_S = m88200BATC::S;
516: static const uint32 BATC_INVALID = m88200BATC::INVALID;
517: std::array<m88200BATC, 10> batc {};
518:
1.1 root 519: // PATC
1.1.1.7 root 520: static const uint32 PATC_S = m88200PATC::S;
521: static const uint32 PATC_INVALID = m88200PATC::INVALID;
522: void CreatePATCEntry();
1.1.1.9 ! root 523: void InvalidatePATCEntry(m88200PATC&);
1.1 root 524: std::array<m88200PATC, 56> patc {};
1.1.1.7 root 525: // 次回追加する位置
526: int patc_next {};
527:
1.1.1.9 ! root 528: // BATC/PATC 混合のハッシュ。
! 529: // 1エントリが 4KB の1ページを示し、4GB のメモリ空間全体あるので
! 530: // 1M 個 (x User/Supervisor で2倍)。
! 531: // 各エントリは1バイトで、内容は以下の通り。
! 532: // 0: BATC/PATC なし
! 533: // 0xff-0xf6: BATC #(~n)
! 534: // 1-56: PATC #(n-1)
! 535: // BATC は重複して設定することも可能だが、してはいけないとマニュアルに
! 536: // 書いてあるので、ここでも動作不定でよいことにする。
! 537: // 前半 (0x00'0000..0x0f'ffff) が User モード用、
! 538: // 後半 (0x10'0000..0x1f'ffff) が Supervisor モード用。
! 539: inline uint32 addr2hash(bool issuper, uint32 addr) const;
! 540: void DumpATC();
! 541: std::array<uint8, 0x200000> atc_hash_all {};
! 542: // 現在の特権状態によって atc_hash_all の [0] か [0x10'0000] を指す。
! 543: uint8 *atc_hash {};
! 544:
1.1.1.7 root 545: // 統計
546: uint64 translate_total {};
547: std::array<uint64, 10> batc_hit {};
548: uint64 patc_hit {};
549: uint64 atc_miss {};
1.1.1.9 ! root 550: #define M88200_STAT
1.1.1.7 root 551: #if defined(M88200_STAT)
552: // 開発用の統計
553: uint64 stat_patc_create {}; // エントリ作成回数
554: uint64 stat_patc_invcmd_all {}; // Invalidate ALL 発行回数
555: uint64 stat_patc_invcmd_seg {}; // Invalidate Segment 発行回数
556: uint64 stat_patc_invcmd_page {}; // Invalidate Page 発行回数
557: uint64 stat_patc_invalidate {}; // 無効にした PATC の総数
558: #endif
1.1 root 559:
560: //
561: // キャッシュ
562: //
1.1.1.3 root 563: private:
1.1 root 564: std::array<m88200CacheSet,256> setarray {};
1.1.1.3 root 565: // キャッシュラインにメモリから読み込む
566: uint64 ReadLine(m88200CacheSet& set, int line, uint32 tagaddr);
567: // キャッシュラインをメモリに書き出す
568: uint64 CopyBackLine(m88200CacheSet& set, int line);
1.1 root 569:
1.1.1.3 root 570: public:
1.1 root 571: // キャッシュに対して paddr の読み込みを行う
572: uint64 CacheRead(uint32 paddr);
573: // キャッシュに対して paddr への書き込みを行う
574: uint64 CacheWrite(uint32 paddr, uint32 data, int size);
575: uint64 CacheWriteHit(m88200CacheSet& set, int line,
576: uint32 paddr, uint32 data, int size);
577: uint64 CacheXmem(uint32 paddr, uint32 data, int size);
578:
579: // モニタスクリーン作成用
580: void MonitorCacheSet(TextScreen&, int y, int setidx);
581: void MonitorCacheOverview(TextScreen&, int y, int cursor, bool is_gui);
582: void MonitorCacheOverview(TextScreen& s, int y, bool is_gui) {
583: MonitorCacheOverview(s, y, -1, is_gui);
584: }
585:
1.1.1.3 root 586: //
587: // MBus
588: //
589: public:
1.1.1.7 root 590: // MBus を所有している CMMU を返す。誰も持っていなければ NULL。
1.1.1.3 root 591: // これは static 関数
592: static m88200 *GetBusMaster() { return mbus_master; }
593:
1.1 root 594: private:
1.1.1.3 root 595: void MBusAcquire();
1.1 root 596: void MBusRelease() { }
1.1.1.7 root 597: // 他 CMMU にスヌープさせる (バスマスタ側)
598: void MBusMakeSnoop(uint32, int);
599: // バススヌープを行う (スレーブ側)
600: void Snoop(uint32, int);
1.1.1.3 root 601:
1.1.1.8 root 602: MainbusDevice *mainbus {};
603:
1.1.1.3 root 604: // MBus を所有してる CMMU を指す。NULL なら解放。
605: // これは static 変数で全 m88200 で共有している
606: static m88200 *mbus_master;
1.1.1.7 root 607:
608: // スヌープ相手の CMMU リスト
609: std::vector<m88200*> other_cmmu {};
1.1 root 610: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.