Essential Bit 查询方法及示例 —— 基于 VPK180 的 XilSEM EBD 实现

作者:Ivy Guo,AMD工程师;来源:AMD开发者社区

SEU 事件本身比较罕见,但当 SEM 应用于量产产品、且部署的芯片数量较多时,SEU 的总发生次数依然可观。如果每次 SEU 都重新配置对应芯片,对许多客户和应用场景而言是无法接受的。Essential Bit 的概念正是为此引入。

CRAM 的全部配置位中,只有一部分真正参与了当前设计,其余为空闲位。空闲位即使被高能粒子击中发生翻转,也不会影响正在运行的设计,这类 SEU 可以安全忽略;只有参与设计的配置位发生翻转,功能才可能受影响。我们把参与设计的配置位称为该设计的 Essential Bit,其中必定影响功能的那部分子集称为 Critical Bit。

针对这类需求,AMD 提供了定位设计 Essential Bit 的方法:为具体设计生成 EBD(Essential Bit Data)文件。EBD 的数据位与 CRAM 配置位一一对应——某位为 1,表示对应配置位是 Essential Bit,一旦该位发生 SEU,可按系统要求决定后续动作(继续观察功能、或立即重启等);某位为 0,表示对应配置位为空闲位,设计可照常运行,无需处理。

下面以 VPK180 为例,使用 Vivado/Vitis 2025.2 实现这一功能。Github 上提供了生成和查询 EBD 文件的示例代码原版(下文简称“原版代码”)。

https://github.com/Xilinx/embeddedsw/tree/xlnx_rel_v2025.2/lib/sw_services/xilsem

步骤一:完成 Vivado 设计,生成 pdi 文件

EBD 查询不依赖复杂的逻辑设计,因此只需搭一个最简的 Versal 工程:

  • 新建 RTL 工程,Part 选 xcvp1802-lsvc4072-2MP-e-S(VPK180)。

  • 创建 Block Design(design_1),加入一个 CIPS IP;双击进入 PS PMC → PMC 标签,启用 XilSEM 服务,再 Run Block Automation。

  • 生成 HDL Wrapper 并设为 top。

关键一步——在 Tcl Console 打开 essential bits 输出开关(缺此步 Vivado 不会输出 EBD 数据):

set_property bitstream.seu.essentialbits yes [current_design]

  • Generate Device Image,完成后在 impl_1/ 目录得到 pdi 与 EBD 原始数据。

产物:

  • design_1_wrapper.pdi —— 烧到板子的固件

  • type0_0.ebd_cfi … type0_3.ebd_cfi —— 4 个 SLR(VPK180 为 4-SLR 器件)的 EBD 原始数据

  • Export Hardware(include bitstream)得到 design_1_wrapper.xsa,供 Vitis 使用。

提示:可直接运行示例工程的 scripts/generate_ebd_data_update.tcl,自动完成“设 essentialbits → write_device_image”。

步骤二:把 EBD 原始数据转成 C 文件

板上查询算法读取的是数组形式的 EBD 数据,所以需要把 .ebd_cfi 转成 .c。使用示例工程 ebd_tools/ 里的工具链:

TOOL=$(pwd)/ebd_tools
for slr in 0 1 2 3; do
  cp /path/to/impl_1/type0_${slr}.ebd_cfi ${TOOL}/
  (cd ${TOOL} && bash run_ssit_update.sh ${slr})
done

每个 SLR 产出一个 xsem_ebdgoldendata<N>.c。

注意:原版代码中的 run_ssit.sh 和 xsem_reformat_ebdcfi.c 不支持 SLR3(脚本缺分支、源文件有复制粘贴 bug)。VPK180 是 4-SLR 器件,必须使用示例工程中修复过的 run_ssit_update.sh 和 xsem_reformat_ebdcfi_update.c。

步骤三:建 Vitis 工程,生成 elf 文件

  • 用步骤一的 .xsa 创建 Platform Component,OS 选 standalone,Processor 选 psv_cortexr5_0,在 domain 里勾选 xilsem 库,Build。

  • 创建 Application Component(Empty Application),把以下文件拷进 app 的 src/:xsem_ebd_search.c / .h(查询算法,原版代码)、步骤二生成的 4 个 xsem_ebdgoldendata*.c、以及你的 main.c。

关键设置——EBD 数据约 3 MB,TCM 放不下,必须放 DDR。在 lscript.ld 的 .heap 段之前插入:

.sem_ebddata : {
    KEEP (*(.sem_ebddata))
} > axi_noc_0_ddr_memory_DDR_LOW_0

  • Build,得到 xilsem_ebd_app.elf。

提示:vitis -s scripts/vitis_build_ebd_update.py 可一步完成 platform + app 全部构建(含上面 lscript 的自动 patch)。

main.c 的核心就是调用查询函数:

extern volatile int XSem_EbdBuffer0[];   /* SLR0 数据 */

/* 查询 SLR0 / 块类型 0 / Row0 / Frame0 / Qword0 / Bit98 */
u32 ret = XSem_EbdLookUp(0, 0, 0, 0, 98, &XSem_EbdBuffer0[0]);
/* 返回 1 = essential | 0 = 非 essential | 2 = 参数无效 *

步骤四:工程文件清单

文件

来源

说明

design_1_wrapper.pdi / .xsa

Vivado 生成

步骤一产物

xsem_ebdgoldendata{0..3}.c

自己设计生成

步骤二产物,设计专属,不能用别人的

xsem_ebd_search.c / .h

原版代码直接用

查询算法

run_ssit.sh / xsem_reformat_ebdcfi.c

原版代码需改动

修复 SLR3 支持(见步骤二)

main.c

自写(可参考原版代码)

决定查询哪些位,见下方改动说明

lscript.ld

需改动

加 .sem_ebddata 段到 DDR

构建/下板脚本

自写

generate_ebd_data_update.tcl / vitis_build_ebd_update.py / run_ebd_update.tcl

main.c 做什么:流程很简单——先通过 UART 打印示例信息头,然后依次对选定的若干配置位调用 XSem_EbdLookUp(),逐个判断该位是否为 essential bit 并打印结果,最后打印结束信息。它是对预生成的 golden EBD 数据做纯软件查询,不启动实时扫描。

关于 main.c 的改动:改自原版代码 xsem_ebd_ssit_example.c,功能等价。本示例保留原版用到的两种Block类型,每种各查询 3 个配置位(共 6 次查询),均使用 SLR0 数据。

  • 为 SLR2/SLR3 预留接口:VPK180 共 4 个 SLR,每个对应一份 golden data 数组(XSem_EbdBuffer0..3)。示例只附带 SLR0/SLR1 数据,故 SLR2/SLR3 的声明与查询调用已写好但默认注释,生成对应数据后取消注释即可启用。

预留的 SLR2/SLR3 声明(生成对应数据后取消注释即可启用):

/* extern volatile int XSem_EbdBuffer2[]; */
/* extern volatile int XSem_EbdBuffer3[]; */

步骤五:上板测试结果中的关键 EBD 信息

在板卡 host 上开 UART 终端(115200 8N1),用 xsdb 烧 PDI 并下 ELF 运行(<hw_server_host> 替换为运行 hw_server 的主机名/IP):

xsdb scripts/run_ebd_update.tcl <hw_server_host>

本示例对 SLR0 的两种Block类型各查询 3 个配置位,共 6 次查询。实测(VPK180 / xcvp1802)结果为 1 次 ESSENTIAL、5 次 not essential。UART 输出每次查询的参数、InputMask、FrameMask 与判定。

ESSENTIAL 结果(实测):

[SLR0 BT0 row0 FAddr0 qword0 bit98]
  BT=0 Row=0 FAddr=0x0000 Qword=00 Bit=098
InputMask = 0x00000004
FrameMask = 0x00000C0C
  ==> ESSENTIAL bit

not essential 结果(实测):

[SLR0 BT0 row0 FAddr0 qword1 bit42]
  BT=0 Row=0 FAddr=0x0000 Qword=01 Bit=042
InputMask = 0x00000400
FrameMask = 0x00003800
  ==> not essential

判定逻辑很直接:(FrameMask & InputMask) != 0 即为 essential。注意上面这条 not essential:FrameMask 并不为 0(0x3800),但 0x400 & 0x3800 = 0,所以判为非 essential——说明结论是算法在板上真实从 EBD 数据算出来的,而不是固定字符串。

 结束

至此,我们基于 VPK180 完整走通了“Vivado 生成 EBD → 转 C 数据 → Vitis 编译 → 上板查询”的流程。有了 EBD 查询能力,系统就能在 SEU 发生时区分该位是否参与设计:命中 essential bit 才需采取措施,命中空闲位则可安全忽略,从而在量产场景下大幅减少不必要的重配置。想查询别的位,只需修改 main.c 中 XSem_EbdLookUp(...) 的参数重新编译即可。