Використання TCL в розробці на FPGA

Всім привіт!

Давно не писав статті на улюблену тематику і нарешті дозрів на щось більш-менш пристойне і вартісне. У цій статті мова піде про дуже цікавої задачі, з якої інженер-розробник стикається мало не щодня. Пропоную вам подивитися, яким чином можна використовувати всю міць і простоту TCL скриптів для проектування FPGA. У даній статті опис базується на ПЛІС фірми Xilinx, але це не скасовує можливостей TCL скриптів для кристалів ПЛІС інших виробників.


Цікаво? Поїхали...

Що таке TCL?

TCL (Tool Command Language) — скриптова мова високого рівня для виконання різних завдань. Найчастіше TCL застосовується в зв'язці з графічною оболонкою Tk (Tool Kit), але в рамках цієї статті цей аспект розглядатися не буде. Мова знаходить широке застосування в різних задачах автоматизації процесів:

  • Тестування комплексних модулів, вузлів, частин коду;
  • Швидкісне прототипування;
  • Створення графічних інтерфейсів для консольних додатків;
  • Впровадження в прикладні програми та завдання.
Так або інакше, основний функцією мови TCL є автоматизація рутинних завдань і суттєве зменшення часу, що витрачається на розробку. Програми на TCL не вимагають компонування і компіляції, що робить завдання налагодження скриптів простий і нехитрою. Інтерпретатор TCL поширюється під вільною ліцензією і доступний практично для всіх платформ (у багатьох дистрибутивах Linux він доступний за замовчуванням). Це означає, що ви можете без будь-яких обмежень використовувати його в розробці приватних програм і пропрієтарних програм. На момент написання статті актуальна версія TCL – 8.6. Для роботи з TCL скриптами, їх налагодження та візуалізації доступно безліч дистрибутивів MyTcl, TclKit, ActiveTcl і т. д. Ціна за 1 ліцензію ActiveTcl близько ~1500$, що невиправдано для розробки комерційних додатків. З особистої практики, більша частина розробників користується звичною командним рядком.

Всі програми на мові TCL складаються з команд, які розділяються символом ";" або символом початку нового рядка. Як і в багатьох інших мовах програмування, перше слово — команда, інші слова — аргументи команд.

command arg1 argt2… argN

Наприклад,
set NewValue "Hello World!"
puts $NewValue

Перша команда створює змінну NewValue, а друга команда виконує друк значення змінної в консоль. Для того, щоб використовувати змінні з пробілами використовуються лапки. В інших випадках вони не потрібні. Результат виконання команд представлений на малюнку нижче:



На мій погляд, головне, зручність мови TCL полягає в тому, що будь-який аргумент команди може бути замінений іншою командою. Для цього його необхідно помістити в квадратні дужки. На прикладі нижче я покажу цю можливість. Крім усього іншого, TCL здатний керування поведінкою програми на основі різних подій. Це означає, що обробник команд може виконувати ті чи інші дії не тільки за умовою, записаному в скрипті, але і по всіляких зовнішніх подій (зміна значення змінної в зовнішньому файлі, захоплення даних в каналі, завершення виконання програми, досягнення лічильника таймера певного значення і т. д.). Мова TCL багатим набором команд, містить досить зручні засоби роботи з масивами даних і регулярними виразами. На TCL реалізована можливість написання функцій і процедур, доступно опис циклів і виразів за умовою, що істотно полегшує написання код.

Навіщо вам TCL?
Практично всі розробники на FPGA/ASIC рано чи пізно стикаються з мовою TCL в своїх проектах. У сучасній розробці на ПЛІС скрипти TCL активно застосовуються для задач автоматизації та інтеграції процесів. TCL входить у всі провідні САПР ПЛІС – Quartus Altera, ISE Design Suite Vivado Xilinx. Що дозволяє зробити TCL?

  • створення проекту (додавання вихідних файлів, установка опцій, ієрархії дизайну, призначення файлу верхнього рівня і т. д.),
  • синтез і трасування (аж до створення незалежних стадій з різними налаштуваннями),
  • тестування закінчених вузлів, окремих модулів і всього проекту цілком,
  • автоматична генерація файлів обмежень (UCF / XCI) на базі шаблонів,
  • перевірка часових обмежень для синтезованого і трассированного проекту.
  • завдання параметрів ланцюгів, компонентів і примітивів ПЛІС, установка опцій для IP-ядер,
і т. д.

