Использование скриптов TCL для управления проектами Quartus II

tcl

Программное обеспечение Altera Quartus II предлагает дополнительные возможности разработки в ввиде скриптового языка TCL (Tool Command Language). Язык TCL позволяет писать скрипты для пакетной обработки, для управления проектами, для предварительной и пост обработки результатов компиляции проектов.

Давайте сделаем простой проект для платы Марсоход (давненько я не делал проектов для первой платы Марсоход!) и на примере этого проекта рассмотрим некоторые возможности скриптового языка TCL.

Представьте себе ситуацию, что мы разрабатываем некоторое устройство на базе ПЛИС и передаем это устройство заказчикам. Причем наших устройств, например, сделано уже много. Самое ужасное, что разные заказчики получили устройства кто раньше, кто позже с разными прошивками. Для службы поддержки очень важно знать какая прошивка стоит у конкретного пользователя. Звонит, например, пользователь в службу поддержки и жалуется, что у него что-то не работает. А служба поддержки спрашивает: "А у вас какая прошивка в ПЛИС стоит? Такая-то? А, ну этот баг уже починили! Вам нужно перешить устройство".

Я не знаю, как устройство отображает информацию о текущей версии прошивки, может у устройства дисплей есть или последовательный порт для подключения терминала. Важно, что мы хотим в проект ПЛИС вставлять информацию о дате сборки проекта и может быть о номере сборки.

Как это сделать?

Самый очевидный способ - использование специального скрипта TCL. Скрипт должен запускаться автоматически каждый раз, когда проект ПЛИС в среде Altera Quartus II запускается на компиляцию.

Все настройки проекта хранятся в файле *.qsf - это Quartus Settings File. В этой файл я предлагаю добавить три вот такие строки:

set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:_before.tcl"
set_global_assignment -name POST_MODULE_SCRIPT_FILE "quartus_sh:_after_mod.tcl"
set_global_assignment -name POST_FLOW_SCRIPT_FILE "quartus_sh:_after.tcl"

Эти строки обозначают, что скрипт _before.tcl будет запускаться каждый раз перед полной сборкой проекта.
Скрипт _after.tcl будет запускаться каждый раз после полной сборки проекта.
А скрипт _after_mod.tcl будет запускаться после каждого модуля сборки. Модули это этапы компиляции:

  1. Analysis and synthesis (quartus_map)
  2. Fitter (quartus_fit)
  3. Assembler (quartus_asm)
  4. Timing Analyzer (quartus_tan)

Итак, рассмотрим скрипт _before.tcl. Как я уже сказал, этот скрипт запускается каждый раз перед полной компиляцией проекта.
Вот скрипт, который я написал, _before.tcl:


set arg0 [lindex $quartus(args) 0]
set arg1 [lindex $quartus(args) 1]
set arg2 [lindex $quartus(args) 2]
post_message "++++++++++++++++++++++++++++++++++++++++++++++"
post_message "This TCL script starts before Quartus II build process!!!"
post_message "Script creates Verilog module which says build number and current date"
post_message [format "Arguments: %s %s %s" $arg0 $arg1 $arg2]

#open file with build number and read line
set build_num_file [open "build_number.txt" "r"]
fconfigure $build_num_file -buffering line
gets $build_num_file str
set bn [expr $str]
incr bn
close $build_num_file

#truncate file
close [open "build_number.txt" "w"]

#write increased value of build number back into file
set build_num_file [open "build_number.txt" "w"]
puts $build_num_file [format "%d" $bn]
close $build_num_file
post_message [format "build number: %d" $bn]

#get current date
set systemTime [clock seconds]
set year [clock format $systemTime -format %y]
set month [clock format $systemTime -format %m]
set day [clock format $systemTime -format %d]

