--- nono/vm/ram.cpp 2026/04/29 17:04:36 1.1.1.3 +++ nono/vm/ram.cpp 2026/04/29 17:04:42 1.1.1.4 @@ -17,13 +17,15 @@ // // メインメモリ // + +std::unique_ptr gRAM; + // RAM はロングワード単位でホストバイトオーダ配置なので、 // バイトアクセス、ワードアクセス時は HLB(), HLW() マクロを使用のこと。 -// - std::unique_ptr ram; + +// RAM 容量(バイト単位)であり ram[] の確保したバイト数 int ram_size; -std::unique_ptr gRAM; RAMDevice::RAMDevice() { @@ -32,6 +34,29 @@ RAMDevice::RAMDevice() devaddr = 0; ram_size = 0; + + // アクセスウェイト + switch (gMainApp.GetVMType()) { + case VMTYPE_LUNA88K: + // 取扱説明書p.21 に、CMMU からのアクセスタイムが + // リード(4byte)で 200ns、バーストリード(16byte)で 320ns + // ライト(4byte)で 160ns、バーストライト(16byte)で 280ns とある。 + // 25MHz は 40ns/clockで、この数値は CMMU からのアクセス全体の時間 + // らしいので、ここで加算するウェイトはそれから 2クロック引いたもの。 + read_wait = 3; + write_wait = 2; + break; + case VMTYPE_LUNA1: + // LUNA-I は1ウェイト。 + read_wait = 1; + write_wait = 1; + break; + + case VMTYPE_X68030: + default: + // X68030 ではシステムポートが設定するのでここでは不要。 + break; + } } RAMDevice::~RAMDevice() @@ -42,26 +67,38 @@ RAMDevice::~RAMDevice() bool RAMDevice::Init() { - const ConfigItem& item = gConfig->Find("ram-size"); // [MB] - ram_size = item.AsInt(); + int ram_size_MB; + + const ConfigItem& item = gConfig->Find("ram-size"); + ram_size_MB = item.AsInt(); // XXX 上限は適当。 // LUNA は空間は 1024MB 分あるが末尾に Null と BusErr 領域が必要なはずで // メモリの上限は 1023MB くらいのはず。 - if (ram_size < 1 || ram_size > 1023) { + if (ram_size_MB < 1 || ram_size_MB > 1023) { item.Err(); return false; } - // MB 表記をバイト単位にしてから確保 - ram_size = ram_size * 1024 * 1024; + ram_size = ram_size_MB * 1024 * 1024; ram.reset(new uint8[ram_size]); return true; } +void +RAMDevice::ResetHard() +{ + // X68030 ではリセットで戻るはず。(LUNA は固定なので関係ない) + if (gMainApp.GetVMType() == VMTYPE_X68030) { + read_wait = 0; + write_wait = 0; + } +} + uint64 RAMDevice::Read8(uint32 addr) { + gMPU->AddCycle(read_wait); uint32 data; data = ram[HLB(addr)]; return data; @@ -70,6 +107,7 @@ RAMDevice::Read8(uint32 addr) uint64 RAMDevice::Read16(uint32 addr) { + gMPU->AddCycle(read_wait); uint32 data; data = *(uint16 *)&ram[HLW(addr)]; return data; @@ -78,6 +116,7 @@ RAMDevice::Read16(uint32 addr) uint64 RAMDevice::Read32(uint32 addr) { + gMPU->AddCycle(read_wait); uint32 data; data = *(uint32 *)&ram[addr]; return data; @@ -86,6 +125,7 @@ RAMDevice::Read32(uint32 addr) uint64 RAMDevice::Write8(uint32 addr, uint32 data) { + gMPU->AddCycle(write_wait); ram[HLB(addr)] = data; return 0; } @@ -93,6 +133,7 @@ RAMDevice::Write8(uint32 addr, uint32 da uint64 RAMDevice::Write16(uint32 addr, uint32 data) { + gMPU->AddCycle(write_wait); *(uint16 *)&ram[HLW(addr)] = data; return 0; } @@ -100,6 +141,7 @@ RAMDevice::Write16(uint32 addr, uint32 d uint64 RAMDevice::Write32(uint32 addr, uint32 data) { + gMPU->AddCycle(write_wait); *(uint32 *)&ram[addr] = data; return 0; } @@ -110,6 +152,14 @@ RAMDevice::Peek8(uint32 addr) return ram[HLB(addr)]; } +// アクセスウェイトを設定 (X68030 でシステムポートから呼ばれる) +void +RAMDevice::SetWait(uint32 wait) +{ + read_wait = wait; + write_wait = wait; +} + // filepath で指定されるホストの実行ファイルをゲストにロードする。 // ファイルのフォーマットは自動で認識する。 // target_mid は machine id で、実体は a.out の値を流用してはいるが