Advanced Topics - fpga-lib/site_scons GitHub Wiki
Advanced Topics
Пользовательский билдер
Иногда возникает необходимость добавить сборку цели по зависимости, для которых нет готового билдера. Например, в проекте требуется генерировать вспомогательный файл, создаваемый из некоторых параметров. Для этого SCons
предоставляет те же средства, что и используются при описании инструментов сборки (Tools).
Следующий пример демонстрирует технологию создания пользовательского билдера (и псевдобилдера) для генерирования текстового файла, описывающего некую Capability Structure (файл передаётся компилятору в процессе сборки основных целей). Зависимостями служат конфигурационные файлы, параметры которых определяют значения структуры.
Весь процесс состоит из описания:
- исполнительной функция (action);
- функции-псевдобилдера;
- функции-инициализатора, создающей билдер и псевдобилдер.
Исполнительная функция, которая выполняет требуемые технические действия
#-------------------------------------------------------------------------------
#
# Capability structure create utility
#
from utils import *
#-------------------------------------------------------------------------------
#
# Action
#
def capstruct(target, source, env):
cfg0 = import_config(str(source[0]), env['CFG_PATH'])
cfg1 = import_config(str(source[1]), env['CFG_PATH'])
trg = target[0]
print('create auxiliary file: \'' + trg.name + '\'')
... # processing configuration parameters from cfg0 and cfg1
#-----------------------------------------------------------
#
# Create output file
#
text = ... # create contents of the output file
with open(str(trg), 'w') as out:
out.write(text)
#-------------------------------------------------------------------------------
Функция-псевдобилдер, предоставляющая удобный интерфейс
#-------------------------------------------------------------------------------
def create_capstruct(env, trg, src):
source = []
for s in src:
source.append( search_file(s, env['CFG_PATH']) )
return env.CapStruct(trg, source)
#-------------------------------------------------------------------------------
Функция-инициализатор
Здесь создаётся объект-билдер, который далее добавляется к списку билдеров текущего сборочного окружения. Затем в СО добавляется функция-псевдобилдер.
#-------------------------------------------------------------------------------
def init(env):
CapStruct = Builder(action = capstruct)
env.Append(BUILDERS = {'CapStruct' : CapStruct})
env.AddMethod(create_capstruct, 'CreateCapStruct')
#-------------------------------------------------------------------------------
Применение в скрипте сценариев сборки
Весь код помещается в один файл — например, capstruct.py
, после чего использование в скрипте сборочных сценариев выглядит так:
import os
import capstruct
...
Import('envx')
envx.Tool('vivado')
envx.Tool('questa')
...
capstruct.init(envx)
...
CapStruct = envx.CreateCapStruct(os.path.join(envx['BUILD_SRC_PATH'], 'capstruct.txt'), ['cfg0.yml', 'cfg1.yml'])
...
envx.Alias('capstruct', CapStruct)
...
Подключение аппаратной отладки с помощью Vivado ILA
Настоящий пример демонстрирует способ подключения сигналов для аппаратной отладки с использованием Intergated Logic Analyzer (ILA) из состава САПР FPGA Vivado без привлечения возможностей GUI, т.е. только с помощью редактирования текстовых файлов (исходных и скриптов).
Общие сведения
Суть метода сводится к следующему:
- В соответствующих исходных файлах выбираются сигналы, с которыми требуется работать с помощью ILA.
- Для этих сигналов создаются локальные "дубликаты" — сигналы такого же типа, которым затем присваиваются значения интересуемых сигналов. "Дубликаты" объявляются с директивами
(* mark_debug = "true" *)
(чтобы синтезатор не удалил и не изменил эти сигналы при оптимизации). Далее сигналы-"дубликаты" и будут подключаться к пробникам логического анализатора. Такой приём используется для того, чтобы не "ломать" структуру рабочего кода и иметь возможность быстро включить или выключить отладку, не изменяя исходные файлы. - В специальный
Tcl
скрипт добавляются команды подключения назначенных для ILA сигналов, а скрипт добавляется к проекту и запускается на исполнение в начале этапа имплементации.
Реализация
В рассматриваемом примере используется исходный файл top.sv
из состава демонстрационного проекта-заготовки. Сигналами, предназначенными для наблюдения, выбраны:
logic [`WIDTH-1:0] out;
logic pll_locked;
Для них делается описание "дубликатов":
//------------------------------------------------------------------------------
//
// ILA debug
//
`ifdef TOP_DEBUG_ENABLE
(* mark_debug = "true" *) logic [`WIDTH-1:0] dbg_out;
(* mark_debug = "true" *) logic dbg_pll_locked;
assign dbg_out = out;
assign dbg_pll_locked = pll_locked;
`endif // TOP_DEBUG_ENABLE
Следует отметить, что вся секция с "дубликатами" помещена под директивы условной компиляции. Это сделано для того, чтобы можно было простым изменением значения макроса TOP_DEBUG_ENABLE
подключить этот фрагмент кода к проекту или отключить.
Далее добавляется Tcl
скрипт следующего содержания:
#--------------------------------------------------------
#
# <build variant dir>/tcl/ila.tcl
#
1. puts "\n------->>> Add net to debug probes <<<-------"
2.
3. create_debug_core ila_core ila
4. set_property ALL_PROBE_SAME_MU true [get_debug_cores ila_core]
5. set_property ALL_PROBE_SAME_MU_CNT 1 [get_debug_cores ila_core]
6. set_property C_ADV_TRIGGER false [get_debug_cores ila_core]
7. set_property C_DATA_DEPTH 1024 [get_debug_cores ila_core]
8. set_property C_EN_STRG_QUAL false [get_debug_cores ila_core]
9. set_property C_INPUT_PIPE_STAGES 0 [get_debug_cores ila_core]
10. set_property C_TRIGIN_EN false [get_debug_cores ila_core]
11. set_property C_TRIGOUT_EN false [get_debug_cores ila_core]
12. set_property port_width 1 [get_debug_ports ila_core/clk]
13.
14. connect_debug_port ila_core/clk [get_nets -hier -filter {NAME =~ *pll_inst/inst/clk_out1}]
15.
16. #-------------------------------------------------------------------------------
17. #
18. # Top module
19. #
20. if { $TOP_DEBUG_ENABLE } {
21. net2probe ila_core [get_nets -hier -filter {NAME =~ dbg_out[*]}]
22. net2probe ila_core [get_nets -hier -filter {NAME =~ dbg_pll_locked}]
23. }
24. puts "-----------------------------------------------\n"
Здесь производится настройка отладочного ядра под названием ila_core
(имя можно выбрать произвольным). Чаще всего строки 3..12 менять не приходится, т.к. эти настройки пригодны для большинства проектов. Иногда нужно изменить длину захвата данных — здесь она равна 1024 (строка 7), это минимальное значение. Как правило нужно один раз настроить значение тактовой частоты отладочного ядра (строка 14), указав источник.
И основная работа, которую нужно выполнять в процессе отладки, — это добавление/удаление сигналов для наблюдения, в данном примере это строки 20..23.
ЗАМЕЧАНИЕ. В данном примере сигналы описаны как есть, без префиксов. Это потому, что подключаемые сигналы объявлены в модуле верхнего уровня. На практике основной случай, когда подключаемые сигналы объявлены в модулях по иерархии проекта. В этом случае синтаксис подключения несколько иной:
net2probe ila_core [get_nets -hier -filter {NAME =~ *<instance name>/<signal name>}]
где <instance name>
— имя экземпляра модуля, а <signal name>
— имя сигнала.
Как можно заметить, тут тоже подключение сигналов производится по условию, которое задаёт одноимённая переменная TOP_DEBUG_ENABLE
. Команда net2probe
, используемая для подключения к сигналов к отладочному ядру, описана в файле ila_proc.tcl
, расположенном в директории служебных файлов сборочной системы (по умолчанию site_scons
). В этом же файле описана команда создания дополнительного пробника create_probe
. При создании отладочного ядра оно уже имеет один пробник по умолчанию — к этому пробнику в вышеприведённом примере сигналы и подключаются.
Необходимость создания дополнительных отладочных ядер возникает при аппаратной отладке сигналов из разных тактовых доменов. Т.к. отладочное ядро тактируется вполне конкретным тактовым сигналом, то подключать к этому ядру сигналы из других тактовых доменов некорректно. Поэтому для тех сигналов нужно создавать свои отладочные ядра, которые тактировать соответствующим образом.
Несколько пробников может понадобиться в случае, когда нужны разные условия подключения сигналов. Сигналы, подключаемые к логическому анализатору, могут служить только для наблюдения или для наблюдения и синхронизации (запуска) захвата. Очевидно, что пробник с функцией захвата требует дополнительных ресурсов со стороны FPGA для организации логики запуска — нужны регистры, хранящие условия запуска, компараторы и т.д. В то же время обычно нет необходимости иметь возможность запуска захвата для всех сигналов. Поэтому логично создать как минимум два пробника, один с типом DATA
, а другой с типом DATA_AND_TRIGGER
. Этот параметр указывается при создании пробника командой create_probe
.
Для управления всем вышеописанным удобно создать файл с параметрами:
#-----------------------------------
#
# ila.yml
#
parameters:
USE_ILA : 1
TOP_DEBUG_ENABLE : 1
который сделать зависимостью для генерируемых файлов cfg_params.svh
и ila_params.tcl
(фрагменты из файла скрипта сборочных сценариев из демонстрационного проекта:
...
hdl_param_deps = 'main.yml clk.yml ila.yml'
...
prj_impl_deps = os.path.join(dirs.CFG, 'tcl', 'ila.tcl')
...
CfgParamsHeader = envx.CreateCfgParamsHeader(os.path.join(envx['BUILD_SRC_PATH'], 'cfg_params.svh'), hdl_param_deps)
IlaParamsTcl = envx.CreateCfgParamsTcl(os.path.join(envx['BUILD_SRC_PATH'], 'ila_params.tcl'), 'ila.yml')
...
Depends(ImplVivadoProject, [prj_impl_deps])
Теперь при запуске проекта на сборку будет выполнено следующее:
create cfg params tcl: 'ila_params.tcl'
create cfg params header: 'cfg_params.svh'
create Vivado project: 'ac701'
...
***********************************
Vivado project successfully created
***********************************
...
synthesize Vivado project: 'ac701'
...
************************************************
Vivado project successfully synthesized
************************************************
...
implement Vivado project: 'ac701'
...
------->>> Add net to debug probes <<<-------
Connecting 4 nets: dbg_out[0] ... dbg_out[3]
Connecting 1 net : dbg_pll_locked
-----------------------------------------------
...
************************************************
Vivado project successfully implemented
************************************************
Как видно, на этапе имплементации (P&R) произведено успешное добавление сигналов к отладочному ядру. После загрузки битстрима в FPGA можно осуществлять наблюдение значений этих сигналов или устанавливать для них условия запуска захвата.
ЗАМЕЧАНИЕ. Необходимо контролировать подключение сигналов — в случае неуспеха Vivado выдаёт предупреждение. Обычно это случается, если программе не удаётся найти указанный для подключения сигнал или его описание не соответствует ему — например, если сигнал является многобитным, а описан без маски [*]
или наоборот — однобитный сигнал описан с такой маской.
Tcl
скрипта
Создание блочного дизайна из Методика
Инструментарий САПР Vivado
позволяет экспортировать блочный дизайн (БД) в виде Tcl
скрипта и впоследствии воссоздать из этого скрипта блочный дизайн путём запуска в консоли Vivado
. На этом обстоятельстве построена методика создания конфигурационного Tcl
скрипта, используемого в системе сборки.
Методика создания блочного дизайна состоит из следующих шагов.
- Средствами IP Integrator создаётся (отрисовывается) блочный дизайн в графическом виде.
- Через меню
File->Export->Export Block Design...
дизайн экспортируется вTcl
скрипт. - Получившийся
Tcl
файл содержит много избыточной информации, интерес представляет фрагмент в конце между строками комментариев# Create interface ports
и# Restore current instance
. Этот фрагмент необходимо скопировать в отдельный файл, который и будет представлять собой конфигурацию блочного дизайна. Именно этот фрагмент содержит описание всех cells, межсоединений и портов блочного дизайна. Для полноценного скрипта, способного воссоздать блочный дизайн, недостаёт только нескольких команд перед (пролог) и после (эпилог). Билдер блочных дизайнов системы сборки автоматически генерирует прологи и эпилоги для всех БД проекта.
Пример
В качестве примера создаётся БД сумматора с буферами FIFO и синхронизацией ввода:
После "отрисовки" БД в IP Integrator'е и экспорте БД в Tcl
файл, интересующий фрагмент представляет собой следующее:
# Create interface ports
set dinp_a [ create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:fifo_write_rtl:1.0 dinp_a ]
set dinp_b [ create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:fifo_write_rtl:1.0 dinp_b ]
# Create ports
set adder_en [ create_bd_port -dir O -from 0 -to 0 adder_en ]
set clk [ create_bd_port -dir I -type clk -freq_hz 125000000 clk ]
set dout [ create_bd_port -dir O -from 8 -to 0 -type data dout ]
set rst [ create_bd_port -dir I rst ]
# Create instance: and_gate, and set properties
set and_gate [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 and_gate ]
set_property -dict [ list \
CONFIG.C_SIZE {1} \
] $and_gate
# Create instance: c_addsub_0, and set properties
set c_addsub_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:c_addsub:12.0 c_addsub_0 ]
set_property -dict [ list \
CONFIG.A_Type {Unsigned} \
CONFIG.A_Width {8} \
CONFIG.B_Type {Unsigned} \
CONFIG.B_Width {8} \
CONFIG.Latency {1} \
CONFIG.Out_Width {9} \
] $c_addsub_0
# Create instance: fifo_a, and set properties
set fifo_a [ create_bd_cell -type ip -vlnv xilinx.com:ip:fifo_generator:13.2 fifo_a ]
set_property -dict [ list \
CONFIG.Data_Count_Width {5} \
CONFIG.Fifo_Implementation {Common_Clock_Distributed_RAM} \
CONFIG.Full_Threshold_Assert_Value {30} \
CONFIG.Full_Threshold_Negate_Value {29} \
CONFIG.Input_Data_Width {8} \
CONFIG.Input_Depth {32} \
CONFIG.Output_Data_Width {8} \
CONFIG.Output_Depth {32} \
CONFIG.Read_Data_Count_Width {5} \
CONFIG.Write_Data_Count_Width {5} \
] $fifo_a
# Create instance: fifo_b, and set properties
set fifo_b [ create_bd_cell -type ip -vlnv xilinx.com:ip:fifo_generator:13.2 fifo_b ]
set_property -dict [ list \
CONFIG.Data_Count_Width {5} \
CONFIG.Fifo_Implementation {Common_Clock_Distributed_RAM} \
CONFIG.Full_Threshold_Assert_Value {30} \
CONFIG.Full_Threshold_Negate_Value {29} \
CONFIG.Input_Data_Width {8} \
CONFIG.Input_Depth {32} \
CONFIG.Output_Data_Width {8} \
CONFIG.Output_Depth {32} \
CONFIG.Read_Data_Count_Width {5} \
CONFIG.Write_Data_Count_Width {5} \
] $fifo_b
# Create instance: not_gate_0, and set properties
set not_gate_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 not_gate_0 ]
set_property -dict [ list \
CONFIG.C_OPERATION {not} \
CONFIG.C_SIZE {1} \
CONFIG.LOGO_FILE {data/sym_notgate.png} \
] $not_gate_0
# Create instance: not_gate_1, and set properties
set not_gate_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 not_gate_1 ]
set_property -dict [ list \
CONFIG.C_OPERATION {not} \
CONFIG.C_SIZE {1} \
CONFIG.LOGO_FILE {data/sym_notgate.png} \
] $not_gate_1
# Create interface connections
connect_bd_intf_net -intf_net FIFO_WRITE_1 [get_bd_intf_ports dinp_a] [get_bd_intf_pins fifo_a/FIFO_WRITE]
connect_bd_intf_net -intf_net FIFO_WRITE_1_1 [get_bd_intf_ports dinp_b] [get_bd_intf_pins fifo_b/FIFO_WRITE]
# Create port connections
connect_bd_net -net CLK_1 [get_bd_ports clk] [get_bd_pins c_addsub_0/CLK] [get_bd_pins fifo_a/clk] [get_bd_pins fifo_b/clk]
connect_bd_net -net and_gate_Res [get_bd_ports adder_en] [get_bd_pins and_gate/Res] [get_bd_pins c_addsub_0/CE] [get_bd_pins fifo_a/rd_en] [get_bd_pins fifo_b/rd_en]
connect_bd_net -net c_addsub_0_S [get_bd_ports dout] [get_bd_pins c_addsub_0/S]
connect_bd_net -net fifo_generator_0_dout [get_bd_pins c_addsub_0/A] [get_bd_pins fifo_a/dout]
connect_bd_net -net fifo_generator_0_empty [get_bd_pins fifo_a/empty] [get_bd_pins not_gate_0/Op1]
connect_bd_net -net fifo_generator_1_dout [get_bd_pins c_addsub_0/B] [get_bd_pins fifo_b/dout]
connect_bd_net -net fifo_generator_1_empty [get_bd_pins fifo_b/empty] [get_bd_pins not_gate_1/Op1]
connect_bd_net -net not_gate_0_Res [get_bd_pins and_gate/Op1] [get_bd_pins not_gate_0/Res]
connect_bd_net -net not_gate_1_Res [get_bd_pins and_gate/Op2] [get_bd_pins not_gate_1/Res]
connect_bd_net -net rst_1 [get_bd_ports rst] [get_bd_pins fifo_a/srst] [get_bd_pins fifo_b/srst]
Использовать это описание в таком виде возможно, но как правило требуется некая параметризация БД, чтобы он был согласован с другими частями проекта и не приходилось при изменении того или иного параметра править этот конфигурационный Tcl
файл. В частности, в данном случае имеет смысл параметризовать ширину шин данных, глубину буферов FIFO, рабочую частоту и т.п. Результирующий файл выглядит так:
source $BUILD_SRC_DIR/cfg_params.tcl
#-------------------------------------------------------------------------------
#
# BD Configuration Section
#
# Create interface ports
set dinp_a [ create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:fifo_write_rtl:1.0 dinp_a ]
set dinp_b [ create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:fifo_write_rtl:1.0 dinp_b ]
# Create ports
set clk [ create_bd_port -dir I -type clk -freq_hz [expr $MAIN_CLK*1000000] clk ]
set dout [ create_bd_port -dir O -from 47 -to 0 -type data dout ]
set rst [ create_bd_port -dir I rst ]
# Create instance: fifo_a, and set properties
set fifo_a [ create_bd_cell -type ip -vlnv xilinx.com:ip:fifo_generator:13.2 fifo_a ]
set_property -dict [ list \
CONFIG.Data_Count_Width ${FIFO_DCOUNT_WIDTH} \
CONFIG.Fifo_Implementation {Common_Clock_Distributed_RAM} \
CONFIG.Full_Threshold_Assert_Value [expr ${FIFO_DEPTH}-2] \
CONFIG.Full_Threshold_Negate_Value [expr ${FIFO_DEPTH}-3] \
CONFIG.Input_Data_Width ${DATA_WIDTH} \
CONFIG.Input_Depth ${FIFO_DEPTH} \
CONFIG.Output_Data_Width ${DATA_WIDTH} \
CONFIG.Output_Depth ${FIFO_DEPTH} \
CONFIG.Read_Data_Count_Width ${FIFO_DCOUNT_WIDTH} \
CONFIG.Write_Data_Count_Width ${FIFO_DCOUNT_WIDTH} \
] $fifo_a
# Create instance: fifo_b, and set properties
set fifo_b [ create_bd_cell -type ip -vlnv xilinx.com:ip:fifo_generator:13.2 fifo_b ]
set_property -dict [ list \
CONFIG.Data_Count_Width ${FIFO_DCOUNT_WIDTH} \
CONFIG.Fifo_Implementation {Common_Clock_Distributed_RAM} \
CONFIG.Full_Threshold_Assert_Value [expr ${FIFO_DEPTH}-2] \
CONFIG.Full_Threshold_Negate_Value [expr ${FIFO_DEPTH}-3] \
CONFIG.Input_Data_Width ${DATA_WIDTH} \
CONFIG.Input_Depth ${FIFO_DEPTH} \
CONFIG.Output_Data_Width ${DATA_WIDTH} \
CONFIG.Output_Depth ${FIFO_DEPTH} \
CONFIG.Read_Data_Count_Width ${FIFO_DCOUNT_WIDTH} \
CONFIG.Write_Data_Count_Width ${FIFO_DCOUNT_WIDTH} \
] $fifo_b
# Create instance: c_addsub_0, and set properties
set c_addsub_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:c_addsub:12.0 c_addsub_0 ]
set_property -dict [ list \
CONFIG.A_Type {Unsigned} \
CONFIG.A_Width ${DATA_WIDTH} \
CONFIG.B_Type {Unsigned} \
CONFIG.B_Width ${DATA_WIDTH} \
CONFIG.Latency {1} \
CONFIG.Out_Width [expr ${DATA_WIDTH} + 1] \
] $c_addsub_0
# Create instance: not_gate_0, and set properties
set not_gate_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 not_gate_0 ]
set_property -dict [ list \
CONFIG.C_OPERATION {not} \
CONFIG.C_SIZE {1} \
CONFIG.LOGO_FILE {data/sym_notgate.png} \
] $not_gate_0
# Create instance: and_gate, and set properties
set and_gate [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 and_gate ]
set_property -dict [ list \
CONFIG.C_SIZE {1} \
] $and_gate
# Create instance: not_gate_1, and set properties
set not_gate_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 not_gate_1 ]
set_property -dict [ list \
CONFIG.C_OPERATION {not} \
CONFIG.C_SIZE {1} \
CONFIG.LOGO_FILE {data/sym_notgate.png} \
] $not_gate_1
create_bd_port -dir O adder_en
# Create interface connections
connect_bd_intf_net -intf_net FIFO_WRITE_1 [get_bd_intf_ports dinp_a] [get_bd_intf_pins fifo_a/FIFO_WRITE]
connect_bd_intf_net -intf_net FIFO_WRITE_1_1 [get_bd_intf_ports dinp_b] [get_bd_intf_pins fifo_b/FIFO_WRITE]
# Create port connections
connect_bd_net -net CLK_1 [get_bd_ports clk] [get_bd_pins c_addsub_0/CLK] [get_bd_pins fifo_a/clk] [get_bd_pins fifo_b/clk]
connect_bd_net -net fifo_generator_0_empty [get_bd_pins fifo_a/empty] [get_bd_pins not_gate_0/Op1]
connect_bd_net -net fifo_generator_1_empty [get_bd_pins fifo_b/empty] [get_bd_pins not_gate_1/Op1]
connect_bd_net -net not_gate_0_Res [get_bd_pins not_gate_0/Res] [get_bd_pins and_gate/Op1]
connect_bd_net -net not_gate_1_Res [get_bd_pins not_gate_1/Res] [get_bd_pins and_gate/Op2]
connect_bd_net -net c_addsub_0_S [get_bd_ports dout] [get_bd_pins c_addsub_0/S]
connect_bd_net -net and_gate_Res [get_bd_pins and_gate/Res] [get_bd_pins c_addsub_0/CE] [get_bd_pins fifo_a/rd_en] [get_bd_pins fifo_b/rd_en] [get_bd_ports adder_en]
connect_bd_net -net fifo_generator_0_dout [get_bd_pins c_addsub_0/A] [get_bd_pins fifo_a/dout]
connect_bd_net -net fifo_generator_1_dout [get_bd_pins c_addsub_0/B] [get_bd_pins fifo_b/dout]
connect_bd_net [get_bd_ports rst] [get_bd_pins fifo_b/srst]
connect_bd_net [get_bd_ports rst] [get_bd_pins fifo_a/srst]
#-------------------------------------------------------------------------------
Следует обратить внимание на то, что первой строкой идёт загрузка конфигурационного Tcl
файла с параметрами, на которые далее ссылаются выражения, чтобы достичь целей параметризации. Сам этот загружаемый конфигурационный файл является генерируемым системой сборки из пользовательских yml
конфигурационных файлов. Содержимое cfg_params.tcl
:
#--------------------------------------------------------------------------------
#
# This file is automatically generated. Do not edit the file!
#
#--------------------------------------------------------------------------------
set VERBOSE 1
set BASE_CLK 125
set VARIANT_NAME ac701
set PROJECT_NAME ac701
set TOP_NAME top
set TESTBENCH_NAME top_tb
set DEVICE xc7a200tfbg676-2
set COMPLEX_EXAMPLE ""
set DATA_WIDTH 8
set FIFO_DEPTH 32
set FIFO_DCOUNT_WIDTH 5
set CLK_OUT_PHASE_SHIFT 270
set REF_CLK 200
set MAIN_CLK 125
set DIFF_REFCLK yes
set REF_CLK_PERIOD 5.0
set REF_CLK_HALF_PERIOD 2.5
#--------------------------------------------------------------------------------
В дальнейшем система сборки генерирует целевой файл создания БД, который выглядит так:
#--------------------------------------------------------------------------------
#
# Block design "adder" create script
#...
# This file is automatically generated. Do not edit the file manually.
#
#--------------------------------------------------------------------------------
set PROJECT_NAME adder
set TOP_NAME adder
set DEVICE xc7a200tfbg676-2
set BUILD_SRC_DIR /opt/slon/xilinx/build-system-examples/build/ac701/src
set SIM_SCRIPT_DIR /opt/slon/xilinx/build-system-examples/build/ac701/syn/sim_script
create_project -f ${PROJECT_NAME}.xpr ..
set_property part ${DEVICE} [current_project]
set_property top ${TOP_NAME} [get_filesets sources_1]
set bd_name {adder}
set bd_path {/opt/slon/xilinx/build-system-examples/build/ac701/bd/adder/adder.srcs/sources_1/bd/adder/adder.bd}
set bd_wrapper ${PROJECT_NAME}.gen/sources_1/bd/${bd_name}/hdl/${bd_name}_wrapper.v
puts ""
puts "======== Create block design \"$bd_name\" ========"..
create_bd_design "${bd_name}"
open_bd_design ${bd_path}
source {/opt/slon/xilinx/build-system-examples/src/cfg/ac701/bd/adder.tcl}
validate_bd_design
make_wrapper -files [get_files ${bd_path}] -top
add_files -norecurse ${bd_wrapper}
update_compile_order -fileset sources_1
puts ""
puts "-------- Export simulation for \"$bd_name\" --------"
set_property top ${bd_name}_wrapper [get_filesets sim_1]
generate_target simulation [get_files ${bd_path}] -force
export_simulation -of_objects [get_files ${bd_wrapper}] -simulator questa -absolute_path -force -directory ${SIM_SCRIPT_DIR}/${bd_name}
.
#--------------------------------------------------------------------------------
Этот файл помещается в build/<build-variant-name>/bd/_script
. Путём запуска этого скрипта с помощью САПР Vivado
осуществляется создание проекта Vivado
, содержащего данный БД. В дальнейшем, как уже было сказано, на этапе создания основного проекта Vivado
для текущего сборочного варианта, система сборки подключает созданные таким образом БД в проект.