Всі ці стадії, так чи інакше, є базовими операціями в процесі розробки на ПЛІС: від створення моделей поведінки вузлів на мові VHDL/Verilog до налагодження закінченого проекту в САПР на етапі синтезу і трасування. Як правило, складні проекти містять велику кількість модулів, написаних різними розробниками, кілька IP-ядер, файли обмежень, бібліотеки і пакети функцій. У підсумку, закінчений проект має певну ієрархічну структуру і набір правил для підключення тих чи інших модулів до необхідних вузлів проекту. Розробнику складно тримати в голові знання про те, де і як повинні перебувати налагоджені модулі та які функції вони виконують, якщо в його роботі вони використовуються, але знання про їх роботі не потрібні на етапі розробки (так звані "black-box" модулі). На допомогу приходить TCL скрипт, який управляє структурою проекту та пов'язує необхідні вузли за заздалегідь підготовленим шаблонах. Це забезпечує гнучкість у розробці і дає можливість повторюваності закінчених вузлів при міграції від одного проекту до іншого.

Як правило, одночасно зі стадією створення нових вузлів для ПЛІС протікає стадія налагодження цих вузлів окремо від проекту і в сукупності з закінченою системою. Первинне моделювання проводиться абстраговано від ПЛІС на комп'ютері в спеціалізованих САПР і середовищах моделювання: це Modelsim, ISim, Aldec Active-HDL і інші. Для реалізації завдання налагодження проектів на допомогу також приходять TCL скрипти, що дозволяють обробляти події, що виникають під час моделювання, та приймати рішення за результатами роботи моделі. При налагодженні RTL-вузла чисто на HDL мовах може виникнути складність написання моделі, оскільки будь-яка зміна в поведінці схеми призведе до необхідності зміни моделі і наборів тестування. Використання зв'язки моделі на HDL мовою і TCL скриптах досить зручно і для багатьох рішень дозволяє прискорити процес налагодження, а також уніфікувати складні тести.

За стадіями написання коду та його налагодження йдуть звичні кроки синтезу, розміщення та трасування проекту в кристалі ПЛІС. Мабуть, це один з найбільш складних кроків, який вимагає великих обчислювальних ресурсів робочої станції і тривалого часу виконання до повного завершення. Скрипти TCL дозволяють керувати подіями виконання на кожній стадії, аналізувати результати тих або інших обчислень для досягнення найкращих характеристик по розведенню і трасуванні проекту (обсяг займаних ресурсів, максимальні тактові частоти, допустимі значення затримок по таймінгів і інше). Крім того, TCL дає можливість виключити рутинні дії по вибору і зміни налаштувань, повторному запуску стадій перевірок, перезапуску конкретного етапу при створенні файлу прошивки ПЛІС. Така автоматизація проектування практично повністю виключає постійну присутність людини на цих стадіях.

Сподіваюся, що, дочитавши до цих рядків, ви вже переконані у тому, що TCL – зручна і потужна штука, якої вкрай необхідно користуватися в своїх проектах. Нижче я розберу один з корисних скриптів, який використовується нашою командою для створення проекту в середовищі Vivado, для додавання вже написаних файлів вихідних текстів, всіляких IP-ядер, файлів обмежень XCI і багато іншого.

TCL your FPGA!
Розглянемо один з найпростіших TCL скриптів для автоматичного створення проекту на ПЛІС. Попередні дії зовсім мінімальні: на локальній машині потрібно наявність каталогу вихідними текстами проекту, як показано на малюнку нижче.


Для зручності я використовую незалежні каталоги для проектів, створених в середовищі Xilinx ISE Design Suite Vivado, якщо це дозволяє сімейство ПЛІС (7 серія: Artix, Kintex, Virtex). Вихідні файли лежать в каталозі /src проект vivado в однойменному каталозі, а проект для середовища ISE створюється в каталозі /ise, але результати синтезу і розведення зберігаються у теці /implement. Все це зроблено для зручності управління проектом в цілому і незалежного управління в різних середовищах. Також це робить ієрархію більш наочною і позбавляє вас від купи сміттєвих файлів в исходниках. Окремо слід зазначити каталог /top в директорії вихідних текстів, де лежить файл верхнього рівня і необхідні файли обмежень (для ISE це *.ucf файл, для Vivado це *.xdc файл).

Проект містить змішані IP-ядра – старі, створені у ISE і нові, створені Vivado. В каталозі core_k7 лежать ядра, створені в CoreGenerator для ISE. Вони не регенеруються і не оновлюються при використанні в проекті Vivado (причому файл *.vhd використовується для моделювання, файл *.ngc – для синтезу, а файл *.xco в проект Vivado не додається). В каталозі /ipcores лежать нові ядра у форматі *.xci, створені безпосередньо в середовищі Vivado. Слід зазначити, що для кожного ядра потрібна окрема під-директорія, інакше для IP-ядер в проекті встановлюється атрибут "LOCKED", що не дає можливості оновлювати ядра і регенерувати їх для синтезу.

