# Разработка ## Сборка C++ собирается командой `make` из корня проекта; Eigen и nlohmann/json лежат в `data_acq_and_processing/third_party/`, других внешних библиотек нет. | Цель | Что собирает или делает | | --- | --- | | `all` (по умолчанию) | `build/bin/data_preprocessor`, `build/bin/data_processor` | | `rph_radar_collector` | `build/bin/rph_radar_collector`; в `all` не входит | | `check-native` | тесты C++: кадры, кольца, конфигурация, наборы, режекторный фильтр, локатор, псевдотерминал коллектора (на поддельной библиотеке L-Card) | | `check-sar3d` | 3D SAR на настоящем CUDA-бэкенде против эталона | | `check-gpr` | GPR на CPU, без видеокарты, против эталона | | `clean` | удаляет каталог сборки | | Переменная | По умолчанию | Что задаёт | | --- | --- | --- | | `BUILD_DIR` | `build` | каталог сборки. Программа запускает процессы только из `build/bin/`, другой каталог нужен для проверок | | `CUDA_ROOTS` | пакеты `nvidia/*` в `.venv` и `/usr/local/cuda` | где искать `nvrtc.h`, `cuda.h`, `libnvrtc` | | `PYTHON` | `.venv/bin/python` | интерпретатор для `check-sar3d` и `check-gpr` | | `NATIVE_SANITIZERS` | не задана | санитайзеры для тестов C++, например `address,undefined` | | `CXX`, `CXXFLAGS`, `LDFLAGS` | `g++`, `-std=c++20 -O2 …`, `-pthread -lrt` | компилятор и флаги | `BUILD_DIR`, `CUDA_ROOTS`, `CXX`, `CXXFLAGS` и `LDFLAGS` задаются в командной строке `make`, а не через окружение; `PYTHON` и `NATIVE_SANITIZERS` можно задать и переменной окружения. `CXXFLAGS` в командной строке заменяет весь набор флагов, вместе с `-std=c++20` и отслеживанием зависимостей `-MMD -MP`. `make` сам пересобирает нужное, если изменились найденная CUDA или санитайзеры. Сборка с CUDA и без неё описана в главе [Установка и запуск](installation.md). ## Тесты ```sh QT_QPA_PLATFORM=offscreen .venv/bin/python -m unittest discover -s python_app/tests make check-native ASAN_OPTIONS=detect_leaks=0 make check-native NATIVE_SANITIZERS=address,undefined make check-sar3d make check-gpr ``` | Набор | Что нужно | | --- | --- | | Python, `python_app/tests` | `.venv` с пакетами, `QT_QPA_PLATFORM=offscreen` (дисплея у тестов нет), запись в `/dev/shm`, псевдотерминалы, UDP на loopback. Железо не нужно | | C++, `make check-native` | g++ с C++20 | | 3D SAR, `make check-sar3d` | сборка с CUDA и пригодная видеокарта; без неё проверяются только предупреждение и правила рамок, остальное пропускается | | GPR, `make check-gpr` | numpy | Особые случаи: - `test_processor_history` запускает настоящий `build/bin/data_processor` и пропускается, если он не собран. - Тесты окна строят настоящее окно на временном профиле из `run_config_examples/run_config_simulator.example.json` и не зависят от корневого `run_config.json` (`python_app/tests/gui_test_support.py`). - `test_deploy_scripts` гоняет `deploy/update.sh` во временном каталоге с заглушками `systemctl` и `make`. - `test_cart_firmware` компилирует прошивку тележки на компьютере и пропускается без g++. - `data_acq_and_processing/tests/test_backprojection.py` в общий прогон не входит: его запускают `make check-sar3d` и `make check-gpr`. - `test_documentation` проверяет документацию: `docs/configuration.md` называет каждый ключ профиля и `processing_live.json`, главы называют каждую подпись окна и диалогов (жирным, кодом или заголовком), а относительные ссылки ведут на существующие файлы. Новый ключ или кнопка без описания роняет этот тест. > **Внимание.** Не запускайте тесты от root: созданные ими кольца в `/dev/shm` > станут принадлежать root, и программа от обычного пользователя получит отказ в > доступе. Проверка на старой видеокарте (NVRTC 13 не компилирует под карты старее sm_75): ```sh make check-sar3d BUILD_DIR=/tmp/radar_build_nvrtc12 CUDA_ROOTS="$HOME/.cache/radar_nvrtc12/nvidia/cuda_nvrtc $HOME/.cache/radar_nvrtc12/nvidia/cuda_runtime" ``` ## Эталоны 3D SAR и GPR `data_acq_and_processing/tests/sar3d_reference.npz` и `gpr_reference.npz` строит генератор, который выполняет неизменённые функции ноутбука `Multi_depthnorm_clean.ipynb` (ячейки 1 и 5) и скрипта `Horns_motion_4x4_ground.py` с заменёнными параметрами. В эталоне 3D SAR десять случаев: шесть объёмов (ширина отклика, вычитание среднего предыдущих коллекций для каждого кадра апертуры, отношение к фону) и четыре сцены точечных отражателей в шуме для CLEAN с объектами и рамками. Правила рамок проверяются по одному на синтетических объектах. Архивы записывают хеши SHA-256 исходников и версии NumPy и SciPy. Перегенерировать эталоны нужно только при правке алгоритма; ноутбук и скрипт хранятся вне репозитория: ```sh .venv/bin/python data_acq_and_processing/tests/generate_backprojection_reference.py \ --notebook /путь/к/Multi_depthnorm_clean.ipynb \ --gpr-script /путь/к/Horns_motion_4x4_ground.py ``` Другую сборку можно проверить так: `make check-sar3d BUILD_DIR=/путь/к/сборке` или `BACKPROJECTION_FIXTURE=/путь/к/сборке/native_tests/backprojection_fixture` при запуске `test_backprojection.py Sar3dTest`. ## Утилиты | Команда | Что делает | | --- | --- | | `.venv/bin/python -m python_app.scripts.rph_radar_calibrate --config <профиль> --sweeps 200 [--warmup 10] [--apply]` | фазовая калибровка радиофотонного радара (глава [Оборудование](hardware.md)) | | `.venv/bin/python -m python_app.scripts.per_point_switching_check --config <профиль> [--collections 3] [--switch-connected]` | проверка переключения стимула на железе; выход 0 — норма, 1 — сбой | | `./start.sh --producer-only --profile <профиль>` | только процесс сбора с выводом в терминал — для отладки железа | ## Правила кода - Обязателен только функциональный контракт: программа в правильном порядке собирает коллекции, предобрабатывает, обрабатывает и показывает результат в окне и в вебе, даёт выбрать настройки предобработки и выполнить действия пользователя. Внутреннее устройство можно менять под этот контракт. - Код — читаемый и без лишнего: понятные имена, без мёртвых опций и «умных» трюков. - Наименьшая версия Python — 3.10 (код использует `dataclass(slots=True)` и `match`). - `.venv/bin/pyright python_app` — 0 ошибок, без подавлений и расширения исключений (режим `basic`). - Нумерацию антенн и портов задаёт профиль: она уточняется по железу, менять её самостоятельно нельзя. - Корневой `run_config.json` остаётся профилем симулятора. - Изменив поведение, исправьте документацию в том же изменении (таблица «Где что править» в главе [Устройство программы](architecture.md)); полноту ключей и подписей проверяет `test_documentation`. Документ описывает, как устроено сейчас; числа перепроверяются по коду. ## Прошивки > **Внимание.** `top_master.bin` и `combined.vnafw` — единственные копии рабочего > битстрима мастера и рабочего образа; битстрим заново не воспроизводится. Не > перезаписывайте их, новые сборки кладите под новыми именами. - VHDL — только ASCII: любой другой символ, даже длинное тире в комментарии, ломает GHDL (`invalid character, even in a comment`). - В `VNA.xise` закреплено `Starting Placer Cost Table (1-100) Map spartan6 = 2`; не сбрасывайте его в 1: ограничение `MCU_MOSI OFFSET hold` и в стоковой прошивке проходит с запасом всего +0,458 нс. - После правки FPGA прогоните тестбенч и мутационный тест — внесите ошибку и убедитесь, что тестбенч падает: ```sh ghdl -a --std=93 Sweep.vhd Test_Sweep.vhd && ghdl -r --std=93 Test_Sweep --assert-level=error ``` - Изменение объёма логики FPGA сравнивайте по Timing Score с контрольной сборкой стоковой прошивки. Порядок сборки прошивок — [reproduce/README.md](../device_firmware/multi_libreVNA_firmware/reproduce/README.md). ## Git - Основная ветка — `main`. - Правила `build*` и `build/` в корневом `.gitignore` скрывают и файлы комплекта сборки прошивок (в том числе `build.sh` и эталонные бинарники STM32); для них добавлены исключения, а часть файлов скрывает ещё и вложенный `.gitignore` LibreVNA. Добавляя файлы в `device_firmware/`, проверяйте `git status --ignored` и при необходимости `git add -f`. - В репозиторий не входят: `.venv`, `build/`, `python_app/data*`, `python_app/runtime`, ноутбуки `*.ipynb`, локальные инструменты разработчиков.