Перейти к содержанию
    

И снова кастомизация IPcore в Vivado

Приветствую всех!

Давно я кручусь вокруг этой темы, много раз возвращался к похожим веткам на форуме, перечитал мануалы от Xilinx, но не дается оно мне. Есть ощущение, что не хватает легкого волшебного пендаля, чтоб всё встало на свои места, и чтоб над головой лампочка, как в мультике, загорелась. 

Что я хочу получить:

Хочу навести красоту, наподобие стандартных корок - чтоб жмешь разные галочки в GUI, и в зависимости от этого подключались разные HDL-ные или IPcore-ные внутренности, и менялось, например количество внешних портов.

Что умею на данные момент:
1) Могу накидать форму для GUI в IP packager'е - тут всё интуитивно понятно. Могу играть с Enablement dependency, включая/выключая порт. Вижу сгенерированный tcl-скрипт для GUI с функциями proc update_PARAM_VALUE... и proc validate_PARAM_VALUE...

2) Независимо от этого могу на основе Export Block Design создать свой скриптик, который будет с учетом внешних условностей делать create_cell'ы и соединять их connect_net'ами. 

Не могу понять, как мне скрестить первый и второй пункты. Сейчас у меня GUI - просто пустышка, а скрипт могу запустить только вручную, например, для восстановления проекта из git.

По всей вероятности всё должно работать автоматически: кинул Ipcore на канвас, изменил параметры - запустился скрипт, который подтянул нужные исходники, создал топ-левел и т.д. Запустил валидацию BD, пошла пропаганда параметров - опять запустился тот же скрипт. Как этого добиться?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 часов назад, OparinVD сказал:

кинул Ipcore на канвас, изменил параметры - запустился скрипт, который подтянул нужные исходники, создал топ-левел и т.д. Запустил валидацию BD, пошла пропаганда параметров - опять запустился тот же скрипт.

Боюсь, что именно так: "бросил на канвас и всё завертелось" не получится. Рисование BD в GUI есть операция ручная. И все действия там ручные. В противоположность скрипты, будучи запущенными, всё делают без вмешательства. Но там и описание получается текстом (местами малочитебельным).

 

Насколько понял, вы имеете в виду подход через IP Integrator. Если речь только про IP ядра, которые можно традиционно инстанцировать в HDL, там рам всё проще: сгенерил из скрипта корку и всё. Параметры корки скрипту передать. А с IP Integrator процесс несколько иной. Я делаю так: исходно рисуется BD, экспортируется Tcl скрипт, из которого выдираю непосредственно описание инстансов и межсоединений (оно там ближе к концу компактно лежит). Далее это помещаю в свой скрипт-шаблон между прологом и эпилогом, получается нечто такое:

 

#================================================================================
#
#    Prologue
#
source $BUILD_SRC_DIR/cfg_params.tcl
source $BUILD_SRC_DIR/impl_env.tcl

set bd_name         noc_slon
set bd_path         "${PROJECT_NAME}.srcs/sources_1/bd/${bd_name}/${bd_name}.bd"

set cips_name       versal_cips_mamont

puts "\n======== Create block design \"$bd_name\" ========"

create_bd_design "${bd_name}"
update_compile_order -fileset sources_1
open_bd_design ${bd_path}

#-------------------------------------------------------------------------------
#
#   BD Configuration Section
#

create_bd_cell -type ip -vlnv xilinx.com:ip:versal_cips:3.1 ${cips_name}

set_property -dict [                                        \
    list CONFIG.PS_PMC_CONFIG "                             \
        PMC_REF_CLK_FREQMHZ          ${PMC_REF_CLK}         \
        PS_NUM_FABRIC_RESETS         0                      \
        PS_USE_PMCPL_CLK0            0                      \
        PS_USE_PMCPL_CLK1            0                      \
        PS_USE_PMCPL_CLK2            0                      \
        PS_USE_PMCPL_CLK3            0                      \
        SMON_ALARMS                  Set_Alarms_On          \
        SMON_ENABLE_TEMP_AVERAGING   0                      \
        SMON_TEMP_AVERAGING_SAMPLES  8                      \
    "                                                       \
    CONFIG.PS_PMC_CONFIG_APPLIED {1}                        \
]                                                           \
[get_bd_cells ${cips_name}]

apply_bd_automation -rule xilinx.com:bd_rule:cips -config { \
    board_preset  {No}                                      \
    boot_config   {Custom}                                  \
    configure_noc {Add new AXI NoC}                         \
    debug_config  {Custom}                                  \
    design_flow   {Full System}                             \
    mc_type       {None}                                    \
    num_mc        {1}                                       \
    pl_clocks     {None}                                    \
    pl_resets     {None}                                    \
}                                                           \
[get_bd_cells ${cips_name}]

