blob: 060f38fa503e63dd72399194339f69a5cbdecbe0 [file] [log] [blame]
Philipp Gühring87f57522021-06-09 01:25:19 +02001print STDERR "DRC Expander - expands the DRC rules in MAGIC tech files and annotates the layers that might cause the DRC issues\n";
2
3# Original tech file:
4my $tech=$ARGV[0] || "/usr/local/lib/magic/sys/sky130A.tech";
5my $expand=0;
6my $debug=0;
7my $createrules=0; # Create code for rules instead of expanding the tech file
8
9print STDERR "Processing the original tech file: $tech\n";
10
11#our %contacts=();
12our %alias=();
13
14# Required DRC rules for SKY130: area,cifmaxwidth,edge4way,exact_overlap,extend,overhang,rect_only,spacing,surround,width
15my $rules=<<EOF
16surround types1 types2 distance presence error
17widespacing types1 wwidth types2 distance flavor error
18spacing types1 types2 distance adjacency error
19width type-list width error
20overhang types1 types2 distance error
21extend types1 types2 distance error
22rect_only types error
23angles types allowed why
24edge types1 types2 d OKTypes cornerTypes cornerDist error [plane]
25edge4way types1 types2 d OKTypes cornerTypes cornerDist error [plane]
26exact_overlap type-list
27no_overlap type-list1 type-list2
28off_grid types pitch why
29area types minarea minedge why
30maxwidth layers mwidth [bends] why
31cifwidth layer width why
32cifspacing layer1 layer2 separation adjacency why
33cifarea layer minarea minedge why
34cifmaxwidth layer mwidth [bends] why
35EOF
36;
37
38print STDERR "Extracting optional arguments:\n";
39my @erules=();
40foreach my $line(split "\n",$rules)
41{
42 if($line=~m/\[/)
43 {
44 my $a=$line; $a=~s/\[\w+\]//;
45 my $b=$line; $b=~s/\[//; $b=~s/\]//;
46 #print "A: $a\nB: $b\n";
47 push @erules,$a;
48 push @erules,$b;
49 }
50 else
51 {
52 #print "R: $line\n";
53 push @erules,$line;
54 }
55}
56
57print STDERR "Handling rules:\n";
58foreach my $rule (@erules)
59{
60 print STDERR " # Rule: $rule\n";
61 my @a=split " ",$rule;
62 my $kind=shift @a;
63 #print "Kind:$kind\n";
64 my $regexp="^\\s*($kind)";
65 my @types=("zero","other");
66 my @typelists=();
67 foreach(@a)
68 {
69 $regexp.="\\s+";
70 if($_=~m/^(types|type-list|layer|OKTypes)/)
71 {
72 $regexp.="(\\S+)";
73 push @types,"type-list";
74 }
75 elsif($_=~m/^(why|error)/)
76 {
77 $regexp.="\"([^\"]*)\"";
78 push @types,"why";
79 }
80 else
81 {
82 $regexp.="(\\S+)";
83 push @types,"other";
84 }
85 }
86
87 next unless($createrules);
88
89 $regexp.="\\s*\$";
90 print " if(m/$regexp/)\n {\n";
91 print ' print " # ORIGINAL RULE:$oneline\n";'."\n";
92 foreach(2 .. scalar(@types)-1)
93 {
94 print " my \$vl$_=\$$_;\n" if($types[$_] eq "type-list");
95 print " my \$l$_=join \" \",allLayers(\$vl$_);\n" if($types[$_] eq "type-list");
96 # print " print STDERR \"L$_: \$vl$_ -> \$l$_\n\" if(\$debug);\n" if($types[$_] eq "type-list");
97 print " my \$text=\$$_;\n" if($types[$_] eq "why");
98 push @typelists,$_ if($types[$_] eq "type-list");
99 }
100 print " print \" ";
101 foreach(1 .. scalar(@types)-1)
102 {
103 print "\$$_ " if($types[$_] eq "other");
104 print "\$vl$_ " if($types[$_] eq "type-list");
105 if($types[$_] eq "why")
106 {
107 print "\\\"\$$_ ";
108 #print "[erase ".join(",",@typelists)."]";
109 foreach my $tl (@typelists)
110 {
111 print "[erase \$l$tl]";
112 }
113 print "\\\"";
114 }
115 }
116 print "\\n\";\n";
117 print " }\n";
118 print "\n";
119 # $1 $vl1 $vl2 $4 $5 \"$6 [erase $l1]".(($vl1 eq $vl2)?"":"[erase $l2]")."\"\n";
120
121
122}
123
124exit if($createrules);
125
126#magic: tech layers allli
127# At first we are reading through the original tech file to search for all the virtual layers that need to be expanded
128open IN,"<$tech";
129while(<IN>)
130{
131 s/\\//g;
132 if(m/^\s*(spacing|surround)\s+(\S+)\s+(\S+)\s+/)
133 {
Philipp Gühringbad02082021-06-10 01:19:55 +0200134 my $a2=$2;
135 my $a3=$3;
136 $alias{$a2}=1;
137 $alias{$a3}=1;
138 foreach(split(",",$a2))
Philipp Gühring87f57522021-06-09 01:25:19 +0200139 {
140 $alias{$_}=1;
Philipp Gühringbad02082021-06-10 01:19:55 +0200141 $alias{$1}=1 if(m/^([^\/]+)/);
Philipp Gühring87f57522021-06-09 01:25:19 +0200142 }
Philipp Gühringbad02082021-06-10 01:19:55 +0200143 foreach(split(",",$a3))
Philipp Gühring87f57522021-06-09 01:25:19 +0200144 {
145 $alias{$_}=1;
Philipp Gühringbad02082021-06-10 01:19:55 +0200146 $alias{$1}=1 if(m/^([^\/]+)/);
Philipp Gühring87f57522021-06-09 01:25:19 +0200147 }
148 }
Philipp Gühring4e696c92021-06-10 00:36:47 +0200149 # Rule: width type-list width error
150 if(m/^\s*(width)\s+(\S+)\s+(\S+)\s+"([^"]*)"\s*$/)
151 {
152 $alias{$2}=1;
153 foreach(split(",",$2))
154 {
155 $alias{$_}=1;
156 }
157 }
Philipp Gühring87f57522021-06-09 01:25:19 +0200158}
159close IN;
160
161
162if($debug)
163{
164 print STDERR "BEFORE:\n";
165 foreach(sort keys %alias)
166 {
167 print STDERR "$_ -> $alias{$_}\n";
168 }
169}
170
171# No we are asking magic what those virtual layers actually mean
172 if(open OUT,"|magic -dnull -noconsole -T $tech >magic.layers.out")
173 {
174 print OUT "puts \"CUT HERE -------- CUT HERE\"\n";
175 foreach(sort keys %alias)
176 {
177 print OUT "puts \"EXPANDING: $_\"\n";
178 print OUT "puts [tech layers $_]\n";
179 }
180 print OUT "puts \"CUT HERE -------- CUT HERE\"\n";
181 print OUT "quit -noprompt\n";
182 close OUT;
183
184 # Now we are retrieving the answer from Magic:
185 if(open IN,"<magic.layers.out")
186 {
187 while(<IN>)
188 {
189 if(m/^EXPANDING: (\S+)/)
190 {
191 my $next=<IN>;
192 chomp $next;
193 $alias{$1}=$next;
194 }
195 }
196 close IN;
197 }
198 else
199 {
200 die "Could not get the results from magic!\n";
201 }
202 }
203 else
204 {
205 die "Could not run magic!\n";
206 }
207
208
209if($debug)
210{
211 print STDERR "\n\nAFTER:\n";
212 foreach(sort keys %alias)
213 {
214 print STDERR "$_ -> $alias{$_}\n";
215 }
216 exit;
217}
218
219open IN,"<$tech";
220
221# This function expands a single layer-list into all the physical layers it means
222sub allLayers($)
223{
224 #if($_[0] !~ m/\//) # If we do not look for "images" (which are signalled by / in the typelist and are currently not supported by magic), then we can just use the whole typelist which is more efficient.
225 #{
226 #return split " ",$alias{$_[0]} ;
227 #}
228
229 my @a=split ",",$_[0];
230 my %b=();
231 foreach(@a)
232 {
Philipp Gühringbad02082021-06-10 01:19:55 +0200233 print STDERR "piece: $_\n" if($debug);
234 if(m/(\/\S+)/ && defined($alias{$_}) && $alias{$_})
Philipp Gühring87f57522021-06-09 01:25:19 +0200235 {
Philipp Gühringbad02082021-06-10 01:19:55 +0200236 print STDERR "WE FOUND A SLASH AND AN ALIAS\n" if($debug);
Philipp Gühring87f57522021-06-09 01:25:19 +0200237 my $image=$1;
238 foreach my $part(split " ",$alias{$_})
239 {
Philipp Gühringbad02082021-06-10 01:19:55 +0200240 print STDERR "PART: $part\n" if($debug);
Philipp Gühring87f57522021-06-09 01:25:19 +0200241 $b{$part.(($part =~ m/\//)?"":$image)}=1;
242 }
243 }
Philipp Gühringbad02082021-06-10 01:19:55 +0200244 elsif(m/^([^\/]+)(\/\S+)/) # This is a workaround for bugs in magic that hopefully get fixed
245 {
246 print STDERR "WE FOUND A SLASH BUT NO ALIAS\n" if($debug);
247 my $image=$2;
248 my $short=$1;
249 foreach my $part(split " ",$alias{$short})
250 {
251 print STDERR "PART: $part\n" if($debug);
252 $b{$part.$image}=1;
253 }
254 }
Philipp Gühring87f57522021-06-09 01:25:19 +0200255 else
256 {
Philipp Gühringbad02082021-06-10 01:19:55 +0200257 print STDERR "NO SLASH OR ALIAS\n" if($debug);
Philipp Gühring87f57522021-06-09 01:25:19 +0200258 foreach my $part(split " ",$alias{$_})
259 {
260 $b{$part}=1;
261 }
262 }
263 }
264 return sort keys %b;
265}
266
267my $section="";
268our %drckind=();
269# Finally we are processing the whole tech file and annotating the rules:
270while(<IN>)
271{
272 while($_=~m/\\$/)
273 {
274 $_.=<IN>;
275 }
276 if(m/^(\w+)/)
277 {
278 $section=$1;
279 }
280 # if($section eq "contact" && m/^\s+(\w+)/)
281 #{
282 # my $a=$_;
283 # $a=~s/^\s+//; $a=~s/\s+$//;
284 # my @a=split(/\s+/,$a);
285 # my $cont=shift(@a);
286 # foreach my $cnt(@a)
287 # {
288 # print STDERR "CONTACT: $cont -> $cnt\n";
289 # $contacts{$cont}{$cnt}=1;
290 # $contacts{$cnt}{$cont}=1;
291 # }
292 #}
293 #if($section eq "aliases" && m/^\s+(\w+)/)
294 #{
295 # my $a=$_;
296 # $a=~s/^\s+//; $a=~s/\s+$//;
297 # my @a=split(/\s+/,$a);
298 # my $cont=shift(@a);
299 # foreach my $cnt(@a)
300 # {
301 # print STDERR "ALIAS: $cont -> $cnt\n";
302 # $alias{$cont}=$cnt;
303 # }
304 #}
305 my $oneline=$_;
306 $oneline=~s/\n//sg;
307 tr/\\//;
308 if($section eq "drc")
309 {
310 if(m/^\s*(\w+)/)
311 {
312 $drckind{$1}=1;
313 }
314 }
315
316
317 if(m/^\s*(spacing|surround)\s+(\S+)\s+(\S+)\s+(\d+)\s+\\?\s*(\w+)\s+\\?\s*"([^"]+)"/)
318 {
319 #print " # ORIGINAL RULE:$oneline\n";
320 my $vl1=$2;
321 my $vl2=$3;
322 my $text=$6;
323 my $l1=join " ",allLayers($vl1);
324 print STDERR "L1: $vl1 -> $l1\n" if($debug);
325 my $l2=join " ",allLayers($vl2);
326 print STDERR "L2: $vl2 -> $l2\n" if($debug);
327
328 if($expand)
329 {
330 foreach my $layer1(allLayers($vl1))
331 {
332 foreach my $layer2(allLayers($vl2))
333 {
334 #print " $1 $layer1 $layer2 $4 $5 \"$6 [erase $layer1]".(($layer1 eq $layer2)?"":"[erase $layer2]")."\"\n";
335 }
336 }
337 }
338 else
339 {
340 print " $1 $vl1 $vl2 $4 $5 \"$6 [erase $l1".(($vl1 eq $vl2)?"":",$l2")."]\"\n";
341 }
342 #print "\n";
343 }
Philipp Gühring4e696c92021-06-10 00:36:47 +0200344 # Rule: width type-list width error
345 elsif(m/^\s*(width)\s+(\S+)\s+(\S+)\s+"([^"]*)"\s*$/)
346 {
347 print " # ORIGINAL RULE:$oneline\n";
348 my $vl2=$2;
Philipp Gühringbad02082021-06-10 01:19:55 +0200349 print STDERR "ALLLAYERS $vl2\n" if($debug);
Philipp Gühringa6f9fc02021-06-10 01:40:21 +0200350 my $l2=join ",",allLayers($vl2); # For painting we need a different strategy to try each layer individually
Philipp Gühringbad02082021-06-10 01:19:55 +0200351 print STDERR "INFO: vl2=$vl2 l2=$l2\n" if($debug);
Philipp Gühring4e696c92021-06-10 00:36:47 +0200352 my $text=$4;
353 print " $1 $vl2 $3 \"$4 [paint $l2]\"\n";
354 }
355
356
Philipp Gühring87f57522021-06-09 01:25:19 +0200357 else
358 {
359 print $_;
360 }
361}
362close IN;
363
364print STDERR "".join(",", sort keys %drckind)."\n";