Annotation of nono/vm/mainram.cpp, revision 1.1.1.1

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // メインメモリ
                      9: //
                     10: 
                     11: #include "mainram.h"
                     12: #include "config.h"
                     13: #include "mainapp.h"
                     14: #include "mpu.h"
                     15: #include "prom.h"
                     16: 
                     17: // MainRAM はロングワード単位でホストバイトオーダ配置なので、
                     18: // バイトアクセス、ワードアクセス時は HLB(), HLW() マクロを使用のこと。
                     19: /*static*/ std::unique_ptr<uint8[]> MainRAMDevice::mainram;
                     20: 
                     21: // コンストラクタ
                     22: MainRAMDevice::MainRAMDevice()
                     23:        : inherited(OBJ_MAINRAM)
                     24: {
                     25:        // アクセスウェイト
                     26:        switch (gMainApp.GetVMType()) {
                     27:         case VMType::LUNA1:
                     28:                // LUNA-I は1ウェイト。
                     29:                read_wait  = 1;
                     30:                write_wait = 1;
                     31:                break;
                     32: 
                     33:         case VMType::LUNA88K:
                     34:                // 取扱説明書p.21 に、CMMU からのアクセスタイムが
                     35:                // リード(4byte)で 200ns、バーストリード(16byte)で 320ns
                     36:                // ライト(4byte)で 160ns、バーストライト(16byte)で 280ns とある。
                     37:                // 25MHz は 40ns/clockで、この数値は CMMU からのアクセス全体の時間
                     38:                // らしいので、ここで加算するウェイトはそれから 2クロック引いたもの。
                     39:                read_wait  = 3;
                     40:                write_wait = 2;
                     41:                break;
                     42: 
                     43:         case VMType::X68030:
                     44:         default:
                     45:                // X68030 ではシステムポートが設定するのでここでは不要。
                     46:                break;
                     47:        }
                     48: }
                     49: 
                     50: // デストラクタ
                     51: MainRAMDevice::~MainRAMDevice()
                     52: {
                     53: }
                     54: 
                     55: // 初期化
                     56: bool
                     57: MainRAMDevice::Init()
                     58: {
                     59:        if (inherited::Init() == false) {
                     60:                return false;
                     61:        }
                     62: 
                     63:        const ConfigItem& item = gConfig->Find("ram-size");
                     64:        int ram_size_MB = item.AsInt();
                     65:        if (ram_size_MB < 1) {
                     66:                item.Err();
                     67:                return false;
                     68:        }
                     69:        // 下限以外の制約は機種による
                     70:        switch (gMainApp.GetVMType()) {
                     71:         case VMType::X68030:
                     72:                // メインメモリは 12MB まで。
                     73:                // 内部は 8KB 単位で処理できるが設定が 1MB 単位。
                     74:                if (ram_size_MB > 12) {
                     75:                        item.Err("Configurable maximum main memory size is 12 [MB]");
                     76:                        return false;
                     77:                }
                     78:                break;
                     79: 
                     80:         case VMType::LUNA1:
                     81:                // 16MB までは、実機に合わせて 4MB 単位とする。
                     82:                // see http://wiki.netbsd.org/ports/luna68k/luna68k_info/#hardware
                     83:                //
                     84:                // 16MB を超える増設 (or 魔改造) 部分は 1MB 単位で 255MB までとする。
                     85:                // 実 ROM のメモリチェックは 32KB だかそのくらいずつ行われ、
                     86:                // 最後に番兵として Null 領域 (BusError ではなく) が必要。
                     87:                // 現行の構成をあまり変えない範囲なら厳密には (256MB - 32KB) が
                     88:                // 上限だが、設定ファイルからの指定が 1MB 単位なので 255MB。
                     89:                if (ram_size_MB <= 16) {
                     90:                        if (ram_size_MB % 4 != 0) {
                     91:                                item.Err("For 16MB or less, must be specified in 4 [MB] unit");
                     92:                                return false;
                     93:                        }
                     94:                } else if (ram_size_MB > 255) {
                     95:                        item.Err("Configurable maximum RAM size is 255 [MB]");
                     96:                        return false;
                     97:                }
                     98:                break;
                     99: 
                    100:         case VMType::LUNA88K:
                    101:         {
                    102:                // 64MB までは、実機に合わせて 16MB 単位とする。
                    103:                //
                    104:                // 64MB を超える増設 (or 魔改造) 部分は未確認。
                    105:                if (ram_size_MB <= 64) {
                    106:                        if (ram_size_MB % 16 != 0) {
                    107:                                item.Err("For 64MB or less, must be specified in 16 [MB] unit");
                    108:                                return false;
                    109:                        }
                    110:                } else if (ram_size_MB > 255) {
                    111:                        item.Err("Configurable maximum RAM size is 255 [MB]");
                    112:                        return false;
                    113:                }
                    114: 
                    115:                // PROM 1.20 では 240MB を上限にする。
                    116:                // 0x0f00'0000 (ちょうど 240MB 目) へのアクセスでバスエラーが
                    117:                // 出ることを CMMU のアドレス変換チェックに使っているため。
                    118:                auto prom = dynamic_cast<PROMDevice *>(GetPROMDevice());
                    119:                if (prom && prom->GetROMVer() == 120) {
                    120:                        if (ram_size_MB > 240) {
                    121:                                item.Err("Maximum RAM size with PROM 1.20 is 240 [MB]");
                    122:                                return false;
                    123:                        }
                    124:                }
                    125: 
                    126:                break;
                    127:         }
                    128: 
                    129:         case VMType::NEWS:
                    130:                // XXX とりあえず
                    131:                memset(&mainram[0], 0, ram_size);
                    132:                break;
                    133: 
                    134:         default:
                    135:                PANIC("corrupted vmtype=%s", gMainApp.GetVMName().c_str());
                    136:        }
                    137: 
                    138:        ram_size = ram_size_MB * 1024 * 1024;
                    139:        mainram.reset(new uint8[ram_size]);
                    140: 
                    141:        // Human68k モードならここで一度だけメモリをゼロクリアする。
                    142:        // この時は Human68k::Init() が MainRAM にプログラムを転送するため
                    143:        // 電源オン時点で RAM を初期化してはいけない…。うーんこの…。
                    144:        // MainRAM::Init() が Human68k::Init() より先に呼ばれることは
                    145:        // VM_X68030 で指定してある。
                    146:        // 一方、通常モードなら VM リスタート(電源再投入) で前の内容を残さない
                    147:        // ために ResetHard(true) でメモリを (ゼロでなくてもいいので) クリアする
                    148:        // 必要がある。
                    149:        if (gMainApp.human_mode) {
                    150:                memset(&mainram[0], 0, ram_size);
                    151:        }
                    152: 
                    153:        // devtable[] への RAM デバイスの配置はこの後 VM::Init 側で行っている
                    154: 
                    155:        return true;
                    156: }
                    157: 
                    158: // 電源オン/リセット
                    159: void
                    160: MainRAMDevice::ResetHard(bool poweron)
                    161: {
                    162:        if (poweron) {
                    163:                if (gMainApp.human_mode || gMainApp.IsNEWS()) {
                    164:                        // Human モードと NEWS は Init() がメモリに書き込むので
                    165:                        // ここでクリアしない。うーん。
                    166:                } else {
                    167:                        // 通常モードならメモリをクリア
                    168:                        // XXX ノイズを用意するべき
                    169:                        memset(&mainram[0], 0, ram_size);
                    170:                }
                    171:        }
                    172: 
                    173:        // X68030 ではリセットで戻るはず。(LUNA は固定なので関係ない)
                    174:        if (gMainApp.IsX68030()) {
                    175:                read_wait  = 0;
                    176:                write_wait = 0;
                    177:        }
                    178: }
                    179: 
                    180: uint64
                    181: MainRAMDevice::Read8(uint32 addr)
                    182: {
                    183:        mpu->AddCycle(read_wait);
                    184:        uint32 data;
                    185:        data = mainram[HLB(addr)];
                    186:        putlog(4, "$%08x.B -> $%02x", addr, data);
                    187:        return data;
                    188: }
                    189: 
                    190: uint64
                    191: MainRAMDevice::Read16(uint32 addr)
                    192: {
                    193:        mpu->AddCycle(read_wait);
                    194:        uint32 data;
                    195:        data = *(uint16 *)&mainram[HLW(addr)];
                    196:        putlog(4, "$%08x.W -> $%04x", addr, data);
                    197:        return data;
                    198: }
                    199: 
                    200: uint64
                    201: MainRAMDevice::Read32(uint32 addr)
                    202: {
                    203:        mpu->AddCycle(read_wait);
                    204:        uint32 data;
                    205:        data = *(uint32 *)&mainram[addr];
                    206:        putlog(4, "$%08x.L -> $%08x", addr, data);
                    207:        return data;
                    208: }
                    209: 
                    210: uint64
                    211: MainRAMDevice::Write8(uint32 addr, uint32 data)
                    212: {
                    213:        mpu->AddCycle(write_wait);
                    214:        mainram[HLB(addr)] = data;
                    215:        putlog(3, "$%08x.B <- $%02x", addr, data);
                    216:        return 0;
                    217: }
                    218: 
                    219: uint64
                    220: MainRAMDevice::Write16(uint32 addr, uint32 data)
                    221: {
                    222:        mpu->AddCycle(write_wait);
                    223:        *(uint16 *)&mainram[HLW(addr)] = data;
                    224:        putlog(3, "$%08x.W <- $%04x", addr, data);
                    225:        return 0;
                    226: }
                    227: 
                    228: uint64
                    229: MainRAMDevice::Write32(uint32 addr, uint32 data)
                    230: {
                    231:        mpu->AddCycle(write_wait);
                    232:        *(uint32 *)&mainram[addr] = data;
                    233:        putlog(3, "$%08x.L <- $%08x", addr, data);
                    234:        return 0;
                    235: }
                    236: 
                    237: uint64
                    238: MainRAMDevice::Peek8(uint32 addr)
                    239: {
                    240:        return mainram[HLB(addr)];
                    241: }
                    242: 
                    243: uint64
                    244: MainRAMDevice::Poke8(uint32 addr, uint32 data)
                    245: {
                    246:        if ((int32)data >= 0) {
                    247:                mainram[HLB(addr)] = data;
                    248:        }
                    249:        return 0;
                    250: }
                    251: 
                    252: // アクセスウェイトを設定 (X68030 でシステムポートから呼ばれる)
                    253: void
                    254: MainRAMDevice::SetWait(uint32 wait)
                    255: {
                    256:        read_wait  = wait;
                    257:        write_wait = wait;
                    258: }
                    259: 
                    260: // info->path で指定されたホストの実行ファイルをゲストにロードする。
                    261: bool
                    262: MainRAMDevice::LoadFromFile(LoadInfo *info)
                    263: {
                    264:        BootLoader loader(this);
                    265: 
                    266:        return loader.LoadFromFile(info);
                    267: }
                    268: 
                    269: // info->data, size で指定されたバッファを実行ファイルとみなしてゲストに
                    270: // ロードする。
                    271: bool
                    272: MainRAMDevice::LoadFromData(LoadInfo *info)
                    273: {
                    274:        BootLoader loader(this);
                    275: 
                    276:        return loader.LoadFromData(info);
                    277: }

unix.superglobalmegacorp.com

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