Annotation of nono/m88xx0/m88200.h, revision 1.1.1.12

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.6   root      167:        DECLARE_MONITOR_CALLBACK(MonitorUpdateReg);
                    168:        DECLARE_MONITOR_CALLBACK(MonitorUpdateATC);
                    169:        DECLARE_MONITOR_CALLBACK(MonitorUpdateCache);
                    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:        uint32 GetLaddr() const { return acc_laddr; }
1.1.1.12! root      461:        uint32 GetPaddr() const { return acc_paddr; }
1.1.1.5   root      462:  private:
1.1       root      463:        uint32 acc_laddr {};            // Logical Address
1.1.1.12! root      464:        uint32 acc_paddr {};            // Physical Address
1.1       root      465: 
1.1.1.5   root      466:  public:
1.1       root      467:        // acc_stat は 4 ビットのみ使用。
                    468:        // それ以外のビットは代入時にマスクすること。
                    469:        static const uint32 ACC_STAT_MASK = DESC_WT | DESC_G | DESC_CI | DESC_WP;
                    470:        uint32 acc_stat {};
                    471:        // Table Address.  とマニュアルには書いてあるけど、テーブル先頭と
                    472:        // 紛らわしいし 88200 のアドレス変換ツリーは2段固定で、今何段目か
                    473:        // しらんけど現在のテーブルアドレス…みたいなのを持つ必要はないので、
                    474:        // ここでは
                    475:        // sdaddr ... Segment Descriptor Address
                    476:        // pdaddr ... Page    Descriptor Address
                    477:        // の2つに明確に分けて管理することにする。
                    478:        uint32 acc_sdaddr {};
1.1.1.12! root      479:        busaddr acc_pdaddr {};
1.1.1.3   root      480:        bool acc_read {};                       // True if read access
1.1       root      481:        bool acc_IsWrite() const { return !acc_read; }  // True if write access
                    482: 
                    483:        // S/U 信号線
                    484:        // 実際には P Bus の Address フェーズで毎回送られてくるが
                    485:        // そうそう変わらないので状態変化を通知してもらう方式。
1.1.1.9   root      486:        // acc_super は S か U のみ。
                    487:        busaddr acc_super {};
1.1.1.7   root      488:        void SetSuper(bool super);
1.1.1.9   root      489:        bool IsSuper() const { return acc_super.IsSuper(); }
                    490:        bool IsUser() const  { return !IsSuper(); }
1.1       root      491: 
                    492:        m88200PATC *acc_patc {};        // ヒットした PATC エントリ
1.1.1.3   root      493:        uint32 tmp_desc {};                     // TEMP_DESCR
1.1       root      494: 
                    495:        //
                    496:        // アドレス変換
                    497:        //
                    498:        bool Translate();
1.1.1.9   root      499:        busaddr TranslatePeek(busaddr laddr) const;
1.1       root      500:  private:
                    501:        static std::string stat2str(uint32 stat);
                    502:        bool SelectAreaDesc();
                    503:        bool TableSearch();
                    504:        bool FetchSegmentDesc();
                    505:        bool FetchPageDesc();
                    506:        bool UpdatePageDesc();
                    507: 
1.1.1.7   root      508:        // BATC
                    509:        static const uint32 BATC_LBA_MASK       = BWP_LBA_MASK;
                    510:        static const uint32 BATC_S                      = m88200BATC::S;
                    511:        static const uint32 BATC_INVALID        = m88200BATC::INVALID;
1.1.1.12! root      512:        void MakeBATCHash();
1.1.1.7   root      513:        std::array<m88200BATC, 10> batc {};
1.1.1.12! root      514:        // 検索用のハッシュ。値のビットN (0..9) が立っていれば batc[N] がこの
        !           515:        // ハッシュに当たることを示している (この後完全一致で比較する必要はある)。
        !           516:        // [0x00] => 0b00'0000'0000;
        !           517:        std::array<uint16, 16> batc_hash_s {};
        !           518:        std::array<uint16, 16> batc_hash_u {};
        !           519:        // 現在の特権状態によって batc_hash_{s,u} のいずれかを指す。
        !           520:        uint16 *batc_hash {};
        !           521:        static int batc_hash_func(uint32 a) {
        !           522:                return (a >> 19) & 0x0f;
        !           523:        }
1.1.1.7   root      524: 
1.1       root      525:        // PATC
1.1.1.7   root      526:        static const uint32 PATC_S                      = m88200PATC::S;
                    527:        static const uint32 PATC_INVALID        = m88200PATC::INVALID;
                    528:        void CreatePATCEntry();
1.1.1.12! root      529:        void InvalidatePATCHash(int);
1.1       root      530:        std::array<m88200PATC, 56> patc {};
1.1.1.12! root      531:        // 検索用のハッシュ。値のビット N (0..55) が立っていれば patc[N] がこの
        !           532:        // ハッシュに当たることを示している (この後完全一致で比較する必要はある)。
        !           533:        std::array<uint64, 256> patc_hash_s {};
        !           534:        std::array<uint64, 256> patc_hash_u {};
        !           535:        // 現在の特権状態によって patc_hash_{s,u} のいずれかを指す。
        !           536:        uint64 *patc_hash {};
        !           537:        static int patc_hash_func(uint32 a) {
        !           538:                return (a >> 12) & 0xff;
        !           539:        }
        !           540:        // 空きエントリ。patc[N] が空いていればビット N を立てる。
        !           541:        uint64 patc_free {};
        !           542:        // 次回追加する位置。
