Annotation of nono/vm/interrupt.cpp, revision 1.1

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2020 nono project
        !             4: // Licensed under nono-license.txt
        !             5: //
        !             6: 
        !             7: #include "interrupt.h"
        !             8: #include "dmac.h"
        !             9: #include "lance.h"
        !            10: #include "pedec.h"
        !            11: #include "m68030.h"
        !            12: #include "mfp.h"
        !            13: #include "mpu680x0.h"
        !            14: #include "scc.h"
        !            15: #include "sio.h"
        !            16: #include "spc.h"
        !            17: #include "sysclk.h"
        !            18: 
        !            19: //                           IODevice
        !            20: //                              |
        !            21: //                              v
        !            22: //                       InterruptDevice
        !            23: //                              |
        !            24: //     +------------------------+-------------------------+
        !            25: //     |                        |                         |
        !            26: //     |                        v                         |
        !            27: //     |                  M680x0Interrupt                 |
        !            28: //     |                        |                         |
        !            29: //     |               +--------+--------+                |
        !            30: //     v               v                 v                v
        !            31: // PEDECDevice    X68030Interrupt    LunaInterrupt   SysCtlrDevice
        !            32: // (X68030のLv1   (X68030)           (LUNA-I)        (LUNA88K)
        !            33: //  カスケード)
        !            34: 
        !            35: std::unique_ptr<InterruptDevice> gInterrupt;
        !            36: 
        !            37: //
        !            38: // 仮想割り込みコントローラ (共通部)
        !            39: //
        !            40: 
        !            41: // コンストラクタ
        !            42: InterruptDevice::InterruptDevice()
        !            43: {
        !            44:        logname = "interrupt";
        !            45:        devname = "Interrupt";
        !            46: }
        !            47: 
        !            48: // デストラクタ
        !            49: InterruptDevice::~InterruptDevice()
        !            50: {
        !            51: }
        !            52: 
        !            53: 
        !            54: //
        !            55: // 仮想割り込みコントローラ (m680x0 共通部)
        !            56: //
        !            57: 
        !            58: // CPU コアからの割り込みアクノリッジを受け付けるグローバル関数
        !            59: int
        !            60: m68030_interrupt_acknowledge(int lv)
        !            61: {
        !            62:        return gInterrupt->InterruptAcknowledge(lv);
        !            63: }
        !            64: 
        !            65: // コンストラクタ
        !            66: M680x0Interrupt::M680x0Interrupt()
        !            67: {
        !            68: }
        !            69: 
        !            70: // デストラクタ
        !            71: M680x0Interrupt::~M680x0Interrupt()
        !            72: {
        !            73: }
        !            74: 
        !            75: // リセット
        !            76: void
        !            77: M680x0Interrupt::ResetHard()
        !            78: {
        !            79:        ipl = 0;
        !            80:        intmap = 0x00000001;
        !            81:        memset(&counter, 0, sizeof(counter));
        !            82: }
        !            83: 
        !            84: // 子デバイスが割り込み信号線をアサートした (m680x0 共通)
        !            85: void
        !            86: M680x0Interrupt::AssertINT(Device *source)
        !            87: {
        !            88:        uint32 oldmap;
        !            89:        uint32 srcmap;
        !            90:        int newipl;
        !            91: 
        !            92:        oldmap = intmap;
        !            93:        srcmap = GetIntmap(source);
        !            94:        intmap |= srcmap;
        !            95: 
        !            96:        if ((oldmap ^ intmap) != 0) {
        !            97:                // 立ち上がりエッジでカウント
        !            98:                counter[__builtin_clz(srcmap)]++;
        !            99:        }
        !           100: 
        !           101:        newipl = (uint)(31 - __builtin_clz(intmap)) / 4;
        !           102: 
        !           103:        // アサートによって割り込みレベルが上がったら、新しいレベルを通知
        !           104:        // (現在通知中より低い割り込みは受け付けただけでここで保留)
        !           105:        if (newipl > ipl) {
        !           106:                ipl = newipl;
        !           107:                gMPU->Interrupt(ipl);
        !           108:        }
        !           109: }
        !           110: 
        !           111: // 小デバイスが割り込み信号線をネゲートした (m680x0 共通)
        !           112: void
        !           113: M680x0Interrupt::NegateINT(Device *source)
        !           114: {
        !           115:        int newipl;
        !           116: 
        !           117:        intmap &= ~GetIntmap(source);
        !           118:        // intmap の最下位ビットは常に立ててあり intmap は 0 にならない
        !           119:        newipl = (uint)(31 - __builtin_clz(intmap)) / 4;
        !           120: 
        !           121:        // ネゲートによって割り込みレベルが下がったら、新しいレベルを通知
        !           122:        // (以前に保留されていた低いレベルがあればここで見えるようになる)
        !           123:        if (newipl < ipl) {
        !           124:                ipl = newipl;
        !           125:                gMPU->Interrupt(ipl);
        !           126:        }
        !           127: }
        !           128: 
        !           129: 
        !           130: //
        !           131: // X68030 仮想割り込みコントローラ
        !           132: //
        !           133: 
        !           134: // コンストラクタ
        !           135: X68030Interrupt::X68030Interrupt()
        !           136: {
        !           137:        monitor_size = nnSize(24, 6);
        !           138: }
        !           139: 
        !           140: // デストラクタ
        !           141: X68030Interrupt::~X68030Interrupt()
        !           142: {
        !           143: }
        !           144: 
        !           145: // デバイスから Intmap 値を引く
        !           146: uint32
        !           147: X68030Interrupt::GetIntmap(Device *source) const
        !           148: {
        !           149:        if (__predict_true(source == gMFP.get())) {
        !           150:                return IntmapMFP;
        !           151:        }
        !           152:        if (__predict_true(source == gSCC.get())) {
        !           153:                return IntmapSCC;
        !           154:        }
        !           155:        if (__predict_true(source == gDMAC.get())) {
        !           156:                return IntmapDMAC;
        !           157:        }
        !           158:        if (__predict_true(source == gPEDEC.get())) {
        !           159:                return IntmapPEDEC;
        !           160:        }
        !           161:        if (source == NULL) {
        !           162:                // XXX デバイスまだいないのでとりあえず
        !           163:                return IntmapNMI;
        !           164:        }
        !           165:        PANIC("Unknown interrupt source?");
        !           166: }
        !           167: 
        !           168: // 割り込みアクノリッジに応答する
        !           169: int
        !           170: X68030Interrupt::InterruptAcknowledge(int lv)
        !           171: {
        !           172:        switch (lv) {
        !           173:         case 6:
        !           174:                return gMFP->InterruptAcknowledge();
        !           175: 
        !           176:         case 5:
        !           177:                return gSCC->InterruptAcknowledge();
        !           178: 
        !           179:         case 3:
        !           180:                return gDMAC->InterruptAcknowledge();
        !           181: 
        !           182:         case 1:
        !           183:                return gPEDEC->InterruptAcknowledge(lv);
        !           184: 
        !           185:         default:
        !           186:                break;
        !           187:        }
        !           188:        PANIC("Unknown interrupt acknowledge lv=%d", lv);
        !           189: }
        !           190: 
        !           191: void
        !           192: X68030Interrupt::MonitorUpdate(TextScreen& monitor)
        !           193: {
        !           194:        int y;
        !           195:        struct {
        !           196:                const char *name;
        !           197:                uint32 map;
        !           198:        } table[] = {
        !           199:                { "NMI",        IntmapNMI },
        !           200:                { "MFP",        IntmapMFP },
        !           201:                { "SCC",        IntmapSCC },
        !           202:                { "DMAC",       IntmapDMAC },
        !           203:                { "PEDEC",      IntmapPEDEC },
        !           204:        };
        !           205: 
        !           206:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
        !           207:        uint intr_level = gMPU680x0->GetCPU()->reg.intr_level;
        !           208: 
        !           209:        monitor.Clear();
        !           210: 
        !           211:        y = 0;
        !           212:        monitor.Print(0, y++, "Lv Device    Count  IM=%d", intr_level);
        !           213:        for (int i = 0; i < countof(table); i++) {
        !           214:                uint32 map = table[i].map;
        !           215:                int clz = __builtin_clz(map);
        !           216:                int lv = (31 - clz) / 4;
        !           217:                monitor.Print(0, y, "%d", lv);
        !           218:                monitor.Print(2, y, TA::OnOff(intmap & map), "%s", table[i].name);
        !           219:                monitor.Print(8, y, "%10u", counter[clz]);
        !           220:                if (lv <= intr_level) {
        !           221:                        monitor.Puts(20, y, "Mask");
        !           222:                }
        !           223:                y++;
        !           224:        }
        !           225:        // XXX PEDEC 分もここに表示したい
        !           226: }
        !           227: 
        !           228: //
        !           229: // LUNA-I 仮想割り込みコントローラ
        !           230: //
        !           231: 
        !           232: // コンストラクタ
        !           233: LunaInterrupt::LunaInterrupt()
        !           234: {
        !           235:        monitor_size = nnSize(24, 5);
        !           236: }
        !           237: 
        !           238: // デストラクタ
        !           239: LunaInterrupt::~LunaInterrupt()
        !           240: {
        !           241: }
        !           242: 
        !           243: 
        !           244: // デバイスから Intmap 値を引く
        !           245: uint32
        !           246: LunaInterrupt::GetIntmap(Device *source) const
        !           247: {
        !           248:        if (__predict_true(source == gSIO.get())) {
        !           249:                return IntmapSIO;
        !           250:        }
        !           251:        if (__predict_true(source == gSysClk.get())) {
        !           252:                return IntmapSysClk;
        !           253:        }
        !           254:        if (__predict_true(source == gEthernet.get())) {
        !           255:                return IntmapLance;
        !           256:        }
        !           257:        if (__predict_true(source == gSPC.get())) {
        !           258:                return IntmapSPC;
        !           259:        }
        !           260:        PANIC("Unknown interrupt source?");
        !           261: }
        !           262: 
        !           263: // 割り込みアクノリッジに応答する
        !           264: int
        !           265: LunaInterrupt::InterruptAcknowledge(int lv)
        !           266: {
        !           267:        // LUNA は全てオートベクタ
        !           268:        return AutoVector;
        !           269: }
        !           270: 
        !           271: void
        !           272: LunaInterrupt::MonitorUpdate(TextScreen& monitor)
        !           273: {
        !           274:        int y;
        !           275:        struct {
        !           276:                const char *name;
        !           277:                uint32 map;
        !           278:        } table[] = {
        !           279:                { "SIO",        IntmapSIO },
        !           280:                { "Clock",      IntmapSysClk },
        !           281:                { "Lance",      IntmapLance },
        !           282:                { "SPC",        IntmapSPC },
        !           283:        };
        !           284: 
        !           285:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
        !           286:        uint intr_level = gMPU680x0->GetCPU()->reg.intr_level;
        !           287: 
        !           288:        monitor.Clear();
        !           289: 
        !           290:        y = 0;
        !           291:        monitor.Print(0, y++, "Lv Device    Count  IM=%d", intr_level);
        !           292:        for (int i = 0; i < countof(table); i++) {
        !           293:                uint32 map = table[i].map;
        !           294:                int clz = __builtin_clz(map);
        !           295:                int lv = (31 - clz) / 4;
        !           296:                monitor.Print(0, y, "%d", lv);
        !           297:                monitor.Print(2, y, TA::OnOff(intmap & map), "%s", table[i].name);
        !           298:                monitor.Print(8, y, "%10u", counter[clz]);
        !           299:                if (lv <= intr_level) {
        !           300:                        monitor.Puts(20, y, "Mask");
        !           301:                }
        !           302:                y++;
        !           303:        }
        !           304: }

unix.superglobalmegacorp.com

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