From 718dc2a9acb17cfeef72c54def9619f1f99fcd21 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Tue, 29 Mar 2022 21:23:27 -0700 Subject: [PATCH] improvement: track opens (ie, unconnected same-named nets) --- connectivity.oas | Bin 0 -> 1078 bytes example.py | 11 ++++++ snarl/interfaces/masque.py | 17 +++++++- snarl/main.py | 33 +++++----------- snarl/tracker.py | 79 +++++++++++++++++++++++++++++-------- snarl/types.py | 1 - 6 files changed, 99 insertions(+), 42 deletions(-) create mode 100644 connectivity.oas diff --git a/connectivity.oas b/connectivity.oas new file mode 100644 index 0000000000000000000000000000000000000000..865bf318727c6f1e0a01a036daac774cf85d9f93 GIT binary patch literal 1078 zcmd_m|4S2L9Ki8=p6BMd-R!h`M2JBn@mpRaCxt%+)1C8lp4n*$5kpEsurjcCOr=Q< zMr19Mp&??BphQtnFbl*Cbl@+iKP{LgQLy|WrUoYTLwB2J{?LEW^TYGJ?tKrRAD#k5 zte1{8xD-jrvH(=(I8G%PYX7q39#VYut`?snd1TS;ljJ7RBcAb{liW=;nY1m-mj2x= z|LcM+*P{5E8czGFM6cJ1x~_F1eKRpi`{k>x9d!m=2D}EU4Y&<>3{)DZF(4VJG9a2t zi(P`fvP7^KR|$5vV3%}?g1uTlJ%YVPKkM|(Tf$~sY3pk3C_?~I)_vaXP6YRQ%DcTB zp}n3mYr5IqTISToK$;T}MZ%*L@uUMLD5%D6WosodHmoc;hN3aQHUnxXd&kUDmjVFtB=hSk zm^s1|CN=`L3VD(d=K`fXF|8B*i}uffMVcolOdUwdDi@L`4)^!5RML@+I}^-L`ByWpNII6e_or|-inhgBmD_2?MCFF_L-I@> zCclpkTc)Z 1: # Found a short logger.warning(f'Nets {found_nets} are shorted on layer {layer} in poly:\n {pformat(poly)}') - merge_groups.append(found_nets) # type: ignore + merge_groups.append([name] + [NetName(nn) for nn in found_nets[1:]]) for group in merge_groups: first_net, *defunct_nets = group @@ -82,17 +82,6 @@ def check_connectivity( for net_a, net_b in merge_pairs: nets_info.merge(net_a, net_b) - - print('merged pairs') - print(pformat(merge_pairs)) - - print('\nFinal nets:') - print([kk for kk in nets_info.nets if isinstance(kk, str)]) - - print('\nNet sets:') - for short in nets_info.get_shorted_nets(): - print('(' + ','.join(sorted(list(short))) + ')') - return nets_info @@ -142,9 +131,9 @@ def label_poly( def find_merge_pairs( connectivity: connectivity_t, - nets: Mapping[net_name_t, Mapping[layer_t, Sequence[contour_t]]], + nets: Mapping[NetName, Mapping[layer_t, Sequence[contour_t]]], via_polys: Mapping[layer_t, Sequence[contour_t]], - ) -> Set[Tuple[net_name_t, net_name_t]]: + ) -> Set[Tuple[NetName, NetName]]: # # Merge nets based on via connectivity # @@ -155,8 +144,6 @@ def find_merge_pairs( if not vias: continue - #TODO deal with polygons that have holes (loops?) - for top_name in nets.keys(): top_polys = nets[top_name][top_layer] if not top_polys: @@ -165,7 +152,7 @@ def find_merge_pairs( for bot_name in nets.keys(): if bot_name == top_name: continue - name_pair = tuple(sorted((top_name, bot_name), key=lambda s: id(s))) + name_pair = tuple(sorted((top_name, bot_name))) if name_pair in merge_pairs: continue diff --git a/snarl/tracker.py b/snarl/tracker.py index 802d39f..ca4c27d 100644 --- a/snarl/tracker.py +++ b/snarl/tracker.py @@ -1,31 +1,61 @@ -from typing import List, Set +from typing import List, Set, ClassVar, Optional from collections import defaultdict +from dataclasses import dataclass -from .types import layer_t, net_name_t, contour_t +from .types import layer_t, contour_t + + +class NetName: + name: Optional[str] + subname: int + count: ClassVar[defaultdict[Optional[str], int]] = defaultdict(int) + + def __init__(self, name: Optional[str] = None) -> None: + self.name = name + self.subname = self.count[name] + NetName.count[name] += 1 + + def __lt__(self, other: 'NetName') -> bool: + if self.name == other.name: + return self.subname < other.subname + elif self.name is None: + return False + elif other.name is None: + return True + else: + return self.name < other.name + + def __repr__(self) -> str: + if self.name is not None: + name = self.name + else: + name = '(None)' + + if NetName.count[self.name] == 1: + return name + else: + return f'{name}__{self.subname}' class NetsInfo: - nets: defaultdict[net_name_t, defaultdict[layer_t, List]] - net_aliases: defaultdict[net_name_t, net_name_t] + nets: defaultdict[NetName, defaultdict[layer_t, List]] + net_aliases: defaultdict[NetName, NetName] def __init__(self) -> None: self.nets = defaultdict(lambda: defaultdict(list)) self.net_aliases = defaultdict(list) - def resolve_name(self, net_name: net_name_t) -> net_name_t: + def resolve_name(self, net_name: NetName) -> NetName: while net_name in self.net_aliases: net_name = self.net_aliases[net_name] return net_name - def merge(self, net_a: net_name_t, net_b: net_name_t) -> None: + def merge(self, net_a: NetName, net_b: NetName) -> None: net_a = self.resolve_name(net_a) net_b = self.resolve_name(net_b) # Always keep named nets if the other is anonymous - if not isinstance(net_a, str) and isinstance(net_b, str): - keep_net, old_net = net_b, net_a - else: - keep_net, old_net = net_a, net_b + keep_net, old_net = sorted((net_a, net_b)) #logger.info(f'merging {old_net} into {keep_net}') self.net_aliases[old_net] = keep_net @@ -34,17 +64,34 @@ class NetsInfo: self.nets[keep_net][layer] += self.nets[old_net][layer] del self.nets[old_net] - def get(self, net: net_name_t, layer: layer_t) -> List[contour_t]: + def get(self, net: NetName, layer: layer_t) -> List[contour_t]: return self.nets[self.resolve_name(net)][layer] - def get_shorted_nets(self) -> List[Set[str]]: + def get_shorted_nets(self) -> List[Set[NetName]]: shorts = defaultdict(list) for kk in self.net_aliases: - if isinstance(kk, str): - base_name = self.resolve_name(kk) - assert(isinstance(base_name, str)) - shorts[base_name].append(kk) + if kk.name is None: + continue + + base_name = self.resolve_name(kk) + assert(base_name.name is not None) + shorts[base_name].append(kk) shorted_sets = [set([kk] + others) for kk, others in shorts.items()] return shorted_sets + + def get_open_nets(self) -> defaultdict[str, List[NetName]]: + opens = defaultdict(list) + seen_names = {} + for kk in self.nets: + if kk.name is None: + continue + + if kk.name in seen_names: + if kk.name not in opens: + opens[kk.name].append(seen_names[kk.name]) + opens[kk.name].append(kk) + else: + seen_names[kk.name] = kk + return opens diff --git a/snarl/types.py b/snarl/types.py index 1acf31e..54482c4 100644 --- a/snarl/types.py +++ b/snarl/types.py @@ -2,5 +2,4 @@ from typing import Union, Tuple, List, Sequence, Optional layer_t = Tuple[int, int] contour_t = List[Tuple[int, int]] -net_name_t = Union[str, object] connectivity_t = Sequence[Tuple[layer_t, Optional[layer_t], layer_t]]