Need help with: RuntimeError: Heap lost: the DeepShapeStore container no longer exists in Region.-

Hello @Matthias, I hope you are doing well, thank you for your work on this great project.
I am trying to use the drc deep function(it seems it helps in reducing memory usage and time). I am not sure if this is good enough:
layer_top = pya.Region(layout_ut.top_cell().begin_shapes_rec(layout_ut.layer(atop.layer, atop.datatype)), pya.DeepShapeStore())
and using pya.DeepShapeStore()

I am getting this error on the not operation between layer_top and layer_bot
layer_top - layer_bot

RuntimeError: Heap lost: the DeepShapeStore container no longer exists in Region.-

#!/bin/python3.8
import klayout.db as pya
import klayout.rdb as rdb
import argparse
import time
import gc
from pprint import pprint
from pathlib import Path

class Material:
    def __init__(self, name, bottom, list_of_tops):
        self.name = name
        self.bottom = bottom
        self.list_of_tops = list_of_tops

def mark_purpose_not_overlapping_drawing(layout_path, markers_output_file):
    layout_ut = pya.Layout()
    layout_ut.read(str(layout_path))
    report = rdb.ReportDatabase(str(markers_output_file))
    rdb_top_cell = report.create_cell(layout_ut.top_cell().name)

    materials = [
                    Material("nwell",    bottom=pya.LayerInfo(64,20),  list_of_tops=[pya.LayerInfo(64,16),pya.LayerInfo(64,5)]),
                    Material("diff",     bottom=pya.LayerInfo(65,20),  list_of_tops=[pya.LayerInfo(65,16),pya.LayerInfo(65,6)]),
                    Material("tap",      bottom=pya.LayerInfo(65,44),  list_of_tops=[pya.LayerInfo(65,48),pya.LayerInfo(65,5)]),
                    Material("poly",     bottom=pya.LayerInfo(66,20),  list_of_tops=[pya.LayerInfo(66,16),pya.LayerInfo(66,5)]),
                    Material("licon1",   bottom=pya.LayerInfo(66,44),  list_of_tops=[pya.LayerInfo(66,58)]),
                    Material("li1",      bottom=pya.LayerInfo(67,20),  list_of_tops=[pya.LayerInfo(67,16),pya.LayerInfo(67,5)]),
                    Material("mcon",     bottom=pya.LayerInfo(67,44),  list_of_tops=[pya.LayerInfo(67,48)]),
                    Material("met1",     bottom=pya.LayerInfo(68,20),  list_of_tops=[pya.LayerInfo(68,16),pya.LayerInfo(68,5)]),
                    Material("via",      bottom=pya.LayerInfo(68,44),  list_of_tops=[pya.LayerInfo(68,58)]),
                    Material("met2",     bottom=pya.LayerInfo(69,20),  list_of_tops=[pya.LayerInfo(69,16),pya.LayerInfo(69,5)]),
                    Material("via2",     bottom=pya.LayerInfo(69,44),  list_of_tops=[pya.LayerInfo(69,58)]),
                    Material("met3",     bottom=pya.LayerInfo(70,20),  list_of_tops=[pya.LayerInfo(70,16),pya.LayerInfo(70,5)]),
                    Material("via3",     bottom=pya.LayerInfo(70,44),  list_of_tops=[pya.LayerInfo(70,48)]),
                    Material("met4",     bottom=pya.LayerInfo(71,20),  list_of_tops=[pya.LayerInfo(71,16),pya.LayerInfo(71,5)]),
                    Material("via4",     bottom=pya.LayerInfo(71,44),  list_of_tops=[pya.LayerInfo(71,48)]),
                    Material("met5",     bottom=pya.LayerInfo(72,20),  list_of_tops=[pya.LayerInfo(72,16),pya.LayerInfo(72,5)]),
                    Material("pad",      bottom=pya.LayerInfo(76,20),  list_of_tops=[pya.LayerInfo(76,5),pya.LayerInfo(76,16)]),
                    Material("pnp",      bottom=pya.LayerInfo(82,44),  list_of_tops=[pya.LayerInfo(82,59)]),
                    Material("npn",      bottom=pya.LayerInfo(82,20),  list_of_tops=[pya.LayerInfo(82,5)]),
                    Material("rdl",      bottom=pya.LayerInfo(74,20),  list_of_tops=[pya.LayerInfo(74,16),pya.LayerInfo(74,5)]),
                    Material("inductor", bottom=pya.LayerInfo(82,24),  list_of_tops=[pya.LayerInfo(82,25)])]

    for amaterial in materials:
        for atop in amaterial.list_of_tops:
            layer_top = pya.Region(layout_ut.top_cell().begin_shapes_rec(layout_ut.layer(atop.layer, atop.datatype)), pya.DeepShapeStore())
            layer_bot = pya.Region(layout_ut.top_cell().begin_shapes_rec(layout_ut.layer(amaterial.bottom.layer, amaterial.bottom.datatype)), pya.DeepShapeStore())
            print(f"Doing {amaterial.bottom.layer}/{amaterial.bottom.datatype} with {atop.layer}/{atop.datatype}")
            violating_region = layer_top - layer_bot
            category_inst = report.create_category(f"{atop.layer}/{atop.datatype}")
            report.create_items(rdb_top_cell.rdb_id(), category_inst.rdb_id(), pya.CplxTrans(layout_ut.dbu), violating_region)
            # del violating_region
            # del layer_top
            # gc.collect()
        # del layer_bot
        # gc.collect()
    report.save(str(markers_output_file))

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-l", "--layout_path", required=True, type=Path, help="Layout path")
    parser.add_argument("-m", "--markers_output_file", required=True, type=Path, help="violating shapes makeres file path")
    args = parser.parse_args()
    layout_path = Path(args.layout_path).absolute()
    markers_output_file = Path(args.markers_output_file).absolute()
    mark_purpose_not_overlapping_drawing(layout_path, markers_output_file)

Your help is greatly appreciated, hopefully I am not causing you too much trouble, thanks again for taking the time.

Comments

  • @nofal Thanks for your feedback.

    When you use DeepShapeStore, you need to create a single one and make sure the Regions share the same object. It's a container for the internal data that deep mode needs for it's computations. You also need to make sure Python does not free the object before the Regions. As the DeepShapeStore also acts as a cache it's efficient not the generate a new one, but to keep it somewhere you can reuse it.

    As a useful pattern, you can create a Processor class which provides the computations and holds the reference to the DeepShapeStore plus the results:

    class Processor:
      def __init__(self):
        self.dss = pya.DeepShapeStore()
        self.result = None
      def compute(self):
        self.result = pya.Region(..., self.dss)
        ...
      def get_result(self):
         return self.result
    

    Matthias

  • Thank you for the awesome response @Matthias it definitely showed great improvement in memory usage and execution time.

  • @nofal Good to hear :)

    My own experiences are somewhat indifferent - sometimes deep mode is very fast and lean, sometimes very slow. For being of good use in general, deep mode definitely needs some polishing.

Sign In or Register to comment.