Not signed in (Sign In)

Vanilla 1.1.4 is a product of Lussumo. More Information: Documentation, Community Support.

    • CommentAuthorDom
    • CommentTimeMar 31st 2017 edited
     

    Hi,

    i want to calculate the antenna effect for a few different layouts. Right now i calculate the gate first and then i iterate over ever poly gate to define the metal and via layers, code below. The tiling is to reduce the memory for further calculation, i only have a 32bit computer and without i run into a memory issue. My problem now is the time. When iterate over every polygon form region1 and check interacting parts with the metal region it's very slow. Is there a other and faster way to do something like this because right now i need a few hours for a small layout with around 10k gates.

    region1 = RBA::Region::new()       
    tp = RBA::TilingProcessor::new
    tp.threads = 4
    tp.input("a1",RBA::Region::new(topcell.begin_shapes_rec(active layer index))
    tp.input("a2",RBA::Region::new(topcell.begin_shapes_rec(poly layer index))
    tp.output("x1", region1)
    tp.tile_size(@topcell.bbox.width, @topcell.bbox.height)
    tp.queue("_output(x1, (a2.merge).select_interacting(a1))")
    tp.execute("1")
    
    region1.each do |polygon|
    ## get the gate area
    gate_area = 0
    gate_region = RBA::Region::new()
    tp = RBA::TilingProcessor::new
    tp.threads = 4
    tp.input("a1",RBA::Region::new(topcell.begin_shapes_rec(active layer index))
    tp.input("a2",RBA::Region::new(polygon))
    tp.output("x1", gate_region)
    tp.tile_size(@topcell.bbox.width, @topcell.bbox.height)
    tp.queue("_output(x1, a2.merge & a1)")
    tp.execute("1")
    
    gate_area = gate_region.area
    region_metal = RBA::Region::new() 
    region_via = RBA::Region::new()
    tp = RBA::TilingProcessor::new
    tp.threads = 4
    tp.input("ground",RBA::Region::new(polygon))                            
    tp.input("via",RBA::Region::new(topcell.begin_shapes_rec(via layer index))
    tp.input("top",RBA::Region::new(topcell.begin_shapes_rec(metal layer index))))
    tp.output("x1", region_metal)
    tp.output("x2", region_via)
    tp.tile_size(@topcell.bbox.width, @topcell.bbox.height)
    tp.queue(<<END)
    var bx =  ground & via;
    _output(x1,(top.merge).select_interacting(bx) );
    _output(x2, bx )
    END
    tp.execute("1")
    
    end 
    end
    

    Thanks for help Dominik

    • CommentAuthorMatthias
    • CommentTimeMar 31st 2017
     

    Hi Dominik,

    I have some doubts whether this code is correct. Where is the gate area used? Maybe I am missing something - if you use Markdown markup (four blanks in front of code lines), the code will be easier to read.

    Basically a specific rule like the antenna check is definitely something that needs to be coded in C++. Ruby will be much too slow for that purpose.

    I also think that tiling is not a valid approach, since it will cut polygons apart. That way the area is not computed correctly for polygons touch polygons from neighbour tiles.

    Matthias

    • CommentAuthorDom
    • CommentTimeApr 3rd 2017
     
    Hi Matthias,

    that's what i expected, but thank you for your help.

    I am aware of the problem with tiling that's why i use the whole chip as tile size. But this will clean the memory after i finished my calculation, without i will run into a memory issue.

    Regards
    Dominik
    • CommentAuthorMatthias
    • CommentTimeApr 4th 2017
     

    Hi Dominik,

    the reason why the tiling processor helps is that it will free memory immediately while in Ruby, the garbage collector will do this occasionally. You can however, enforce memory release with the "_destroy" method.

    Looking at your code reveals some optimization potential in Ruby too. Specifically the merge method is called many times on the whole layer. You should do this once outside the loop. You can also utilize region queries to confine the computations to the vicinity of the gate net.

    Here is some sketch for an optimized code:

    active = RBA::Region::new(topcell.begin_shapes_rec(active layer index))
    
    # Prepare a container with merged poly shapes which are having contact with 
    # active
    poly = RBA::Region::new(topcell.begin_shapes_rec(poly layer index))
    poly.merge
    poly_merged_over_active = poly.select_interacting(active)
    poly._destroy
    
    # prepare a Shapes container for region lookup containing the merged metal shapes
    # NOTE: instead of a region we use a ShapeProcessor. As soon as Shapes#insert(region)
    # is available, this will be the easier method
    sp = ShapeProcessor::new
    metal_merged = RBA::Shapes::new
    sp.merge(topcell.layout, topcell, metal layer index, metal_merged, true, 0, false, false)
    
    # Iterate over the poly chunks
    poly_merged_over_active.each do |polygon|
    
      # Select the active area in the area of the poly net
      active_over_polygon = RBA::Region::new(topcell.begin_shapes_rec_overlapping(active layer index, polygon.bbox))
    
      # Determine the total gate are on this net 
      gate_region = RBA::Region::new(polygon) & active_over_polygon
      gate_area = gate_region.area  # what will happen with that?
      gate_region._destroy
    
      # Select via inside the gate net by first selecting a subregion through
      # the gate net bounding box and then doing a boolean AND
      via_over_polygon = RBA::Region::new(topcell.begin_shapes_rec_overlapping(via layer index, polygon.bbox))
      via_region = RBA::Region::new(polygon) & via_over_polygon
    
      # Select the metal net interacting with the vias
      metal_over_polygon = RBA::Region::new 
      # NOTE: with a Region for metal_merged we can get rid of this loop:
      metal_merged.each_overlapping(polygon.bbox) { |p| region_metal.insert(p) }
      metal_region = metal_over_polygon.select_interacting(via_region)
      metal_over_polygon._destroy
    
      # now do what you need to do with gate_area, via_region and metal_region ...
    
    end 
    

    Matthias

    • CommentAuthorDom
    • CommentTimeApr 5th 2017
     

    Hi Matthias,

    i tried to use destroy before, but not _destroy that's why I used tiling. But anyway when i want to use your code with _destroy my application is crushing down, without i have no problem I use QT to create an Interface, is there some influence in the background?

    Thank you for your help Dominik

    • CommentAuthorMatthias
    • CommentTimeApr 7th 2017 edited
     

    Hi Dominik,

    I have not tested the code myself since your version wasn't complete. Maybe you can paste or publish your real version in some other way so I can try that.

    Anyhow, _destroy is not mandatory, so without it should do too. But in general, _destroy is doing the same thing that the garbage collector would do - but when you want it to happen, not when the garbage collector chooses to do that. That will render some more reproducibility.

    Without your full code I can't say whether there is some interference. And I can't debug anything. Please don't let me guess.

    Matthias