003. Шина CPU и RAM

Направить адреса RAM CPU через CpuBus.

Урок 3 из 356 · tests/chapter_01_cpu/test_003_cpu_bus_to_ram.py

Файл для обновления

emulator/bus/cpu_bus.py

Расположение

class CpuBus

Ссылка

https://www.nesdev.org/wiki/CPU_memory_map

Почему этот шаг существует

CPU использует 16-битное адресное пространство, тогда как внутренняя RAM содержит всего 0x800 физических байт. Адреса $0000-$1FFF повторяют одну и ту же RAM четыре раза.

Полная эталонная реализация

from dataclasses import dataclass, field

from emulator.memory.ram import RAM


@dataclass
class CpuBus:
    ram: RAM = field(default_factory=RAM)

    def read(self, addr: int) -> int:
        if 0x0000 <= addr <= 0x1FFF:
            return self.ram.read(addr & 0x07FF)

        raise ValueError(f"Unsupported CPU bus read: {addr:04X}")

    def write(self, addr: int, value: int) -> None:
        if 0x0000 <= addr <= 0x1FFF:
            self.ram.write(addr & 0x07FF, value)
            return

        raise ValueError(f"Unsupported CPU bus write: {addr:04X}")

Важный инвариант

physical_ram_address = cpu_address & 0x07FF

Минимальный пример

Запись $42 по адресу CPU $0800 изменяет физический байт RAM $0000, поэтому чтение $0000, $0800, $1000 или $1800 обращается к одному и тому же хранилищу.

Распространённое заблуждение

Зеркалирование не выделяет четыре массива RAM. Шина преобразует четыре диапазона адресов CPU в одно и то же устройство RAM. На этом шаге неподдерживаемые адреса вызывают ValueError, а сам bytearray отклоняет значения вне беззнакового 8-битного диапазона.

Вне рамок

  • маршрутизация программной ROM
  • регистры PPU и контроллера
  • выполнение CPU

Запустить этот урок

uv run pytest tests/chapter_01_cpu/test_003_cpu_bus_to_ram.py -v