Перейдемо до опису TCL скрипта:

# Stage 1: Specify project settings
set TclPath [file dirname [file normalize [info script]]]
set NewLoc [string range $TclPath 0 [string last / $TclPath]-5]

set PartDev "xc7k325tffg900-2"
set PrjDir [string range $TclPath 0 [string last / $NewLoc]]
set TopName [string range $NewLoc [string last / $NewLoc]+1 end]

Перший рядок шукає розташування TCL скрипта на локальній машині (знаходиться в каталозі src/tcl) і створює строкову змінну з повним шляхом до файлу.
У другому рядку створюється додаткова змінна, з якої вирізається частина шляху. Обидві змінні потрібні для того, щоб в наступних змінних вручну не вказувати шлях до проекту і назва файлу верхнього рівня.
Змінна PartDev містить назву кристала ПЛІС. І це єдина змінна, що змінюється в проекті! Всі інші рядки скрипта залишаються НЕЗМІННИМИ в будь-якому проекті.

# Stage 2: Auto-complete part for path
set PrjName $TopName.xpr
set SrcDir $PrjDir/$TopName/src
set VivNm "vivado"
set VivDir $PrjDir/$TopName/$VivNm

cd $PrjDir/$TopName
pwd

if {[file exists $VivNm] == 1} { delete file -force $VivNm }
file mkdir $VivNm
cd $VivDir

На наступній стадії створюються додаткові змінні, які визначають розташування вихідних файлів, створюють директорію vivado, якщо її немає і т. д. Хочу зазначити, що я перевіряю наявність директорії vivado на локальній машині. Якщо директорія існує – вона віддаляється і створюється заново, щоб не було ніяких конфліктів в новому проекті.
Команда cd змінює робочу директорію, а команда pwd показує розташування робочої директорії.

# Stage 3: Find sources: *.vhd, *.ngc *.xci *.xco *.xdc etc.
# This stage used instead of: add_files -scan_for_includes $SrcDir
set SrcVHD [findFiles $SrcDir ".*.vhd"]
set SrcVer [findFiles $SrcDir ".*.v"]
set SrcNGC [findFiles $SrcDir ".*.ngc"]
set SrcXCI [findFiles $SrcDir ".*.xci"]
set SrcXDC [findFiles $SrcDir ".*.xdc"]

set SrcPCI [findFiles $SrcDir "cl_pcie*"]
set NewLoc [string range $SrcPCI 0 [string last / $SrcPCI]-6]

Тут все примітивно і зрозуміло – створюються змінні, що визначають назви всіх вихідних файлів в каталозі /src. Для пошуку файлів використовується процедура findFiles, до якої ми ще повернемося.
Окремо проводиться пошук компонента вузла PCI-E, який є базовою і невід'ємною частиною для всіх наших проектів.

# Stage 4: Find all subdirs for IP cores (VHD, XCO, NGC, EDN)
set PrjAll {}
lappend PrjAll $DirIps $DirAdm $SrcDir/core_v2_ise $SrcDir/core_v4_ise $SrcDir/core_v5_ise $SrcDir/core_v6_ise $SrcDir/core_k7 $SrcDir/TestBench

set SrcSim {}
for {set i 0} {$i < [llength $PrjAll]} {incr i} {
set SrcXXX [findFiles [lindex $PrjAll $i] ".*.vhd"]
put $SrcXXX
foreach SrcAdd $SrcXXX {
lappend SrcSim $SrcAdd
}
}

На наступній стадії проводиться пошук всіх IP-ядер у проекті. Причому в змінну SrcSim записуються назви файлів, які використовуються для моделювання. Команда lappend в циклі додає до змінної інші значення, формуючи масив, який на мові TCL називається листом. На цьому підготовча частина скрипта закінчується і починається створення проекту.

# Stage 5: Create project and add source files
create_project -force $TopName $VivDir -part $PartDev
set_property target_language VHDL [current_project]

add_files -norecurse $SrcNGC
add_files -norecurse $SrcXCI
export_ip_user_files -of_objects [get_files $SrcXCI] -force -quiet
add_files $SrcVHD
add_files -fileset constrs_1 -norecurse $SrcXDC

Створюємо проект, визначаємо файл верхнього рівня, встановлюємо тип кристала ПЛІС (в даному прикладі це Kintex-7 K325T), додаємо знайдені вихідні файли.

# Stage 6: Set properties and update compile order
set_property top $TopName [current_fileset]
for {set i 0} {$i < [llength $SrcSim]} {incr i} {
set_property used_in_synthesis false [get_files [lindex $SrcSim $i]]
}

