Best Practice for Organizing PCell Library

Hi,

I'm working on a Python library with some PCells in it and want to organize my code in a modular way.
Right now, each PCell is defined in its own Python file – pcell1.py, pcell2.py – like this:

# $autorun
import pya

class PCell1(pya.PCellDeclarationHelper):
    # …

Then, in the main lib.lym file, I do something like:

import os, sys
script_dir = os.path.dirname(__file__)
if script_dir not in sys.path:
    sys.path.insert(0, script_dir)

import pcell1
import pcell2

class Lib(pya.Library):
    def __init__(self):
        self.description = "A Library"
        self.layout().register_pcell("PCell1", PCell1())
        self.layout().register_pcell("PCell2", PCell2())
        self.register("Lib")

Lib()

This works, but I'd like to ask, is there a better way to structure a Python library for Klayout?

Thanks in advance!

Comments

  • This is a good question, before I did this part as

    import sys
    
    sys.path.append(r"xxxx")
    

    By doing so, you can simplify the path part, but for register part. I use same structure as you.

  • Yes, actually that is a good question.

    I think, organizing PCells that way is already very clear. Usually you would base your PCell code on other utility modules which then sit in further modules.

    If you make your PCells thin wrappers around some utility modules which do the core work - while the PCell just adds the parameter declarations, you can also place the actual PCell implementations in a single file, import by "*" and use introspection to register the PCells. This way the registration part becomes generic.

    I think however, the actual art is how to organize the utilities and what generation mechanisms or paradigms you follow. I have once tried a dynamic model of layout generation that works with derivations rather the computations here: https://github.com/klayoutmatthias/sky130A_el/tree/master/python/sky130_primlib. I am not saying that is state of the art or specifically elegant, but it was an interesting experience and in the future I would like to further explore that approach.

    Matthias

  • Thank you for your answers.

    For my small libraries I'll keep my lym-file pretty much like this, but put the py-files into a package. This way I also no longer need the # $autorun, which wasn't always working for some reason.

    If I ever write a larger library or publish one, I'll structure it better — but for now, this will do.

  • Hi @p00276,

    very good.

    $autorun isn't an option to organize packages as the order of execution may not be the one you expect. It is meant to execute some top level scripts which are independent from others, such as scripts registering menu items or libraries. Not terraforming.

    Python modules or Ruby import/load are much better options.

    Please be aware that the system has a single module space only and this remains. So once you have imported a module and change the source code of it, you need to force a reload or restart the application.

    In Python the reload technique is importlib.reload(module) (see for example here: https://stackoverflow.com/questions/437589/how-do-i-unload-reload-a-python-module).

    Matthias

Sign In or Register to comment.