cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
ymherklotz
Visitor
Visitor
574 Views
Registered: ‎06-06-2019

Mismatch between C simulation and RTL simulation using volatile

Hi,

The following bug produces an error in Vivado HLS 2018.3, 2019.1 and 2019.2.  I have attached a directory with all the necessary files below.

To create the project layout, we can first create the ./bug.c file which produces the bug.  This was reduced from a much larger program that was calculating the CRC of a result.

./bug.c

volatile unsigned int g = 0;
int a[256] = {0};
int c = 0;

void d(char b) {
  c = (c & 4095) ^ a[(c ^ b) & 15];
}

void e(long f) {
  d(f); d(f >> 8); d(f >> 16); d(f >> 24);
  d(f >> 32); d(f >> 40); d(f >> 48);
}

int result() {
  for (int i = 0; i < 56; i++)
    a[i] = i;
  e(g);
  e(-2L);
  return c;
}

We then have to generate a main function to provide the golden output. We first write the following driver into ./bug_driver.c which contains the main function that generates the checksum.

./bug_driver.c

#include "stdio.h"

int result();

int main() { printf("checksum = %X\n", result()); }

Then generate the golden output using GCC by compiling the driver with the initial bug and check the golden output. This golden output is then written to out.gold.txt.

gcc bug_driver.c bug.c -o bug_gcc
./bug_gcc | tee out.gold.txt
checksum = F

We then also need to provide a test bench for Vivado that will detect a mismatch between the Verilog simulation and C output. This loads the file out.gold.txt and checks that the output is equivalent to the current result.

./bug_tb.c

#include <stdio.h>

unsigned int result();

int main () {
  FILE *fp;
  FILE *fp1;
  unsigned int resultOut;
  char str[1000];
  fp=fopen("out.txt","w");
  fp1=fopen("out.gold.txt", "r");

  resultOut = result();
  printf("Verilog result is %X\n", resultOut);
  printf("C output:");
  while (fgets(str, 1000, fp1) != NULL) printf("%s", str);
  fprintf(fp,"checksum = %X\n",resultOut);

  fclose(fp);
  fclose(fp1);

  printf ("Comparing against output data \n");

  if (system("diff -w out.txt out.gold.txt")) {
    fprintf(stdout, "*******************************************\n");
    fprintf(stdout, "FAIL: Output DOES NOT match the golden output\n");
    fprintf(stdout, "*******************************************\n");
    return 1;
  } else {
    fprintf(stdout, "*******************************************\n");
    fprintf(stdout, "PASS: The output matches the golden output!\n");
    fprintf(stdout, "*******************************************\n");
    return 0;
  }
}

Finally, we create the tcl file to create the Vivado project and include all the relevant source files.

./vivado.tcl

open_project -reset bug
set_top result
add_files bug.c
add_files -tb out.gold.txt
add_files -tb bug_tb.c
open_solution -reset "solution1"
set_part {xc7z020-clg484-1}
create_clock -period 10 -name default
csynth_design
csim_design
cosim_design
export_design -format ip_catalog
exit

Then we can run the vivado_hls command to run Vivado HLS and check for the bug.

vivado_hls -f vivado.tcl | tail -n24
INFO: [Common 17-206] Exiting xsim at Fri Oct  2 16:32:50 2020...
INFO: [COSIM 212-316] Starting C post checking ...
1c1
< checksum = 0
---
> checksum = F
Verilog result is 0
C output:checksum = F
Comparing against output data
*******************************************
FAIL: Output DOES NOT match the golden output
*******************************************
ERROR: [COSIM 212-361] C TB post check failed, nonzero return value '1'.
ERROR: [COSIM 212-4] *** C/RTL co-simulation finished: FAIL ***
INFO: [COSIM 212-211] II is measurable only when transaction number is greater than 1 in RTL simulation. Otherwise, they will be marked as all NA. If user wants to calculate them, please make sure there are at least 2 transactions in RTL simulation.
command 'ap_source' returned error code
    while executing
"source vivado.tcl"
    ("uplevel" body line 1)
    invoked from within
"uplevel \#0 [list source $arg] "

INFO: [HLS 200-112] Total elapsed time: 43.31 seconds; peak allocated memory: 92.524 MB.
INFO: [Common 17-206] Exiting vivado_hls at Fri Oct  2 16:32:51 2020...
0 Kudos
2 Replies
xilinxacct
Professor
Professor
519 Views
Registered: ‎10-23-2018

@ymherklotz 

I think your types are the problem... you are shifting more bits than a 'long' holds. (I suspect you are getting an overflow message). HLS long is a 32 bit value... use long long for 64 bit. (you also 'may' want to be consistent on choice of unsigned)

Hope that Helps
If so, Please mark as solution accepted. Kudos also welcomed.

0 Kudos
ymherklotz
Visitor
Visitor
481 Views
Registered: ‎06-06-2019

Hi @xilinxacct,

Thank you for the quick reply.

You are right that I should have used `long long` in the code example.  Substituting `long` for `long long` does not solve it though, and the output still contains a mismatch between the C simulation and RTL simulation.

Finally, being constistent in the use of signed and unsigned should not affect the value of the output.  Interestingly, changing unsigned to signed does seem to give the same result as C.  However, converting `unsigned` to `long long` or `int` to `long long` should not be different.

The test case that still shows different behaviour in GCC and Vivado is shown below.

volatile unsigned int g = 0;
int a[256] = {0};
int c = 0;

void d(char b) {
  c = (c & 4095) ^ a[(c ^ b) & 15];
}

void e(long long f) {
  d(f); d(f >> 8); d(f >> 16); d(f >> 24);
  d(f >> 32); d(f >> 40); d(f >> 48);
}

int result() {
  for (int i = 0; i < 56; i++)
    a[i] = i;
  e(g);
  e(-2L);
  return c;
}

 Thank you,

Yann

0 Kudos