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: 
Explorer
Explorer
771 Views
Registered: ‎04-18-2017

How to force functions to interface each other?

Hello,

 

I have 6 functions that have axi stream (I set the pragma at the beginning of each of them so all the ports are axis) and I want them to be interfaced directly to each other rather than the input and output of each to go back to memory. I want the generated hardware to be like this:

 

diagram.png

 

Each of these functions will be accelerated separability into HW. I cannot build a wrapper and include all of them in a single function to be accelerated.

 

What pragmas should I use to achieve this? Is it possible to do it with SDSoC?

 

Thank you very much for the help.

0 Kudos
6 Replies
Explorer
Explorer
763 Views
Registered: ‎09-19-2017

Re: How to force functions to interface each other?

Hi aripod,

 

Unfortunately, right now the only way to get a direct connection is to call the hw functions in the same scope (ie. function) and pass the variable between the two functions. There is an example for the mmult() passing output source_mmult_out to the madd() function: https://github.com/Xilinx/SDSoC_Examples/blob/master/cpp/getting_started/direct_connect/src/main.cpp#L112 . You dont need any directives specific to making the direct connection, this happens automatically (if possible). 

 

Sam

0 Kudos
Explorer
Explorer
721 Views
Registered: ‎04-18-2017

Re: How to force functions to interface each other?

Hi @skalicky,

 

That is what I did in my main function. Here is a snippet where I use the variables and functions:

 

uint32_t FirstChunk[SPLITTED_SIZE_ARR];
uint32_t SecondChunk[SPLITTED_SIZE_ARR];
uint32_t ThirdChunk[SPLITTED_SIZE_ARR];
uint32_t FourthChunk[SPLITTED_SIZE_ARR];
uint32_t FilteredFirstChunk[SPLITTED_SIZE_ARR];
uint32_t FilteredSecondChunk[SPLITTED_SIZE_ARR];
uint32_t FilteredThirdChunk[SPLITTED_SIZE_ARR];
uint32_t FilteredFourthChunk[SPLITTED_SIZE_ARR];

// Split the input image
Split_four(input_ptr,FirstChunk,SecondChunk,ThirdChunk,FourthChunk);
// First Chunk
Passthrough(FirstChunk, FilteredFirstChunk);	// accelerated function.
// Second Chunk
Passthrough(SecondChunk, FilteredSecondChunk);	// accelerated function.
// Third Chunk
RgbxToGray(ThirdChunk, FilteredThirdChunk);	// accelerated function.
// Fourth Chunk
RgbxToGray(FourthChunk, FilteredFourthChunk);	// accelerated function.
//Merge The resultant Data
Merge_Four(FilteredFirstChunk, FilteredSecondChunk, FilteredThirdChunk, FilteredFourthChunk, output_ptr);

And the functions are:

#include "split_four.h"

#pragma SDS data mem_attribute(inputbuffer:PHYSICAL_CONTIGUOUS,  FirstChunk:PHYSICAL_CONTIGUOUS, SecondChunk:PHYSICAL_CONTIGUOUS, ThirdChunk:PHYSICAL_CONTIGUOUS, FourthChunk:PHYSICAL_CONTIGUOUS)
#pragma SDS data copy(inputbuffer[0:SIZE_ARR], FirstChunk[0:SPLITTED_SIZE_ARR], SecondChunk[0:SPLITTED_SIZE_ARR],ThirdChunk[0:SPLITTED_SIZE_ARR], FourthChunk[0:SPLITTED_SIZE_ARR])
#pragma SDS data data_mover(inputbuffer:AXIDMA_SIMPLE, FirstChunk:AXIDMA_SIMPLE, SecondChunk:AXIDMA_SIMPLE,ThirdChunk:AXIDMA_SIMPLE,FourthChunk:AXIDMA_SIMPLE)
#pragma SDS data access_pattern(inputbuffer:SEQUENTIAL, FirstChunk:SEQUENTIAL, SecondChunk:SEQUENTIAL,ThirdChunk:SEQUENTIAL,FourthChunk:SEQUENTIAL)

