Annotation of nono/vm/pluto.cpp, revision 1.1.1.9

1.1       root        1: //
                      2: // nono
1.1.1.3   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.8   root        7: //
                      8: // Pluto-X (独自の仮想ボード)
                      9: //
                     10: 
1.1       root       11: #include "pluto.h"
1.1.1.2   root       12: #include "mainapp.h"
1.1.1.9 ! root       13: #include "mainbus.h"
        !            14: #include "mainram.h"
1.1.1.3   root       15: #include "mpu680x0.h"
1.1.1.9 ! root       16: #include "sram.h"
1.1.1.5   root       17: 
1.1.1.8   root       18: // コンストラクタ
1.1       root       19: PlutoDevice::PlutoDevice()
1.1.1.9 ! root       20:        : inherited(OBJ_PLUTO)
1.1       root       21: {
                     22: }
                     23: 
1.1.1.8   root       24: // デストラクタ
1.1       root       25: PlutoDevice::~PlutoDevice()
                     26: {
                     27: }
                     28: 
1.1.1.8   root       29: // リセット
1.1.1.4   root       30: void
1.1.1.8   root       31: PlutoDevice::ResetHard(bool poweron)
1.1.1.4   root       32: {
                     33:        // XXX not yet
                     34:        m_count = 0;
                     35: }
                     36: 
1.1.1.3   root       37: // ROM
                     38: /*static*/ const uint16
                     39: PlutoDevice::rom[] = {
                     40:        // ホストファイル起動
                     41:        0x00ea, 0xc004,                 //      .dc.l   _start  ; 起動アドレス
                     42:                                                        //_start:
1.1.1.9 ! root       43:        0x46fc, 0x2700,                 //      move.w  #0x2700,%sr
1.1.1.3   root       44:        0x2039, 0x00ea, 0xc450, //      move.l  (ROMIO_LOAD),%d0
1.1.1.9 ! root       45:        0x6b04,                                 //      bmi.s   _err
        !            46:        0x2040,                                 //      move.l  %d0,%a0
        !            47:        0x4e90,                                 //      jsr             (%a0)
1.1.1.3   root       48:                                                        //_err:
                     49:        0x43fa, 0x000c,                 //      lea.l   (_errmsg),%a1
                     50:        0x7021, 0x4e4f,                 //      IOCS    B_PRINT
                     51:                                                        //_loop:
                     52:        0x4e72, 0x2600,                 //      stop    #0x2600
                     53:        0x60fa,                                 //      bra.s   _loop
                     54:                                                        //_errmsg:
                     55:        0x2a2a, 0x2043, 0x616e, //      .dc.b   "** Can"
                     56:        0x6e6f, 0x7420, 0x6c6f, //      .dc.b   "not lo"
                     57:        0x6164, 0x2068, 0x6f73, //      .dc.b   "ad hos"
                     58:        0x7420, 0x6669, 0x6c65, //      .dc.b   "t file"
                     59:        0x2e00,                                 //      .dc.b   ".",0
                     60: };
                     61: 
                     62: uint64
                     63: PlutoDevice::Read8(uint32 addr)
                     64: {
1.1.1.9 ! root       65:        uint32 offset = addr - baseaddr;
1.1.1.3   root       66:        uint32 data;
                     67: 
                     68:        if (offset < sizeof(rom)) {
                     69:                data = rom[offset / 2];
                     70:                if ((offset & 1) == 0) {
                     71:                        return data >> 8;
                     72:                } else {
                     73:                        return data & 0xff;
                     74:                }
                     75:        }
                     76: 
                     77:        return (uint64)-1;
                     78: }
                     79: 
                     80: uint64
                     81: PlutoDevice::Read16(uint32 addr)
                     82: {
1.1.1.9 ! root       83:        uint32 offset = addr - baseaddr;
1.1.1.3   root       84: 
                     85:        if (offset < sizeof(rom)) {
                     86:                return rom[offset / 2];
                     87:        }
                     88: 
                     89:        return (uint64)-1;
                     90: }
                     91: 
                     92: uint64
                     93: PlutoDevice::Read32(uint32 addr)
                     94: {
1.1.1.9 ! root       95:        uint32 offset = addr - baseaddr;
1.1.1.3   root       96:        uint32 data;
                     97: 
                     98:        if (offset < sizeof(rom)) {
                     99:                data = rom[offset / 2] << 16;
                    100:                data |= rom[(offset / 2) + 1];
                    101:                return data;
                    102:        }
                    103:        switch (offset) {
                    104:         case 0x450:    // ROMIO_LOAD
                    105:                return ROM_Load();
                    106: 
                    107:         default:
                    108:                break;
                    109:        }
                    110:        return (uint64)-1;
                    111: }
                    112: 
                    113: uint64
                    114: PlutoDevice::Write8(uint32 addr, uint32 data)
                    115: {
                    116:        switch (addr) {
                    117:         case 0xeac403:
                    118:                write_8_benchmark(addr, data);
                    119:                break;
                    120:         default:
                    121:                break;
                    122:        }
                    123:        putlog(0, "未実装バイト書き込み $%06x", addr);
                    124:        return 0;
                    125: }
                    126: 
                    127: uint64
                    128: PlutoDevice::Write16(uint32 addr, uint32 data)
                    129: {
                    130:        putlog(0, "未実装ワード書き込み $%06x", addr);
                    131:        return 0;
                    132: }
                    133: 
                    134: uint64
                    135: PlutoDevice::Peek8(uint32 addr)
                    136: {
1.1.1.9 ! root      137:        uint32 offset = addr - baseaddr;
1.1.1.3   root      138:        uint32 data;
                    139: 
                    140:        if (offset < sizeof(rom)) {
                    141:                data = rom[offset / 2];
                    142:                if ((offset & 1) == 0) {
                    143:                        return data >> 8;
                    144:                } else {
                    145:                        return data & 0xff;
                    146:                }
                    147:        }
                    148: 
                    149:        return (uint64)-1;
                    150: }
                    151: 
                    152: //
                    153: // ホストファイル起動
                    154: //
                    155: 
