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

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.1.7 ! root       16: #include <vector>
1.1       root       17: 
1.1.1.5   root       18: // XP からの割り込み用。
                     19: // これだけ1デバイスで2本あるので、仕方なく識別子を用意。
                     20: #define DEVICE_XPINT_HIGH      ((Device *)(intptr_t)1)
                     21: #define DEVICE_XPINT_LOW       ((Device *)(intptr_t)2)
                     22: 
                     23: class DMACDevice;
1.1.1.7 ! root       24: class GFPICDevice;
1.1.1.5   root       25: class MFPDevice;
1.1.1.7 ! root       26: class MPU680x0Device;
1.1.1.5   root       27: class NMIDevice;
                     28: class PEDECDevice;
1.1.1.6   root       29: class RTL8019ASDevice;
1.1.1.5   root       30: class SCCDevice;
                     31: class SPCDevice;
                     32: 
1.1.1.4   root       33: // 割り込みを受け付けるデバイス。
1.1       root       34: // これ自体は IODevice である必要はないが、PEDEC や SysCtlr がこれを
                     35: // 継承するため。
                     36: class InterruptDevice : public IODevice
                     37: {
                     38:        using inherited = IODevice;
1.1.1.7 ! root       39: 
        !            40:        // intmap と名前の紐付け
        !            41:        struct mapname {
        !            42:                uint32 intmap {};
        !            43:                const char *name {};
        !            44:                Device *source {};
        !            45: 
        !            46:                mapname(uint32 intmap_, const char *name_, Device *source_) {
        !            47:                        intmap = intmap_;
        !            48:                        name = name_;
        !            49:                        source = source_;
        !            50:                }
        !            51:        };
        !            52: 
1.1       root       53:  public:
                     54:        InterruptDevice();
1.1.1.5   root       55:        InterruptDevice(int objid_);
1.1.1.7 ! root       56:        ~InterruptDevice() override;
1.1       root       57: 
1.1.1.7 ! root       58:        // リセットで割り込みを下げるのは各割り込み送出デバイスの責任。
1.1.1.4   root       59:        void ResetHard(bool poweron) override;
1.1       root       60: 
                     61:        // AssertINT()、NegateINT()、ChangeINT() の呼び出し側は、
                     62:        // (アサート中に AssertINT() を呼ぶというような) 現在の状態が
                     63:        // 変わらないような呼び出しをしても構わない。特に副作用はない。
                     64: 
                     65:        // 子デバイスが割り込み信号線をアサートした
1.1.1.3   root       66:        void AssertINT(Device *source);
1.1       root       67:        // 子デバイスが割り込み信号線をネゲートした
1.1.1.3   root       68:        void NegateINT(Device *source);
1.1       root       69: 
                     70:        // 子デバイスが割り込み信号線を val の状態に変えた。
                     71:        // true ならアサート、false ならネゲート。
                     72:        void ChangeINT(Device *source, bool val) {
                     73:                if (val) {
                     74:                        AssertINT(source);
                     75:                } else {
                     76:                        NegateINT(source);
                     77:                }
                     78:        }
                     79: 
                     80:        // MPU からの割り込みアクノリッジに応答する
1.1.1.7 ! root       81:        virtual busdata InterruptAcknowledge(int lv) = 0;
1.1.1.3   root       82: 
1.1.1.6   root       83:        // 割り込み信号線の状態を取得する
                     84:        bool GetINT(const Device *source) const;
                     85: 
1.1.1.3   root       86:  protected:
                     87:        // 割り込みを上位デバイス(MPUなど)に伝達する。
                     88:        // 子デバイスが割り込み信号線の状態を変えたときに呼び出される。
                     89:        virtual void ChangeInterrupt() = 0;
                     90: 
                     91:        // Intmap について
                     92:        //
                     93:        // Intmap は 32bit のビットマップ値で、最大 31 個(といいつつ今の所 28 個)
                     94:        // の割り込み発生の有無を個別に管理できる。
                     95:        // 発生している割り込みのうち最も優先度が高い 1つを高速に検索するため、
                     96:        // MSB 側を最も優先度が高い割り込みとして、Count-Leading-Zero で検索
                     97:        // することにする。
                     98:        // __builtin_clz(0) は動作未定義になるので、最下位ビットを常に立てて
                     99:        // おくことで、割り込みなし(上位31bitがすべて0)の場合でもこの式が使える
                    100:        // ようにしておく。
                    101:        //
                    102:        // 具体的にどの割り込みをどのビットに割り当てるかは継承先の実装によるが、
                    103:        // m680x0 の場合、以下のように 1レベル 4つずつ割り当てることにする。
                    104:        //
                    105:        //    3                   2                   1                   0
                    106:        //  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
                    107:        // +-------+-------+-------+-------+-------+-------+-------+-------+
                    108:        // |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 |
                    109:        // +-------+-------+-------+-------+-------+-------+-------+-------+
                    110:        //
                    111:        // これにより同一レベルのデバイス 4 つまでの割り込み信号線の状態を独立
                    112:        // して保持しつつ、アサートされている信号線のうち最もレベルの高いものは
                    113:        // 以下だけで求めることが出来る。
                    114:        //
1.1.1.7 ! root      115:        //  ipl = (31 - __builtin_clz(intmap_status)) / 4;
1.1.1.3   root      116:        //
1.1.1.5   root      117:        // LUNA-88K の外部割り込みコントローラであるシステムコントローラも
1.1.1.3   root      118:        // 概ねこれに近いので、sysctlr もこの構造を使う。
                    119:        //
                    120:        // PEDEC は 7レベル分けする必要ないので、適当に割り当ててある。
1.1.1.7 ! root      121:        //
        !           122:        // Goldfish PIC は 7レベル分け不要なのと 32ビット必要そうなので、
        !           123:        // 番兵を使わず 32ビット全域を使う。
        !           124:        // また元の仕様が LSB 側から数えるスタイルなのでここでもそれに従う。
1.1.1.3   root      125: 
                    126:        static const uint32 IntmapSentinel = 0x00000001;
                    127: 
1.1.1.7 ! root      128:        // 割り込みソースを登録する。
        !           129:        void RegistINT(uint32 intmap_, const char *name_, Device *source_);
        !           130: 
1.1.1.3   root      131:        // デバイスから Intmap 値を引く。
1.1.1.7 ! root      132:        uint32 GetIntmap(const Device *source) const;
        !           133: 
        !           134:        // Intmap 値から名前を引く。
        !           135:        const char *GetIntName(uint32 intmap_) const;
        !           136: 
        !           137:        // 割り込みソース一覧 (概ね使用頻度の高い順)
        !           138:        std::vector<mapname> intmap_list {};
        !           139: 
        !           140:        // モニタでの表示順 (概ね優先度の高い順)
        !           141:        std::vector<uint32> disp_list {};
        !           142: 
        !           143:        // 割り込みソースが存在するところは %1
        !           144:        uint32 intmap_avail {};
        !           145: 
        !           146:        // 割り込み状態 (各 %1 ならアサート)
        !           147:        uint32 intmap_status {};
1.1.1.3   root      148: 
1.1.1.7 ! root      149:        // (必要なら) 割り込みマスク (各 %1 なら有効)
        !           150:        // 割り込みマスク機能を持ってない人は使わなくてもよい。
        !           151:        uint32 intmap_enable {};
1.1.1.3   root      152: 
                    153:        // 割り込み回数 (アサートのエッジでカウントアップする)
                    154:        // [0]  が Intmap の bit31 割り込みのカウント。
                    155:        // [27] が Intmap の bit 4 割り込みのカウント。
1.1.1.7 ! root      156:        uint64 counter[32] {};
1.1       root      157: };
                    158: 
                    159: // m680x0 仮想割り込みコントローラ (共通部)
                    160: class M680x0Interrupt : public InterruptDevice
                    161: {
                    162:        using inherited = InterruptDevice;
1.1.1.7 ! root      163: 
1.1       root      164:  public:
1.1.1.7 ! root      165:        // 割り込みアクノリッジの特殊値。
        !           166:        static const uint32 AutoVector  = -1;   // オートベクタ要求
1.1       root      167: 
                    168:  public:
                    169:        M680x0Interrupt();
1.1.1.7 ! root      170:        ~M680x0Interrupt() override;
1.1       root      171: 
1.1.1.5   root      172:        bool Init() override;
1.1.1.4   root      173:        void ResetHard(bool poweron) override;
1.1       root      174: 
                    175:  protected:
1.1.1.3   root      176:        void ChangeInterrupt() override;
1.1       root      177: 
                    178:        // 現在の割り込みレベル
                    179:        int ipl {};
1.1.1.7 ! root      180: 
        !           181:        MPU680x0Device *mpu680x0 {};
1.1       root      182: };
                    183: 
                    184: // X68k 仮想割り込みコントローラ
                    185: //
                    186: // Level
                    187: //  7    INTERRUPT スイッチ
                    188: //  6    MFP
                    189: //  5    SCC
                    190: //  4    (拡張ボード)
                    191: //  3    DMAC
                    192: //  2    (拡張ボード)
                    193: //  1    PEDEC   <--+-- SPC
                    194: //                  +-- HDD (SASI)
                    195: //                  +-- FDC
                    196: //                  +-- FDD
                    197: //                  +-- PRN
                    198: //
                    199: class X68030Interrupt : public M680x0Interrupt
                    200: {
                    201:        using inherited = M680x0Interrupt;
                    202: 
                    203:        // 割り込みマップ                            76543210
                    204:        static const uint32 IntmapNMI           = 0x80000000;
                    205:        static const uint32 IntmapMFP           = 0x08000000;
                    206:        static const uint32 IntmapSCC           = 0x00800000;
1.1.1.6   root      207:        static const uint32 IntmapNereid0       = 0x00080000;
                    208:        static const uint32 IntmapNereid1       = 0x00040000;
1.1       root      209:        static const uint32 IntmapDMAC          = 0x00008000;
                    210:        static const uint32 IntmapPEDEC         = 0x00000080;
                    211: 
                    212:  public:
                    213:        X68030Interrupt();
1.1.1.7 ! root      214:        ~X68030Interrupt() override;
1.1       root      215: 
1.1.1.5   root      216:        bool Init() override;
1.1.1.7 ! root      217:        busdata InterruptAcknowledge(int lv) override;
1.1       root      218: 
                    219:  private:
1.1.1.2   root      220:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
                    221: 
1.1.1.5   root      222:        DMACDevice *dmac {};
                    223:        MFPDevice *mfp {};
                    224:        NMIDevice *nmi {};
                    225:        PEDECDevice *pedec {};
1.1.1.6   root      226:        std::array<RTL8019ASDevice *, 2> net {};
1.1.1.5   root      227:        SCCDevice *scc {};
                    228: 
1.1.1.2   root      229:        Monitor monitor { this };
1.1       root      230: };
                    231: 
                    232: // LUNA-I 仮想割り込みコントローラ
                    233: //
                    234: // Level
                    235: //  7
                    236: //  6    SIO
                    237: //  5    SystemClock
                    238: //  4     (XP high)
                    239: //  3    Lance
                    240: //  2    SPC
                    241: //  1     (XP low)
                    242: //
                    243: class LunaInterrupt : public M680x0Interrupt
                    244: {
                    245:        using inherited = M680x0Interrupt;
                    246: 
                    247:        // 割り込みマップ                            76543210
1.1.1.4   root      248:        static const uint32 IntmapNMI           = 0x80000000;
1.1       root      249:        static const uint32 IntmapSIO           = 0x08000000;
                    250:        static const uint32 IntmapSysClk        = 0x00800000;
1.1.1.5   root      251:        static const uint32 IntmapXPHigh        = 0x00400000;
1.1       root      252:        static const uint32 IntmapLance         = 0x00008000;
                    253:        static const uint32 IntmapSPC           = 0x00000800;
1.1.1.5   root      254:        static const uint32 IntmapXPLow         = 0x00000080;
1.1       root      255: 
                    256:  public:
                    257:        LunaInterrupt();
1.1.1.7 ! root      258:        ~LunaInterrupt() override;
1.1       root      259: 
1.1.1.5   root      260:        bool Init() override;
1.1.1.7 ! root      261:        busdata InterruptAcknowledge(int lv) override;
1.1.1.5   root      262: 
                    263:  private:
                    264:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
                    265: 
                    266:        Monitor monitor { this };
                    267: };
                    268: 
                    269: // NEWS 仮想割り込みコントローラ
                    270: //
                    271: // Level
                    272: //  7
                    273: //  6    Timer
                    274: //  5    SCC(vectored)
                    275: //  4    SIC, Lance
                    276: //  3
                    277: //  2
                    278: //  1
                    279: //
                    280: class NewsInterrupt : public M680x0Interrupt
                    281: {
                    282:        using inherited = M680x0Interrupt;
                    283: 
                    284:        // 割り込みマップ                            76543210
                    285:        static const uint32 IntmapNMI           = 0x80000000;
                    286:        static const uint32 IntmapTimer         = 0x08000000;
                    287:        static const uint32 IntmapSCC           = 0x00800000;
                    288:        static const uint32 IntmapSIC           = 0x00080000;
                    289:        static const uint32 IntmapLance         = 0x00040000;
                    290: 
                    291:  public:
                    292:        NewsInterrupt();
1.1.1.7 ! root      293:        ~NewsInterrupt() override;
1.1.1.5   root      294: 
                    295:        bool Init() override;
1.1.1.7 ! root      296:        busdata InterruptAcknowledge(int lv) override;
1.1       root      297: 
1.1.1.5   root      298:        // 割り込みステータスを返す (NewsCtlr から呼ばれる)
                    299:        uint8 PeekStatus() const;
                    300: 
1.1       root      301:  private:
1.1.1.2   root      302:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
                    303: 
1.1.1.5   root      304:        SCCDevice *scc {};
                    305: 
1.1.1.2   root      306:        Monitor monitor { this };
1.1       root      307: };
                    308: 
