UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor vemulpt2
Visitor
131 Views
Registered: ‎05-04-2019

Abnormal program termination during HLS synthesis

Hi, 

I'm trying to generate a systolic array for Matrix multiplication using HLS. However, I keep getting Abnormal program termination (11) error after the pre-synthesis step.

I've attached the source code(Unable to attach the file, so I've pasted it here), tcl script and hs_err log. Anyone have an idea how to fix it? This is really frustrating.

The problem is definitely in the gemm_systolic function. When I inline the load_a_pipes() function, the code synthesizes, but I get a DRC warning, and co-simulation deadlocks.

Thanks!

 

#include "gemm_systolic.h"

void PE(pe_stream &a_in, pe_stream &a_out,
		pe_stream &b_in, pe_stream &b_out,
		float & c_out) {
	float sum = 0;
	for(int i = 0; i < DIM; i ++) {
			float a = a_in.read();
			float b = b_in.read();

			sum += a*b;

			a_out.write(a);
			b_out.write(b);
	}
	c_out = sum;
}


float axis_read(AXIS &in) {
	//Cast int to float
	union {
		int ival;
		float fval;
	}converter;

	converter.ival = in.data;
	volatile auto last = in.last;

	return converter.fval;
}

AXIS axis_write(float const &val, bool last = false) {

	//Cast float to int
	union {
		int ival;
		float fval;
	}converter;

	AXIS ret;

	converter.fval = val;

	ret.data = converter.ival;
	ret.last = last;

	return ret;

}

void gemm_tiled(float A[M][K], float B[K][N], float C[M][N]) {
#pragma HLS INLINE

	L0:for(int i = 0; i < M; i++) {
		L1:for(int j = 0; j < N; j++) {
			float sum = 0;
			L2:for(int k = 0; k < K; k++) {
				sum += A[i][k] * B[k][j];
			}
			C[i][j] = sum;
		}
	}
}

void load_input_matrices(AXIS in_stream[M*K + K*N], float A[M][K], float B[K][N]) {
#pragma HLS INLINE
	int idx = 0;

	//Copy in first matrix
	for(int i = 0; i < M; i++) {
		load_A:for(int j = 0 ; j < K; j++) {
			A[i][j] = axis_read(in_stream[idx++]);
		}
	}

	for(int i = 0; i < K; i++) {
		load_B:for(int j = 0 ; j < N; j++) {
			B[i][j] = axis_read(in_stream[idx++]);
		}
	}
}

void write_output_matrix(AXIS out_stream[M*N], float C[M][N]) {
#pragma HLS INLINE
	int idx = 0;
	// Copy output matrix back
	for(int i = 0; i < M; i++) {
		write_C:for(int j = 0 ; j < N; j++) {
			out_stream[idx++] = axis_write(C[i][j], ((i == (M-1) && j == (N-1))));
		}
	}
}

void flush_pipe(pe_stream &pipe) {
	for(int i = 0; i < DIM; i++) {
#pragma HLS PIPELINE II=1
		pipe.read();
	}
}

void load_a_pipes(pe_stream a_pipes[DIM+1][DIM+1],const float A[DIM][DIM]) {
	for(int i = 0; i < DIM; i++) {
#pragma HLS UNROLL
		for(int j = 0; j < DIM; j++) {
#pragma HLS PIPELINE II=1
			a_pipes[0][i].write(A[j][i]);
		}
	}
}

void load_b_pipes(pe_stream b_pipes[DIM+1][DIM+1],const float B[DIM][DIM]) {
	for(int i = 0; i < DIM; i++) {
#pragma HLS UNROLL
		for(int j = 0; j < DIM; j++) {
#pragma HLS PIPELINE II=1
			b_pipes[i][0].write(B[i][j]);
		}
	}
}

