Часть 11: ИНТЕРПРЕТАТОРЫ


plug

11-4: Интерфейс Java

plug



Этот раздел поясняет интерфейс языка интерпретатора Java в Electric, системе разработки VLSI.

В разделе предполагается, что читатель очень хорошо знает Electric, и как-то знаком с внутренним строением системы. Внутреннее руководство (Internals Manual) (документ, доступный на Static Free Software) обеспечивает широкий, С-ориентированный взгляд на информацию, описанную здесь. Для пользователей Java, однако, этот раздел суммирует важные аспекты внутреннего руководства. В общем, наилучший путь к пониманию этого раздела - выполнить каждую команду по мере ее объяснения.

На протяжении этого раздела примеры кода Java будут появляться underlined (подчеркнутыми). Например, метод "getArcProto" получает имя прототипа дуги и возвращает указатель на этот объект. Это кодируется, как Electric.getArcProto("Metal-1"), который вычисляется по указателю формы ArcInst(21726672).

Управление сессией

Для вызова интерпретатора Java используйте субкоманду Java... команды Language Interpreter меню Tools. На некоторых системах, возможно, понадобится переместить курсор в окно сообщений (текстовое окно), чтобы интерпретатор "слышал" вас.

Если у вас установлено Bean Shell (см. инструкции по установке), тогда интерпретатор Java будет доступен с поддержкой любых выражений Java. Bean Shell также позволит вам использовать "E" вместо "Electric" в любых выражениях.

Если Bean Shell не установлено, тогда интерпретатор может принимать только один тип команды: CLASS.METHOD, который вызывает метод в классе. Метод может быть статическим и не принимать параметры.

Electric имеет свою собственную частную область для классов Java, которые он добавляет к списку размещения, и которые Java будет просматривать. Этот путь - поддиректория "java" директории библиотеки Electric. Лучше всего размещать ваш код Java здесь, и добавлять эту import строку при старте:
  import COM.staticfreesoft.*;

Чтобы вернуться в Electric из Java, введите ^D (удерживайте на клавиатуре клавишу Control и нажмите "D"). В  Windows вы должны нажать клавишу ESC.

Java, используемая в параметрах

Важное использование Java - это в атрибутах и параметрах. Например, атрибут "width" схемы транзистора может быть установлен так, чтобы быть кодом. Этот код принимает форму выражения, такого, как 2+2 или Math.Sqrt(7.5).

Обычно выражения нуждаются в использовании значения параметра (см. раздел 6-8 о создании фасета параметров). Чтобы получить значение параметра из образца выше в иерархии, используйте:
  Electric.getParentVal("name", default, height)
где "name" - имя атрибута, default - возвращаемое значение по умолчанию, если атрибут не найден, а height - количество пройденных уровней иерархии при поиске атрибута (0 для бесконечности). Как горячие клавиши для поиска значений параметров, Bean Shell добавляет пять макросов, которые используют этот шаблон:

Так что, если транзистор в фасете с параметром, названным "strength", и он должен быть равен половине этого значения ширины, используйте выражение @strength/2.

Структура базы данных

Полная база данных 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

WindowPart

window partition object

WindowFrame

display window object

Constraint

constraint system object

Graphics

graphical attributes object

Polygon

graphical shape object

XArray

transformation object

Также есть возможность иметь отображаемые переменные (те, чьи значения появляются на объекте) с ключевым словом:
 vdisplay.

Любой объект Java, который представлен объектом Electric, в действительности объект с единственным полем в нем: адресом объекта в Electric. Вы можете получить это поле с помощью getAddress, и вы можете установить это поле (опасная операция) с помощью setAddress. Вы можете посмотреть, указывается ли это поле нулевым указателем, с помощью метода isNull. И, наконец, вы можете посмотреть, эквивалентны ли два поля с помощью isEqual (помните, что объекты Java могут быть разными, но если их адреса Electric одинаковы, тогда они одинаковые объекты Electric).

Проверка базы данных

Для начала поиска в базе данных важно знать текущую библиотеку. Это сделано так:
  Electric.curLib()

возвращает указатель на объект Library (например, Library 15464800). Отсюда текущий фасет может быть получен с помощью:
  Electric.getVal(Electric.curLib(), "firstnodeproto")

Существенно, что любой атрибут может быть проверен с помощью getVal, и новый атрибут может быть создан с помощью setVal. getVal имеет следующий формат:
  Electric.getVal(object, attribute)
