csci2021/ArchLab/archlab-handout/sim/pipe/gen-driver.pl
Michael Zhang 1fa36db752
f
2018-01-29 17:45:27 -06:00

252 lines
4.9 KiB
Perl
Executable file

#!/usr/bin/perl
#!/usr/local/bin/perl
#
# gen-driver - Generate driver file for any ncopy function
#
use Getopt::Std;
$n = 0;
getopts('hcrn:f:b:');
if ($opt_h) {
print STDERR "Usage $argv[0] [-h] [-c] [-n N] [-f FILE]\n";
print STDERR " -h print help message\n";
print STDERR " -c include correctness checking code\n";
print STDERR " -n N set number of elements\n";
print STDERR " -f FILE set input file (default stdin)\n";
print STDERR " -b blim set byte limit for function\n";
print STDERR " -r Allow random result\n";
die "\n";
}
$check = 0;
if ($opt_c) {
$check = 1;
}
$bytelim = 1000;
if ($opt_b) {
$bytelim = $opt_b;
}
if ($opt_n) {
$n = $opt_n;
if ($n < 0) {
print STDERR "n must be at least 0\n";
die "\n";
}
}
$randomval = 0;
# Accumulated count
$rval = 0;
$poscount = 0;
if ($opt_r) {
$randomval = 1;
} else {
# Value that should be returned by function
$tval = int($n/2);
}
# The data to be stored.
@data = ();
for ($i = 0; $i < $n; $i++) {
$data[$i] = -($i+1);
if ($randomval) {
if (int(rand(2)) == 1) {
$data[$i] = -$data[$i];
$rval++;
$poscount++;
}
} else {
if ($rval < $tval && int(rand(2)) % 2 == 1 ||
$tval - $rval >= $n - $i) {
$data[$i] = -$data[$i];
$rval++;
$poscount++;
}
}
}
$rval = $poscount;
# Values to put at beginning and end of destination
$Preval = "0xbcdefa";
$Postval = "0xdefabc";
print <<PROLOGUE;
#######################################################################
# Test for copying block of size $n;
#######################################################################
.pos 0
main: irmovq Stack, %rsp # Set up stack pointer
# Set up arguments for copy function and then invoke it
irmovq \$$n, %rdx # src and dst have $n elements
irmovq dest, %rsi # dst array
irmovq src, %rdi # src array
call ncopy
PROLOGUE
if ($check) {
print <<CALL;
call check # Call checker code
halt # should halt with 0xaaaa in %rax
CALL
} else {
print <<HALT;
halt # should halt with num nonzeros in %rax
HALT
}
print "StartFun:\n";
if ($opt_f) {
open (CODEFILE, "$opt_f") || die "Can't open code file $opt_f\n";
while (<CODEFILE>) {
printf "%s", $_;
}
} else {
while (<>) {
printf "%s", $_;
}
}
print "EndFun:\n";
if ($check) {
print <<CHECK;
####################################################################
# Epilogue code for the correctness testing driver
####################################################################
# This is the correctness checking code.
# It checks:
# 1. %rax has $rval. Set %rax to 0xbbbb if not.
# 2. The total length of the code is less than or equal to $bytelim.
# Set %rax to 0xcccc if not.
# 3. The source data was copied to the destination.
# Set %rax to 0xdddd if not.
# 4. The words just before and just after the destination region
# were not corrupted. Set %rax to 0xeeee if not.
# If all checks pass, then sets %rax to 0xaaaa
check:
# Return value test
irmovq \$$rval,%r10
subq %r10,%rax
je checkb
irmovq \$0xbbbb,%rax # Failed test #1
jmp cdone
checkb:
# Code length check
irmovq EndFun,%rax
irmovq StartFun,%rdx
subq %rdx,%rax
irmovq \$$bytelim,%rdx
subq %rax,%rdx
jge checkm
irmovq \$0xcccc,%rax # Failed test #2
jmp cdone
checkm:
irmovq dest, %rdx # Pointer to next destination location
irmovq src,%rbx # Pointer to next source location
irmovq \$$n,%rdi # Count
andq %rdi,%rdi
je checkpre # Skip check if count = 0
mcloop:
mrmovq (%rdx),%rax
mrmovq (%rbx),%rsi
subq %rsi,%rax
je mok
irmovq \$0xdddd,%rax # Failed test #3
jmp cdone
mok:
irmovq \$8,%rax
addq %rax,%rdx # dest ++
addq %rax,%rbx # src++
irmovq \$1,%rax
subq %rax,%rdi # cnt--
jg mcloop
checkpre:
# Check for corruption
irmovq Predest,%rdx
mrmovq (%rdx), %rax # Get word before destination
irmovq \$$Preval, %rdx
subq %rdx,%rax
je checkpost
irmovq \$0xeeee,%rax # Failed test #4
jmp cdone
checkpost:
# Check for corruption
irmovq Postdest,%rdx
mrmovq (%rdx), %rax # Get word after destination
irmovq \$$Postval, %rdx
subq %rdx,%rax
je checkok
irmovq \$0xeeee,%rax # Failed test #4
jmp cdone
checkok:
# Successful checks
irmovq \$0xaaaa,%rax
cdone:
ret
CHECK
}
print <<EPILOGUE1;
###############################
# Source and destination blocks
###############################
.align 8
src:
EPILOGUE1
for ($i = 0; $i < $n; $i++) {
print "\t.quad $data[$i]\n";
}
print <<EPILOGUE2;
.quad $Preval # This shouldn't get moved
.align 16
Predest:
.quad $Preval
dest:
EPILOGUE2
for ($i = 0; $i < $n; $i++) {
print "\t.quad 0xcdefab\n";
}
print <<EPILOGUE3;
Postdest:
.quad $Postval
.align 8
# Run time stack
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
Stack:
EPILOGUE3