# CBE Platform — Полное руководство по созданию плагинов и систем ## Содержание 1. [Введение](#1-введение) 2. [Архитектура CBE](#2-архитектура-cbe) 3. [Формат плагина (.cbeplugin)](#3-формат-плагина-cbeplugin) 4. [Создание модуля CPU](#4-создание-модуля-cpu) 5. [Создание модуля RAM](#5-создание-модуля-ram) 6. [Создание модуля GPU](#6-создание-модуля-gpu) 7. [Создание модуля KBD (клавиатура)](#7-создание-модуля-kbd) 8. [Создание модуля SND (звук)](#8-создание-модуля-snd) 9. [Создание модуля BIOS](#9-создание-модуля-bios) 10. [Создание модуля DISK](#10-создание-модуля-disk) 11. [Семантические операции инструкций](#11-семантические-операции) 12. [Написание программ на ассемблере](#12-написание-программ-на-ассемблере) 13. [Написание программ на C/C++](#13-написание-программ-на-cc) 14. [Написание программ на Python](#14-написание-программ-на-python) 15. [Hex-машинный код](#15-hex-машинный-код) 16. [Сборка плагинов (cbecc)](#16-сборка-плагинов-cbecc) 17. [Тулчейн: компиляция из разных языков](#17-тулчейн-компиляция-из-разных-языков) 18. [Система POST-диагностики](#18-система-post-диагностики) 19. [Memory-mapped I/O](#19-memory-mapped-io) 20. [Бесконечные шаги и детектор циклов](#20-бесконечные-шаги-и-детектор-циклов) 21. [Тёмная тема GUI](#21-тёмная-тема-gui) 22. [Примеры](#22-примеры) 23. [Устранение неполадок](#23-устранение-неполадок) 24. [Справочник команд](#24-справочник-команд) --- ## 1. Введение **CBE (Create. Build. Execute.)** — платформа для эмуляции и создания собственных компьютерных компонентов: процессоров, оперативной памяти, видеокарт, дисков, BIOS, клавиатур и звуковых карт. Всё это собирается в единую архитектуру и запускается через эмулятор с графическим интерфейсом. Основная идея: вы описываете поведение компонента через JSON-конфигурацию и/или бинарные данные, а платформа предоставляет среду выполнения с: - Эмулятором на Java с GUI (Swing) - Компилятором .cbeplugin - Тулчейном для ассемблера, C/C++, Python, hex - Системой POST-диагностики - Детектором бесконечных циклов - Тёмной темой ### Ключевые концепции - **Plugin** — модуль в формате `.cbeplugin`, содержащий метаданные, инструкции, микрокод и данные - **ModuleInstance** — экземпляр загруженного модуля в эмуляторе - **Engine** — оркестратор, управляющий всеми модулями и циклом выполнения CPU - **Bus** — системная шина, связывающая модули - **Registers** — регистры CPU - **POST** — Power-On Self-Test, система самодиагностики при старте - **Memory-mapped I/O** — регистры ввода-вывода, отображённые на адресное пространство --- ## 2. Архитектура CBE ``` ┌─────────────────────────────────────────────────────────────┐ │ CBE Emulator │ ├─────────────────────────────────────────────────────────────┤ │ ┌───────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ │ │ │ CPU │ │ RAM │ │ GPU │ │ KBD │ │ │ │ (плагин) │ │ (плагин) │ │ (плагин) │ │ (плагин) │ │ │ └─────┬─────┘ └────┬─────┘ └────┬─────┘ └─────┬─────┘ │ │ │ │ │ │ │ │ ┌─────┴──────────────┴─────────────┴───────────────┴─────┐ │ │ │ System Bus (шина) │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌─────┴─────┐ ┌────┴────┐ ┌─────┴─────┐ ┌──────┴─────┐ │ │ │ SND/Sound│ │ BIOS │ │ DISK │ │ POST │ │ │ │ (плагин) │ │ (плагин)│ │ (плагин) │ │ (встроено) │ │ │ └───────────┘ └─────────┘ └───────────┘ └────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ### Модули (ModuleType) | Тип | ID | Описание | |---------|----|--------------------------------------------------------------| | CPU | 0 | Процессор. Определяет регистры, набор инструкций, микрокод | | RAM | 1 | Оперативная память с банками данных | | DISK | 2 | Диск с секторной адресацией (512 байт/сектор) | | GPU | 3 | Видеокарта. 80x25 текстовый режим, VRAM, курсор | | BIOS | 4 | BIOS с информацией о системе | | KBD | 5 | Клавиатура с буфером клавиш, handshake-протокол | | SND | 6 | Звуковая карта (PC Speaker beep) | | DATA_ONLY | 7 | Только данные, без логики | ### CompileMode | Режим | ID | Описание | |------------|----|------------------------------------| | FULL | 0 | Только логика (инструкции + микрокод) | | HYBRID | 1 | Логика + данные | | PACK_ONLY | 2 | Только данные | --- ## 3. Формат плагина (.cbeplugin) ### Структура файла Бинарный формат с little-endian числами: ``` Смещение Размер Поле -------- ------ ------------------------------------ 0 8 Магическая строка: "CBE_PLUG\0" 8 4 Версия (int32 LE) 12 4 Размер заголовка (int32 LE, всегда 62) 16 1 ModuleType (byte) 17 1 CompileMode (byte) 18 4 Смещение секции метаданных (int32 LE) 22 4 Длина секции метаданных 26 4 Смещение таблицы опкодов 30 4 Длина таблицы опкодов 34 4 Смещение таблицы микрокода 38 4 Длина таблицы микрокода 42 4 Смещение байткода обработчика 46 4 Длина байткода обработчика 50 4 Смещение секции данных 54 4 Длина секции данных 58 4 CRC32 (покрывает байты 0..57) ``` ### Секции после заголовка - **Метаданные:** JSON-строка с name, arch, module_type, version, tdp, frequency - **Таблица опкодов:** JSON-массив объектов инструкций - **Микрокод:** JSON-объект { command: [byte, ...] } - **Байткод обработчика:** зарезервировано (raw bytecode) - **Секция данных:** [bank_count:4][bank0_size:4][bank0_data...][bank1_size:4]... --- ## 4. Создание модуля CPU ### Структура директории ``` my-cpu.cpu/ ├── module.json # Метаданные модуля ├── registers.json # Определения регистров ├── instructions/ # Определения инструкций │ ├── 0x00.json # NOP │ ├── 0x01.json # MOV │ └── ... ├── microcode/ │ └── bus.json # Сигналы шины ├── roms/ │ └── boot.bin # Boot ROM (исполняемый код) ├── banks/ # Банки данных (опционально) │ └── bank_0.bin ├── program.asm # Исходник программы (альтернатива boot.bin) ├── program.c # Исходник на C ├── program.py # Исходник на Python └── program.hex # Hex-машинный код ``` ### module.json ```json { "name": "MyCPU", "arch": "my-8bit", "module_type": "cpu", "version": 1, "tdp": 5.0, "memory_size": 65536, "frequency": 1000000 } ``` Поля: - `name` — название процессора - `arch` — архитектура (строка) - `module_type` — "cpu" - `tdp` — тепловыделение (W) - `memory_size` — размер адресного пространства (байт) - `frequency` — частота в Hz ### registers.json ```json { "a": 0, "b": 0, "c": 0, "d": 0, "pc": 0, "sp": 0, "carry": 0, "zero": 0 } ``` Каждый регистр — ключ с начальным значением. `pc` (program counter) и `sp` (stack pointer) обязательны. ### Определение инструкции Файл `instructions/0x00.json`: ```json { "opcode": 0, "mnemonic": "NOP", "args": [], "cycles": 1, "semantics": [ {"op": "nop"} ] } ``` Инструкция с аргументами: ```json { "opcode": 2, "mnemonic": "MOV_IMM_A", "args": [ {"name": "value", "type": "imm"} ], "cycles": 2, "semantics": [ {"op": "load_imm", "to": "a", "value": "$next"} ] } ``` - `opcode` — числовой код операции (0-255) - `mnemonic` — мнемоника для ассемблера - `args` — список аргументов (name + type: "reg", "imm", "address") - `cycles` — тактов на выполнение - `semantics` — список семантических операций (см. раздел 11) ### Микрокод (bus.json) ```json { "memory_read": [0x01, 0x00], "memory_write": [0x02, 0x00], "io_read": [0x03], "io_write": [0x04] } ``` Каждый сигнал — имя и массив байт. ### Boot ROM Файл `roms/boot.bin` содержит исполняемый код, который загружается в начало адресного пространства CPU при старте. Максимальный размер — 64KB. Можно создать: - через ассемблер (program.asm) - через компилятор C (program.c) - через Python-транслятор (program.py) - как hex-дамп (program.hex) --- ## 5. Создание модуля RAM ``` my-ram.ram/ ├── module.json ├── banks/ │ └── bank_0.bin # Начальные данные RAM └── controller/ # Опциональный контроллер └── microcode/ └── bus.json ``` ### module.json ```json { "name": "MyRAM", "arch": "generic-ram", "module_type": "ram", "version": 1, "tdp": 2.0, "bank_size": 256, "bank_count": 1 } ``` Поля: - `bank_size` — размер банка в байтах - `bank_count` — количество банков --- ## 6. Создание модуля GPU ``` my-gpu.gpu/ ├── module.json ├── banks/ │ └── bank_0.bin # VRAM (2000 байт для 80x25) └── microcode/ └── bus.json ``` ### module.json ```json { "name": "MyGPU", "arch": "vga-text-80x25", "module_type": "gpu", "version": 1, "tdp": 10.0, "vram_size": 2000, "rows": 25, "cols": 80 } ``` Поля: - `vram_size` — размер видеопамяти (80x25 = 2000) - `rows` — количество строк - `cols` — количество колонок GPU отображается как 80x25 текстовый терминал (а-ля QEMU). Вывод символов осуществляется записью в порт 0xC0. --- ## 7. Создание модуля KBD ``` my-kbd.kbd/ └── module.json ``` ### module.json ```json { "name": "MyKeyboard", "arch": "ps2-like", "module_type": "kbd", "version": 1, "tdp": 0.5, "buffer_size": 32 } ``` Поля: - `buffer_size` — размер буфера клавиш Клавиатура работает через memory-mapped I/O: - Чтение `0xFB` — данные клавиши (peek, не удаляет) - Чтение `0xFA` — статус (0 = нет клавиши, 1 = есть) - Запись `0xFA = 0` — acknowledge (удаляет клавишу из буфера) --- ## 8. Создание модуля SND ``` my-snd.snd/ └── module.json ``` ### module.json ```json { "name": "MySound", "arch": "pc-speaker", "module_type": "snd", "version": 1, "tdp": 1.0 } ``` Любая запись в порт `0xF9` вызывает системный звуковой сигнал (beep). Частота ограничена 10 beep/сек. --- ## 9. Создание модуля BIOS ``` my-bios.bios/ └── module.json ``` ### module.json ```json { "name": "MyBIOS", "arch": "generic-bios", "module_type": "bios", "version": 1, "tdp": 1.0 } ``` BIOS хранит строку информации о системе, доступную через `engine.getSystemInfo()`. Триггер перезапуска диагностики — запись в порт `0xF7`. --- ## 10. Создание модуля DISK ``` my-disk.disk/ ├── module.json └── banks/ └── bank_0.bin # Данные диска ``` ### module.json ```json { "name": "MyDisk", "arch": "ata-like", "module_type": "disk", "version": 1, "tdp": 5.0, "sector_size": 512 } ``` Диск работает через порты: - `0xB0` — запись LBA сектора (инициирует чтение) - `0xB1` — статус готовности (1 = готов) - `0xB2+` — данные сектора (512 байт) Если последние 2 байта сектора 0 равны `0x55 0xAA`, диск считается загрузочным. ### Загрузка с диска (Boot flow) При старте эмулятор выполняет POST-диагностику, которая: 1. Пишет BIOS-программу в память CPU (адреса `0x00..0x15`) 2. Строит POST-текст и размещает его в буфере display (`0x16+`) 3. Если диск загрузочный (сектор 0 содержит `0x55 0xAA`): - Копирует сектор 0 в память CPU по адресу `0x80` - Заменяет idle-цикл BIOS (`0x14..0x15`) на `JMP_IMM 0x80` 4. CPU начинает выполнение с `PC=0`: - Исполняет BIOS-программу, которая выводит POST-текст на GPU - После вывода POST-текста переходит к `0x14` → прыжок на `0x80` - CPU выполняет загрузочный код из сектора 0 Пример создания загрузочного диска (Python): ```python # TinyCPU bytecode for boot sector at address 0x80 # Prints "BOOT OK!" to GPU via port 0xC0, then halts program = bytes([ 0x02, 0x42, # MOV_IMM_A 'B' 0x0A, 0xC0, # STORE_A 0xC0 0x02, 0x4F, # MOV_IMM_A 'O' 0x0A, 0xC0, # STORE_A 0xC0 0x02, 0x4F, # MOV_IMM_A 'O' 0x0A, 0xC0, # STORE_A 0xC0 0x02, 0x54, # MOV_IMM_A 'T' 0x0A, 0xC0, # STORE_A 0xC0 0x02, 0x20, # MOV_IMM_A ' ' 0x0A, 0xC0, # STORE_A 0xC0 0x02, 0x4F, # MOV_IMM_A 'O' 0x0A, 0xC0, # STORE_A 0xC0 0x02, 0x4B, # MOV_IMM_A 'K' 0x0A, 0xC0, # STORE_A 0xC0 0x02, 0x21, # MOV_IMM_A '!' 0x0A, 0xC0, # STORE_A 0xC0 0xFF, # HLT ]) sector = program + b'\x00' * (510 - len(program)) + b'\x55\xAA' ``` Готовый пример: `examples/system-disk/disk.img/`. --- ## 11. Семантические операции | Операция | Описание | |-------------|--------------------------------------------------------------| | `copy` | Копирует значение из `from` в `to` | | `load_imm` | Загружает непосредственное значение (literal или `$next`) | | `add` | Складывает `from` + `to`, сохраняет в `result`, обновляет флаги carry/zero | | `sub` | Вычитает `to` из `from`, обновляет флаги borrow/zero | | `cmp` | Сравнивает `from` - `to`, обновляет флаги | | `store` | Записывает значение в память `mem[address]` | | `load` | Читает из памяти `mem[address]` в регистр | | `jmp` | Безусловный переход на адрес в `to` | | `jcc` | Условный переход, если флаг равен ожидаемому | | `jmp_imm` | Переход на байт, следующий за опкодом | | `jcc_imm` | Условный переход на байт за опкодом | | `call` | Push адреса возврата в стек, прыжок | | `ret` | Pop адреса из стека, прыжок | | `push` | Push значения в стек | | `pop` | Pop значения из стека | | `inc` | Инкремент значения | | `nop` | Нет операции | ### Специальные значения - `$next` — следующий байт в памяти (используется для immediate значений) - `arg.X` — ссылка на аргумент инструкции по имени - `mem[N]` — прямая ссылка на память по адресу N - `mem[arg.X]` — косвенная адресация через аргумент ### Условные переходы ```json { "op": "jcc_imm", "condition": "zero,1", "to": "$next" } ``` Формат условия: `"имя_флага,ожидаемое_значение"`. Например `"zero,1"`, `"carry,0"`. --- ## 12. Написание программ на ассемблере Ассемблер CBE поддерживает мнемоники, определённые в инструкциях CPU. ### Синтаксис ```asm ; комментарий label: ; определение метки MNEMONIC ; инструкция без аргументов MNEMONIC arg1, arg2 ; инструкция с аргументами .org 0x100 ; установка адреса .byte 0xAB ; эмит байта .db "hello", 0 ; эмит строки с нулевым терминатором ``` ### Адресация - Числа: `0x10` (hex), `10` (dec), `0b1010` (bin), `$10` (hex) - Метки: `loop_start`, `loop_start+5` - Символы: `'A'` (ASCII код) ### Пример ```asm ; Программа Hello World .org 0x00 start: MOV_IMM_A 0x48 ; 'H' STORE_A 0xC0 ; вывод на GPU MOV_IMM_A 0x65 ; 'e' STORE_A 0xC0 MOV_IMM_A 0x6C ; 'l' STORE_A 0xC0 MOV_IMM_A 0x6C ; 'l' STORE_A 0xC0 MOV_IMM_A 0x6F ; 'o' STORE_A 0xC0 HLT ``` ### Сборка ```bash # Собрать .asm в .bin с архитектурой TinyCPU cbecc asm program.asm -o roms/boot.bin --arch examples/tiny-cpu.cpu # Или собрать весь плагин (авто-детекция program.asm) cbecc build my-cpu.cpu -o build/my-cpu.cbeplugin ``` --- ## 13. Написание программ на C/C++ ### Поддержка Транслятор C → TinyCPU поддерживает: - Объявление переменных: `int x = 5;`, `char c;` - Присваивание: `x = expr;` - Вывод на GPU: `write_gpu('A');` - Вывод в порт: `outb(addr, value);` - Циклы: `while`, `for` (ограниченно) - Условные операторы: `if` (ограниченно) - `return 0` → HLT ### Пример ```c void write_gpu(char c) { // Транслируется в MOV_IMM_A c; STORE_A 0xC0 } int main() { write_gpu('H'); write_gpu('e'); write_gpu('l'); write_gpu('l'); write_gpu('o'); write_gpu('\n'); return 0; } ``` ### Компиляция ```bash # Для TinyCPU (встроенный транслятор) cbecc ccompile program.c -o roms/boot.bin --arch tinycpu # Для нативной архитектуры (x86_64 через gcc) cbecc ccompile program.c -o program.bin --arch x86_64 # C++ cbecc ccompile program.cpp -o roms/boot.bin --arch tinycpu ``` ### Для реальных архитектур Для не-tinycpu архитектур `cbecc ccompile` использует: 1. `gcc` для компиляции в объектный файл 2. `ld` или `objcopy` для извлечения flat binary Убедитесь, что установлены `gcc`, `binutils`. --- ## 14. Написание программ на Python ### Поддержка Транслятор Python → TinyCPU поддерживает упрощённый синтаксис: - Присваивание: `x = 5` - Вывод: `print(x)` → GPU (0xC0) - Циклы: `for i in range(n):`, `while condition:` - Условные операторы: `if x == 5:` - Комментарии: `# comment` ### Пример ```python # Hello World для TinyCPU print("Hello from Python!") # Счётчик count = 0 while count < 5: print(count) count = count + 1 ``` ### Трансляция ```bash cbecc py program.py -o roms/boot.bin # Или в составе сборки плагина (auto-detect) cbecc build my-cpu.cpu -o build/my-cpu.cbeplugin ``` --- ## 15. Hex-машинный код Hex-загрузчик поддерживает форматы: - Простые hex-байты: `02 48 0A C0 FF` - C-стиль: `{0x02, 0x48, 0x0A, 0xC0, 0xFF}` - Intel HEX (.hex): `:1000000002480AC0FF...` - Один байт на строку - Разделители: пробелы, запятые, новые строки ### Пример ``` ; boot.bin в hex-формате ; MOV_IMM_A 'H' ; STORE_A 0xC0 ; HLT 02 48 0A C0 FF ``` ### Конвертация ```bash cbecc hex program.hex -o roms/boot.bin ``` --- ## 16. Сборка плагинов (cbecc) ### Основные команды ```bash # Сборка из source-директории (авто-детекция program.*) cbecc build my-plugin.cpu -o build/my-plugin.cbeplugin # Сборка с указанием бинарника программы cbecc plugin my-plugin.cpu --program build/program.bin -o build/my-plugin.cbeplugin # Сборка стандартная (без авто-детекции) java -cp modules/cbecc/build/libs/cbecc-0.1.0.jar:modules/loader/build/libs/loader-0.1.0.jar:modules/core/build/libs/core-0.1.0.jar com.cbe.cbecc.Main build my-plugin.cpu -o build/my-plugin.cbeplugin ``` ### Процесс сборки 1. Чтение `module.json` 2. Определение ModuleType 3. Парсинг метаданных 4. Если есть `program.asm/py/c/cpp/hex` — компиляция в `roms/boot.bin` 5. Построение секции метаданных (JSON) 6. Построение таблицы опкодов (JSON-массив из инструкций) 7. Построение таблицы микрокода (JSON) 8. Построение секции данных (банки + ROMs) 9. Вычисление CRC32 10. Запись .cbeplugin файла --- ## 17. Тулчейн: компиляция из разных языков ### Общая схема ``` program.asm ──→ Assembler ──→ boot.bin program.c ──→ CCompiler ──→ boot.bin (gcc + objcopy или встроенный транслятор) program.py ──→ PythonTranslator ──→ boot.bin program.hex ──→ HexLoader ──→ boot.bin │ ▼ module.json + registers.json + instructions/ + microcode/ │ ▼ Compiler (.cbeplugin) │ ▼ my-plugin.cbeplugin ←── run.sh/gradle ``` ### Авто-детекция При запуске `cbecc build