Vivado Mismatch using volatile

Reported Fixed
Issue X

The following bug produces an error in Vivado HLS 2018.3, 2019.1 and 2019.2.

To create the project layout, we can first create the ./bug.c file which produces the bug.

./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...