Using xSCOPE for fast “printf debugging”#
The previous example in Communicating between tiles was very slow due to the time taken
to print each line of text to the terminal. This is made particularly noticable
if the value of ITERATIONS
is increased.
This default behaviour can be slow for a number of reasons:
A JTAG interface is being used to control the transfer.
There is no buffering for the transferred data.
The data is transferred via the debug kernel. All running logical cores on a tile are halted whilst the transfer on a given logical core completes.
It is clear to see that the default behaviour can play havoc if the application being debugged has any real-time constraints. To mitigate this problem, the xSCOPE interface is provided.
![../../_images/debug-setup.png](../../_images/debug-setup.png)
Fig. 2 xTAG debug setup showing JTAG and xLINK connections#
The xSCOPE interface makes use of a physical high bandwidth xLINK connection to the xTAG debugger. Buffering is provided on the xTAG debugger itself. Through this mechanism there is no need to halt all the logical cores whilst another conducts a transfer.
The net result is that xSCOPE can be used as a high performance debug interface with minimal impact on the real-time performance of the application under examination. Use of xSCOPE is thus recommended in almost all cases.
Configuring and using xSCOPE#
This example presumes that we are using xSCOPE to accelerate debug of the previous example: Communicating between tiles.
xSCOPE is configured by creating an XML xSCOPE config file with the
suffix: .xscope
. Here we create the most basic configuration file:
<xSCOPEconfig ioMode="basic" enabled="true">
</xSCOPEconfig>
XCC recognises files with this suffix. The file is provided to XCC as an argument during building. If compiling and linking separately, the .xscope files must be provided to XCC at every stage, since they are used both to autogenerate definitions at compile time, and provide functionality at link time.
xcc -target=XCORE-200-EXPLORER basic.xscope multitile.xc main.c
Now run the application using xrun --xscope
(not
--io
as previously used):
xrun --xscope a.xe
The printed output is now produced seemingly instantaneously. Try increasing the
value for ITERATIONS
.
Important
Use of xSCOPE on one or more logical cores of a tile results in a single channel end being allocated for use by xSCOPE.
Tip
Try changing ioMode
from basic
to timed
. This causes
the output timestamp to be displayed with the written data.
Note that this also reduces the amount of data that can be buffered at any
time.
Using xSCOPE “probes”#
As well as using xSCOPE to accelerate literal “printf debugging” as above, xSCOPE “probes” can be used to send named streams of data to the host for debugging purposes. For example, these could be streams of ADC samples.
The underlying mechanism used for xSCOPE probes is the same as that used by the
calls to printf()
above. Probes however are even more efficient, as they
avoid overheads both in CPU time and data transfer.
Probes are added into the xSCOPE config file as follows:
<xSCOPEconfig ioMode="basic" enabled="true">
<Probe name="Tile0 Result" type="CONTINUOUS" datatype="UINT" units="mV" enabled="true"/>
<Probe name="Tile1 i" type="CONTINUOUS" datatype="UINT" units="mV" enabled="true"/>
<Probe name="Tile1 Accumulation" type="CONTINUOUS" datatype="UINT" units="mV" enabled="true"/>
</xSCOPEconfig>
With xSCOPE probes now configured, they can be exploited by adding the
highlighted modifications into main.c
:
#include <stdio.h>
#include <xcore/channel.h>
#include <xscope.h>
#define ITERATIONS 10
void main_tile0(chanend_t c)
{
int result = 0;
printf("Tile 0: Result %d\n", result);
xscope_int(TILE0_RESULT, result);
chan_out_word(c, ITERATIONS);
result = chan_in_word(c);
printf("Tile 0: Result %d\n", result);
xscope_int(TILE0_RESULT, result);
}
void main_tile1(chanend_t c)
{
int iterations = chan_in_word(c);
int accumulation = 0;
for (int i = 0; i < iterations; i++)
{
accumulation += i;
printf("Tile 1: Iteration %d Accumulation: %d\n", i, accumulation);
xscope_int(TILE1_I, i);
xscope_int(TILE1_ACCUMULATION, accumulation);
}
chan_out_word(c, accumulation);
}
Build similarly to before:
xcc -target=XCORE-200-EXPLORER probes.xscope multitile.xc main.c
This time, when running, add --xscope-file
to
specify a file to write the probe output into:
$ xrun --xscope --xscope-file xscope.vcd a.xe
A standard VCD file xscope.vcd
is produced in the current directory,
which can be opened with any third-party VCD viewer. One option is
GTKWave. To use gtkwave to view
the VCD file:
$ gtkwave xscope.vcd
After ‘dragging’ the signals into the viewing area, the display might look like this:
![../../_images/gtkwave.png](../../_images/gtkwave.png)
Installation and use of GTKWave or other VCD viewers is outside the scope of this document.
Note
xSCOPE tracing as described in this example can be performed using XSIM.
Summary#
xSCOPE can be used to perform fast “printf debugging”. This
method (using xrun --xscope
instead of xrun --io
)
is faster than printf debugging over JTAG. It is much better for real-time
performance, and should often be the preferred option.