跳转到主要内容

使用 Python 调试 PCIe 问题

本文转载自:<span id="profileBt"><a href="https://mp.weixin.qq.com/s/QyU2PROW21ArcwbCahtjGQ"&gt; XILINX开发者社区</a></span>

<font color="#FF8000">本文作者:赛灵思工程师 Deepesh Man Shakya</font>

本篇博文提供了一个示例,用于演示如何使用 Python 脚本调试赛灵思 PCIe 设计。此处提供的技巧可应用于所有设计,而非仅供 PCIe 专用。

如果您当前使用的方法与此处所述方法类似,或者如果您决定使用所提供的脚本、在其基础上进一步强化,并愿意与我们分享您的脚本,我们将深表感激,并将与此论坛中的 PCIe 社区成员分享您提供的脚本。

<strong>获取 CSV:</strong>

现在,您不仅可以使用 Python 脚本执行调试分析,更重要的是,借由 Vivado ILA 所生成的 ILA 文件可以进一步简化此操作。通过将 *.ila 扩展名重命名为 *.zip 然后将生成的文件解压,即可将其转换为 CSV 文件。

解压后的文件夹将包含以下列表中的文件:
<center><img src="http://xilinx.eetrend.com/files/2022-04/wen_zhang_/100559142-248374-tu1…; alt=""></center>

Python 可提供相应的库,用于 CSV 文件分析,以便对 Vivado ILA 所生成的调试信号数据执行详尽的分析。调试信号还可在 Vivado 硬件管理器中以波形形式来查看。对于计算某些接口中的数据包数量、解读数据包内的字段值等分析操作,使用 Python 脚本方法更便于进行定制调试。

<strong>Python 脚本用例示例</strong>

此处提供的 Python 脚本会对 ILA 数据执行分析,这些数据包含下图所示的 RQ/RC/CQ/CC 接口信号。此模块框图源自 (PG213),该文档适用于 UltraScale+ 器件 Integrated Block for PCI Express IP。

PG213: https://docs.xilinx.com/r/zh-CN/pg213-pcie4-ultrascale-plus/%E5%BC%95%E…
<center><img src="http://xilinx.eetrend.com/files/2022-04/wen_zhang_/100559142-248375-tu2…; alt=""></center>

此脚本可识别每个接口上有效的数据包、提取每个数据包中的描述符文件,并报告输出每个字段的值。

<strong>适用于 PCIe 调试的 Python 代码示例:</strong>

该脚本执行的步骤如下所述:

<li>打开 CSV 文件。</li>

<li>从所选 CSV 文件中提取数据。</li>

<li>提取包含目标数据的特定列/报头。</li>

<li>使用“tready”、“tvalid”和“tlast”作为限定符来识别有效的数据包。</li>

<li>提取有效的 tdata 值,并使用函数执行十六进制到二进制转换。</li>

<li>二进制转换是从“tdata”提取比特级数据所必需的操作。</li>

<li>打印含十六进制数据的描述符字段。</li>

以下 func_rq_pkt_analysis() 函数会导入 CSV 文件并基于提供的 tready 值来判定要对哪个接口运行分析。
<center><img src="http://xilinx.eetrend.com/files/2022-04/wen_zhang_/100559142-248376-tu3…; alt=""></center>

以下代码可识别 .csv 文件中相应字段的列编号,如下所示:
<center><img src="http://xilinx.eetrend.com/files/2022-04/wen_zhang_/100559142-248381-tu4…; alt=""></center>

仅提取 tready 值、tdata 值、tvalid 值和 tlast 值,并将其存储在词典中,作为对应索引的值,该索引将用作为词典的键。
<center><img src="http://xilinx.eetrend.com/files/2022-04/wen_zhang_/100559142-248382-tu5…; alt=""></center>

下一步是对词典中存储的数据执行分析。词典包含 tdata、tready、tvalid 和 tlast。

for 循环会遍历词典中的每一行,如果发现 tready 和 tvalid 均为“1”,那么它会将对应数据复制到变量中。tdata 作为十六进制数值存储在 CSV 文件中。为了对描述符字段标识执行比特级提取,需将十六进制值转换为二进制。

描述符字段的提取是基于 (PG213) 中提供的描述符格式来执行的。以下示例显示了完成方完成 (CC) 接口的描述符。
<center><img src="http://xilinx.eetrend.com/files/2022-04/wen_zhang_/100559142-248383-tu6…; alt=""></center>
<center><img src="http://xilinx.eetrend.com/files/2022-04/wen_zhang_/100559142-248384-tu7…; alt=""></center>

为打印描述符字段值,需使用 bin_to_hex_print( ) 函数将此二进制值再次转换为十六进制。

该函数定义如下:
<center><img src="http://xilinx.eetrend.com/files/2022-04/wen_zhang_/100559142-248385-tu8…; alt=""></center>

以下是本篇博文随附的 waveform.csv 文件的输出示例:
<center><img src="http://xilinx.eetrend.com/files/2022-04/wen_zhang_/100559142-248386-tu9…; alt=""></center>

<strong>代码限制示例</strong>

提供的代码示例仅作为概念证明。提供的脚本则可在以下情况下“按现状”直接使用:

1.数据包包含 1 个数据节拍,即 tready/tvalid 和 tlast 全都在同一个时钟周期内断言有效。
2.不使用跨接。
3.对应接口的 tdata、tready、tvalid 和 tlast 的信号命名方式与本文随附的 .csv 文件中的命名相同。

<strong>使用 Python 执行 PCIe 调试的用例</strong>

Python 脚本示例可通过扩展用于调试下列各种场景:

1.计算每个接口上的数据包数量。

2.在启用跨接的用户接口上执行数据包分析。

3.支持分析含多个数据节拍的数据包,例如,跨多个时钟周期的数据包。

4.验证是否接收到拆分完成包。

5.在给定的 ILA 捕获窗口缓冲器大小足够的情况下,验证用户逻辑在 CC 接口上生成的完成包是否正确,并验证在 RC 接口上是否同样接收到完成包(用于 RQ 接口上的对应请求)。