где object - ассоциируемый объект, а attribute - запрашиваемые атрибуты. Список всех существующих атрибутов на объектах Electric дан в конце этого документа.

Новые атрибуты могут быть созданы на любом объекте с помощью setVal. В общем, многие из существующих атрибутов, которые описаны в конце этого документа, не могут быть установлены с помощью setVal, но управляются специальными методами модификации базы данных. Формат setVal:
  Electric.setVal(object, attribute, value, options)
где options это либо 0, либо displayable для показа этого атрибута при отображении объекта. Например, для добавления нового атрибута, названного "power-consumption" к компоненту транзистор "t1", и придания ему значения 75, используйте:
  Electric.setVal(t1, "power-consumption", 75, 0);
Для добавления отображаемого имени узлу "t1" используйте:
  Electric.setVal(t1, "NODE_name", "Q1", Electric.vdisplay);
Вы можете задать массив значений. Например, для установки очертания узла чисто слоя - pure-layer node "metal" со звездочкой используйте:
  Integer[] outline = new Integer[8];
  outline[0] = -1000; outline[1] = 0;
  outline[2] = 0; outline[3] = 1000;
  outline[4] = 1000; outline[5] = 0;
  outline[6] = 0; outline[7] = -1000;
  Electric.setVal(metal, "trace", outline, 0);

Единственный элемент в массиве атрибутов может быть установлен с помощью:
  Electric.setInd(object, attribute, index, value)
где index - это 0-базируемый элемент массива.

И, наконец, атрибут может быть удален с помощью:
  Electric.delVal(object, attribute)
Однако только те атрибуты, которые были созданы  setVal, могут быть удалены таким образом. Другие атрибуты защищены.

Основы синтеза

Для создания нового фасета в текущей библиотеке используйте:
  Electric.newNodeProto(facetName, Electric.curLib())
возвращающее указатель NodeProto, который может быть использован при последующих вызовах, которые размещают компоненты и провода в этом фасете.

Для получения адреса существующего NodeProto используйте:
  Electric.getNodeProto(facetName)

возвращающее тот же тип значения, что и NewNodeProto. Таким образом, код:
  Electric.NodeProto myfacet = Electric.newNodeProto("adder{lay}", Electric.curLib());
тот же, что и код:
  Electric.newNodeProto("adder{lay}", Electric.curLib());
  Electric.NodeProto myfacet = Electric.getNodeProto("adder{lay}");
а оба - часть представления "layout" ячейки, названной "adder".

В качестве отступления, метод getCell может быть использован для получения объекта Cell, как здесь:
  Electric.getCell("adder")
возвращая то же, что и:
  Electric.getVal(myfacet, "cell")

Для создания компонента в фасете используйте:
  Electric.newNodeInst(proto, lowX, highX, lowY, highY, transpose, angle, facet)
где proto это NodeProto компонента, который будет создан, lowX, highX, lowY и highY - это рамки компонента, angle число десятков градусов поворота компонента, transpose это не нуль для транспонирования ориентации компонента (после поворота), а faset - NodeProto в котором будет размещаться компонент.

Четыре ограничивающих значения это нечто путанное для вычисления. Для примитивов компонент (таких, как транзистор) любое значение приемлемо, и компонент будет масштабирован. Однако все еще хорошо бы знать значение по умолчанию, которое может быть получено из NodeProto с помощью getVal следующим образом:
  Electric.NodeProto tran = Electric.getNodeProto("P-Transistor");
  int lowx = ((Integer)Electric.getVal(tran, "lowx")).intValue();
  int highx = ((Integer)Electric.getVal(tran, "highx")).intValue();
  int lowy = ((Integer)Electric.getVal(tran, "lowy")).intValue();
  int highy = ((Integer)Electric.getVal(tran, "highy")).intValue();
Когда сложные компоненты (фасеты) размещаются, контуры ДОЛЖНЫ быть точно такими же, как рамки содержимого фасета. Эта информация доступна вышеприведенным образом. В качестве примера newNodeInst, и получения вычисления выше показанного контура, предопределенный размер P-транзистора создается в "adder" фасета с помощью:
  Electric.NodeInst t1 = Electric.newNodeInst(tran, lowx, highx, lowy, highy, 0, 0, myfacet);
Возвращаемый указатель на компонент транзистор будет использован позже при соединении.

Для соединения двух компонент необходимо знать следующие четыре вещи:

