view pygar-benchmarks/setup/run-sim.bmark @ 69:5c963ab14143 pygar svn.70

[svn r70] added an attempt at multi-fileing
author punk
date Wed, 12 May 2010 00:07:40 -0400
parents 0ede0715dbd6
children
line wrap: on
line source
1 #!/usr/bin/env perl
2 # -*- perl -*-
4 use strict;
5 use warnings;
6 use Getopt::Long qw(:config no_auto_abbrev no_ignore_case pass_through);
7 use IO::Pty;
9 #
10 # Turn on warnings
11 #
12 $^W = 1;
14 ##
15 ## Benchmark run script
16 ##
18 sub ExecModel($);
19 sub Exec($$);
20 sub CompareOutput();
21 sub ReadConfig($$);
24 #############################################################################
25 #############################################################################
26 ##
27 ## Start by figuring out the model location and type.
28 ##
29 #############################################################################
30 #############################################################################
32 my %config;
34 ReadConfig("config/env.sh", 1);
35 ReadConfig("$config{modelDir}/config/env.sh", 1);
36 ReadConfig("$config{modelDir}/config/signature.sh", 0);
38 ##
39 ## Pseudo-enumeration of possible model types
40 ##
41 my $MODEL_NONE = 0;
42 my $MODEL_FPGA = 1; # Model runs on FPGA hardware
43 my $MODEL_BLUESIM = 2; # Bluesim
44 my $MODEL_VSIM = 3; # Verilog simulator
46 my $mType = $MODEL_NONE;
49 #############################################################################
50 #############################################################################
51 ##
52 ## Process command line arguments
53 ##
54 #############################################################################
55 #############################################################################
57 my $help = 0;
58 my $onlyCompare = 0;
59 my $noCompare = 0;
60 my $forceLoad = 0;
61 my $gdb = 0;
62 my $noProgram = 0;
63 my $noReserve = 0;
64 my $funcpPrefix = "";
65 my $funcpSuffix = "";
66 my $noshowfp = 0;
67 my $printCycle = undef;
68 my $showfp = undef;
69 my $bluesimCmd = undef;
70 my $vcdStart = undef;
71 my $vcdCycles = 20000;
72 my $m5run = 0;
74 my $status = GetOptions("help!" => \$help,
75 "gdb!" => \$gdb,
76 "noprogram!" => \$noProgram,
77 "noreserve!" => \$noReserve,
78 "force-load!" => \$forceLoad,
79 "funcp-prefix=s" => \$funcpPrefix,
80 "funcp-suffix=s" => \$funcpSuffix,
81 "noshowfp!" => \$noshowfp,
82 "onlycompare!" => \$onlyCompare,
83 "nocompare!" => \$noCompare,
84 "pc=s" => \$printCycle,
85 "showfp:s" => \$showfp,
86 "bluesim=s" => \$bluesimCmd,
87 "vcdstart=i" => \$vcdStart,
88 "vcdcycles=i" => \$vcdCycles,
89 "m5!" => \$m5run,
90 );
92 # Put quotation marks back on arguments that have spaces since they will be
93 # passed through a shell once more.
94 foreach my $i ( 0 .. $#ARGV ) {
95 if (($ARGV[$i] =~ /\s/) && ! ($ARGV[$i] =~ /['"]$/)) {
96 $ARGV[$i] = '"' . $ARGV[$i] . '"';
97 }
98 }
100 if ($onlyCompare != 0) {
101 exit(CompareOutput());
102 }
104 if ($m5run != 0) {
105 $mType = $MODEL_NONE;
106 }
107 elsif (-f "$config{modelDir}/$config{model}_hw.errinfo") {
108 $mType = $MODEL_FPGA;
109 }
110 elsif (-f "$config{modelDir}/$config{model}_hw.exe") {
111 $mType = $MODEL_BLUESIM;
112 }
113 elsif (-f "$config{modelDir}/$config{model}_hw.vexe") {
114 $mType = $MODEL_VSIM;
115 }
116 else {
117 die("Can't determine model type");
118 }
120 if ($help || ! $status) {
121 print STDERR "\nArguments:\n";
122 print STDERR " [--gdb] Invokes the software side in gdb\n";
123 print STDERR " [--noprogram] Skips the FPGA load and reservation steps\n";
124 print STDERR " [--noreserve] Skips the FPGA reservation steps\n";
125 print STDERR " [--funcp-prefix=\"<prefix>\"]\n";
126 print STDERR " Prepend prefix to HAsim's --funcp argument\n";
127 print STDERR " [--funcp-suffix=\"<suffix>\"]\n";
128 print STDERR " Append suffix to HAsim's --funcp argument\n";
129 print STDERR " [--onlycompare] Only compare output files (without running)\n";
130 print STDERR " [--nocompare] Skip comparison of output files\n";
131 print STDERR " [--m5] Run workload in m5 without HAsim\n";
133 if ($mType == $MODEL_FPGA) {
134 print STDERR " [--force-load] Load a bitfile to the FPGA even if it has errors\n";
135 }
137 if ($mType == $MODEL_BLUESIM) {
138 print STDERR " [--vcdstart=<cycle>] Generate VCD dump for wave viewer (e.g. gtkwave)\n";
139 print STDERR " [--vcdcycles=<cycles>] VCD dump length (default = 20000)\n";
140 }
142 if ($config{isHybridModel}) {
143 my $cmd = "$config{modelDir}/$config{model} --help-run-append";
144 system($cmd);
145 }
147 exit(1);
148 }
150 #############################################################################
151 #############################################################################
152 ##
153 ## Adjust model arguments
154 ##
155 #############################################################################
156 #############################################################################
158 # Show front panel?
159 if ($noshowfp) {
160 $showfp = 'none';
161 }
162 elsif (defined($showfp)) {
163 # Specified on the run command line
164 $showfp = 'gui' if ($showfp eq '');
165 }
166 elsif ($config{feeder} eq 'none') {
167 # For null feeder default to showing LEDs on stdout
168 $showfp = 'stdout';
169 }
170 else {
171 # Other models have heartbeats
172 $showfp = 'none';
173 }
175 my $feedFlags = "${funcpPrefix} $config{feedFlags} ${funcpSuffix}";
177 if ($config{feeder} eq 'm5') {
178 # Tell m5 to be quiet and not to enable the remote gdb port. Under netbatch
179 # it appears there are sometimes attempts to connect to the port, which
180 # stops simulation.
181 $feedFlags = "--quiet --remote-gdb-port=0 ${feedFlags}";
182 }
184 my $cmd;
186 if ($m5run == 0) {
187 # Normal run
188 $cmd = "$config{modelDir}/$config{model} --modeldir=$config{modelDir} --workload=$config{workload} --showfp=${showfp} --funcp=\"${feedFlags}\" $config{genFlags}";
189 foreach my $c (@ARGV) {
190 $cmd .= " $c";
191 }
193 if (defined($printCycle)) {
194 $cmd .= " --pc=${printCycle}";
195 }
196 }
197 else {
198 if ($config{feeder} ne 'm5') {
199 die("This workload does not use m5");
200 }
202 # Running inside m5 without HAsim
203 my $m5cmd;
204 if (exists($ENV{M5BIN})) {
205 $m5cmd = $ENV{M5BIN};
206 }
207 else {
208 my $m5bin = "platform/m5/build/ALPHA_SE/m5." . ($gdb ? "debug" : "opt");
209 $m5cmd = `awb-resolver ${m5bin}`;
210 chomp($m5cmd);
211 die("Failed to find $m5bin") if ($m5cmd eq '');
212 }
214 $cmd = "${m5cmd} ${feedFlags}";
216 # Drop --hasim-sim
217 $cmd =~ s/--hasim-sim //;
218 # Drop escaping of quotes
219 $cmd =~ s/\\"/"/g;
221 $noProgram = 1;
222 }
224 #
225 # Bluesim arguments
226 #
228 # Generate dump.vcd for wave viewer (e.g. gtkwave)?
229 if (defined($vcdStart)) {
230 my $vcdCmd = "sim vcd on; sim step $vcdCycles; sim stop";
231 if ($vcdStart > 0) {
232 $vcdCmd = "sim step ${vcdStart}; ${vcdCmd}";
233 }
235 if (defined($bluesimCmd)) {
236 $bluesimCmd .= " ";
237 }
238 else {
239 $bluesimCmd = "";
240 }
241 $bluesimCmd .= "-c \"$vcdCmd\"";
242 }
244 if (defined($bluesimCmd)) {
245 $cmd .= " --bluesim=\'$bluesimCmd\'";
246 }
248 # Adjust the arguments for Bluesim if it is being invoked directly
249 if (! $config{isHybridModel} && ($mType == $MODEL_BLUESIM)) {
250 $cmd =~ s/\s--/ +--/g;
252 # Bluesim may expect to load a program from a well known file
253 unlink('program.vmh');
254 link("program/$config{workload}.$config{ISA}.vmh", 'program.vmh');
255 }
258 #############################################################################
259 #############################################################################
260 ##
261 ## Load the FPGA and run the model
262 ##
263 #############################################################################
264 #############################################################################
266 #
267 # Move old stats file so we are sure statistics come from this run
268 #
269 if (-f "$config{workload}.stats") {
270 rename("$config{workload}.stats", "$config{workload}.stats.old");
271 }
273 if ($mType == $MODEL_FPGA) {
274 if (! defined($printCycle)) {
275 # User didn't specify a cycle printing interval. Pick one more reasonable
276 # for HW.
277 #$cmd .= " --pc=10000000";
278 }
280 # Load FPGA
281 $ENV{FPGA_BIT_FILE} = "$config{modelDir}/.xilinx/$config{model}_par.bit";
283 if (! $noProgram) {
284 if (! $forceLoad && -s "$config{modelDir}/$config{model}_hw.errinfo") {
285 print STDERR "FPGA bit file has errors:\n\n";
286 system("cat $config{modelDir}/$config{model}_hw.errinfo > /dev/stderr");
287 print STDERR "\nUse --force-load to ignore the error.\n";
288 exit(1);
289 }
291 if (! $noReserve) {
292 Exec("hasim-fpga-ctrl --reserve", "Failed to reserve FPGA");
293 }
295 # Does a download script exist to program the FPGA?
296 my $needProgram = (-f "$config{modelDir}/config/$config{model}.download");
297 $needProgram = 1;
299 # Is the FPGA already programmed with the correct bit file?
300 if (exists($config{signature})) {
301 my $curSignature = `hasim-fpga-ctrl --getsignature`;
302 chomp($curSignature);
303 if ($curSignature eq $config{signature}) {
304 print "FPGA is already programmed (signature match)...\n";
305 #$needProgram = 0;
306 }
307 }
309 if ($needProgram) {
310 Exec("hasim-fpga-ctrl --program", "Failed to enter FPGA programming mode");
312 my $dir = `pwd`;
313 chomp($dir);
314 Exec("(cd $config{modelDir}; ./config/$config{model}.download ${dir}/FPGA_programming.log)", "Failed to program FPGA");
316 if (exists($config{signature})) {
317 Exec("hasim-fpga-ctrl --setsignature=$config{signature}", "Failed to set FPGA bit image signature");
318 }
319 }
321 Exec("hasim-fpga-ctrl --activate", "Failed to activate FPGA or driver");
322 }
323 }
325 # Run the software side or a hardware simulator
326 my $run_status = 0;
327 if ($config{isHybridModel} || ($mType != $MODEL_FPGA)) {
328 $cmd = $cmd." 2> proc.trace\n";
329 $run_status = ExecModel($cmd);
330 }
332 # Create a stats file for null workloads to make regression.launcher happy (HACK)
333 if ( $config{workload} eq "null" ) {
334 system("touch null.stats");
335 }
337 if (-f "hasim_events.out") {
338 system("sort hasim_events.out -o hasim_events.out.$$; mv -f hasim_events.out.$$ hasim_events.out");
339 }
340 if (-f "$config{workload}.stats") {
341 system("sort $config{workload}.stats -o $config{workload}.stats.$$; mv -f $config{workload}.stats.$$ $config{workload}.stats");
342 }
344 if (($mType == $MODEL_FPGA) && ! $noProgram && ! $noReserve) {
345 Exec("hasim-fpga-ctrl --drop-reservation", "Failed to drop FPGA reservation");
346 }
348 if ($run_status != 0) {
349 exit($run_status);
350 }
351 else {
352 exit(CompareOutput());
353 }
356 sub ErrorExit($) {
357 my $msg = shift;
359 print STDERR "${msg}\n";
361 if (($mType == $MODEL_FPGA) && ! $noProgram && ! $noReserve) {
362 system("hasim-fpga-ctrl --drop-reservation");
363 }
365 exit(1);
366 }
369 ##
370 ## ExecModel --
371 ## This is the routine that actually invokes the model. stdout and stderr
372 ## are logged in a file. The return value is the exit status of the model.
373 ##
374 sub ExecModel($) {
375 my $cmd = shift;
377 if ($gdb) {
378 ## gdb needs stdin. Just use system() and don't do logging.
379 system("gdb -args " . $cmd);
380 return 0;
381 }
383 ##
384 ## Invoke the model, but log its output both to stdout and to a file.
385 ## Use a pty so the invoked program will use line buffering instead
386 ## of fully buffered writes. (Libc sets up stdout line buffered when
387 ## it thinks it is writing to a terminal. It uses fully buffered
388 ## writing to a pipe.)
389 ##
391 my $pty = new IO::Pty;
392 my $slave = $pty->slave();
394 my $pid = fork();
395 die "Couldn't fork: $!" unless defined $pid;
397 if (! $pid) {
398 # Child process is the monitoring process
399 $pty->make_slave_controlling_terminal();
401 my $output = "$config{workload}.$config{ISA}.out";
402 if(exists($config{silent})) {
403 $output = "/dev/null";
404 }
406 if (! open(LOG, ">$output")) {
407 print STDERR "Error opening log file $output\n";
408 }
410 # Unbuffered I/O loop
411 while (1) {
412 my $buf;
413 my $n = sysread($slave, $buf, 4096);
415 last if ($n == 0);
417 syswrite(STDOUT, $buf);
418 syswrite(LOG, $buf);
419 }
421 close(LOG);
422 exit(0);
423 }
425 # Bind new PTY to STDOUT (but save old STDOUT)
426 $pty->close_slave();
427 open(my $oldOut, ">&", STDOUT) or die $!;
428 open(STDOUT, ">&", $pty) or die $!;
430 # Run model
431 my $result = system("${cmd} 2>&1");
433 # Send ^d to end child logging thread
434 print "\cD";
436 # Return to normal STDOUT
437 close(STDOUT);
438 open(STDOUT, ">&", $oldOut) or die $!;
439 close($oldOut);
441 # Compute exit status of model
442 my $status = 0;
443 if ($result == -1) {
444 print STDERR "Model execution failed\n";
445 $status = 1;
446 }
447 elsif ($result & 127) {
448 print STDERR "Child died with signal " . ($result & 127) . ", " . (($result & 128) ? 'with' : 'without') . " coredump\n";
449 $status = 1;
450 }
451 elsif (($result >> 8) != 0) {
452 $status = $result >> 8;
453 print "Model exited with status $status\n";
454 }
456 return $status;
457 }
460 sub Exec($$) {
461 my $cmd = shift;
462 my $errmsg = shift;
464 system($cmd);
465 if ($? == -1) {
466 ErrorExit("Failed to execute $cmd: $!");
467 }
468 elsif ($? & 127) {
469 ErrorExit("Child died with signal " . ($? & 127) . ", " . (($? & 128) ? 'with' : 'without') . " coredump");
470 }
471 elsif (($? >> 8) != 0) {
472 ErrorExit("${errmsg}");
473 }
474 }
477 sub CompareOutput() {
478 return 0 if ($noCompare != 0);
479 return 0 if (! exists($config{compare}) || ($config{compare} eq ''));
481 # run the checker
482 `cd ./checker/ && make clean && make`;
483 `./checker/checker input.wav out_gold.wav`;
484 print "about to call compare_wavs\n";
485 my $out=`./checker/compare_wavs/compare_wavs 10 out_gold.wav out_hw.wav`;
487 if ($out !~ /fail/) {
488 print "*** Output comparison passed ***\n";
489 system("touch $config{workload}.stats");
490 return 0;
491 }
492 else {
493 print "*** Output comparison failed ***\n";
494 return 1;
495 }
496 }
499 #
500 # Read the configuration file
501 #
502 sub ReadConfig($$) {
503 my $conf = shift;
504 my $required = shift;
506 my $status = open(CONFIG, "< $conf");
507 if (! $status) {
508 return if (! $required);
509 die("Failed to open $conf");
510 }
512 while (<CONFIG>) {
513 chomp;
514 my $t = $_;
515 $t =~ s/#.*//;
516 if ($t =~ /^\s*([^\s]+)\s*=\s*"(.*)"\s*$/) {
517 my $c = $1;
518 my $v = $2;
519 $v =~ s/^["'](.*)["']$/$1/; # Drop quotation marks
520 $config{$c} = $v;
521 }
522 elsif ($t =~ /^\s*([^\s]+)\s*=\s*([^\s]+)\s*$/) {
523 my $c = $1;
524 my $v = $2;
525 $config{$c} = $v;
526 }
527 }
528 }