// Filename : matrix_mult.cpp
//
// This file was initially generated by SpaceStudio but is meant to be modified
// by the user.
#include "matrix_mult.h"
#include "spacecomp_pre_cpp.h"


matrix_mult::matrix_mult(SPACECOMP_CTOR_PARAMS(matrix_mult, INDEX))
	: abstract_module(SPACECOMP_MBASE_ARGS(matrix_mult, INDEX))
	, SPACECOMP_START_ILIST(matrix_mult, INDEX)
{
	SPACECOMP_THREAD(matrix_mult, INDEX, thread);
	request_stack(16 * 1024 + (MATRIX_ROWS*MATRIX_COLUMNS*4*3));
}

void matrix_mult::thread(SPACECOMP_THREAD_PARAMS(matrix_mult, INDEX, thread)) {
	spacecomp_thread_initialize();
	uint32_t matrix1[MATRIX_ROWS*MATRIX_COLUMNS];
	uint32_t matrix2[MATRIX_ROWS*MATRIX_COLUMNS];
	uint32_t result[MATRIX_ROWS*MATRIX_COLUMNS];
	while (1) {
		const bool initializing = spacecomp_thread_loop_start();
		if (initializing) {}
		read_matrix(matrix1);
		read_matrix(matrix2);
		multiply(matrix1, matrix2, result);
		send_result(result);
	}
}

void matrix_mult::read_matrix(uint32_t* matrix) {
	ModuleRead(CONTROLLER0_ID, SPACE_BLOCKING, matrix, MATRIX_ELEMENTS);
	if (is_verbose()) {
		SpacePrint("Matrix_mult receiving... \n");
		for (unsigned i = 0; i < MATRIX_ROWS; ++i){
			SpacePrint("\t");
			for (unsigned j = 0; j < MATRIX_COLUMNS; ++j) {
				SpacePrint("%d ",matrix[i * MATRIX_ROWS + j]);
			}
			SpacePrint("\n");
		}
		SpacePrint("\n");
	}
}

void matrix_mult::send_result(uint32_t* matrix) {
	if (is_verbose()) {
		SpacePrint("Matrix_mult sending \n");
		for (unsigned i = 0; i < MATRIX_ROWS; ++i){
			SpacePrint("\t");
			for (unsigned j = 0; j < MATRIX_COLUMNS; ++j) {
				SpacePrint("%d ",matrix[i * MATRIX_ROWS + j]);
			}
			SpacePrint("\n");
		}
		SpacePrint("\n");
	}
	ModuleWrite(CONTROLLER0_ID, SPACE_BLOCKING, matrix, MATRIX_ELEMENTS);
}

void matrix_mult::multiply(uint32_t* in_1, uint32_t* in_2, uint32_t* out) {
	L1: for(int i=0;i<MATRIX_ROWS;i++)
		L2: for(int j=0;j<MATRIX_COLUMNS;j++) {
			out[i*MATRIX_ROWS+j]=0;
			L3: for(int k=0;k<MATRIX_COLUMNS;k++) {
//#pragma HLS unroll
//#pragma HLS PIPELINE II=2
				out[i*MATRIX_ROWS+j]+=in_1[i*MATRIX_ROWS+k]*in_2[k*MATRIX_ROWS+j];
			}
		}
}

#include "spacecomp_post_cpp.h"
