#!/usr/bin/perl
#
# BUGBUG: Known bugs:
# 1) Implicit symbols in a device don't get enumerated properly.
# This is why the power pins don't show for the TTL. Hopefully
# all logic will be explicit in the schematics.
# 2) Pads which would be marked ***unused*** in OUTPUT PINLIST
# are omitted.
#
# Read a schematic and "export" the partlist and pinlist.
# Note that we don't try to properly parse the XML.
#
# Extract the information in a format similar to the Eable
# EXPORT PARTLIST and EXPORT PINLIST commands.
#
sub mycmp {
$sa = $a; $sb = $b; # Copies to whittle on.
while ($sa cmp "") {
if ($sa =~ s/^(\d+)//) {
$da = $1;
if ($sb =~ s/^(\d+)//) {
return $da <=> $1 if $da <=> $1;
next; # Both numeric and equal
}
return $da cmp $sa if $da cmp $sa;
}
# Not numbers, check next character.
undef $da, $db;
$da = $1 if $sa =~ s/^(.)//;
$db = $1 if $sb =~ s/^(.)//;
return $da cmp $db if $da cmp $db;
}
}
$status = 0;
foreach $if (@ARGV) {
if (! -r $if) {
warn "$if: $!\n";
$status = 2;
next;
}
#
# Make the output directory, if it is missing.
$of = $if;
$of =~ s/[.]sch$//i;
$of =~ s:.*/::; # basename
mkdir $of unless -d $of;
#
# Check the ...pins.txt and ...prts.txt timestamps.
$pins = "$of/${of}pins.txt";
$prts = "$of/${of}prts.txt";
if ((-r $pins) # ...pins.txt exists
&& (-M $pins < -M $0) # and is newer than this script
&& (-M $pins < -M $if) # and is newer than schematic
&& (-r $prts) # ...prts.txt exists
&& (-M $prts < -M $0) # and is newer than this script
&& (-M $prts < -M $if)) { # and is also newer than schematic
next; # Output files are up to date!
}
#
# One or more of the output files needs to be remade.
# First, read the schematic and figure out what is what.
warn "remaking $pins, $prts\n";
open(INPUT, "$if") || die "$if: $!";
$sheet = 0;
# Clear the databases here to allow iteration to succeed.
%haspad, %direction, %symbol, %package, %pad;
%haspad = %direction = %symbol = %package = %pad = ();
%part = %sheet = %partpad = ();
die if %haspad;
die if %direction;
die if %symbol;
die if %package;
die if %pad;
die if %part;
die if %sheet;
die if %partpad;
while () {
$sheet++ if //;
$library = $1 if m::;
$library = undef if m::;
#
# Within a library, packages are defined before use.
# Make note of packages with pads or smds.
$package = $1 if / and within a .
# First, remember the symbols for the gates.
$set = $1 if / within a .
# They make a reference to a package, and if the package
# has pads, we care about it.
if (//) {
($device, $package) = ($1, $2);
next unless defined $haspad{"$library;$package"};
#warn "remembering for ($library/$set$device:$package)\n";
$package{"$library;$set$device"} = $package;
next;
}
# Also make note of , as it associates pads with pins
# within the device.
if (m::) {
($gate, $pin, $pad) = ($1, $2, $3);
#warn "setting pad{'$library;$set$device;$gate;$pin'} = $pad\n";
$pad{"$library;$set$device;$gate;$pin"} = $pad;
}
#
# Once the libraries have been described, the parts used
# can be identified.
if (/:;
next unless defined $package{"$library;$set$device"};
$package = $package{"$library;$set$device"};
$part{$part} = "$value;$set;$device;$package;$library";
}
#
# Instance updates $sheet
if (/ followed by
# a number of .
# This requires us to look up the corresponding pad. We are also
# expected to look up the pin direction.
$net = $1 if /$prts") || die "$prts: $!";
print PRT "Exported from $if\n\n";
print PRT "Part Value Device Package Library Sheet\n\n";
foreach $part (sort keys %part) {
($value, $set, $device, $package, $library) = split(/;/, $part{$part});
$set =~ s/[*]//;
printf PRT "%-8s %-14s %-15s %-12s %-8s %d\n",
$part, $value, "$set$device", $package, $library, $sheet;
}
#
# Open and write the sorted pins list.
open(PIN, ">$pins") || die "$pins: $!";
print PIN "Exported from $if\n\n";
print PIN "Part Pad Pin Dir Net\n";
$opart = "";
foreach $partpad (sort mycmp keys %partpad) {
($part, $pad) = split(/;/, $partpad);
next unless defined $part{$part};
if ($part eq $opart) {
$part = "";
} else {
print PIN "\n";
$opart = $part;
}
($pin, $dir, $net) = split(/;/, $partpad{$partpad});
printf PIN "%-8s %-8s %-10s %-8s %-s\n",
$part, $pad, $pin, $dir, $net;
}
}
exit $status;