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

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

unix.superglobalmegacorp.com

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