Tool vivado🔗

Environment variables🔗

Переменные сборочного и исполнительного окружения удобно задать в сборочном скрипте:

#-------------------------------------------------------------------------------
#
#    Environment
#
envx['ENV']['DISPLAY']            = os.environ['DISPLAY']
envx['ENV']['HOME']               = os.environ['HOME']
envx['ENV']['XILINX']             = env.XILINX
envx['ENV']['MENTOR']             = env.MENTOR
envx['ENV']['MGLS_LICENSE_FILE']  = env.MGLS_LICENSE_FILE
envx['ENV']['XILINX_VIVADO']      = env.XILINX_VIVADO
envx['XILINX_VIVADO']             = env.XILINX_VIVADO
envx['XILINX_HLS']                = env.XILINX_HLS
envx['QUESTABIN']                 = env.QUESTABIN
envx['QUESTASIM']                 = env.QUESTASIM
envx['VENDOR_LIB_PATH']           = env.VENDOR_LIB_PATH

envx['ROOT_PATH']                 = dirs.ROOT
envx['BUILD_PATH']                = dirs.BUILD

где env и dirs — объекты с параметрами, получаемые:

env  = import_config('env.yml')
dirs = import_config('dirpath.yml')

а конфигурационные файлы env.yml и dirpath представляют собой нечто подобное:

#
#   env.yml
#
parameters:
    XILINX              : = os.environ['XILINX']
    MENTOR              : = os.environ['MENTOR']

    XILINX_TOOL_VERSION : '2021.2'
    QUESTA_TOOL_VERSION : '2021.1'

    XILINX_VIVADO       : = os.path.join(XILINX, 'Vivado', XILINX_TOOL_VERSION)
    XILINX_HLS          : = os.path.join(XILINX, 'Vitis_HLS', XILINX_TOOL_VERSION)

    MGLS_LICENSE_FILE   : = os.path.join(MENTOR, 'license.dat')
    QUESTABASE          : = os.path.join(MENTOR, QUESTA_TOOL_VERSION, 'questasim')
    QUESTABIN           : = os.path.join(QUESTABASE, 'bin')
    QUESTASIM           : = os.path.join(QUESTABASE, 'linux_x86_64', 'vsim')

    VENDOR_LIB_NAME     : = 'xlib-vv' + XILINX_TOOL_VERSION + '-qs' + QUESTA_TOOL_VERSION
    VENDOR_LIB_PATH     : = os.path.join(MENTOR, 'vendor', VENDOR_LIB_NAME, 'func')
#
#   dirpath.yml
#
import : main

options:
    suffix    : _DIR

parameters:
    ROOT           : = os.path.abspath(str(Dir('#')))
    LIB            : = os.path.join(ROOT,   'lib')
    SRC            : = os.path.join(ROOT,   'src')
    COMMON         : = os.path.join(SRC,    'cfg', 'common')
    CFG            : = os.path.join(SRC,    'cfg', main.VARIANT_NAME)
    SCRIPT         : = os.path.join(CFG,    'script')
    SRC_SYN        : = os.path.join(SRC,    'pl', 'syn')
    SRC_SIM        : = os.path.join(SRC,    'pl', 'sim')
    CFG_LOCAL      : = os.path.join(CFG,    'env')
    CFG_COMMON     : = os.path.join(COMMON, 'env')
    SCRIPT_COMMON  : = os.path.join(COMMON, 'script')
    BUILD          : = os.path.join(ROOT,   'build', main.VARIANT_NAME)

Из описанных переменных окружения далее формируются пути к исполняемым файлам внешних инструментов и строится структура файлов и директорий для синтезатора и симулятора.

