Creating multiple array instances of a PCell (using Python)

edited November 2014 in Ruby Scripting
Hi,

I'm currently using the Python-preview (KLayout 0.24) and I'd like to create multiple array instances of a PCell with different parameters each time for both the array and the PCell itself using a Python script. I figured the CellInstArray-class would be a good starting point, but I have no idea where to specify the arguments for the PCell.

I also searched the documentation without results for:
- creating a new layout (Python script)
- working with cell hierarchy (Python script)
- working with layers (Python script)

Can someone enlighten me as to how I should approach this?
Thanks!

Comments

  • edited November 2014

    Hi,

    There is some basic documentation in the "Resources" part of this site referring to the evaluation version: http://www.klayout.de/python_preview.html.

    This gives some sample already for creating a layout.

    Regarding the PCell instantation I think you refer to the other thread - I guess there is a general problem with a huge amount of cells.

    I'll try to provide a Python version of that code, but I don't think it will be faster or take less memory. It's a good benchmark however.

    Matthias

  • edited November 2014

    Hello,

    Here is the Python code for the script in the other thread:

    DISCLAIMER: I have not tested with the released eval version yet, but with a development snapshot of mine.

    EDIT: I noticed that I messed up the threads - the other one is called "Creating letters" (http://klayout.de/forum/comments.php?DiscussionID=439&page=1#Item_12) and the basic problem there is the instantiation of many PCell variants. The code below is creating "fake" PCell instances to work around a performance issue with the PCell cache. This is not a recommendation for PCell instantiation code in general, since the sample below will only work for the TEXT PCell. But this code may serve as a sample of how to translate Ruby to Python (it's pretty mechanical in fact).

    Matthias

    import pya
    
    
    class Generator:
    
      def __init__(self):
    
        self.layout = pya.Layout()
        self.layout.dbu = 0.001
    
        self.top = self.layout.create_cell("TOP")
        self.layer_index = self.layout.insert_layer(pya.LayerInfo(15,99))
    
        self.lib = pya.Library.library_by_name("Basic")
        if self.lib == None:
          raise Exception("Unknown lib 'Basic'")
    
        self.pcell_decl = self.lib.layout().pcell_declaration("TEXT");
        if self.pcell_decl == None:
          raise Exception("Unknown PCell 'TEXT'")
    
      def make_pattern(self, l, w, xpos, ypos, num):
    
        a1 = [ 
          pya.Point(0, 0), 
          pya.Point(100, 0), 
          pya.Point(100, l + w), 
          pya.Point(200, l + w), 
          pya.Point(200, 0), 
          pya.Point(300, 0) 
        ]
    
        y1 = l + w / 2 - 20
        x1 = 150
        d1 = [ pya.Point(x1, y1), pya.Point(x1, -w / 2) ]
    
        y2 = w / 2 + 20
        x2 = 50
        e1 = [ pya.Point(x2, y2), pya.Point(x2, l + w + w / 2) ]
    
    
        unit_cell = self.layout.create_cell("1")
        unit_cell.shapes(self.layer_index).insert(pya.Path(a1, w))
        unit_cell.shapes(self.layer_index).insert(pya.Path(d1, w))
        unit_cell.shapes(self.layer_index).insert(pya.Path(e1, w))
        unit_cell.shapes(self.layer_index).insert(pya.Box(x1 - w / 2 - 2, y1 - 2, x1 - w / 2 + 2, y1 + 2))
        unit_cell.shapes(self.layer_index).insert(pya.Box(x1 + w / 2 + 2, y1 - 2, x1 + w / 2 + 2, y1 + 2))
        unit_cell.shapes(self.layer_index).insert(pya.Box(x2 - w / 2 - 2, y2 - 2, x2 - w / 2 + 2, y2 + 2))
        unit_cell.shapes(self.layer_index).insert(pya.Box(x2 + w / 2 + 2, y2 - 2, x2 + w / 2 + 2, y2 + 2))
    
        nx = 45
        dx = 200
        ny = 28
        dy = 320
        ox = xpos
        oy = ypos
    
        trans = pya.Trans(pya.Point(ox, oy))
        ax = pya.Point(dx, 0)
        ay = pya.Point(0, dy)
        self.top.insert(pya.CellInstArray(unit_cell.cell_index(), trans, ax, ay, nx, ny))
    
        # Note: this is the translation of named parameters to the PCell specific parameter vector
        # pv. Since the parameter vector is built the same way always, we could simply exchange the 
        # text parameter, given we have the index.
    
        param = { 
          "text": "%02d-%06d" % ( l, num ), 
          "layer": pya.LayerInfo(15,99), 
          "mag": 1 
        }
    
        pv = []
        for p in self.pcell_decl.get_parameters():
          if p.name in param:
            pv.append(param[p.name])
          else:
            pv.append(p.default)
    
        # "fake PCell code" - see other thread ("Creating letters")
        text_cell = self.layout.create_cell("1T")
        self.pcell_decl.produce(self.layout, [ self.layer_index ], pv, text_cell)
    
        t = pya.Trans(pya.Trans.R0, -1000 + xpos, -1000 + ypos)
        self.top.insert(pya.CellInstArray(text_cell.cell_index(), t))
    
      def done(self, filename):
        self.layout.write(filename)
        print("Output file written: " + filename)
    
    # =================================================================
    
    g = Generator()
    
    ncolumns = 1000
    nrows = 500
    num = 1
    
    for i in range(0, ncolumns):
      print("Column " + str(i+1) + "/" + str(ncolumns) + " ..")
      for j in range(0, nrows):
        g.make_pattern(50 + (i + j) % 73, 30, 15000 * i, 15000 * j, num)
        num = num + 1
    
    g.done("test.oas")
    
Sign In or Register to comment.