DRC with coincident edges

Hi, guys. I got two layers, layer A and layer B. I have a question about the way to do the following rule.
At least two edges of layer A must be coincident with layer B.

Thanks for your help.


  • Hi @JSS,

    The description is not quite specific. Can you show some example graphically?


  • Hi @Matthias,

    Thank you for your reply. Here are some examples of the description.
    Hope this helps.


  • Hi @JSS,

    thanks for the picture. This makes things easier to discuss.

    Here is my solution (needs version 0.29.0):

    report("Discussion 2500")
    l1 = input(1, 0)
    l2 = input(2, 0)
    coincident_edges = (l1.edges & l2.edges)
    # needs 0.29.0:
    error = l1.not_interacting(coincident_edges, 2)
    error.output("error", "less than 2 coincident edges")

    with the following results:


  • Hi @Matthias,

    Thank you very much for your reply. It really helps me to solve my problem.

    I have 2 more questions about the DRC script.

    Here is the description of the first one: minimum extended distance of layer A beyond Layer B when two layers interact.

    The illustration of this is shown below.

    I tried to script the rule:

    la = input(1, 1)
    lb = input(1, 2)
    mnDistance = 5.um
    error = ((la.and(lb).edges).and(lb.edges)).separation((((la.interacting(lb)).not(lb)).edges).not_interacting(lb.edges), mnDistance)
    error.output("minimum extended distance of layer A beyond Layer B when two layers interact: 5 um")

    But this code does not work. Always find no error.

    The other description of the second DRC: All sides of Layer C must be of the same length.

    The following is my script.

    lc = input(1, 4)
    error = lc.without_bbox_aspect_ratio(1)
    error.output("All sides of Layer C must be of the same length")

    But this script only works on squares and hexagons, not on triangles.

    Could you please have a look at why these codes are not working?


  • Hi @JSS,

    The first question is easy: that is the definition of "enclosing":

    l2.enclosing(l1, 0.5).output("l2 is enclosing l1 by at least 500nm")

    which gives:

    The second question is difficult. There is no function to check this. That is a quiet an exotic design rule. You can code this explicit:

    not_same_sides = polygons    # collects the errors here
    # scans layer l1 for polygons without equal edges and places them in "not_same_sides"
    l1.each do |poly|
      (min, max) = poly.each_edge.collect { |e| e.length }.minmax
      if (min - max).abs > 1e-6
    not_same_sides.output("Polygons which do not have identical sides")

    However, that function will create a flat error layer and can be slow on large designs.


  • Hi @Matthias,

    Thank you again for your answers. This really solves my questions.

    I have another question regarding a DRC. Here is the description: the minimum width of the layer 1 shape.

    Usually this can be easily solved by "width". But it does not seem to work for shapes like trapezoid.

    Is there a way to do this?

    Thanks for your helping.


  • edited May 2

    Hi @JSS,

    Of course, width also works on trapezoids. However, as there are corners with angle < 90 degree, and that formally qualifies as a width violation (the edges are facing each other):

    together with the intended violation:

    You can fix this by specifying an angle limit - for example 70 degree:

    width(1.0.um, angle_limit(70))

    which leaves only the intended violation.


    edited May 6

    Hi @Matthias

    Thank you so much for all your help lately, I've benefited so much!

    I have got a new question. I was wondering if you would mind helping me out.

    Here is the description: minimum Layer A spacing if either Layer A shape is larger than 5 um x 5 um: 1.0 um.

    I use "sized" to filter shape larger than 5um x 5um.

    I don't want the original polygon to be affected, so I create a new layer to insert layer A into.

    Then I use "sep" to find out the error. But this method seems useless for my DRC.

    The following is my script.

    l1_clone = l1
    error = (l1_clone.sized(-5.0.um, -5.0.um).sized(5.0.um, 5.0.um)).drc(0.0.um < sep(l1) < 1.0.um)

    Is there something wrong with my code or is there an effective way to do this?


    An additional question on May 6.

    Hi Matthias I'd like to ask you one more question.

    Is there a way to find out the angle of the touching corner?

    I want to highlight the angle that is not 120 degrees. Like the corners in the picture below.

    I tried "width" with a small value to find all the touching corners.

    But this method does not seem to find touching corner only, or some of them would be missed if the value is too small.

    Is there any way to solve this issue? Thanks a lot.


    edited May 7

    Hi guys, I find a way to solve my first question.

    l1_clone = l1.sized(-2.5.um, -2.5.um).sized(2.5.um, 2.5.um)
    error = l1_clone.drc(sep(l1 - l1_clone) < 1.0.um).polygons | l1_clone.drc(space < 1.0.um).polygons

    And the second one I try to solve with this script.

    error = l1.edges.interacting(l1.corners(90).sized(1) + l1.corners(90.1 .. 119.9).sized(1))

    The output is as shown in the figure.

    The method also highlights the overlapping polygons, I wonder if there is a way to not highlight them. Thanks.

    Best Regards,


  • Hi @JSS,

    for the second problem, I propose this solution (caution: needs 0.29.x version):

    # see below
    bad_corner_edge_pairs = l1.corners(0.0 .. 59.9, as_edge_pairs) + l1.corners(60.1 .. 180.0, as_edge_pairs)
    all_corners = l1.corners(as_dots)
    # needs klayout 0.29.x:
    kissing_corners = all_corners.interacting(all_corners)
    bad_corner_edges = bad_corner_edge_pairs.edges.interacting(kissing_corners)

    Note that the angle of a corner is defined by the "bending angle" or "turn angle", not the angle between the edges forming the corner. So a turn angle of 0 does not mean a reflection, but a straight continuation (no corner at all). In contrast, a turn angle of 180 degree means a reflection which corresponds to zero angle between the attached edges. Both of these cases are for illustration only, as in reality reflections or straight lines do not form corners.

    Specifically: as you ask for detecting inner corners with 120 degree between the edges, the corresponding "turn angle" is 60 degree. So we check for 0..59.9 and 60.1..180 for bad angles.

    The result is this:


  • Hi @Matthias,

    This code solved my question perfectly.
    Thank you for your kind help.


Sign In or Register to comment.