#-------------------------------------------------------------------------------
#
#    Tool 'vivado'
#
...
VIVADO = os.path.join(env['XILINX_VIVADO'], 'bin', 'vivado')
HLS    = os.path.join(env['XILINX_HLS'], 'bin', 'vitis_hls')
...
env['BUILD_SYN_PATH'] = os.path.join(env['BUILD_PATH'], 'syn')
...
#-------------------------------------------------------------------------------
#
#    Tool 'questa'
#
...
env['VLOGCOM']        = os.path.join(env['QUESTABIN'], 'vlog')
env['VCOMCOM']        = os.path.join(env['QUESTABIN'], 'vcom')
env['VLIBCOM']        = os.path.join(env['QUESTABIN'], 'vlib')
env['VMAPCOM']        = os.path.join(env['QUESTABIN'], 'vmap')
env['VSIMCOM']        = os.path.join(env['QUESTABIN'], 'vsim')
...
env['BUILD_SIM_PATH'] = os.path.join(env['BUILD_PATH'], 'sim')
env['SIM_CMD_SCRIPT'] = os.path.join(env['ROOT_PATH'], 'site_scons', 'site_tools', 'questa.tcl' )
...

ЗАМЕЧАНИЕ

Переменная envx['BUILD_PATH'] задаёт базовый путь для текущей сборки – место, где создаются все продукты генерации, начиная от генерируемых исходных и заголовочных файлов и заканчивая проектом синтезатора, скриптами симулятора и т.п.

Как правило, значение этой переменной связано с именем сборочного варианта – так проще избежать путаницы: все продукты генерации, компиляции, симуляции, синтеза и т.д. воздаются в директории с тем же именем, что и имя сборочного варианта, включая относительный путь.

Однако, существует возможность указать любой произвольный путь для целевой сборки, определив переменную сборочного окружения envx['BUILD_PATH'] соответствующим образом. Это позволяет, в частности, генерировать разные целевые сборки из одного и того же сборочного варианта, указав, например, разные параметры сборки (через аргументы командной строки), и, что крайне важно, такой подход позволяет запускать эти сборки параллельно.

Возможность запускать сборки параллельно актуальна при прогоне тестов на симуляторе: можно запустить несколько длительных тестов из одного и того же сборочного варианта, указав параметром разные пути к исходным файлам тестов. За счёт многоядерности современных процессоров достигается существенная экономия времени тестирования.

Переменные общего назначения🔗

Name Description Default Value
VIVADO_VERNUM Номер используемой
версии САПР Vivado
Извлекается из
env['XILINX_VIVADO']
VIVADO_PROJECT_NAME Название проекта САПР Vivado 'vivado_project'
TOP_NAME Имя модуля верхнего уровня 'top'
DEVICE Наименование ПЛИС 'xc7a200tfbg676-2'
VIVADO_PROJECT_MODE Режим работы с САПР.
В настоящее время поддерживается
только Project Mode
True
SYNCOM Команда запуска САПР в пакетном
режиме
VIVADO + ' -mode batch'
SYNSHELL Команда запуска САПР в
интерактивном режиме
VIVADO + ' -mode tcl'
SYNGUI Команда запуска САПР в
графическом режиме
VIVADO + ' -mode gui'
HLSCOM Команда запуска HLS компилятора HLS
SYN_TRACE Опция управления трассировкой
команд
' -notrace'
SYN_JOURNAL Опция ведения журнала ' -nojournal'
PROJECT_CREATE_FLAGS Опции, передаваемые Tcl
команде create_project.
Типовое значение -f (force),
что вынуждает САПР FPGA
создавать проект даже если он
открыт
''
HLSFLAGS Флаги компилятора HLS ''
VERBOSE Управляет печатью полной
командной строки выполняемого
действия
True

Директории и пути🔗

