Subversion Repositories OpenARM Single-board Computer

Rev

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