multithreading tests from 152 lab 5
[riscv-tests.git] / mt / aq_matmul / matmul_gendata.pl
diff --git a/mt/aq_matmul/matmul_gendata.pl b/mt/aq_matmul/matmul_gendata.pl
new file mode 100755 (executable)
index 0000000..f21bb46
--- /dev/null
@@ -0,0 +1,200 @@
+#!/usr/bin/perl -w
+#==========================================================================
+# matmul_gendata.pl
+#
+# Author : Christopher Batten (cbatten@mit.edu)
+# Date   : April 29, 2005
+#
+(our $usageMsg = <<'ENDMSG') =~ s/^\#//gm;
+#
+# Simple script which creates an input data set and the reference data
+# for the matmul benchmark.
+#
+ENDMSG
+
+use strict "vars";
+use warnings;
+no  warnings("once");
+use Getopt::Long;
+
+#--------------------------------------------------------------------------
+# Command line processing
+#--------------------------------------------------------------------------
+
+our %opts;
+
+sub usage()
+{
+
+  print "\n";
+  print " Usage: matmul_gendata.pl [options] \n";
+  print "\n";
+  print " Options:\n";
+  print "  --help  print this message\n";
+  print "  --size  size of input data [1000]\n";
+  print "  --seed  random seed [1]\n";
+  print "$usageMsg";
+
+  exit();
+}
+
+sub processCommandLine()
+{
+
+  $opts{"help"} = 0;
+  $opts{"size"} = 1000;
+  $opts{"seed"} = 1;
+  Getopt::Long::GetOptions( \%opts, 'help|?', 'size:i', 'seed:i' ) or usage();
+  $opts{"help"} and usage();
+
+}
+
+#--------------------------------------------------------------------------
+# Helper Functions
+#--------------------------------------------------------------------------
+
+sub printArray
+{
+  my $arrayName = $_[0];
+  my $arrayRef  = $_[1];
+
+  my $numCols = 20;
+  my $arrayLen = scalar(@{$arrayRef});
+
+  print "static data_t ".$arrayName."[ARRAY_SIZE] = \n";
+  print "{\n";
+
+  if ( $arrayLen <= $numCols ) {
+    print "  ";
+    for ( my $i = 0; $i < $arrayLen; $i++ ) {
+      print sprintf("%3d",$arrayRef->[$i]);
+      if ( $i != $arrayLen-1 ) {
+        print ", ";
+      }
+    }
+    print "\n";
+  }
+
+  else {
+    my $numRows = int($arrayLen/$numCols);
+    for ( my $j = 0; $j < $numRows; $j++ ) {
+      print "  ";
+      for ( my $i = 0; $i < $numCols; $i++ ) {
+        my $index = $j*$numCols + $i;
+        print sprintf("%3d",$arrayRef->[$index]);
+        if ( $index != $arrayLen-1 ) {
+          print ", ";
+        }
+      }
+      print "\n";
+    }
+
+    if ( $arrayLen > ($numRows*$numCols) ) {
+      print "  ";
+      for ( my $i = 0; $i < ($arrayLen-($numRows*$numCols)); $i++ ) {
+        my $index = $numCols*$numRows + $i;
+        print sprintf("%3d",$arrayRef->[$index]);
+        if ( $index != $arrayLen-1 ) {
+          print ", ";
+        }
+      }
+      print "\n";
+    }
+
+  }
+
+  print  "};\n\n";
+}
+
+
+
+#--------------------------------------------------------------------------
+# Matmul
+#--------------------------------------------------------------------------
+
+# http://answers.oreilly.com/topic/418-how-to-multiply-matrices-in-perl/
+
+sub mmult {
+    my ($m1,$m2) = @_;
+    my ($m1rows,$m1cols) = matdim($m1);
+    my ($m2rows,$m2cols) = matdim($m2);
+
+    my $result = [  ];
+    my ($i, $j, $k);
+
+    for $i (range($m1rows)) {
+        for $j (range($m2cols)) {
+            for $k (range($m1cols)) {
+                $result->[$i][$j] += $m1->[$i][$k] * $m2->[$k][$j];
+            }
+        }
+    }
+    return $result;
+}
+
+sub range { 0 .. ($_[0] - 1) }
+
+
+sub veclen {
+    my $ary_ref = $_[0];
+    my $type = ref $ary_ref;
+    if ($type ne "ARRAY") { die "$type is bad array ref for $ary_ref" }
+    return scalar(@$ary_ref);
+}
+
+sub matdim {
+    my $matrix = $_[0];
+    my $rows = veclen($matrix);
+    my $cols = veclen($matrix->[0]);
+    return ($rows, $cols);
+}
+
+#--------------------------------------------------------------------------
+# Main
+#--------------------------------------------------------------------------
+
+sub main()
+{
+
+  processCommandLine();
+  srand($opts{"seed"});
+
+  # create random input arrays
+  my $mat_values1;
+  my $mat_values2;
+  for ( my $i = 0; $i < $opts{"size"}; $i++ ) {
+    for ( my $j = 0; $j < $opts{"size"}; $j++ ) {
+      $mat_values1->[$i][$j] = int(rand(4));
+      $mat_values2->[$i][$j] = int(rand(4));
+    }
+  }
+
+  # perform matmul
+  my $mat_results = mmult( $mat_values1, $mat_values2 );
+  
+  # translate 2d arrays to 1d-somethings (I don't know how to code in perl - Chris)
+  my @values1;
+  my @values2;
+  my @results;
+  for ( my $i = 0; $i < $opts{"size"}; $i++ ) {
+    for ( my $j = 0; $j < $opts{"size"}; $j++ ) {
+    my $value1 = $mat_values1->[$i][$j];
+    my $value2 = $mat_values2->[$i][$j];
+    my $result = $mat_results->[$i][$j];
+    push( @values1, $value1 );
+    push( @values2, $value2 );
+    push( @results, $result );
+    }
+  }
+
+  print "\n\#define ARRAY_SIZE ".($opts{"size"}*$opts{"size"})." \n\n";
+  print "\n\#define DIM_SIZE ".$opts{"size"}." \n\n";
+   
+  printArray( "input1_data", \@values1 );
+  printArray( "input2_data", \@values2 );
+  printArray( "verify_data", \@results);
+}
+
+main();
+