Annotation of nono/vm/interrupt.h, revision 1.1.1.3

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: #pragma once
                      8: 
                      9: #include "device.h"
1.1.1.2   root       10: #include "monitor.h"
1.1       root       11: 
                     12: //
                     13: // 割り込みを受け付けるデバイス
                     14: // これ自体は IODevice である必要はないが、PEDEC や SysCtlr がこれを
                     15: // 継承するため。
                     16: //
                     17: class InterruptDevice : public IODevice
                     18: {
                     19:        using inherited = IODevice;
                     20:  public:
                     21:        InterruptDevice();
1.1.1.2   root       22:        InterruptDevice(const std::string& objname_);
1.1       root       23:        virtual ~InterruptDevice() override;
                     24: 
1.1.1.3 ! root       25:        void ResetHard() override;
        !            26: 
1.1       root       27:        // 継承クラスの ResetHard() は保持している割り込み情報を全てキャンセルする。
                     28:        // 各子デバイスはその ResetHard() で NegateINT() を明示的に呼び出して
                     29:        // 割り込みをキャンセルする必要はなく、もし自身で独自に割り込み信号線の
                     30:        // 状態に関する変数を持っていればそれをクリアするだけでよい。
                     31: 
                     32:        // AssertINT()、NegateINT()、ChangeINT() の呼び出し側は、
                     33:        // (アサート中に AssertINT() を呼ぶというような) 現在の状態が
                     34:        // 変わらないような呼び出しをしても構わない。特に副作用はない。
                     35: 
                     36:        // 子デバイスが割り込み信号線をアサートした
1.1.1.3 ! root       37:        void AssertINT(Device *source);
1.1       root       38:        // 子デバイスが割り込み信号線をネゲートした
1.1.1.3 ! root       39:        void NegateINT(Device *source);
1.1       root       40: 
                     41:        // 子デバイスが割り込み信号線を val の状態に変えた。
                     42:        // true ならアサート、false ならネゲート。
                     43:        void ChangeINT(Device *source, bool val) {
                     44:                if (val) {
                     45:                        AssertINT(source);
                     46:                } else {
                     47:                        NegateINT(source);
                     48:                }
                     49:        }
                     50: 
                     51:        // MPU からの割り込みアクノリッジに応答する
                     52:        virtual int InterruptAcknowledge(int lv) = 0;
1.1.1.3 ! root       53: 
        !            54:  protected:
        !            55:        // 割り込みを上位デバイス(MPUなど)に伝達する。
        !            56:        // 子デバイスが割り込み信号線の状態を変えたときに呼び出される。
        !            57:        virtual void ChangeInterrupt() = 0;
        !            58: 
        !            59:        // Intmap について
        !            60:        //
        !            61:        // Intmap は 32bit のビットマップ値で、最大 31 個(といいつつ今の所 28 個)
        !            62:        // の割り込み発生の有無を個別に管理できる。
        !            63:        // 発生している割り込みのうち最も優先度が高い 1つを高速に検索するため、
        !            64:        // MSB 側を最も優先度が高い割り込みとして、Count-Leading-Zero で検索
        !            65:        // することにする。
        !            66:        // __builtin_clz(0) は動作未定義になるので、最下位ビットを常に立てて
        !            67:        // おくことで、割り込みなし(上位31bitがすべて0)の場合でもこの式が使える
        !            68:        // ようにしておく。
        !            69:        //
        !            70:        // 具体的にどの割り込みをどのビットに割り当てるかは継承先の実装によるが、
        !            71:        // m680x0 の場合、以下のように 1レベル 4つずつ割り当てることにする。
        !            72:        //
        !            73:        //    3                   2                   1                   0
        !            74:        //  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
        !            75:        // +-------+-------+-------+-------+-------+-------+-------+-------+
        !            76:        // |7 7 7 7|6 6 6 6|5 5 5 5|4 4 4 4|3 3 3 3|2 2 2 2|1 1 1 1| %0001 |
        !            77:        // +-------+-------+-------+-------+-------+-------+-------+-------+
        !            78:        //
        !            79:        // これにより同一レベルのデバイス 4 つまでの割り込み信号線の状態を独立
        !            80:        // して保持しつつ、アサートされている信号線のうち最もレベルの高いものは
        !            81:        // 以下だけで求めることが出来る。
        !            82:        //
        !            83:        //  ipl = (31 - __builtin_clz(intmap)) / 4;
        !            84:        //
        !            85:        // LUNA88K の外部割り込みコントローラであるシステムコントローラも
        !            86:        // 概ねこれに近いので、sysctlr もこの構造を使う。
        !            87:        //
        !            88:        // PEDEC は 7レベル分けする必要ないので、適当に割り当ててある。
        !            89: 
        !            90:        static const uint32 IntmapSentinel = 0x00000001;
        !            91: 
        !            92:        // デバイスから Intmap 値を引く。
        !            93:        virtual uint32 GetIntmap(Device *source) const = 0;
        !            94: 
        !            95:        // 割り込みマップ
        !            96:        uint32 intmap {};
        !            97: 
        !            98:        // 割り込み回数 (アサートのエッジでカウントアップする)
        !            99:        // [0]  が Intmap の bit31 割り込みのカウント。
        !           100:        // [27] が Intmap の bit 4 割り込みのカウント。
        !           101:        uint64 counter[28] {};
1.1       root      102: };
                    103: 
                    104: //
                    105: // m680x0 仮想割り込みコントローラ (共通部)
                    106: //
                    107: class M680x0Interrupt : public InterruptDevice
                    108: {
                    109:        using inherited = InterruptDevice;
                    110:  public:
                    111:        static const int AutoVector = -1;       // オートベクタ
                    112: 
                    113:  public:
                    114:        M680x0Interrupt();
                    115:        virtual ~M680x0Interrupt() override;
                    116: 
                    117:        void ResetHard() override;
                    118: 
                    119:  protected:
1.1.1.3 ! root      120:        void ChangeInterrupt() override;
1.1       root      121: 
                    122:        // 現在の割り込みレベル
                    123:        int ipl {};
                    124: };
                    125: 
                    126: //
                    127: // X68k 仮想割り込みコントローラ
                    128: //
                    129: // Level
                    130: //  7    INTERRUPT スイッチ
                    131: //  6    MFP
                    132: //  5    SCC
                    133: //  4    (拡張ボード)
                    134: //  3    DMAC
                    135: //  2    (拡張ボード)
                    136: //  1    PEDEC   <--+-- SPC
                    137: //                  +-- HDD (SASI)
                    138: //                  +-- FDC
                    139: //                  +-- FDD
                    140: //                  +-- PRN
                    141: //
                    142: class X68030Interrupt : public M680x0Interrupt
                    143: {
                    144:        using inherited = M680x0Interrupt;
                    145: 
                    146:        // 割り込みマップ                            76543210
                    147:        static const uint32 IntmapNMI           = 0x80000000;
                    148:        static const uint32 IntmapMFP           = 0x08000000;
                    149:        static const uint32 IntmapSCC           = 0x00800000;
                    150:        static const uint32 IntmapDMAC          = 0x00008000;
                    151:        static const uint32 IntmapPEDEC         = 0x00000080;
                    152: 
                    153:  public:
                    154:        X68030Interrupt();
                    155:        virtual ~X68030Interrupt() override;
                    156: 
                    157:        int InterruptAcknowledge(int lv) override;
                    158: 
                    159:  private:
                    160:        uint32 GetIntmap(Device *soruce) const override;
1.1.1.2   root      161: 
                    162:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
                    163: 
                    164:        Monitor monitor { this };
1.1       root      165: };
                    166: 
                    167: //
                    168: // LUNA-I 仮想割り込みコントローラ
                    169: //
                    170: // Level
                    171: //  7
                    172: //  6    SIO
                    173: //  5    SystemClock
                    174: //  4     (XP high)
                    175: //  3    Lance
                    176: //  2    SPC
                    177: //  1     (XP low)
                    178: //
                    179: class LunaInterrupt : public M680x0Interrupt
                    180: {
                    181:        using inherited = M680x0Interrupt;
                    182: 
                    183:        // 割り込みマップ                            76543210
                    184:        static const uint32 IntmapSIO           = 0x08000000;
                    185:        static const uint32 IntmapSysClk        = 0x00800000;
                    186:        static const uint32 IntmapLance         = 0x00008000;
                    187:        static const uint32 IntmapSPC           = 0x00000800;
                    188: 
                    189:  public:
                    190:        LunaInterrupt();
                    191:        virtual ~LunaInterrupt() override;
                    192: 
                    193:        int InterruptAcknowledge(int lv) override;
                    194: 
                    195:  private:
                    196:        uint32 GetIntmap(Device *source) const override;
1.1.1.2   root      197: 
                    198:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
                    199: 
                    200:        Monitor monitor { this };
1.1       root      201: };
                    202: 
                    203: // LUNA88K は sysctlr.cpp 参照。
                    204: 
                    205: extern std::unique_ptr<InterruptDevice> gInterrupt;

unix.superglobalmegacorp.com

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