void Split_four(uint32_t inputbuffer[SIZE_ARR], uint32_t FirstChunk[SPLITTED_SIZE_ARR],uint32_t SecondChunk[SPLITTED_SIZE_ARR],uint32_t ThirdChunk[SPLITTED_SIZE_ARR],uint32_t FourthChunk[SPLITTED_SIZE_ARR])
{
#pragma HLS DATAFLOW
	uint32_t i1=0, i2=0, i3=0, i4=0;
    uint8_t section=0;

	for(uint32_t i=0; i<SIZE_ARR; i++)
	{
#pragma HLS PIPELINE II=1
		if(i%(COLS/2)==0 && i>0)
		{
			if(section==0)
				section=1;
			else
				section=0;
		}

		if(i<(SIZE_ARR/2))
		{
			if(section==0)
			{
				FirstChunk[i1] = inputbuffer[i];
				i1++;
			}
			else
			{
				SecondChunk[i2] = inputbuffer[i];
				i2++;
			}
		}
		else
		{
			if(section==0)
			{
				ThirdChunk[i3] = inputbuffer[i];
				i3++;
			}
			else
			{
				FourthChunk[i4] = inputbuffer[i];
				i4++;
			}
		}
	}
}
#include "merge.h"

#pragma SDS data mem_attribute(FirstChunk:PHYSICAL_CONTIGUOUS,  SecondChunk:PHYSICAL_CONTIGUOUS, ThirdChunk:PHYSICAL_CONTIGUOUS, FourthChunk:PHYSICAL_CONTIGUOUS, outputbuffer:PHYSICAL_CONTIGUOUS)
#pragma SDS data copy(FirstChunk[0:SPLITTED_SIZE_ARR], SecondChunk[0:SPLITTED_SIZE_ARR], ThirdChunk[0:SPLITTED_SIZE_ARR],FourthChunk[0:SPLITTED_SIZE_ARR], outputbuffer[0:SIZE_ARR])
#pragma SDS data data_mover(FirstChunk:AXIDMA_SIMPLE, SecondChunk:AXIDMA_SIMPLE, ThirdChunk:AXIDMA_SIMPLE,FourthChunk:AXIDMA_SIMPLE,outputbuffer:AXIDMA_SIMPLE)
#pragma SDS data access_pattern(FirstChunk:SEQUENTIAL, SecondChunk:SEQUENTIAL, ThirdChunk:SEQUENTIAL,FourthChunk:SEQUENTIAL,outputbuffer:SEQUENTIAL)

void Merge_Four(uint32_t FirstChunk[SPLITTED_SIZE_ARR],uint32_t SecondChunk[SPLITTED_SIZE_ARR],uint32_t ThirdChunk[SPLITTED_SIZE_ARR],uint32_t FourthChunk[SPLITTED_SIZE_ARR], uint32_t outputbuffer[SIZE_ARR])
{
/*#pragma HLS INTERFACE axis port=FirstChunk
#pragma HLS INTERFACE axis port=SecondChunk
#pragma HLS INTERFACE axis port=ThirdChunk
#pragma HLS INTERFACE axis port=FourthChunk
#pragma HLS INTERFACE axis port=outputbuffer*/
#pragma HLS DATAFLOW
	uint32_t i1=0, i2=0, i3=0, i4=0;
    uint8_t section=0;

	for(uint32_t i=0; i<SIZE_ARR; i++)
	{
#pragma HLS PIPELINE II=1
		if(i%(COLS/2)==0 && i>0)
		{
			if(section==0)
				section=1;
			else
				section=0;
		}

		if(i<(SIZE_ARR/2))
		{
			if(section==0)
			{
				outputbuffer[i] = FirstChunk[i1];
				i1++;
			}
			else
			{
				outputbuffer[i] = SecondChunk[i2];
				i2++;
			}
		}
		else
		{
			if(section==0)
			{
				outputbuffer[i] = ThirdChunk[i3];
				i3++;
			}
			else
			{
				outputbuffer[i] = FourthChunk[i4];
				i4++;
			}
		}
	}
}
#include "passthrough.h"

#pragma SDS data mem_attribute(input:PHYSICAL_CONTIGUOUS, output:PHYSICAL_CONTIGUOUS)
#pragma SDS data copy(input[O:SPLITTED_SIZE_ARR], output[0:SPLITTED_SIZE_ARR])   // Logically..it should be 0:SPLITTED_SIZE_ARR-1
#pragma SDS data data_mover(input:AXIDMA_SIMPLE, output:AXIDMA_SIMPLE)
#pragma SDS data access_pattern(input:SEQUENTIAL, output:SEQUENTIAL)
void Passthrough(uint32_t input[SPLITTED_SIZE_ARR], uint32_t output[SPLITTED_SIZE_ARR])
{
#pragma HLS INTERFACE axis port=input
#pragma HLS INTERFACE axis port=output
#pragma HLS DATAFLOW
	for(int i=0; i<SPLITTED_SIZE_ARR; i++)
	{
#pragma HLS PIPELINE II=1
		output[i] = input[i];
	}
}
#include <RgbxToGray.h>

