Subversion Repositories OpenARM Single-board Computer

Rev

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