Места соединения названы PortProtos и ассоциированы с NodeProtos. Для получения адреса используйте:
  Electric.getPortProto(nodeProto, portName)
Например, для получения порта поликремния на левой стороне MOSIS CMOS P-транзистора используйте:
  Electric.PortProto polyleft = Electric.getPortProto(tran, "p-trans-poly-left");
К сожалению, нет хороших способов получить список имен портов на примитивах компонент. Есть, однако,  некоторые упрощения. Например, если есть только один порт (как в случае с большинством контактов и выводов), тогда его имя не нужно:
  Electric.PortProto port = (Electric.PortProto)Electric.getVal(tran, "firstportproto");
Этим будет получен первый порт на компоненте P-транзистор. Для получения координат порта для соединения используйте:
  Electric.portPosition(node, port)
Возвращается массив с координатами. Например:
  Integer[] portpos = Electric.portPosition(t1, polyleft);
и будут получены координаты порта "p-trans-poly-left" на вновь созданном P-транзисторе t1. Значение X будет portpos[0].intValue(), а значение Y portpos[1].intValue().

Последняя часть необходимой информации - тип дуги и ширина дуги. Задавая имя дуги, можно получить тип с помощью:
  Electric.getArcProto(arcName)
Задавая ArcProto, предопределенная ширина будет получена с помощью:
  Electric.getVal(arc, "nominalwidth")
Когда вся информация готова, вызов:
  Electric.newArcInst(arcType, width, bits, nodeA, portA, xA, yA, nodeB, portB, xB, yB, facet)
разместит проводку. Вы можете игнорировать значение bits и установить его в ноль.

Размер, использованный для создания узла или дуги, не обязательно размер объекта. Причина этого в том, что размер, заданный newNodeInst - внешняя связь объекта, который может включать слои имплантанта. Чтобы получить разницу между "nominal size" и newNodeInst размером, используйте:
  Electric.nodeProtoSizeOffset(primitiveNodeProto)
что вернет массив 4 целых с low X, high X, low Y и high Y рамки. Шаблон:
  Electric.arcProtoWidthOffset(arcProto)
вернет разницу между "nominal width" и актуальной шириной, использованной в newArcInst.

Вот полный пример размещения транзистора, контакта и проведения соединения между ними (результат показан внизу).

  /* create a facet called "tran-contact" in the current library */
  Electric.NodeProto myfacet = Electric.newNodeProto("tran-contact", Electric.curLib());

  /* get pointers to primitives */
  Electric.NodeProto tran = Electric.getNodeProto("P-Transistor");
  Electric.NodeProto contact = Electric.getNodeProto("Metal-1-Polysilicon-1-Con");

  /* get default sizes of these primitives */
  int tlowx = ((Integer)Electric.getVal(tran, "lowx")).intValue();
  int thighx = ((Integer)Electric.getVal(tran, "highx")).intValue();
  int tlowy = ((Integer)Electric.getVal(tran, "lowy")).intValue();
  int thighy = ((Integer)Electric.getVal(tran, "highy")).intValue();
  int clowx = ((Integer)Electric.getVal(contact, "lowx")).intValue();
  int chighx = ((Integer)Electric.getVal(contact, "highx")).intValue();
  int clowy = ((Integer)Electric.getVal(contact, "lowy")).intValue();
  int chighy = ((Integer)Electric.getVal(contact, "highy")).intValue();

  /* get pointer to Polysilicon arc and its default width */
  Electric.ArcProto arctype = Electric.getArcProto("Polysilicon-1");
  int width = ((Integer)Electric.getVal(arctype, "nominalwidth")).intValue();

  /* create the transistor and the contact to its left */
  Electric.NodeInst c1 = Electric.newNodeInst(contact, clowx, chighx, clowy, chighy,
   0, 0, myfacet);
  Electric.NodeInst t1 = Electric.newNodeInst(tran, tlowx+8000, thighx+8000,
   tlowy, thighy, 0, 0, myfacet);

  /* get the transistor's left port coordinates */
  Electric.PortProto tport = Electric.getPortProto(tran, "p-trans-poly-left");
  Integer[] tpos = Electric.portPosition(t1, tport);

  /* get the contacts's only port coordinates */
  Electric.PortProto cport = (Electric.PortProto)Electric.getVal(contact, "firstportproto");
  Integer[] cpos = Electric.portPosition(c1, cport);

  /* run a wire between the primitives */
  Electric.newArcInst(arctype, width, 0,
   t1, tport, tpos[0].intValue(), tpos[1].intValue(),
   c1, cport, cpos[0].intValue(), cpos[1].intValue(), myfacet);

