It looks like you're new here. If you want to get involved, click one of these buttons!

Hello,

Some EDA tool has chamfer function, which can add extra pattern to prevent

metal trace from transition with 90 degree angle or less ( Maybe not often to see in VLSI ?)

Someone told me, it can be done by " round corner " function, but I tried and failed, due to

triangle compensation is preferred.. Share below code for fun, any smart method or comment will be appreciated.

BTW, the initial length of chamfer ( tear_drop ) is 20 " um "

```
import pya
cellview = pya.CellView.active()
layout = cellview.layout()
top = cellview.cell
metal = layout.layer(9 , 0)
tear_drop = layout.layer(6 , 0)
pya.Application.instance().main_window().current_view().add_missing_layers()
target_90 = pya.Region( layout.top_cell().begin_shapes_rec(metal)).with_angle(270, 360 , False)
count_90 = target_90.size()
first_edge_iter_90 = target_90.first_edges().each()
second_edge_iter_90 = target_90.second_edges().each()
target_90_pairs_set = [ k for k in target_90.each() ]
center_90_set = []
start_point_set = []
end_point_set = []
def center_90():
for i in range(0, count_90):
center = target_90_pairs_set[i].first.crossing_point(target_90_pairs_set[i].second)
center_90_set.append(center)
def start_point():
for j in range(0, count_90):
P1 = target_90_pairs_set[j].first.d().x
P2 = target_90_pairs_set[j].first.d().y
P3 = target_90_pairs_set[j].first.length()
P4 = center_90_set[j].x
P5 = center_90_set[j].y
length = 20000
if P1 >= 0 and P2 == 0 and P3 >= length:
start_point_set.append(pya.Point(P4 - length, P5))
elif P1 >= 0 and P2 == 0 and P3 < length:
start_point_set.append(pya.Point(P4 - P3, P5))
elif P1 < 0 and P2 == 0 and P3 >= length:
start_point_set.append(pya.Point(P4 + length, P5))
elif P1 < 0 and P2 == 0 and P3 < length:
start_point_set.append(pya.Point(P4 + P3, P5))
elif P1 == 0 and P2 >= 0 and P3 >= length:
start_point_set.append(pya.Point(P4 , P5 -length))
elif P1 == 0 and P2 >= 0 and P3 < length:
start_point_set.append(pya.Point(P4 , P5 - P3))
elif P1 == 0 and P2 < 0 and P3 >= length:
start_point_set.append(pya.Point(P4 , P5 + length))
elif P1 == 0 and P2 < 0 and P3 < length:
start_point_set.append(pya.Point(P4 , P5 + P3))
else:
pass
def end_point():
for j in range(0, count_90):
P1 = target_90_pairs_set[j].second.d().x
P2 = target_90_pairs_set[j].second.d().y
P3 = target_90_pairs_set[j].second.length()
P4 = center_90_set[j].x
P5 = center_90_set[j].y
length = 20000
if P1 >= 0 and P2 == 0 and P3 >= length:
end_point_set.append(pya.Point(P4 + length, P5))
elif P1 >= 0 and P2 == 0 and P3 < length:
end_point_set.append(pya.Point(P4 + P3, P5))
elif P1 < 0 and P2 == 0 and P3 >= length:
end_point_set.append(pya.Point(P4 - length, P5))
elif P1 < 0 and P2 == 0 and P3 < length:
end_point_set.append(pya.Point(P4 - P3, P5))
elif P1 == 0 and P2 >= 0 and P3 >= length:
end_point_set.append(pya.Point(P4 , P5 + length))
elif P1 == 0 and P2 >= 0 and P3 < length:
end_point_set.append(pya.Point(P4 , P5 + P3))
elif P1 == 0 and P2 < 0 and P3 >= length:
end_point_set.append(pya.Point(P4 , P5 - length))
elif P1 == 0 and P2 < 0 and P3 < length:
end_point_set.append(pya.Point(P4 , P5 - P3))
else:
pass
def tear():
for x in range(0, count_90):
P1 = start_point_set[x]
P2 = center_90_set[x]
P3 = end_point_set[x]
poly = pya.Polygon( [ P1, P2, P3 ] )
top.shapes(tear_drop).insert(poly)
center_90()
start_point()
end_point()
tear()
```

## Comments

Now you are challenging me

Here is a simple solution that uses a DRC function with an intra-polygon space check with an above-90 angle limit to generate notch violation markers on inner 90 degree-corners. 1µm is the edge length of the marker:

Result:

This approach will not work properly on edges less than 1µm length because then the chamfering gets non-45 degree.

The rounded-corner approach works as well (DRC) when you set the outer corner radius to 0 and use the octagon approximation (n=8):

Caveat: the corner rounding does not apply full radius on edges shorter than f µm (f is 1.707...) but applies a smaller chamfering:

So both approaches have a slight disadvantage that you may be able to mitigate with specific design rules.

Matthias

hello Matthias,

You should be kidding me..

Method one already works perfectly to me, I have no ruby background, so I missed many great information in the manual, even can not understand properly.You solution always hit the problem in 3 rows, it is magic.

I am not sure why I can not upload a gds file on.. so please see below image:

the solution also can make the tear for a trace connect to circle, it's already good enough to tape out mask if merged polygons, even better than what Cadence did, but I will keep trying to make it as " triangle " shape to reduce file size if convert to MEBES. Maybe will share another long code again, when it's done

Very good, thanks for the feedback

You can upload GDS if you zip it. This forum does now know about our favourite file formats ...

Matthias

Hello Matthias,

It's my bad, I should notice that, updated test gds ok, and trying to solve it with math.(sin , cos, tan) friends..

Hello Matthias,

Try & error, come out below code, it seems work,

Thanks for your perfect reply and this creative tool

Vincent

Of course this solution is valid too and I really want encourage users to try their own ways. So please go ahead and thanks for sharing the code!

There are a few things you're probably aware of:

Kind regards,

Matthias