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

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

unix.superglobalmegacorp.com

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