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

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

unix.superglobalmegacorp.com

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