Figure 11.1

Иерархия 

Фасеты, как созданные newNodeProto, могут быть размещены в других фасетах с помощью newNodeInst. Образцы просто используют комплексные поля NodeProto, а не примитивы NodeProtos, как в вышеприведенном примере. Например, следующий код создает новый фасет, названный "two-trans" и размещает два образца фасета "tran-contact", один над другим.

  /* create a facet called "two-trans" */
  Electric.NodeProto higherfacet =
   Electric.newNodeProto("two-trans",
    Electric.curLib());

  /* get pointer to the "tran-contact" facet */
  Electric.NodeProto tc =
   Electric.getNodeProto("tran-contact");

  /* get size of this facet */
  int lowx = ((Integer)Electric.getVal(tc,
   "lowx")).intValue();
  int highx = ((Integer)Electric.getVal(tc,
   "highx")).intValue();
  int lowy = ((Integer)Electric.getVal(tc,
   "lowy")).intValue();
  int highy = ((Integer)Electric.getVal(tc,
   "highy")).intValue();

  /* create two facet instances, one above the other */
  Electric.NodeInst o1 = Electric.newNodeInst(tc,
   lowx, highx, lowy, highy, 0, 0, higherfacet);
  Electric.NodeInst o2 = Electric.newNodeInst(tc,
   lowx, highx, lowy+10000, highy+10000,
    0, 0, higherfacet);

Figure 11.2

Другой необходимой особенностью при создании иерархии является возможность разместить провода между местами соединения на образцах фасета. Чтобы сделать это, необходимо создать экспорты. При этом берется порт на примитиве компонента (например, транзистора или контакта в фасете "tran-contact") и устраивается в экспорте на текущем фасете. Выполняется все с помощью:
  Electric.newPortProto(facet, nodeInFacet, portOnNode, portName)
где facet - это фасет, содержащий компонент, чей порт экспортируется, nodeInFacet это тот компонент, а portOnNode это частный порт на этом узле, который будет экспортирован. Например, для экспорта верхнего и нижнего портов фасета "tran-contact" (как показано здесь), может быть добавлен следующий код:


  Electric.newPortProto(myfacet, t1,
   Electric.getPortProto(tran, "p-trans-diff-top"),
    "topdiff");
  Electric.newPortProto(myfacet, t1,
   Electric.getPortProto(tran, "p-trans-diff-bottom"),
    "botdiff");

Figure 11.3

И затем компоненты "o1" и "o2" в фасете "two-trans" могут быть соединены, используя порты, названные "topdiff" и "botdiff":

  /* get pointer to P-Active arc and its default width */
  Electric.ArcProto darctype =
   Electric.getArcProto("P-Active");
  int dwidth = ((Integer)Electric.getVal(darctype,
   "nominalwidth")).intValue();

  /* get the bottom facet's top port */
  Electric.PortProto lowport = Electric.getPortProto(tc,
   "topdiff");
  Integer[] lowpos = Electric.portPosition(o1,
   lowport);

  /* get the top facet's bottom port */
  Electric.PortProto highport = Electric.getPortProto(tc,
   "botdiff");
  Integer[] highpos = Electric.portPosition(o2,
   highport);

  /* run a wire between the primitives */
  Electric.newArcInst(darctype, dwidth, 0,
   o1, lowport, lowpos[0].intValue(),
    lowpos[1].intValue(),
   o2, highport, highpos[0].intValue(),
    highpos[1].intValue(), higherfacet);

Figure 11.4

Модификация

Два вида модификации может быть выполнено для существующих объектов: удаление и изменение. Для удаления фасета используйте:
  Electric.killNodeProto(facet)

Чтобы скопировать фасет (внутри той же библиотеки или из одной библиотеки в другую) используйте:
  Electric.copyNodeProto(fromFacet, toLibrary, toFacetName)
где fromFacet - оригинальный фасет (NodeProto) и toLibrare - библиотека-получатель (destination ). Используйте (curLib) для копирования в ту же самую библиотеку. Новое имя фасета - последний параметр. Метод возвращает адрес нового фасета (NodeProto).

Для удаления компонента используйте:
  Electric.killNodeInst(node)
До удаления компонента все провода и экспорты должны быть удалены.