# Create interface ports

set CH0_DDR4_0_0 [ create_bd_intf_port -mode Master -vlnv xilinx.com:interface:ddr4_rtl:1.0 CH0_DDR4_0_0 ]

set S00_AXI [ create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S00_AXI ]
set_property -dict [ list \
 CONFIG.ADDR_WIDTH {64} \
 CONFIG.ARUSER_WIDTH {0} \
 <...>
 CONFIG.WUSER_BITS_PER_BYTE {1} \
 CONFIG.WUSER_WIDTH {0} \
 ] $S00_AXI

set sys_clk0_0 [ create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_clock_rtl:1.0 sys_clk0_0 ]
set_property -dict [ list \
 CONFIG.FREQ_HZ {200000000} \
 ] $sys_clk0_0


# Create ports
set clk [ create_bd_port -dir I -type clk -freq_hz 250000000 clk ]
set_property -dict [ list \
 CONFIG.ASSOCIATED_BUSIF {S00_AXI} \
] $clk

# Create instance: axi_noc_0, and set properties
set axi_noc_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_noc:1.0 axi_noc_0 ]
set_property -dict [ list \
    CONFIG.LOGO_FILE                   {data/noc_mc.png}       \
    CONFIG.CONTROLLERTYPE              {DDR4_SDRAM}            \
    <...>
    CONFIG.MC_EN_ECC_SCRUBBING         {false}                 \
    CONFIG.MC_INIT_MEM_USING_ECC_SCRUB {false}                 \
] $axi_noc_0

set_property -dict [ list \
 #CONFIG.DATA_WIDTH {64} \
 #CONFIG.CONNECTIONS {MC_0 { read_bw {1720} write_bw {1720} read_avg_burst {4} write_avg_burst {4}} } \
 CONFIG.CONNECTIONS {MC_0 { read_bw {12500} write_bw {12500} read_avg_burst {4} write_avg_burst {4}} } \
 CONFIG.CATEGORY {pl} \
] [get_bd_intf_pins /axi_noc_0/S00_AXI]

set_property -dict [ list \
 CONFIG.ASSOCIATED_BUSIF {S00_AXI} \
] [get_bd_pins /axi_noc_0/aclk0]

# Create interface connections
connect_bd_intf_net -intf_net S00_AXI_1 [get_bd_intf_ports S00_AXI] [get_bd_intf_pins axi_noc_0/S00_AXI]
connect_bd_intf_net -intf_net axi_noc_0_CH0_DDR4_0 [get_bd_intf_ports CH0_DDR4_0_0] [get_bd_intf_pins axi_noc_0/CH0_DDR4_0]
connect_bd_intf_net -intf_net sys_clk0_0_1 [get_bd_intf_ports sys_clk0_0] [get_bd_intf_pins axi_noc_0/sys_clk0]

# Create port connections
connect_bd_net -net clk_1 [get_bd_ports clk] [get_bd_pins axi_noc_0/aclk0]

# Create address segments
assign_bd_address -offset 0x00000000 -range 0x80000000 -target_address_space [get_bd_addr_spaces noc_tg/Data] [get_bd_addr_segs axi_noc_0/S00_AXI/C0_DDR_LOW0] -force

#================================================================================
#
#    Epilogue
#
#-------------------------------------------------------------------------------
#
#   BD Final Tasks Section
#
validate_bd_design
make_wrapper -files [get_files ${bd_path}] -top
add_files -norecurse ${PROJECT_NAME}.gen/sources_1/bd/${bd_name}/hdl/${bd_name}_wrapper.v
update_compile_order -fileset sources_1

puts "\n-------- Export simulation for \"$bd_name\" --------"
set sim_top_name [get_property top [get_filesets sim_1]]  
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_path}] -simulator questa -absolute_path -force -directory ${SIM_SCRIPT_DIR}
set_property top $sim_top_name [get_filesets sim_1]


#--------------------------------------------------------------------------------

 И уже в этом скрипте правлю по месту то, что надо. Управляющие параметры передаются через подключаемые файлы. С этого момента данный скрипт является основным для BD - если что-то надо подправить на уровне GUI интегратора, то делаю это в GUI и смотрю, какую команду Vivado выдаёт в консоль. Добавляю (или меняю) это в этом скрипте. Но чаще всего достаточно поправить прямо в тексте. После генерирования BD в GUI интегратора всё это легко проверяется. Автоматизация достигается сама собой, а параметризация через внешние файлы. Вся эта кухня управляется системой сборки, дабы автоматизировать генерирование скриптов и запуск инструментов по зависимостям (например, при изменении каких-либо параметров), но можно и руками запускать или из пакетного файла.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 hours ago, dxp said:

Боюсь, что именно так: "бросил на канвас и всё завертелось" не получится. Рисование BD в GUI есть операция ручная. И все действия там ручные

Да, речь про IPI. Только я имел в виду, что "всё завертелось" бы не вокруг моего IP, а внутри него в результате изменений параметров через GUI корки или через распространение параметров от соседей. Хотя заметил у вас команду apply_bd_automation - взял на заметку, похоже тоже пригодится.

Как-то так tcl-скрипт и технологию его "набивки" я себе и представлял. На практике руку еще не набивал, но тут хотя бы всё понятно - бери и делай. 

Не могу понять, как связать действия в GUI настройки корки с таким скриптом. Например, я кинул свой IPcore на канвас IPI, потом дабл-кликом зашел в GUI для его конфигурации, изменил значение property, которое меняет внутреннюю структуру моего IP, (например, для простоты меняет количество инстансов какого-нибудь субмодуля). Закрыл GUI - что происходит дальше? Как мне эти изменения передать моему скрипту? 

Или даже по-другому. Как пользоваться Customization Parameter'ами при упаковке IPcore? С теми параметрами, что вытащены с топ-левела HDL, всё понятно - настройка на уровне HDL и происходит. А как пользоваться дополнительными property? Они же, наверно, должны настраивать IPcore на уровне TCL? 

PS: по рекомендациям в соседних темах я, к сожалению, не смог заглянуть в недра стандартных корок - не разобрался. Например, понял механику того, как повесить хук на Вивадовские функции, но совершенно не понял, как с помощью этого инструмента отследить, что происходит при настройке стандартных корок... Т.е. я могу добавить в функцию что-то свое новое, но как мне это поможет заглянуть в "старое"?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Опытные люди тут на форуме объяснили, что cells в BD не параметризуются снаружи, т.е. тут автоматизации не достичь. Поэтому только через Tcl. BD ж по сути Tcl и есть, просто в графическом виде. Ну, строго говоря, там внутреннее описание не Tcl (раньше было XML, сейчас JSON), но суть та же: используется некий язык для описания параметров и межсоединений. Зато в Tcl можно экспортировать и потом запуском Tcl скрипта создать весь BD. Собственно, это вышеприведённый скрипт и делает. У меня он запускается на этапе создания проекта. У нас подход такой, что проекты (xpr) ценности не представляют и являются продуктом, которые генерирует система сборки исходя из заданных параметров. Вот на этом этапе этот скрипт и запускает в качестве хука для скрипта создания проекта.

 

Что касается

11 минут назад, OparinVD сказал:

Например, я кинул свой IPcore на канвас IPI, потом дабл-кликом зашел в GUI для его конфигурации, изменил значение property, которое меняет внутреннюю структуру моего IP, (например, для простоты меняет количество инстансов какого-нибудь субмодуля). Закрыл GUI - что происходит дальше? Как мне эти изменения передать моему скрипту? 

то после этого действия вы увидите в консоли Вивады тиклевую команду, которая выполнила это действие. Вот эту команду и добавить в скрипт (или если она там есть, но с другими параметрами, то подкорректировать эти параметры). Т.е. по сути выполнить действие через GUI IPI с целью подсмотреть, как это действие выполнить командой. И перенести после этого в скрипт. Так скрипт будет всегда делать автоматически все нужные действия. Для проверки правильности можно просто удалить из проекта BD и запустить скрипт из консоли. Он должен будет родить BD заново. После этого проверить правильность через тот же GUI IPI. Но это нечасто приходится делать - обычно структура BD как-то на первых этапах уже "кристаллизуется", потом уже только параметры меняются. А это легко передаётся в Tcl скрипт через включаемые файлы. А чтобы не забывать пересоздать BD при изменении влияющего параметра служит как раз система сборки, которая отслеживает зависимости - например, изменился параметр, который влияет на BD в том числе, - и собирает все нужные цели. Если при этом надо пересоздать проект, то и это делается (это ненакладная цель - 6-7 секунд на это уходит на моей не самой быстрой машине).

 