set NgcGlb [findFiles $DirIps ".*.ngc"]
for {set i 0} {$i < [llength $NgcGlb]} {incr i} {
set_property IS_GLOBAL_INCLUDE 1 [get_files [lindex $NgcGlb $i]]
}
set_property IS_GLOBAL_INCLUDE 1 [get_files $SrcPCI]

Встановлюємо опції для файлів моделювання (виключаємо з синтезу), визначаємо параметр GLOBAL_INCLUDE для ядер, використовуваних у вузлі PCI-E (це специфічна особливість, необхідна для наших проектів).

# Stage 7: Upgrade IP Cores (if needed)
report_ip_status -name ip_status 
set IpCores [get_ips]
for {set i 0} {$i < [llength $IpCores]} {incr i} {
set IpSingle [lindex $IpCores $i]

set locked [get_property IS_LOCKED $IpSingle]
set upgrade [get_property UPGRADE_VERSIONS $IpSingle]
if {$upgrade != "" && $locked} {
upgrade_ip $IpSingle
}
}
report_ip_status -name ip_status

На цій стадії проводиться пошук IP-ядер проекту у форматі XCI, перевіряється необхідність оновлення версії ядра і параметр locked, на який впливає зміна кристала ПЛІС. Після аналізу ядер відбувається оновлення і видається звіт про успішне завершення операції.

# Stage 8: Set properties for Synthesis and Implementation (Custom field)
set_property strategy Flow_PerfOptimized_high [get_runs synth_1]
set_property strategy Performance_ExtraTimingOpt [get_runs impl_1]

launch_runs synth_1
wait_on_run synth_1
open_run synth_1 -name synth_1
launch_runs impl_1 -to_step write_bitstream
wait_on_run impl_1

Завершальна стадія, на якій відбувається встановлення параметрів синтезу і трасування – вибирається стратегія зі списку доступних. Потім по черзі запускається синтез, розміщення та трасування до повної розведення прошивки ПЛІС.
Як видно, використання скрипта дозволяє позбавити користувача від рутинної роботи по створенню проекту, додавання нових файлів, оновлення IP-ядер та багатьох інших однотипних речей. Скрипт повністю автоматизований і вимагає встановлення єдиного аргументу – тип кристала ПЛІС. Його можна поставити як змінну у файлі, або як аргумент, який виконується одночасно із запуском TCL-скрипта. На малюнку нижче наведений скріншот робочої області проекту в середовищі Vivado, який був запущений з використанням скрипта:



Окремо слід звернути увагу на процедуру findFiles, за допомогою якої можна проводити пошук всіх файлів в директорії. Аргументи функції: basedir – каталог пошуку, pattern – маска пошуку.

proc findFiles { basedir pattern } {

set basedir [string trimright [file join [file normalize $basedir] { }]]
set fileList {}

foreach fileName [glob -nocomplain -type {f r} -path $basedir $pattern] {
lappend fileList $fileName
} 

foreach dirName [glob -nocomplain -type {d r} -path $basedir *] {
set subDirList [findFiles $dirName $pattern]
if { [llength $subDirList] > 0 } {
foreach subDirFile $subDirList {
lappend fileList $subDirFile
}
}
}
return $fileList
}

Пошук виконується в кілька кроків: визначення робочої директорії як шаблону, створення списку по імені файлу з зазначенням повного шляху і формування масиву-списку типу list, якщо знайдених файлів більше одного. Приклад роботи функції findFiles наведено на малюнку нижче. Для пояснення написаний цикл, який виводить на екран всі знайдені файли. Як видно, вказується повний шлях до кожного файлу.



Скрипт запускається з командного рядка, або з використанням GUI додатки Vivado. У першому випадку необхідно запустити Vivado TCL Shell і написати просту команду

vivado –mode tcl –source %full_path/example.tcl 
 

Примітка: з командного рядка можна запустити і графічне середовище, змінивши режим запуску mode gui.
У середовищі Vivado запускаються скрипти нехитро і просто: Menu -> Tools -> Run TCL Script...



На цьому знайомство з мовою TCL завершується. На цьому можливості автоматизації проектів не закінчуються. У цьому простому прикладі я хотів показати, як з використанням TCL скриптів можна автоматизувати проектування на ПЛІС. Мова TCL є дуже зручним, простим для розуміння і найголовніше – відкритим для використання. За особистими оцінками, впровадження скриптів в життя розробників дозволяє в кілька разів зменшити час на повне створення проекту від початкової до завершальної стадії, і залишити більше часу на «чисту» розробку (написання коду). Нижче наведені корисні посилання для знайомства з TCL-скриптами на FPGA.

Література:
Спасибі за увагу!
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.