Для изменения размера или ориентации компонента используйте:
  Electric.modifyNodeInst(node, dLowX, dLowY, dHighX, dHighY, dRotation, dTrans)
где dLowX, dLowY, dHighX и dHighY изменения позиции и размера. dRotation и dTrans изменения ориентации.

Для изменения прототипа компонента используйте:
  Electric.replaceNodeInst(oldNode, newPrototype)
где старый компонент - oldNode, а новый NodeProto, который должен быть на его месте, это newPrototype. Этот новый прототип должен быть способен соединиться со всеми существующими дугами. Метод возвращает адрес нового компонента.

Для удаления проводов используйте:
  Electric.killArcInst(arc)

Для изменения ширины или позиции проводов используйте:
  Electric.modifyArcInst(arc, dWidth, dX1, dY1, dX2, dY2)
где dWidth, dX1, dY1, dX2 и dY2 - изменения ширины, X/Y позиции end 1, и X/Y позиции end 2. Заметьте, что изменения позиции не сказываются на перемещении соединенных узлов, так что изменения могут быть только небольшими, работающими внутри портов.

Для изменения прототипа провода используйте: 
  Electric.replaceArcInst(oldArc, newPrototype)
где oldArc - формирователь провода, а newPrototype - новый ArcProto для использования. Узлы на обоих концах должны быть доступны этому новому типу провода. Метод возвращает адрес нового провода.

Для удаления экспорта используйте: 
  Electric.killPortProto(facet, port)
что удалит порт port на фасете facet.

Для перемещения экспорта с одного компонента на другой (сохраняя присоединенные провода) используйте:
  Electric.movePortProto(facet, oldPort, newNode, portOnNewNode)
где старый порт - oldPort в фасете facet, а его теперь перемещенный компонент - newNode (который также в фасете facet), порт portOnNewNode этого компонента.

Поиск

Общей операцией является поиск всех компонент в фасете. Следующий код печатает имена всех компонент в фасете "myfacet":

  Electric.NodeInst node;
  for(node = (Electric.NodeInst)Electric.getVal(myfacet, "firstnodeinst");
   !node.isNull();
   node = (Electric.NodeInst)Electric.getVal(node, "nextnodeinst"))
  {
   System.out.println("Found " + describeNode(node) + " node");
  }

Где describeNode - определено так (имя узла находится в разных местах, в зависимости от того, является ли он примитивом или сложным NodeProto):

  public static String describeNode(Electric.NodeInst node)
  {
   Electric.NodeProto proto = (Electric.NodeProto)Electric.getVal(node, "proto");
   if (((Integer)Electric.getVal(proto, "primindex")).intValue() != 0)
    return((String)Electric.getVal(proto, "primname"));
   return((String)Electric.getVal((Electric.Cell)Electric.getVal(proto, "cell"), "cellname"));
  }

А следующий код печатает имена всех проводов в фасете "myfacet":

  Electric.ArcInst arc;
  for(arc = (Electric.ArcInst)Electric.getVal(myfacet, "firstarcinst");
   !arc.isNull();
   arc = (Electric.ArcInst)Electric.getVal(arc, "nextarcinst"))
  {
   String arcname = (String)Electric.getVal((Electric.ArcProto)Electric.getVal(arc, "proto"),
    "protoname")
   System.out.println("Found " + arcname + " arc");
  }

Для осуществления поиска всех узлов и дуг в прямоугольной области фасета вначале вызовите:
  Electric.initSearch(lowX, highX, lowY, highY, facet)
где lowX, highX, lowY и highY - координаты поиска в фасете facet (NodeProto). Этот метод вернет ключ поиска, который затем повторно будет передан:
  Electric.nextObject(searchKey)
что вернет Geom объекты каждого узла и дуги в области поиска. Когда метод возвращает нулевой Geom , поиск завершается. Geom объекты могут указывать либо на узел, либо на дугу, в зависимости от их атрибута "entryisnode". Затем атрибут "entryaddr" укажет на актуальный NodeInst или ArcInst. Если вы намерены прекратить поиск раньше, вызовите:
  Electric.termSearch(searchKey)
Вот пример кода, который печатает имена всех узлов и дуг в области (2000 <= X <= 10000, -3000 <= Y <= 3000). Выбранная область показана здесь как черный ящик.

