view scripts/run-null.bmark @ 58:52f9a257c2ba pygar svn.59

[svn r59] LUTRAMing
author punk
date Mon, 10 May 2010 13:47:12 -0400
parents 90197e3375e2
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 $printCycle = undef;
67 my $bluesimCmd = undef;
68 my $vcdStart = undef;
69 my $vcdCycles = 20000;
70 my $m5run = 0;
72 my $status = GetOptions("help!" => \$help,
73 "gdb!" => \$gdb,
74 "noprogram!" => \$noProgram,
75 "noreserve!" => \$noReserve,
76 "force-load!" => \$forceLoad,
77 "funcp-prefix=s" => \$funcpPrefix,
78 "funcp-suffix=s" => \$funcpSuffix,
79 "onlycompare!" => \$onlyCompare,
80 "nocompare!" => \$noCompare,
81 "pc=s" => \$printCycle,
82 "bluesim=s" => \$bluesimCmd,
83 "vcdstart=i" => \$vcdStart,
84 "vcdcycles=i" => \$vcdCycles,
85 "m5!" => \$m5run,
86 );
88 # Put quotation marks back on arguments that have spaces since they will be
89 # passed through a shell once more.
90 foreach my $i ( 0 .. $#ARGV ) {
91 if (($ARGV[$i] =~ /\s/) && ! ($ARGV[$i] =~ /['"]$/)) {
92 $ARGV[$i] = '"' . $ARGV[$i] . '"';
93 }
94 }
96 if ($onlyCompare != 0) {
97 exit(CompareOutput());
98 }
100 if ($m5run != 0) {
101 $mType = $MODEL_NONE;
102 }
103 elsif (-f "$config{modelDir}/$config{model}_hw.errinfo") {
104 $mType = $MODEL_FPGA;
105 }
106 elsif (-f "$config{modelDir}/$config{model}_hw.exe") {
107 $mType = $MODEL_BLUESIM;
108 }
109 elsif (-f "$config{modelDir}/$config{model}_hw.vexe") {
110 $mType = $MODEL_VSIM;
111 }
112 else {
113 die("Can't determine model type");
114 }
116 if ($help || ! $status) {
117 print STDERR "\nArguments:\n";
118 print STDERR " [--gdb] Invokes the software side in gdb\n";
119 print STDERR " [--noprogram] Skips the FPGA load and reservation steps\n";
120 print STDERR " [--noreserve] Skips the FPGA reservation steps\n";
121 print STDERR " [--funcp-prefix=\"<prefix>\"]\n";
122 print STDERR " Prepend prefix to HAsim's --funcp argument\n";
123 print STDERR " [--funcp-suffix=\"<suffix>\"]\n";
124 print STDERR " Append suffix to HAsim's --funcp argument\n";
125 print STDERR " [--onlycompare] Only compare output files (without running)\n";
126 print STDERR " [--nocompare] Skip comparison of output files\n";
127 print STDERR " [--m5] Run workload in m5 without HAsim\n";
129 if ($mType == $MODEL_FPGA) {
130 print STDERR " [--force-load] Load a bitfile to the FPGA even if it has errors\n";
131 }
133 if ($mType == $MODEL_BLUESIM) {
134 print STDERR " [--vcdstart=<cycle>] Generate VCD dump for wave viewer (e.g. gtkwave)\n";
135 print STDERR " [--vcdcycles=<cycles>] VCD dump length (default = 20000)\n";
136 }
138 if ($config{isHybridModel}) {
139 my $cmd = "$config{modelDir}/$config{model} --help-run-append";
140 system($cmd);
141 }
143 exit(1);
144 }
146 #############################################################################
147 #############################################################################
148 ##
149 ## Adjust model arguments
150 ##
151 #############################################################################
152 #############################################################################
154 my $feedFlags = "${funcpPrefix} $config{feedFlags} ${funcpSuffix}";
156 if ($config{feeder} eq 'm5') {
157 # Tell m5 to be quiet and not to enable the remote gdb port. Under netbatch
158 # it appears there are sometimes attempts to connect to the port, which
159 # stops simulation.
160 $feedFlags = "--quiet --remote-gdb-port=0 ${feedFlags}";
161 }
163 my $cmd;
165 if ($m5run == 0) {
166 # Normal run
167 $cmd = "$config{modelDir}/$config{model} --modeldir=$config{modelDir} --workload=$config{workload} --funcp=\"${feedFlags}\" $config{genFlags}";
168 foreach my $c (@ARGV) {
169 $cmd .= " $c";
170 }
172 if (defined($printCycle)) {
173 $cmd .= " --pc=${printCycle}";
174 }
175 }
176 else {
177 if ($config{feeder} ne 'm5') {
178 die("This workload does not use m5");
179 }
181 # Running inside m5 without HAsim
182 my $m5cmd;
183 if (exists($ENV{M5BIN})) {
184 $m5cmd = $ENV{M5BIN};
185 }
186 else {
187 my $m5bin = "platform/m5/build/ALPHA_SE/m5." . ($gdb ? "debug" : "opt");
188 $m5cmd = `awb-resolver ${m5bin}`;
189 chomp($m5cmd);
190 die("Failed to find $m5bin") if ($m5cmd eq '');
191 }
193 $cmd = "${m5cmd} ${feedFlags}";
195 # Drop --hasim-sim
196 $cmd =~ s/--hasim-sim //;
197 # Drop escaping of quotes
198 $cmd =~ s/\\"/"/g;
200 $noProgram = 1;
201 }
203 #
204 # Bluesim arguments
205 #
207 # Generate dump.vcd for wave viewer (e.g. gtkwave)?
208 if (defined($vcdStart)) {
209 my $vcdCmd = "sim vcd on; sim step $vcdCycles; sim stop";
210 if ($vcdStart > 0) {
211 $vcdCmd = "sim step ${vcdStart}; ${vcdCmd}";
212 }
214 if (defined($bluesimCmd)) {
215 $bluesimCmd .= " ";
216 }
217 else {
218 $bluesimCmd = "";
219 }
220 $bluesimCmd .= "-c \"$vcdCmd\"";
221 }
223 if (defined($bluesimCmd)) {
224 $cmd .= " --bluesim=\'$bluesimCmd\'";
225 }
227 # Adjust the arguments for Bluesim if it is being invoked directly
228 if (! $config{isHybridModel} && ($mType == $MODEL_BLUESIM)) {
229 $cmd =~ s/\s--/ +--/g;
231 # Bluesim may expect to load a program from a well known file
232 unlink('program.vmh');
233 link("program/$config{workload}.$config{ISA}.vmh", 'program.vmh');
234 }
237 #############################################################################
238 #############################################################################
239 ##
240 ## Load the FPGA and run the model
241 ##
242 #############################################################################
243 #############################################################################
245 #
246 # Move old stats file so we are sure statistics come from this run
247 #
248 if (-f "$config{workload}.stats") {
249 rename("$config{workload}.stats", "$config{workload}.stats.old");
250 }
252 if ($mType == $MODEL_FPGA) {
253 if (! defined($printCycle)) {
254 # User didn't specify a cycle printing interval. Pick one more reasonable
255 # for HW.
256 #$cmd .= " --pc=10000000";
257 }
259 # Load FPGA
260 $ENV{FPGA_BIT_FILE} = "$config{modelDir}/.xilinx/$config{model}_par.bit";
262 if (! $noProgram) {
263 if (! $forceLoad && -s "$config{modelDir}/$config{model}_hw.errinfo") {
264 print STDERR "FPGA bit file has errors:\n\n";
265 system("cat $config{modelDir}/$config{model}_hw.errinfo > /dev/stderr");
266 print STDERR "\nUse --force-load to ignore the error.\n";
267 exit(1);
268 }
270 if (! $noReserve) {
271 Exec("hasim-fpga-ctrl --reserve", "Failed to reserve FPGA");
272 }
274 # Does a download script exist to program the FPGA?
275 my $needProgram = (-f "$config{modelDir}/config/$config{model}.download");
277 $needProgram = 1;
279 # Is the FPGA already programmed with the correct bit file?
280 if (exists($config{signature})) {
281 my $curSignature = `hasim-fpga-ctrl --getsignature`;
282 chomp($curSignature);
283 if ($curSignature eq $config{signature}) {
284 print "FPGA is already programmed (signature match)...\n";
285 #$needProgram = 0;
286 }
287 }
289 if ($needProgram) {
290 Exec("hasim-fpga-ctrl --program", "Failed to enter FPGA programming mode");
292 my $dir = `pwd`;
293 chomp($dir);
294 Exec("(cd $config{modelDir}; ./config/$config{model}.download ${dir}/FPGA_programming.log)", "Failed to program FPGA");
296 if (exists($config{signature})) {
297 Exec("hasim-fpga-ctrl --setsignature=$config{signature}", "Failed to set FPGA bit image signature");
298 }
299 }
301 Exec("hasim-fpga-ctrl --activate", "Failed to activate FPGA or driver");
302 }
303 }
305 # Run the software side or a hardware simulator
306 my $run_status = 0;
307 if ($config{isHybridModel} || ($mType != $MODEL_FPGA)) {
308 $run_status = ExecModel($cmd);
309 }
311 # Create a stats file for null workloads to make regression.launcher happy (HACK)
312 if ( $config{workload} eq "null" ) {
313 system("touch null.stats");
314 }
316 if (-f "hasim_events.out") {
317 system("sort hasim_events.out -o hasim_events.out.$$; mv -f hasim_events.out.$$ hasim_events.out");
318 }
319 if (-f "$config{workload}.stats") {
320 system("sort $config{workload}.stats -o $config{workload}.stats.$$; mv -f $config{workload}.stats.$$ $config{workload}.stats");
321 }
323 if (($mType == $MODEL_FPGA) && ! $noProgram && ! $noReserve) {
324 Exec("hasim-fpga-ctrl --drop-reservation", "Failed to drop FPGA reservation");
325 }
327 if ($run_status != 0) {
328 exit($run_status);
329 }
330 else {
331 exit(CompareOutput());
332 }
335 sub ErrorExit($) {
336 my $msg = shift;
338 print STDERR "${msg}\n";
340 if (($mType == $MODEL_FPGA) && ! $noProgram && ! $noReserve) {
341 system("hasim-fpga-ctrl --drop-reservation");
342 }
344 exit(1);
345 }
348 ##
349 ## ExecModel --
350 ## This is the routine that actually invokes the model. stdout and stderr
351 ## are logged in a file. The return value is the exit status of the model.
352 ##
353 sub ExecModel($) {
354 my $cmd = shift;
356 if ($gdb) {
357 ## gdb needs stdin. Just use system() and don't do logging.
358 system("gdb -args " . $cmd);
359 return 0;
360 }
362 ##
363 ## Invoke the model, but log its output both to stdout and to a file.
364 ## Use a pty so the invoked program will use line buffering instead
365 ## of fully buffered writes. (Libc sets up stdout line buffered when
366 ## it thinks it is writing to a terminal. It uses fully buffered
367 ## writing to a pipe.)
368 ##
370 my $pty = new IO::Pty;
371 my $slave = $pty->slave();
373 my $pid = fork();
374 die "Couldn't fork: $!" unless defined $pid;
376 if (! $pid) {
377 # Child process is the monitoring process
378 $pty->make_slave_controlling_terminal();
380 my $output = "$config{workload}.$config{ISA}.out";
381 if(exists($config{silent})) {
382 $output = "/dev/null";
383 }
385 if (! open(LOG, ">$output")) {
386 print STDERR "Error opening log file $output\n";
387 }
389 # Unbuffered I/O loop
390 while (1) {
391 my $buf;
392 my $n = sysread($slave, $buf, 4096);
394 last if ($n == 0);
396 syswrite(STDOUT, $buf);
397 syswrite(LOG, $buf);
398 }
400 close(LOG);
401 exit(0);
402 }
404 # Bind new PTY to STDOUT (but save old STDOUT)
405 $pty->close_slave();
406 open(my $oldOut, ">&", STDOUT) or die $!;
407 open(STDOUT, ">&", $pty) or die $!;
409 # Run model
410 my $result = system("${cmd} 2>&1");
412 # Send ^d to end child logging thread
413 print "\cD";
415 # Return to normal STDOUT
416 close(STDOUT);
417 open(STDOUT, ">&", $oldOut) or die $!;
418 close($oldOut);
420 # Compute exit status of model
421 my $status = 0;
422 if ($result == -1) {
423 print STDERR "Model execution failed\n";
424 $status = 1;
425 }
426 elsif ($result & 127) {
427 print STDERR "Child died with signal " . ($result & 127) . ", " . (($result & 128) ? 'with' : 'without') . " coredump\n";
428 $status = 1;
429 }
430 elsif (($result >> 8) != 0) {
431 $status = $result >> 8;
432 print "Model exited with status $status\n";
433 }
435 return $status;
436 }
439 sub Exec($$) {
440 my $cmd = shift;
441 my $errmsg = shift;
443 system($cmd);
444 if ($? == -1) {
445 ErrorExit("Failed to execute $cmd: $!");
446 }
447 elsif ($? & 127) {
448 ErrorExit("Child died with signal " . ($? & 127) . ", " . (($? & 128) ? 'with' : 'without') . " coredump");
449 }
450 elsif (($? >> 8) != 0) {
451 ErrorExit("${errmsg}");
452 }
453 }
456 sub CompareOutput() {
457 return 0 if ($noCompare != 0);
458 return 0 if (! exists($config{compare}) || ($config{compare} eq ''));
460 }
463 #
464 # Read the configuration file
465 #
466 sub ReadConfig($$) {
467 my $conf = shift;
468 my $required = shift;
470 my $status = open(CONFIG, "< $conf");
471 if (! $status) {
472 return if (! $required);
473 die("Failed to open $conf");
474 }
476 while (<CONFIG>) {
477 chomp;
478 my $t = $_;
479 $t =~ s/#.*//;
480 if ($t =~ /^\s*([^\s]+)\s*=\s*"(.*)"\s*$/) {
481 my $c = $1;
482 my $v = $2;
483 $v =~ s/^["'](.*)["']$/$1/; # Drop quotation marks
484 $config{$c} = $v;
485 }
486 elsif ($t =~ /^\s*([^\s]+)\s*=\s*([^\s]+)\s*$/) {
487 my $c = $1;
488 my $v = $2;
489 $config{$c} = $v;
490 }
491 }
492 }