TCL - язык управления
средой разработки
Рост производительности персональных компьютеров позволил использовать ПК с платформой Windows для проектирования сложных проектов на ПЛИС. Программное обеспечение для разработки ПЛИС на ПК приближается по своим функциональным возможностям к программам, работающим на рабочих станциях, и приобретает новые для пользователей ПК свойства. Одним из таких свойств является встраиваемый язык TCL.
Процесс разработки ПЛИС включает в себя процедуру описания поведенческой модели узлов проектируемого устройства, тестирование полученной модели, процедуру синтеза, тестирование синтезированной модели. Существуют другие подходы к проектированию, и при использовании различных средств количество и предназначение этапов разработки может изменяться, но для рассмотрения общего подхода предлагается вышеописанная схема.
Описания поведенческой модели в настоящее время выполняются на высокоуровневых языках описания аппаратуры: Verilog HDL и VHDL. Проект обычно содержит много модулей, разрабатываемых различными разработчиками, библиотеки, также практикуется повторное использование кода. Таким образом, проект имеет структуру, описание которой требуется не только на уровне языка описания аппаратуры, но и на уровне хранения информации: в каких файлах хранятся модули или библиотеки, куда направлять результаты или сообщения и т. п. Одно из назначений языка управления в среде разработки — управление структурой проекта и связь с операционной системой.
При отладке проекта (симуляция поведенческой модели) появляется потребность в обработке событий, возникающих во время симуляции, и реакция на них. Например, моделирование внешних воздействий или отображение результатов в преобразованной форме. Использование языка HDL для этих целей может оказаться не эффективным, и любое изменение в описании модели влечет за собой необходимость перезапуска симуляции. Таким образом, развитый скриптовый язык позволяет облегчить моделирование проекта.
Наибольшую вычислительную мощность требует процесс синтеза, как правило, это итеративный процесс, который приходится запускать с различными параметрами для того, чтобы добиться требуемых характеристик по времени и занимаемой площади. Отсутствие языка управления требует присутствия оператора для изменения параметров синтеза, перезапуска и сохранения полученных результатов. Наличие командного языка позволяет автоматизировать этот процесс.
Преимущество стандартного скриптового языка перед графической оболочкой управления заключается в упрощении процедуры переноса проекта с одной платформы на другую. Если управляющие скрипты разбиты на две части: платформо-зависимую и универсальную, то изменения потребует только первая часть скриптов. А так как функции, выполняемые специализированными командами в разных средах проектирования, достаточно похожи (иногда достаточно заменить только имя команды), то изменения платформо-зависимой части не вызывает труда. Забегая вперед, скажу, что эти изменения могут быть выполнены скриптом TCL, так как язык имеет мощные средства обработки текста.
Почему в качестве такого языка выбран TCL? Плюс этого языка в том, что библиотеки распространяются свободно и позволяют создавать приложения (объединять интерпретатор TCL и скомпилированные функции, описанные на С/С++ или другой системе), в которых синтаксис языка расширяется функциями, запрограммированными пользователями и выполняющими основную задачу средства проектирования (например project, do_optimize, do_build_generic, constrain_ file и т. п). Из-за того что эти функции скомпилированы, скорость их исполнения высока, а вызывающий их интерпретатор TCL имеет плюсы, присущие
интерпретаторам. Простота синтаксиса и логики работы интерпретатора, а также существование языка в течение длительного времени обеспечивает выигрыш по сравнению с другими языками, имеющими подобные свойства (Perl, Scheme, Java, Python и др.).
Так как TCL используется программистами для разработки пользовательских интерфейсов и интернет-приложений, то документация содержит много лишнего с точки зрения пользователя средств разработки (как правило, описание графического интерфейса Тk).
Владеющим английским языком советую посетить www.scriptics.com. К настоящему времени мне не удалось найти соответствующих ресурсов на русском. В описании я постараюсь не прибегать к использованию специфических команд конкретной среды разработки, симулятора, синтеза, так как в различных средах эти команды имеют различный синтаксис, описание которого нужно искать в документации. Для проверки прилагаемых в статье примеров будет достаточно просто интерпретатора TCL, не встроенного в какую-либо среду разработки, для Windows интерпретатор TCL можно загрузить с http://sources.redhat.com/cygwin/ (нужен пакет tcltk — это библиотека, но я рекомендую поставить все утилиты). Исполняемые файлы wish или tclsh (cygwish — для Windows). Следует заметить, что в некоторых версиях cygwin содержатся ошибки, например, в работе с регулярными выражениями. Пользователи Unix сумеют найти wish или tclsh без моей помощи. Но, конечно, гораздо эффективнее будет разобраться с описанием дополнительных tcl-команд, реализованных в средстве проектирования, и воспользоваться скриптами с практической пользой.
Основы синтаксиса
Одним из плюсов TCL является простота синтаксиса. Все конструкции языка имеют следующий вид:
procedure_name list_of_arguments
|
разделителями являются «;» или перевод строки.
Что интересно — даже управляющие конструкции языка: циклы, условные операторы и т. п. реализованы таким же образом.
Например:
В этом примере два оператора:
- set — имеет два аргумента: а — имя переменной, 10 — присваиваемое значение;
- expr — имеет произвольное число аргументов (в данном примере 1) и выполняет математические вычисления;
- % — это приглашение, которое обычно используется в tcl (его вводить не надо), если вводимая команда занимает несколько строк, то приглашение может иметь вид «>».
Первый оператор завершен знаком «;», а второй — переводом строки. Результат, который должен быть выведен на экран:
Для того чтобы узнать, какие команды существуют в системе, можно воспользоваться командой info:
Как можно видеть из отклика, управляющие конструкции языка if, for, while и др. являются командами. Часть команд может быть описана на языке TCL. Чтобы получить список таких команд, используйте следующее выражение:
Чтобы посмотреть реализацию (например, процедуры history), наберите
Если первый символ команды #, то оставшаяся часть строки — комментарий.
#comment
% set a 1; #comment
% lappend a #not comment
1 #not comment
|
Подстановки
Перед исполнением строки интерпретатор выполняет подстановки. Использование подстановок — основной механизм программирования на TCL. Подстановки должны быть понятны пользователям юникс-подобных систем, а пользователям других ОС я рекомендую внимательно изучить следующие описания, попробовать написать свои команды с подстановками и предсказать результат.
- символ «$» обозначает подстановку переменной: то есть во всех случаях, когда нужно получить значение переменной, следует писать $имя_переменной, вместо имя_переменной
%set a 20; expr $a*$a
400
|
но следует помнить, что некоторым процедурам требуется именно имя переменной, а не ее значение, примерами таких процедур являются
%set a
%incr a
%foreach a {1 2 3 4} {puts -nonewline «$a «}
1 2 3 4 %
|
- для подстановки результата команд используются квадратные скобки «[« «]», то есть выполняется команда — для этого запускается еще одна процедура интерпретатора TCL, — и результат выполнения заменяет
скобки с содержимым:
%set a 1;set b [incr a]
%foreach a {1 2 3 4} {puts «a=$a a^2=[expr $a*$a]»}
|
- символьная подстановка «\» используется так же, как и в С для подстановки непечатных символов: \n — перевод строки, \t — табуляция и т. д. Во время ввода команды знак «\» перед переводом строки позволяет
продолжить команду на другой строке.
% puts «a\tb\nc\
d\te\\f»
a b
c d e\f
%
|
Для работы языковых конструкций подстановку иногда следует отложить, для этого используются фигурные скобки «{» «}». Рассмотрим пример с фигурными скобками подробнее: для работы цикла foreach требуется, чтобы тело цикла (puts «a=$a a^2=[expr $a*$a]») выполнялось каждый раз с новым значением переменной а. Поэтому оно помещается в фигурные скобки, тем самым указывается, что подстановки должны выполняться внутри цикла во время исполнения итераций. То есть то, что заключено внутри фигурных скобок, игнорируется интерпретатором. Исполнение произойдет, когда скобки будут «раскрыты».
% set a {expr 3+2}
expr 3+2
% puts $a
expr 3+2
% eval $a
5
|
В предлагаемом примере переменная а получает значение «expr 3+2», и для того чтобы его вычислить используется процедура eval.
Внимательный читатель может задать вопрос: почему нельзя воспользоваться квадратными скобками для вычисления значения вместо eval? Это связано с тем, что интерпретатор выполняет подстановку один раз, то есть выполняется один проход. Для того чтобы выполнить подстановку и получить результат в выражении, полученном после подстановки, выполняемой автоматически, требуется принудительно запустить интерпретатор, используя процедуру eval.
Кавычки используются для блокирования действия символов-разделителей (пробелов, табуляций и т. п.). Но, в отличие от фигурных скобок, интерпретатор выполняет подстановки в строке, заключенной в кавычки.
Переменные TCL
Все переменные в TCL являются символьными строками. При выполнении арифметических выражений строки-операнды преобразуются в численное представление, а после завершения вычислений результат преобразуется в строку.
% set a 123
123
% expr ${a}456+1
123457
|
В данном случае фигурные скобки показывают, что требуется значение переменной а, если бы скобок не было, интерпретатор искал бы переменную а456. Если строка содержит внутри себя пробелы, то она должна заключаться в кавычки.
В TCL поддерживаются массивы и списки. Массив реализован как хэш-таблица, поэтому размер и размерность массива могут быть какими угодно и даже допустимо использование строковых значений в качестве индекса.
% unset a
% set a(1) privet
privet
% set a(string) 100
100
% set a(1,2,35,9) 5
5
|
Оператор unset нужен, чтобы удалить переменную а. Создавая элемент массива а(1), мы создаем массив, который может рассматриваться как одномерный массив set a(1) privet, хэш-таблица set a(string) 100, или как четырехмерный массив set a(1,2,35,9) 5.
Для работы с массивами существует набор процедур
% set b 1
1
% array exist a
1
% array exist b
0
% array size a
3
% parray a
a(1) = privet
a(1,2,35,9) = 5
a(string) = 100
% array names a
1,2,35,9 1 string
% set i 1
1
% set j 2
2
% puts $a($i,$j,35,9)
5
|
Распечатать массив можно процедурой parray, остальные операции выполняет процедура array, в которой первый аргумент определяет операцию, а второй — имя массива. Некоторые из возможных действий с массивами:
- еxist — определяет, является ли данный объект массивом;
- size — возвращает количество элементов;
- names — выдает значения индексов массива.
В последнем примере видно, что для массивов подстановка производится дважды: подстановка индексов, а затем подстановка значения элементов.
В качестве упражнения предлагаю проверить, что выдаст следующая конструкция:
% foreach i [array names a] {puts $a($i)}
|
Важным объектом является список (list). Как правило, многие процедуры TCL возвращают список или получают его в качестве аргумента. Неоднократно использовавшаяся в примерах процедура foreach получает своим вторым аргументом список, значения из которого последовательно принимает переменная цикла (первый аргумент). Собственно, любая запись, не заключенная в кавычки, является простым списком. Для разделения элементов используется пробел.
А кавычки (или фигурные скобки) используются для того, чтобы заключить слова, разделенные пробелами, в один элемент. Вообще, любая TCL-конструкция является списком, а любой список является синтаксически правильной конструкцией. Можно рассматривать список как строку, а список, элементами которого являются другие списки, как строку, содержащую пары фигурных скобок. То есть разделение на строки, списки и языковые конструкции является условным — для интерпретатора TCL эти объекты не различаются. Особым элементом является массив, так как это единственный элемент, в котором подстановка выполняется дважды: «вычисление» индекса и получение значения по индексу.
Регулярные выражения
Так как основным типом данных, которые обрабатываются языком TCL, являются строки, то нужен механизм обработки строк. Такой механизм существует в TCL и называется «регулярными выражениями» (regexp). Пользователи, работающие в юникс-подобных системах, наверняка сталкивались с обработкой регулярных выражений, так как она реализована во многих утилитах этих ОС. Упрощенным примером реализации регулярных выражений в DOS/Windows является возможность использования символов «*» и «?» при задании шаблона для работы с файлами.
TCL поддерживает несколько механизмов регулярных выражений и позволяет задавать шаблоны различной сложности для поиска фрагментов строк. Общая идея состоит в использовании специальных символов с предопределенным значением. Наиболее простой вариант называется globbing и использует следующие символы:
- ? — заменяет любой одиночный символ;
- * — заменяет любую группу символов (в том числе и нулевой длины);
- [набор_символов] — любой символ из набора;
- [символ_А-символ_Z] — диапазон символов (не всегда работает корректно с русскими буквами);
- {строка1,строка2,...} — заменяет любую строку.
Как правило, тип globbing используемых выражений задается ключом -glob или оговаривается, что команда понимает только такой тип выражений, например, команда glob, которая служит для поиска файлов.
Для проверки работы регулярных выражений воспользуемся командой поиска в списке lsearch.
% set alist {abra abababra ababra abbbra abbra cabr dabra abracadabra
cadabra moreabrcdbr oncemoreabra abram abramm}
abra abababra ababra abbbra abbra cabr dabra abracadabra cadabra
moreabrcdbr oncemoreabra abram abramm
% lsearch -glob $alist abb*
3
|
Для того чтобы по индексу получить значение, используется lindex.
% lindex $alist [lsearch -glob $alist abb*]
abbbra
|
Так как lsearch возвращает первую строку, удовлетворяющую регулярному выражению, то для того, чтобы получить все строки, напишем простой скрипт.
% set pattern abb*
abb*
% set blist $alist
abra abababra ababra abbbra abbra cabr dabra abracadabra cadabra
moreabrcdbr oncemoreabra abram abramm
% while {[set i [lsearch -glob $blist $pattern]]>=0}\
>{puts [lindex $blist $i]; set blist [lreplace $blist $i $i]}
abbbra
abbra
% puts $blist
abra abababra ababra cabr dabra abracadabra cadabra moreabrcdbr oncemoreabra
abram abramm
|
Данный скрипт можно сохранить в файл (стандартным расширением является tcl) или использовать повторный ввод (если интерпретатор собран с поддержкой readline и history, то для повтора команды можно использовать клавишу «стрелка вверх»).
Используемый цикл while повторяется до тех пор, пока lsearch находит в списке строки, удовлетворяющие образцу, заданному регулярным выражением (если соответствия не обнаружено, то lsearch возвращает -1). В теле цикла производится печать обнаруженной строки и удаленние ее из списка blist. Таким образом, по завершении цикла получается распечатка выражений, удовлетворяющих образцу, а список blist содержит оставшиеся выражения. Присваивая переменной pattern различные регулярные выражения, можно проверить работу скрипта и механизм действия регулярных выражений.
Более мощную систему представляют собственно регулярные выражения regexp:
- . — любой символ, кроме перевода каретки;
- ^ — начало строки;
- $ — конец строки;
- regexp* — выражение, повторенное любое число раз, в том числе 0;
- regexp+ — выражение, повторенное любое число раз, большее 0;
- regexp? — выражение либо его отсутствие.
- regexp{N} regexp{N,M} regexp{N,} — показывает точное число повторений {N}, интервал {N,M} — больше или равно N и меньше или равно M, и {N,} — больше или равно N.
Таким образом , regexp* == regexp{0,} , regexp+ == regexp{1,} , regexp? == regexp{0,1}: regexp1|regexp2 — выражение удовлетворяет либо regexp1, либо regexp2;
- [abc] — набор символов;
- [^abc] — набор исключенных символов (то есть в данном месте проверяемой строки такого символа быть не должно);
- [a-z] — интервал символов;
- [^a-z] — интервал исключенных символов;
- () — задает приоритет при построении regexp;
- \ — отменяет значение специальных символов.
Для проверки работы регулярных выражений воспользуемся скриптом с командой поиска в списке lsearch. Нужно заменить ключ -glob на -regexp (существует еще ключ -exact, который задает поиск по точному совпадению).
% set blist $alist
abra abababra ababra abbbra abbra cabr dabra abracadabra cadabra
moreabrcdbr oncemoreabra abram abramm
% set pattern abb.*
abb.*
% while {[set i [lsearch -regexp $blist $pattern]]>=0}\
{puts [lindex $blist $i]; set blist [lreplace $blist $i $i]}
abbbra
abbra
|
Обратите внимание, что образец «*» в glob-выражениях соответствует образцу «.*» в regexp-выражениях. Достаточно распространенная ошибка — использование в регулярных выражениях (regexp) «*» вместо «.*».
Попробуем задавать разные образцы regexp. Я буду приводить только образец и совпавшие строки, а скрипт будет использоваться тот же.
% set pattern «(ab){2}.*»
(ab){2}.*
....
abababra
ababra
% set pattern {^[cd]ab.*}
^[cd]ab.*
....
cabr
dabra
% set pattern {.{2,4}ab.*}
.{2,4}ab.*
....
abababra
ababra
abracadabra
cadabra
moreabrcdbr
oncemoreabra
|
Для того чтобы научиться использовать регулярные выражения, можно попрактиковаться в задании образца для приведенного скрипта, выбирающего выражения из списка.
Управляющие конструкции
Как и в любом другом языке программирования, в TCL есть набор управляющих конструкций. Управляющие конструкции содержат какое-либо условие (cond) и выполняемые операции — тело (body). Из-за принципа подстановки в TCL, для того чтобы исполнение операторов в конструкциях условия и тела происходило во время выполнения (а не разбора) выражения — их следует заключать в фигурные скобки. В остальном синтаксис большинства управляющих конструкций похож на синтаксис процедурных языков.
Управляющие конструкции TCL можно разделить на группы:
- условные: if then elseif else switch;
- циклы: for, while, foreach, continue, break;
- процедуры: proc, return, global, uplevel, upvar.
Я не буду подробно останавливаться на конструкциях, подобных используемым в других языках, а приведу синтаксис и пример.
if {cond1} then {body1} esleif {cond2} then {body2} … else {bodyN}
|
Ключевое слово then не обязательно.
% set a 2; if {$a==2} then {puts a=2} elseif {$a==3} then {puts a=3} else
{puts a!=2,3}
a=2
% set a 3; if {$a==2} {puts a=2} elseif {$a==3} {puts a=3} else {puts
a!=2,3}
a=3
% set a 1; if {$a==2} {puts a=2} elseif {$a==3} {puts a=3} else {puts
a!=2,3}
a!=2,3
|
Эти действия могут быть выполнены командой switch:
% set a 1; switch $a {2 {puts a=2} 3 {puts a=3} default {puts a!=2,3}}
a!=2,3
% set a 2; switch $a {2 {puts a=2} 3 {puts a=3} default {puts a!=2,3}}
a=2
|
Циклы реализуются следующим образом:
for {start} {test} {next} {body}
foreach variable list {body}
while {cond} {body}
|
В дополнение к приведенным выше примерам использования циклов приведу примеры использования циклов с командами continue, break.
% for {set i 1} {$i<5} {incr i} {puts $i}
1
2
3
4
% for {set i 1} {$i<5} {incr i} {if {$i==3} continue; puts $i}
1
2
4
% foreach i {1 2 3 4} {if {$i>2} break; puts $i}
1
2
|
Важным элементом языка являются процедуры, определяемые пользователем. Перед использованием процедура должна быть объявлена с помощью команды proc. В качестве примера рассмотрим рекуррентную процедуру вычисления факториала.
% proc fac x {
if {$x<=1} {return 1}
expr $x * [fac [expr $x-1]]
}
% fac 3
6
% fac 10
3628800
|
Для доступа к коду процедуры и получения информации о ней можно воспользоваться командой info: info args fac или info body fac. В качестве примера оформим процедуру поиска значений в списке.
% proc find_all_glob {blist pattern} {
while {[set i [lsearch -glob $blist $pattern]]>=0} {puts [lindex $blist $i];
set blist [lreplace $blist $i $i]}
}
|
Предположив, что переменная alist сохранила значение, определенное выше, вызовем процедуру.
% find_all_glob $alist *dab*
dabra
abracadabra
cadabra
|
В процедуре TCL параметры и все используемые переменные (set) являются локальными, для того чтобы получить доступ к глобальным переменным, требуется воспользоваться командой global. Перепишем процедуру, так чтобы она работала с глобальной переменной blist. При использовании процедуры find_all_glob значение переменной blist, объявленной на верхнем уровне, не меняется.
% proc find_all_glob_modify {pattern} {global blist
while {[set i [lsearch -glob $blist $pattern]]>=0} {puts [lindex $blist $i];
set blist [lreplace $blist $i $i]}
}
% set blist $alist
abra abababra ababra abbbra abbra cabr dabra abracadabra cadabra
moreabrcdbr oncemoreabra abram abramm
% find_all_glob_modify {ab[rb]*}
abra
abbbra
abbra
abracadabra
abram
abramm
% puts $blist
abababra ababra cabr dabra cadabra moreabrcdbr oncemoreabra
|
Использовать глобальные переменные не всегда удобно, поэтому TCL предоставляет пользователю механизм работы с «вызовом по ссылке», то есть вместо копии переменной в параметре можно получить саму переменную и модифицировать ее. Этот механизм реализуется командой upvar.
% proc find_all_glob_upvar {clist pattern} {upvar $clist blist
while {[set i [lsearch -glob $blist $pattern]]>=0} {puts [lindex $blist $i];
set blist [lreplace $blist $i $i]}
}
% set blist $alist
abra abababra ababra abbbra abbra cabr dabra abracadabra cadabra
moreabrcdbr oncemoreabra abram abramm
% find_all_glob_upvar blist *cad*
abracadabra
cadabra
% puts $blist
abra abababra ababra abbbra abbra cabr dabra moreabrcdbr oncemoreabra
abram abramm
% find_all_glob_upvar alist {ab[ar]*}
abra
abababra
ababra
abracadabra
abram
abramm
% puts $alist
abbbra abbra cabr dabra cadabra moreabrcdbr oncemoreabra
|
Формат директивы uplevel: uplevel parameter_name local_variable. После объявления локальной переменной с помощью директивы uplevel, любые операции с ней будут приводить к изменению переменной, полученной в качестве параметра. Следует обратить внимание, что параметр, используемый в процедуре с командой uplevel, передается без подстановки (без знака $).
В TCL есть еще одно замечательное свойство, которое позволяет пользователю создавать управляющие конструкции языка. Очень мало языков имеет такую возможность. На практике мне не приходилось пользоваться этой возможностью, но в сложных скриптах, предназначенных для распространения, и в коммерческих продуктах такие конструкции встречаются. Реализуется это с помощью директивы uplevel. Напишем цикл do:
% proc do {var first last body} {upvar $var v; for {set v $first}
{$v<=$last} {incr v} {uplevel $body}}
% do i 1 5 {puts [expr $i*$i]}
1
4
9
16
25
|
Смысл команды uplevel в том, что ее аргумент исполняется на верхнем уровне и имеет доступ к переменным верхнего уровня. В процедуру может передаваться произвольное число параметров, и процедура может получать параметры с предопределенными значениями (default). При вызове процедуры с предопределенными параметрами, если фактический параметр не передается, то формальный принимает предопределенное
значение.
% proc mult args {set s 1; foreach i $args {set s [expr $s * $i]}; return $s}
15
% mult 2 4
8
% mult 2 3 4 5
120
|
Для передачи произвольного числа аргументов указывается специальный аргумент args. После вызова процедуры этот аргумент содержит список параметров.
% proc mul {val1 {val2 2}} {expr $val1 * $val2}
% mul 4
8
% mul 4 5
20
|
В описании аргумента с предопределенным значением используется конструкция {name value}.
Важно рассмотреть взаимодействие tcl с операционной системой: как правило, команды ОС выполняются из tclsh. Но также существует команда exec, которой следует пользоваться в некоторых случаях. Следует учесть, что в DOS и Windows разделителем поддиректорий в полном имени файла выступает символ обратной косой черты «\», а не косой черты «/», принятый в Unix. Если программа автоматически не переводит этот разделитель, то пользователям Windows следует использовать '\\» для обозначения «\» — это стандартная необходимость при использовании утилит Unix под Windows. В cygwin реализовано автоматическое преобразование разделителя и в дальнейшем я буду использовать «/».
Для получения списка файлов текущей директории используется команда glob:
% glob *
bin lib src local tmp man doc info i686-pc-cygwin include share sbin
var ssl i686-pc-mingw32 autotool
|
Пользуясь образцами globbing, можно выбрать требуемую группу файлов (например, исходники на verilog и отчеты: glob *.v *.log).
Смена директории — cd, получить имя текущей директории — pwd. Также существует набор специфических команд, связанных с обработкой ошибок и отладкой, поддержкой многозадачности, контролем времени, взаимодействием с ОС и т. п.
Зная основы языка и принципы работы интерпретатора, не составит труда разобраться с этими возможностями и правильно использовать команды, не приведенные в данном обзоре.
Примеры использования
Приведу примеры использования TCL в среде разработки Ambit. Для использования примеров с другой средой следует заменить специфические команды Ambit на соответствующие команды используемой среды.
Пример 1: сохранение и восстановление базы данных в сжатом виде:
proc write_adb_gz { adbfile } {
write_adb -hierarchical /tmp/${adbfile}
gzip -f /tmp/${adbfile}
mv -f /tmp/${adbfile}.gz .
}
proc read_adb_gz { file } {
set tmpfile /tmp/tmp[exec date +%H%M%S].adb
gunzip -c $file > $tmpfile
read_adb $tmpfile
rm -f $tmpfile
}
|
Для использования этих процедур в другом средстве синтеза нужно заменить write_adb, read_adb на команды записи и чтения, реализованные в этом средстве.
Пример 2: генерация отчета статического временного анализа .
foreach report_type {«-summary -max_paths 200» «-max_points 200»}
{
foreach clock {MCLK SCLK FCLK BCLK SPICLK} {
foreach mode {early late} {
eval report_timing -net -$mode -clock_from $clock $report_type -
max_slack 0.2
}
}
}
|
Здесь специфической командой является report_timing с параметрами.
Пример 3: генерация доклада о нарушении ограничений.
set inst_list [find -inst «cr grp_*»]
foreach inst $inst_list {
set_current_instance $inst
report_design_rule_violations >> /tmp/ambit_tmp_log_file
set_current_instance
}
|
В этом примере специфические команды find, set_current_instance, report_design_rule_ violations.
Пример 4: выравнивание тактового дерева после завершения автоматического синтеза:
set n 0
foreach mem_clk_pin [find -pin cmem*/CLK*] {
set cbuf [create_instance [find -cell CLKBUFX20] cbuf$n]
set drivepin [get_fanin -level 1 $mem_clk_pin]
add_conn $drivepin [find -pin [get_name $cbuf]/A]
delete_netconn $mem_clk_pin
add_conn [find -pin [get_name $cbuf]/Y] $mem_clk_pin
set n [expr $n + 1]
}
|
Заключение
Предполагается, что в ближайшее время языком управления в средствах разработки ПЛИС будет оставаться TCL. Данная статья должна помочь разработчику создавать скрипты TCL и понимать скрипты, написанные другим разработчиком. Несмотря на большое количество разнообразных скобок, которые вводят в заблуждение начинающего пользователя, TCL является простым для понимания и удобным языком. Использующийся в TCL принцип однократной подстановки позволяет упростить программную реализацию интерпретатора и в то же время сделать основы синтаксиса языка простыми для запоминания человеком.
Сергей Емец
|