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

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
1.1.1.4   root        7: //
                      8: // 割り込みコントローラ
                      9: //
                     10: 
1.1       root       11: #pragma once
                     12: 
                     13: #include "device.h"
1.1.1.2   root       14: #include "monitor.h"
1.1.1.6 ! root       15: #include <array>
1.1       root       16: 
1.1.1.5   root       17: // XP からの割り込み用。
                     18: // これだけ1デバイスで2本あるので、仕方なく識別子を用意。
                     19: #define DEVICE_XPINT_HIGH      ((Device *)(intptr_t)1)
                     20: #define DEVICE_XPINT_LOW       ((Device *)(intptr_t)2)
                     21: 
                     22: class DMACDevice;
                     23: class LanceDevice;
                     24: class MFPDevice;
                     25: class NewsCtlrDevice;
                     26: class NMIDevice;
                     27: class PEDECDevice;
1.1.1.6 ! root       28: class RTL8019ASDevice;
1.1.1.5   root       29: class SCCDevice;
                     30: class SIODevice;
                     31: class SPCDevice;
                     32: class SysClkDevice;
                     33: 
1.1.1.4   root       34: // 割り込みを受け付けるデバイス。
1.1       root       35: // これ自体は IODevice である必要はないが、PEDEC や SysCtlr がこれを
                     36: // 継承するため。
                     37: class InterruptDevice : public IODevice
                     38: {
                     39:        using inherited = IODevice;
                     40:  public:
                     41:        InterruptDevice();
1.1.1.5   root       42:        InterruptDevice(int objid_);
1.1       root       43:        virtual ~InterruptDevice() override;
                     44: 
                     45:        // 継承クラスの ResetHard() は保持している割り込み情報を全てキャンセルする。
                     46:        // 各子デバイスはその ResetHard() で NegateINT() を明示的に呼び出して
                     47:        // 割り込みをキャンセルする必要はなく、もし自身で独自に割り込み信号線の
                     48:        // 状態に関する変数を持っていればそれをクリアするだけでよい。
1.1.1.4   root       49:        void ResetHard(bool poweron) override;
1.1       root       50: 
                     51:        // AssertINT()、NegateINT()、ChangeINT() の呼び出し側は、
                     52:        // (アサート中に AssertINT() を呼ぶというような) 現在の状態が
                     53:        // 変わらないような呼び出しをしても構わない。特に副作用はない。
                     54: 
                     55:        // 子デバイスが割り込み信号線をアサートした
1.1.1.3   root       56:        void AssertINT(Device *source);
1.1       root       57:        // 子デバイスが割り込み信号線をネゲートした
1.1.1.3   root       58:        void NegateINT(Device *source);
1.1       root       59: 
                     60:        // 子デバイスが割り込み信号線を val の状態に変えた。
                     61:        // true ならアサート、false ならネゲート。
                     62:        void ChangeINT(Device *source, bool val) {
                     63:                if (val) {
                     64:                        AssertINT(source);
                     65:                } else {
                     66:                        NegateINT(source);
                     67:                }
                     68:        }
                     69: 
                     70:        // MPU からの割り込みアクノリッジに応答する
                     71:        virtual int InterruptAcknowledge(int lv) = 0;
1.1.1.3   root       72: 
1.1.1.6 ! root       73:        // 割り込み信号線の状態を取得する
        !            74:        bool GetINT(const Device *source) const;
        !            75: 
1.1.1.3   root       76:  protected:
                     77:        // 割り込みを上位デバイス(MPUなど)に伝達する。
                     78:        // 子デバイスが割り込み信号線の状態を変えたときに呼び出される。
                     79:        virtual void ChangeInterrupt() = 0;
                     80: 
                     81:        // Intmap について
                     82:        //
                     83:        // Intmap は 32bit のビットマップ値で、最大 31 個(といいつつ今の所 28 個)
                     84:        // の割り込み発生の有無を個別に管理できる。
                     85:        // 発生している割り込みのうち最も優先度が高い 1つを高速に検索するため、
                     86:        // MSB 側を最も優先度が高い割り込みとして、Count-Leading-Zero で検索
                     87:        // することにする。
                     88:        // __builtin_clz(0) は動作未定義になるので、最下位ビットを常に立てて
                     89:        // おくことで、割り込みなし(上位31bitがすべて0)の場合でもこの式が使える
                     90:        // ようにしておく。
                     91:        //
                     92:        // 具体的にどの割り込みをどのビットに割り当てるかは継承先の実装によるが、
                     93:        // m680x0 の場合、以下のように 1レベル 4つずつ割り当てることにする。
                     94:        //
                     95:        //    3                   2                   1                   0
                     96:        //  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
                     97:        // +-------+-------+-------+-------+-------+-------+-------+-------+
                     98:        // |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 |
                     99:        // +-------+-------+-------+-------+-------+-------+-------+-------+
                    100:        //
                    101:        // これにより同一レベルのデバイス 4 つまでの割り込み信号線の状態を独立
                    102:        // して保持しつつ、アサートされている信号線のうち最もレベルの高いものは
                    103:        // 以下だけで求めることが出来る。
                    104:        //
                    105:        //  ipl = (31 - __builtin_clz(intmap)) / 4;
                    106:        //
1.1.1.5   root      107:        // LUNA-88K の外部割り込みコントローラであるシステムコントローラも
1.1.1.3   root      108:        // 概ねこれに近いので、sysctlr もこの構造を使う。
                    109:        //
                    110:        // PEDEC は 7レベル分けする必要ないので、適当に割り当ててある。
                    111: 
                    112:        static const uint32 IntmapSentinel = 0x00000001;
                    113: 
                    114:        // デバイスから Intmap 値を引く。
1.1.1.6 ! root      115:        virtual uint32 GetIntmap(const Device *source) const = 0;
1.1.1.3   root      116: 
                    117:        // 割り込みマップ
                    118:        uint32 intmap {};
                    119: 
                    120:        // 割り込み回数 (アサートのエッジでカウントアップする)
                    121:        // [0]  が Intmap の bit31 割り込みのカウント。
                    122:        // [27] が Intmap の bit 4 割り込みのカウント。
                    123:        uint64 counter[28] {};
1.1       root      124: };
                    125: 
                    126: // m680x0 仮想割り込みコントローラ (共通部)
                    127: class M680x0Interrupt : public InterruptDevice
                    128: {
                    129:        using inherited = InterruptDevice;
                    130:  public:
                    131:        static const int AutoVector = -1;       // オートベクタ
                    132: 
                    133:  public:
                    134:        M680x0Interrupt();
                    135:        virtual ~M680x0Interrupt() override;
                    136: 
1.1.1.5   root      137:        bool Init() override;
1.1.1.4   root      138:        void ResetHard(bool poweron) override;
1.1       root      139: 
                    140:  protected:
1.1.1.3   root      141:        void ChangeInterrupt() override;
1.1       root      142: 
                    143:        // 現在の割り込みレベル
                    144:        int ipl {};
                    145: };
                    146: 
                    147: // X68k 仮想割り込みコントローラ
                    148: //
                    149: // Level
                    150: //  7    INTERRUPT スイッチ
                    151: //  6    MFP
                    152: //  5    SCC
                    153: //  4    (拡張ボード)
                    154: //  3    DMAC
                    155: //  2    (拡張ボード)
                    156: //  1    PEDEC   <--+-- SPC
                    157: //                  +-- HDD (SASI)
                    158: //                  +-- FDC
                    159: //                  +-- FDD
                    160: //                  +-- PRN
                    161: //
                    162: class X68030Interrupt : public M680x0Interrupt
                    163: {
                    164:        using inherited = M680x0Interrupt;
                    165: 
                    166:        // 割り込みマップ                            76543210
                    167:        static const uint32 IntmapNMI           = 0x80000000;
                    168:        static const uint32 IntmapMFP           = 0x08000000;
                    169:        static const uint32 IntmapSCC           = 0x00800000;
1.1.1.6 ! root      170:        static const uint32 IntmapNereid0       = 0x00080000;
        !           171:        static const uint32 IntmapNereid1       = 0x00040000;
1.1       root      172:        static const uint32 IntmapDMAC          = 0x00008000;
                    173:        static const uint32 IntmapPEDEC         = 0x00000080;
                    174: 
                    175:  public:
                    176:        X68030Interrupt();
                    177:        virtual ~X68030Interrupt() override;
                    178: 
1.1.1.5   root      179:        bool Init() override;
1.1       root      180:        int InterruptAcknowledge(int lv) override;
                    181: 
                    182:  private:
1.1.1.6 ! root      183:        uint32 GetIntmap(const Device *soruce) const override;
1.1.1.2   root      184: 
                    185:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
                    186: 
1.1.1.5   root      187:        DMACDevice *dmac {};
                    188:        MFPDevice *mfp {};
                    189:        NMIDevice *nmi {};
                    190:        PEDECDevice *pedec {};
1.1.1.6 ! root      191:        std::array<RTL8019ASDevice *, 2> net {};
1.1.1.5   root      192:        SCCDevice *scc {};
                    193: 
1.1.1.2   root      194:        Monitor monitor { this };
1.1       root      195: };
                    196: 
                    197: // LUNA-I 仮想割り込みコントローラ
                    198: //
                    199: // Level
                    200: //  7
                    201: //  6    SIO
                    202: //  5    SystemClock
                    203: //  4     (XP high)
                    204: //  3    Lance
                    205: //  2    SPC
                    206: //  1     (XP low)
                    207: //
                    208: class LunaInterrupt : public M680x0Interrupt
                    209: {
                    210:        using inherited = M680x0Interrupt;
                    211: 
                    212:        // 割り込みマップ                            76543210
1.1.1.4   root      213:        static const uint32 IntmapNMI           = 0x80000000;
1.1       root      214:        static const uint32 IntmapSIO           = 0x08000000;
                    215:        static const uint32 IntmapSysClk        = 0x00800000;
1.1.1.5   root      216:        static const uint32 IntmapXPHigh        = 0x00400000;
1.1       root      217:        static const uint32 IntmapLance         = 0x00008000;
                    218:        static const uint32 IntmapSPC           = 0x00000800;
1.1.1.5   root      219:        static const uint32 IntmapXPLow         = 0x00000080;
1.1       root      220: 
                    221:  public:
                    222:        LunaInterrupt();
                    223:        virtual ~LunaInterrupt() override;
                    224: 
1.1.1.5   root      225:        bool Init() override;
                    226:        int InterruptAcknowledge(int lv) override;
                    227: 
                    228:  private:
1.1.1.6 ! root      229:        uint32 GetIntmap(const Device *source) const override;
1.1.1.5   root      230: 
                    231:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
                    232: 
                    233:        LanceDevice *lance {};
                    234:        NMIDevice *nmi {};
                    235:        SIODevice *sio {};
                    236:        SPCDevice *spc {};
                    237:        SysClkDevice *sysclk {};
                    238: 
                    239:        Monitor monitor { this };
                    240: };
                    241: 
                    242: // NEWS 仮想割り込みコントローラ
                    243: //
                    244: // Level
                    245: //  7
                    246: //  6    Timer
                    247: //  5    SCC(vectored)
                    248: //  4    SIC, Lance
                    249: //  3
                    250: //  2
                    251: //  1
                    252: //
                    253: class NewsInterrupt : public M680x0Interrupt
                    254: {
                    255:        using inherited = M680x0Interrupt;
                    256: 
                    257:        // 割り込みマップ                            76543210
                    258:        static const uint32 IntmapNMI           = 0x80000000;
                    259:        static const uint32 IntmapTimer         = 0x08000000;
                    260:        static const uint32 IntmapSCC           = 0x00800000;
                    261:        static const uint32 IntmapSIC           = 0x00080000;
                    262:        static const uint32 IntmapLance         = 0x00040000;
                    263: 
                    264:  public:
                    265:        NewsInterrupt();
                    266:        virtual ~NewsInterrupt() override;
                    267: 
                    268:        bool Init() override;
1.1       root      269:        int InterruptAcknowledge(int lv) override;
                    270: 
1.1.1.5   root      271:        // 割り込みステータスを返す (NewsCtlr から呼ばれる)
                    272:        uint8 PeekStatus() const;
                    273: 
1.1       root      274:  private:
1.1.1.6 ! root      275:        uint32 GetIntmap(const Device *source) const override;
1.1.1.2   root      276: 
                    277:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
                    278: 
1.1.1.5   root      279:        LanceDevice *lance {};
                    280:        NewsCtlrDevice *newsctlr {};
                    281:        SCCDevice *scc {};
                    282: 
1.1.1.2   root      283:        Monitor monitor { this };
1.1       root      284: };
                    285: 
1.1.1.5   root      286: // LUNA-88K は sysctlr.cpp 参照。
1.1       root      287: 
1.1.1.5   root      288: static inline InterruptDevice *GetInterruptDevice() {
                    289:        return Object::GetObject<InterruptDevice>(OBJ_INTERRUPT);
                    290: }

unix.superglobalmegacorp.com

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