Figure 11.5

  int key = Electric.initSearch(2000, 10000, -3000, 3000, myfacet);
  for(;;)
  {
   Electric.Geom object = Electric.nextObject(key);
   if (object.isNull()) break;
   int isnode= ((Integer)Electric.getVal(object, "entryisnode")).intValue();
   if (isnode != 0)
   {
    Electric.NodeInst ni = (Electric.NodeInst)Electric.getVal(object, "entryaddr");
    System.out.println("Found node " + describenode(ni));
   } else
   {
    Electric.ArcInst ai = (Electric.ArcInst)Electric.getVal(object, "entryaddr");
    String arcname = (String)Electric.getVal((Electric.ArcProto)Electric.getVal(ai, "proto"),
     "protoname");
    System.out.println("Found arc " + arcname);
   }
  }

Слои и прямоугольники (Polygon)

Узлы и дуги построены вне слоев, и слои описаны в объектах типа Polygon. Чтобы получить все слои в узле, вначале вызовите:
  Electric.nodePolys(node)
чтобы получить количество прямоугольников (polygons) на узле, а затем сделать повторный вызов:
  Electric.shapeNodePoly(node, index)
для получения прямоугольников.

Если вы хотите получить электрические слои (больший набор, который прерывает слои там, где они пересекают электрические границы), используйте nodeEPolys и shapeENodePoly. Для получения всех слоев в дуге, вначале вызовите arcPolys для получения количества прямоугольников на дуге, а затем сделайте повторный вызов shapeArcPoly, чтобы получить прямоугольники.

Поскольку объекты polygon создаются динамически, они должны быть освобождены, когда вы закончили с ними. Вызовите:
  Electric.freePolygon(poly)
для освобождения (ресурса) Polygon.

Чтобы получить информацию о частном слое в технологии, вызовите:
  Electric.layerName(tech, layer)
для получения имени или
  Electric.layerFunction(tech, layer)
для получения его поведения (как описано в модуле "efunction.h").

Следующий пример находит все прямоугольники на узле и печатает имена их слоя:

  for(node = (Electric.NodeInst)Electric.getVal(myFacet, "firstnodeinst");
    !node.isNull();
    node = (Electric.NodeInst)Electric.getVal(node, "nextnodeinst"))
  {
    int polys = Electric.nodePolys(node);
    for(int i = 0; i < polys; i++)
    {
      Electric.Polygon poly = Electric.shapeNodePoly(node, i);
      Electric.Technology tech = (Electric.Technology)Electric.getVal(poly, "tech");
      int layer = ((Integer)Electric.getVal(poly, "layer")).intValue();
      int count = ((Integer)Electric.getVal(poly, "count")).intValue();
      String layerName = Electric.layerName(tech, layer);
      System.out.println("Polygon on layer " + layerName + " has " + count + " points");
      Electric.freePolygon(poly);
    }
  }

Есть три подпрограммы, способные получить правила разработки для слоев.
  Electric.maxDRCSurround(tech, library, layer)
возвращает максимальное расстояние вокруг слоя (в выбранной технологии и библиотеке), в котором может быть любое правило разработки. Подпрограмма:
  Electric.DRCMinDistance(tech, library, layer1, layer2)
возвращает минимальное расстояние между слоями (в выбранной технологии и библиотеке). Подпрограмма:
  Electric.DRCMinWidth(tech, library, layer)
возвращает минимальный характерный размер слоя (в выбранной технологии и библиотеке).

Поскольку узлы могут вращаться, необходимо обеспечить трансформацию узлов для всех прямоугольников перед использованием значений координат. Для создания трансформации, описывающей вращение узлов, используйте:
  Electric.makeRot(node)
возвращающее объект XArray. Для создания трансформации, описывающей позицию узла внутри его родителя, используйте:
  Electric.makeTrans(node)

Для использования трансформации к прямоугольнику (polygon) используйте:
  Electric.xformPoly(poly, trans)

Виды

Вид (отображение) - объект, описывающий ячейку. Есть много стандартных отображений: Layout, Schematic, Icon, Simulation-snapshot, Skeleton, VHDL, Verilog, Document, Unknown и много вариантов Netlist. Дополнительно может быть создан новый вид с помощью "newView":
  Electric.newView(viewName, abbreviation)

и вид может быть удален с помощью killView (стандартные виды не могут удаляться):
  Electric.killView(view)
Для получения объекта вида используйте getView на его имени.

Для ассоциации разных видов ячейки методы iconView и contentsView достигают разных фасет. Например:
  Electric.iconView(myfacet)