1.1.1.7 ! root      309: // virt68k 仮想割り込みコントローラ
        !           310: //
        !           311: // Level
        !           312: //  7
        !           313: //  6    GFPIC6
        !           314: //  5    GFPIC5
        !           315: //  4    GFPIC4
        !           316: //  3    GFPIC3
        !           317: //  2    GFPIC2
        !           318: //  1    GFPIC1
        !           319: //
        !           320: class Virt68kInterrupt : public M680x0Interrupt
        !           321: {
        !           322:        using inherited = M680x0Interrupt;
        !           323: 
        !           324:        // 割り込みマップ                            76543210
        !           325:        static const uint32 IntmapGFPIC6        = 0x08000000;
        !           326:        static const uint32 IntmapGFPIC5        = 0x00800000;
        !           327:        static const uint32 IntmapGFPIC4        = 0x00080000;
        !           328:        static const uint32 IntmapGFPIC3        = 0x00008000;
        !           329:        static const uint32 IntmapGFPIC2        = 0x00000800;
        !           330:        static const uint32 IntmapGFPIC1        = 0x00000080;
        !           331: 
        !           332:  public:
        !           333:        Virt68kInterrupt();
        !           334:        ~Virt68kInterrupt() override;
        !           335: 
        !           336:        bool Init() override;
        !           337:        busdata InterruptAcknowledge(int lv) override;
        !           338: 
        !           339:        // モニタを1行増やす。割り込みソース登録ごとに GFPIC から呼ばれる。
        !           340:        void IncMonitorHeight();
        !           341: 
        !           342:  private:
        !           343:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
        !           344: 
        !           345:        std::array<GFPICDevice *, 7> gfpic {};
        !           346: 
        !           347:        Monitor monitor { this };
        !           348: };
        !           349: 
1.1.1.5   root      350: // LUNA-88K は sysctlr.cpp 参照。
1.1       root      351: 
1.1.1.5   root      352: static inline InterruptDevice *GetInterruptDevice() {
                    353:        return Object::GetObject<InterruptDevice>(OBJ_INTERRUPT);
                    354: }

unix.superglobalmegacorp.com

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