Rev 153 | Rev 231 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
118 | jelle | 1 | #!/usr/bin/perl |
2 | # -*- perl -*- |
||
3 | |||
4 | # Copyright (C) 2006 DJ Delorie dj@delorie.com |
||
5 | # Released under the terms of the GNU General Public License, version 2 |
||
6 | |||
7 | # Usage: djboxsym sample.symdef > sample.sym |
||
8 | |||
133 | agaran | 9 | $y{left} = 300; |
10 | $y{right} = 300; |
||
131 | agaran | 11 | $y{labels} = -200; |
118 | jelle | 12 | $labelpin = 0; |
13 | |||
14 | # Read in the file, storing information about each pin. |
||
15 | |||
141 | agaran | 16 | my $pinnumwidth = 0; |
17 | my $blockname; |
||
18 | |||
222 | agaran | 19 | # vars used later too |
20 | my (%x, %y); |
||
21 | |||
22 | # vars used during parsing |
||
23 | my ($side, $busmode, $errors) = ('',0, 0); |
||
24 | # main loop which parses file |
||
118 | jelle | 25 | while (<>) { |
222 | agaran | 26 | # skip empty lines |
27 | next if /^#/; |
||
118 | jelle | 28 | |
222 | agaran | 29 | # cleanup leading/trailing spaces |
30 | s/^\s+//; |
||
31 | s/\s+$//; |
||
118 | jelle | 32 | |
222 | agaran | 33 | # convert spaces/tabs sequence to single space |
34 | s/[\s\t]+/ /g; |
||
118 | jelle | 35 | |
222 | agaran | 36 | # remove all CR/LF newlines |
37 | s/[\r\n]+$//; |
||
38 | |||
39 | # Note change of section. |
||
40 | if (/^\[(.*)\]/) { |
||
41 | $side = $1; |
||
42 | $space = 0; |
||
43 | next; |
||
118 | jelle | 44 | } |
222 | agaran | 45 | |
46 | # Start a bus |
||
47 | if (/^\.bus/) { |
||
48 | $busmode = 1; |
||
49 | next; |
||
118 | jelle | 50 | } |
51 | |||
222 | agaran | 52 | # blank lines - cancel bus, add gap. |
53 | if (! /\S/) { |
||
54 | if ($busmode) { |
||
55 | $y{$side} += 200; |
||
56 | $busmode = 0; |
||
57 | } |
||
58 | if ($space) { |
||
59 | if ($side =~ /left|right/) { |
||
60 | $y{$side} += 300; |
||
61 | } elsif ($side =~ /top|bottom/) { |
||
62 | $x{$side} += 400; |
||
63 | } |
||
64 | $space = 0; |
||
65 | } |
||
141 | agaran | 66 | next; |
67 | } |
||
118 | jelle | 68 | |
69 | |||
222 | agaran | 70 | # Hidden labels are stored separately, because we don't care how |
71 | # big they are. |
||
72 | if (/! (\S.*)/ && $side eq "labels") { |
||
73 | # code probably could be more smart and store labels ex in certain order |
||
74 | push(@attrs, $1); |
||
75 | next; |
||
118 | jelle | 76 | } |
77 | |||
222 | agaran | 78 | # Visible labels are stored as pins because their size affects the |
79 | # size of the symbols' box. |
||
80 | if (/\S/ && $side eq "labels") { |
||
81 | # an blockswith |
||
82 | if ($_ =~ /^block=/) { |
||
83 | $blockname = $_; |
||
84 | # printf STDERR "Blocname %s\n", $blockname; |
||
85 | next; |
||
86 | } |
||
118 | jelle | 87 | |
222 | agaran | 88 | $labelpin --; |
89 | $pinside{$labelpin} = $side; |
||
90 | $piny{$labelpin} = $y{labels}; |
||
91 | $pinlabel{$labelpin} = $_; |
||
92 | $y{labels} -= 200; |
||
93 | $rlen{$labelpin} = &textlen($_); |
||
94 | next; |
||
141 | agaran | 95 | } |
96 | |||
222 | agaran | 97 | # Regular pins are handled here. |
98 | if (/^([0-9A-Za-z]+)\s*(.*)/) { |
||
99 | $space = 1; |
||
100 | ($pin, $rest) = ($1,$2); |
||
101 | |||
102 | if ($saw_pin{$pin}) { |
||
103 | print STDERR "DUPLICATE PIN $pin (was $pinlabel{$pin}, now $rest)\n"; |
||
104 | $errors ++; |
||
105 | } |
||
106 | |||
107 | $saw_pin{$pin} = 1; |
||
108 | # our symbols use letters in names so next line wents wrong imo |
||
109 | # we have two solutions, use numbers only (hard for BGA or sth like that) |
||
110 | # or rework symdefs that we would get: |
||
111 | # <#pin> <pin-number from datasheet> <pinname> <pintype> <other attributes> |
||
112 | $maxpin = $pin if $maxpin < $pin; |
||
113 | |||
114 | $pinside{$pin} = $side; |
||
115 | |||
116 | next if $side eq "nc"; |
||
117 | |||
118 | if ($rest =~ /^([!>]+) (.*)/) { |
||
119 | $flags = $1; |
||
120 | $pinlabel{$pin} = $2; |
||
121 | $bubble{$pin} = 1 if $flags =~ /!/; |
||
122 | $edge{$pin} = 1 if $flags =~ />/; |
||
123 | } else { |
||
124 | $pinlabel{$pin} = $rest; |
||
125 | } |
||
126 | |||
127 | $rlen{$pin} = &textlen($pinlabel{$pin}); |
||
128 | |||
129 | if ($pinnumwidth < &textlen($pin)) { |
||
130 | $pinnumwidth = &textlen($pin); |
||
131 | } |
||
132 | |||
133 | if ($side =~ /left|right/) { |
||
134 | $y = $piny{$pin} = $y{$side}; |
||
135 | $y{$side} += ($busmode ? 200 : 300); |
||
136 | } |
||
137 | |||
138 | if ($side =~ /top|bottom/) { |
||
139 | $tw = &alignpin((200 + $rlen{$pin}) / 2); |
||
140 | $pinx{$pin} = $w{$side} + $tw; |
||
141 | $w{$side} += $tw + $tw; |
||
142 | } |
||
143 | |||
118 | jelle | 144 | } |
145 | |||
146 | } |
||
147 | |||
222 | agaran | 148 | # parser finished here |
149 | |||
150 | # round to nearest multiple of 100 larger or equal to actual number |
||
141 | agaran | 151 | $pinnumwidth += 100 - ($pinnumwidth % 100); |
152 | |||
118 | jelle | 153 | $minpin = $labelpin; |
154 | $boxwidth = 0; |
||
155 | %bw = (); |
||
156 | |||
157 | # for each horizontal slice of the symbol, keep track of how much |
||
158 | # width is used up by the left, middle, and right labels. |
||
159 | for $lp (keys %pinside) { |
||
160 | next unless $pinside{$lp} =~ /left|right|label/; |
||
161 | $yb = &alignpin($piny{$lp}); |
||
162 | for ($y=$yb-100; $y<=$yb+100; $y+=100) { |
||
222 | agaran | 163 | # again we got not numbers inside, so lt/gt operator dont work well.. need to track why and how fix |
118 | jelle | 164 | if ($bw{$y}{$pinside{$lp}} < $rlen{$lp}) { |
165 | $bw{$y}{$pinside{$lp}} = $rlen{$lp}; |
||
166 | } |
||
167 | } |
||
168 | } |
||
169 | |||
170 | # Compute the height of the box. |
||
171 | for $p (keys %pinside) { |
||
222 | agaran | 172 | next unless $pinside{$p} =~ /left|right/; |
173 | if ($maxy < $piny{$p}) { |
||
174 | $maxy = $piny{$p}; |
||
175 | } |
||
118 | jelle | 176 | } |
133 | agaran | 177 | $maxy += 300; |
118 | jelle | 178 | |
179 | # Now, use the slice widths to compute the minimum width of the box. |
||
180 | for ($i=0; $i<$maxy; $i+=100) { |
||
222 | agaran | 181 | my $w = 0; |
182 | |||
183 | $w += $bw{$i}{left} if (defined $bw{$i}{left}); |
||
184 | $w += $bw{$i}{labels} if (defined $bw{$i}{labels}); |
||
185 | $w += $bw{$i}{right} if (defined $bw{$i}{right}); |
||
186 | |||
118 | jelle | 187 | if ($bw{$i}{labels}) { |
188 | $wl = ($bw{$i}{left} + $bw{$i}{labels}/2) * 2; |
||
189 | $w = $wl if $w < $wl; |
||
190 | $wl = ($bw{$i}{right} + $bw{$i}{labels}/2) * 2; |
||
191 | $w = $wl if $w < $wl; |
||
192 | } |
||
222 | agaran | 193 | # need to review that if()'s |
118 | jelle | 194 | if ($bw{$i}{left} && $bw{$i}{labels}) { |
195 | $w += 100; |
||
196 | } elsif ($bw{$i}{left} && $bw{$i}{right}) { |
||
197 | $w += 200; |
||
198 | } |
||
199 | if ($bw{$i}{right} && $bw{$i}{labels}) { |
||
200 | $w += 100; |
||
201 | } |
||
202 | if ($boxwidth < $w) { |
||
203 | $boxwidth = $w; |
||
204 | } |
||
205 | } |
||
206 | |||
121 | jelle | 207 | |
208 | for ($i = $y{labels}; $i <= 0; $i+=100) { |
||
209 | my $w = $bw{$i}{labels}; |
||
210 | $w += 100 - ($w%100); |
||
153 | agaran | 211 | if (defined $blockname && defined $bw{$i}{labels}) { # device name is longest, so rest arent affected |
142 | agaran | 212 | my ($p,$q) = split ('=', $blockname,2); |
213 | #printf STDERR "LINE %s %d w=%d\n", $bw{$i}{labels}, $i, $w; |
||
214 | $w += &textlen($q) + 100; # same space enforcement as it was for inside labels |
||
215 | #printf STDERR "LINE %s %d w=%d\n", $bw{$i}{labels}, $i, $w; |
||
216 | # so we have to block name width to $w here.. |
||
217 | # but only in last line (device name) |
||
218 | } |
||
121 | jelle | 219 | #$w = (int($w/100) * 100) + (($w/100) > int($w/100))?100:0; |
220 | if ($boxwidth < $w) { |
||
221 | $boxwidth = $w; |
||
222 | } |
||
223 | } |
||
224 | |||
225 | #printf STDERR "test: %d\n", $y{labels}; |
||
226 | |||
118 | jelle | 227 | $boxwidth = $w{top} if $boxwidth < $w{top}; |
228 | $boxwidth = $w{bottom} if $boxwidth < $w{bottom}; |
||
229 | |||
230 | # Flip Y coordinates (we count from the top, but symbols coordinates |
||
231 | # are from the bottom). |
||
232 | for $p (keys %pinside) { |
||
133 | agaran | 233 | next unless $pinside{$p} =~ /left|right/; |
118 | jelle | 234 | $piny{$p} = $maxy - $piny{$p} + 300; |
235 | } |
||
236 | |||
133 | agaran | 237 | for $p (keys %pinside) { |
238 | next unless $pinside{$p} =~ /label/; |
||
239 | $piny{$p} = $maxy + $piny{$p} - $minpin * 200 + 400; |
||
240 | } |
||
241 | |||
118 | jelle | 242 | $boxwidth = &alignpin($boxwidth); |
243 | $boxwidth += 200; |
||
244 | |||
245 | # Adjust the position of the top/bottom pins so that, as a group, |
||
246 | # they're centered. |
||
247 | for $p (keys %pinside) { |
||
248 | next unless $pinside{$p} =~ /top|bottom/; |
||
141 | agaran | 249 | $pinx{$p} += &alignpin(($boxwidth - $w{$pinside{$p}})/2) + $pinnumwidth; |
118 | jelle | 250 | } |
251 | |||
252 | # Labels are centered in the box. |
||
121 | jelle | 253 | # labels have to be top, lef |
118 | jelle | 254 | for $lp ($minpin..-1) { |
121 | jelle | 255 | #$pinx{$lp} = &alignpin($boxwidth/2) + 300; |
141 | agaran | 256 | $pinx{$lp} = $pinnumwidth; |
118 | jelle | 257 | } |
258 | |||
259 | # Version. |
||
260 | print "v 20060123 1\n"; |
||
261 | |||
262 | # Symbol box. |
||
263 | printf("B %d %d %d %d 3 0 0 0 -1 -1 0 -1 -1 -1 -1 -1\n", |
||
141 | agaran | 264 | $pinnumwidth, 300, $boxwidth, $maxy); |
118 | jelle | 265 | |
266 | # These are the hidden labels. |
||
267 | $ax = 300 + $boxwidth; |
||
268 | $ay = 400 + $maxy; |
||
269 | for $a (reverse @attrs) { |
||
270 | printf("T %d %d 9 10 0 0 0 0 1\n%s\n", |
||
271 | $ax, $ay, $a); |
||
272 | $ay += 200; |
||
273 | } |
||
274 | |||
141 | agaran | 275 | # blockname if present |
276 | if(defined $blockname) { |
||
277 | printf("T %d %d 5 10 1 1 0 6 1\n%s\n", $boxwidth + $pinnumwidth, $maxy + 400, $blockname); |
||
278 | } |
||
279 | |||
118 | jelle | 280 | # Now print all the pins. |
222 | agaran | 281 | # and here non digit numbers bug us too, so we need to rework.. |
118 | jelle | 282 | for $p (sort {$a<=>$b} keys %pinside) { |
283 | next unless $pinside{$p}; |
||
284 | if ($pinside{$p} eq "left") { |
||
141 | agaran | 285 | $pinx{$p} = $pinnumwidth; |
118 | jelle | 286 | } |
287 | if ($pinside{$p} eq "right") { |
||
141 | agaran | 288 | $pinx{$p} = $pinnumwidth + $boxwidth; |
118 | jelle | 289 | } |
222 | agaran | 290 | # here we get warning about undefined value in addition, probably one of things isnt defined.. |
118 | jelle | 291 | if ($p > 0 && !$saw_pin{$p}) { |
292 | print STDERR "MISSING PIN $p\n"; |
||
293 | $errors++; |
||
294 | } else { |
||
295 | printf STDERR ("%3d %-6s %4d %4d %s\n", |
||
296 | $p, $pinside{$p}, $pinx{$p}, $piny{$p}, $pinlabel{$p}); |
||
297 | } |
||
298 | |||
299 | eval "&drawpin_$pinside{\"$p\"} (\"$p\")"; |
||
300 | } |
||
301 | |||
302 | # what remains are helper functions; for drawing each type of pin, |
||
303 | # each type of label, etc. |
||
304 | |||
305 | sub drawpin_nc { |
||
306 | } |
||
307 | |||
308 | sub drawpin_top { |
||
309 | my($pin) = @_; |
||
310 | $y = $maxy + 300; |
||
311 | printf("P %d %d %d %d 1 0 0\n", |
||
312 | $pinx{$pin}, $y+300, $pinx{$pin}, $y); |
||
313 | print "{\n"; |
||
314 | &pltext($pinx{$pin}, $y-50, 5, $pinlabel{$pin}); |
||
315 | &ntext($pinx{$pin}+50, $y+50, 0, $pin); |
||
316 | print "}\n"; |
||
317 | } |
||
318 | |||
319 | sub drawpin_bottom { |
||
320 | my($pin) = @_; |
||
321 | printf("P %d %d %d %d 1 0 0\n", |
||
322 | $pinx{$pin}, 0, $pinx{$pin}, 300); |
||
323 | print "{\n"; |
||
324 | &pltext($pinx{$pin}, 350, 3, $pinlabel{$pin}); |
||
325 | &ntext($pinx{$pin}+50, 250, 2, $pin); |
||
326 | print "}\n"; |
||
327 | } |
||
328 | |||
329 | sub drawpin_labels { |
||
330 | my($pin) = @_; |
||
131 | agaran | 331 | <ext($pinx{$pin}, $piny{$pin}, 0, $pinlabel{$pin}); |
118 | jelle | 332 | } |
333 | |||
334 | sub circle { |
||
335 | my ($x, $y) = @_; |
||
336 | print "V $x $y 50 3 0 0 0 -1 -1 0 -1 -1 -1 -1 -1\n"; |
||
337 | } |
||
338 | |||
339 | sub drawpin_left { |
||
340 | my($pin) = @_; |
||
341 | $x = $pinx{$pin}; |
||
342 | $px = 50; |
||
343 | if ($bubble{$pin}) { |
||
344 | $x -= 100; |
||
345 | &circle($x+50, $piny{$pin}); |
||
346 | } |
||
347 | if ($edge{$pin}) { |
||
348 | $px += 100; |
||
349 | printf("L %d %d %d %d 3 0 0 0 0 0\n", |
||
350 | $pinx{$pin}, $piny{$pin}-50, |
||
351 | $pinx{$pin}+100, $piny{$pin}); |
||
352 | printf("L %d %d %d %d 3 0 0 0 0 0\n", |
||
353 | $pinx{$pin}+100, $piny{$pin}, |
||
354 | $pinx{$pin}, $piny{$pin}+50); |
||
355 | |||
356 | } |
||
357 | printf("P %d %d %d %d 1 0 0\n", |
||
141 | agaran | 358 | $pinx{$pin} - $pinnumwidth, $piny{$pin}, $x, $piny{$pin}); |
118 | jelle | 359 | print "{\n"; |
360 | &pltext($pinx{$pin} + $px, $piny{$pin}, 1, $pinlabel{$pin}); |
||
361 | &ntext($pinx{$pin} -100, $piny{$pin} + 50, 6, $pin); |
||
362 | print "}\n"; |
||
363 | } |
||
364 | |||
365 | sub drawpin_right { |
||
366 | my($pin) = @_; |
||
367 | $x = $pinx{$pin}; |
||
368 | $px = 50; |
||
369 | if ($bubble{$pin}) { |
||
370 | $x += 100; |
||
371 | &circle($x-50, $piny{$pin}); |
||
372 | } |
||
373 | if ($edge{$pin}) { |
||
374 | $px += 100; |
||
375 | printf("L %d %d %d %d 3 0 0 0 0 0\n", |
||
376 | $pinx{$pin}, $piny{$pin}-50, |
||
377 | $pinx{$pin}-100, $piny{$pin}); |
||
378 | printf("L %d %d %d %d 3 0 0 0 0 0\n", |
||
379 | $pinx{$pin}-100, $piny{$pin}, |
||
380 | $pinx{$pin}, $piny{$pin}+50); |
||
381 | |||
382 | } |
||
383 | printf("P %d %d %d %d 1 0 0\n", |
||
141 | agaran | 384 | $pinx{$pin} + $pinnumwidth, $piny{$pin}, $x, $piny{$pin}); |
118 | jelle | 385 | print "{\n"; |
386 | &pltext($pinx{$pin} - $px, $piny{$pin}, 7, $pinlabel{$pin}); |
||
387 | &ntext($pinx{$pin} +100, $piny{$pin} + 50, 0, $pin); |
||
388 | print "}\n"; |
||
389 | } |
||
390 | |||
391 | sub ntext { |
||
392 | my ($x, $y, $a, $s) = @_; |
||
393 | printf("T %d %d 5 8 1 1 0 %s 1\npinnumber=%s\n", $x, $y, $a, $s); |
||
394 | printf("T %d %d 5 8 0 1 0 %s 1\npinseq=%s\n", $x, $y, $a, $s); |
||
395 | } |
||
396 | |||
397 | sub pltext { |
||
398 | my ($x, $y, $a, $s) = @_; |
||
399 | $s = "pinlabel=$s" unless $s =~ /=/; |
||
400 | printf("T %d %d 9 10 1 1 0 %s 1\n%s\n", $x, $y, $a, $s); |
||
401 | } |
||
402 | |||
403 | sub ltext { |
||
404 | my ($x, $y, $a, $s) = @_; |
||
134 | agaran | 405 | printf("T %d %d 5 10 1 1 0 %s 1\n%s\n", $x, $y, $a, $s); |
118 | jelle | 406 | } |
407 | |||
408 | sub textlen { |
||
409 | my($t) = @_; |
||
410 | $t =~ s/^[^=]*=//; |
||
411 | $t =~ s@\\_@@g; |
||
412 | return length($t) * 120; |
||
413 | } |
||
414 | |||
415 | sub alignpin { |
||
416 | my($v) = @_; |
||
417 | return int(($v + 99) / 100) * 100; |
||
418 | } |
||
419 | |||
420 | exit $errors; |