T27.AI

Блог

WASM-интерпретатор заработал на плате: 134 из 134, из спеки

2026-10-12 · 4 мин чтения

[программы лежат в ROM, собранном из спеки; по проводу ходят запросы, а не .wasm-бинарники; одна плата, одна ночь, шесть прогонов] Спека t27 в gHashTag/t27 (ветка wasm-board, 351e3cdf4) стала Verilog-ядром через t27c gen-verilog, прошла через openXC7 на ALINX AX7203 и ответила на 134 из 134 запросов точно -- шесть прогонов подряд, 804 из 804. 21 опкод из набора WASM MVP, ROM на 14 программ и 101 байт, i32.mul как 32-тактовая микропоследовательность; тайминг вырос с 18,57 до 70,41 МГц при планке 68,7 на одном проценте LUT -- каждая частота здесь оценка nextpnr, а не подписанный тайминг. Самотест конформансного стенда поймал баг со смещениями в проводе, который завалил бы 76 проверок на полностью исправной плате.

Титульная карточка статьи, иллюстрации пока нет: WASM-интерпретатор заработал на плате: 134 из 134, из спеки
Открыть титульную карточку в исходном размере
#t27#FPGA#WASM

За ночь на 12 октября одна спека t27 стала Verilog-ядром, openXC7 уложила его на ALINX AX7203 (Artix-7 XC7A200T-2), и кристалл ответил на каждый запрос точно: 134 из 134, шесть прогонов подряд, 804 из 804 ответов бит в бит. Этот пост -- цепочка квитанций: что работает, чего это стоило и чем это не является.

Сессия на стенде: прошивка, самотест, прогон

Записано на стенде 12 октября 2026, 04:14 UTC: пять команд, все с кодом 0, 32,5 секунды. Страница с плеером -- t27.ai/term/wasm-board-ax7203/. Открыть запись на отдельной странице.

Что исполняет кремний

Ядро на кристалле -- fpga_wasm_board, сгенерированное t27c gen-verilog из specs/fpga/wasm_board_ax7203.t27 в gHashTag/t27 (ветка wasm-board, коммит 351e3cdf4). Оно говорит по UART на 1 144 744 бода, разбирает кадры AA 55 и исполняет 21 опкод из набора WebAssembly MVP. Четырнадцать программ -- 101 байт -- лежат в ROM, собранном из той же спеки; по проводу ходят запросы и ответы, а не бинарники.

Верхний уровень подъёма платы -- STARTUPE2 для конфигурационного тактового сигнала, трёхтриггерный синхронизатор UART, светодиоды -- написан вручную (fpga/vivado/wasm_board_ax7203.v), под исключением owner-approved-foreign в том репозитории. Всё, что считает, сгенерировано из спеки; всё, что только поднимает кристалл, -- нет.

Тайминг: оценка nextpnr, от 18,57 до 70,41 МГц

Инструментарий -- openXC7: yosys с -flatten -abc9 -nocarry -nodsp -nosrl, затем nextpnr (размещатель heap, router1, seed 1). Оценка nextpnr для первого варианта -- 18,57 МГц. Переписывание i32.mul в 32-тактовую микропоследовательность сдвигов и сложений подняло оценку до 70,41 МГц при планке 68,7. Ядро стоит 3 910 из 269 200 LUT на XC7A200T -- один процент -- и 1 127 триггеров. Локальная сборка занимает около 65 секунд без Docker, битстрим -- 9 730 755 байт.

Самотест поймал первый баг, и это был наш баг

До любого прогона на железе конформансный стенд в trinity-fpga сверяет модель платы с золотым интерпретатором -- независимым интерпретатором WASM MVP со своей таблицей опкодов и общим декодером signed-LEB128, не делящим со спекой ни строчки. Пятнадцать перекрёстных проверок привязывают список портов спеки к проводам.

Самотест стенда вводит шесть отказов -- ложь, плохой опкод, разрыв последовательности, потерянный кадр, соскальзывание бита, чужая программа -- и доказывает, что каждая проверка падает на своём отказе. Именно это и поймало настоящий баг до платы: X_OFF и Y_OFF в спеке -- смещения в теле кадра, но на проводе x лежит в байте шесть, после двух байтов синхронизации. Прочитай смещения не так -- и 76 из 134 проверок падают, при полностью исправной плате. Самотест превратил это в правку до первой прошивки.

На плате

openFPGALoader прошивает битстрим по кабелю FT232H секунд за пятнадцать, без sudo, и отвечает done. Дальше плата ответила на 134 из 134 запросов точно -- шесть прогонов подряд, 804 из 804 ответов, ноль расхождений, ноль потерянных кадров, 416 ответов в секунду в темпе линии. Набор векторов закреплён хэшем:

89527478cf813f99b9e76fce77f1b846b5f3ddbf22cb212f08b5ac0eec108f8f
ЧтоРезультат
Тайминг (оценка nextpnr)оценка: 70,41 МГц при планке 68,7; 18,57 до микропоследовательности i32.mul
Площадь на XC7A200T3 910 из 269 200 LUT (1%); 1 127 триггеров
Прогоны на плате6 x 134/134 точно = 804/804; 416 ответов/с
СборкаopenXC7, локально, ~65 с, без Docker; битстрим 9 730 755 байт

Округа

Программные интерпретаторы -- wasm3, WAMR, wasmi -- исполняют WASM на CPU и делают это хорошо; WASM в железе -- куда менее населённая область. За 2024-2026 появилась небольшая академическая серия рукописных WASM-on-FPGA проектов, а выгрузка eBPF на умные сетевые карты и старая линия Java-в-кремнии (picoJava, JOP) -- прецедент того, что байткод вообще может быть целью для железа. Отличие здесь не в скорости -- против них не заявлено никакой, -- а в происхождении и порядке работы: считающее ядро сгенерировано из спеки, а конформансный стенд с самотестом отказов был написан и проходил до того, как первый битстрим коснулся платы.

Чем это не является

Эпик trinity-fpga#917 -- ИИ-сгенерированное железо, исполняющее WASM -- закрыл свой MVP на кремнии. Дальше: расширять набор опкодов, грузить программы по проводу и ужимать рукописный верхний уровень до нуля.

Чего это не решает

Пруфы

Поработаем вместе

Нужно довести FPGA/RTL-задачу до замеров на железе?

Работаю по контракту и part-time с hardware-AI, FPGA/RTL и ML-системами — от спецификации и открытого тулчейна до воспроизводимых измерений.