// ************************************************************************** //
//                                                                            //
//    eses                   eses                                             //
//   eses                     eses                                            //
//  eses    eseses  esesese    eses   Embedded Systems Group                  //
//  ese    ese  ese ese         ese                                           //
//  ese    eseseses eseseses    ese   Department of Computer Science          //
//  eses   eses          ese   eses                                           //
//   eses   eseses  eseseses  eses    University of Kaiserslautern            //
//    eses                   eses                                             //
//                                                                            //
// ************************************************************************** //
// The module below implements a matrix multiplication using O(D1*D2*D3)      //
// processors to perform the multiplication in O(D2) depth. Clearly, this is  //
// not optimal, since the multiplication can be done by O(D1*D2*D3) processors//
// in O(log(D2)) depth using a balanced summation obtained by prefix sums.    //
// ************************************************************************** //

macro D1 = 3;
macro D2 = 4;
macro D3 = 5;

module MatrixMultCombN([D1][D2]int ?a, [D2][D3]int ?b, [D1][D3]int c){
    for(i=0..D1-1)
        for(j=0..D3-1)
            c[i][j] = sum(k=0..D2-1) (a[i][k] * b[k][j]);
}
drivenby {
    for(i=0..D1-1)
        for(j=0..D2-1)
            a[i][j] = i*D2+j;
    for(i=0..D2-1)
        for(j=0..D3-1)
            b[i][j] = i*D3+j;
    // check correctness of matrix multiplication
    for(i=0..D1-1)
        for(j=0..D3-1)
            assert(c[i][j] == sum(k=0..D2-1) (a[i][k] * b[k][j]));
}