#pragma SDS data mem_attribute(input:PHYSICAL_CONTIGUOUS, output:PHYSICAL_CONTIGUOUS)
#pragma SDS data copy(input[O:SPLITTED_SIZE_ARR], output[0:SPLITTED_SIZE_ARR])   // Logically..it should be 0:SPLITTED_SIZE_ARR-1
#pragma SDS data data_mover(input:AXIDMA_SIMPLE, output:AXIDMA_SIMPLE)
#pragma SDS data access_pattern(input:SEQUENTIAL, output:SEQUENTIAL)
void RgbxToGray(uint32_t input[SPLITTED_SIZE_ARR], uint32_t output[SPLITTED_SIZE_ARR])
{
#pragma HLS INTERFACE axis port=input
#pragma HLS INTERFACE axis port=output
#pragma HLS DATAFLOW
	for(int i=0; i<SPLITTED_SIZE_ARR; i++)
	{
#pragma HLS PIPELINE II=1
		//output[i] = input[i];

		// Extract values
		uint8_t red   = (uint8_t)((input[i] >>  0) & 0xFF); // (data << 24) >> 24;
		uint8_t green = (uint8_t)((input[i] >>  8) & 0xFF); // data(data << 16) >> 24;
		uint8_t blue  = (uint8_t)((input[i] >> 16) & 0xFF); // (data << 8) >> 24;

		uint32_t gray = (307 * (uint32_t)red + 604 * (uint32_t)green + 113 * (uint32_t)blue) >> 10;
		uint32_t gray_norm = gray * 0x00010101;
		// Store output
		output[i] = gray_norm;
	}
}

They work, but as the functions (or rather HW blocks) are not connected directly to each other, I have a very lo frame rate. They end up being each of them connected back to the processor rather the "pipeline" design I need. Therefore, I need it for my design the HW to be like the block diagram I draw.

 

Thanks for the help.

0 Kudos
Highlighted
Explorer
Explorer
708 Views
Registered: ‎09-19-2017

Re: How to force functions to interface each other?

Hi aripod,

 

Im confused by your diagram when compared to the code you posted. Can you repost the diagram with the function names matching the source code you posted?

 

It looks like you have the following setup:

 

Split_four --> {Passthrough_0, Passthrough_1, RgbxToGray_0, RgbxToGray_1} --> Merge_Four

 

Is this the design you're trying to achieve? If so, you need to accelerate the split_four and merge_four functions. Then SDSoC should pick up the data flow and put all 6 functions in hardware with direct connections to each other. 


Sam

 

 

0 Kudos
Explorer
Explorer
687 Views
Registered: ‎04-18-2017

Re: How to force functions to interface each other?

Hi @skalicky,

 

It is like you said:

diagram.png

 

I all four functions into HW, so I accelerate all of them but regardless of using the variables I don't get the "pipeline" design I am looking for. Why do you say I should only accelerate split and merge? And the other two ones? They also have to be in HW, as they are the most processing-intensive ones.

 

Thanks for the help.

 

EDIT: I quickly tested just accelerating split and merge but this ended up the same way. not in a "pipeline" fashion and with passthorugh and rgbxtogray only on software.

0 Kudos
Explorer
Explorer
673 Views
Registered: ‎09-19-2017

Re: How to force functions to interface each other?

Hi aripod,

 

I didnt say you need to accelerate "only" split and merge. You need to also accelerate split and merge in addition to passthrough and rgbxtogray (all 4 functions) in order to get all of them in hardware with the pipeline structure you're looking for. 

 

Sam

0 Kudos
Explorer
Explorer
665 Views
Registered: ‎04-18-2017

Re: How to force functions to interface each other?

Hi @skalicky,

 

I know.....and that's why I started this thread, because I don't get that pipeline design that I want when I accelerate all functions and "connect" them with variables.

 

Thanks for the help.

0 Kudos