• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Custom IC SKILL
  3. DRC warning when use abConvertPolygonToPath.ils code

Stats

  • Locked Locked
  • Replies 4
  • Subscribers 143
  • Views 3153
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

DRC warning when use abConvertPolygonToPath.ils code

Esteban Saavedra
Esteban Saavedra 10 months ago

Hi All,

I'm using a code (abConvertPolygonToPath.ils) that I found in other posts to convert a rect object to a path object inside a pcell code, but when I try to run a DRC, the layout export fails due to a warning message, here is the log message

*WARNING* (DB-270001): Pcell evaluation for 18A_asaavedr/lay_mesh_BM0_BM4_3p6_3p6/layout has the following error(s):

*WARNING* (DB-270002): ("eval" 0 t nil ("*Error* eval: undefined function" abConvertPolygonToPath))

 

ERROR (XOASIS-231): Pcell evaluation failed for '18A_asaavedr/lay_mesh_BM0_BM4_3p6_3p6/layout' because the Pcell SKILL code contains either a syntax error or an unsupported XOasis function. Check the standard output or the Virtuoso log file for more information. Cadence recommends correcting the Pcell SKILL code to resolve the issue. However, to ignore these errors and continue the translation, you may use the 'ignorePcellEvalFail' option.

INFO (XOASIS-282): Translation Failed. '1' error(s) and '3' warning(s) found.

And when compile the code I get the following message:

*WARNING* defgeneric function already defined - abConvertPolygonToPath

I will aprreciate any help in how to waive this error, or fix it.

Thank you

  • Cancel
