Annotation of nono/m680x0/m68030mmu.h, revision 1.1.1.11

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #pragma once
                      8: 
1.1.1.8   root        9: #include <array>
                     10: #include <mutex>
                     11: #include "fixedqueue.h"
1.1.1.6   root       12: 
1.1.1.11! root       13: // ATC 実装種別。
        !            14: //#define M68030_CUSTOM_ATC
        !            15: #define ATC_ORDER64
        !            16: 
        !            17: // ATC エントリ数。
        !            18: #define M68030_ATC_LINES (22)
        !            19: 
        !            20: #if defined(M68030_CUSTOM_ATC)
        !            21: #else
        !            22: # if defined(ATC_ORDER64)
        !            23: #  if M68030_ATC_LINES > 24
        !            24: #   error M68030_ATC_LINES must be <= 24 on ATC_ORDER64.
        !            25: #  endif
        !            26: #  if M68030_ATC_LINES < 13
        !            27: #   error M68030_ATC_LINES must be >= 13 on ATC_ORDER64.
        !            28: #  endif
        !            29: # endif
        !            30: #endif
        !            31: 
1.1.1.9   root       32: class MPU68030Device;
1.1       root       33: 
                     34: // SRP, CRP
                     35: class m68030RP
                     36: {
                     37:        //        6                   5                   4               3
                     38:        //  3 2 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
                     39:        // +-+-----------------------------+---------------------------+---+
1.1.1.11! root       40:        // |U|           LIMIT             |              0            |DT |
1.1       root       41:        // +-+-----------------------------+---------------------------+---+
                     42:        //
                     43:        //    3                   2                   1                   0
                     44:        //  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
                     45:        // +-------------------------------------------------------+-------+
                     46:        // |           TABLE ADDRESS (PA31-PA4)                    |unused |
                     47:        // +-------------------------------------------------------+-------+
                     48:  public:
                     49:        static const uint32 H_MASK      = 0xffff0003;
                     50: };
                     51: 
                     52: // TT レジスタの各フィールドを束ねた構造体のようなもの。
