使用XSCOPE快速打印调试
上一节中在tiles之间通信的例子非常慢,因为每一行文本输出到主机终端的时间很长。如果增加ITERATIONS的值,这个问题就更明显了。
这种默认行为之所以慢,有以下几个原因:
- 使用了JTAG接口来控制传输。
- 没有为传输数据提供缓冲区。
- 数据是通过调试内核传输的。在一个tile上的所有运行中的逻辑核都会在给定逻辑核完成传输时暂停。
很明显,这种默认行为会对正在调试的应用程序的实时性能造成严重影响。为了解决这个问题,XMOS提供了XSCOPE接口。
XSCOPE接口利用了物理高带宽的XLINK连接到XTAG调试器。缓冲区是在XTAG调试器上提供的。通过这种机制,就不需要在一个逻辑核进行传输时暂停其他逻辑核。
最终的结果是,XSCOPE可以作为一个高性能的调试接口,对正在检查的应用程序的实时性能影响很小。因此,在几乎所有情况下,都建议使用XSCOPE。
配置和使用XSCOPE
在下面的例子中,我们使用XSCOPE 来加速上一篇文章中的调试例子:在tiles之间通信。
XSCOPE是通过创建一个XML XSCOPE配置文件来配置的,这个文件的后缀是:.xscope。这里我们创建一个最基本的配置文件:
<xSCOPEconfig ioMode="basic" enabled="true">
</xSCOPEconfig>
XCC可以识别这个后缀的文件。这个文件作为一个参数在构建时提供给XCC(如果编译和链接作为单独的构建步骤,那么在链接步骤时提供):
xcc -target=XK-EVK-XU316 basic.xscope multitile.xc main.c
现在使用 xrun --xscope 运行应用程序(不要像之前那样使用--io):
打印输出现在看起来几乎是瞬间完成的,你可以试着增加ITERATIONS的值来验证这一点。
在一个tile的一个或多个逻辑核上使用XSCOPE会导致一个通道端被分配给XSCOPE使用。
试着把 ioMode 从 basic 改成 timed。这会让输出时间戳和打印数据一起显示在控制台上。注意这也会占用缓冲空间。
配置XSCOPE的另一种方法是使用xscope_user_init()函数,但这种方法已经被弃用了。
使用XSCOPE“探针”
除了像上面那样使用XSCOPE来加速字面意义上的“printf调试”之外,XSCOPE“探针”还可以用来向主机发送命名的数据流,以便于调试。这些数据流可能是ADC采样值等数据。
XSCOPE探针使用的底层机制与上面的printf()调用使用的相同。但是,探针更加高效,因为它们避免了CPU时间和数据传输方面的开销。
在XSCOPE文件中添加探针的配置如下:
<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>
现在XSCOPE探针已经配置好了,我们可以通过在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(0, result);
chan_out_word(c, ITERATIONS);
result = chan_in_word(c);
printf("Tile 0: Result %d\n", result);
xscope_int(0, 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(1, i);
xscope_int(2, accumulation);
}
chan_out_word(c, accumulation);
}
和之前一样进行构建:
xcc -target=XK-EVK-XU316 probes.xscope multitile.xc main.c
这次运行时,添加--xscope-file来指定一个文件来写入探针的输出:
xrun --xscope --xscope-file xscope.vcd a.xe
在当前目录下会生成一个标准的VCD文件xscope.vcd,它可以用任何第三方的VCD查看器打开。其中一个选择是GTKWave。使用以下命令以通过gtkwave来查看VCD文件:
gtkwave xscope.vcd
在将信号“拖拽”到查看区域后,显示效果可能是这样的:

GTKWave或其他VCD查看器的安装和使用超出了本文档的范围。
本例中描述的XScope调试追踪可以使用XSIM进行。
总结
你现在可以使用XScope功能来进行“printf调试”。事实上,这种方法(使用xrun --xscope)应该总是优先选择的方法,而不是之前教程中展示的默认方法(使用xrun --io)。
