自定义RISC-V指令clp仿真执行报错,请求技术支持
自定义RISC-V
clp 指令执行非法指令错误排查 需求背景
需要实现对应以下C clamp函数的自定义RISC-V指令clp,使用F扩展,指令格式为:
clp rd rs1 rs2 rs3 rm 26..25=1 6..2=0x15 1..0=3
对应的C函数:
double clamp(double x) { return x < 0 ? 0 : x > 1 ? 1 : x; }
已完成的修改操作
1. RISC-V GNU工具链修改
- 在
riscv-gnu-toolchain/riscv-binutils/include/opcode/riscv-opc.h中添加MASK_CLP和MATCH_CLP定义 - 在
riscv-gnu-toolchain/riscv-binutils/opcodes/riscv-opc.c中添加指令条目:
{"clp", 0, INSN_CLASS_D_INX, "D,S,T,R", MATCH_CLP|MASK_RM, MASK_CLP|MASK_RM, match_opcode, 0}, {"clp", 0, INSN_CLASS_D_INX, "D,S,T,R,m", MATCH_CLP, MASK_CLP, match_opcode, 0},
- 重新编译工具链
2. Spike模拟器修改
- 在
spike/riscv/encoding.h中添加MATCH_CLP和MASK_CLP定义 - 在
spike/riscv/insns目录创建clp.h,内容如下:
require_either_extension('D', EXT_ZDINX); require_fp; softfloat_roundingMode = RM; if(f64_lt(FRS1_D, FRS2_D)){ WRITE_FRD_D(FRS1_D); } else if(f64_lt(FRS3_D,FRS1_D)){ WRITE_FRD_D(FRS3_D); } else WRITE_FRD_D(FRS2_D); set_fp_exceptions;
- 在
spike/riscv/riscv.mk.in中添加该指令的编译条目 - 在
spike/disasm/disasm.cc中添加DEFINE_FR3TYPE(clp); - 重新编译Spike
3. 测试程序
编写clamp.c测试代码:
#include<stdio.h> int main(){ double a=0.0; double b=1.0; double c=0.3; double d; asm volatile ( "clp %[w], %[x], %[y], %[z]\n\t" : [w] "=f"(d) : [x] "f" (c), [y] "f" (a), [z] "f" (b) ); printf("%f\n",d); return 0; }
问题现象
执行spike pk clamp时,提示An illegal instruction was executed!
排查方向与解决方案
1. 检查指令编码一致性
确保工具链(riscv-opc.h)和Spike(encoding.h)中的MATCH_CLP、MASK_CLP定义完全匹配,严格对应指令格式的位字段:
- 指令格式指定
26..25=1、6..2=0x15、1..0=3,这些固定位必须在MATCH_CLP中设置为对应值,MASK_CLP要覆盖这些固定位以及寄存器字段、rm字段的位置 - 示例:如果指令是R型变种,MASK需要包含所有非寄存器的固定位,MATCH则是这些固定位的预期值
2. 验证测试程序的指令编码
编译测试程序后,用objdump -d clamp反汇编,查看生成的clp指令机器码是否和Spike中MATCH_CLP匹配。如果编码不匹配,说明工具链的指令定义有误:
- 检查riscv-opc.c中的指令条目,确认
INSN_CLASS、操作数格式("D,S,T,R"等)是否正确对应clp的指令类型 - 确认测试程序中的asm语句操作数顺序是否符合指令格式:指令格式是
clp rd rs1 rs2 rs3 rm,测试代码中未指定rm参数,工具链会默认填充rm字段值,需确保该默认值在Spike的MATCH_CLP允许范围内(或修改asm语句添加rm参数,比如clp %[w], %[x], %[y], %[z], rtz)
3. 检查Spike的扩展启用情况
- 执行Spike时需明确启用D扩展(因为使用双精度浮点),命令改为:
spike --extension=D pk clamp - 确认pk(Proxy Kernel)是否支持自定义指令,或是否需要重新编译pk以包含对
clp指令的支持(Spike通常会直接处理自定义指令,但如果pk过滤非法指令则可能出现问题)
4. 验证Spike的指令注册
- 检查
spike/riscv/riscv.mk.in中是否正确添加了clp指令的编译规则,确保clp.h被正确编译进Spike - 确认
disasm.cc中的DEFINE_FR3TYPE(clp);是否正确,对应指令的类型是否为三源浮点寄存器类型
5. 检查指令逻辑中的扩展依赖
clp.h中使用了require_either_extension('D', EXT_ZDINX);,需确保测试时Spike启用了其中一个扩展(D扩展是最直接的选择)
内容的提问来源于stack exchange,提问作者沈思远
相关产品推荐
相关产品推荐

