#!/usr/bin/perl -w #swap line 1 and 3 to use the perl debugger #!/usr/bin/perl -d:ptkdb use strict; use warnings; #use diagnostics; require 5.006; our $VERSION = do { my @r=(q$Revision: 1.9 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r }; use Getopt::Long qw(GetOptions); use GDS2; $|++; $\="\n"; ## No need to edit next line ... modified automatically by RCS #'@(#) $RCSfile: gdsdump2gds.pl,v $ $Revision: 1.9 $ $Date: 2003-12-12 14:55:44-06 $'; BEGIN { use constant TRUE => 1; use constant FALSE => 0; } ## subs used sub printUsage(); sub printVersion(); ## process command line... my $DEBUG=FALSE; my $verbose=FALSE; GetOptions( 'debug' => \$DEBUG, 'help' => \&printUsage, 'version' => \&printVersion, 'verbose' => \$verbose, ) || printUsage(); my $fileNameIn = ''; $fileNameIn = shift if ($#ARGV >= 0); my $fileNameOut = ''; $fileNameOut = shift if ($#ARGV >= 0); printUsage() if ($#ARGV >= 0); ## take care of things we need from user that were not ## supplied on command line if ($fileNameIn eq '') { my $notDone = 9; #limit for how many times we will ask while ($notDone) { printf("Dump file to read: "); $fileNameIn = ; chomp $fileNameIn; $notDone = 0 if ($fileNameIn ne ''); } printUsage() if ($fileNameIn eq ''); } if ($fileNameOut eq '') { my $notDone = 9; #limit for how many times we will ask while ($notDone) { printf("GDS2 file to create: "); $fileNameOut = ; chomp $fileNameOut; $notDone = 0 if ($fileNameOut ne ''); } printUsage() if ($fileNameOut eq ''); } if ($fileNameIn eq $fileNameOut) { print "ERROR: input and output files can not be the same."; printUsage(); } ############################################################################### ######## OK we are finally ready to go to work... :-) open(DUMP,$fileNameIn) or die "Unable to read $fileNameIn because $!"; my $gds2FileOut = new GDS2(-fileName => ">$fileNameOut"); my $compactFormat = FALSE; my $line; my $type; my $dataString; $line = ; $compactFormat = TRUE if ($line =~ m/gds2\s*{/); #} seek DUMP, 0, 0; ##reset to file beginning my $inStr=FALSE; if ($compactFormat) { while () { my $dumpLine=$_; $dumpLine=~s|^\s+||; ## make following comparisions easier... next if (m/^#/); ## see # as here-to-line-end comment next if (m/^$/); my $lines = ''; if (m/^b\s*\{\s*(\d+)[^x]+xy\s*\(([^)]+)\)\s*\}/) { #b{6 xy(1.1 4.2 1.1 1.15 3.9 1.15 3.9 4.2 1.1 4.2)} my $layer=$1; my $xy=$2; my $dt=0; $xy =~ s/\s+/ /g; $xy =~ s/^\s+//; $xy =~ s/\s+$//; if ($xy =~ m/^([\d\.\-]+)\s+([\d\.\-]+)(.*)/) { my $x = $1; my $y = $2; if ($xy !~ m/\s$x\s+$y$/) { $xy .= " $x $y"; ## closure } } if (m/\sdt(\d+)\s/) { $dt=$1; } $lines = " BOUNDARY\n LAYER $layer\n DATATYPE $dt\n XY $xy\n ENDEL\n"; } elsif (m/^p\s*\{\s*(\d+)[^x]+xy\s*\(([^)]+)\)\s*\}/) { #p{16 pt2 xy(-0.425 -0.1 -0.425 -0.425 4.825 -0.425 4.825 0.425 -0.425 0.425 -0.425 0.1)} my $layer=$1; my $xy=$2; my $dt=0; my $pt=0; my $w=0; $xy =~ s/\s+/ /g; if (m/\sdt(\d+)\s/) { $dt=$1; } if (m/\spt(\d)\s/) { $pt=$1 } if (m/\sw([\d\.]+)\s/) { $w=$1 } $lines = " PATH\n LAYER $layer\n DATATYPE $dt\n PATHTYPE $pt\n WIDTH $w\n XY $xy\n ENDEL\n"; } elsif (m/^t\s*\{\s*(\d+)[^x][^y]+\sxy\s*\(([^)]+)\)\s+'([^']+)'\}/) { #t{0 0 mc f0 bl fx m0.1 a270 xy(78.875 38.825) 'MPPD5'} my $layer=$1; my $xy=$2; my $string = $3; my $strans='0000000000000000'; $strans='1000000000000000' if (m/\sfx\s/); my $pres = '0000000000'; my $havePresentation = FALSE; if (m/\sf1\s/) { $pres .= '01'; $havePresentation = TRUE; } elsif (m/\sf2\s/) { $pres .= '10'; $havePresentation = TRUE; } elsif (m/\sf3\s/) { $pres .= '11'; $havePresentation = TRUE; } else { $pres .= '00'; $havePresentation = TRUE if (m/\sf0\s/); } ######################## if (m/\sml\s/) { $pres .= '0100'; $havePresentation = TRUE; } elsif (m/\smc\s/) { $pres .= '0101'; $havePresentation = TRUE; } elsif (m/\smr\s/) { $pres .= '0110'; $havePresentation = TRUE; } elsif (m/\sbl\s/) { $pres .= '1000'; $havePresentation = TRUE; } elsif (m/\sbc\s/) { $pres .= '1001'; $havePresentation = TRUE; } elsif (m/\sbr\s/) { $pres .= '1010'; $havePresentation = TRUE; } elsif (m/\stc\s/) { $pres .= '0001'; $havePresentation = TRUE; } elsif (m/\str\s/) { $pres .= '0010'; $havePresentation = TRUE; } else { $pres .= '0000'; $havePresentation = TRUE if (m/\stl\s/); } my $tt=0; ## text type my $pt=0; ## path type my $dt=0; ## data type my $mag=1; my $angle = 0; if (m/\sa([\d\.]+)\s/) { $angle=$1 } $xy =~ s/\s+/ /g; if (m/\stt(\d+)\s/) { $tt=$1 } if (m/\spt(\d+)\s/) { $pt=$1 } if (m/\sm([\d\.]+)\s/) { $mag=$1 } $lines = " TEXT\n LAYER $layer\n TEXTTYPE $tt\n"; $lines .= " PRESENTATION $pres\n" if ($havePresentation); $lines .= " PATHTYPE $pt\n STRANS $strans\n MAG $mag\n"; $lines .= " ANGLE $angle\n" if ($angle != 0); $lines .= " XY $xy\n STRING '$string'\n ENDEL\n"; } elsif (m/^s{'([^']+)'\s.*xy\s*\(([^)]+)\)\s*\}/) { #s{'CC1804CD_1' xy(2.5 37.125)} my $name=$1; my $xy=$2; $xy =~ s/\s+/ /g; my $angle = 0; my $mag = 1; my $strans='0000000000000000'; $strans='1000000000000000' if (m/\sfx\s/); if (m/\sm([\d\.]+)\s/) { $mag=$1 } if (m/\sa([\d\.]+)\s/) { $angle=$1 } $lines = " SREF\n SNAME '$name'\n STRANS $strans\n MAG $mag\n"; $lines .= " ANGLE $angle\n" if ($angle != 0); $lines .= " XY $xy\n ENDEL\n"; } elsif (m/^a{'([^']+)'[^c]+cr\s*\(([^)]+)\)\s+xy\s*\(([^)]+)\)\s*\}/) { #a{'CC1804CD_1' a270 cr(41 3) xy(119.85 52.225 119.85 11.225 122.85 52.225)} my $name=$1; my $cr=$2; my $xy=$3; $cr =~ s/\s+/ /g; $xy =~ s/\s+/ /g; my $angle = 0; my $mag = 1; my $strans='0000000000000000'; $strans='1000000000000000' if (m/\sfx\s/); if (m/\sm([\d\.]+)\s/) { $mag=$1 } if (m/\sa([\d\.]+)\s/) { $angle=$1 } $lines = " AREF\n SNAME '$name'\n STRANS $strans\n MAG $mag\n"; $lines .= " ANGLE $angle\n" if ($angle != 0); $lines .= " COLROW $cr\n XY $xy\n ENDEL\n"; } elsif (m/^cell\s*\{\s*c=(\d+)\-(\d+)\-(\d+)\s+(\d+):(\d+):(\d+)\s+m=(\d+)\-(\d+)\-(\d+)\s+(\d+):(\d+):(\d+)\s+'([^']+)'/) ##} { #cell{c=1998-08-17 14:31:10 m=1998-08-17 14:33:47 'CC1804_R1' ##} $lines = sprintf("BGNSTR %d %d %d %d %d %d %d %d %d %d %d %d\n STRNAME '%s'\n", $1 > 1900?($1 - 1900):$1, $2,$3,$4,$5,$6, $7 > 1900?($7 - 1900):$7, $8,$9,$10,$11,$12, $13, ); $inStr = TRUE; } elsif ($dumpLine =~ m/^}$/) { # if ($inStr) { $lines = "ENDSTR\n"; } else { $lines = "ENDLIB\n"; } $inStr = FALSE; } elsif (m/^[cm]=(\d+)\-(\d+)\-(\d+)\s+(\d+):(\d+):(\d+)\s+[am]=(\d+)\-(\d+)\-(\d+)\s+(\d+):(\d+):(\d+)/) { #c=1998-08-11 13:09:15 m=1998-09-15 11:34:10 $lines = sprintf("BGNLIB %d %d %d %d %d %d %d %d %d %d %d %d\n", $1 > 1900?($1 - 1900):$1, $2,$3,$4,$5,$6, $7 > 1900?($7 - 1900):$7, $8,$9,$10,$11,$12, ); } elsif (m/^lib\s+'([^']+)'\s+(\S+)\s+(\S+)/) { #lib 'cc1804' 0.001 1e-9 $lines = "LIBNAME '$1'\nUNITS $2 $3\n"; } elsif ($dumpLine =~ m/^gds2\s*\{\s*(\d+)$/) { #gds2{600 #} $lines = "HEADER $1\n"; } else { print STDERR "ERROR: bad line $_"; exit 4; } printf STDERR "$lines" if ($verbose); $lines =~ s/\n/ \n/gs; foreach $line (split("\n",$lines)) { $line=~s|^\s+||; if ($line =~ m|^([a-z]+) (.*)|i) { $type=$1; $dataString=$2 if (defined $2); $gds2FileOut -> printGds2Record(-type=>$type,-asciiData=>$dataString) } else { print "WARNING: Unable to parse '$line'"; } } } } else { while () { $line=$_; $line=~s|^\s+||; ## make following comparisions easier... next if (m|^#|); ## see # as here-to-line-end comment chomp $line; $line=~s|#.*||; $line=~s|$| |g; ## for match below $dataString=''; if ($line =~ m|^([a-z]+) (.*)|i) { $type=$1; $dataString=$2 if (defined $2); $gds2FileOut -> printGds2Record(-type=>$type,-asciiData=>$dataString) } else { print "WARNING: Unable to parse '$line'"; } } } $gds2FileOut -> close; close DUMP; exit 0; ## subroutines... ################################################################################ sub printVersion() { print $VERSION; exit 0; } ################################################################################ sub printUsage() { print <::= HEADER BGNLIB [LIBDIRSIZE] [SRFNAME] [LIBSECR] # # LIBNAME [REFLIBS] [FONTS] [ATTRTABLE] [GENERATIONS] # # [] UNITS {}* ENDLIB # # # # ::= FORMAT | FORMAT {MASK}+ ENDMASKS # # # # ::= BGNSTR STRNAME [STRCLASS] {}* ENDSTR # # # # ::= { | | | | | # # | }* ENDEL # # # # ::= BOUNDARY [ELFLAGS] [PLEX] LAYER DATATYPE XY # # # # ::= PATH [ELFLAGS] [PLEX] LAYER DATATYPE [PATHTYPE] # # [WIDTH] XY # # # # ::= SREF [ELFLAGS] [PLEX] SNAME [] XY # # # # ::= AREF [ELFLAGS] [PLEX] SNAME [] COLROW XY # # # # ::= TEXT [ELFLAGS] [PLEX] LAYER # # # # ::= TEXTTYPE [PRESENTATION] [PATHTYPE] [WIDTH] [] XY # # STRING # # # # ::= STRANS [MAG] [ANGLE] # # # # ::= NODE [ELFLAGS] [PLEX] LAYER NODETYPE XY # # # # ::= BOX [ELFLAGS] [PLEX] LAYER BOXTYPE XY # # # # ::= PROPATTR PROPVALUE # ################################################################################ =head2 example file HEADER 3 BGNLIB 99 8 4 20 36 16 100 4 18 17 14 16 LIBNAME 'and2b' UNITS 0.001 1e-09 BGNSTR 96 1 16 12 47 41 96 1 16 12 47 41 STRNAME 'AND2B' BOUNDARY LAYER 10 DATATYPE 0 XY 8.2 -2.1 8.2 9.1 -2.1 9.1 -2.1 -2.1 8.2 -2.1 ENDEL SREF SNAME 'FMARK' XY 0 0 ENDEL TEXT LAYER 59 TEXTTYPE 0 PRESENTATION 0000000000001000 PATHTYPE 0 STRANS 0000000000000000 MAG 0.1 XY 2.05 1.4 STRING 'VDD' ENDEL ENDSTR BGNSTR 96 1 16 12 47 41 96 1 16 12 47 41 STRNAME 'FMARK' PATH LAYER 0 DATATYPE 0 PATHTYPE 0 WIDTH 0 XY -0.7 -0.7 1.4 1.4 2.8 1.4 ENDEL PATH LAYER 0 DATATYPE 0 PATHTYPE 0 WIDTH 0 XY -0.7 0.7 0.7 -0.7 ENDEL PATH LAYER 0 DATATYPE 0 PATHTYPE 0 WIDTH 0 XY 0.7 0.7 1.75 0.7 ENDEL ENDSTR ENDLIB =cut