Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:28:17

0001 #!/usr/bin/perl
0002 
0003 @Offs[3] = [ 0, 1, 3, 1, 2, 4, 3, 4, 5 ];
0004 @Offs[4] = [ 0, 1, 3, 6, 1, 2, 4, 7, 3, 4, 5, 8, 6, 7, 8, 9 ];
0005 @Offs[5] = [ 0, 1, 3, 6, 10, 1, 2, 4, 7, 11, 3, 4, 5, 8, 12, 6, 7, 8, 9, 13, 10, 11, 12, 13, 14 ];
0006 @Offs[6] = [ 0, 1, 3, 6, 10, 15, 1, 2, 4, 7, 11, 16, 3, 4, 5, 8, 12, 17, 6, 7, 8, 9, 13, 18, 10, 11, 12, 13, 14, 19, 15, 16, 17, 18, 19, 20 ];
0007 
0008 $PREF = "      ";
0009 $BR   = " ";
0010 $JOIN = "$BR";
0011 $POST = " ";
0012 
0013 
0014 #$a = "A.fArray";
0015 #$b = "B.fArray";
0016 #$c = "C.fArray";
0017 $a = "a";
0018 $b = "b";
0019 $c = "c";
0020 
0021 $vectype = "IntrVec_t";
0022 
0023 $SYMMETRIC = 1;
0024 
0025 ################################################################################
0026 
0027 sub mult_sym
0028 {
0029   my $D = shift;
0030 
0031   my @Off = @{$Offs[$D]};
0032 
0033   for (my $i = 0; $i < $D; ++$i)
0034   {
0035     for (my $j = 0; $j < $D; ++$j)
0036     # for (my $j = 0; $j <= $i; ++$j)
0037     {
0038       # my $x = $Off[$i * $D + $j];
0039       my $x = $i * $D + $j;
0040       printf "${PREF}${c}[%2d*N+n] =${POST}", $x;
0041 
0042       my @sum;
0043 
0044       for (my $k = 0; $k < $D; ++$k)
0045       {
0046         my $iko = $Off[$i * $D + $k];
0047         my $kjo = $Off[$k * $D + $j];
0048 
0049         push @sum, sprintf("${a}[%2d*N+n]*${b}[%2d*N+n]", $iko, $kjo);
0050       }
0051       print join(" +$JOIN", @sum), ";";
0052       print "\n";
0053     }
0054   }
0055 }
0056 
0057 sub mult_sym_fma
0058 {
0059   # This actually runs quite horribly, twice slower than the
0060   # fully expressd version.
0061   # Changing order of k and i loops doesn't change anything.
0062   #
0063   # However, this should be close to what we need for auto-generated
0064   # intrinsics!
0065 
0066   my $D = shift;
0067 
0068   my @Off = @{$Offs[$D]};
0069 
0070   for (my $i = 0; $i < $D; ++$i)
0071   {
0072     for (my $k = 0; $k < $D; ++$k)
0073     {
0074       for (my $j = 0; $j < $D; ++$j)
0075       {
0076         my $x = $i * $D + $j;
0077         my $iko = $Off[$i * $D + $k];
0078         my $kjo = $Off[$k * $D + $j];
0079 
0080         my $op = ($k == 0) ? " =" : "+=";
0081 
0082         printf "${PREF}${c}[%2d*N+n] ${op} ${a}[%2d*N+n]*${b}[%2d*N+n];\n",
0083            $x, $iko, $kjo;
0084       }
0085       print "\n";
0086     }
0087   }
0088 }
0089 
0090 sub reg_name
0091 {
0092   my ($var, $idx) = @_;
0093 
0094   return "${var}_${idx}";
0095 
0096 }
0097 
0098 sub load_if_needed
0099 {
0100   my ($var, $idx, $arc) = @_;
0101 
0102   my $reg = reg_name(${var}, ${idx});
0103 
0104   if ($arc->[$idx] == 0)
0105   {
0106     print "${PREF}${vectype} ${reg} = LD($var, $idx);\n";
0107     ++$tick;
0108   }
0109 
0110   ++$arc->[$idx];
0111 
0112   return $reg;
0113 }
0114 
0115 sub store
0116 {
0117   my ($var, $idx) = @_;
0118 
0119   my $reg = reg_name(${var}, ${idx});
0120 
0121   print "${PREF}ST(${var}, ${idx}, ${reg});\n";
0122 
0123   return $reg;
0124 }
0125 
0126 sub mult_sym_fma_intrinsic
0127 {
0128   # Order of k and i loops should be different for 3x3 and 6x6. (?)
0129 
0130   my $D = shift;
0131 
0132   my @Off = @{$Offs[$D]};
0133 
0134   local $tick = 0;
0135 
0136   # Counts of use. For a and b to fetch, for c to store
0137   my @ac, @bc, @cc, @to_store;
0138 
0139   for (my $i = 0; $i < $D; ++$i)
0140   {
0141     for (my $k = 0; $k < $D; ++$k)
0142     {
0143       for (my $j = 0; $j < $D; ++$j)
0144       {
0145         my $x = $i * $D + $j;
0146         my $iko = $Off[$i * $D + $k];
0147         my $kjo = $Off[$k * $D + $j];
0148 
0149         my $areg = load_if_needed("a", $iko, \@ac);
0150         my $breg = load_if_needed("b", $kjo, \@bc);
0151         my $creg = reg_name("c", $x);
0152 
0153         my $op = ($k == 0) ? "=" : "+=";
0154 
0155         if ($k == 0)
0156         {
0157           print "${PREF}${vectype} ${creg} = MUL(${areg}, ${breg});\n";
0158         }
0159         else
0160         {
0161           print "${PREF}${creg} = FMA(${areg}, ${breg}, ${creg});\n";
0162         }
0163 
0164         ++$tick;
0165 
0166         if ($k + 1 == $D)
0167         {
0168           $cc[$x] = $tick + 4; #### Will be ready to store in 4 cycles. Really 4?
0169           push @to_store, $x;
0170         }
0171 
0172         # Try to store the finished ones.
0173         while (1)
0174         {
0175           last unless @to_store;
0176           my $s = $to_store[0];
0177           last if $tick < $cc[$s];
0178 
0179           store("c", $s);
0180           shift @to_store;
0181           ++$tick;
0182         }
0183 
0184       }
0185       print "\n";
0186     }
0187   }
0188 
0189   for $s (@to_store)
0190   {
0191     store("c", $s);
0192 
0193     ++$tick;
0194   }
0195 }
0196 
0197 ################################################################################
0198 
0199 sub mult_std
0200 {
0201   my $D = shift;
0202 
0203   for (my $i = 0; $i < $D; ++$i)
0204   {
0205     for (my $j = 0; $j < $D; ++$j)
0206     {
0207       my $x = $i * $D + $j;
0208       printf "${PREF}${c}[%2d*N+n] =${POST}", $x;
0209 
0210       my @sum;
0211 
0212       for (my $k = 0; $k < $D; ++$k)
0213       {
0214         my $iko = $i * $D + $k;
0215         my $kjo = $k * $D + $j;
0216 
0217         push @sum, sprintf "${a}[%2d*N+n]*${b}[%2d*N+n]", $iko, $kjo;
0218       }
0219       print join(" +$JOIN", @sum), ";";
0220       print "\n";
0221     }
0222   }
0223 }
0224 
0225 ################################################################################
0226 
0227 if (scalar @ARGV != 1)
0228 {
0229   print STDERR "Usage: $0 function_call\n";
0230   print STDERR << "FNORD";
0231 Some options:
0232   $0 "mult_sym(3);"
0233   $0 "mult_sym_fma(3);"
0234   $0 "mult_sym_fma_intrinsic(6);"
0235 
0236   $0 "mult_std();"
0237 FNORD
0238 
0239   exit(1);
0240 }
0241 
0242 eval $ARGV[0];