Name Description Default Value
CFG_PATH Директория текущего сборочного
варианта
os.path.abspath(os.curdir)
CONFIG_SEARCH_PATH Список путей, по которым
осуществляется поиск конфи-
гурационных файлов во время
работы сканера (обработка
секции import в конфигу-
рационных файлах)
env['CFG_PATH']
BUILD_SRC_PATH Директория, куда помещаются
сгенерированные исходные файлы
(*.svh, *.tcl)
os.path.join(env['BUILD_PATH'], 'src')
BUILD_SYN_PATH Директория, в которой создаётся
исполнительное окружение
для синтеза (проект, IP ядра и т.п.)
os.path.join(env['BUILD_PATH'], 'syn')
IP_OOC_PATH Директория для IP ядер, скриптов,
библиотеки симуляционных
моделей
os.path.join(env['BUILD_SYN_PATH'], 'ip_ooc')
BD_OOC_PATH Директория для блочных дизайнов,
создаваемых out-of-context
os.path.join(env['BUILD_PATH'], 'bd')
BUILD_HLS_PATH Директория для создания проектов
HLS, скриптов их создания и компи-
ляции и репозитория целевых IP
ядер
os.path.join(env['BUILD_SYN_PATH'], 'hls')
INC_PATH Список путей, в которых произво-
дится поиск включаемых файлов.
Поиск автоматически выполняется
в директориях, где расположены
исходные файлы, и INC_PATH
дополняет этот список элементами,
в которых исходных файлов нет,
но есть включаемые —
например, BUILD_SRC_PATH
''
IP_SCRIPT_DIRNAME Имя директории, в которую поме-
щаются скрипты для обслужива-
ния IP ядер. Сама директория
располагается в IP_OOC_PATH
'_script'
BD_SCRIPT_DIRNAME Имя директории, в которую
помещаются Tcl скрипты
создания OOC блочных
дизайнов. Сама директория
располагается в BD_OOC_PATH
'_script'
SIM_SCRIPT_DIRNAME Имя директории, где поме-
щаются скрипты для создания
симуляционных библиотек IP ядер,
блочных дизайнов, HLS IP ядер и т.п.
'sim_script'
SIM_SCRIPT_PATH Директория, содержащая скрипты
для создания симуляционных
библиотек IP ядер, блочных
дизайнов, HLS IP ядер и т.п.
os.path.join(env['BUILD_SYN_PATH'], env['SIM_SCRIPT_DIRNAME'])
HLS_SCRIPT_DIRNAME Имя директории, в которую
помещаются скрипты для создания
и компиляции HLS IP
'_script'
HLS_IP_NAME_SUFFIX Суффикс для имён HLS IP '_hlsip'

Расширения файлов🔗

Name Description Default Value
CONFIG_SUFFIX конфигурационные файлы 'yml'
TOOL_SCRIPT_SUFFIX скрипты 'tcl'
IP_CORE_SUFFIX IP ядра 'xci'
BD_SUFFIX Блочные дизайны 'bd'
DCP_SUFFIX Design Checkpoint. Архив, содержащий
результат работы САПР: синтезированный
проект, разведённый, синтезированное
IP ядро и т.п.
'dcp'
BITSTREAM_SUFFIX выходной файл 'bit'
CONSTRAINTS_SUFFIX констрейны 'xdc'
VIVADO_PROJECT_SUFFIX проект Vivado 'xpr'
V_SUFFIX Verilog 'v'
SV_SUFFIX SystemVerilog 'sv'
V_HEADER_SUFFIX Verilog header 'vh'
SV_HEADER_SUFFIX SystemVerilog header 'svh'
HLS_TARGET_SUFFIX HLS IP repository archived item 'zip'
USER_DEFINED_PARAMS Пользовательские параметры, передаваемые
на этап создания проекта САПР путём создания
соответствующих переменных в скрипте,
который создаёт проект Vivado
{}

Builders🔗

Перечислены билдеры и псевдобилдеры. Билдеры как правило не используются напрямую, т.к. они имеют вполне определённый интерфейс запуска, который далеко не всегда удобен, поэтому в скрипте сборочных сценариев обычно используются псевдобилдеры, которые по сути являются "обёртками" вокруг самих билдеров.


IpCreateScript🔗

True builder

Генерирует Tcl скрипт, с помощью которого создаётся IP ядро.


IpCreateScripts🔗

Pseudo-builder

Генерирует Tcl скрипты для создания IP ядер из списка конфигурационных файлов. Создаёт скрипты по схеме <name>-create.tcl. Использует билдер IpCreateScript.

Пример использования:

ip = read_sources('ip.yml')
...
IP_Create_Scripts = envx.IpCreateScripts(ip)

IpSynScript🔗

True builder

Генерирует скрипт для out-of-context синтеза IP ядра.


IpSynScripts🔗

Pseudo-builder

Генерирует Tcl скрипты для синтеза IP ядер из списка конфигурационных файлов. Создаёт скрипты по схеме <name>-syn.tcl. Использует билдер IpSynScript.