1.1.1.9   root       53: // MPU68030Device::SetTT(), GetTT() で読み書きする。
1.1       root       54: class m68030TT
                     55: {
                     56:        //    3                   2                   1                   0
                     57:        //  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
                     58:        // +---------------+---------------+-+-+-+-+-+-+-+-+-+-----+-+-----+
                     59:        // |LogicalAddrBase|LogicalAddrMask|E|       |C|R|M| | FCB | | FCM |
                     60:        // +---------------+---------------+-+-+-+-+-+-+-+-+-+-----+-+-----+
                     61: 
                     62:  public:
                     63:        static const uint32 MASK                = 0xffff8777;
                     64: 
                     65:        static const uint32 LBASE_MASK  = 0xff000000;
                     66:        static const uint32 LMASK_MASK  = 0x00ff0000;
                     67:        static const uint32 E                   = 0x00008000;
                     68:        static const uint32 CI                  = 0x00000400;
                     69:        static const uint32 RW                  = 0x00000200;
                     70:        static const uint32 RWM                 = 0x00000100;
                     71:        static const uint32 FCBASE_MASK = 0x00000070;
                     72:        static const uint32 FCMASK_MASK = 0x00000007;
                     73: 
1.1.1.11! root       74:        void Set(uint32 data);
        !            75: 
        !            76:        // アクセスがこの TT と一致するか調べる。
        !            77:        bool Match(busaddr addr) const;
        !            78: 
1.1.1.7   root       79:        bool e {};                              // イネーブル
                     80:        bool ci {};                             // キャッシュ禁止
1.1.1.11! root       81:  private:
1.1.1.3   root       82:        uint64 base {};                 // ベース
                     83:        uint64 mask {};                 // マスク
1.1       root       84: };
                     85: 
                     86: // TC レジスタの各フィールドを束ねた構造体のようなもの。
                     87: // m68kcpu::SetTC(), GetTC() で読み書きする。
                     88: class m68030TC
                     89: {
1.1.1.7   root       90:        //    3                   2                   1                   0
                     91:        //  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
                     92:        // +-+---------+-+-+-------+-------+-------+-------+-------+-------+
                     93:        // |E|    0    |S|F|  PS   |  IS   |  TIA  |  TIB  |  TIC  |  TID  |
                     94:        // +-+---------+-+-+-------+-------+-------+-------+-------+-------+
                     95:        //  |           | +-- FCL (Function Code Lookup Enable)
                     96:        //  |           +---- SRE (Supervisor Root Pointer Enable)
                     97:        //  +-- Enable
1.1       root       98:  public:
                     99:        static const uint32 MASK        = 0x83ffffff;
                    100:        static const uint32 TC_E        = 0x80000000;
                    101:        static const uint32 TC_SRE      = 0x02000000;
                    102:        static const uint32 TC_FCL      = 0x01000000;
                    103: 
                    104:        // レジスタの各フィールド
1.1.1.3   root      105:        uint32 e {};            // TC_E   の位置
                    106:        uint32 sre {};          // TC_SRE の位置
                    107:        uint32 fcl {};          // TC_FCL の位置
                    108:        uint ps {};
                    109:        uint is {};
1.1.1.11! root      110: 
        !           111:        // 68030 のテーブルは最大4階層 (TIA 〜 TID) で、
        !           112:        // TIA から termlv 段までが有効。
1.1       root      113:        union {
                    114:                uint tix[4] {};
                    115:                struct {
                    116:                        uint tia;
                    117:                        uint tib;
                    118:                        uint tic;
                    119:                        uint tid;
                    120:                } __packed;
                    121:        };
                    122: 
1.1.1.11! root      123:        int termlv {};                  // 有効な段数 (例えば TIB までなら 2)
1.1       root      124:        int shift[4] {};                // TIA-TID の各部分のシフト量
                    125:        uint32 mask[4] {};              // TIA-TID の各部分のマスク
1.1.1.3   root      126:        uint32 lmask {};                // TIA-TID 全体のマスク
                    127:        uint32 pgmask {};               // PS 部分のマスク
1.1       root      128: 
                    129:  public:
1.1.1.11! root      130:        // 値を代入し、二次変数も用意する。
        !           131:        // 構成例外を起こすなら false を返す。
        !           132:        bool Set(uint32);
        !           133: 
        !           134:        // (E に関わらず) 構成が有効なら true を返す。
        !           135:        bool ConfigOK() const   { return config_ok; }
        !           136: 
        !           137:  private:
1.1       root      138:        bool Check() const;
                    139:        void MakeMask();
1.1.1.11! root      140: 
        !           141:        bool config_ok {};              // (E に関わらず) 構成が有効なら true
1.1       root      142: };
                    143: 
                    144: class m68030MMUSR
                    145: {
                    146:  public:
                    147:        static const uint16 MASK = 0xee43;
                    148:        static const uint16 B    = 0x8000;      // バスエラー
                    149:        static const uint16 L    = 0x4000;      // リミット違反
                    150:        static const uint16 S    = 0x2000;      // スーパバイザ専用
                    151:        static const uint16 W    = 0x0800;      // 書き込み保護
                    152:        static const uint16 I    = 0x0400;      // 無効
                    153:        static const uint16 M    = 0x0200;      // 修正
                    154:        static const uint16 T    = 0x0040;      // 透過アクセス
                    155:        static const uint16 N    = 0x0007;      // レベル数
                    156: };
                    157: 
                    158: // ATC の1エントリ
                    159: struct m68030ATCLine
                    160: {
1.1.1.11! root      161:        // tag:
        !           162:        //     3                   2                   1                   0
        !           163:        //   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
        !           164:        //  +---------------+---------------+---------------+-------+-----+-+
        !           165:        //  |              Logical Address [31:8]           |   0   | FC  |I|
        !           166:        //  +---------------+---------------+---------------+-------+-----+-+
        !           167:        //   I:  Invalid (%1で無効)。
        !           168:        //   FC: busaddr 形式の FC (210 の順) で、_Motorola のみで使用。
        !           169:        //       _Custom のほうは FC 別のテーブルなのでここは使わない。
1.1       root      170:        //
1.1.1.11! root      171:        // paddr:
        !           172:        //   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
        !           173:        //  +---------------+---------------+---------------+---------------+
        !           174:        //  |             Physical Address [31:8]           |       0       |
        !           175:        //  +---------------+---------------+---------------+---------------+
1.1.1.7   root      176:        //
1.1.1.11! root      177:        // data:
        !           178:        //   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
        !           179:        //  +---------------+---------------+---------------+-------+-+-+-+-+
        !           180:        //  |                         0                             |B|C|P|M|
        !           181:        //  +---------------+---------------+---------------+-------+-+-+-+-+
        !           182:        //   B: Bus Error
        !           183:        //   C: Cache Inhibit
        !           184:        //   P: Write Protect
        !           185:        //   M: Modified
1.1       root      186: 
                    187:        static const uint32 LADDR_MASK  = 0xffffff00;
                    188:        static const uint32 INVALID             = 0x00000001;
                    189:        static const uint32 PADDR_MASK  = 0xffffff00;
                    190:        static const uint32 BUSERROR    = 0x00000008;
                    191:        static const uint32 CINHIBIT    = 0x00000004;
                    192:        static const uint32 WPROTECT    = 0x00000002;
                    193:        static const uint32 MODIFIED    = 0x00000001;
                    194: 
                    195:        uint32 tag;
                    196:        uint32 paddr;
                    197:        uint32 data;
1.1.1.11! root      198: #if defined(M68030_CUSTOM_ATC)
1.1.1.8   root      199:        uint32 age;
1.1.1.11! root      200: #endif
1.1       root      201: 
                    202:        uint32 GetTag() const           { return tag; }
                    203: 
1.1.1.11! root      204:        void   Invalidate()                     { tag |= INVALID; }
1.1       root      205:        bool   IsInvalid() const        { return tag & INVALID; }
                    206:        bool   IsValid() const          { return !IsInvalid(); }
                    207: 
                    208:        uint32 GetLAddr() const         { return tag & LADDR_MASK; }
1.1.1.11! root      209: #if !defined(M68030_CUSTOM_ATC)
        !           210:        uint32 GetFC() const            { return (tag >> 1) & 7; }
        !           211: #endif
1.1       root      212:        uint32 GetPAddr() const         { return paddr; }
                    213:        bool   IsBusError() const       { return data & BUSERROR; }
                    214:        bool   IsCInhibit() const       { return data & CINHIBIT; }
                    215:        bool   IsWProtect() const       { return data & WPROTECT; }
                    216:        bool   IsModified() const       { return data & MODIFIED; }
1.1.1.8   root      217: };
1.1       root      218: 
1.1.1.11! root      219: // ATCTable_* の共通部分だが、ポリモーフィズム (virtual) は使わずに書く。
        !           220: class m68030ATCTable
        !           221: {
        !           222:  public:
        !           223:        static constexpr int LINES = M68030_ATC_LINES;
        !           224: 
        !           225:        // 論理アドレスマスクを設定する。
        !           226:        void SetMask(uint32 lmask_) {
        !           227:                lmask = lmask_;
        !           228:        }
        !           229: 
        !           230:  protected:
        !           231:        // デバッグ表示用
        !           232:        static std::string LineToStrCommon(const m68030ATCLine *, uint fc);
        !           233: 
        !           234:  public:
        !           235:        int loglevel {};
        !           236: 
        !           237:  protected:
        !           238:        // cpu->mmu_tc.lmask のコピー。
        !           239:        uint32 lmask {};
        !           240: 
        !           241:        MPU68030Device *cpu {};
        !           242: };
        !           243: 
        !           244: #if defined(M68030_CUSTOM_ATC)
        !           245: //
        !           246: // カスタム ATC。FC を分離し、TT と ATC を同時に検索する魔改造版。
        !           247: //
        !           248: 