#write Verilog file
set file [open "cur_build.v" w]
puts $file "module cur_build ("
puts $file { output wire [31:0]buildno,}
puts $file { output wire [7:0]year,}
puts $file { output wire [7:0]month,}
puts $file { output wire [7:0]day}
puts $file " );"
puts $file "assign buildno = $bn;"
puts $file "assign year = $year;"
puts $file "assign month = $month;"
puts $file "assign day = $day;"
puts $file "endmodule"
close $file
post_message "--------------------------------------------"


Этот скрипт читает из текстового файла build_number.txt строку с последним номером сборки, затем увеличивает номер сборки на единицу и записывает это новое число в виде строки в тот же самый файл build_number.txt. Кроме этого, скрипт берет текущую дату: год, месяц, день. Из всех этих собранных данных скрипт создает текстовый файл с описанием модуля на языке Verilog. У модуля есть только выходные сигналы на которых наши данные о текущей пошивке.

А вот какой получается выходной Verilog модуль:


module cur_build (
output wire [31:0]buildno,
output wire [7:0]year,
output wire [7:0]month,
output wire [7:0]day
);
assign buildno = 29;
assign year = 15;
assign month = 05;
assign day = 16;
endmodule


Это автоматически генерируемый файл. Каждый раз при запуске проекта на компиляцию этот Verilog модуль пересоздается.

А вот так будет выглядеть весь мой проект, его топовый модуль в графическом виде:

schema FPGA

Я всего лишь хочу на светодиодах платы Марсоход по очереди отображать номер сборки, год сборки (в столетии), месяц сборки и день сборки. Конечно, прямо вот этот проект для платы Марсоход сам по себе имеет мало смысла, но ведь это всего лишь демонстрация принципа использования скриптового языка TCL для встраивания идентификатора сборки внутрь проекта ПЛИС.

При компиляции этого проекта в окне сообщений среды Quartus II мы увидим вот такие сообщения:

Quartus II TCL msg

Вот эта строка "build number: 29" - это строка, которую выдает мой скрипт. Номер сборки каждый раз при компиляции увеличивается.

Давайте посмотрим, что еще можно сделать из скриптов TCL.

Вот при компиляции проекта создается файл для прошивки ПЛИС max2.pof. А можно ли после создания этого файла из скрипта сделать еще что нибудь с этим файлом? Конечно можно. Например, давайте из скрипта TCL конвертируем POF файл в файл SVF (Serial Vector FIle).

Напишем скрипт _after_mod.tcl:


set arg0 [lindex $quartus(args) 0]
set arg1 [lindex $quartus(args) 1]
set arg2 [lindex $quartus(args) 2]
post_message "+++++++++++++++++++++++++++++++++++++++++++++++++++++"
post_message "This TCL script runs after every Quartus II module!!!"
post_message [format "Arguments: %s %s %s" $arg0 $arg1 $arg2]

#do convert programming file only after assembler
if [string match "quartus_asm" $arg0] {

# Include commands here that are run after the assembler
post_message "Convert POF file to SVF file"
set cmd "quartus_cpf -c -q 4.5MHz -g 3.3 -n p max2.pof max2.svf"

# If the command can't be run, return an error.
if { [catch {open "|$cmd"} input] } {
return -code error $input
}
}


Этот скрипт будет запускаться после каждого модуля, этапа компиляции. Внутри скрипта есть проверка - если этап компиляции - это ассемблер, то после него должен появиться POF файл. Вот тогда запускается программа quartus_cpf для преобразования выходного файла из одного формата в другой.

Вот и все готово.

При компиляции номер сборки вставляется в проект и после сборки скрипт преобразовывает выходной файл в SVF файл. Вот такие возможности дает скриптовый язык TCL для программистов Altera Quartus II.

Напоследок небольшое видео о том как работает мой проект в плате Марсоход. На светодиодах последовательно отображается номер сборки (29), год (15), месяц Май (5) и число сборки (16-е).

Проект для ПЛИС платы Марсоход для среды Altera Quartus II можно взять здесь: 

Еще материалы по теме:

  1. TCL scripting.
  2. Quartus II scripting refference manual.

 


Добавить комментарий