Parents
  • Andrew Beckett
    Andrew Beckett 10 months ago

    Any auxiliary functions called from within the body of the PCell need to be loaded in each session (loading them at the time the PCell is defined is insufficient).

    Add:

    load(“/path/to/abConvertPolygonToPath.ils”)

    to a libInit.il (libInit.ils) file within the library containing your PCell. This will get auto loaded the first time the library is accessed within a session (including the stream out used during DRC) which will ensure that these supporting functions are loaded before they are needed.

    Note, the pcDefinePCell only needs to be loaded when you define the PCell (definitely not from the libInit file).

    Andrew (that’s my code you’re using!)

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • Andrew Beckett
    Andrew Beckett 10 months ago

    Any auxiliary functions called from within the body of the PCell need to be loaded in each session (loading them at the time the PCell is defined is insufficient).

    Add:

    load(“/path/to/abConvertPolygonToPath.ils”)

    to a libInit.il (libInit.ils) file within the library containing your PCell. This will get auto loaded the first time the library is accessed within a session (including the stream out used during DRC) which will ensure that these supporting functions are loaded before they are needed.

    Note, the pcDefinePCell only needs to be loaded when you define the PCell (definitely not from the libInit file).

    Andrew (that’s my code you’re using!)

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
  • Esteban Saavedra
    Esteban Saavedra 9 months ago in reply to Andrew Beckett

    Hi Andrew,.

    Thanks for your response I follwed the steps thta mentiones, but now I'm having the following error:

    *WARNING* (DB-270001): Pcell evaluation for 18A_asaavedr/lay_mesh_BM0_BM4_3p6_3p6/layout has the following error(s):
    *WARNING* (DB-270002): ("eval" 0 t nil ("*Error* eval: undefined function" leLayerXor))

    ERROR (XOASIS-231): Pcell evaluation failed for '18A_asaavedr/lay_mesh_BM0_BM4_3p6_3p6/layout' because the Pcell SKILL code contains either a syntax error or an unsupported XOasis function. Check the standard output or the Virtuoso log file for more information. Cadence recommends correcting the Pcell SKILL code to resolve the issue. However, to ignore these errors and continue the translation, you may use the 'ignorePcellEvalFail' option.
    INFO (XOASIS-282): Translation Failed. '1' error(s) and '3' warning(s) found.

    There is an issue with the variable "leLayerXor", could you please help me to know what else I'm missing?

    Thank you.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett 9 months ago in reply to Esteban Saavedra

    OK, I wrote the code 23 years ago, so I couldn't remember the details off the top of my head. I just looked at it, and it's not suitable for use in PCells, because it uses a function that can't be used in PCells (leLayerXor).

    I will take a look at the code and look to change the Xor to use something that is safe to use in PCells. However, this won't be for a few days as I am going to be away this week.

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett 9 months ago in reply to Andrew Beckett

    Here's an updated version of the code (I cleaned up a few unnecessary things too) that uses dbLayerXor rather than leLayerXor and as a result should work in PCells:

    /* abConvertPolygonToPath.ils
    
    Author     A.D.Beckett
    Group      Custom IC (UK), Cadence Design Systems Ltd.
    Language   SKILL
    Date       Aug 09, 2001 
    Modified   Nov 11, 2024 
    By         A.D.Beckett
    
    Code to attempt to convert polygons or rectangles to paths.
    
    Usage:
    
    abConvertPolygonToPath(obj) or
    abConvertPolygonToPath(list_of_objs)
    
    Typical usage:
    
    abConvertPolygonToPath(geGetSelSet())
    
    The code is SKILL++ code - ensure that the .ils suffix
    is retained, to ensure it is interpreted correctly.
    
    This employs a fairly brute force algorithm. It uses 
    rodCreatePath to create a path along the edge of one half
    of the polygon, starting at successive points in the polygon.
    For each path that was successfully created, it XORs the new
    shape with the original shape, in order to find out whether the
    path covers the original shape (and no more). If a matching
    path is found, the search stops.
    The algorithm is generally quite successful, and works in
    most cases where there is a solution - even with 45 degree
    paths. Non-45 degree paths are less likely to succeed.
    
    By default, the working layers are "y1", "y2". If you
    need to change these for whatever reason, this can be done
    as follows:
    
    abSetConvertPolygonWorkLayer("work1" '("annotate" "drawing1"))
    abSetConvertPolygonWorkLayer("work2" '("annotate" "drawing2"))
    
    In other words, use the layers you need as the second argument.
    
    (Note to the interested. I don't use the create object from
      object feature of rodCreatePath - partly because that isn't
      available in 4.4.3, but also because it doesn't actually
      save that much code. I'd need to tell it the start and end
      handles to use - which would still need to be derived. Also,
      the width would still need to be calculated in the same way
      it's being done now).
    
    Updated in version 1.5 to use dbLayerXor rather than leLayerXor
    so that the code can be used in PCells.
    
    ***************************************************
    
    SCCS Info: @(#) abConvertPolygonToPath.ils 11/11/24.22:04:15 1.5
    
    */
    
    ;*;PUBLIC abConvertPolygonToPath
    ;*;PUBLIC abSetConvertPolygonWorkLayer
    
    /***************************************************************
    *                                                              *
    *                (abConvertPolygonToPath (obj))                *
    *                                                              *
    *  The generic function which errors if any invalid arguments  *
    *                          are given.                          *
    *                                                              *
    ***************************************************************/
    
    (defgeneric abConvertPolygonToPath (obj)
      (error "abConvertPolygonToPath passed incorrect args %L\n" obj)
      )
    
    
    /****************************************************************
    *                                                               *
    *           (abConvertPolygonToPath ((obj dbobject)))           *
    *                                                               *
    * The method which handles converting database objects to paths *
    *                                                               *
    ****************************************************************/
    
    (defmethod abConvertPolygonToPath ((obj dbobject))
      (let ((cellView (getq obj cellView))
    	(origLayer (getq obj lpp))
    	(nPoints (getq obj nPoints))
    	(work1 (abGetConvertPolygonWorkLayer "work1"))
    	(work2 (abGetConvertPolygonWorkLayer "work2"))
    	(pointstried 0) newPoints
    	width pt1 pt2 halfpoints found newShape
    	hidewoport
    	pointList xorResults
    	)
           ;-----------------------------------------------------------------
           ; Decide if this is a shape we can do anything with
           ;-----------------------------------------------------------------
           (cond
    	;----------------------------------------------------------------
    	; Polygons - just get the point list
    	;----------------------------------------------------------------
    	((and (equal (getq obj objType) "polygon")
    	      (evenp nPoints))
    	 (setq pointList (getq obj points))
    	 )
    	;----------------------------------------------------------------
    	; Rectangles - build the point list. Try to be vaguely
    	; smart by ordering the point list so that the algorithm
    	; below will choose the minimum width as the path width
    	;----------------------------------------------------------------
    	((equal (getq obj objType) "rect")
    	 (let (ll ur w1 w2)
    	      (setq ll (lowerLeft (getq obj bBox)))
    	      (setq ur (upperRight (getq obj bBox)))
    	      (setq w1 (difference (xCoord ur) (xCoord ll)))
    	      (setq w2 (difference (yCoord ur) (yCoord ll)))
    	      (setq pointList
    		    (if (greaterp w1 w2)
    			(list
    			 ll (list (xCoord ll) (yCoord ur))
    			 ur (list (xCoord ur) (yCoord ll)))
    			(list
    			 ll (list (xCoord ur) (yCoord ll))
    			 ur (list (xCoord ll) (yCoord ur)))
    			))
    	      (setq nPoints 4)
    	      )
    	 )
    	)
           ;-----------------------------------------------------------------
           ; If a point list was found above, try to find a path
           ; which fits the polygon
           ;-----------------------------------------------------------------
           (when pointList
    	     (setq halfpoints (rightshift nPoints 1))
    	     ;-----------------------------------------------------------
    	     ; Set up a port for hiding warnings. Unfortunately
    	     ; the rodCreatePath function creates two sets of warnings,
    	     ; and so getWarn can't swallow them
    	     ;-----------------------------------------------------------
    	     (setq hidewoport (outfile "/dev/null"))
    	     (foreach map subList pointList
    		      (unless (or found (geqp pointstried halfpoints))
    			      ;------------------------------------------
    			      ; Get the guessed width - the length
    			      ; of the first segment of the subList
    			      ;------------------------------------------
    			      (setq pt1 (car subList))
    			      (setq pt2 (cadr subList))
    			      (setq width
    				    (sqrt
    				     (plus
    				      (expt
    				       (difference (xCoord pt2) (xCoord pt1)) 2)
    				      (expt
    				       (difference (yCoord pt2) (yCoord pt1)) 2)
    				      )))
    			      ;------------------------------------------
    			      ; Build the new point list - this is
    			      ; the first "halfpoints" number of points
    			      ; in the rest of the subList
    			      ;------------------------------------------
    			      (setq newPoints nil)
    			      (for point 1 halfpoints
    				   (setq subList (cdr subList))
    				   (setq newPoints 
    					 (cons (car subList) newPoints))
    				   )
    			      ;------------------------------------------
    			      ; Try creating the path with both left and right
    			      ; justification (if necessary). Note that
    			      ; the errset is there to trap errors thrown
    			      ; if the point list was invalid.
    			      ;------------------------------------------
    			      (forall just '("left" "right")
    				      (progn
    				       ;---------------------------------
    				       ; Invoke wrapper around rodCreatePath
    				       ;---------------------------------
    				       (setq newShape
    					     (abConvertPolygonToPathCreatePath
    					      hidewoport cellView work1 width
    					      newPoints just
    					      ))
    				       (getWarn)
    				       ;---------------------------------
    				       ; If a shape was created, Xor the
    				       ; original shape with the new shapes.
    				       ;---------------------------------
    				       (when newShape
    					     (setq xorResults
    						   (dbLayerXor
    						    cellView work2
    						    (list obj) (list (getq newShape dbId))
    						    ))
    					     ;---------------------------
    					     ; If there was anything output
    					     ; by the Xor, then the path isn't
    					     ; the same as the polygon, so
    					     ; delete this attempt
    					     ;---------------------------
    					     (if xorResults 
    						 (progn
    						  (foreach shape xorResults
    							   (dbDeleteObject
    							    shape
    							    )
    							   )
    						  (dbDeleteObject
    						   (getq newShape dbId))
    						  )
    						 ;-----------------------
    						 ; Otherwise we've found a
    						 ; matching path
    						 ;-----------------------
    						 (setq found t)
    						 )
    					     )
    				       (null found)
    				       )
    				      )
    			      ;------------------------------------------
    			      ; Increment the number of points tried. There's
    			      ; no need to go past half way around the
    			      ; polygon
    			      ;------------------------------------------
    			      (postincrement pointstried)
    			      )
    		      )
    	     ;-----------------------------------------------------------
    	     ; Close the port for hiding warnings
    	     ;-----------------------------------------------------------
    	     (when hidewoport (close hidewoport))
    	     )
           ;-----------------------------------------------------------------
           ; Cleanup. If it was found, delete the original object
           ; and move the new path onto the right layer. 
           ;-----------------------------------------------------------------
           (when found 
    	 (putpropq (getq newShape dbId) origLayer lpp)
    	 (dbDeleteObject obj)
    	 ;---------------------------------------------------------------
    	 ; Return the object and un-rodify it
    	 ;---------------------------------------------------------------
    	 (prog1
    	   (getq newShape dbId)
    	   (rodUnNameShape newShape)
    	   )
    	 )
           )
      )
    
    /***************************************************************
    *                                                              *
    *            (abConvertPolygonToPath ((obj list)))             *
    *                                                              *
    * A method which handles a list of objects being passed to the *
    *   function. This does a mapcar on the entries in the list    *
    *                                                              *
    ***************************************************************/
    
    (defmethod abConvertPolygonToPath ((obj list))
      (mapcar abConvertPolygonToPath obj)
      )
    
    /*****************************************************************************
    *                                                                            *
    * (abConvertPolygonToPathCreatePath woport cellView layer width points just) *
    *                                                                            *
    *    Function to wrap up creating the path (or at least trying) in order     *
    *        to trap any errors or warnings. Note that this is defined as        *
    *        a SKILL (i.e. dynamically scoped) function in order to allow        *
    *                       woport to be safely overridden                       *
    *                                                                            *
    *****************************************************************************/
    
    (inSkill
      (defun abConvertPolygonToPathCreatePath
    	 (woport cellView layer width points just)
    	 (let (newShape)
    	      (errset
    	       (setq newShape
    		     (rodCreatePath
    		      ?cvId cellView 
    		      ?layer layer
    		      ?width width
    		      ?pts points
    		      ?justification just
    		      )
    		     )
    	       ) ; errset
    	      newShape
    	      ) ; let
    	 ) ; defun
      ) ; inSkill
    
    /***************************************************************
    *                                                              *
    * A lexically scoped bit of code to provide a means of hiding  *
    *  a "global" variable. This is to allow the user to override  *
    *                   the working layers used.                   *
    *                                                              *
    ***************************************************************/
    (let (workLayers)
      (setq abGetConvertPolygonWorkLayer
    	(lambda (layerName) (arrayref workLayers layerName))
    	)
      (setq abSetConvertPolygonWorkLayer
    	(lambda (layerName actualLayer) 
    		(setarray workLayers layerName actualLayer))
    	)
      ;----------------------------------------------------------------------
      ; Initialise the workLayers table with the default working
      ; layers
      ;----------------------------------------------------------------------
      (setq workLayers (makeTable 'abConvertPolygonWorkLayers nil))
      (abSetConvertPolygonWorkLayer "work1" '("y1" "drawing"))
      (abSetConvertPolygonWorkLayer "work2" '("y2" "drawing"))
      )
    
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information