/* CCSflattenAndMerge.il

Language   SKILL
Date       Apr 17, 2007 
Modified   Apr 20, 2007 

Function to flatten and merge a particular layer into a
destination (typically scratch) cellView:

src=geOpenCellView()
dst=dbOpenCellViewByType(src~>libName src~>cellName "flattened" 
				      "maskLayout" "w")
CCSflattenAndMerge(src dst '("M1" "drawing"))

Or

CCSflattenedArea(src dst '("M1" "drawing"))

(this will flatten and merge, and then calculate the area of the shapes).
Uses ABarea.il to calculate the area of the shapes.

This code handles simple mosaics - complex mosaics (as produced by the
end-of-lifed Structure Compiler tool are not handled). The mosaic
handling should work in both OpenAccess and CDB. Also, vias are 
handled in OpenAccess.

***************************************************

SCCS Info: @(#) CCSflattenAndMerge.il 04/20/07.12:52:45 1.2

*/

/*******************************************************************************
*  DISCLAIMER: The following code is provided for Cadence customers to use at  *
*   their own risk. The code may require modification to satisfy the           *
*   requirements of any user. The code and any modifications to the code may   *
*   not be compatible with current or future versions of Cadence products.     *
*   THE CODE IS PROVIDED "AS IS" AND WITH NO WARRANTIES, INCLUDING WITHOUT     *
*   LIMITATION ANY EXPRESS WARRANTIES OR IMPLIED WARRANTIES OF MERCHANTABILITY *
*   OR FITNESS FOR A PARTICULAR USE.                                           *
*******************************************************************************/


/***************************************************************
*                                                              *
*         (CCSflattenAndMerge srcCv dstCv lpp @optional         *
*                 (transform list(0:0 "R0" 1))                 *
*                           (top t))                           *
*                                                              *
*  Traverse a hierarchy, copying and transforming shapes on a  *
*     specified layer purpose pair into a flat destination     *
* cellView. At the end, merge all the shapes on that lpp. The  *
*  transform and top arguments are normally only passed when   *
*   this function is called recursively from within itself.    *
*                                                              *
***************************************************************/

(defun CCSflattenAndMerge (srcCv dstCv lpp @optional 
				(transform list(0:0 "R0" 1))
				(top t))
  (foreach shape 
	   (dbGetq
	    (car (exists LPP (dbGetq srcCv lpps) 
			 (and
			  (equal (dbGetq LPP layerName) (car lpp))
			  (equal (dbGetq LPP purpose) (cadr lpp)))))
	    shapes)
	   (dbCopyFig shape dstCv transform)
	   )
  (foreach inst (dbGetq srcCv instances)
	   (when (equal (dbGetq inst objType) "inst")
		 (CCSflattenAndMerge (dbGetq inst master) dstCv
				    lpp
				    (dbConcatTransform
				     (dbGetq inst transform)
				     transform)
				    nil)
		 )
	   )
  (foreach via (dbGetq srcCv vias)
	   (CCSflattenAndMerge (dbGetq (dbGetq via viaHeader) master) dstCv
			      lpp
			      (dbConcatTransform
			       (list (dbGetq via origin) (dbGetq via orient) 1)
			       transform)
			      nil
			      )
	   )
  (foreach mosaic (dbGetq srcCv mosaics)
	   (if (equal (dbGetq mosaic mosaicType) "simple")
	       (let (master orient xy isOA newTransform mosaicTransform)
		    ;----------------------------------------------------
		    ; OpenAccess stores mosaics differently - in CDB,
		    ; the individual instances are rotated - in OA, the
		    ; whole mosaic is rotated. So need to detect database
		    ; type used, and adjust transformations accordingly
		    ;----------------------------------------------------
		    (setq isOA (and (isCallable 'dbGetDatabaseType)
				    (equal (dbGetDatabaseType) "OpenAccess")))
		    (setq master 
			  (dbGetq (car (dbGetq mosaic instanceList)) master))
		    (setq orient (car (dbGetq mosaic tileArray)))
		    ;----------------------------------------------------
		    ; If OA, the transformation of the whole mosaic
		    ; is calculated - by shifting to the origin, rotating,
		    ; and then shifting back
		    ;----------------------------------------------------
		    (when isOA
			  (setq mosaicTransform
				(dbConcatTransform
				 (dbConcatTransform
				  (list 
				   (mapcar 'minus (dbGetq mosaic xy)) "R0" 1)
				  (list (list 0 0) orient 1))
				 (list (dbGetq mosaic xy) "R0" 1))
				))
		    ;----------------------------------------------------
		    ; Iterate over the rows and columns, flattening each
		    ; sub-instance in the simple mosaic
		    ;----------------------------------------------------
		    (for row 0 (sub1 (dbGetq mosaic rows))
			 (for col 0 (sub1 (dbGetq mosaic columns))
			      (setq xy
				    (list
				     (plus (xCoord (dbGetq mosaic xy))
					   (times col (dbGetq mosaic uX)))
				     (plus (yCoord (dbGetq mosaic xy))
					   (times row (dbGetq mosaic uY)))
				     ))
			      ;------------------------------------------
			      ; Compute the transformation of the sub-instance
			      ; Done differently for OA and CDB
			      ;------------------------------------------
			      (setq newTransform
				    (if isOA
					(dbConcatTransform
					 (dbConcatTransform
					  (list xy "R0" 1)
					  mosaicTransform)
					 transform)
					(dbConcatTransform
					 (list xy orient 1)
					 transform)
					))
			      ;------------------------------------------
			      ; Call CCSflattenAndMerge recursively
			      ;------------------------------------------
			      (CCSflattenAndMerge master dstCv lpp
						 newTransform
						 nil)
			      ) ; for col
			 ) ; for row
		    ) ; let
	       (warn "Complex mosaic %s in %s/%s/%s ignored\n"
		     (dbGetq mosaic name)
		     (dbGetq srcCv libName)
		     (dbGetq srcCv cellName)
		     (dbGetq srcCv viewName)
		     )
	       )
	   )
  ;----------------------------------------------------------------------
  ; Using leMergeShapes is slow, so use dbLayerOr to do the merging,
  ; and then delete the original shapes
  ;----------------------------------------------------------------------
  (when top
    (let (origShapes)
      (setq origShapes
	    (dbGetq (car (exists LPP (dbGetq dstCv lpps)
				 (and
				   (equal (dbGetq LPP layerName) (car lpp))
				   (equal (dbGetq LPP purpose) (cadr lpp)))))
		    shapes))
      (dbLayerOr dstCv lpp origShapes)
      (foreach shape origShapes (dbDeleteObject shape))
      )
    t
    )
  )

/************************************************************************
*                                                                       *
*                   (CCSflattenedArea srcCv dstCv lpp)                   *
*                                                                       *
*   Given an empty destination (scratch) cellView, flatten and merge    *
* all shapes on the given layer purpose pair, and then return the area. *
*                                                                       *
************************************************************************/

(defun CCSflattenedArea (srcCv dstCv lpp)
  (let ((area 0.0))
    (CCSflattenAndMerge srcCv dstCv lpp)
    (foreach shape
	     (dbGetq (car (exists LPP (dbGetq dstCv lpps)
				  (and
				    (equal (dbGetq LPP layerName) (car lpp))
				    (equal (dbGetq LPP purpose) (cadr lpp)))))
		     shapes)
	     (setq area (plus area (or (ABarea shape) 0.0)))
	     )
    area
    )
  )
