Mercurial > pygar
comparison scripts/run.bmark @ 23:90197e3375e2 pygar svn.24
[svn r24] added testing, but something is wrong with our c++ file.
author | rlm |
---|---|
date | Wed, 28 Apr 2010 08:19:09 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
22:0cfbb1e2de22 | 23:90197e3375e2 |
---|---|
1 #!/usr/bin/env perl | |
2 # -*- perl -*- | |
3 | |
4 use strict; | |
5 use warnings; | |
6 use Getopt::Long qw(:config no_auto_abbrev no_ignore_case pass_through); | |
7 use IO::Pty; | |
8 | |
9 # | |
10 # Turn on warnings | |
11 # | |
12 $^W = 1; | |
13 | |
14 ## | |
15 ## Benchmark run script | |
16 ## | |
17 | |
18 sub ExecModel($); | |
19 sub Exec($$); | |
20 sub CompareOutput(); | |
21 sub ReadConfig($$); | |
22 | |
23 | |
24 ############################################################################# | |
25 ############################################################################# | |
26 ## | |
27 ## Start by figuring out the model location and type. | |
28 ## | |
29 ############################################################################# | |
30 ############################################################################# | |
31 | |
32 my %config; | |
33 | |
34 ReadConfig("config/env.sh", 1); | |
35 ReadConfig("$config{modelDir}/config/env.sh", 1); | |
36 ReadConfig("$config{modelDir}/config/signature.sh", 0); | |
37 | |
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 | |
45 | |
46 my $mType = $MODEL_NONE; | |
47 | |
48 | |
49 ############################################################################# | |
50 ############################################################################# | |
51 ## | |
52 ## Process command line arguments | |
53 ## | |
54 ############################################################################# | |
55 ############################################################################# | |
56 | |
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; | |
73 | |
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 ); | |
91 | |
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 } | |
99 | |
100 if ($onlyCompare != 0) { | |
101 exit(CompareOutput()); | |
102 } | |
103 | |
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 } | |
119 | |
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"; | |
132 | |
133 if ($mType == $MODEL_FPGA) { | |
134 print STDERR " [--force-load] Load a bitfile to the FPGA even if it has errors\n"; | |
135 } | |
136 | |
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 } | |
141 | |
142 if ($config{isHybridModel}) { | |
143 my $cmd = "$config{modelDir}/$config{model} --help-run-append"; | |
144 system($cmd); | |
145 } | |
146 | |
147 exit(1); | |
148 } | |
149 | |
150 ############################################################################# | |
151 ############################################################################# | |
152 ## | |
153 ## Adjust model arguments | |
154 ## | |
155 ############################################################################# | |
156 ############################################################################# | |
157 | |
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 } | |
174 | |
175 my $feedFlags = "${funcpPrefix} $config{feedFlags} ${funcpSuffix}"; | |
176 | |
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 } | |
183 | |
184 my $cmd; | |
185 | |
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 } | |
192 | |
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 } | |
201 | |
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 } | |
213 | |
214 $cmd = "${m5cmd} ${feedFlags}"; | |
215 | |
216 # Drop --hasim-sim | |
217 $cmd =~ s/--hasim-sim //; | |
218 # Drop escaping of quotes | |
219 $cmd =~ s/\\"/"/g; | |
220 | |
221 $noProgram = 1; | |
222 } | |
223 | |
224 # | |
225 # Bluesim arguments | |
226 # | |
227 | |
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 } | |
234 | |
235 if (defined($bluesimCmd)) { | |
236 $bluesimCmd .= " "; | |
237 } | |
238 else { | |
239 $bluesimCmd = ""; | |
240 } | |
241 $bluesimCmd .= "-c \"$vcdCmd\""; | |
242 } | |
243 | |
244 if (defined($bluesimCmd)) { | |
245 $cmd .= " --bluesim=\'$bluesimCmd\'"; | |
246 } | |
247 | |
248 # Adjust the arguments for Bluesim if it is being invoked directly | |
249 if (! $config{isHybridModel} && ($mType == $MODEL_BLUESIM)) { | |
250 $cmd =~ s/\s--/ +--/g; | |
251 | |
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 } | |
256 | |
257 | |
258 ############################################################################# | |
259 ############################################################################# | |
260 ## | |
261 ## Load the FPGA and run the model | |
262 ## | |
263 ############################################################################# | |
264 ############################################################################# | |
265 | |
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 } | |
272 | |
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 } | |
279 | |
280 # Load FPGA | |
281 $ENV{FPGA_BIT_FILE} = "$config{modelDir}/.xilinx/$config{model}_par.bit"; | |
282 | |
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 } | |
290 | |
291 if (! $noReserve) { | |
292 Exec("hasim-fpga-ctrl --reserve", "Failed to reserve FPGA"); | |
293 } | |
294 | |
295 # Does a download script exist to program the FPGA? | |
296 my $needProgram = (-f "$config{modelDir}/config/$config{model}.download"); | |
297 $needProgram = 1; | |
298 | |
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 } | |
308 | |
309 if ($needProgram) { | |
310 Exec("hasim-fpga-ctrl --program", "Failed to enter FPGA programming mode"); | |
311 | |
312 my $dir = `pwd`; | |
313 chomp($dir); | |
314 Exec("(cd $config{modelDir}; ./config/$config{model}.download ${dir}/FPGA_programming.log)", "Failed to program FPGA"); | |
315 | |
316 if (exists($config{signature})) { | |
317 Exec("hasim-fpga-ctrl --setsignature=$config{signature}", "Failed to set FPGA bit image signature"); | |
318 } | |
319 } | |
320 | |
321 Exec("hasim-fpga-ctrl --activate", "Failed to activate FPGA or driver"); | |
322 } | |
323 } | |
324 | |
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 } | |
331 | |
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 } | |
336 | |
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 } | |
343 | |
344 if (($mType == $MODEL_FPGA) && ! $noProgram && ! $noReserve) { | |
345 Exec("hasim-fpga-ctrl --drop-reservation", "Failed to drop FPGA reservation"); | |
346 } | |
347 | |
348 if ($run_status != 0) { | |
349 exit($run_status); | |
350 } | |
351 else { | |
352 exit(CompareOutput()); | |
353 } | |
354 | |
355 | |
356 sub ErrorExit($) { | |
357 my $msg = shift; | |
358 | |
359 print STDERR "${msg}\n"; | |
360 | |
361 if (($mType == $MODEL_FPGA) && ! $noProgram && ! $noReserve) { | |
362 system("hasim-fpga-ctrl --drop-reservation"); | |
363 } | |
364 | |
365 exit(1); | |
366 } | |
367 | |
368 | |
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; | |
376 | |
377 if ($gdb) { | |
378 ## gdb needs stdin. Just use system() and don't do logging. | |
379 system("gdb -args " . $cmd); | |
380 return 0; | |
381 } | |
382 | |
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 ## | |
390 | |
391 my $pty = new IO::Pty; | |
392 my $slave = $pty->slave(); | |
393 | |
394 my $pid = fork(); | |
395 die "Couldn't fork: $!" unless defined $pid; | |
396 | |
397 if (! $pid) { | |
398 # Child process is the monitoring process | |
399 $pty->make_slave_controlling_terminal(); | |
400 | |
401 my $output = "$config{workload}.$config{ISA}.out"; | |
402 if(exists($config{silent})) { | |
403 $output = "/dev/null"; | |
404 } | |
405 | |
406 if (! open(LOG, ">$output")) { | |
407 print STDERR "Error opening log file $output\n"; | |
408 } | |
409 | |
410 # Unbuffered I/O loop | |
411 while (1) { | |
412 my $buf; | |
413 my $n = sysread($slave, $buf, 4096); | |
414 | |
415 last if ($n == 0); | |
416 | |
417 syswrite(STDOUT, $buf); | |
418 syswrite(LOG, $buf); | |
419 } | |
420 | |
421 close(LOG); | |
422 exit(0); | |
423 } | |
424 | |
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 $!; | |
429 | |
430 # Run model | |
431 my $result = system("${cmd} 2>&1"); | |
432 | |
433 # Send ^d to end child logging thread | |
434 print "\cD"; | |
435 | |
436 # Return to normal STDOUT | |
437 close(STDOUT); | |
438 open(STDOUT, ">&", $oldOut) or die $!; | |
439 close($oldOut); | |
440 | |
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 } | |
455 | |
456 return $status; | |
457 } | |
458 | |
459 | |
460 sub Exec($$) { | |
461 my $cmd = shift; | |
462 my $errmsg = shift; | |
463 | |
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 } | |
475 | |
476 | |
477 sub CompareOutput() { | |
478 return 0 if ($noCompare != 0); | |
479 return 0 if (! exists($config{compare}) || ($config{compare} eq '')); | |
480 | |
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`; | |
486 | |
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 } | |
497 | |
498 | |
499 # | |
500 # Read the configuration file | |
501 # | |
502 sub ReadConfig($$) { | |
503 my $conf = shift; | |
504 my $required = shift; | |
505 | |
506 my $status = open(CONFIG, "< $conf"); | |
507 if (! $status) { | |
508 return if (! $required); | |
509 die("Failed to open $conf"); | |
510 } | |
511 | |
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 } |