Subversion Repositories OpenARM Single-board Computer

Rev

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
    &ltext($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;