1.1.1.7   root      156: // -X オプションで指定されたホストファイルをロードする。
1.1.1.3   root      157: // ロードできればエントリポイントを返す。
1.1.1.7   root      158: // exec_file が指定されている時に呼ぶこと。
1.1.1.3   root      159: uint32
                    160: PlutoDevice::ROM_Load()
                    161: {
1.1.1.7   root      162:        assert(gMainApp.exec_file);
1.1.1.3   root      163: 
1.1.1.9 ! root      164:        auto mainbus = GetMainbusDevice();
        !           165:        auto mainram = GetMainRAMDevice();
        !           166:        auto mpu680x0 = GetMPU680x0Device();
        !           167:        auto sram = GetSRAMDevice();
        !           168: 
1.1.1.3   root      169:        // ホストファイルをロード
1.1.1.9 ! root      170:        LoadInfo info(gMainApp.exec_file);
        !           171:        if (mainram->LoadFromFile(&info) == false) {
        !           172:                return -1;
        !           173:        }
        !           174: 
        !           175:        // NetBSD/x68k のプライマリブートローダが /boot を読み込む時、および
        !           176:        // /boot がカーネルを読み込む時には、レジスタ渡しのパラメータがあるので、
        !           177:        // ここで用意する。
        !           178:        // 本当はターゲットが NetBSD/x68k の /boot とカーネルの時に限定すべきの
        !           179:        // ような気もするけど、とりあえず。必要なパラメータは
        !           180:        //
        !           181:        // %d6 に bootdev、NetBSD/x68k の場合は
        !           182:        // bootdev = $MACULPTT
        !           183:        //            ||||||++- major type
        !           184:        //            |||||+--- パーティション番号
        !           185:        //            ||||+---- SCSI なら LUN、それ以外なら 0
        !           186:        //            |||+----- unit (SCSI なら SCSI ID、FD ならドライブ番号)
        !           187:        //            ||+------ ctlr (spc0 なら 0 のやつ)
        !           188:        //            |+------- adaptor (spc = 1、mha = 2)
        !           189:        //            +-------- magic ($a)
        !           190:        // major type は fd=2、MemoryDisk=8、sd=4、(st=5、)、cd=7、ne=255。
        !           191:        //
        !           192:        // %d7 に howto だが今の所使ってないようだ。
        !           193:        //
        !           194:        // 一方、/boot がカーネルを読み込む時はこれに加えてスタック渡しの
        !           195:        // パラメータもある。これは (取り出す順に)
        !           196:        //  firstpa.L  .. 読み込んだカーネル先頭の物理アドレス?
        !           197:        //  physsize.L .. RAM 容量 (SRAM の $ed0008.L の値)
        !           198:        //  esym.L     .. シンボルの後ろ、なので実質読み込んだ全体のサイズ
        !           199:        //
        !           200:        // これも本当はターゲットが NetBSD/x68k のカーネルの時に限定すべきの
        !           201:        // ような気もするけど、とりあえず。
        !           202: 
        !           203:        mpu680x0->reg.D[6] = 0xa1000004;
        !           204:        mpu680x0->reg.D[7] = 0;
        !           205: 
        !           206:        mpu680x0->reg.A[7] = sram->GetRAMSize();
        !           207:        mpu680x0->reg.A[7] -= 4;
        !           208:        mainbus->Write32(mpu680x0->reg.A[7], info.end - info.start);    // esym
1.1.1.3   root      209: 
1.1.1.9 ! root      210:        mpu680x0->reg.A[7] -= 4;
        !           211:        mainbus->Write32(mpu680x0->reg.A[7], sram->GetRAMSize());       // physsize
        !           212: 
        !           213:        mpu680x0->reg.A[7] -= 4;
        !           214:        mainbus->Write32(mpu680x0->reg.A[7], 0x00000000);                       // firstpa
1.1.1.3   root      215: 
1.1.1.9 ! root      216:        return info.entry;
1.1.1.3   root      217: }
                    218: 
