|
|
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:
11: #include "bus.h"
12: #include <array>
13:
14: class m88kcpu;
15:
16: // SAPR, UAPR レジスタ
17: struct m88200APR
18: {
19: bool enable;
20: uint32 addr;
21: uint32 stat;
22: const char *name; // 自分の名前(ログ表示用)
23: };
24:
25: // BATC
26: struct m88200BATC
27: {
28: // LBA には S, V ビットを混ぜておく。比較を1回で済ませるため。
29: // V ビットは invalid なら %1 にして一致しなくしておく。
30: // 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
31: // +-------------------------+-------------------------+-+-------+--+
32: // | LBA | 0 |S| 0 |~V|
33: // +-------------------------+-------------------------+-+-------+--+
34: uint32 lba; // LBA,S,V
35: uint32 pba; // PBA
36: // stat は ACC_STAT_MASK と同じ WT,G,CI,WP のみ使用。
37: // BATC (BWP レジスタ) のビット位置とは違うので注意。
38: uint32 stat;
39: bool wp; // WP (比較で使うのでこれだけ抜き出しておく)
40: };
41:
42: // PATC
43: struct m88200PATC
44: {
45: // LPA には S ビットと有効/無効情報を混ぜておく。比較を1回で済ませるため。
46: // V ビットは invalid なら %1 にして一致しなくしておく。実際の
47: // PATC エントリの有効/無効は 46ビットの PATC 構造の外で管理されている?
48: // 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
49: // +---------------------------------------+-----------+-+-------+--+
50: // | LPA | |S| 0 |~V|
51: // +---------------------------------------+-----------+-+-------+--+
52: uint32 lpa; // LPA,S,(V)
53: uint32 pfa; // PFA
54: uint32 stat; // ACC_STAT_MASK と同じ WT,G,CI,WP のみ使用。
55: bool m; // Modified
56: bool wp; // Write Protect (比較で使うのでこれだけ抜き出しておく)
57: };
58:
59: // キャッシュの1セット
60: class m88200CacheSet
61: {
62: public:
63: enum Status {
64: EU = 0, // Exclusive Unmodified
65: EM = 1, // Exclusive Modified
66: SU = 2, // Shared Unmodified
67: IV = 3, // Invalid
68: };
69:
70: //
71: // 3 2 1
72: // 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
73: // +---------------------------------------+---------------+----+---+
74: // | tag | set |Word| |
75: // +---------------------------------------+---------------+----+---+
76:
77: // タグはアドレスの上位 20ビット。
78: // ただし無効なラインかどうかのチェックも一度で済ませるために
79: // 無効(vv[]==IV)ならビット 0 を 1 にしておく。比較対象の paddr は
80: // 下位12ビットを落としているため、これで絶対に一致しなくなる。
81: static const uint32 TAG_INVALID = 0x00000001;
82: uint32 tag[4];
83:
84: // LRU
85: // CSSP の L ビットのロジックに従う。
86: int L {};
87:
88: // ステータス
89: Status vv[4];
90:
91: // データ。word[] は以下の順
92: // Word
93: // +0 +1 +2 +3
94: // line0 [ 0] [ 1] [ 2] [ 3]
95: // line1 [ 4] [ 5] [ 6] [ 7]
96: // :
97: uint32 word[16];
98:
99: // 自身のセットインデックス
100: uint32 setidx;
101:
102: // 引数 L の状態から line を最新にしたらどうなるか、を返す。
103: // 表示処理で一時変数に対して処理が必要なため static 分離してある。
104: static int TryUseLine(int L, int line);
105:
106: // 引数 L の状態から line を最古にしたらどうなるか、を返す。
107: // 対称性のため static 分離してある。
108: static int TryUnuseLine(int L, int line);
109:
110: // 引数 L の状態で、最新の line を返す。
111: // 表示処理で一時変数に対して処理が必要なため static 分離してある。
112: static int TryGetOldestLine(int L);
113:
114: void Use(int line) {
115: L = TryUseLine(L, line);
116: }
117:
118: // 更新用に最も古いラインを選んで差し出す
119: int SelectOldestLine() const;
120:
121: void Update(int line, Status status);
122:
123: uint64 ReadLine(int line, uint32 tagaddr);
124:
125: void Write(int line, uint32 paddr, uint32 data, int size);
126:
127: uint64 CopyBackLine(int line);
128:
129: // キャッシュを検索して、ヒットした line を返す。
130: int Lookup(uint32 tagaddr) const;
131: };
132:
133: class m88200 : public Object
134: {
135: public:
136: m88200();
137: ~m88200() override;
138:
139: // 本当はコンストラクタ渡ししたかったもの
140: void Ctor(m88kcpu *parent_);
141:
142: // リセット
143: void Reset();
144:
145: bool MonitorUpdate() override;
146:
147: private:
148: m88kcpu *parent;
149:
150: public:
151: //
152: // レジスタ
153: //
154:
155: // IDR (ID Register) +$000
156: // 3 2 1
157: // 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
158: // +---------------+-----+---------+-------------------------------+
159: // | ID | Type| Version | reserved |
160: // +---------------+-----+---------+-------------------------------+
161: //
162: // ID はリセット時、下位7ビットはハードウェアで初期化、最上位ビットは
163: // 0 で初期化。その後は全ビット変更可能。
164: // Type は $5 = 88200、$6 = 88204。ここでは 88200 固定。
165: // Version は不明。
166: uint32 id;
167: uint32 version;
168:
169: // IDR レジスタの内容を返す
170: uint32 GetIDR() const {
171: return (id << 24) | (0x5 << 21);
172: }
173: // ID を設定する (IDR ではない)
174: void SetID(uint id_);
175: // Version フィールドを設定する
176: void SetVersion(uint version_);
177:
178: // SCR (System Command Register) +$004
179: // 3 2 1
180: // 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
181: // +---------------------------------------------------+-----------+
182: // | reserved |CommandCode|
183: // +---------------------------------------------------+-----------+
184: uint32 command;
185: uint32 GetSCR() const;
186: void SetSCR(uint32 val);
187: private:
188: static const char * const commandname[];
189: static const uint32 GG_LINE = 0;
190: static const uint32 GG_PAGE = 1;
191: static const uint32 GG_SEG = 2;
192: static const uint32 GG_ALL = 3;
193: void FlushCache();
194: void InvalidatePATC();
195:
196: public:
197: // SSR (System Status Register) +$008
198: // 3 2 1
199: // 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
200: // +---------------------------------------------------------------+
201: // | |C|B| |W|S|G|C| |M|U|W|B|V|
202: // | reserved |E|E| res |T|P| |I|r| | |P|H| |
203: // +---------------------------------------------------------------+
204: static const uint32 SSR_CE = 0x00008000; // Copyback Error
205: static const uint32 SSR_BE = 0x00004000; // Bus Error
206: static const uint32 SSR_WT = 0x00000200; // WriteThrough
207: static const uint32 SSR_SP = 0x00000100; // Supervisor Privilege
208: static const uint32 SSR_G = 0x00000080; // Global
209: static const uint32 SSR_CI = 0x00000040; // Cache Inhibit
210: static const uint32 SSR_M = 0x00000010; // Modified
211: static const uint32 SSR_U = 0x00000008; // Used
212: static const uint32 SSR_WP = 0x00000004; // Write Protection
213: static const uint32 SSR_BH = 0x00000002; // BATC Hit
214: static const uint32 SSR_V = 0x00000001; // Valid
215: uint32 ssr;
216: uint32 GetSSR() const { return ssr; }
217: void SetSSR(uint32 val) { ssr = val; }
218:
219: // SAR (System Address Register) +$00c
220: // 3 2 1
221: // 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
222: // +---------------------------------------------------------------+
223: // | Address |
224: // +---------------------------------------------------------------+
225: uint32 sar;
226: uint32 GetSAR() const { return sar; }
227: void SetSAR(uint32 val) { sar = val; }
228:
229: // SCTR (System Control Register) +$104
230: // 3 2 1
231: // 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
232: // +-------------------------------+-+-+-+-------------------------+
233: // | |P|S|P| |
234: // | reserved |E|E|R| reserved |
235: // +-------------------------------+-+-+-+-------------------------+
236: static const uint32 SCTR_PE = 0x00008000; // Parity Enable
237: static const uint32 SCTR_SE = 0x00004000; // Snoop Enable
238: static const uint32 SCTR_PR = 0x00002000; // Priority Arbitration
239: uint32 sctr;
240: uint32 GetSCTR() const { return sctr; }
241: void SetSCTR(uint32 val);
242:
243: // SAPR (Supervisor Area Pointer Register) +$200
244: // UAPR (User Area Pointer Register) +$204
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: // | Supervisor Segment Table Base Address | |W| |G|C| |T|
249: // | or User Segment Table Base Address |0 0|T|0| |I|0 0 0 0 0|E|
250: // +---------------------------------------+---+-+-+-+-+---------+-+
251: static const uint32 APR_ADDR_MASK = 0xfffff000; // Base Address
252: static const uint32 APR_WT = 0x00000200; // WriteThrough
253: static const uint32 APR_G = 0x00000080; // Global
254: static const uint32 APR_CI = 0x00000040; // Cache Inhibit
255: static const uint32 APR_TE = 0x00000001; // Translation Enable
256: m88200APR uapr {};
257: m88200APR sapr {};
258: private:
259: uint32 GetAPR(const m88200APR&) const;
260: void SetAPR(m88200APR&, uint32 data);
261: public:
262: uint32 GetAPR(uint issuper) const;
263: uint32 GetUAPR() const { return GetAPR(uapr); }
264: uint32 GetSAPR() const { return GetAPR(sapr); }
265: void SetAPR(uint issuper, uint32 data);
266: void SetUAPR(uint32 data) { SetAPR(uapr, data); }
267: void SetSAPR(uint32 data) { SetAPR(sapr, data); }
268:
269: // PFSR (P Bus Fault Status Register) +$108
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: // | |Fault| |
274: // | reserved | Code| reserved |
275: // +-------------------------+-----+-------------------------------+
276: static const uint32 FAULT_CODE_SUCCESS = 0; // Success (No fault)
277: static const uint32 FAULT_CODE_BUSERR = 3; // Bus Error
278: static const uint32 FAULT_CODE_SEGMENT = 4; // Segment Fault
279: static const uint32 FAULT_CODE_PAGE = 5; // Page Fault
280: static const uint32 FAULT_CODE_SUPERVISOR = 6; // Supervisor Violation
281: static const uint32 FAULT_CODE_WRITE = 7; // Write Violation
282: uint32 fault_code;
283: uint32 GetPFSR() const {
284: return fault_code << 16;
285: }
286: void SetPFSR(uint32 data) {
287: fault_code = (data >> 16) & 7;
288: }
289:
290: // PFAR (P Bus Fault Address Register) +$10c
291: // 3 2 1
292: // 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
293: // +---------------------------------------------------------------+
294: // | Address |
295: // +---------------------------------------------------------------+
296: uint32 fault_addr;
297: uint32 GetPFAR() const { return fault_addr; }
298: void SetPFAR(uint32 val) { fault_addr = val; }
299:
300: // BWP0-7 (BATC Write Ports 0..7) +$400..+$41c
301: // 3 2 1
302: // 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
303: // +---------------------------------------------------------------+
304: // | | |S|W|G|C|W|V|
305: // | Logical Block Address | Physical Block Address | |T| |I|P| |
306: // +---------------------------------------------------------------+
307: static const uint32 BATC_LBA_MASK = 0xfff80000;
308: static const uint32 BATC_PBA_MASK = 0x0007ffc0;
309: static const uint32 BATC_S = 0x00000020; // Address Space
310: static const uint32 BATC_WT = 0x00000010; // WriteThrough
311: static const uint32 BATC_G = 0x00000008; // Global
312: static const uint32 BATC_CI = 0x00000004; // Cache Inhibit
313: static const uint32 BATC_WP = 0x00000002; // Write Protect
314: static const uint32 BATC_V = 0x00000001; // Valid
315: std::array<m88200BATC, 10> batc {};
316: uint32 GetBATC(uint n) const;
317: void SetBATC(uint n, uint32 val);
318:
319: // CDP0-3 (Cache Data Ports 0..3) +$800..+$80c
320: // 3 2 1
321: // 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
322: // +---------------------------------------------------------------+
323: // | Data Word |
324: // +---------------------------------------------------------------+
325:
326: // CTP0-3 (Cache Tag Ports 0..3) +$840..+$84c
327: // 3 2 1
328: // 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
329: // +---------------------------------------+-----------------------+
330: // | Physical Address | reserved |
331: // +---------------------------------------+-----------------------+
332:
333: // CSSP (Cache Set Status Port) +$880
334: // 3 2 1
335: // 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
336: // +---------------------------------------------------------------+
337: // | |L|L|L|L|L|L|D|D|D|D|VV3|VV2|VV1|VV0| |
338: // |res|5|4|3|2|1|0|3|2|1|0| | | | | reserved |
339: // +---------------------------------------------------------------+
340: static const uint32 CSSP_L5 = 0x20000000; // Line5
341: static const uint32 CSSP_L4 = 0x10000000; // Line4
342: static const uint32 CSSP_L3 = 0x08000000; // Line3
343: static const uint32 CSSP_L2 = 0x04000000; // Line2
344: static const uint32 CSSP_L1 = 0x02000000; // Line1
345: static const uint32 CSSP_L0 = 0x01000000; // Line0
346: static const uint32 CSSP_D3 = 0x00800000; // Line Disable
347: static const uint32 CSSP_D2 = 0x00400000; // Line Disable
348: static const uint32 CSSP_D1 = 0x00200000; // Line Disable
349: static const uint32 CSSP_D0 = 0x00100000; // Line Disable
350: static const uint32 CSSP_VV3 = 0x000c0000; // Line Valid
351: static const uint32 CSSP_VV2 = 0x00030000; // Line Valid
352: static const uint32 CSSP_VV1 = 0x0000c000; // Line Valid
353: static const uint32 CSSP_VV0 = 0x00003000; // Line Valid
354: static const uint32 CSSP_VV3_OFFSET = 18;
355: static const uint32 CSSP_VV2_OFFSET = 16;
356: static const uint32 CSSP_VV1_OFFSET = 14;
357: static const uint32 CSSP_VV0_OFFSET = 12;
358: uint32 GetCSSP() const;
359: void SetCSSP(uint32 val);
360:
361: //
362: // 物理バスアクセス
363: //
364: // XXX size をどうするか
365: uint64 MBusRead(uint32 paddr, int size);
366: uint64 MBusWrite(uint32 paddr, uint32 data, int size);
367: uint64 MBusXmem(uint32 paddr, uint32 data, int size);
368:
369: //
370: // アクセス関数
371: //
372: private:
373: template <int bits> uint64 load(uint32 addr);
374: template <int bits> uint64 store(uint32 addr, uint32 data);
375: template <int bits> uint64 xmem(uint32 addr, uint32 data);
376: public:
377: uint64 load_8(uint32 addr);
378: uint64 load_16(uint32 addr);
379: uint64 load_32(uint32 addr);
380: uint64 store_8(uint32 addr, uint32 data);
381: uint64 store_16(uint32 addr, uint32 data);
382: uint64 store_32(uint32 addr, uint32 data);
383: uint64 xmem_8(uint32 addr, uint32 data);
384: uint64 xmem_16(uint32 addr, uint32 data);
385: uint64 xmem_32(uint32 addr, uint32 data);
386:
387: //
388: // 現在のアクセス中の状態。
389: //
390: // アドレス変換およびデータキャッシュルーチンではこれらの値を
391: // グローバルに状態変数として使う。
392:
393: // ディスクリプタの下位にあるフラグは全部ビット位置が同じ。
394: // Area descriptor (SAPR or UAPR)
395: // 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
396: // +---------------------------------------+---+-+-+-+-+---------+-+
397: // | Supervisor Segment Table Base Address | |W| |G|C| |T|
398: // | or User Segment Table Base Address |0 0|T|0| |I|0 0 0 0 0|E|
399: // +---------------------------------------+---+-+-+-+-+---------+-+
400: //
401: // Segment Descriptor
402: // 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
403: // +---------------------------------------+---+-+-+-+-+-----+-+-+-+
404: // | Page Table Base Address (PTBA) | |W|S|G|C| |W| |V|
405: // | |0 0|T|P| |I|0 0 0|P|0| |
406: // +---------------------------------------+---+-+-+-+-+-----+-+-+-+
407: //
408: // Page Descriptor
409: // 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
410: // +---------------------------------------+---+-+-+-+-+-+-+-+-+-+-+
411: // | Page Frame Address (PFA) | |W|S|G|C| |M|U|W| |V|
412: // | |0 0|T|P| |I|0| | |P|0| |
413: // +---------------------------------------+---+-+-+-+-+-+-+-+-+-+-+
414: //
415: // acc_stat も同じビット位置を使う。
416: // 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
417: // +---------------------------------------+---+-+-+-+-+-----+-+---+
418: // | | |W| |G|C| |W| |
419: // | |0 0|T|0| |I| 0 |P| 0 |
420: // +---------------------------------------+---+-+-+-+-+-----+-+---+
421: //
422: static const uint32 DESC_WT = 0x00000200; // Write Through
423: static const uint32 DESC_SP = 0x00000100; // Supervisor Protect
424: static const uint32 DESC_G = 0x00000080; // Global
425: static const uint32 DESC_CI = 0x00000040; // Cache Inhibit
426: static const uint32 DESC_M = 0x00000010; // Modified
427: static const uint32 DESC_U = 0x00000008; // Used
428: static const uint32 DESC_WP = 0x00000004; // Write Protect
429: static const uint32 DESC_V = 0x00000001; // Valid
430:
431: uint32 acc_laddr {}; // Logical Address
432: uint32 acc_paddrH {}; // Physical Address 上位30ビット。
433: // 下位2ビットは 0 固定。
434: uint32 acc_paddrL {}; // paddr の下位2ビット
435: // 上位30ビットは 0 固定。
436:
437: // acc_stat は 4 ビットのみ使用。
438: // それ以外のビットは代入時にマスクすること。
439: static const uint32 ACC_STAT_MASK = DESC_WT | DESC_G | DESC_CI | DESC_WP;
440: uint32 acc_stat {};
441: // Table Address. とマニュアルには書いてあるけど、テーブル先頭と
442: // 紛らわしいし 88200 のアドレス変換ツリーは2段固定で、今何段目か
443: // しらんけど現在のテーブルアドレス…みたいなのを持つ必要はないので、
444: // ここでは
445: // sdaddr ... Segment Descriptor Address
446: // pdaddr ... Page Descriptor Address
447: // の2つに明確に分けて管理することにする。
448: uint32 acc_sdaddr {};
449: uint32 acc_pdaddr {};
450: bool acc_read; // True if read access
451: bool acc_IsWrite() const { return !acc_read; } // True if write access
452:
453: // S/U 信号線
454: // 実際には P Bus の Address フェーズで毎回送られてくるが
455: // そうそう変わらないので状態変化を通知してもらう方式。
456: // true なら super, false なら user。
457: bool acc_super;
458: void SetSuper(bool super) {
459: acc_super = super;
460: }
461:
462: m88200PATC *acc_patc {}; // ヒットした PATC エントリ
463: uint32 tmp_desc; // TEMP_DESCR
464:
465: //
466: // アドレス変換
467: //
468: bool Translate();
469: uint64 TranslatePeek(uint32 laddr, bool issuper, bool do_search) const;
470: private:
471: static std::string stat2str(uint32 stat);
472: bool SelectAreaDesc();
473: bool TableSearch();
474: bool FetchSegmentDesc();
475: bool FetchPageDesc();
476: bool UpdatePageDesc();
477: void CreatePATCEntry();
478:
479: public:
480: // PATC
481: static const uint32 PATC_S = 0x00000020; // Supervisor
482: std::array<m88200PATC, 56> patc {};
483:
484:
485: //
486: // キャッシュ
487: //
488:
489: std::array<m88200CacheSet,256> setarray {};
490:
491: // キャッシュに対して paddr の読み込みを行う
492: uint64 CacheRead(uint32 paddr);
493: // キャッシュに対して paddr への書き込みを行う
494: uint64 CacheWrite(uint32 paddr, uint32 data, int size);
495: uint64 CacheWriteHit(m88200CacheSet& set, int line,
496: uint32 paddr, uint32 data, int size);
497: uint64 CacheXmem(uint32 paddr, uint32 data, int size);
498:
499: // モニタスクリーン作成用
500: void MonitorCacheSet(TextScreen&, int y, int setidx);
501: void MonitorCacheOverview(TextScreen&, int y, int cursor, bool is_gui);
502: void MonitorCacheOverview(TextScreen& s, int y, bool is_gui) {
503: MonitorCacheOverview(s, y, -1, is_gui);
504: }
505:
506: private:
507: // まだない
508: void MBusAcquire() { }
509: void MBusRelease() { }
510: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.