находит ассоциированный фасет иконки ячейки, в которой находится "myfacet".

Библиотеки

В примерах выше всегда используются текущие библиотеки. Это определяется вызовом:
  Electric.curLib()

Однако могут быть и другие библиотеки. Для получения специально названной библиотеки используйте: 
  Electric.getLibrary(libName)

Для создания новой библиотеки используйте:
  Electric.newLibrary(libraryName, libraryFile)
где libraryName - используемое имя, а libraryFile - имя, где эта библиотека будет хранится. Этот метод возвращает адрес нового объекта библиотеки, который может быть использован, когда создается фасет.

Только одна библиотека является текущей, и для переключения вы должны использовать: 
  Electric.selectLibrary(lib)

Библиотека может быть удалена:
  Electric.killLibrary(lib)

Библиотека может быть вытерта (erased) (ее фасеты удаляются, но не сама библиотека) с помощью:
  Electric.eraseLibrary(lib)

Технологии

Технология - это окружение разработки, включающее примитивы компонент и прототипы проводов. Текущая технология может быть получена с помощью:
  Electric.curTech()

Определенная технология может быть получена по имени с помощью:
  Electric.getTechnology(techName)

Все технологии могут быть найдены в списке, начинающемся с технологии, которая называется "Generic".

Инструменты

Инструмент - это кусочек кода синтеза или анализа, который может оперировать на базе данных. Обычный объект инструмента может быть получен с помощью:
  Electric.getAid(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

Некоторое количество инструментов доступно через:
  Electric.maxAid()
И частные инструменты, индексированные от 0 до Electric.maxAid()-1, могут быть получены:
  Electric.indexAid(index)

Инструменты можно переключать с помощью:
  Electric.toolTurnOn(tool, noCatchUp)
где tool объект инструмента, а noCatchUp не нулевое для сдерживания активности, обычно предусмотрено, когда инструмент отключается.

Инструмент можно отключить с помoщью: 
  Electric.toolTurnOff(tool)

Инструменту можно передать специальные инструкции:
  Electric.tellTool(tool, count, parameters)
где parameters - массив строк count. Например, для вывода списка всех технологий используйте код:
  Electric.Tool user = Electric.getTool("user");
  String[] message = new String[2];
  message[0] = "show";
  message[1] = "technologies";
  Electric.tellTool(user, 2, message);
Команда "show technologies" и другие команды исходят от низкоуровневого интерпретатора команд, который полностью задокументирован в  Internals Manual.

Разное

Для форсирования отображения изменений, сделанных в чертеже на экране, вы должны использовать:
  Electric.flushChanges()

Все изменения в базе данных выстраиваются во внутреннюю очередь в "batch", который включает изменения и любые вынужденные сторонние эффекты этих изменений. Новый пакет (batch) создается для каждой сессии Java интерпретатора (также для каждой команды Electric, которая вызывается с клавиатуры/мышкой). Для отказа от последнего пакета изменений используйте:
  Electric.undoABatch()

Множественные вызовы этим методом в единственном пакете отменят множество пакетов. Для очистки списка пакетов изменений используйте:
  Electric.noUndoAllowed()

Если вы создаете проводник, который делает много изгибов, необходимо создать специальные узлы, называемые "pins" на каждом изгибе. Для отыскания, какого рода вывод использовать для данного типа проводника, используйте:
  Electric.getPinProto(arc)
где arc - тип проводника, а метод возвращает тип компонента (NodeProto) вывода.

Сетевые объекты могут быть получены по имени с методом getNetwork, который берет имя и фасет для поиска. Например, код:
  Electric.getNetwork("insig", myfacet)
получает адрес сети, названный "insig" в фасете myfacet.

Общая функция образца узла может быть определена с помощью: 
  Electric.nodeFunction(node)
возвращая значения из списка констант в файле С заголовка "efunction.h". Это значение совершенно то же самое, что было бы получено при просмотре полей "userbits" прототипа узла. Однако некоторые компоненты, имеющие общие прототипы, будут в большей степени специфицироваться этим методом. Для поиска вашего местоположения в иерархии (если этот объект виден внутри другого) используйте:
  Electric.getTraversalPath()
что вернет массив NodeInsts, прерываемый нулевым. Каждый элемент - образец, выше в иерархии, который содержит формирователь уровня.


Prev

Предыдущий

   

Contents

Содержание

   

Следующий

Next