// ************************************************************************** //
//                                                                            //
//    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 following module implements a systolic array for matrix multiplication //
// where the two NxN matrices are piped into a NxN element systolic array.    //
// Note the skewed pipelining of the inputs.                                  //
// ************************************************************************** //

macro N=4;

module MatMul([N]nat ?x,?y,[N][N]nat c) {
    [N][N]nat a,b;
    loop {
        w: pause;
        for(i=0..N-1)
            for(j=0..N-1) {
                next(a[i][j]) = (j==0 ? x[i] : a[i][j-1]);
                next(b[i][j]) = (i==0 ? y[j] : b[i-1][j]);
                next(c[i][j]) = c[i][j] + a[i][j] * b[i][j];
            }
    }
}
drivenby {
    [N][N]nat ma,mb;
    ma = [
        [4,1,2,1],
        [3,2,4,3],
        [2,3,6,5],
        [1,4,8,7]
        ];
    mb = [
        [1,5,2,6],
        [2,4,2,5],
        [2,3,1,4],
        [1,2,1,3]
        ];

    pause;

    // skewed input of the matrices
    for(t=0..N+N-1) {
        for(i=0..N-1) {
            x[i] = (t<=N-1+i & i<=t ? ma[i][N-1-(t-i)] : 0);
            y[i] = (t<=N-1+i & i<=t ? mb[N-1-(t-i)][i] : 0);
        }
        pause;
    }
    pause;
    pause;
    pause;
    pause;

}