Пример использования:

ip = read_sources('ip.yml')
...
IP_Syn_Scripts = envx.IpSynScripts(ip)

IpCreate🔗

True builder

Создаёт IP ядро.


CreateIps🔗

Pseudo-builder

Создаёт IP ядра по списку скриптов, сгенерированы с помощью IpCreateScripts. Использует билдер IpCreate.

Пример использования:

IP_Cores = envx.CreateIps(IP_Create_Scripts)

IpSyn🔗

True builder

Синтезирует IP ядро в режиме out-of-context.


SynIps🔗

Pseudo-builder

Синтезирует IP ядра, используя в качестве зависимостей скрипты, созданные IpSynScrips и файлы самих IP ядер. Использует билдер IpSyn.

Пример использования:

IP_OOC_Syn = envx.SynIps(IP_Syn_Scripts, IP_Cores)

BdCreate🔗

True builder

Создаёт блочный дизайн на основе Tcl скрипта, описывающего используемые элементы (cells), их межсоединения и порты. Блочный дизайн создаётся в виде отдельно стоящего Vivado проекта (out-of-context). В дальнейшем блочный дизайн из такого проекта может быть подключен в рабочий проект. Методика подготовки Tcl скрипта описана по ссылке.


CreateOocBd🔗

Pseudo-builder

Создаёт проекты с блочными дизайнами на основе списка конфигурационных файлов. Использует BdCreate билдер.

bd = read_sources('bd.yml')
...
bd_ooc = envx.CreateOocBd(bd)

HlsCSynthScript🔗

True builder

Создаёт Tcl скрипт для создания HLS проекта и его компиляции. Зависимостью является yml файл параметров HLS. В результате создаётся Tcl скрипт с командами создания HLS проекта и его компиляции до элемента IP репозитория. Пример целевого скрипта:

--------------------------------------------------------------------------------
#
#   This file is automatically generated. Do not edit the file!
#
#--------------------------------------------------------------------------------

set PROJECT_NAME  adder
set TOP_NAME      adder
set DEVICE        xc7a50tftg256-1
set SOLUTION_NAME sol_1

# Project structure
open_project -reset ${PROJECT_NAME}

# Add syn sources
add_files -cflags "-g -DDATA_WIDTH=4" /opt/slon/xilinx/build-system-examples/src/hls/adder/src/adder.cpp


# Add sim sources
add_files -tb -csimflags "-g -I/opt/cad/mentor/2021.1/questasim/include -I/opt/cad/xilinx/Vitis_HLS/2021.2/include" /opt/slon/xilinx/build-system-examples/src/hls/adder/tb/main.cpp


set_top ${TOP_NAME}
# Add solution
open_solution -reset -flow_target vivado ${SOLUTION_NAME}
set_part ${DEVICE}
create_clock -period 8.0ns -name adder_clk
set_clock_uncertainty 25%

# Add hooks
source /opt/slon/xilinx/build-system-examples/src/cfg/7a50t/hls/adder/directives.tcl


csynth_design

export_design -rtl verilog -format ip_catalog -ipname adder -version 1.0 -vendor slon -library hls -output /opt/slon/xilinx/build-system-examples/build/7a50t/syn/hls/ip/adder.zip

exit
#--------------------------------------------------------------------------------

CreateHlsCSynthScript🔗

Pseudo-builder

Псевдобилдер, получающий аргументом список конфигурационных HLS yml файлов и осуществляющий запуск для каждого из них билдера HlsCSynthScript. Пример использования:

HlsCSynScripts = envx.CreateHlsCSynthScript(hls)

HlsCSynth🔗

True builder

Билдер выполняет создание HLS проекта и его компиляцию, в результате которой создаётся элемент IP репозитория, пригодный для использования в качестве IP ядра в целевом проекте. Напрямую не используется, вызывается из псевдобилдера LaunchHlsCSynth (см. ниже)


LaunchHlsCSynth🔗

Pseudo-builder

Служит для запуска создания и компиляции HLS проектов. Пример использования:

HlsCsyn = envx.LaunchHlsCSynth(HlsCSynScripts, hls)
где, HlsCSynScripts — список скриптов, полученных в результате работы CreateHlsCSynthScript, hls — список конфигурационных yml файлов HLS.


HlsIpSynScripts🔗

Pseudo-builder

Псевдобилдер осуществляет генерирование скриптов создания IP ядер из HLS IP репозитория, созданного инструментами, описанными выше. Полученные скрипты далее используются точно так же, как и скрипты для синтеза IP ядер, получаемые из конфигурационных yml файлов IP ядер.

HLS_IP_Syn_Scripts = envx.HlsIpSynScripts(HlsCsyn)

Использование результата:

#   IP scripts
IP_Create_Scripts  = envx.IpCreateScripts(ip)                 # скрипты создания IP из yml описания
IP_Syn_Scripts     = envx.IpSynScripts(ip)                    # скрипты синтеза IP
HLS_IP_Syn_Scripts = envx.HlsIpSynScripts(HlsCsyn)            # скрипты синтеза HLS IP

#   IP cores
IP_Cores           = envx.CreateIps(IP_Create_Scripts)        # создание IP ядер
All_IP             = IP_Cores + HlsCsyn                       # полный список IP ядер: пользовательских и HLS

All_IP_Syn_Scripts = IP_Syn_Scripts + HLS_IP_Syn_Scripts      # скрипты для синтеза всех IP ядер
IP_OOC_Syn         = envx.SynIps(All_IP_Syn_Scripts, All_IP)  # синтез всех IP ядер

CfgParamsHeader🔗

True builder

Создаёт заголовочные файлы HDL с параметрами, взятыми из указанных конфигурационных файлов. Генерируется пара файлов:

  • <hdl-param-filename>.svh;
  • <hdl-param-filename>_pkg.svh,

где <hdl-param-filename> – имя целевого файла, задаваемое в скрипте сборочного сценария при вызове билдера.

Если в конфигурационном файле, являющимся зависимостью, определён раздел options, в котором, в свою очередь, определены параметры prefix, suffix, то значения этих параметров конкатенируются с именами рабочих параметров, соответственно до и после:

#
#  params.yml
#
...
options:
    prefix : PARAMS_

parameters:
    DATA  : 10
    WIDTH : 8

Результат:

<hdl-param-filename>.svh:

`define PARAMS_DATA  10
`define PARAMS_WIDTH 8  

<hdl-param-filename>_pkg.svh:

...
package <hdl-param-filaname>;
    ...
    localparam int PARAMS_DATA  = 10;
    localparam int PARAMS_WIDTH = 8;  
    ...
endpackage    
...

Для параметров поддерживается три типа:

  1. целый знаковый int;
  2. с плавающей точкой real;
  3. строковый string.

Типы параметров используются в package и выводятся из типов параметров конфигурационных (yaml) файлов.


CreateCfgParamsHeader🔗

Pseudo-builder

Может принимать в качестве зависимостей строку с именами файлов, разделёнными пробелом, или список. Создаёт полный (абсолютный) путь для каждого файла и вызывает билдер CfgParamsHeader.

Пример использования:

hdl_param_deps = 'main.yml clk.yml'
...
CfgParamsHeader = envx.CreateCfgParamsHeader(os.path.join(envx['BUILD_SRC_PATH'], 'cfg_params.svh'), hdl_param_deps)

CfgParamsTcl🔗

True builder

Создаёт Tcl файл с параметрами, взятыми из указанных конфигурационных файлов. Как и билдер по генерированию включаемых HDL файлов, данный билдер распознаёт раздел options с параметрами prefix и suffix, используя их сходным образом:

#
#   dirpath.yml
#
options: 
    suffix : _DIR

parameters:
    SRC_SYN  : = '{' + os.path.join('src', 'syn') + '}'
    SRC_SIM  : = '{' + os.path.join('src', 'sim') + '}'

Результат:

set SRC_SYN_DIR {src/syn}
set SRC_SIM_DIR {src/sim}

CreateCfgParamsTcl🔗

Pseudo-builder