void PE_inst(pe_stream a_pipes[DIM+1][DIM+1], pe_stream b_pipes[DIM+1][DIM+1], float C[DIM][DIM]) {
	PE_loop:for(int pe = 0; pe < DIM*DIM; pe++) {
#pragma HLS UNROLL
		int i = pe/DIM;
		int j = pe%DIM;
		PE(a_pipes[i][j], a_pipes[i+1][j], b_pipes[i][j], b_pipes[i][j+1], C[j][i]);
	}
}

void flush_pipes(pe_stream a_pipes[DIM+1][DIM+1], pe_stream b_pipes[DIM+1][DIM+1]) {
	for(int i = 0; i < DIM; i++) {
#pragma HLS UNROLL
		flush_pipe(a_pipes[DIM][i]);
	}
	for(int j = 0; j < DIM; j++) {
#pragma HLS UNROLL
		flush_pipe(b_pipes[j][DIM]);
	}
}

void gemm_systolic(const float A[DIM][DIM], const float B[DIM][DIM], float C[DIM][DIM]) {
#pragma HLS DATAFLOW
	pe_stream a_pipes[DIM+1][DIM+1];
	#pragma HLS STREAM variable=a_pipes
	#pragma HLS STREAM variable=b_pipes
	pe_stream b_pipes[DIM+1][DIM+1];

	load_a_pipes(a_pipes, A);

	load_b_pipes(b_pipes, B);

	PE_inst(a_pipes, b_pipes, C);
	flush_pipes(a_pipes, b_pipes);
}

void hls_gemm_systolic(AXIS in_stream[M*K + K*N], AXIS out_stream[M*N]) {
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE axis register both port=in_stream
#pragma HLS INTERFACE axis register both port=out_stream


	float A[M][K];
	float B[K][N];
	float C[M][N];
#pragma HLS ARRAY_PARTITION variable=A complete dim=1
#pragma HLS ARRAY_PARTITION variable=B complete dim=2
#pragma HLS ARRAY_PARTITION variable=C complete dim=1
#pragma HLS ARRAY_PARTITION variable=C complete dim=2

	load_input_matrices(in_stream, A, B);
	gemm_systolic(A,B,C);
	write_output_matrix(out_stream, C);


}
0 Kudos
2 Replies
Xilinx Employee
Xilinx Employee
87 Views
Registered: ‎07-21-2014

Re: Abnormal program termination during HLS synthesis

Hi @vemulpt2 

 

Sorry for the inconvenience. I have reproduced the issue at my end.

I will let you know the updates on this soon.

 

-Sheryas

----------------------------------------------------------------------------------------------
Try to search answer for your issue in forums or xilinx user guides before you post a new thread.

Kindly note- Please mark the Answer as "Accept as solution" if information provided solves your query.
Give Kudos (star provided in right) to a post which you think is helpful and reply oriented.
----------------------------------------------------------------------------------------------
0 Kudos
Xilinx Employee
Xilinx Employee
40 Views
Registered: ‎07-21-2014

Re: Abnormal program termination during HLS synthesis

Following are a couple of scenarios that could be causing the issue. Also, there are guidelines regarding this mentioned in UG902 page#215 "HLS Stream Library".

https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_1/ug902-vivado-high-level-synthesis.pdf

1- Array of streams is not supported.
so stream declarations-
pe_stream a_pipes[DIM+1][DIM+1];
pe_stream b_pipes[DIM+1][DIM+1];

can cause the issue and may not behave as expected.

2- hls::stream class should always be passed between functions as C++ reference arguments.
eg. in your case "load_a_pipes" function should receive "a_pipes" as reference argument from the function call.

In any case, tool should not crash and I am working on that. Meanwhile, you can modify the code according to the guidelines in UG.

-Shreyas

----------------------------------------------------------------------------------------------
Try to search answer for your issue in forums or xilinx user guides before you post a new thread.

Kindly note- Please mark the Answer as "Accept as solution" if information provided solves your query.
Give Kudos (star provided in right) to a post which you think is helpful and reply oriented.
----------------------------------------------------------------------------------------------