Accessing the "absolute" position of a shape

Hi,

I'm wondering if there is any helper function/method that allows me to retrieve the absolute position of a shape (relative to the top level cell) in a hierarchical GDS - or do I need to walk my way back to the top cell through the instance tree ?
The use case is to retrieve the position of shapes on a particular layer that defines the bonding pad openings in a ASIC.

I'm using a code similar to this:

def get_bbox_for_cells_containing_cb_layer(
    layout: kdb.Layout, layer: int, datatype: int
):

    layer1 = layout.layer(layer, datatype)
    top_cell = layout.top_cell()

    iter = top_cell.begin_shapes_rec(layer1)
    while not (iter.at_end()):
        if iter.shape().is_polygon():
            logging.debug("Polygon: " + str(iter.shape().dpolygon))
            logging.debug("  From shape " + str(iter.shape()))
            logging.debug("  Property   " + str(iter.shape().properties()))
            logging.debug("    BBOX " + str(iter.shape().dbbox()))
        elif iter.shape().is_path():

The shapes I'm collecting are "deep" into the hierarchy of the GDS (they don't belong to the top level).

Thank you

Comments

  • Hi,

    About this?

    Test Data



    Code and Results

    import klayout.db as kdb
    
    def Find_BondingPad_Positions( indesign: str, layer: int, datatype: int ):
      #-----------------------------------------------------------
      # [1] Open the input design
      #-----------------------------------------------------------
      layout  = kdb.Layout()
      layout.read(indesign)
      topcell = layout.top_cell()
      layIdx  = layout.layer(layer, datatype)
    
      pads_relative = list()  # container for the relative coordinates
      pads_absolute = list()  # container for the absolute coordinates
    
      #-----------------------------------------------------------
      # [2] Iterate over the cell instances
      #-----------------------------------------------------------
      iterI = topcell.begin_instances_rec()
      while not (iterI.at_end()):
        # (A) Gets the accumulated transformation of the current instance parent cell to the top cell.
        #     This transformation represents how the current instance is seen in the top cell.
        #     This version returns the micron-unit transformation.
        dtrans = iterI.dtrans()
        cell   = iterI.inst_cell()
    
        # (B) Skip the current child cell if it does not contain target shapes
        target_shapes = [ shape for shape in cell.each_shape(layIdx, kdb.Shapes.SBoxes) ]
        if len(target_shapes) == 0:
          iterI.next()
        # (C) Otherwise...
        else:
          # (1) Gets the micron-unit transformation of the current instance.
          #     This is the transformation of the current instance inside its parent.
          #     'dtrans * inst_dtrans' gives the full micron-unit transformation how
          #     the current cell is seen in the top cell.
          #     See also inst_trans and inst_cell.
          inst_dtrans = iterI.inst_dtrans()
    
          # (2) Iterate over the shapes
          for shape in target_shapes:
            current_dbox = shape.dbox
            pads_relative.append(current_dbox)
            pads_absolute.append(current_dbox.transformed(dtrans * inst_dtrans))
    
          print( f"### Cell <{cell.name}> in <{indesign}> contains <{len(target_shapes)}> rectangles with L/D={layer}/{datatype} ###" )
          print("")
          iterI.next()
    
      #---------------------------------------------------
      # [3] Print the results
      #---------------------------------------------------
      print( f"### In Relative Coordinates ###" )
      for item in sorted(pads_relative):
        print( f"  {item}" )
      print("")
    
      print( f"### In Absolute Coordinates ###" )
      for item in sorted(pads_absolute):
        print( f"  {item}" )
      print("")
    
    def Main():
      indesign = "F2592.gds"
      Find_BondingPad_Positions( indesign, 5, 0 )
    
    #===================================================================================
    if __name__ == "__main__":
      Main()
    
    ### Cell <A> in <F2592.gds> contains <16> rectangles with L/D=5/0 ###
    
    ### In Relative Coordinates ###
      (0,0;108,108)
      (200,0;308,108)
      (400,0;508,108)
      (600,0;708,108)
      (800,0;908,108)
      (1000,0;1108,108)
      (1200,0;1308,108)
      (1400,0;1508,108)
      (0,512;108,620)
      (200,512;308,620)
      (400,512;508,620)
      (600,512;708,620)
      (800,512;908,620)
      (1000,512;1108,620)
      (1200,512;1308,620)
      (1400,512;1508,620)
    
    ### In Absolute Coordinates ###
      (1448.7,347;1556.7,455)
      (1648.7,347;1756.7,455)
      (1848.7,347;1956.7,455)
      (2048.7,347;2156.7,455)
      (2248.7,347;2356.7,455)
      (2448.7,347;2556.7,455)
      (2648.7,347;2756.7,455)
      (2848.7,347;2956.7,455)
      (1448.7,859;1556.7,967)
      (1648.7,859;1756.7,967)
      (1848.7,859;1956.7,967)
      (2048.7,859;2156.7,967)
      (2248.7,859;2356.7,967)
      (2448.7,859;2556.7,967)
      (2648.7,859;2756.7,967)
      (2848.7,859;2956.7,967)
    
  • edited September 17

    With two instances of cell A

    ### Cell <A> in <F2592-2A.gds> contains <16> rectangles with L/D=5/0 ###
    
    ### In Relative Coordinates ###
      (0,0;108,108)
      (200,0;308,108)
      (400,0;508,108)
      (600,0;708,108)
      (800,0;908,108)
      (1000,0;1108,108)
      (1200,0;1308,108)
      (1400,0;1508,108)
      (0,512;108,620)
      (200,512;308,620)
      (400,512;508,620)
      (600,512;708,620)
      (800,512;908,620)
      (1000,512;1108,620)
      (1200,512;1308,620)
      (1400,512;1508,620)
    
    ### In Absolute Coordinates ###
      (1448.7,347;1556.7,455)
      (1648.7,347;1756.7,455)
      (1848.7,347;1956.7,455)
      (2048.7,347;2156.7,455)
      (2248.7,347;2356.7,455)
      (2448.7,347;2556.7,455)
      (2648.7,347;2756.7,455)
      (2848.7,347;2956.7,455)
      (1448.7,859;1556.7,967)
      (1648.7,859;1756.7,967)
      (1848.7,859;1956.7,967)
      (2048.7,859;2156.7,967)
      (2248.7,859;2356.7,967)
      (2448.7,859;2556.7,967)
      (2648.7,859;2756.7,967)
      (2848.7,859;2956.7,967)
      (1829.9,1033.4;1937.9,1141.4)
      (2341.9,1033.4;2449.9,1141.4)
      (1829.9,1233.4;1937.9,1341.4)
      (2341.9,1233.4;2449.9,1341.4)
      (1829.9,1433.4;1937.9,1541.4)
      (2341.9,1433.4;2449.9,1541.4)
      (1829.9,1633.4;1937.9,1741.4)
      (2341.9,1633.4;2449.9,1741.4)
      (1829.9,1833.4;1937.9,1941.4)
      (2341.9,1833.4;2449.9,1941.4)
      (1829.9,2033.4;1937.9,2141.4)
      (2341.9,2033.4;2449.9,2141.4)
      (1829.9,2233.4;1937.9,2341.4)
      (2341.9,2233.4;2449.9,2341.4)
      (1829.9,2433.4;1937.9,2541.4)
      (2341.9,2433.4;2449.9,2541.4)
    

    Updated: 2024-09-17

Sign In or Register to comment.