Всем привет! Я Константин Павлов, старший инженер по разработке систем на кристалле. Работаю в группе прототипирования в компании YADRO, занимаюсь отладкой на ПЛИС исходного кода, который затем будет работать в ASIC.
В статье я расскажу об итеративной (многократной) сборке проектов ПЛИС. Зачем она нужна и какими способами — вендорскими и самописными — ее возможно реализовать. А еще на примерах из практики покажу, каких впечатляющих результатов можно добиться, используя итеративную сборку.
Что такое итеративная сборка
Разработчики, использующие языки программирования общего назначения, например C или Python, привыкли, что, если код написан синтаксически верно, компилятор предсказуемо качественно его соберет. Различия в производительности и эффективности работы программ, которую обеспечивают конкурирующие компиляторы, несущественны для большинства применений.
При использовании языков описания аппаратуры (HDL) дело обстоит совершенно иначе. Каждый, кто сколько-нибудь серьезно занимался разработкой на HDL, не раз упирался в ограничения выбранной аппаратуры. Или оказывался в ситуации, когда IDE вообще не может собрать проект без нарушения временных ограничений (в просторечии — «времянки не сходятся»). То есть проект собрался, но практического смысла в полученных артефактах нет: они неработоспособны.
Даже абсолютно корректный HDL-код не всегда успешно заработает на целевой аппаратной платформе и с необходимой производительностью. Рассмотрим факторы, которые могут влиять на успешность сборки.
Архитектура выбранного семейства ПЛИС.
Серии ПЛИС отличаются по производительности, емкости, доступным вариантам корпуса. Даже в рамках одной серии от одного производителя существуют чипы с различным спидгрейдом и различными достижимыми максимальными частотами. Количество тактовых ресурсов, линий IO, специализированных аппаратных блоков всегда конечно и может вдруг оказаться недостаточным для выполнения поставленной задачи.
Среда разработки (IDE).
Выбрав модель ПЛИС, разработчик зачастую вынужден использовать определенную безальтернативную среду разработки, предоставленную вендором. IDE разных производителей по-разному реализуют процесс сборки, имеют различный функционал и дают разные возможности для анализа дизайна. Необходимость уметь пользоваться всевозможными наборами инструментов требует от разработчика дополнительных усилий и кругозора.
Параметры модулей проекта.
HDL позволяют описывать модули параметрически. Например, условный двоичный счетчик может иметь параметр N, определяющий его ширину. Такой счетчик без проблем имплементируется в проекте ПЛИС, если параметр N равен 8. Но, если решаемая задача требует реализовать счетчик шириной N равной 1024, этот абсолютно корректный код можно будет воплотить в жизнь только при условии снижения тактовых частот. А это часто недопустимо исходя из требований решаемой задачи.
Констрейны.
Файлы ограничений в формате SDC/XDC — стандарт в индустрии. Их необходимо причислять к исходным файлам проекта ПЛИС наряду с HDL-кодом, поскольку они существенно влияют на то, как IDE будет интерпретировать HDL, на каких низкоуровневых примитивах и в каком месте на кристалле реализует логические функции. В крупных проектах ПЛИС работа по наполнению и оптимизации файлов констрейнов является наиболее трудным и творческим этапом во всем маршруте разработки.
Это только основные факторы, влияющие на успешность сборки проекта ПЛИС. Мы видим, что «голые» HDL-исходники — это далеко не все, что необходимо для успешной сборки. FPGA-разработчик сталкивается с огромной неопределенностью, вызванной десятками факторов, на всех этапах развития проекта.
Итеративная сборка (далее И. С.) — это прием, который позволяет разработчикам ПЛИС с помощью автоматизированных средств запускать сборку проекта многократно, с различными настройками, чтобы исследовать предполагаемые технические решения или оптимизировать уже используемые. И. С. позволяет существенно снизить неопределенность, вызванную различными факторами, и проверить устойчивость проекта или его частей к изменению внешних условий.
Задачи, которые помогает решить И. С.:
Выбор электронной компонентной базы.
Такая задача возникает на раннем этапе разработки проекта, когда мы только прорабатываем его архитектуру и состав аппаратных средств. И. С. может помочь с выбором оптимальных по характеристикам моделей ПЛИС для использования в целевом проекте. Запустив сборку заготовки будущего проекта под несколько моделей ПЛИС, можно проанализировать, какая из них будет наилучшим образом удовлетворять требованиям.
Проверка синтезируемости кода во всем диапазоне перестройки параметров.
В зависимости от значения параметра может меняться внутренний алгоритм реализации модуля. И. С. дает возможность автоматизированно проверить все варианты реализации, уменьшив количество ошибок и сократив время на отладку.
Контроль отсутствия временных нарушений.
В зависимости от значений параметров HDL-модулей меняется сложность имплементации в ПЛИС. В ходе разработки HDL-кода разработчик не всегда осознает, какова на практике область допустимых значений для перестройки параметров, какие комбинации параметров вызовут нарушения временных ограничений. И. С. дает возможность проверить, в каком диапазоне значений параметров реализованный HDL-код будет пригодным к использованию. Исключается ситуация, когда минимальные изменения в проекте приводят к неожиданной деградации характеристик и/или увеличению сроков разработки.
Выбор наилучшей стратегии синтеза и имплементации.
Такая задача обычно возникает на завершающем этапе разработки проекта, когда все необходимые функции реализованы и отлажены по отдельности. Разработчику необходимо собрать проект целиком, поэтому заполненность ПЛИС близка к 100%. Возникает потребность не просто «как-то» собирать проект с дефолтными настройками, а делать это эффективно, за минимальное время, при этом без ухудшения качества. И. С. на данном этапе может помочь проварьировать стратегии имплементации, доступные в IDE, и выбрать оптимальную для конкретного проекта.
Если сформулировать коротко, И. С. дает разработчикам дополнительную информацию о поведении разрабатываемого кода и снижает риски получить некачественный, неустойчивый к изменениям проект.
Способы организации итеративной сборки
Разобравшись в терминологии и преимуществах, которые дает многократная сборка проектов ПЛИС, предлагаю рассмотреть, какими средствами мы можем организовать И. С. в своих проектах. Начнем с вариантов, которые я считаю недостаточно хорошими, а далее перейдем к более рациональным решениям.
Самый наивный и трудоемкий способ реализации И. С. — это ручная сборка и компиляция нескольких проектов подряд. Мы вручную делаем копии «базового» проекта, вносим изменения в код, затем вручную запускаем каждый вариант на сборку. После того, как все компиляции завершатся, нужно будет пройтись по директориям, прочитать отчеты и попробовать из них что-то понять. Я считаю, что выявить таким образом какие-то закономерности будет сложно, если вообще возможно.
Второй способ, который можно предложить, — это использование подхода Design runs. Он позволяет скомпилировать проект с разными стратегиями сборки или под разные модели ПЛИС, не выходя за пределы единственного открытого дизайна в окне IDE. Недостаток этого подхода в том, что он доступен только в среде AMD/Xilinx Vivado. Design runs — встроенная стандартная функция Vivado, но способ по-прежнему полуручной, поскольку детальный анализ и сравнение результатов сборки не автоматизированы.
В среде Intel/Altera Quartus есть похожая, но не полностью аналогичная функция, которая называется SEED. SEED — это числовой параметр проекта, при изменении которого меняется и расстановка примитивов проекта на кристалле. Меняя SEED, можно собрать «другой вариант» проекта с другими максимальными рабочими частотами (Fmax). Собрав несколько аналогичных проектов, можно выбрать тот, который обеспечивает наилучшие характеристики. Аналогично Design runs, это полуручной способ. Детальный анализ и сравнение результатов сборки тоже не автоматизированы.
Следующий способ — это инкрементальная компиляция. С ней мы можем переиспользовать для сборки результаты предыдущих запусков. Если от запуска к запуску изменения проекта незначительны, IDE будет собирать заново только изменившиеся части дизайна. Так мы можем на основе одной «удачной» сборки получать ее доработанные варианты с улучшенными характеристиками. Инкрементальная компиляция доступна во всех известных IDE для разработки ПЛИС, однако реализована везде по-разному. Способ нельзя назвать удобным для реализации И. С. Да и детальный анализ и сравнение результатов сборки здесь тоже никак не автоматизированы.
Утилита Quartus Design Space Explorer
От простых и неэффективных методов многократной сборки FPGA перейдем к тем, которые заслуживают большего внимания. В частности — к утилите dse.exe из пакета Intel/Altera Quartus. Ее окно показано на рисунке.
Здесь речь уже идет о качественном, автоматизированном решении для И.С. Суть работы с утилитой проста. Мы задаем папку с базовым проектом и настраиваем, с какими параметрами необходимо собирать проект, какие параметры проварьировать и в каких пределах. Можно пробовать собирать проект с различными значениями SEED или менять стратегии сборки.
После настройки и запуска утилита самостоятельно сделает локальные копии базового проекта, внесет изменения в каждую копию, в параллель проведет сборку и покажет агрегированный отчет. Каждый из собранных проектов доступен на диске для дальнейшего анализа.
Пример использования dse.exe
Однажды я разрабатывал среднего размера FPGA-проект ( ~10 килоLUT ), в котором была критически важна производительность преобразования потока данных. Я считал, что алгоритм обработки сделан уже достаточно хорошо, поэтому увеличивать производительность планировал за счет повышения тактовой частоты. Я задался вопросом, а можно ли получить бо́льшие частоты — Fmax в терминах IDE Quartus — просто изменяя внешние условия, например, операционную систему и версию среды. Здесь-то мне и пригодилась утилита dse.exe.
Я сделал несколько виртуальных машин с Windows 7 и Linux Manjaro, установил на них различные версии Quartus Lite Edition и воспользовался Design Space Explorer, чтобы перебирать значения SEED. Это позволило получить статистику по сборке одного и того же FPGA-проекта для каждой из комбинаций «операционная система/версия IDE». Чтобы среда собирала проект с максимальными возможными частотами Fmax, в констрейнах была назначена заведомо недостижимая тактовая частота дизайна в 1 ГГц.
Полученные значения Fmax приведены в таблице и на графиках ниже.
Это совсем не очевидно, но, оказывается, достижимая рабочая частота собранного проекта ПЛИС существенно отличается в зависимости от внешних, совершенно искусственных факторов.
Худший результат сборки — проект работает максимум на 207 МГц. Лучший из полученных результатов — проект работает на частоте 374 МГц. Из раза в раз на Quartus версии 13.1 на Windows получаются плохие результаты. А если взять Linux и собирать проект в Quartus 20.1 с агрессивными настройками, тот же самый код компилируется с Fmax практически в два раза выше!
Это реальный пример, какую пользу можно получить от итеративной сборки. Сделав несколько запусков компиляции в различных условиях, мы выявили закономерности, позволяющие оптимизировать параметры дизайна. В данном случае мы получили почти двукратный прирост в производительности прошивки ПЛИС, просто поменяв машину, на которой собираем релиз!
Мой подход к итеративной сборке
Design Space Explorer — отличная утилита, но она работает только с проектами для ПЛИС Intel/Altera. Прямых аналогов от других производителей я не знаю.
Мне захотелось создать инструмент, который бы работал похожим образом, но был более универсален. Он должен предоставлять возможность делать копии базового проекта ПЛИС, менять параметры запуска компиляции и итеративно собирать проекты. А также иметь средства для автоматизированного анализа результатов.
Идею я реализовал в виде шаблона для итеративной сборки FPGA-проектов. Он состоит из нескольких HDL-исходников и вспомогательных скриптов. Любой более сложный проект можно будет сделать на основе шаблона и поэкспериментировать с И. С. Я разработал это решение с расчетом, чтобы его можно было легко адаптировать под любую IDE для разработки ПЛИС и получить максимальную гибкость в применении.
Рассмотрим вариант шаблонного проекта, предназначенный для итеративной сборки ПЛИС AMD/Xilinx. Структура файлов проекта следующая:
├── Makefile
└── base
├── Makefile
├── scripts
│ ├── compile_vivado.tcl
│ ├── get_fmax_vivado_special.tcl
│ └── set_prj_vivado.tcl
└── src
├── define.vh
├── fast_counter.sv
├── main.sv
└── timing.xdc
Проект состоит из головного, или «внешнего», makefile
и директории базового проекта. Базовый проект base
содержит директорию src/
с исходными файлами HDL, директорию scripts/
с вспомогательными TCL-скриптами, и «внутренний» makefile
.
«Внешний» makefile
«Внешний» makefile нужен, чтобы скопировать основной проект ПЛИС необходимое количество раз. В нем также определяется переменная VAR
, которая будет определять различия дочерних проектов друг от друга. В шаблоне реализован последовательный перебор натуральных чисел от VAR_MIN
до VAR_MAX
, однако ничто не мешает реализовать любой, сколь угодно сложный закон перестройки параметров. Переменная внедряется в дочерние проекты через автогенерируемый файл define.vh
. Для каждого значения переменной VAR
будет создан и независимо собран дочерний проект.
Для удобства анализа результатов сборки множества проектов, во «внешнем» makefile предусмотрен отдельный job под названием report
. Мы в цикле проходим по сгенерированным дочерним проектам и достаем из отчетов только ту информацию, которая нам интересна в данный момент.
Листинг «внешнего» makefile
VAR_START = 5
VAR_STOP = 64
VAR = $(shell seq $(VAR_START) ${VAR_STOP})
JOBS = $(addprefix job,${VAR})
.PHONY: all report clean
all: report
echo '$@ success'
${JOBS}: job%:
mkdir -p ./$*; \
cp -r ./base/* ./$*; \
echo "// Do not edit. This file is auto-generated" > ./$*/src/define.vh; \
echo "\`define WIDTH $*" >> ./$*/src/define.vh; \
$(MAKE) -C ./$* all
fmax.csv: ${JOBS}
echo '# FMAX summary report for iterative compilation' > fmax.csv; \
echo 'var, clk1, clk2' >> fmax.csv; \
export BC_LINE_LENGTH=0; \
v=$(VAR_START); while [ "$$v" -le $(VAR_STOP) ]; do \
echo $$v | xargs echo -n >> fmax.csv; \
echo -n ', ' >> fmax.csv; \
(cat ./$$v/test.runs/impl_1/main_timing_summary_routed.rpt | \
grep -A6 '| Intra Clock Table' | tail -n1 | gawk {'print $$2'} | \
xargs echo -n '1000/(1-'; echo ')') | bc | xargs echo -n >> fmax.csv; \
echo -n ', ' >> fmax.csv; \
(cat ./$$v/test.runs/impl_1/main_timing_summary_routed.rpt | \
grep -A7 '| Intra Clock Table' | tail -n1 | gawk {'print $$2'} | \
xargs echo -n '1000/(1-'; echo ')') | bc | xargs echo -n >> fmax.csv; \
echo >> fmax.csv; \
v=$$((v+1)); \
done
report: fmax.csv
cat fmax.csv
clean:
v=$(VAR_START); while [ "$$v" -le $(VAR_STOP) ]; do \
rm -rfv $$v; \
rm -rfv fmax.csv; \
v=$$((v+1)); \
done
«Внутренний» makefile
«Внутренний» makefile предназначен для сборки конкретного дочернего проекта. В нем указывается имя проекта, модель ПЛИС и состав исходных файлов. Этот файл необходимо заполнить один раз при подготовке базового проекта.
Листинг «внутреннего» makefile
PROJ = test
# selecting largest pin count part in the family
PART = xc7a200tffv1156-1
# # selecting target part
# PART = xc7k325tffg900-2
SRCS = src/main.sv \
src/define.vh \
src/fast_counter.sv
XDCS = src/timing.xdc
SCRIPTS = scripts/allow_undefined_ports.tcl
#------------------------------------------------------------------------------
.PHONY: all info setup compile clean
all: setup compile
info:
echo -e \\n ' Project name: ' $(PROJ) \
\\n ' Part: ' $(PART) \
\\n ' Sources: ' $(SRCS) \
\\n ' Constraints: ' $(XDCS) \
\\n ' Scripts: ' $(SCRIPTS)
setup: .setup.done
.setup.done: $(SRCS) $(SCRIPTS)
# passing args as files
echo $(PROJ) > .proj
echo $(PART) > .part
echo $(SRCS) | tr -s " " "\012" > .srcs
echo $(XDCS) | tr -s " " "\012" > .xdcs
echo $(SCRIPTS) | tr -s " " "\012" > .scripts
# processing
vivado -mode batch -source scripts/set_prj_vivado.tcl
# cleaning
rm -f .proj
rm -f .part
rm -f .srcs
rm -f .xdcs
rm -f .scripts
compile: .compile.done
.compile.done: .setup.done
vivado -mode batch -source scripts/compile_vivado.tcl
clean:
$(shell ./clean_vivado.sh )
rm -f $(PROJ).xpr
rm -f .part
rm -f .srcs
rm -f .xdcs
rm -f .scripts
Вспомогательные TCL-скрипты
В среду Vivado встроен скриптовый язык TCL. Поэтому для сборки проектов потребовалось подготовить несколько вспомогательных TCL-скриптов.
В скрипте set_prj_vivado.tcl
мы считываем параметры проекта, прокинутые из «внутреннего» makefile, создаем проект Vivado под выбранную модель ПЛИС, добавляем исходники в проект.
Код скрипта set_prj_vivado.tcl
# quickly read args, and don't even close file handles :)
set proj [split [read [open ".proj" r]] "\n"]
set part [split [read [open ".part" r]] "\n"]
set srcs [split [read [open ".srcs" r]] "\n"]
set xdcs [split [read [open ".xdcs" r]] "\n"]
set scripts [split [read [open ".scripts" r]] "\n"]
# remove last empty elements
set idx [lsearch ${proj} ""]
set proj [lreplace ${proj} ${idx} ${idx}]
set idx [lsearch ${part} ""]
set part [lreplace ${part} ${idx} ${idx}]
set idx [lsearch ${srcs} ""]
set srcs [lreplace ${srcs} ${idx} ${idx}]
set idx [lsearch ${xdcs} ""]
set xdcs [lreplace ${xdcs} ${idx} ${idx}]
set idx [lsearch ${scripts} ""]
set scripts [lreplace ${scripts} ${idx} ${idx}]
#puts "proj = [list ${proj}]"
#puts "part = [list ${part}]"
#puts "srcs = [list ${srcs}]"
#puts "xdcs = [list ${xdcs}]"
#puts "scripts = [list ${scripts}]"
# for example, xc7k325tffg900-2
create_project -force ${proj} . -part ${part}
if {${srcs} ne ""} {
add_files -fileset sources_1 ${srcs}
update_compile_order -fileset sources_1
}
if {${xdcs} ne ""} {
add_files -fileset constrs_1 ${xdcs}
}
if {${scripts} ne ""} {
add_files -fileset utils_1 ${scripts}
}
set aup_script "scripts/allow_undefined_ports.tcl"
if {${aup_script} in ${scripts}} {
set_property STEPS.WRITE_BITSTREAM.TCL.PRE [get_files ${aup_script} -of [get_fileset utils_1]] [get_runs impl_1]
}
exec touch .setup.done
Скрипт сompile_vivado.tcl
нужен, чтобы запустить синтез и имплементацию. Затем нам нужно просто дождаться завершения процесса.
Код скрипта сompile_vivado.tcl
open_project test.xpr
reset_runs impl_1
launch_runs impl_1
wait_on_run impl_1
#open_run impl_1
#write_bitstream -force test.bit
# TODO create marker file only when Vivado is successful
exec touch .compile.done
Запуск итеративной сборки нужно производить из корня проекта командой make -j
. Компиляция дочерних проектов происходит параллельно. Утилита make контролирует, сколько независимых процессов компиляции будут выполняться одновременно. Как только один из процессов сборки завершится, make запустит на сборку очередной дочерний проект.
Преимущества предложенного решения
Компактный код, который легко адаптировать под задачу. При необходимости шаблон легко корректировать и поддерживать. Например, сделать итерации не по одному, а по двум параметрам в дочерних проектах.
Простота. Мы не применяем никаких изощренных техник, нам не нужно устанавливать или изучать дополнительные технологии. Утилита make широко известна и активно используется в индустрии, работает везде.
Предложенный подход актуален при работе с любой средой проектирования, с ПЛИС любого производителя. В статье описан вариант шаблона для Vivado, но можно поменять запуск Vivado на запуск Quartus, Gowin EDA, IceCube и любого другого САПР или тулчейна. Мы получили универсальный инструмент для И.С., не заточенный на определенного вендора или конкретную серию ПЛИC.
Встроенные возможности по анализу отчетов. Команды, которые мы можем использовать в make-файле, универсальны. В нашем распоряжении весь арсенал текстовых утилит типа sed, awk и прочих. У нас нет так называемого vendor lock: мы используем технологии, которые одинаково работают с любым проектом и на любой аппаратной платформе.
Шаблон для итеративной сборки FPGA-проектов, который мы рассмотрели, полностью доступен в моем GitHub-репозитории. Вариант того же шаблона, но адаптированного под среду Quartus, вы найдете по этой ссылке.
Всем удачи! Исследуйте свои проекты ПЛИС с помощью итеративной сборки.
Комментарии (25)
nikolz
11.07.2024 11:02В данном случае мы получили почти двукратный прирост в производительности прошивки ПЛИС, просто поменяв машину, на которой собираем релиз!
Вы сравнивали полученные прошивки на железе? В реальности какое совпадение расчетного быстродействия с действительным?
По-моему , это, как минимум, странно, что ОС виртуальной сборки влияет на быстродействие конечной прошивки.
Возможно, что 200 при сборке под Windows равно в железе 250 при сборке под Linux.
pConst Автор
11.07.2024 11:02Возможно, что 200 при сборке под Windows равно в железе 250 при сборке под Linux.
Вполне логичное рассуждение. В IDE встроен временной анализатор, который делает для нас расчеты слеков и Fmax. Полное знание о том, как делаются эти расчеты, и какой там уровень пессимизма заложен - есть только у производителя. Нам ничего не остается, кроме как доверять этим отчетам
pConst Автор
11.07.2024 11:02Как вы предлагаете проверить "действительную" производительность? Что и чем измерять? =)
nikolz
11.07.2024 11:02Навскидку.
1) спросил бы у разработчиков IDE. Они, как минимум, должны доказать, что их IDE проектируют реальное, а не фантастику. Т е у них должны быть тесты оценки ошибок проектирования.
2) Сделал бы серию тестовых разработок от простого к сложному для Win и Linux и оценил различие реального и виртуального.
------------------
Но, как минимум, странно, что Вы не тестируете реальную производительность и не проверяете реальность виртуальных устройств.
"Если на клетке слона прочтешь надпись «буйвол», не верь глазам своим."
Козьма Прутков
Brak0del
11.07.2024 11:02Но, как минимум, странно, что Вы не тестируете реальную производительность и не проверяете реальность виртуальных устройств.
Странно было бы это делать. Коммерческие EDA для ПЛИС -- это тщательно отлаженный в части алгоритмов софт. В него вложены десятки лет исследований и миллиарды долларов денег. ПЛИС работают в медицине, энергетике и прочей критической инфраструктуре, в науке и т.д. Если бы там были такие ошибки, как вы предполагаете, то вендоров EDA давно бы засыпали исками и мы бы это не обсуждали. Так что лучше исходить, что железо при заданных температурных и прочих условиях будет работать корректно на тех частотах, что показывает EDA.
nikolz
11.07.2024 11:02Тогда тем более странно, что Вы получаете под разными ОС разные результаты и полагаете, что это будет так же на реальном железе.
Скорее всего, что на разных ОС получается разный масштаб оценки времени работы вашей прошивки. Тогда у Вас время измеряется в попугаях. На винде - это зеленые попугаи, а на Линукс синие. И они разные по цвету.
pConst Автор
11.07.2024 11:02+1Давайте немного отвлечемся от ОС и начнем с другого:
Пускай ОС и версия IDE одна и та же. Берем два одинаковых проекта и собираем их с разными SEED. Логика раскладывается на чипе различным образом, и поэтому в отчетах тайминга видим различные Fmax. Логично?
Теперь собираем одинаковые проекты в разных версиях IDE на одной ОС, SEED не трогаем. Разные версии среды отличаются версиями библиотек, или, может, какими-то настройками, реализацией алгоритмов, наличием или отсутствием дополнительных шагов оптимизации. Снова получим различную разводку логики на кристалле и разные Fmax
Ну и возвращаемся к ОС. Снова берем два идентичных проекта. Как и в случае 2, на процесс сборки будут влиять внешние условия. Расстановка примитивов на кристалле снова будет отличаться, что повлияет на Fmax
В итоге, на Fmax во всех рассмотренных случаях влияет один фактор - физическое расположение примитивов и связей между ними. Механизм одинаковый во всех трех случаях. Считать, что расчеты временного анализатора в одной из ОС "подкручены" - это из разряда теорий заговора =)
PeeWeee
11.07.2024 11:02+1Скорее всего, что на разных ОС получается разный масштаб оценки времени работы вашей прошивки. Тогда у Вас время измеряется в попугаях. На винде - это зеленые попугаи, а на Линукс синие. И они разные по цвету.
Скорее всего, Вы мало знакомы с ПЛИС и софтом для разработки под них. Это не упрек лично Вам, тут скорее претензия к автору.
Все эти методики "гаданий на сиде" и так ограниченно применимы и, главное, вызывают уныние напоминанием завимости разработчика прошивок ПЛИС от вещи в себе - проприетарной среды разработки, которая не во всех моментах адекватно задокументирована, и которую в большинстве случаев невозможно заменить.
А попытка об этом рассказать в краткой статье, в том числе и тем, кто не ходит сам по этим граблям, местами на ощупь в потемках, создает привратное впечатление "мартышек, дергающих ручки оргАна, наугад в ожидание симфонии". Такой подход тоже бывает, и чаще чем хотелось бы. Но спешу заверить господ софтварных программистов - в RTL программирование недостаток квалификации и обмена опытом(в силу малочисленностии, специфичности, обьективной закрытости, отсутствия 300какосекунд) частично компенсируется реалтаймом выполнения и необходимостью взаимодействия с физическим миром. Вообщем откровенные мартышки "х..к, х..к и в продакшен" прилично отсеиваются на начальном этапе.
Brak0del
11.07.2024 11:02Тогда тем более странно, что Вы получаете под разными ОС разные результаты и полагаете, что это будет так же на реальном железе.
Но ведь не странно. Имплементация проекта, place & route -- это NP-полная задача. Поэтому лучшее решение без полного перебора найти сложно, но можно попытаться к нему приблизиться с помощью эвристик. На разных постановках будут построены разные решения. То, какое решение получится, существенно зависит от начальных условий, в том числе от порядка обхода, доступных ресурсов, порядка окончания подзадач и т.д. Даже в пределах одной ОС и одной среды разница обязательно будет на многопоточке, о чём упоминал раньше. По поводу ресурсов, насколько понимаю, в зависимости от свободной памяти/кэша тулза будет выбирать на какие порции разбивать задачу и отсюда тоже выползут различия. Возможно, в примере выше разница в том, что линукс выделяет немного больше памяти для тулзы.
Итого: имеем разные начальные постановки для задачи, которая существенно зависит от начальных условий, отсюда пляшут и все остальные различия. В результате получаем разные правильные решения одной и той же задачи, которые удовлетворяют таймингам и прочим констрейтам. Побитовое совпадение прошивок можно рассматривать как ещё один констрейнт, который как минимум некоторые тулы не соблюдают до тех пор, пока специально их об этом не попросишь.
Скорее всего, что на разных ОС получается разный масштаб оценки времени работы вашей прошивки.
Это не так. Масштаб один и тот же. В документации есть инструкции как получить побитовое совпадение на разных ОС.
nikolz
11.07.2024 11:02Если я правильно понял, то в результате на разных ОС получились разные конфигурации железа и разные прошивки. И эти разности порождаются не параметрами IDE, не исходными данными, а особенностями исполнения IDE в конкретной ОС.
Если так, то вообще ничего не понятно, по какой причине одна и та же IDE с одинаковыми параметрами и алгоритмом дает различные прошивки в зависимости от ОС.
Ведь при исполнении задачи (одной задачи, без просмотра одновременно кино и игры в виртуальную реальность), ОС вообще не влияет на алгоритм задачи(IDE).
Но если разработчикам все это устраивает, то пусть будет так как есть. Успехов в изучении особенностей ОС.
Brak0del
11.07.2024 11:02Если я правильно понял, то в результате на разных ОС получились разные конфигурации железа и разные прошивки.
Да.
Ведь при исполнении задачи (одной задачи, без просмотра одновременно кино и игры в виртуальную реальность), ОС вообще не влияет на алгоритм задачи(IDE).
Влияние есть. Если упрощенно, то в ходе размещения на кристалле EDA разобьёт проект на планарные куски, каждый кусок будет размещаться/разводиться отдельно, например отдельным потоком. Затем результаты будут сшиты вместе как лоскутное одеяло. В зависимости от порядка завершения потоков на швах будут различия. Они обычно непринципиальны, но побитово прошивки получатся разные. Порядок завершения потоков зависит от ОС и от прочих вещей. Если все задачи выполняются на одном потоке, то различий на швах не будет.
Ещё одна причина скорее всего в размерах кусков, на которые разбивается задача. Насколько могу судить они как-то связаны с размером доступной оперативы и/или с размером кэша. Это тоже место соприкосновения с ОС.
nikolz
11.07.2024 11:02В зависимости от порядка завершения потоков на швах будут различия.
Эта особенность IDE указана разработчикам в документации?
Как минимум должно быть указано, а еще лучше в самом IDE устанавливается приоритет решения задач в потоках. В любом случае разработчики должны это знать и предупреждать клиентов о сюрпризах.
Если этого нет в документации то это ошибка IDE. Я бы выкатил претензию разработчикам,либо попросил их решить указанную проблему, а не занимался изучением влияния погоды на движение луны.
В зависимости от порядка завершения потоков на швах будут различия. Они обычно непринципиальны, но побитово прошивки получатся разные.
Ну, да. Судя по статье, 20% быстродействия - это по Вашему "непринципиально"?
Brak0del
11.07.2024 11:02Эта особенность IDE указана разработчикам в документации?
Да. И она экономит много времени имплементации, иногда процентов 40-50. Если имплементация занимает час или 3 часа, то это ощутимо.
Ну, да. Судя по статье, 20% быстродействия - это по Вашему "непринципиально"?
Добро пожаловать в мир NP-полных задач. Эвристики не обещают всегда строить оптимальные решения. Но опытный инженер всегда найдёт, где добыть пару лишних процентов. По поводу конкретно 20%, конечно есть ещё вопрос к постановке эксперимента, соблюдены ли системные требования вендора по оперативе и т.д. EDA может не построить качественное решение, если на слабом железе пытаться имплементировать.
nikolz
11.07.2024 11:02+1Я с Вами согласен. Но статью-то написали не дилетанты, а спецы из компании YADRO. Поэтому и удивляюсь и задаю вопросы.
old_bear
11.07.2024 11:02Какая-то лютая ерунда написана про "зависимость от ОС".
Сравнивайте одинаковые версии с одинаковыми настройками и будет всё совпадать в пределах дёрганий генератора случайных чисел, который обильно используется в процессе P&R. На вашем же графике видно, что на обеих ОС результаты как 17-ых так и 20-ых версий в одних и тех же коридорах колеблются.
Вполне ожидаемо что старенькая 13-я версия хуже умеет в P&R и что агрессивные настройки дают прирост. Включите эти агрессивные настройки в 20-й версии на Win и получите статистически похожий результат.Поправьте пожалуйста эту часть в статье чтобы людей в заблуждение не вводить. Особенно тех, кто судя по комментариям слабо понимает откуда этот Fmax получается.
helmm
11.07.2024 11:02+1Design Space Explorer — отличная утилита, но она работает только с проектами для ПЛИС Intel/Altera. Прямых аналогов от других производителей я не знаю.
У Xilinx похожая функциональность есть для чипов 6-ой и более ранних серий - SmartXplorer.
malishich
А Вы не в курс о причинах почему одна и та же версия Quartus даже на разных ОС собирает по разному, вроде бы как ожидается некая детерминированность. Просто никогда не собирал на Linux, открытие для меня такое поведение.
pConst Автор
В разных ОС вызовы системных функций реализованы по-разному. У Linux свой API, у винды - свой. Поэтому и разница. А если вы не меняете ОС и версию IDE - то производитель гарантирует детерминированность. То есть выходные файлы будут бит-в бит идентичными.
mpa4b
Звучит как "вызовы системных функций реализованы по-разному, потому и сортировка даёт разные результаты".
Во-1, была задана заведомо недостижимая цель по частоте и в таком случае нет никакой гарантии, что софт всё ещё попытается выжать максимум, во-2 видимо, "понимая это" (при помощи каких-нибудь эвристических алгоримтов) софт ограничивает попытки фиттинга ну например каким-то временем (везде разным), и тут вылезает и рандом, и разница между машинами/виртуалками/etc.
pConst Автор
В своих догадках мы можем опираться на документацию производителя. А производители говорят нам, что используют так называемый "timing driven" синтез и имплементацию. https://www.intel.com/content/www/us/en/programmable/quartushelp/17.0/logicops/logicops/def_synth_timing_driven_synthesis.htm
https://docs.amd.com/r/en-US/ug904-vivado-implementation/Routing
Это означает, что среда будет использовать тем более сложные и времязатратные алгоритмы, чем более высокие таргеты по частоте мы задаем.
А если цели добиваться высоких частот нет - среда будет экономить время и завершит сборку. Хотя возможности дополнительной оптимизации дизайна у нее еще есть
eugenk
У меня был случай с ice40 (Lattice). Делал проект под заказ. Собирал у себя под линуксом на iceCube2, всё прекрасно работало. Собирали той же самой версией iceCube2 у заказчика под виндой. Не работало. Выходные файлы бит в бит разумеется не совпадали. Не знаю как фирма-производитель тестировала собственный софт... Кончилось тем, что стали собирать инструментами проекта iceStorm. Тот давал одинаковые результаты и под линуксом и под виндой.
checkpoint
Проприетарный софт давно уже просто кусок дорогостоящего, но очень хорошо обернутого говна. Yosys + NextPNR наше всё!
pConst Автор
Далеко не всем нужна повторяемость сборки. Это просто один из нюансов, для кого-то важный, для кого-то - нет
Brak0del
Не совсем. Ещё недетерминированность даёт многопоточность. Если собираете несколькими потоками, то например в Vivado могут быть разные результаты из-за недетерминированности порядка завершения потоков и "сшивания" результата. В целом, хорошее обсуждение повторяемости для одного из вендоров есть здесь.