Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / perlmod / pal / 1.13 / bin / pal
CommitLineData
86530b38
AT
1: # -*- perl -*-
2eval 'exec $PERL_CMD -S $0 ${1+"$@"}'
3 if 0;
4
5use FindBin;
6use File::Spec;
7
8#
9# PAL: Perl Augmented Language.
10#
11
12$VERSION= '1.13';
13$COMBINE_CONTINUATION= 0; #lines ended with \ printed as it is
14
15$prog= &basename($0);
16($PROG= $prog)=~ tr/a-z/A-Z/;
17
18$PERL = $ENV{PERL_CMD};
19if(not defined $PERL) {
20 $PERL= "/usr/perl5/bin/perl"; #path for perl5; site dependent
21 # warn "WARNING: BW_PERL not defined, using $PERL.\n";
22}
23$BASE= "$FindBin::Bin/.."; #released path
24$RUNTIME= "${PROG}_runtime.pl";
25if ($^O eq 'solaris') {
26$INCLUDE_CMD= "$FindBin::Bin/include";
27}
28if ($^O eq 'linux') {
29$INCLUDE_CMD= "$FindBin::Bin/include.linux";
30}
31$OUTPUT_DIR= "."; # default output directory
32
33$,= ' ';
34$USER= $ENV{'USER'} || getlogin() || (getpwuid($<))[0] ;
35
36
37@ARGV_save= @ARGV;
38& initialize(); #may change BASE
39
40if(! $QUIET) {
41# $cmd= "echo \"`date +%m/%d/%y:%H`: $prog @ARGV\" >> $BASE/Log/$USER";
42# $cmd.= "; chmod 660 $BASE/Log/$USER" ;
43# system( $cmd );
44 }
45
46#Run cpp on the input file to expand #includes and __LINE__.
47#The reason we can't use the perl option that runs cpp before running perl
48#is because after running cpp, we have to do some massaging on output file.
49
50### process only '#inc' as include directive :
51
52if(1) { #direct pipe.
53$cmd= "$INCLUDE_CMD -i '#inc' -pal $include_string $infile ";
54open(PP_FILE, " $cmd |") or die "Can't open pipe from '$cmd' $!\n"; #preprocessed file as input
55}else{ #write to a file first.
56$cmd= "$INCLUDE_CMD -i '#inc' -pal $include_string $infile > $infile_pp";
57& EXIT2(1, $cmd) if( system("$cmd") ) ;
58open(PP_FILE, "< $infile_pp") or die "Can't open '$infile_pp' $!\n"; #preprocessed file as input
59}
60
61open(PL_FILE, "> $infile_pl") or die "Can't write '$infile_pl' $!\n"; #translated (perl) output
62
63print PL_FILE "#! $PERL \n"; #make perl code executable
64print PL_FILE "# Translated Perl code from '$0 @ARGV_save'\n\n";
65
66for($i= 0; $i< @INCLUDE; $i++) {
67 print PL_FILE "unshift(\@INC, '$INCLUDE[$i]');\n";
68 }
69print PL_FILE "srand($SEED);\n" if($SEED);
70print PL_FILE "\$BASE= '$BASE';\n";
71print PL_FILE "use lib '$FindBin::Bin/../lib';\n";
72print PL_FILE "require \'$RUNTIME';\n";
73
74& LINES_TO_PERL ();
75
76close(PP_FILE);
77close(PL_FILE);
78chmod(0750, $infile_pl);
79
80if($keep_tmpFile != 2) {
81 if ( $outputFile ) {
82 $attach= " > $outputFile" if($outputFile);
83 # Make sure current dir is writable, since we'll be generating temp files.
84 & EXIT2(1, "Output directory '$OUTPUT_DIR' must be writable")
85 if(! -w $OUTPUT_DIR);
86 }
87 # print STDERR "execute: $infile_pl @ARGV $attach \n";
88 if( system("$PERL $infile_pl @ARGV $attach") ) {
89 &EXIT2(1, "Can't execute $infile_pl @ARGV $attach");
90 }
91}
92
93&cleanup();
94
95
96
97################################################################################
98# initialize & process cmd-line arguments
99################################################################################
100sub process_cmdline {
101my($PERLOPTIONS) = '';
102my $ofile;
103
104while(substr($ARGV[0],0,1) eq '-' || $ARGV[0]=~ /^([A-Za-z_]\w*=)(.*)/) {
105 my($arg)= shift(@ARGV);
106
107 # [Viranjit 11/21/03]
108 if ( $arg =~ /^(-\S+)=(.+)/ ) { # handle -<opt>=<val>
109 $arg = $1; # convert to -<opt> <val>
110 unshift @ARGV, $2;
111 }
112
113 if( substr($arg,0,1) ne '-') { #set var from cmd-line
114 $EVAL_STR .= "\$$1$2;\n"; # process "foo= bar"
115 }elsif($arg eq '-base') { #change base to non-default place
116 $BASE= shift(@ARGV); # for experimenting new version.
117 }elsif($arg eq '-h' || $arg eq '-help') {
118 & EXIT(0);
119 }elsif($arg eq '-H' || $arg eq '-HELP') {
120 & EXIT(0);
121 # & INFO(); exit(0);
122 }elsif($arg eq '-I') {
123 @INCLUDE= (@INCLUDE, shift(@ARGV));
124 }elsif($arg eq '-k' || $arg eq '-keep') {
125 $keep_tmpFile= 1;
126 }elsif($arg eq '-ko' || $arg eq '-keeponly') {
127 $keep_tmpFile= 2;
128 }elsif($arg eq '-o') {
129 $outputFile= shift(@ARGV); #user-given output file
130 (undef, $OUTPUT_DIR, $ofile) =
131 File::Spec->splitpath( $outputFile );
132 $OUTPUT_DIR = "." if $OUTPUT_DIR eq "";
133 }elsif($arg eq '-q' || $arg eq '-quiet') {
134 $QUIET= 1;
135 }elsif($arg eq '-R' || $arg eq '-REVERSE') {
136 $REVERSE= shift(@ARGV); #user-def reverse char
137 }elsif($arg eq '-r' || $arg eq '-reverse') {
138 $REVERSE= "\\\."; #default reverse char: '.'
139 }elsif($arg eq '-s' || $arg eq '-seed') {
140 $SEED= shift(@ARGV); #set random seed
141 }elsif($arg eq '-w') {
142 $PERLOPTIONS .= ' -w';
143 }elsif($arg eq '-perl') {
144 my($newperl)= shift(@ARGV);
145 if (-x $newperl) {
146 $PERL = $newperl;
147 }
148 }
149 }
150 $PERL .= $PERLOPTIONS if ($PERLOPTIONS ne '');
151}
152
153sub EXIT2 { & EXIT(@_, 'NoUsage'); }
154
155sub EXIT {
156 my($errCode, $errStr, $NoUsage)= @_;
157 print STDERR "$PROG ERR (line $.): $errStr\n" if($errStr);
158 & usage() if(! $NoUsage);
159 & cleanup();
160 exit($errCode);
161}
162
163sub initialize {
164 #reset all control variables :
165 @INCLUDE= ();
166 $REVERSE= ''; #default: no reverse mode
167
168 & EXIT(1) if($#ARGV == -1);
169
170 & process_cmdline(); #process argv before input file
171
172 & EXIT(0, "Missing input file") if($#ARGV < 0);
173
174 $infile= shift(@ARGV);
175 my($name)= &basename($infile);
176 $infile_pp= "/usr/tmp/$name.$$.pp"; #after preprocess
177 $infile_pl= "/usr/tmp/$name.$$.pl"; #after xlating to perl
178
179## & process_cmdline() if($#ARGV >= 0); #after input file
180# & EXIT(1, "Cmd-Line error") if($#ARGV >= 0) ;
181
182 # Check suffix of input file and make sure it exists.
183 if($infile !~ /\.[^\.]*(pal|pm|tg)$/i && #no .pal|.pm|.tg suffix, and
184 ! $REVERSE) { # not start w/ reverse mode
185 & EXIT2(1, "$infile must be ended with '.*(pal|pm|tg)'");
186 }
187 & EXIT2(1, "$infile does not exist") if(! -r $infile);
188
189 # Make sure include directories exist.
190 for($i= 0; $i < @INCLUDE; $i++) {
191 if(! -d $INCLUDE[$i]) {
192 & EXIT2(1, "Directory $INCLUDE[$i] does not exist");
193 }else{
194 $include_string = $include_string . " -I $INCLUDE[$i]";
195 }
196 }
197
198}
199
200
201sub LINES_TO_PERL { #translate all lines to perl
202my($REVERSE_save);
203
204$curr_linenum= 0;
205$REVERSE_save= $REVERSE;
206
207$INIT= 1;
208$line= '';
209$currLineType= '';
210while(<PP_FILE>) { #read input file, and do some filtering
211 if(/^# line (\d+) (.*)/) {
212 $curr_linenum= $1 - 1; # -1 because the line itself is following
213 $curr_file= $2;
214 print PL_FILE $_;
215 next;
216 }else{
217 ++ $curr_linenum;
218 }
219 if(/^$REVERSE#+\s*(END_INIT|ENDINIT)/ && $INIT) { # put "foo=bar" after #END_INIT
220 s/^$REVERSE//;
221 print PL_FILE "$_";
222 print PL_FILE $EVAL_STR;
223 $INIT= 0;
224 next;
225 }
226 if($line ne '') { #this is a continued line: strip its prefix
227 if( $currLineType ne &lineType($_) ) {
228 &EXIT2(1, "prefix of continued line doesn't match previous line");
229 }
230 s/^://;
231 s/^$REVERSE// if($REVERSE ne '');
232 }
233 if($COMBINE_CONTINUATION==1 && s/\\\s*$// ) {
234 #line ended w/ \, cat to previous line
235 $currLineType= &lineType($_) if(! $currLineType);
236 $line.= $_;
237 next;
238 }elsif($COMBINE_CONTINUATION==2 &&
239 ((! /#define/) && s/\\\s*$/\n/) ) {
240 #ended w/ \, and not #define
241 $currLineType= &lineType($_) if(! $currLineType);
242 $line.= $_;
243 next;
244 }
245
246
247 $line.= $_; #concate w/ potential previous lines
248 $line_save= $line;
249 & line_to_perl(*line); #change :-lines to perl print stmt
250 if($line_save ne $line) {
251 $line=~ s/\n(.)/\n# line $curr_linenum $curr_file\n$1/g;
252# print PL_FILE "# line $curr_linenum $curr_file\n" if($line =~ /\n./);
253 }
254 print PL_FILE "$line";
255 $line= ''; #reset only after a 'line' is complete
256 $currLineType= '';
257 }
258}
259
260
261sub lineType {
262my($line)= @_;
263my($prefix)= substr($line,0,1);
264my($typ)=
265 ($prefix eq ':') && ($MODE eq 'PLAIN' || $REVERSE eq '') ? ':' :
266 ($prefix eq $REVERSE) && ($REVERSE ne '') ? $REVERSE :
267 'x' ;
268$typ;
269}
270
271
272#
273# Massage the cpp output file to
274# replace lines beginning with ":" with print statements
275# replace single quote with backslash quote
276# replace '\n' with '\\n'
277# massage some of the spacing.
278
279sub line_to_perl { #translate 1 line to perl stmt
280local(*line) = @_;
281my($print_linenum)= 1;
282my($i);
283
284 if($MODE eq 'PLAIN') { #===> complete_as_is (plain) TEXT mode:
285 # if($line =~ s/^[ \t]*://) { #text stuff
286 if($line =~ s/^://) { #text stuff
287 $line= & PASS_AS_IS( $line );
288 }elsif($REVERSE ne '' && $line =~ s/^$REVERSE//) { #perl stmt
289 & check_mode_switch(*line);
290# }elsif($line =~ /^#/) { #cpp-generated stuff: pass
291# ; # unchanged as perl comment
292 }elsif($line =~ s/^\\#/#/) { #text escaped comment: put back
293 $line= & pass_as_is( $line ) ; #plain text
294 }else{ $line= & pass_as_is( $line ) ; } #plain text
295
296 }elsif($REVESE ne ';' && $line =~ s/^;//) { #===> complete_as_is TEXT mode:
297 ## ';' in first column: NOT even perl variable will be evaluated
298 ## Note that: perl variables still evaluated in ordinary TEXT mode
299 $line= & pass_as_is( $line ) ;
300
301 }elsif($REVERSE eq '') { #==> PERL mode: text needs prefix w/ ':'
302 if($line =~ s/^://) { #rm text-prefix up to ':'
303 $line= & PASS_AS_IS( $line ); #text
304 }else{
305 & check_mode_switch(*line); #perl stmt
306 }
307 }else { #==> TEXT mode: perl code prefixed w/ $REVERSE
308 if($line =~ s/^$REVERSE//) { #perl stmt: remove prefix
309 & check_mode_switch(*line);
310
311# }elsif($line =~ /^\s*#/) { #cpp-generated stuff: pass
312# ; # unchanged as perl comment
313 }elsif($line =~ s/^\\#/#/) { #text escaped comment: put back
314 $line= & PASS_AS_IS( $line ) ; #AS_IS line
315 }else{ $line= & PASS_AS_IS( $line ) ; #AS_IS line
316 }
317 }
318}
319
320sub check_mode_switch { #mode-switch command: start_perl, and
321local(*line)= @_; # start_text[(reverse_string)]
322
323if($line=~ /^\s*#/) { #comment at the begin:
324 ;
325}elsif($line=~ /^\s*start_plain/) { #switch to pure text mode
326 $MODE= 'PLAIN';
327 $line= ''; #nullify the line
328}elsif($line=~ /^\s*start_perl/) { #switch to perl mode
329 $REVERSE_save= $REVERSE; #save prev REVERSE char
330 $REVERSE= ''; #clear REVERSE
331 $MODE= '';
332 $line= ''; #nullify the line
333}elsif($line=~ s/^\s*start_text//) {
334 if($line=~ s/\s*\((.*)\)//) { #switch to text mode
335 $REVERSE= "$1"; #use specified $REVERSE
336 }elsif($REVERSE_save ne '') {
337 $REVERSE= $REVERSE_save; #use prev $REVERSE
338 }else{
339 $REVERSE= "\\\."; #use default $REVERSE
340 }
341 $line= ''; #nullify the line
342 $MODE= '';
343}else{ my($prefix_stmt)= & proc_SELECTION(*line);
344 $line= $prefix_stmt . $line;
345 }
346$line;
347}
348
349
350sub pass_as_is { #COMPLETELY as is: nothing will be evaluated
351my($line)= @_ ;
352
353$line =~ s/\n$//; # get rid of \n, if any.
354$line =~ s/\\/\\\\/g; # change \ to \\; to print as \
355$line =~ s/'/\\'/g; # replace quote w/ 'backslash quote'
356#$line = "print \"\\n\", \'$line\';\n"; #enclose $line w/ ': no escaped needed
357$line = "print \'$line\', \"\\n\";\n"; #enclose $line w/ ', so no escaped needed
358}
359
360
361sub PASS_AS_IS { #everything EXCEPT PERL $ variables appear as is
362local($line)= @_; #perl variable is evaluated to its value;
363 #so only $ need be escaped by programmer.
364
365$line=~ s/\n$//; # get rid of \n
366
367my($prefix_stmt)= & proc_SELECTION(*line, 1);
368
369### only '\' and " need be escaped !!
370$line =~ s/\\/\\\\/g; # change \ to \\ for printing as \
371$line =~ s/"/\\"/g; # change " to \" for printing as "
372
373### preseve $ as $; so when printed, it is perl variable.
374### preseve \$ as \$; so when printed, it is '$' . {...}.
375### preseve $$ as $$; so when printed, it is process id.
376$line =~ s/\\\\([\[\$\@\]])/\\$1/g; # put \\$ back to \$; to print as $
377
378#$line = $prefix_stmt . "print \"\\n$line\";\n";
379$line = $prefix_stmt . "print \"$line\\n\";\n";
380
381}
382
383#------------------- [[....]] is selection list which randomly choose element
384#------------------- [e[...]] is enumeration list which choose elements in order
385#------------------- [l[...]] return the number of elements in the list
386
387sub proc_SELECTION { #process selection list [e?[...]]
388local(*string, $func_sub)= @_; #string is either text or perl stmt.
389my($list, $cmd); #list is stuff within [e?[ and ]]
390my($sel_stmt, $fun_stmt);
391my($acc);
392
393$acc= '';
394########## selection list replacement:
395while( 1 ) { ###--replace next [..[..]] to a $variable
396 last if($string !~ /\[([\w ,:]*)\[([^\]]*)\]\]/) ;
397########### [ cmd [ .list. ] ]
398 ++ $list_idx; #GLOBAL: increment after done with it
399 $acc .= $` . "\$\{_PARAM$list_idx\}"; #become a variable
400 $string = $'; #process rest later
401
402 $cmd= $1;
403 $list= "$2";
404 $list=~ s/([^\\])"/$1\\"/g; # escape non-escaped "
405 $list=~ s/^"/\\"/;
406 $list=~ s/\n//g; # remove all new-line char
407
408 my($ln)= $curr_linenum - 1;
409 ##--- $_PARAMn is delay-evaluated until the last run, where all
410 ##----- $perl variables in [[..]] list are evaluated else where.
411 $sel_stmt .= "\$_PARAM$list_idx= &proc_SEL($list_idx, \"[$list]\", \"$cmd\", \"$curr_file:$ln\");\n";
412 }
413
414$string= $acc . $string;
415$acc= '';
416########## function call replacement in 'text string':
417if( $func_sub ) {
418 while(1) {
419 last if($string !~ /(.)?\&\s*([a-zA-Z_]\w*\s*\([^\)]*\))/ );
420### & ---funcName-- ( ..... )
421 $match= $&;
422 if($1 eq '\\') {
423 $string= $'; #set before another substitute.
424 $acc .= $`;
425 $match =~ s/^.//; #un-escape \& to &.
426 $acc .= $match;
427 next;
428 }
429 ++ $func_idx;
430 $acc .= $` . "$1\$\{_RETURN$func_idx\}";
431 $string = $'; #remaining part
432 $fun_stmt .= "\$_RETURN$func_idx= & $2;\n";
433 }
434 }
435# $fun_stmt=~ s/\\"/"/g; #un-escape \"
436# $fun_stmt=~ s/\\\\/\\/g; #un-escape \\
437
438$string= "$acc" . "$string"; # substitute orignal stmt
439
440$sel_stmt . $fun_stmt; #### return prefix stmt: proc_SEL() + func-call
441}
442
443
444################################################################################
445# cleanup
446################################################################################
447sub cleanup { # remove .pp and .pl files when no -k option
448if($keep_tmpFile) {
449 my($targ)= &basename($infile_pl);
450 $targ=~ s/$$\.//;
451 $targ= File::Spec->catfile( $OUTPUT_DIR, $targ) if $OUTPUT_DIR ne ".";
452 system("mv $infile_pl $targ");
453}else{
454 unlink($infile_pp) if(-f $infile_pp);
455 unlink($infile_pl) if(-f $infile_pl);
456 }
457}
458
459
460################################################################################
461# usage and INFO
462################################################################################
463sub usage {
464my(@version)= split(' ', $VERSION);
465print <<EOF;
466Usage: $prog [options] {file.$prog} [{\@ARGV for file.$prog}]
467 options:
468 {var}={expr} will set ${var} to {expr} after "^#END_INIT", before
469 which is the place to give default values.
470 -h(elp) print usage information.
471 -I <include_dir> add <include_dir> to search path for #includes.
472 -k(eep) keep temporary files after run.
473 -ko|-keeponly generate temporary files and exit.
474 -o <outfile> output assembly language to <outfile>.
475 -perl <file> Change the default perl version use to <file>.
476 -r(everse) reverse to TEXT mode by treating lines prefixed w/ '.'
477 as perl stmt, the rest are output unchanged.
478 -R '{prefix}' same as -r except perl-prefix set to {prefix};
479 char special to regular expression need be escaped.
480 -s(eed) {number} set random number seed by calling 'srand({number})'.
481'$PROG', Perl extended Language, is a macro language based on Perl.
482Version: 1.00.
483EOF
484
485# -H(ELP) more info about $PROG extension: reverse mode,
486# string/number selection/enumeration, etc.
487#end of print <<EOF;
488}
489
490sub INFO {
491print <<EOF;
492 List substitution: same as what CHAOS accepted
493 1. [[....]]: selection; replace the whole thing with a randomly
494 selected element from the ... list.
495 2. [e[...]]: enumeration; replace the while thing with the NEXT
496 element from the ... list.
497 3. [l[...]]: length; replace the whole thing with the number of
498 elements of the ... list.
499 4. Type of list:
500 a. number list: [[0, 2, 4-9, 11-13]]
501 b. string list: [[bc1f, bc1t, bc1fl, bc1tl]]
502 About MODE: perl, text, and plain-text";
503 The original testgen is always in perl mode where all lines are perl
504 stmt by default. Only those prefixed with ':' are output as is with
505 perl variables evaluated. $PROG can switch mode bewteen perl and
506 text. In perl mode, text needs be prefixed with ':' just like in
507 testgen. In text mode, all lines are text by default. Perl stmt
508 need be started with perl-prefix, whose default is '.'. It can
509 be set to something else by using -R option. To make life more
510 versatile (or complicated :-), $PROG can switch modes on the fly.
511 Two pseudo perl functions are added for the purpose:
512 start_perl and start_text[({new_perl_prefix})]
513 Start_perl switches to perl mode and to comply with testgen, the
514 text-prefix is always ':'. Start_text switches to text mode with
515 perl-prefix set to either previous perl-prefix or {new_perl_prefix}
516 if specified. NOTE: perl-prefix is to process as regular expression.
517 Appropriate escape is needed. Here are Examples to set . and []
518 as perl-prefix:
519 $prog -R '\\.' and $prog -R '\\[\\]' on the command line, and
520 start_text(\\.) and start_text(\\[\\]) on your .tg file.
521 In text mode, perl variables are still evaluated. To prevent that,
522 a pure text mode is added which must always be prefixed with ';'
523 if it is not used as perl_prefix.
524 Other differences in TEXT lines:
525 '\$': In testgen, '\$' if not for perl variables is escaped with \$\$;
526 in $PROG, it is escaped with more conventional \\\$.
527 '#': .tg file is first fed to cpp for macro processing.
528 So, '#' can't appear in the 1st column even in text
529 mode unless it is escaped with \\.
530 leading spaces: In testgen, spaces following ':' are replaced with
531 1 blank; in $PROG, they survive to maintain original indent.
532EOF
533 # end of prnt <<EOF;
534}
535
536
537sub basename {
538 my($name) = @_;
539 my( $basename ) = "";
540 split(/\//, $name);
541 $basename = pop @_;
542## $basename =~ s/,.*$//;
543 return($basename);
544 }
545
5461;
547