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

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2024 nono project
        !             4: // Licensed under nono-license.txt
        !             5: //
        !             6: 
        !             7: //
        !             8: // Goldfish 割り込みコントローラ
        !             9: //
        !            10: 
        !            11: // 32本の独立した割り込みソースを持ち、独立してマスクできるコントローラ。
        !            12: // オリジナルの Google のドキュメントは用語がひどすぎてアレ。
        !            13: //
        !            14: // レジスタ仕様は次の通り。
        !            15: //  +$00.L STATUS              R-: ペンディングしている割り込み数 (0-32)。
        !            16: //  +$04.L PENDING             R-: 最も優先度の高いペンディング割り込み取得。
        !            17: //  +$08.L CLEAR_ALL   -W: 割り込みペンディングをすべてクリアする。
        !            18: //  +$0c.L DISABLE             -W: 指定の割り込みを無効にする。
        !            19: //  +$10.L ENABLE              -W: 指定の割り込みを有効にする。
        !            20: //
        !            21: // bit0 (IRQ1) なら $00000001、bit31 (IRQ32) なら $80000000 で、
        !            22: // IRQ1 側 (LSB 側) が優先度が高い。
        !            23: //
        !            24: // PENDING は最も優先度の高いペンディングのビットを(たぶん1つ)返す。
        !            25: // ペンディング割り込みがなければ 0 を返す。
        !            26: //
        !            27: // CLEAR_ALL はすべての割り込みソース (ENABLE されていないものも含む)
        !            28: // のレベルを low に落とす。enable 状態は変えない。
        !            29: //
        !            30: // ENABLE/DISABLE は指定したビット位置の割り込みを有効/無効にする。
        !            31: //
        !            32: // PENDING/ENABLE/DISABLE はいずれも
        !            33: //
        !            34: // nono では intmap の構造を流用するがここではレベル判定が不要なので、
        !            35: // Goldfish の仕様通り 32ビットすべてで割り込みを受け付ける。
        !            36: //
        !            37: // ここまでが単体の Goldfish 割り込みコントローラの仕様で、このコントローラ
        !            38: // にはレベルの概念はないので m68k で使う場合はこれを Lv1 から Lv6 までの
        !            39: // 6個用意して、各自目的のレベルのコントローラに配線するという仕組み。
        !            40: //
        !            41: // MPU <--- Virt68kInterrupt <-+- GFPICDevice(Lv6)
        !            42: //                             +- GFPICDevice(Lv5)
        !            43: //                             +- GFPICDevice(Lv4)
        !            44: //                             +- GFPICDevice(Lv3)
        !            45: //                             +- GFPICDevice(Lv2)
        !            46: //                             +- GFPICDevice(Lv1)
        !            47: 
        !            48: #include "goldfish_pic.h"
        !            49: #include <algorithm>
        !            50: 
        !            51: // コンストラクタ
        !            52: GFPICDevice::GFPICDevice(int id_)
        !            53:        : inherited(OBJ_GFPIC(id_))
        !            54: {
        !            55: }
        !            56: 
        !            57: // デストラクタ
        !            58: GFPICDevice::~GFPICDevice()
        !            59: {
        !            60: }
        !            61: 
        !            62: // 初期化
        !            63: bool
        !            64: GFPICDevice::Init()
        !            65: {
        !            66:        if (inherited::Init() == false) {
        !            67:                return false;
        !            68:        }
        !            69: 
        !            70:        interrupt = GetInterruptDevice();
        !            71: 
        !            72:        return true;
        !            73: }
        !            74: 
        !            75: // 電源オン/リセット
        !            76: void
        !            77: GFPICDevice::ResetHard(bool poweron)
        !            78: {
        !            79:        intmap_enable = 0;
        !            80:        ChangeInterrupt();
        !            81: }
        !            82: 
        !            83: busdata
        !            84: GFPICDevice::Read32(uint32 addr)
        !            85: {
        !            86:        uint32 offset = addr & 0xfff;
        !            87:        busdata data;
        !            88: 
        !            89:        switch (offset) {
        !            90:         case STATUS:
        !            91:                data = __builtin_popcount(intmap_status);
        !            92:                putlog(2, "STATUS -> $%08x", data.Data());
        !            93:                break;
        !            94: 
        !            95:         case PENDING:
        !            96:                // 一番下の立っているビットだけにして返す。
        !            97:                data = intmap_status & -intmap_status;
        !            98:                putlog(2, "PENDING -> $%08x", data.Data());
        !            99:                break;
        !           100: 
        !           101:         default:
        !           102:                data.SetBusErr();
        !           103:                break;
        !           104:        }
        !           105: 
        !           106:        return data;
        !           107: }
        !           108: 
        !           109: busdata
        !           110: GFPICDevice::Write32(uint32 addr, uint32 data)
        !           111: {
        !           112:        uint32 offset = addr & 0xfff;
        !           113:        busdata r;
        !           114: 
        !           115:        switch (offset) {
        !           116:         case CLEAR_ALL:
        !           117:                putlog(1, "CLEAR_ALL");
        !           118:                intmap_status = 0;
        !           119:                ChangeInterrupt();
        !           120:                break;
        !           121: 
        !           122:         case DISABLE:
        !           123:                putlog(1, "DISABLE $%08x", data);
        !           124:                intmap_enable &= ~data;
        !           125:                break;
        !           126: 
        !           127:         case ENABLE:
        !           128:                putlog(1, "ENABLE  $%08x", data);
        !           129:                intmap_enable |= data;
        !           130:                break;
        !           131: 
        !           132:         default:
        !           133:                r.SetBusErr();
        !           134:                break;
        !           135:        }
        !           136:        return r;
        !           137: }
        !           138: 
        !           139: busdata
        !           140: GFPICDevice::Peek8(uint32 addr)
        !           141: {
        !           142:        return busdata::BusErr;
        !           143: }
        !           144: 
        !           145: // Virt68kInterrupt の下請け。上のサマリ部分。
        !           146: void
        !           147: GFPICDevice::MonitorUpdateSummary(TextScreen& screen, int x, int y)
        !           148: {
        !           149:        for (int i = 0; i < 32; i++) {
        !           150:                uint32 bit = 0x8000'0000 >> i;
        !           151:                if ((intmap_avail & bit) != 0) {
        !           152:                        bool status = (intmap_status & bit);
        !           153:                        bool enable = (intmap_enable & bit);
        !           154:                        screen.Putc(x, y, TA::OnOff(status), (enable ? 'E' : 'D'));
        !           155:                } else {
        !           156:                        screen.Putc(x, y, '.');
        !           157:                }
        !           158:                x++;
        !           159:                if ((i % 8) == 7) {
        !           160:                        x++;
        !           161:                }
        !           162:        }
        !           163: }
        !           164: 
        !           165: // Virt68kInterrupt の下請け。下の個別部分。
        !           166: int
        !           167: GFPICDevice::MonitorUpdateDetail(TextScreen& screen, int y, int lv)
        !           168: {
        !           169: // 0         1         2         3         4         5         6         7
        !           170: // 01234567890123456789012345678901234567890123456789012345678901234567890123456
        !           171: // Lv Device IM=7 IRQ         20         10         1                      Count
        !           172: // 1  GFPIC1 Mask 21098765 43210987 65432109 87654321 01234567890123456789012345
        !           173: //
        !           174: // GFPIC1 IRQ22 XXXXX                                 01234567890123456789012345
        !           175: 
        !           176:        for (auto intmap : disp_list) {
        !           177:                int clz = __builtin_clz(intmap);
        !           178:                int irq = 32 - clz;
        !           179:                const char *name = GetIntName(intmap);
        !           180: 
        !           181:                screen.Print(0, y, "GFPIC%d IRQ%2d", lv, irq);
        !           182:                screen.Puts(13, y, TA::OnOff(intmap_status & intmap), name);
        !           183:                screen.Print(51, y, "%26s", format_number(counter[clz]).c_str());
        !           184:                y++;
        !           185:        }
        !           186: 
        !           187:        return y;
        !           188: }
        !           189: 
        !           190: busdata
        !           191: GFPICDevice::InterruptAcknowledge(int lv)
        !           192: {
        !           193:        // たぶん何もしない。
        !           194:        return 0;
        !           195: }
        !           196: 
        !           197: // 割り込み信号線の状態を変える
        !           198: void
        !           199: GFPICDevice::ChangeInterrupt()
        !           200: {
        !           201:        bool irq = (intmap_enable & intmap_status);
        !           202:        interrupt->ChangeINT(this, irq);
        !           203: }
        !           204: 
        !           205: // この PIC に IRQ を登録する。
        !           206: // ここだけ子デバイスが自発的に登録を行う方式。
        !           207: // irq は 1-32。
        !           208: void
        !           209: GFPICDevice::RegistIRQ(int irq, const char *name, Device *source)
        !           210: {
        !           211:        uint32 intmap = 1U << (irq - 1);
        !           212: 
        !           213:        assertmsg((intmap_avail & intmap) == 0, "IRQ=%d already registered", irq);
        !           214: 
        !           215:        RegistINT(intmap, name, source);
        !           216: 
        !           217:        // 表示順は IRQ01 -> IRQ32
        !           218:        disp_list.push_back(intmap);
        !           219:        std::sort(disp_list.begin(), disp_list.end());
        !           220: 
        !           221:        // ここで親の Virt68kInterrupt のモニタ行数を増やす。
        !           222:        // 本当は登録がすべて終わった頃に Virt68kInterrupt から各 GFPIC
        !           223:        // に問い合わせたいが、どちらも Init() での処理であり、オブジェクトの
        !           224:        // 依存関係から無理なので、こっちから都度プッシュする。
        !           225:        auto virt68kinterrupt = dynamic_cast<Virt68kInterrupt*>(interrupt);
        !           226:        virt68kinterrupt->IncMonitorHeight();
        !           227: }

unix.superglobalmegacorp.com

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