1.1.1.7   root      543:        int patc_next {};
                    544: 
                    545:        // 統計
                    546:        uint64 translate_total {};
                    547:        std::array<uint64, 10> batc_hit {};
                    548:        uint64 patc_hit {};
                    549:        uint64 atc_miss {};
                    550: #if defined(M88200_STAT)
                    551:        // 開発用の統計
                    552:        uint64 stat_patc_create {};                             // エントリ作成回数
                    553:        uint64 stat_patc_invcmd_all {};                 // Invalidate ALL 発行回数
                    554:        uint64 stat_patc_invcmd_seg {};                 // Invalidate Segment 発行回数
                    555:        uint64 stat_patc_invcmd_page {};                // Invalidate Page 発行回数
                    556:        uint64 stat_patc_invalidate {};                 // 無効にした PATC の総数
1.1.1.12! root      557:        uint64 stat_patc_search {};                             // ハッシュを引いた回数
        !           558:        uint64 stat_patc_miss1 {};                              // ハッシュだけでミスした回数
        !           559:        uint64 stat_patc_miss2 {};                              // ビットを調べてミスした回数
        !           560:        std::array<int, 8> stat_batc_hash_s {}; // BATC.S の衝突状況
        !           561:        std::array<int, 8> stat_batc_hash_u {}; // BATC.U の衝突状況
1.1.1.7   root      562: #endif
1.1       root      563: 
                    564:        //
1.1.1.12! root      565:        // 物理アドレスアクセス
        !           566:        //
        !           567:        busdata PhysRead(busaddr paddr, uint32 stat);
        !           568:        busdata PhysWrite(busaddr paddr, uint32 data, uint32 stat);
        !           569: 
        !           570:        //
1.1       root      571:        // キャッシュ
                    572:        //
1.1.1.3   root      573:  private:
1.1       root      574:        std::array<m88200CacheSet,256> setarray {};
1.1.1.3   root      575:        // キャッシュラインにメモリから読み込む
1.1.1.12! root      576:        bool ReadLine(m88200CacheSet& set, uint line, uint32 tagaddr);
1.1.1.3   root      577:        // キャッシュラインをメモリに書き出す
1.1.1.12! root      578:        bool CopyBackLine(m88200CacheSet& set, uint line);
1.1       root      579: 
                    580:        // キャッシュに対して paddr の読み込みを行う
1.1.1.12! root      581:        busdata CacheRead(uint32 paddr);
1.1       root      582:        // キャッシュに対して paddr への書き込みを行う
1.1.1.12! root      583:        busdata CacheWrite(uint32 paddr, uint32 data, uint size);
        !           584:        busdata CacheWriteHit(m88200CacheSet& set, uint line,
1.1.1.10  root      585:                uint32 paddr, uint32 data, uint size);
1.1.1.12! root      586:        busdata CacheXmem(uint32 paddr, uint32 data, uint size);
1.1       root      587: 
1.1.1.12! root      588:  public:
1.1       root      589:        // モニタスクリーン作成用
1.1.1.10  root      590:        void MonitorCacheSet(TextScreen&, int y, uint setidx);
                    591:        void MonitorCacheOverview(TextScreen&, int y, uint cursor, bool is_gui);
1.1       root      592:        void MonitorCacheOverview(TextScreen& s, int y, bool is_gui) {
                    593:                MonitorCacheOverview(s, y, -1, is_gui);
                    594:        }
                    595: 
1.1.1.3   root      596:        //
                    597:        // MBus
                    598:        //
                    599:  public:
1.1.1.7   root      600:        // MBus を所有している CMMU を返す。誰も持っていなければ NULL。
1.1.1.3   root      601:        // これは static 関数
                    602:        static m88200 *GetBusMaster() { return mbus_master; }
                    603: 
1.1       root      604:  private:
1.1.1.12! root      605:        static constexpr bool IM_0 = false;
        !           606:        static constexpr bool IM_1 = true;
1.1.1.3   root      607:        void MBusAcquire();
1.1       root      608:        void MBusRelease() { }
1.1.1.7   root      609:        // 他 CMMU にスヌープさせる (バスマスタ側)
1.1.1.12! root      610:        void MBusMakeSnoop(uint32 addr, bool im);
1.1.1.7   root      611:        // バススヌープを行う (スレーブ側)
1.1.1.12! root      612:        void Snoop(uint32 addr, bool im);
1.1.1.3   root      613: 
1.1.1.8   root      614:        MainbusDevice *mainbus {};
                    615: 
1.1.1.3   root      616:        // MBus を所有してる CMMU を指す。NULL なら解放。
                    617:        // これは static 変数で全 m88200 で共有している
                    618:        static m88200 *mbus_master;
1.1.1.7   root      619: 
                    620:        // スヌープ相手の CMMU リスト
                    621:        std::vector<m88200*> other_cmmu {};
1.1       root      622: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.