1#!/usr/local/bin/perl -w 2# 3# Copyright (C) 2003, 2011 Dan McMahill 4# 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation; either version 2 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program; if not, write to the Free Software 17# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 18# MA 02111-1301 USA. 19 20 21# This script is used to process PADS PowerPCB .eco files to backannotate 22# changes to gEDA schematics. Not all ECO file sections are implemented, 23# and this program is relatively untested. Please proceed with caution. 24# 25 26# for parsing input options 27use Getopt::Long; 28 29# for ceil function 30use POSIX; 31 32# don't allow -he to be interpreted as --help 33$Getopt::Long::autoabbrev=0; 34 35# make the options be case sensitive 36$Getopt::Long::ignorecase=0; 37 38&GetOptions( ('h|help' => \&usage, 39 'n|nocopy' => \$nocopy, 40 'v|verbose' => \$verbose, 41 'V|version' => \&version 42 ) ); 43 44usage() if $Getopt::Long::error; 45usage() unless @ARGV; 46 47# ECO file name 48$eco = shift( @ARGV ); 49 50# if no schematic names follow, exit 51usage() unless @ARGV; 52 53# make sure the input netlist exists and we can open it 54$i = 0; 55while( @ARGV ) { 56 $fname[$i] = shift( @ARGV ); 57 die "Schematic file $fname[$i] does not exist or can not be read" 58 unless -r $fname[$i]; 59 $i++; 60} 61 62$filecnt = $i; 63 64 65if( $verbose ){ print "Loading ECO file: $eco\n"; } 66$eco_state="DEFAULT"; 67$got_end=0; 68open( ECO, "$eco" ) or die "Can't open ECO file $eco !\n"; 69 70$line = <ECO>; 71if( $line =~ /^\*PADS-ECO-V3\.0\*[\n\r]*$/ ) { 72 print "Read ECO header line\n" if $verbose ; 73} elsif( $line =~ /^\*PADS-ECO-\*/ ) { 74 print "Unknown ECO file version: $line\n"; 75 exit 1; 76} else { 77 print "Invalid ECO file header: $line\n"; 78 exit 1; 79} 80 81while( $line = <ECO> ) { 82 # if( $verbose ){ print "$line\n"; } 83 if( $line =~ /^\*CHGPART\*/ ) { 84 # change type of part (forward annotation) 85 $eco_state="CHGPART"; 86 next; 87 } elsif( $line =~ /^\*DEL_ATTRIBUTE\*/ ) { 88 # delete object attribute (forward annotation) 89 $eco_state="DEL_ATTRIBUTE"; 90 next; 91 } elsif( $line =~ /^\*DELPART\*/ ) { 92 # delete part from the design (forward annotation) 93 $eco_state="DELPART"; 94 next; 95 } elsif( $line =~ /^\*DELPIN\*/ ) { 96 # delete pins from net (forward annotation) 97 $eco_state="DELPIN"; 98 next; 99 } elsif( $line =~ /^\*END\*/ ) { 100 # end of ECO file 101 $eco_state="END"; 102 $got_end=1; 103 next; 104 } elsif( $line =~ /^\*JOINNET\*/ ) { 105 # join two nets together (forward annotation) 106 $eco_state="JOINNET"; 107 next; 108 } elsif( $line =~ /^\*NET\*/ ) { 109 # add pin to net (forward annotation) 110 $eco_state="NET"; 111 next; 112 } elsif( $line =~ /^\*PART\*/ ) { 113 # add part to the design (forward annotation) 114 $eco_state="PART"; 115 next; 116 } elsif( $line =~ /^\*REMARK\*/ ) { 117 # don't change state on comment lines 118 print "Skipping *REMARK* line\n" if $verbose; 119 next; 120 } elsif( $line =~ /^\*RENNET\*/ ) { 121 # rename netname (forward annotation) 122 $eco_state="RENNET"; 123 next; 124 } elsif( $line =~ /^\*RENPART\*/ ) { 125 # rename part in design (forward/backward annotation) 126 $eco_state="RENPART"; 127 print "Starting *RENPART* (Refdes Renumber) section\n" if $verbose; 128 next; 129 } elsif( $line =~ /^\*SET_ATTRIBUTE\*/ ) { 130 # set object attribute (forward annotation) 131 $eco_state="SET_ATTRIBUTE"; 132 next; 133 } elsif( $line =~ /^\*SIGNAL\*/ ) { 134 # part of *NET* and also *SPLITNET* (forward annotation) 135 $eco_state="SIGNAL"; 136 next; 137 } elsif( $line =~ /^\*SPLITNET\*/ ) { 138 # split net into two new nets (forward annotation) 139 $eco_state="SPLITNET"; 140 next; 141 } elsif( $line =~ /^\*SWPGATES\*/ ) { 142 $eco_state="SWPGATES"; 143 print "Starting *SWPGATES* (Gate Swapping) section\n" if $verbose; 144 next; 145 } elsif( $line =~ /^\*SWPPINS\*/ ) { 146 $eco_state="SWPPINS"; 147 print "Starting *SWPPINS* (Pin Swapping) section\n" if $verbose; 148 next; 149 } elsif( $line =~ /^\*/ ) { 150 print "WARNING: Unknown command line:\n"; 151 print " $line\n"; 152 $eco_state="DEFAULT"; 153 next; 154 } else { 155 # this must be a data line 156 #if( $verbose ){ print "Processing data line: $line"; } 157 } 158 159 if( $eco_state =~ "RENPART" ) { 160 parseRENPART($line); 161 } elsif( $eco_state =~ "SWPGATES" ) { 162 parseSWPGATES($line); 163 } elsif( $eco_state =~ "SWPPINS" ) { 164 parseSWPPINS($line); 165 } else { 166 print "Skipping lines in $eco_state section\n" if $verbose; 167 } 168 169} 170close( ECO ); 171 172for($i=0; $i < $filecnt; $i++) { 173 print "Processing schematic file #", $i+1, ": $fname[$i]\n"; 174 open(NETLIST,"$fname[$i]") or 175 die "Can't open schematic $fname[$i]: $!\n"; 176 177 # open output netlist 178 $outfname="$fname[$i].new"; 179 open(OUTSCH,">$outfname") or die "Can't open $outfname: $!\n"; 180 181 while($line = <NETLIST>) { 182 $line = executeRENPART($line); 183 print OUTSCH "$line"; 184 } 185 close(NETLIST); 186 close(OUTSCH); 187 188 if( $nocopy ) { 189 print "Leaving page #",$i+1," output in $outfname\n"; 190 } 191 else { 192 system("mv $outfname $fname[$i]"); 193 } 194 195} 196 197print "\n---- Gate Swapping ----\n"; 198executeSWPGATES(); 199print "\n---- Pin Swapping ----\n"; 200executeSWPPINS(); 201print "\nBackannotation finished ", scalar localtime, "\n"; 202 203exit; 204 205 206####################################################################### 207# 208# Subroutines 209# 210####################################################################### 211 212#--------------------------------- 213# executeRENPART(line) 214#--------------------------------- 215 216sub executeRENPART { 217 my $line = shift(@_); 218 219 return $line unless defined %cmd_rename; 220 return $line unless $line =~ /^refdes=/; 221 222 # pick out the reference designator 223 $refdes = $line; 224 $refdes =~ s/^refdes=//; 225 $refdes =~ s/[\r\n]*$//; 226 227 # see if its listed in our hash of reference designators to be 228 # renamed 229 return $line unless exists $cmd_rename{$refdes}; 230 231 print "executeRENPART(): Renaming $refdes to $cmd_rename{$refdes}\n" 232 if $verbose; 233 return "refdes=$cmd_rename{$refdes}\n"; 234 235} 236 237#--------------------------------- 238# executeSWPGATES() 239#--------------------------------- 240 241sub executeSWPGATES { 242 my $key; 243 244 foreach $key (keys %cmd_swap_gates ) { 245 print "Please manually swap gates $key and $cmd_swap_gates{$key}\n"; 246 } 247} 248 249#--------------------------------- 250# executeSWPPINS() 251#--------------------------------- 252 253sub executeSWPPINS { 254 my $key; 255 my @pins; 256 257 foreach $key (keys %cmd_swap_pins ) { 258 @pins = split '\.',,$cmd_swap_pins{$key}; 259 print "Please manually swap pins $pins[0] and $pins[1] on $key\n"; 260 } 261} 262 263#--------------------------------- 264# parseRENPART(line) 265#--------------------------------- 266 267sub parseRENPART { 268 my $line = shift(@_); 269 my @refs; 270 @refs = split ' ',,$line; 271 272 print "parseRENPART(): Scheduling rename of $refs[0] to $refs[1]\n" 273 if $verbose; 274 $cmd_rename{$refs[0]} = $refs[1]; 275 276} 277 278#--------------------------------- 279# parseSWPGATES(line) 280#--------------------------------- 281 282sub parseSWPGATES { 283 my $line = shift(@_); 284 my @refs; 285 @refs = split ' ',,$line; 286 287 print "parseSWPGATES(): Scheduling swap of gate $refs[0] with $refs[1]\n" 288 if $verbose; 289 $cmd_swap_gates{$refs[0]} = $refs[1]; 290 291} 292 293#--------------------------------- 294# parseSWPPINS(line) 295#--------------------------------- 296 297sub parseSWPPINS { 298 my $line = shift(@_); 299 @refs = split ' ',,$line; 300 @pins = split '\.',,$refs[1]; 301 302 print "parseSWPPINS(): Scheduling swap of pins on $refs[0] : pins ", 303 "$pins[0] and $pins[1]\n" if $verbose; 304 $cmd_swap_pins{$refs[0]} = $refs[1]; 305 306} 307 308#--------------------------------- 309# usage() 310# 311# prints program usage 312#--------------------------------- 313 314sub usage { 315 my $pname = $0; 316 $pname =~ s/.*\///g; 317 318 print "Usage:\n\n"; 319 print "\t$pname [-n|--nocopy] [-v|--verbose] change.eco file1.sch [file2.sch [file3.sch ... ] ]\n"; 320 print "\t$pname -h|--help\n"; 321 print "\t$pname -V|--version\n"; 322 print "\n"; 323 print "$pname reads a PADS PowerPCB ECO file and backannotates changes\n"; 324 print "to a gEDA schematic.\n"; 325 print "\n"; 326 print "$pname accepts the following options:\n"; 327 print "\n"; 328 print " -h|--help Displays this help message.\n"; 329 print "\n"; 330 print " -n|--nocopy If given, this flag leaves the modified files in new files\n"; 331 print " whose names are generated by appending a \".new\" to the\n"; 332 print " original file names. The default is to overwrite the original.\n"; 333 print "\n"; 334 print " -v|--verbose Enables verbose output.\n"; 335 print "\n"; 336 print " -V|--version Shows the version of this program.\n"; 337 print "\n\n"; 338 print "$pname was written by Dan McMahill <dmcmahill\@netbsd.org>\n"; 339 print "\n\n"; 340 exit; 341} 342 343#--------------------------------- 344# version() 345# 346# prints program version 347#--------------------------------- 348 349sub version { 350 open(PROG,"$0") or die "Could not open \"$0\" to find version\n\n"; 351 my $pname = $0; 352 $pname =~ s/.*\///g; 353 354 while($line = <PROG>) { 355 if( $line =~ /^#\s*\$Id.*\$/) { 356 @words = split ' ',,$line; 357 $version = $words[3]; 358 $date = $words[4]; 359 print "$pname ($0): Version $version, $date\n"; 360 exit; 361 } 362 } 363 print "Could not determine version of \"$0\"\n\n"; 364 exit; 365} 366 367# ---------------------------------------------- 368# 369# Change Log 370# 371# $Log$ 372# Revision 1.1 2003-08-31 21:39:52 ahvezda 373# Added pads_backannotate perl script 374# 375# Revision 1.4 2003/07/19 04:34:55 dan 376# bring this program up to a usable state. Refdes renumbering is fully 377# supported and pin/gate swapping while not supported, gives a report of 378# the manual swaps needed. 379# 380# Revision 1.3 2003/03/03 03:44:26 dan 381# Finish up code to handle the RENPART .eco directive. The output files 382# are still not written, but everything else is in place to handle backannotation 383# of reference designator renumbers. 384# 385# Revision 1.2 2003/02/21 12:30:30 dan 386# fix perl path 387# 388# Revision 1.1 2003/02/19 23:31:50 dan 389# start (non functional so far) of a pads to gschem backannotation tool 390# 391# 392# 393