File "hier.il"

Full Path: /home/analogde/www/VirtualKeyboardSample/SKILL/hier.il
File size: 11.21 KB
MIME-type: text/plain
Charset: utf-8

/***************************************************************
*                                                              *
*                     CCShiHierLayerOps()                      *
*                                                              *
*   This function builds and displays the hierarchical layer   *
* generation operations form. It is really intended to be run  *
*  from a menu item or a bindkey because the code stores the   *
* cellview and techfile on the form.  The form is intended to  *
* be similar to the existing "Layer Generation" form for easy  *
*                familiarity for the end-users.                *
*                                                              *
***************************************************************/
procedure(CCShiHierLayerOps()
  let( (cv techId layer1 layer2 outLayer operation level eqLab form)
    ;; when the cellview is valid and we can get the techfile
    when((cv = geGetEditCellView()) &&
         (techId = techGetTechFile(cv))
      ;; for each layer field create a cyclic layer field with
      ;; the appropriate arguments and values
      foreach(fieldName '(layer1 layer2 outLayer)
	set(fieldName hiCreateLayerCyclicField(
	  ;; the technology file Id
	  techId
	  ;; the prompt for the field (not displayed, see below)
	  strcat(upperCase(substring(fieldName 1 1)) substring(fieldName 2))
	  ;; the callback is empty/unused
	  ""
	  ;; the list of layer choices
	  leGetValidLayerList(techId) || list(leGetEntryLayer(techId))
	  ;; the default layer setting
	  leGetEntryLayer(techId)
	  ;; the name of the field
	  fieldName); hiCreateLayerCyclicField
	); set
      ); foreach
      ;; create the cyclic field for the layer operation
      operation = hiCreateCyclicField(
	?name		'operation
	?choices	list("AND" "AND NOT" "OR" "XOR" "GROW BY")
	?defValue	"AND"
	?prompt		"Layer Operation"
	?callback	"CCSoperationFieldCB()"
      ); hiCreateCyclicField
      ;; create the integer field for the hierarchy depth
      level = hiCreateIntField(
	?name		'level
	?prompt		"Hierarchy Depth"
	?value		geGetCellViewWindow(cv)~>stopLevel || 0
	?acceptNil	nil
	?defValue	0
	?range		list(0 nil)
      ); hiCreateIntField
      ;; create the = label
      eqLab = hiCreateLabel(
	?name		'eqLab
	?labelText	"="
      ); hiCreateLabel
      ;; create the form, the layout is based upon the existing
      ;; "Layer Generation" form
      form = hiCreateAppForm(
	?name		'CCShiHierLayerOps
	?formTitle	"Hierarchical Layer Generation"
	?buttonLayout	'OKCancelApply
	?fields		list( list(layer1 0:0 100:30 0)
			  list(operation 135:0 100:30 0)
			  list(layer2 225:0 100:30 0)
			  list(eqLab 360:0 30:30 0)
			  list(outLayer 380:0 100:30 0)
			  list(level 520:0 130:30 100) )
	?callback	'CCShiHierLayerOpsCB
      ); hiCreateAppForm
      ;; store the layer2 field, the original is removed from the
      ;; form if the operation is changed to "GROW BY", use this
      ;; storage to be able to restore it later
      form->store = layer2
      ;; store the current cellview on the form, this is a convenient
      ;; way of storing and passing the cellview to the callback
      form->cellView = cv
      ;; display the form
      hiDisplayForm(form)
    ); when we can get the techfile for the current cellview
  ); let
); procedure CCShiHierLayerOps