1.1.1.8   root      249: struct m68030ATCStat
                    250: {
1.1.1.11! root      251:        uint32 total {};        // アドレス変換した回数 (TC と TT 両方)
        !           252:        uint32 tthit {};        // TT にヒットした回数
        !           253:        uint32 miss {};         // ATC ミスした回数
        !           254: 
        !           255:        void Clear() {
        !           256:                total = 0;
        !           257:                tthit = 0;
        !           258:                miss = 0;
        !           259:        }
1.1       root      260: };
                    261: 
1.1.1.11! root      262: class m68030ATCTable_Custom : public m68030ATCTable
1.1       root      263: {
                    264:  public:
1.1.1.8   root      265:        // ATC ハッシュ
                    266:        enum : uint8 {
                    267:                HASH_ATC_BASE   = 0,            // ATC #0-
                    268:                HASH_NONE               = 0xff,         // 対応なし
                    269:                HASH_TT                 = 0xfe,         // TT
                    270:                HASH_SUB                = 0xfd,         // PS<4KB
                    271:        };
1.1       root      272: 
1.1.1.11! root      273:        m68030ATCTable_Custom(MPU68030Device *cpu_, uint fc_);
        !           274: 
        !           275:        // 統計情報、移動平均等をリセットする。
        !           276:        void ResetStat();
        !           277: 
        !           278:        // ハッシュを完全に作り直す。
        !           279:        void Rehash();
        !           280: 
        !           281:        // 論理アドレスからタグを作成する。
        !           282:        uint32 MakeTag(const busaddr laddr) const {
        !           283:                return (laddr.Addr() & lmask);
        !           284:        }
1.1       root      285: 
                    286:        // フラッシュ
1.1.1.8   root      287:        // Flush() はこのテーブルのすべてのエントリが対象。
                    288:        // Flush(addr) はこのテーブルのアドレスが一致するエントリが対象。
                    289:        void Flush();
                    290:        void Flush(uint32 addr);
                    291: 
1.1.1.11! root      292:        m68030ATCLine *Pop();
        !           293: 
1.1.1.8   root      294:        // PS<4KB の時に ATC を検索。
                    295:        m68030ATCLine *FindSub(const busaddr laddr);
                    296: 
                    297:        void Invalidate(m68030ATCLine *a);
                    298:        void InvalidateSub(const m68030ATCLine *);
                    299: 
1.1.1.11! root      300:        void ClearHash();
1.1.1.10  root      301:        void MakeHash(const m68030ATCLine *);
1.1.1.8   root      302:        void MoveHead(m68030ATCLine *);
                    303: 
                    304:        // デバッグ表示
                    305:        std::string LineToStr(const m68030ATCLine *a) const;
1.1       root      306: 
1.1.1.11! root      307:        // エントリの実体。
        !           308:        std::array<m68030ATCLine, LINES> line {};
1.1       root      309: 
1.1.1.11! root      310:        // 統計情報。
        !           311:        m68030ATCStat stat {};
        !           312: 
        !           313:        // 移動平均用バッファ。(こっちは排他制御が必要)
        !           314:        FixedQueue<m68030ATCStat, 3> hist {};
        !           315:        bool hist_tt_once_hit {};
        !           316:        std::mutex hist_mtx {};
        !           317: 
        !           318:  private:
1.1.1.8   root      319:        uint32 latest_age {};
                    320: 
                    321:        // このテーブルの FC
                    322:        uint fc {};
                    323: 
                    324:        // PS(ページのビット長) - 12。負数なら PS<4KB
                    325:        int ps4k {};
                    326: 
1.1.1.11! root      327:  public:
        !           328:        // ATC ハッシュ (他のメンバより後ろに置く?)
        !           329:        std::array<uint8, 1024 * 1024> hash {};
        !           330: };
