Forum Discussion
Generated code by Intel HLS does not work
I have the following code:
hls_always_run_component void Target00(ihc::mm_master<word4_t,ihc::aspace<7>, ihc::awidth<32>, ihc::dwidth<32>, ihc::latency<0>, ihc::waitrequest<true> >& device_5, ihc::stream_in<word4_t>& module8_read, ihc::stream_out<word4_t>& module8_write) {
static int kernel_size;
static int height;
static int width;
static int go;
static unsigned long lImageSrc_addr;
static unsigned long result_array_addr;
static bool is_initialized = false;
if (!is_initialized) {
module_init(kernel_size, height, width, go, lImageSrc_addr, result_array_addr);
is_initialized = true;
}
unsigned char lImageSrc[76800];
unsigned char result_array[76800];
module_read_routing_712(HOST0_ID, module8_read, reinterpret_cast<word4_t*>(&lImageSrc_addr), 1);
module_read_routing_771(HOST0_ID, module8_read, reinterpret_cast<word4_t*>(&result_array_addr), 1);
module_read_routing_833(HOST0_ID, module8_read, reinterpret_cast<word4_t*>(&kernel_size), 1);
module_read_routing_889(HOST0_ID, module8_read, reinterpret_cast<word4_t*>(&height), 1);
module_read_routing_940(HOST0_ID, module8_read, reinterpret_cast<word4_t*>(&width), 1);
device_read_routing_993(DEVICEMEMORY_ID, device_5, reinterpret_cast<word4_t*>((unsigned int*)lImageSrc), lImageSrc_addr, 16);
device_read_routing_1074(DEVICEMEMORY_ID, device_5, reinterpret_cast<word4_t*>((unsigned int*)result_array), result_array_addr, 16);
module_read_routing_1164(HOST0_ID, module8_read, reinterpret_cast<word4_t*>(&go), 1);
unsigned long loffset = 0;
int kernel_half = (kernel_size - 1) / 2;
unsigned int pixel;
int private_kernel[7][7] = { 1 };
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
unsigned int sum = 0, x = 0, y = 0;
for (int ky = 0; ky < kernel_size; ky++) {
for (int kx = 0; kx < kernel_size; kx++) {
if (j + kx - kernel_half < 0) {
x = 0;
} else if (j + kx - kernel_half > width - 1) {
x = width - 1;
} else {
x = j + kx - kernel_half;
}
if (i + ky - kernel_half < 0) {
y = 0;
} else if (i + ky - kernel_half > height - 1) {
y = height - 1;
} else {
y = i + ky - kernel_half;
}
pixel = lImageSrc[x + y * width];
sum += ((int)pixel) * private_kernel[ky][kx];
}
}
// Put the result in output memory using a buffer
result_array[j + (i * width)] = (sum / 49);
}
}
device_write_routing_2218(DEVICEMEMORY_ID, device_5, reinterpret_cast<word4_t*>((unsigned int*)lImageSrc), lImageSrc_addr, 16);
device_write_routing_2300(DEVICEMEMORY_ID, device_5, reinterpret_cast<word4_t*>((unsigned int*)result_array), result_array_addr, 16);
module_write_routing_2388(HOST0_ID, module8_write, reinterpret_cast<word4_t*>(&go), 1);
}The expected behavior is the following:
- Read 5 words from a streaming interface
- Read 16 words from a memory (memory map interface)
- Read 16 words from a memory (memory map interface)
- Read 1 word from a streaming interface
- Perform the algorithm (computation)
- Write 16 words to the memory (memory map interface)
- Write 16 words to the memory (memory map interface)
- Write 1 word to a streaming interface
In the generated component, the step 1 and 2 works! Steps 3, 4, 5, 6, 7 and 8 does not work. I even tried to comment out steps 3 and 4 to skip directly to the computation but I am not able to make the generated code performs steps 5, 6, 7 and 8.
At this point, I have no glue about what is going on. Can an Intel HLS engineer give me some input on this issue?
I have also attached the full cpp code + modelsim testbench.
Thanks,
Hubert
To give more context:
The step 1 is the group of function calls { module_read_routing_712, module_read_routing_771, module_read_routing_833, module_read_routing_889, module_read_routing_940 }
The step 2 is the call to device_read_routing_993.
The step 3 is the call to device_read_routing_1074.
The step 4 is the call to module_read_routing_1164.
The step 5 is the code between step 4 and 6.
The step 6 is the call to device_write_routing_2218.
The step 7 is the call to device_write_routing_2300.
The step 8 is the call to module_write_routing_2388.
Hi,
The problem was with the avalon_mm_adapter. @HGuer2 will confirm that the message I sent him fixes the issue.
Sincerely
21 Replies
- HGuer2
New Contributor
I have been using v17.1
- KennyT_altera
Super Contributor
I try to run your design, it mention that missing platformdefinition.h. Can you help to make sure all the files in your zip files? So that I can try run your design. Also, can you provide the steps that you have done to run the simulation. - HGuer2
New Contributor
Sorry for the missing file. I have attached it (with additional testbench files)
To run the simulation, I have done the following:
- Create an empty folder (i.e., C:\testbench)
- Launch "ModelSim - Intel FPGA Starter Edition"
- Within ModelSim, create a new project (inside the folder of step 1)
- Add all HLD (*.sv, *.v and *.vhdl) from from the generated Intel HLS project. Use the "Add Existing FIle" option and add the files located inside the following directories:
- hls\Target00\Target00.prj\components\%kernel%\*
- hls\Target00\Target00.prj\components\%kernel%\ip\*
- hls\Target00\Target00.prj\components\%kernel%\windows64\lib\dspba\Libraries\vhdl\base\*
- Also add the testbench files (see attached zip)
- avalon_mm_adapter.vhd
- Target00_top.vhd
- top.vhd
- In the project tab, select all Verilog files and:
- Right-click and select "Properties"
- Click on the "Verilog & SystemVerilog" tab and select "Use SystemVerilog" for the "Language Syntax" option.
- Generate the compile order by selecting "Compile" and "Compile Order" in the tool bar. Then click "Auto Generate"
- Launch the simulation with the following command vsim -gui -L altera_ver -L lpm_ver -L sgate_ver -L altera_mf_ver -L altera_lnsim_ver -L cyclonev_ver -L altera -L lpm -L sgate -L altera_mf -L altera_lnsim work.top
- Add the required signals add wave -position end sim:/top/system_inst/*
- Start the simulation with the run command for about 2000 ns
- KennyT_altera
Super Contributor
I am still seeing some error when compile your design,
error: use of undeclared identifier 'SPACE_FULL'
return SPACE_FULL;
I am using the Makefile from the design example(attached), did you create your own Makefile? if yes, can you attached it?
make test-x86-64
- HGuer2
New Contributor
Here the command I use to compile:
i++ -march=5CSEMA5F31C6 --component Target00 Target00.cpp --simulator none --clock 10ns -o Target00I have updated the zip to add the missing const (my bad)
- HGuer2
New Contributor
Were you able to replicate the same behavior on your end ?
- KennyT_altera
Super Contributor
Sorry, I am tied to some work this week, I will try to get back to you by next week
- KennyT_altera
Super Contributor
I try run your design, where do you put your testbench files? Testbench files should be automatic generated if you have a int main function. How do you create your own Testbench files? I would suggest you use the int main function in your .cpp code so that the testbench auto created by not using -simulator none- KennyT_altera
Super Contributor
By using this, you will get a testbench in Target00.prj/verification. I would recommend you run a design example <quartus_installation_dir>\hls\examples for the HLS to check on this.
basically, you enable full visibility of all the hdl signal with i++ -ghdl flag
And run the simulation by
vsim test00.prj/verification/vsim.wlf
- HGuer2
New Contributor
I cannot use the verification since I am using the hls_always_run_component argument.
Like I said, you need to create a new ModelSim project where you import all files (generated file by HLS and testbench files { avalon_mm_adapter.vhd, Target00_top.vhd, top.vhd } ).
The top.vhd is the top-level and contains all the stimulus for the generated HLS IP.
- HGuer2
New Contributor
The detailed procedure above works flawlessly to run the simulation.
- KennyT_altera
Super Contributor
Hi,
I give you an example here,
component int accelerate(int a, int b) {
return a+b ;
}
int main() {
srand (0);
for (int i=0; i<10 ; ++ i) {
int x=rand() % 10 ;
int y=rand() % 10 ;
int z= accelerate (x, y);
printf ("%d + %= ("%d + %= \n", x, y, z);
assert(z == x + y); assert(z == x + y);
}
return 0;
}
accelerate is the component for the FPGA, main() become testbench for component accelerate.
Regarding the testbench top.vhd, is this testbench hand coded by you? The way of the avalon mm to write the testbench have to follow the bfm https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_avalon_verification_ip.pdf.
So, I would strongly recommend you auto create the testbench like the example above, otherwise you will have to learn the bfm.
- HGuer2
New Contributor
Alright, I will convert my test-case to use the component attribute along with a main in order to auto-generate a testbench and I will report on my findings. Thanks
- KennyT_altera
Super Contributor
Sure. try to run the example <quartus_installation_dir>/hls/tutorials/interfaces. The instruction is in the README files. This will help you understand more on the test-bench.