Finding all instances of a particular cell in a gds using the Python API

Hello,

I can list all cells from a GDS but can't find a way to access all cell instances in a layout. All examples I've seen are about creating a new instance of a cell and insert it but I can't find how to access all the instances using the Python API... I understood this should be related to CellInstArray and Instance objects but can't find the missing link

Thank you for your help

Ronan

Comments

  • Hi,

    Maybe this method is the one you are searching for.

    I recently used it in fishfinder.py at this link.

  • Hi,

    Thank you. I was able to get further by using the each_parent_inst method. But I'm still struggling to extract the information I'm looking for (for each instance, I would like to get its position and rotation).
    If I print the object, I can see the data I'm after but can't find which field contains the actual information. The vars() / dict does not seem to be implemented as for standard Python objects.

    This is the code I'm using (using the gds from the fishfinder example)

    #!/usr/bin/env python3
    import klayout.db as kdb
    
    
    def list_all_cell_instances(layout, cell_name):
    
        target_cell = layout.cell(cell_name)
        if target_cell is None:
            print(f"Cell '{cell_name}' not found in the layout.")
            return
    
        parentInsts = [item for item in target_cell.each_parent_inst()]
        print(f"Number of parent instances referring to <{cell_name}>: {len(parentInsts)}")
        for inst in parentInsts:
            print(f"-D- inst = {inst}")
            child_inst = inst.child_inst()
    
            dcell_inst = child_inst.dcell_inst
            print(f"\t inst.child_inst() = {child_inst} ({type(child_inst)})")
            print(
                f"\t  vars(child_inst) : {vars(child_inst)} type(child_inst : ({type(child_inst)}) "
            )
            print(
                f"\t  {dcell_inst}  type : {type(dcell_inst)} vars : {vars(dcell_inst)}  "
            )
            print(f"\t  {dcell_inst.na}  {dcell_inst.nb} {dcell_inst.a}  {dcell_inst.b}")
            print()
    
    
    layout = kdb.Layout()
    layout.read("./leaf_chip.gds.gz")
    list_all_cell_instances(layout, "sky130_fd_sc_hd__dfrtp_1")
    
    

    I get output like this

    -D- inst = <klayout.dbcore.ParentInstArray object at 0x7eb5711bb640>
         inst.child_inst() = cell_index=202 m90 1006940,1338240 prop_id=237815 (<class 'klayout.dbcore.Instance'>)
          vars(child_inst) : {} type(child_inst : (<class 'klayout.dbcore.Instance'>) 
          #202 m90 1006.94,1338.24  type : <class 'klayout.dbcore.DCellInstArray'> vars : {}  
          0  0 0,0  0,0
    
    -D- inst = <klayout.dbcore.ParentInstArray object at 0x7eb5711bb6d0>
         inst.child_inst() = cell_index=202 m90 830760,1224000 prop_id=219901 (<class 'klayout.dbcore.Instance'>)
          vars(child_inst) : {} type(child_inst : (<class 'klayout.dbcore.Instance'>) 
          #202 m90 830.76,1224  type : <class 'klayout.dbcore.DCellInstArray'> vars : {}  
          0  0 0,0  0,0
    

    so I see the coordinates and rotation when printing the object . I guess this is because of a proper implementation of str or repr for the object. But vars() return an empty dict... which puzzles me...

  • edited September 11

    Hi,

    I think you have almost done it. :smile:
    I have modified your code, as shown below.

    import klayout.db as kdb
    
    
    def list_all_cell_instances(layout, cell_name):
        # [1] Confirm the presence of "cell_name"
        target_cell = layout.cell(cell_name)
        if target_cell is None:
            print(f"Cell '{cell_name}' not found in the layout.")
            return
    
        # [2] Get all parent instances that refer to "cell_name"
        parentInsts = [item for item in target_cell.each_parent_inst()]
        print(f"Number of parent instances referring to <{cell_name}>: {len(parentInsts)}")
    
        # [3] Iterate over all parent instances
        for idx, inst in enumerate(parentInsts):
            # (A) print the header
            print(f"-D- inst = {inst}")
    
            # (B) get the child instance associated with this parent instance
            child_inst = inst.child_inst()
    
            # (C) get the micrometer unit version of the basic cell instance array object
            dcell_inst = child_inst.dcell_inst
    
            # (D) get and print the level-1 properties
            cplx_trans = dcell_inst.cplx_trans
            is_complex = cplx_trans.is_complex()
            print( f"    idx={idx}, cplx_trans=[{cplx_trans}], is_complex={is_complex}" )
    
            # (E) get and print the level-2 properties
            angle     = cplx_trans.angle
            is_mirror = cplx_trans.is_mirror()
            mag       = cplx_trans.mag
            # angle/mirror code is one of the constants R0, R90, R180, R270, M0, M45, M90 and M135.
            #                                     rot = 0   1    2     3     4   5    6       7
            # rx is the rotation by an angle of x counter clockwise.
            # mx is the mirroring at the axis given by the angle x (to the x-axis).
            rot  = cplx_trans.rot()
            disp = cplx_trans.disp
            print( f"        angle={angle}, is_mirror={is_mirror}, mag={mag}, rot={rot}, disp={disp}" )
            print()
    
    
    layout = kdb.Layout()
    layout.read("./leaf_chip.gds.gz")
    list_all_cell_instances(layout, "sky130_fd_sc_hd__dfrtp_1")
    

    Then, I got the outputs:

    Number of parent instances referring to <sky130_fd_sc_hd__dfrtp_1>: 139
    -D- inst = <klayout.dbcore.ParentInstArray object at 0x14d7a51c54f0>
        idx=0, cplx_trans=[r0 *1 1023.5,1196.8], is_complex=False
            angle=0.0, is_mirror=False, mag=1.0, rot=0, disp=1023.5,1196.8
    :
    :
    :
    -D- inst = <klayout.dbcore.ParentInstArray object at 0x14d7a51cab70>
        idx=138, cplx_trans=[m90 *1 830.76,1224], is_complex=False
            angle=180.0, is_mirror=True, mag=1.0, rot=6, disp=830.76,1224
    

    The child cell

    Show only the top cell and the child cell.

    Go to the reference point of idx=0.

    Go to the reference point of idx=138.

  • Thank you very much. That was all I needed to continue my script. Do you have an explanation why vars() is not working ?

  • @nanor000,

    These are Python-wrapped C++ objects. They do not feature a dict slot. Hence no "vars".

    Matthias

Sign In or Register to comment.