1.1       root      331: 
1.1.1.11! root      332: #else
        !           333: //
        !           334: // Motorola ATC
        !           335: //
1.1.1.7   root      336: 
1.1.1.11! root      337: struct m68030ATCStat
        !           338: {
        !           339:        // 先頭からn番目のヒット回数
        !           340:        std::array<uint64, M68030_ATC_LINES> hit {};
        !           341:        // ATC 検索ミス回数
        !           342:        uint64 miss {};
        !           343: 
        !           344:        void Clear() {
        !           345:                hit = {};
        !           346:                miss = 0;
        !           347:        }
        !           348: };
1.1.1.7   root      349: 
1.1.1.11! root      350: class m68030ATCTable_Motorola : public m68030ATCTable
        !           351: {
        !           352:        friend class MPU68030Device;
1.1.1.8   root      353: 
1.1.1.11! root      354: #if defined(ATC_ORDER64)
        !           355:        static constexpr int ORDER0_COUNT = 12;
        !           356:        static constexpr int ORDER1_COUNT = M68030_ATC_LINES - ORDER0_COUNT;
        !           357: #endif
        !           358: 
        !           359:  public:
        !           360:        explicit m68030ATCTable_Motorola(MPU68030Device *cpu_);
        !           361: 
        !           362:        // 統計情報、移動平均等をリセットする。
        !           363:        void ResetStat();
        !           364: 
        !           365:        // 論理アドレスからタグを作成する。
        !           366:        uint32 MakeTag(const busaddr laddr) const {
        !           367:                return (laddr.Addr() & lmask) | (laddr.GetFC() << 1);
        !           368:        }
        !           369: 
        !           370:        // エントリのフラッシュ。(pflush* 命令から呼ばれる)
        !           371:        void Flush();
        !           372:        void Flush(uint32 fc, uint32 mask);
        !           373:        void Flush(uint32 fc, uint32 mask, uint32 addr);
        !           374: 
        !           375:        // laddr を検索して見付かれば先頭に移動。
        !           376:        m68030ATCLine *LookupAndMove(const busaddr laddr);
        !           377: 
        !           378:        // laddr を検索して見付かったのを返す。(PTEST 用)
        !           379:        const m68030ATCLine *LookupOnly(const busaddr laddr);
        !           380: 
        !           381:        // laddr を検索して返す。なければ NULL を返す。(デバッガ用)
        !           382:        const m68030ATCLine *LookupByDebugger(const busaddr laddr) {
        !           383:                // 今は Only と同じ。
        !           384:                return LookupOnly(laddr);
        !           385:        }
        !           386: 
        !           387:        // 空きもしくは最も古いエントリを先頭に移動。
        !           388:        m68030ATCLine *Pop();
        !           389: 
        !           390:        // pri 番目の idx を返す。
        !           391:        uint GetIdx(uint pri) const
        !           392:        {
        !           393: #if defined(ATC_ORDER64)
        !           394:                if (__predict_true(pri < ORDER0_COUNT)) {
        !           395:                        return (order[0] >> (pri * 5)) & 0x1f;
        !           396:                } else {
        !           397:                        return (order[1] >> ((pri - ORDER0_COUNT) * 5)) & 0x1f;
        !           398:                }
        !           399: #else
        !           400:                return order[pri];
        !           401: #endif
        !           402:        }
        !           403: 
        !           404:        // pri 番目のエントリを返す。
        !           405:        m68030ATCLine *GetLine(uint pri) {
        !           406:                return &line[GetIdx(pri)];
        !           407:        }
        !           408: 
        !           409:        // デバッグ表示
        !           410:        static std::string LineToStr(const m68030ATCLine *);
        !           411: 
        !           412:  private:
        !           413:        // pri 番目の値を idx にする。
        !           414:        void Set(uint pri, uint idx);
        !           415: 
        !           416:        int Lookup(const busaddr);
        !           417: 
        !           418:        // pri 番目の要素を先頭に移動。
        !           419:        void MoveHead(uint pri);
        !           420:        // pri 番目の要素を末尾に移動。
        !           421:        void MoveTail(uint pri);
        !           422: 
        !           423:        // エントリの実体。
        !           424:        std::array<m68030ATCLine, LINES> line {};
        !           425: 
        !           426:        // 順序管理。
        !           427: #if defined(ATC_ORDER64)
        !           428:        std::array<uint64, 2> order {};
        !           429: #else
        !           430:        std::array<uint8, LINES> order {};
        !           431: #endif
        !           432: 
        !           433:        // 統計情報。
        !           434:        m68030ATCStat stat {};
1.1       root      435: };
                    436: 