Таким образом, если не надо менять структуру (наличие тех или иных cell'ов и их межсоединения), то править скрипт BD не приходится. Всё пересобирается автоматом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С топ-левельным BD всё понятно, это я умею. Автосборка еще не запущена, но скрипты для нее уже готовы. Речь всё-таки о другом.

 

Возьмем, например, стандартный axis_interconnect. Если зайти в его GUI и поиграть с настройками, то внутри будут появляться и xbar'ы, и конвертеры частоты или ширины, меняться количество портов и т.д. Как это всё происходит? Подсмотреть команду несложно. Например, для изменения количества входных портов будет так: set_property -dict [_list_ CONFIG.NUM_SI {2}] [get_bd_cells axis_interconnect_1]

 

А дальше что? Кто и как подцепляет внутри интерконнекта дополнительный s_coupler и добавляет порт на xbar? Эта магия работает на уровне HDL или на TCL? 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

32 минуты назад, OparinVD сказал:

Например, для изменения количества входных портов будет так: set_property -dict [_list_ CONFIG.NUM_SI {2}] [get_bd_cells axis_interconnect_1]

А вы возьмите откатите сделанное в GUI действие. И запустите эту команду из консоли. Что произойдёт с интерконнектом?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всё тут же перерисовывается и в сторону увеличения, и в сторону уменьшения количества. И в "закрытом" и в "раскрытом" состоянии

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хотите сказать, что действие, выполненное через GUI, не выполняется с помощью команды, которую же сама Vivado генерит на это действие?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вовсе нет... Как раз наоборот, результат идентичный. Я хочу сказать, что вроде как не параметризуемый снаружи cell вполне себе меняет внутреннюю структуру и подтягивает разные исходники в зависимости от параметров... Чего-то подобного я и хочу добиться от своей корки

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

1 hour ago, dxp said:

Опытные люди тут на форуме объяснили, что cells в BD не параметризуются снаружи

Я так понял TC говорит про возможность автоматизации генерации каcтомных BD внутри IP корки при изменении параметров оной на BD. Как это например делается  в IP AXI interconnect  или AXI Ethernet.   На сколько я знаю внятного описания как это правильно делать внутри IP integrator нет. В свое время я пытался разбираться с этим  пытаясь копировать то как это делается в вышеприведенных (или других похожих) корках.  

 

Удачи! Rob.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот, именно про это! И да, прочитав, основные юзер-гайды, я не нашел ничего вразумительного на этот счет. В разделе про упаковку кастомного IP написаны очевидные вещи про добавление property, его тип, зависимости и т.д., а что делать с ними дальше - не понятно. 

С чего начать? Как заглянуть внутрь процессов в том же axis_interconnect? 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, RobFPGA сказал:

Я так понял TC говорит про возможность автоматизации генерации каcтомных BD внутри IP корки при изменении параметров оной на BD. Как это например делается  в IP AXI interconnect  или AXI Ethernet.   На сколько я знаю внятного описания как это правильно делать внутри IP integrator нет.

Можно попробовать завернуть блок hier в ip ядро, но опять же реконфигурации там не будет. В последних вивадах часть штатных ядер для видео переписали на хлс и они параметризованы как по параметрам работы, так и по портам. Тема конфигурируемых и универсальных (без привязки к чипу, версии вивады и частоте) ядер на хлс для меня так же интересна, но останавливает необходимость контроля результатов синтеза для более менее сложных ядер и необходимость подбора по ним интервалов обработки и т.п.

Изменено пользователем fguy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 minutes ago, OparinVD said:

С чего начать? Как заглянуть внутрь процессов в том же axis_interconnect? 

Тут  уже было пару тем по этому вопросу, я там приводил  некоторые  примеры возможности  заглянуть в процессы  генерации IP.
Кроме непосредственного втупливания в tcl код (часто как баран на новые ворота:declare: ) я пробовал два пути - первый это стандартный хук процедур в TCL с выводом в лог что и в какой последовательности вызывается. Второй в принципе тоже самое, в коде TCL  IP integrator встречается  2 переменные установка которых  включает дебаговый вывод последовательности выполнения части процедур в  IP integrator.   

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

27 minutes ago, OparinVD said:

а как принудительно включить вывод debug-log'а? :blush:

В   сорцах  IP integration (ifx_common_xgui_util.tcl) встречается  такое 

proc ifx_debug_enabled {} {
  global env
  if {[info exists env(XIL_IFX_DEBUG)]} {
    set n [namespace current]
    if {[string match "*$n*" $env(XIL_IFX_DEBUG)] || [string match "*IFX_ALL*" $env(XIL_IFX_DEBUG)]} {
      return 1
    }
  }
  return 0
}

proc ifx_debug_trace_enabled {} {
  global env
  if {[info exists env(XIL_IFX_TRACE)]} {
    set n [namespace current]
    if {[string match "*$n*" $env(XIL_IFX_TRACE)] || [string match "*IFX_ALL*" $env(XIL_IFX_TRACE)]} {
      return 1
    }
  }
  return 0
}

Соответственно если создать переменные окружения XIL_IFX_DEBUG и/или  XIL_IFX_TRACE со строкой имени интересующего namespace или глобального "IFX_ALL"  то  должен  выводится некий отладочный лог  работы IP integration.  

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...