/*****************************************************************
*                                                                *
*                     CCSoperationFieldCB()                      *
*                                                                *
*  This function is called when the operation field is changed.  *
*   It is used to add an integer field in place of the second    *
*  layer field when performing a "GROW BY" operation, or to put  *
* the second layer field back again if the operation is changed  *
* back to something other than this setting.  The last operation *
*   is stored on the form to keep track of what was just done.   *
*                                                                *
*****************************************************************/
procedure(CCSoperationFieldCB()
  let( (form op)
    ;; get the current form (should be the one that caused this
    ;; callback to be called in the first place
    form = hiGetCurrentForm()
    ;; get the value of the operation cyclic field
    op = form->operation->value
    ;; unless the operation is the same as it last was
    unless(op == form->lastOp
      cond(
	;; if the operation is "GROW BY" then delete the layer2
	;; field and add a size floating point field in its place
        (op == "GROW BY"
	  hiDeleteField(form form->layer2->hiFieldSym)
	  hiAddField(form
	    list(hiCreateFloatField(
	      ?name		'size
	      ?value		1.0
	      ?acceptNil	nil
	      ?prompt		"Size"
	      ?range		list(0 nil)
	    )
	    list(225 0) list(100 30) 0)
	  ); hiAddField
	)
	;; if the last operation was "GROW BY" (and the current
	;; operation is not, since that is handled by the condition
	;; above) then delete the size field and put the layer2
	;; field back
	(form->lastOp == "GROW BY"
	  hiDeleteField(form form->size->hiFieldSym)
	  hiAddField(form 
	    list(form->store list(225 0) list(100 30) 0)
	  )
	)
      ); cond
      ;; store the operation on the form
      form->lastOp = op
    ); unless
  ); let
); procedure CCSoperationFieldCB


/****************************************************************
*                                                               *
*           CCSgetLayerPurposePair( r_form s_field )            *
*                                                               *
* A function to take the value of the form's layer cyclic field *
*         and convert it into a layer-purpose pair list         *
*                                                               *
****************************************************************/
procedure(CCSgetLayerPurposePair(form field "rs")
  let( (lpp)
    ;; get the value of the form field passed in
    lpp = getq(get(form field) value)
    ;; then get the part that gives the layer and purpose
    lpp = parseString(cadddr(lpp))
    ;; then remove the () from around the purpose and return
    lpp = setcdr(lpp parseString(cadr(lpp) "()"))
  ); let
); procedure CCSgetLayerPurposePair


/*****************************************************************
*                                                                *
*                 CCShiHierLayerOpsCB( r_form )                  *
*                                                                *
* This procedure is an interface to the CCShierLayerOps function *
* when the form is used to invoke that function. Most values are *
*   taken from the field values directly, except for the layer   *
*  cyclic fields which are processed from the field value to a   *
*  layer-purpose pair entry, and the cellview is obtained from   *
*                  the value stored on the form                  *
*                                                                *
*****************************************************************/
procedure(CCShiHierLayerOpsCB(form "r")
  CCShierLayerOps(
    ?cv		form->cellView
    ?layer1	CCSgetLayerPurposePair(form 'layer1)
    ?layer2	unless(form->size CCSgetLayerPurposePair(form 'layer2))
    ?outLayer	CCSgetLayerPurposePair(form 'outLayer)
    ?op		form->operation->value
    ?size	form->size->value
    ?level	form->level->value
  ); CCShierLayerOps
); procedure CCShiHierLayerOpsCB


/*********************************************************************
*                                                                    *
*             CCShierLayerOps(                                       *
*               [?cv geGetEditCellView() | d_cellView]               *
*               [?layer1 g_layer1]                                   *
*               [?layer2 g_layer2]                                   *
*               [?outLayer g_outLayer]                               *
*               [?op t_layerOperation]                               *
*               [?size n_size]                                       *
*               [?level 0 | x_hierarchyDepth] )                      *
*                                                                    *
* A function to perform layer generation with the option of working  *
* hierarchically.  The function takes all shapes on the named input  *
* layers (flattened in a scratch cellview if working hierarchically) *
*  and uses the dbLayer functions to apply the operation to create   *
*  data on the "outLayer" and then copy these back to the original   *
*   cellview.  If the "size" argument is given it takes precedence   *
*    over the layer2 argument, this assumes that the operation is    *
*                             "GROW BY"                              *
*                                                                    *
*********************************************************************/

procedure(CCShierLayerOps(@key (cv geGetEditCellView())
	  layer1 layer2 outLayer op size (level 0) "dgggtgx")
let((newcv layer1Name layer2Name layerOp newInst newShapes)
  when(and(cv equal(cv~>cellViewType "maskLayout"))
    ;; create a new scratch cell for intermediate operations
    newcv = dbOpenCellViewByType(cv~>libName
	      symbolToString(gensym(cv~>cellName))
	      "layout"
	      "maskLayout" "s"
	    )

	


    layer1Name = stringp(layer1)&&layer1 || pairp(layer1)&&car(layer1)
    layer2Name = stringp(layer2)&&layer2 || pairp(layer2)&&car(layer2)

	printf("* %s \n" layer1Name )
	printf("* %s \n" layer2Name )

	


    ;; copy each shape & instance to the new scratch cell
    ;; NOTE: "textDisplays" will not be copied using this method
    foreach(shape 
      setof(shp cv~>shapes shp~>objType!="textDisplay")
      dbCopyFig(shape newcv)
    )

    ;; when the hierarchy depth is greater than 0, copy the instances,
    ;; and then flatten each instance by the number of levels desired
    ;; Only perform the copy and flatten if level is greater than 0
    when(level>0
      foreach(inst cv~>instances
	;; when the instance was copied, flatten the new instance
	when(newInst=dbCopyFig(inst newcv)
	  dbFlattenInst(newInst level t t t)
	); when the instance is copied
      ); foreach
    ); when the hierarchy depth is > 0

    ;; create new shapes based on the interaction (AND in this
    ;; example) of shapes on certain layers ("metal1" and "poly1"
    ;; in this example) and store the list for the copy back
    layerOp = case(op
      ("AND"		'dbLayerAnd)
      ("AND NOT"	'dbLayerAndNot)
      ("OR"		'dbLayerOr)
      ("XOR"		'dbLayerXor)
      ("GROW BY"	'dbLayerSize)
    )
    ;; use "apply" to pass all the arguments to the appropraite
    ;; dbLayer function
    newShapes = apply(layerOp list(newcv outLayer
      setof(shape newcv~>shapes shape~>layerName == layer1Name)
      ;; if the size argument is non-nil use this for "grow by"
      or(size setof(shape newcv~>shapes shape~>layerName == layer2Name)) )
    )

    ;; copy back each new generated shape to the original layout
    newShapes = foreach(mapcar shape newShapes dbCopyFig(shape cv))

    ;; close the scratch cellview
    dbClose(newcv)
    ;; return the new shape list in the original cellview, this is
    ;; useful when this function is called directly (not via the UI)
    ;;newShapes
  ); when
); let
); procedure CCShierLayerOps