1.1.1.11! root      437: #endif // M68030_CUSTOM_ATC
        !           438: 
        !           439: class m68030ATC
1.1       root      440: {
                    441:  public:
1.1.1.11! root      442:        explicit m68030ATC(MPU68030Device *cpu_);
1.1       root      443: 
1.1.1.7   root      444:        // ログレベルを設定する。Object のとは同じ使い方だけど別物。
                    445:        void SetLogLevel(int loglevel_);
                    446: 
1.1.1.11! root      447:        // TC の設定変更に追従する。
        !           448:        void SetTC(const m68030TC&);
1.1       root      449: 
1.1.1.11! root      450: #if defined(M68030_CUSTOM_ATC)
        !           451:        // ハッシュを完全に作り直す。
        !           452:        void Rehash();
        !           453: #endif
        !           454: 
        !           455:        // テーブルを取得する。
        !           456: #if defined(M68030_CUSTOM_ATC)
        !           457:        m68030ATCTable_Custom *GetTable(uint fc) {
        !           458:                assert((bool)fctables[fc]);
        !           459:                return fctables[fc];
        !           460:        }
        !           461: #else
        !           462:        m68030ATCTable_Motorola *GetTable() {
        !           463:                return table.get();
        !           464:        }
        !           465: #endif
        !           466: 
        !           467:        // エントリのフラッシュ。(pflush* 命令から呼ばれる)
        !           468:        void FlushAll();
        !           469:        void Flush(uint32 fc, uint32 mask);
        !           470:        void Flush(uint32 fc, uint32 mask, uint32 addr);
        !           471: 
        !           472:        // 統計情報、移動平均等をリセットする。
        !           473:        void ResetStat();
        !           474: 
        !           475:        // 統計情報、移動平均等を更新する。
        !           476:        void CalcStat();
1.1.1.7   root      477: 
1.1.1.8   root      478:  private:
1.1.1.11! root      479: #if defined(M68030_CUSTOM_ATC)
        !           480:        // FC 別テーブルは 4つ。こっちはループで回せる。
        !           481:        std::array<std::unique_ptr<m68030ATCTable_Custom>, 4> alltables {};
        !           482:        // fc で検索する場合。実際にはこのうち 4つだけが有効。
        !           483:        std::array<m68030ATCTable_Custom *, 8> fctables {};
        !           484: #else
        !           485:        // テーブルは1つ。
        !           486:        std::unique_ptr<m68030ATCTable_Motorola> table {};
        !           487: #endif
        !           488: 
        !           489:        int loglevel {};
        !           490: 
1.1.1.9   root      491:        MPU68030Device *cpu {};
1.1       root      492: };

unix.superglobalmegacorp.com

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