Часть 11: ИНТЕРПРЕТАТОРЫ
11-3: Интерфейс TCL |
Этот раздел поясняет интерфейс
языка интерпретатора TCL в Electric, системе
разработки VLSI.
На протяжении этого раздела примеры кода TCL будут появляться underlined (подчеркнутыми). Например, предикат "getarcproto" получает имя прототипа дуги и возвращает указатель на этот объект. Это кодируется, как (getarcproto 'Metal-1), который вычисляется по указателю формы #arcproto15391808.
В разделе предполагается, что читатель очень хорошо знает Electric, и как-то знаком с внутренним строением системы. Внутреннее руководство (Internals Manual) (документ, доступный на Static Free Software) обеспечивает широкий, С-ориентированный взгляд на информацию, описанную здесь. Для пользователей TCL, однако, этот раздел суммирует важные аспекты внутреннего руководства. В общем, наилучший путь к пониманию этого раздела - выполнить каждую команду по мере ее объяснения.
Для вызова интерпретатора TCL используйте субкоманду TCL... команды Language Interpreter меню Tools. На некоторых системах, возможно, понадобится переместить курсор в окно сообщений (текстовое окно), чтобы интерпретатор "слышал" вас.
Если у вас есть дисковый файл с кодом
TCL, вы можете прочитать его в интерпретатор,
введя:
source FILENAME
Чтобы вернуться в Electric из TCL, введите ^D (удерживайте на клавиатуре клавишу Control и нажмите "D"). В Windows вы должны нажать клавишу ESC.
Полная база данных Electric - это коллекция объектов, каждый из которых имеет произвольное количество атрибутов. Этот раздел кратко показывает типы объектов и то, как они связаны. Дальнейшее знакомство можно продолжить по внутреннему руководству (Internals Manual). См. в разделе 11-5 список атрибутов этих объектов.
Индивидуальные компоненты внутри схемы описаны nodeinst объектами (образцы узлов), а индивидуальные провода описаны arcinst objects объектами (образцы дуг). Соединения между компонентами и провода описаны portarcinst объектами (образцы портов, которые соединены с дугами). Поскольку и компоненты, и провода имеют геометрию, каждый, тем не менее, имеет ассоциированный объект geom, и все объекты geom в фасете организованы пространственно в R-дерево с набором rtnode объектов.
Класс объектов также существует для описания всех индивидуальностей данного типа. Объект nodeproto описывает компоненты прототипов, которые могут иметь много индивидуальных nodeinst объектов, ассоциированных с ними. Например, CMOS P-транзистор описан единственным объектом nodeproto, и есть много nodeinst объектов для каждого образца такого транзистора в любой цепи. Иерархия реализована вводом сложных компонент, больше известных как фасеты, представленных таким же образом, как примитивы компонент, такие как транзисторы. Например, цепь ALU описана единственным объектом nodeproto, а каждый образец этой цепи выше в иерархии описан объектом nodeinst.
Объект cell собирает разные виды и версии схемы. Каждый из них, назван "facet" (представленный объектом nodeproto), и фасет имеет и указатель view, и номер версии.
Дополнительно к прототипам компонент arcproto описывает классы проводов, а portproto описывает классы проводов соединения компонент (component-wire connections). Дополнительный объект portexpinst, существует для экспортов. Объект network описывает электрически соединенные arcinst и portproto объекты внутри facet.
В качестве дальнейшей агрегации объектов есть library - коллекция ячеек и фасет. technology - набор примитивов компонент (nodeprotos) и всех классов проводов (arcprotos).
Дополнительно к выше описанным указателям на объекты есть некоторые стандартные типы значений, которые могут ассоциироваться через getval:
integer |
32-bit integer |
string |
null-terminated string of bytes |
float |
32-bit floating point number |
window |
window partition object |
windowframe |
display window object |
constraint |
constraint system object |
graphics |
graphical attributes object |
Также есть возможность иметь отображаемые переменные (те, чьи значения появляются на объекте) с ключевым словом: displayable.
Для начала поиска в базе данных важно
знать текущую библиотеку. Это сделано
так:
(curlib)
возвращает указатель на объект library
(например, #library15464800). Отсюда текущий
фасет может быть получен с помощью:
getval [curlib] firstnodeproto
Существенно, что любой атрибут может
быть проверен с помощью getval, и новый
атрибут может быть создан с помощью
setval. Getval имеет следующий
формат:
getval Object Attribute
где
Object - ассоциируемый объект, а Attribute
- запрашиваемые атрибуты. Список всех
существующих атрибутов на объектах
Electric дан в конце этого документа.
Новые атрибуты могут быть созданы на
любом объекте с помощью setval. В общем,
многие из существующих атрибутов,
которые описаны в конце этого документа
не могут быть установлены с помощью
setval, но управляются специальными
предикатами модификации базы данных.
Формат setval:
setval Object
Attribute Value Options
где Options это либо
0, либо displayable для показа этого
атрибута при отображении объекта.
Например, для добавления нового атрибута,
названного "power-consumption" к компоненту
транзистор "t1", и придания ему
значения 75, используйте:
setval
$t1 power-consumption 75
Для добавления
отображаемого имени узлу "t1"
используйте:
setval $t1 NODE_name Q1
displayable
Для установки массива значений
используйте lists. Например, для
установки очертания узла чисто слоя -
pure-layer node "metal" со звездочкой
используйте:
setval $metal trace {-1000
0 0 1000 1000 0 0 -1000}
Единственный элемент в массиве
атрибутов может быть установлен с
помощью:
setind Object Attribute Index
Value
где Index - это 0-базируемый
элемент массива.
И, наконец, атрибут может быть удален
с помощью:
delval Object Attribute
Однако
только те атрибуты, которые были созданы
setval, могут быть удалены таким образом.
Другие атрибуты защищены.
Для создания нового фасета в текущей
библиотеке используйте:
newnodeproto FacetName [curlib]
возвращающий указатель nodeproto, который может быть использован при последующих вызовах, размещающих компоненты и провода в этом фасете.
Для получения адреса существующего
nodeproto используйте:
getnodeproto
FacetName
возвращающий тот же тип
значения, что и newnodeproto. Таким образом,
код:
set myfacet [newnodeproto "adder{lay}"
[curlib]]
тот же, что и код:
newnodeproto
"adder{lay}" [curlib]
set myfacet
[getnodeproto "adder{lay}"]
а оба - часть
представления "layout" ячейки, названной
"adder".
В качестве отступления, предикат
getcell может быть использован для
получения объекта cell, как здесь:
getcell adder
возвращая то же,
что и:
getval $myfacet cell
Для создания компонента в фасете
используйте:
newnodeinst Proto LowX
HighX LowY HighY Transpose Angle Facet
где Proto это
nodeproto компонента, который будет
создан, LowX, HighX, LowY и HighY
- это рамки компонента, Angle число
десятков градусов поворота компонента,
Transpose это не нуль для транспонирования
ориентации компонента (после поворота),
а Faset - nodeproto в котором будет
размещаться компонент.
Четыре ограничивающих значения это
нечто путанное для вычисления. Для
примитивов компонент (таких, как
транзистор) любое значение приемлемо,
и компонент будет масштабирован. Однако
все еще хорошо бы знать значение по
умолчанию, которое может быть получено
из nodeproto с помощью getval следующим
образом:
set tran [getnodeproto
P-Transistor]
set lowx [getval $tran
lowx]
set highx [getval $tran highx]
set
lowy [getval $tran lowy]
set highy [getval
$tran highy]
Когда сложные компоненты
(фасеты) размещаются, контуры ДОЛЖНЫ
быть точно такими же, как рамки содержимого
фасета. Эта информация доступна
вышеприведенным образом. В качестве
примера newnodeinst, и получения вычисления
выше показанного контура, предопределенный
размер P-транзистора создается в "adder"
фасета с помощью:
set t1 [newnodeinst
$tran $lowx $highx $lowy $highy 0 0 $myfacet]
Возвращаемый
указатель на компонент транзистор будет
использован позже при соединении.
Для соединения двух компонент необходимо знать следующие четыре вещи:
Компонентные объекты на двух концах, возвращаемые newnodeinst
Значения portproto мест соединения на компонентах
X и Y координаты мест соединения
Тип, ширину и другие характеристики созданных проводников
Места соединения названы portprotos и
ассоциированы с nodeprotos. Для получения
адреса используйте:
getportproto
NodeProto PortName
Например, для получения
порта поликремния на левой стороне
MOSIS CMOS P-транзистора используйте:
set
polyleft [getportproto $tran p-trans-poly-left]
К сожалению,
нет хороших способов получить список
имен портов на примитивах компонент.
Есть, однако, некоторые упрощения.
Например, если есть только один порт
(как в случае с большинством контактов
и выводов), тогда его имя не нужно:
set
port [getval $tran firstportproto]
Этим будет получен
первый порт на компоненте P-транзистор.
Для получения координат порта для
соединения используйте:
portposition
Node Port
Возвращается список с
координатами. Например:
set
portpos [portposition $t1 $polyleft]
и будут получены
координаты порта "p-trans-poly-left" на
вновь созданном P-транзисторе t1. Значение
X будет lindex $portpos 0, а значение Y lindex
$portpos 1.
Последняя часть необходимой информации
- тип дуги и ширина дуги. Задавая имя
дуги, можно получить тип с
помощью:
getarcproto ArcName
Задавая
arcproto, предопределенная ширина будет
получена с помощью:
getval Arc
nominalwidth
Когда вся информация готова,
вызов:
newarcinst ArcType Width Bits NodeA
PortA XA YA NodeB PortB XB YB Facet
разместит
проводку. Вы можете игнорировать значение
Bits и установить его в ноль.
Вот полный пример размещения транзистора, контакта и проведения соединения между ними (результат показан здесь же).
# create a facet called "tran-contact"
in the current library |
Фасеты, как созданные newnodeproto, могут быть размещены в других фасетах с помощью newnodeinst. Образцы просто используют комплексные поля nodeproto, а не примитивы nodeprotos, как в вышеприведенном примере. Например, следующий код создает новый фасет, названный "two-trans" и размещает два образца фасета "tran-contact", один над другим.
# create a facet called "two-trans" |
Другой необходимой
особенностью при создании иерархии
является возможность разместить провода
между местами соединения на образцах
фасета. Чтобы сделать это, необходимо
создать экспорты. При этом берется порт
на примитиве компонента (например,
транзистора или контакта в фасете
"tran-contact") и устраивается в экспорте
на текущем фасете. Выполняется с помощью:
newportproto Facet NodeInFacet PortOnNode
PortName
где Facet - это фасет, содержащий
компонент, чей порт экспортируется,
NodeInFacet это тот компонент, а PortOnNode
это частный порт на этом узле, который
будет экспортирован. Например, для
экспорта верхнего и нижнего портов
фасета "tran-contact" (как показано
здесь), может быть добавлен следующий
код:
|
И затем компоненты "o1" и "o2" в фасете "two-trans" могут быть соединены, используя порты, названные "topdiff" и "botdiff":
# get pointer to P-Active arc and its default
width |
Два вида модификации может быть
выполнено для существующих объектов:
удаление и изменение. Для удаления
фасета используйте:
killnodeproto
Facet
Чтобы скопировать фасет (внутри той
же библиотеки или из одной библиотеки
в другую) используйте:
copynodeproto
FromFacet ToLibrary ToFacetName
где FromFacet -
оригинальный фасет (nodeproto) и ToLibrare
- библиотека-получатель (destination ).
Используйте (curlib) для копирования
в ту же самую библиотеку. Новое имя
фасета - последний параметр. Предикат
возвращает адрес нового фасета
(nodeproto).
Для удаления компонента используйте:
killnodeinst Node
До удаления
компонента все провода и экспорты должны
быть удалены.
Для изменения размера или ориентации
компонента используйте:
modifynodeinst
Node DLowX DLowY DHighX DHighY DRotation DTrans
где DLowX,
DLowY, DHighX и DHighY изменения
позиции и размера. DRotation и DTrans
изменения ориентации.
Для изменения прототипа компонента
используйте:
replacenodeinst OldNode
NewPrototype
где старый компонент - OldNode,
а новый nodeproto, который должен быть
на его месте, это NewPrototype. Этот новый
прототип должен быть способен соединиться
со всеми существующими дугами. Предикат
возвращает адрес нового компонента.
Для удаления проводов
используйте:
killarcinst Arc
Для изменения ширины или позиции
проводов используйте:
modifyarcinst
Arc DWidth DX1 DY1 DX2 DY2
где DWidth, DX1,
DY1, DX2 и DY2 - изменения ширины,
X/Y позиции end 1, и X/Y позиции end 2. Заметьте,
что изменения позиции не сказываются
на перемещении соединенных узлов, так
что изменения могут быть только
небольшими, работающими внутри портов.
Для изменения прототипа провода
используйте:
replacearcinst OldArc
NewPrototype
где OldArc - формирователь
провода, а NewPrototype - новый arcproto
для использования. Узлы на обоих концах
должны быть доступны этому новому типу
провода. Предикат возвращает адрес
нового провода.
Для удаления экспорта
используйте:
killportproto Facet
Port
что удалит порт Port на фасете
Facet.
Для перемещения экспорта с одного
компонента на другой (сохраняя
присоединенные провода)
используйте:
moveportproto Facet
OldPort NewNode PortOnNewNode
где старый порт -
OldPort в фасете Facet, а его теперь
перемещенный компонент - NewNode (который
также в фасете Facet), порт PortOnNewNode
этого компонента.
Общей операцией является поиск всех компонент в фасете. Следующий код печатает имена всех компонент в фасете "myfacet":
for { set node [getval $myfacet firstnodeinst]
}
{ [string c $node #nodeinst-1] !=
0 }
{ set node [getval $node
nextnodeinst] }
{
puts
stdout [format "Found %s node" [describenode $node]]
}
Где describenode - определено так (имя узла находится в разных местах, в зависимости от того, является ли он примитивом или сложным nodeproto):
proc describenode node
{
set
proto [getval $node proto]
if {
[getval $proto primindex] == 0}
{
return [getval [getval $proto cell] cellname] }
return
[getval $proto primname]
}
А следующий код печатает имена всех проводов в фасете "myfacet":
for { set arc [getval $myfacet firstarcinst]
}
{ [string c $arc #arcinst-1] != 0
}
{ set arc [getval $arc
nextarcinst] }
{
puts
stdout [format "Found %s arc"
[getval
[getval $arc proto] protoname]]
}
Для осуществления
поиска всех узлов и дуг в прямоугольной
области фасета вначале вызовите:
initsearch LowX HighX LowY HighY Facet
где
LowX, HighX, LowY и HighY - координаты
поиска в фасете Facet (nodeproto). Этот
предикат вернет ключ поиска, который
затем повторно будет передан:
nextobject
SearchKey
что вернет geom объекты
каждого узла и дуги в области поиска.
Когда предикат возвращает #geom-1,
поиск завершается. geom объекты могут
указывать либо на узел, либо на дугу, в
зависимости от их атрибута "entryisnode".
Затем атрибут "entryaddr" укажет на
актуальный nodeinst или arcinst. Вот
пример кода, который печатает имена
всех узлов и дуг в области (2000 <= X <=
10000, -3000 <= Y <= 3000). Выбранная область
показана здесь как черный ящик.
set key [initsearch 2000 10000 -3000 3000
$myfacet] |
Вид (отображение) - объект, описывающий
ячейку. Есть много стандартных отображений:
Layout, Schematic, Icon, Simulation-snapshot, Skeleton, VHDL,
Verilog, Document, Unknown и много вариантов Netlist.
Дополнительно может быть создан новый
вид с помощью "newview":
newview
ViewName Abbreviation
и вид может быть удален с помощью
killview (стандартные виды не могут
удаляться):
killview View
Для
получения объекта вида используйте
getview на его имени.
Для ассоциации разных видов ячейки
предикаты iconview и contentsview достигают
разных фасет. Например:
iconview
Myfacet
находит ассоциированный фасет
иконки ячейки, в которой находится
"Myfacet".
В примерах выше всегда используются
текущие библиотеки. Это определяется
вызовом:
curlib
Однако могут
быть и другие библиотеки. Для получения
специально названной библиотеки
используйте:
getlibrary LibName
Для создания новой библиотеки
используйте:
newlibrary LibraryName
LibraryFile
где LibraryName - используемое
имя, а LibraryFile - имя, где эта библиотека
будет хранится. Этот предикат возвращает
адрес нового объекта библиотеки, который
может быть использован, когда создается
фасет.
Только одна библиотека является
текущей, и для переключения вы должны
использовать:
selectlibrary Lib
Библиотека может быть удалена:
killlibrary Lib
Библиотека может быть вытерта (erased)
(ее фасеты удаляются, но не сама библиотека)
с помощью:
eraselibrary Lib
Технология - это окружение разработки,
включающее примитивы компонент и
прототипы проводов. Текущая технология
может быть получена с помощью:
curtech
Определенная технология может быть
получена по имени с помощью:
gettechnology
TechName
Все технологии могут быть найдены в списке, начинающемся с технологии, которая называется "Generic".
Инструмент - это кусочек кода синтеза
или анализа, который может оперировать
на базе данных. Обычный объект инструмента
может быть получен с помощью:
gettool ToolName
где возможные имена инструментов:
compaction |
circuit compaction |
compensation |
geometry compensation |
drc |
design-rule checking |
erc |
electrical-rule checking |
io |
input/output control |
logeffort |
logical effort analysis |
network |
network maintenance |
pla |
programmable logic array generator |
project |
project management |
routing |
automatic wire routing |
silicon-compiler |
netlist-to-layout silicon assembler |
simulation |
simulation |
user |
the user interface |
vhdl-compiler |
VHDL-to-netlist compiler |
Некоторое количество инструментов
доступно через:
maxtool
И
частные инструменты, индексированные
от 0 до (maxtool)-1, могут быть получены:
indextool Index
Инструменты можно переключать с
помощью:
toolturnon Tool NoCatchUp
где
Tool объект инструмента, а NoCatchUp
не нулевое для сдерживания активности,
обычно предусмотрено, когда инструмент
отключается.
Инструмент можно отключить с
помощью:
toolturnoff Tool
Инструменту можно передать специальные
инструкции:
telltool Tool
PARAMETERS
Например, список всех технологий,
используя следующий код:
telltool
[getaid user] {show technologies}
Эти команды
исходят от низкоуровневого интерпретатора
команд, который полностью задокументирован
в Internals Manual.
Все изменения в базе данных выстраиваются
во внутреннюю очередь в "batch",
который включает изменения и любые
вынужденные сторонние эффекты этих
изменений. Новый пакет (batch) создается
для каждой сессии TCL интерпретатора
(также для каждой команды Electric, которая
вызывается с клавиатуры/мышкой). Для
отказа от последнего пакета изменений
используйте:
undoabatch
Множественные вызовы этим предикатом
в единственном пакете отменят множество
пакетов. Для очистки списка пакетов
изменений используйте:
noundoallowed
Если вы создаете проводник, который
делает много изгибов, необходимо создать
специальные узлы, называемые "pins"
на каждом изгибе. Для отыскания, какого
рода вывод использовать для данного
типа проводника, используйте:
getpinproto
Arc
где Arc - тип проводника, а
предикат возвращает тип компонента
(nodeproto) вывода.
Сетевые объекты могут быть получены
по имени с предикатом getnetwork, который
берет имя и фасет для поиска. Например,
код:
getnetwork insig Myfacet
получает
адрес сети, названный "insig" в фасете
Myfacet.
Общая функция образца узла может быть
определена с помощью:
nodefunction
Node
возвращая значения из списка
констант в файле С заголовка "efunction.h".
Это значение совершенно то же самое,
что было бы получено при просмотре полей
"userbits" прототипа узла. Однако
некоторые компоненты, имеющие общие
прототипы, будут в большей степени
специфицироваться этим предикатом.
Чтобы получить значение атрибута из
образца выше в иерархии
используйте:
getparentval Name Default
Height
где Name - имя атрибута, Default
- значение по умолчанию, возвращаемое,
если атрибут не найден, а Height - число
уровней иерархии, по которым нужно
подняться при поиске атрибута (0 для
бесконечности). Как и горячая клавиша
для поиска значений параметра, есть
четыре макроса, которые используют этот
шаблон:
P xx получает значение параметра xx из родительского образца в иерархии.
PD xx def получает значение параметра xx из родительского образца в иерархии и использует значение def, если параметр не может быть найден.
PAR xx получает значение параметра xx из любого высшего образца где-нибудь в иерархии.
PARD xx def получает значение параметра xx из любого высшего образца где-нибудь в иерархии и использует значение def, если параметр не может быть найден.
|
|