Блог
[замеры на одном 8-ядерном Mac, нагрузка на котором менялась за ночь; пары сняты при одинаковой нагрузке] Один ночной цикл замерил все места, где t27 собирает и ждёт, и исправил то, на что указали цифры. Тёплый t27c frontier ускорился с 55-68 с примерно до 0,9 с, неизменный битстрим находится за 0,22-0,39 с вместо 4,3-8,9 с, запуск на плате после одобрения больше не собирает сначала, а прогон корпуса, который CI делает на каждом pull request, сократился с 221-257 с до 108-140 с. Почти всё прежнее время уходило на пересчёт того, что не менялось, и на поочерёдное выполнение независимой работы. Что осталось: около 2 с на спеку в перелинковке zig, 27 с nextpnr на правку логики, около 14 с загрузки платы и гейт C-заголовков на 72 с.

В ночь с 10 на 11 октября один цикл прошёл по всем местам, где t27 что-то собирает и заставляет автора ждать, замерил каждое и поменял то, на что указали замеры. Тёплый t27c frontier ускорился примерно с минуты до долей секунды, неизменный битстрим находится за четверть секунды вместо четырёх-девяти, а прогон корпуса, который CI делает на каждом pull request, занимает половину прежнего времени. Тринадцать pull request, все смержены; журнал цикла — t27#8737.
Почти никуда на новую работу. Оно уходило на пересчёт того, что не менялось с прошлого запуска, и на то, что независимые куски работы выполнялись один за другим. Каждое исправление ниже — про одно из двух.
| Где | Было | Стало | Что изменилось | PR |
|---|---|---|---|---|
t27c frontier, тёплый | 55-68 с | ~0,9 с | Четыре хэша сгенерированного кода спеки берутся из кэша с ключом по самой спеке, всем её импортам и байтам бинарника t27c | t27#8741 |
t27c frontier после пересборки t27c | 55-68 с | 6,3 с | Кэш сначала заполняют 8 воркеров; решения затем принимаются по порядку, ровно как раньше | t27#8847 |
frontier --watch в простое | 33% ядра | 3% | Каждый взгляд смотрит stat файлов и ничего не читает, если stat не сдвинулся | t27#8825 |
frontier --watch, правка спеки, которую импортируют 16 других | 34,5 с | 13,9 с | Перепроверки идут параллельно; спеки с одинаковым именем файла остаются на одном воркере | t27#8856 |
t27c silicon, дизайн не менялся | 4,3-8,9 с | 0,22-0,39 с | Хэши инструментов (среди них chipdb на 333 МБ) берутся из кэша по stat файла; Python-пакеты читаются из venv вместо pip freeze | t27#8808, t27#8814 |
Запуск на плате после /bench approve | сначала сборка, 30-550 с | только загрузка | Бенч-агент собирает битстрим, пока задача ждёт одобрения, не трогая кабель | t27#8797 |
t27c suite --corpus-only | 394-498 с | 167-185 с | Около 13 000 запусков по спекам идут по 8 сразу; результаты собираются в порядке файлов | t27#8837, t27#8840, t27#8845 |
| Тот же шаг в CI | 221-257 с | 108-140 с | То же изменение, замер на раннерах | t27#8837 |
T27_SUITE_JOBS=1 и по умолчанию: вывод ошибок совпал байт в байт, JSON-сводки — кроме полей времени, 259 падений оба раза.pip freeze, а тот называл пакет prjxray (установленный в режиме editable) по коммиту окружающего чекаута t27. Коммит там осиротил бы все закэшированные битстримы, а правка самого prjxray в ключ не попадала (t27#8814).tri hot при первом же замере назвала silicon OVER — 28 с на исправном кэше: каждое десятое попадание в кэш намеренно пересобирается с нуля как аудит ключа, и замер попал на него. Теперь такой прогон замеряется ещё раз (t27#8872).| Путь | Сейчас | Куда уходит | Следующий шаг |
|---|---|---|---|
| Правка спеки → её вердикт | ~2 с на спеку | Zig компилирует и заново линкует тестовый бинарник при каждом запуске; сам t27c тратит 0,03 с | Убрать перелинковку: около 0,2-0,3 с на спеку. Это меняет тест-раннер, который называет каждая печать, поэтому нужна одна полная перепечать |
| Правка логики → битстрим | 36,7 с (ternary_link) | nextpnr 27,3 с: трассировка клоков ищет путь BSCAN → BUFG по всему кристаллу, а роутер настраивает каждый провод 200T, прежде чем развести несколько тысяч | Патч с побайтно тем же результатом ускоряет трассировку клоков в 1,8-5 раз (t27#8754); place-and-route, который остаётся в памяти, убрал бы настройку |
| Битстрим → плата | ~13-15 с | 9,73 МБ по JTAG на частоте по умолчанию | Более быстрый JTAG на кабеле HS2 — около 3 с; нужен тест на плате |
| Одобрение → старт запуска | до 60 с | Бенч-агент опрашивает раз в минуту | Опрос раз в 15 с — примерно на 180 вызовов GitHub API в час больше |
t27c suite | ~170 с | Гейт C-заголовков: 72 с cc -fsyntax-only на каждую спеку при каждом прогоне | Кэшировать его результаты по содержимому (t27#8900) |
Каждый следующий шаг в этой таблице меняет что-то за пределами цикла: то, что записывает каждая печать, то, что уходит на плату, бюджет GitHub API, или файл, который проект открывает для рукописного кода только с разрешения владельца. Ни один из них не сделан без владельца.
tri hot прогоняет каждый горячий путь один раз для разогрева, затем один раз с замером, и пишет OVER, если путь вышел за бюджет или запустился и упал. Это регрессионный тест для кэшей выше, и цикл теперь начинает с него каждый тик.
$ T27_OPENXC7=$HOME/t27/build/fpga/openxc7 tri hot
OK frontier, warm: 856 ms (budget 5000 ms)
OK silicon, reuse hit: 242 ms (budget 2000 ms)
Поработаем вместе
Я аудирую RTL и строю независимые побитово точные модели, затем провожу результат через синтез и, когда это полезно, проверяю на плате Artix-7. Первый модуль проверки — бесплатно.