#!/usr/bin/perl # -*- perl -*- # Copyright (C) 2006 DJ Delorie dj@delorie.com # changed spacings and orientations by adding variable $labelo, for label orientation # and using rlen{} followed by a divide by 1.5 to get vertical text position right. John Griessen 7 sep 2006 # Released under the terms of the GNU General Public License, version 2 # Usage: jgboxsym sample.symdef > sample.sym $y{left} = 300; $y{right} = 300; #This $y{labels} will be good for symbols with more than 20 names all around edge, else...you tweak it. $y{labels} = 1600; #should be about half height to go in middle of symbol. $labelpin = 0; $box_horiz_space = 4800; #main thing to guess about number of pins 300 per pin on bootom or top. # Read in the file, storing information about each pin. while (<>) { next if /^#/; s/^\s+//; s/\s+$//; s/[\s\t]+/ /g; s/[\r\n]+$//; # Note change of section. if (/^\[(.*)\]/) { $side = $1; $space = 0; next; } # Start a bus if (/^\.bus/) { $busmode = 1; next; } # blank lines - cancel bus, add gap. if (! /\S/) { if ($busmode) { $y{$side} += 150; } $busmode = 0; if ($space) { if ($side =~ /left|right/) { $y{$side} += 300; } if ($side =~ /top|bottom/) { $x{$side} += 300; } $space = 0; } next; } # Hidden labels are stored separately, because we don't care how # big they are. if (/! (\S.*)/ && $side eq "labels") { push(@attrs, $1); next; } # Visible labels are stored as pins because their size affects the # size of the symbols' box. if (/\S/ && $side eq "labels") { $labelpin --; $pinside{$labelpin} = $side; $piny{$labelpin} = $y{labels}; $pinlabel{$labelpin} = $_; $y{labels} += 300; $rlen{$labelpin} = &textlen($_); next; } # Regular pins are handled here. if (/^(\d+)\s*(.*)/) { $space = 1; ($pin, $rest) = ($1,$2); if ($saw_pin{$pin}) { print STDERR "DUPLICATE PIN $pin (was $pinlabel{$pin}, now $rest)\n"; $errors ++; } $saw_pin{$pin} = 1; $maxpin = $pin if $maxpin < $pin; $pinside{$pin} = $side; next if $side eq "nc"; if ($rest =~ /^([!>]+) (.*)/) { $flags = $1; $pinlabel{$pin} = $2; $bubble{$pin} = 1 if $flags =~ /!/; $edge{$pin} = 1 if $flags =~ />/; } else { $pinlabel{$pin} = $rest; } $rlen{$pin} = &textlen($pinlabel{$pin}); if ($side =~ /left|right/) { $labelo{$pin} = 0; $y = $piny{$pin} = $y{$side}; $y{$side} += ($busmode ? 150 : 300); } if ($side =~ /top|bottom/) { $labelo{$pin} = 90; $tw = &alignpin(125); $pinx{$pin} = $w{$side} + $tw ; $w{$side} += $tw + $tw; } } } $minpin = $labelpin; $boxwidth = 0; %bw = (); # for each horizontal slice of the symbol, keep track of how much # width is used up by the left, middle, and right labels. for $lp ($minpin..$maxpin) { next unless $pinside{$lp} =~ /left|right|label/; $yb = &alignpin($piny{$lp}); for ($y=$yb-100; $y<=$yb+100; $y+=100) { if ($bw{$y}{$pinside{$lp}} < $rlen{$lp}) { $bw{$y}{$pinside{$lp}} = $rlen{$lp}; } } } # Compute the height of the box. for $p (1..$maxpin) { next unless $pinside{$p} =~ /left|right/; if ($maxy < $piny{$p}) { $maxy = $piny{$p}; } } $maxy += 400; # Now, insert width of the box from above. $boxwidth += $box_horiz_space; # added 300 jg 23apr10 print STDERR "boxwidth after add box_horiz_space = $boxwidth \n"; # jg23apr debug # Flip Y coordinates (we count from the top, but symbols coordinates # are from the bottom). for $p ($minpin..$maxpin) { next unless $pinside{$p} =~ /left|right|labels/; $piny{$p} = $maxy - $piny{$p} + 300; } print STDERR "boxwidth = $boxwidth \n"; # jg23apr debug $boxwidth = &alignpin($boxwidth); print STDERR "boxwidth after alignpin = $boxwidth \n"; # jg23apr debug # Adjust the position of the top/bottom pins so that, as a group, # they're centered. for $p ($minpin..$maxpin) { next unless $pinside{$p} =~ /top|bottom/; $pinx{$p} += &alignpin(($boxwidth - $w{$pinside{$p}})/2) + 150; } # Labels are centered in the box. for $lp ($minpin..-1) { $pinx{$lp} = &alignpin($boxwidth/2) + 300; # added 300 jg23apr10 } # Version. print "v 20060123 1\n"; # Symbol box. printf("B %d %d %d %d 3 0 0 0 -1 -1 0 -1 -1 -1 -1 -1\n", 300, 300, $boxwidth, $maxy); # These are the hidden labels. $ax = 300 + $boxwidth; $ay = 400 + $maxy; for $a (reverse @attrs) { printf("T %d %d 9 10 0 0 0 0 1\n%s\n", $ax, $ay, $a); $ay += 200; } # Now print all the pins. for $p ($minpin..$maxpin) { next unless $pinside{$p}; if ($pinside{$p} eq "left") { $pinx{$p} = 300; } if ($pinside{$p} eq "right") { $pinx{$p} = 300 + $boxwidth; } if ($p > 0 && !$saw_pin{$p}) { print STDERR "MISSING PIN $p\n"; $errors++; } else { printf STDERR ("%3d %-6s %4d %4d %s\n", $p, $pinside{$p}, $pinx{$p}, $piny{$p}, $pinlabel{$p}); } eval "&drawpin_$pinside{$p} ($p)"; } # what remains are helper functions; for drawing each type of pin, # each type of label, etc. sub drawpin_nc { } sub drawpin_top { my($pin) = @_; $y = $maxy + 300 ; printf("P %d %d %d %d 1 0 0\n", $pinx{$pin} , $y+300, $pinx{$pin}, $y); print "{\n"; &pltext($pinx{$pin} - 100, $y-150 - ($rlen{$pin} )/1.5, $labelo{$pin}, 5, $pinlabel{$pin}); &ntext($pinx{$pin}-50, $y+50, $labelo{$pin}, 0, $pin); print "}\n"; } sub drawpin_bottom { my($pin) = @_; printf("P %d %d %d %d 1 0 0\n", $pinx{$pin}, 0, $pinx{$pin}, 300); print "{\n"; &pltext($pinx{$pin}, 450 + ($rlen{$pin} )/1.5, $labelo{$pin}, 3, $pinlabel{$pin}); &ntext($pinx{$pin}-150, 50, $labelo{$pin}, 2, $pin); print "}\n"; } sub drawpin_labels { my($pin) = @_; <ext($pinx{$pin}, $piny{$pin}, $labelo{$pin}, 3, $pinlabel{$pin}); } sub circle { my ($x, $y) = @_; print "V $x $y 50 3 0 0 0 -1 -1 0 -1 -1 -1 -1 -1\n"; } sub drawpin_left { my($pin) = @_; $x = $pinx{$pin}; $px = 50; if ($bubble{$pin}) { $x -= 100; &circle($x+50, $piny{$pin}); } if ($edge{$pin}) { $px += 100; printf("L %d %d %d %d 3 0 0 0 0 0\n", $pinx{$pin}, $piny{$pin}-50, $pinx{$pin}+100, $piny{$pin}); printf("L %d %d %d %d 3 0 0 0 0 0\n", $pinx{$pin}+100, $piny{$pin}, $pinx{$pin}, $piny{$pin}+50); } printf("P %d %d %d %d 1 0 0\n", $pinx{$pin} - 300, $piny{$pin}, $x, $piny{$pin}); print "{\n"; &pltext($pinx{$pin} + $px, $piny{$pin}, $labelo{$pin}, 1, $pinlabel{$pin}); &ntext($pinx{$pin} -100, $piny{$pin} + 50, $labelo{$pin}, 6, $pin); print "}\n"; } sub drawpin_right { my($pin) = @_; $x = $pinx{$pin}; $px = 50; if ($bubble{$pin}) { $x += 100; &circle($x-50, $piny{$pin}); } if ($edge{$pin}) { $px += 100; printf("L %d %d %d %d 3 0 0 0 0 0\n", $pinx{$pin}, $piny{$pin}-50, $pinx{$pin}-100, $piny{$pin}); printf("L %d %d %d %d 3 0 0 0 0 0\n", $pinx{$pin}-100, $piny{$pin}, $pinx{$pin}, $piny{$pin}+50); } printf("P %d %d %d %d 1 0 0\n", $pinx{$pin} + 300, $piny{$pin}, $x, $piny{$pin}); print "{\n"; &pltext($pinx{$pin} - $px, $piny{$pin}, $labelo{$pin}, 7, $pinlabel{$pin}); &ntext($pinx{$pin} +100, $piny{$pin} + 50, $labelo{$pin}, 0, $pin); print "}\n"; } sub ntext { my ($x, $y, $o, $a, $s) = @_; printf("T %d %d 5 8 1 1 %d %s 1\npinnumber=%s\n", $x, $y, $o, $a, $s); printf("T %d %d 5 8 0 1 %d %s 1\npinseq=%s\n", $x, $y, $o, $a, $s); } sub pltext { my ($x, $y, $o, $a, $s) = @_; $s = "pinlabel=$s" unless $s =~ /=/; printf("T %d %d 9 14 1 1 %d %s 1\n%s\n", $x, $y, $o, $a, $s); } sub ltext { my ($x, $y, $o, $a, $s) = @_; printf("T %d %d 9 14 1 1 %d %s 1\n%s\n", $x, $y, $o, $a, $s); } sub textlen { my($t) = @_; $t =~ s/^[^=]*=//; return length($t) * 110; } sub alignpin { my($v) = @_; return int(($v + 49) / 50) * 50; } exit $errors;