Troubleshooting Runtime Errors

Programs compiled using sdscc/sds++ can be debugged using the standard debuggers supplied with the SDSoC™ environment or Xilinx® SDK. Typical runtime errors are incorrect results, premature program exits, and program “hangs.” The first two kinds of errors are familiar to C/C++ programmers, and can be debugged by stepping through the code using a debugger.

A program hang is a runtime error caused by specifying an incorrect amount of data to be transferred across a streaming connection created using #pragma SDS data access_pattern(A:SEQUENTIAL), by specifying a streaming interface in a synthesizeable function within Vivado HLS, or by a C-callable hardware function in a pre-built library that has streaming hardware interfaces. A program hangs when the consumer of a stream is waiting for more data from the producer but the producer has stopped sending data.

Consider the following code fragment that results in streaming input/output from a hardware function.
#pragma SDS data access_pattern(in_a:SEQENTIAL, out_b:SEQUENTIAL)
void f1(int in_a[20], int out_b[20]);     // declaration

void f1(int in_a[20], int out_b[20]) {    // definition
   int i;
   for (i=0; i < 19; i++) {
       out_b[i] = in_a[i];
   }
}

Notice that the loop reads the in_a stream 19 times but the size of in_a[] is 20, so the caller of f1 would wait forever (or hang) if it waited for f1 to consume all the data that was streamed to it. Similarly, the caller would wait forever if it waited for f1 to send 20 int values because f1 sends only 19. Program errors that lead to such “hangs” can be detected by using system emulation to review whether the data signals are static (review the associated protocol signals TLAST, ap_ready, ap_done, TREADY, etc.) or by instrumenting the code to flag streaming access errors such as non-sequential access or incorrect access counts within a function and running in software. Streaming access issues are typically flagged as improper streaming access warnings in the log file, and it is left to the user to determine if these are actual errors. Running your application on the SDSoC emulator is a good way to gain visibility of data transfers with a debugger. You will be able to see where in software the system is hanging (often within a cf_wait() call), and can then inspect associated data transfers in the simulation waveform view, which gives you access to signals on the hardware blocks associated with the data transfer.

The following list shows other sources of run-time errors:
  • Improper placement of wait() statements could result in:
    • Software reading invalid data before a hardware accelerator has written the correct value
    • A blocking wait() being called before a related accelerator is started, resulting in a system hang
  • Inconsistent use of memory consistency #pragma SDS data mem_attribute can result in incorrect results.