Может принимать в качестве зависимостей строку с именами файлов, разделёнными пробелом, или список. Создаёт полный (абсолютный) путь для каждого файла и вызывает билдер CfgParamsTcl.

Пример использования:

CfgParamsTcl = envx.CreateCfgParamsTcl(os.path.join(envx['BUILD_SRC_PATH'], 'cfg_params.tcl'), 'params.yml')

VivadoProject🔗

True builder

Создаёт проект САПР Vivado.


CreateVivadoProject🔗

Pseudo-builder

Принимает в качестве зависимостей исходные файлы HDL, файлы констрейнов и IP ядер. Генерирует имя целевого файла, обрабатывает список зависимостей, формируя полные (абсолютные) пути для каждого файла HDL и констрейнов, подготавливает результирующий список и вызывает билдер VivadoProject. Целевым файлом является <project name>.prj, который является копией project name>.xpr. Такое решение используется по той причине, что САПР Vivado в процессе работы постоянно изменяет xpr файл, что делает его непригодным в качестве цели для системы сборки. С другой стороны, целевой файл должен быть релевантным к изменениям настроек проекта, т.к. система сборки проверяет актуальность файла по MD хэшу. Копия файла проекта достаточно хорошо отвечает вышеперечисленным требованиям.

Пример использования:

xpr_hook       = read_sources('xpr_hook.yml')
...
xpr_deps = 'src_syn.yml xdc.yml'.split() + xpr_hook
...
VivadoProject = envx.CreateVivadoProject(xpr_deps , IP_Cores)

SynthVivadoProject🔗

True builder

Выполняет синтез проекта. Целевым файлом является <top name>.dcp, расположенный в <project name>.runs/synth_1.


LaunchSynthVivadoProject🔗

Pseudo-builder

Осуществляет подготовку и запуск проекта на синтез. Принимает в качестве зависимостей целевой файл проекта и перечень исходных файлов, который может быть представлен в виде строки с именами файлов, разделёнными пробелом, либо в виде списка. Запускает билдер SynthVivadoProject.

Пример использования:

src_syn  = read_sources('src_syn.yml')
xdc      = read_sources('xdc.yml')
...
syn_deps = src_syn + xdc
...
VivadoProject      = envx.CreateVivadoProject(xpr_deps , IP_Cores)
...
SynthVivadoProject = envx.LaunchSynthVivadoProject(VivadoProject, syn_deps)

ImplVivadoProject🔗

True builder

Производит этапы размещения и разводки проекта (place and route). Целевым файлом является битстрим <project name>.runs/impl_1/<top level>.bit


LaunchImplVivadoProject🔗

Pseudo-builder

Выполняет формирование целевого пути и запускает билдер ImplVivadoProject.

Пример использования:

SynthVivadoProject = envx.LaunchSynthVivadoProject(VivadoProject, syn_deps)
ImplVivadoProject  = envx.LaunchImplVivadoProject(SynthVivadoProject)

OpenVivadoProject🔗

True builder

Запускает САПР Vivado в графическом режиме с переходом в директорию проекта и загрузкой проекта. При этом проверяются зависимости и при необходимости выполняется сборка по всей цепочке. Типовой сценарий построен так, что при запуске проекта в графическом режиме проверяется актуальность целевого файла проекта и целевых файлов синтезированных IP ядер. Смысл этого в том, чтобы когда проект запущен в графическом режиме, все "пререквизиты" (проект и IP ядра) были в актуальном состоянии, и пользователь сразу мог приступить к синтезу проекта, не ожидая завершение посторонних заданий (которые в том числе "засоряют" лог сообщений), и, самое главное, чтобы всё требуемое было в актуальном состоянии, чтобы пользователю не нужно было следить за этим, поменяв тот или иной параметр сборочного варианта.


LaunchOpenVivadoProject🔗

Pseudo-builder

Запускает билдер OpenVivadoProject с фиктивной целью, что вынуждает билдер всегда включать цель в граф зависимостей как находящуюся в неактуальном состоянии.

Пример использования:

VivadoProject      = envx.CreateVivadoProject(xpr_deps , IP_Cores)
...
OpenVivadoProject  = envx.LaunchOpenVivadoProject(VivadoProject)