#!/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;