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