1.1       root      219: // ベンチマーク開始
                    220: void
                    221: PlutoDevice::benchmark_start(uint32 data)
                    222: {
                    223:        m_test_num = data;
                    224: 
                    225:        // テスト番号によってパラメータをセット
                    226:        // #2,#3 は NOP による実行サイクル測定。
                    227:        // #4,#5 は movem によるデータ空間アクセス測定。
                    228:        switch (m_test_num) {
                    229:         case 2:
                    230:         case 3:
                    231:                m_test_name = "NOP";
                    232:                m_inst_len = 2;
                    233:                m_inst_cycle = 2;
                    234:                break;
                    235:         case 4:
                    236:         case 5:
                    237:                m_test_name = "MOVEM";
                    238:                m_inst_len = 8;
                    239:                m_inst_cycle = 244;     // XXX 見直すこと
                    240:                break;
                    241:        }
                    242: 
                    243:        // 測定開始時だけ表示
                    244:        if (m_count == 0) {
                    245:                putlog(0, "ベンチマーク開始");
                    246: 
                    247:                // 命令開始アドレス。この時点で REG_PC は次をさしている
1.1.1.9 ! root      248:                m_start_addr = mpu->GetPPC();
1.1       root      249:        }
                    250: 
                    251:        // 測定開始
                    252:        gettimeofday(&m_start, NULL);
                    253: }
                    254: 
                    255: // ベンチマーク終了
                    256: void
                    257: PlutoDevice::benchmark_end()
                    258: {
                    259:        const int SECONDS = 5;  // 測定秒数 [sec]
                    260:        timeval end, result;
                    261:        int t;
                    262:        int num_of_inst;                // 1ループ中の命令セット数
                    263:        double speed;
                    264: 
                    265:        // 測定終了
                    266:        gettimeofday(&end, NULL);
                    267:        m_count++;
                    268: 
                    269:        // 今回1セット分の実行時間 [usec]
                    270:        timersub(&end, &m_start, &result);
                    271: 
                    272:        // 総実行時間
                    273:        timeradd(&result, &m_total, &m_total);
                    274: 
                    275:        // 規定秒数に満たなければ、もう1セット繰り返し。
                    276:        // 次が jmp 命令なのでこの命令を抜けるだけでいい。
                    277:        if (m_total.tv_sec < SECONDS) {
                    278:                return;
                    279:        }
                    280: 
                    281:        // 規定秒数に達していれば、測定終了
                    282:        t = m_total.tv_sec * 1000*1000 + m_total.tv_usec;
                    283:        putlog(0, "ベンチマーク#%d 終了 (%d 回, 計 %d.%03d msec)",
1.1.1.2   root      284:                gMainApp.benchmark_mode, m_count, t / 1000, t % 1000);
1.1       root      285: 
                    286:        // 1ループ中の命令セット数を算出。REG_PPC はこの命令の開始番地
1.1.1.9 ! root      287:        num_of_inst = (mpu->GetPPC() - m_start_addr) / m_inst_len;
1.1       root      288: 
                    289:        // 68030 のクロック数 [MHz] に換算
                    290:        speed = (double)(m_count * num_of_inst) * m_inst_cycle / t;
                    291: 
                    292:        // 表示用にベンチマーク ROM のリビジョンを取得
                    293:        int rev;
                    294: rev = 0;
                    295: #if 0
                    296:        IPLROM1 *iplrom1 = (IPLROM1 *)vm->SearchDevice(DEVICE_IPLROM1);
                    297:        ASSERT(iplrom1);
                    298:        if (!iplrom1->GetBenchmarkROM(m_test_num, NULL, &rev)) {
                    299:                rev = 0;
                    300:        }
                    301: #endif
                    302: 
                    303:        // XXX NetBSD ホストでは有効桁2桁と思われる
                    304:        putlog(0, "ベンチマーク#%d.%d (%s 実行速度) 68030/%3.0fMHz, %d MIPS",
                    305:                m_test_num, rev, m_test_name, speed, (m_count * num_of_inst) / t);
                    306: 
                    307:        // 電源オフ
                    308:        // XXX とりあえずね
                    309:        exit(1);
                    310: }
                    311: 
                    312: //
                    313: void
                    314: PlutoDevice::write_8_benchmark(uint32 addr, uint32 data)
                    315: {
                    316:        switch (data) {
                    317:         case 0:        // ベンチマーク終了
                    318:                benchmark_end();
                    319:                break;
                    320:         case 2:        // ベンチマーク開始
                    321:         case 3:
                    322:         case 4:
                    323:         case 5:
                    324:                benchmark_start(data);
                    325:                break;
                    326:         default:
1.1.1.8   root      327:                VMPANIC("not impl");
1.1       root      328:        }
                    329: }

unix.superglobalmegacorp.com

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