It looks like you're new here. If you want to get involved, click one of these buttons!
Hello,
I'm attempting to implement a PCell library which references itself to construct more complex PCells. In order to do that I need to populate the library without destroying it and rebuilding it since it would cause to unlink all existing PCells.
I achieved to do that by creating the library and using the Library reference instead of using the "self", but the library entries don't automatically refresh like it does when executing the regular self.register(xx).
I tried using self.refresh(), lib.register(xx) again, lib.refresh(), updating the QWidget associated with the libraries, and there's no "library.unregister()" function to try (actually nor "layout.unregister_pcell()" but there is "remove_technology". I guess library.delete() would be the equivalent).
The only solution I found was to switch the selected library view to the "Basic" one and then back.
Here's a sample:
import pya, os
import importlib.util as ilib
lv = pya.Application.instance().main_window().current_view()
wid = lv.widget()
widLib = lv.widget().libraries_frame()
def ezimport(filePath):
  # Makes it less verbose to import modules found from the executing fileName
  # → Script executed from a technology
  extFilePath = filePath.split("/")
  selfPath = os.path.join(os.path.dirname(__file__),*extFilePath)
  spec = ilib.spec_from_file_location(extFilePath[-1], selfPath)
  md = ilib.module_from_spec(spec)
  spec.loader.exec_module(md)
  return md
ent1 = ezimport("ent1_PCell.py")
ent2 = ezimport("ent2_PCell.py")
class NEW_LIB(pya.Library):
  def __init__(self):
    lib = pya.Library.library_by_name("NEW_LIB")
    if not(lib):
      # Set the description
      self.description = "New Library"
      self.register("NEW_LIB")
    self.lib = pya.Library.library_by_name("NEW_LIB")
    # Create the PCell declarations
    # Register PCells to the already existing NEW_LIB already exists
    self.lib.layout().register_pcell("ENTRY1", ent1.PCell1())
    self.lib.layout().register_pcell("ENTRY2", ent2.PCell2())
    self.lib.register("NEW_LIB") # Only registers internally, won't update the library view
    self.refresh() # Won't do a thing
    lib.refresh() # Won't do a thing
    wid.update() # Won't do a thing
    wid.repaint() # Won't do a thing
    widLib.update() # Won't do a thing
    widLib.repaint() # Won't do a thing
# Instantiate and register the library
NEW_LIB()
Thank you,
Gerard
Comments
I found another way to solve it (through the intended way).
Using
self.register()by the end of the library class, and sendselfas a parameter for thePCell1class (be it PCell2 is to be a child of PCell1). The child PCells would be registered inside the definition of the parent PCell class, so only the parent PCells are required to be registered explicitly in the library class.One thing I notice however is that the sub-cell name has the library repeated, and hiding the instanced PCell won't hide a standalone one.
Here's a simplified full code:
Hi @Tabra,
You can register multiple PCells per library.
Why not just doing:
So you just need to register in the proper order. If you delay the "pcell_id" calls to the point when you really need it (in produce_impl), you could even realize recursive dependencies. But I'd say that is bad style.
Matthias
Hi Matthias,
Right, this is the best approach. But an underlying issue remains: When converting the PCells to Static (or saving them in GDS to transfer to another software), the PCells inside another PCell and the same PCells outside the parent PCell are differentiated when they shouldn't.
An example:
In this example, "Spring" calls 2 PCells to build a custom shape by using them as puzzle pieces. You can see that the same PCell corner is being used but one outside the Spring PCell and the rest inside.
Hiding the PCells inside the Spring will hide all instances of the PCell, but not outside the Spring, and viceversa.
Converting the layout to static also reflects the fact that these 2 are fundamentally disconnected, when they shouldn't as the exact same reference is used.
If I may add something, I would like to know if there's an easy way to name the PCells so when converting them to static they have a meaningful name.
Thank you,
Gerard
I don't know how the
NNS_LIB.SpringPCell is made, but the references inside that PCell are different from the outside cell. You can tell from the name: the one is calledNNS_LIB.SpringCornerthe other oneNNS_LIB.NNS_LIB.SpringCorner. That indicates that you created the SpringCorner inside the PCell with a library reference. That is not needed as theSpringPCell is already inside the library.I assume you did something like
This will create a library reference inside a cell that is already inside a library. KLayout's differentiates between local ("static") cells are library references ("proxies"). So when you instantiate a "Spring" PCell the corner effectively becomes a double proxy while outside the "SpringCorner" cell is a single proxy. That means these cells are different.
I think in your code it's sufficient to write:
as you are already local to "NNS_LIB".
Rule of thumb: KLayout is not Virtuoso!
Matthias
Wow, this is exactly what I wanted from the start.
Thank you very much!!
Gerard