近日发现难以做到日更,于是决定月更。

有关项目

总结一下RIF现在碰到的一些问题:

Segmentation Fault

对构建过程和报错进行了描述放在github issue 目前并没有什么头绪,出现了按照test构建,没有segmentation fault但是也出现了vfsgnj指令报错:有dataC未定义。 dataC无论在autogen/的文件里、spike的算法头文件里还是decode.hpp里都没有。 删掉CustomOperator.def里面的其他指令之后就不会报错没有dataC了。

vfsgnj(n/x)

Decode.hpp里面写了和spike一样的算法宏

#define F16_SIGN ((uint16_t)1 << 15)
#define F32_SIGN ((uint32_t)1 << 31)
#define F64_SIGN ((uint64_t)1 << 63)
#define fsgnj16(a, b, n, x) \
  f16((f16(a).v & ~F16_SIGN) | ((((x) ? f16(a).v : (n) ? F16_SIGN : 0) ^ f16(b).v) & F16_SIGN))
#define fsgnj32(a, b, n, x) \
  f32((f32(a).v & ~F32_SIGN) | ((((x) ? f32(a).v : (n) ? F32_SIGN : 0) ^ f32(b).v) & F32_SIGN))
#define fsgnj64(a, b, n, x) \
  f64((f64(a).v & ~F64_SIGN) | ((((x) ? f64(a).v : (n) ? F64_SIGN : 0) ^ f64(b).v) & F64_SIGN))

生成的测试用例,有mask的话遵循ta=1s,ma=1s,但是rvv intrinsic计算结果不遵循,就算有v0.t = 0 也会正常计算所以报错了。 在没有mask的测试用例中,rif golden 算出来的值是0,需要修。

删掉CustomOperator.def里面的其他指令之后发现,autogen/compute{op_type}Op.h里面的头文件竟然不是根据CustomOperator.def 里面有多少个指令来的。 checkout 回很早之前的分支也无法找到指令了。

问题原因

RIF在遇到使用和常规指令不同的宏的指令时会先取消 decode.h 中定义的宏,在头文件中进行 push macro 和 pop macro 操作。

示例如下,此为 include/autogen/compute{op_type}Op.h 中的部分内容:

 #pragma push_macro("VI_VFP_VV_LOOP")
  #undef VI_VFP_VV_LOOP
  #define VI_VFP_VV_LOOP(BODY16, BODY32, BODY64)                               \\
  RIF::RawDatumOperand vd(dataA[i]);                                           \\
  RIF::RawDatumOperand vs1(dataB[i]);                                          \\
  RIF::RawDatumOperand vs2(dataC[i]);                                          \\
  switch (sew) {                                                               \\
  case e16:                                                                    \\
    BODY16;                                                                    \\
    break;                                                                     \\
  case e32:                                                                    \\
    BODY32;                                                                    \\
    break;                                                                     \\
  case e64:                                                                    \\
    BODY64;                                                                    \\
    break;                                                                     \\
  default:                                                                     \\
    assert(0);                                                                 \\
    break;                                                                     \\
  }                                                                            \\
  dataOut[i] = vd;

  #pragma push_macro("VI_VFP_VV_LOOP_WIDE")
  #undef VI_VFP_VV_LOOP_WIDE
  #define VI_VFP_VV_LOOP_WIDE(BODY16, BODY32)                                  \\
  RIF::RawDatumOperand vd(dataA[i]);                                           \\
  RIF::RawDatumOperand vs1(dataB[i]);                                          \\
  RIF::RawDatumOperand vs2(dataC[i]);                                          \\
  switch (sew) {                                                               \\
  case e16:                                                                    \\
    vs2 = f16_to_f32(vs2);                                                     \\
    vs1 = f16_to_f32(vs1);                                                     \\
    BODY16;                                                                    \\
    break;                                                                     \\
  case e32:                                                                    \\
    vs2 = f32_to_f64(vs2);                                                     \\
    vs1 = f32_to_f64(vs1);                                                     \\
    BODY32;                                                                    \\
    break;                                                                     \\
  default:                                                                     \\
    assert(0);                                                                 \\
    break;                                                                     \\
  }                                                                            \\
  dataOut[i] = vd;

  #pragma pop_macro("VI_VFP_VV_LOOP")
  #pragma pop_macro("VI_VFP_VV_LOOP_WIDE")

decode.h 中的默认宏展开为:

#define VI_VFP_VV_LOOP(BODY16, BODY32, BODY64)                                 \
  RIF::RawDatumOperand vs2(dataA[i]);                                          \
  RIF::RawDatumOperand vs1(dataB[i]);                                          \
  RIF::RawDatumOperand vd;                                                     \
  switch (sew) {                                                               \
  case e16:                                                                    \
    BODY16;                                                                    \
    break;                                                                     \
  case e32:                                                                    \
    BODY32;                                                                    \
    break;                                                                     \
  case e64:                                                                    \
    BODY64;                                                                    \
    break;                                                                     \
  default:                                                                     \
    assert(0);                                                                 \
    break;                                                                     \
  }                                                                            \
  dataOut[i] = vd;

如果 #pragma push_macro 没有对应的 #pragma pop_macro 就会导致报错没有对应的数据类型,因为在复用上一个操作的宏。

Debug 方法

参加 AOSCC 时 ksco 老师教了我大量 debug 技巧,比如单步运行 make 找出报错的命令,使用 -E 参数 -o 指定文件位置和名字,查看宏展开之后的内容。 还有解读 ai agent 教我的使用 gdb bt 程序调用栈的报错。大学习,深表感谢。

未解之谜

不知道以下报错为何会发生,但现在已不会复现。

+ build/tool/random_gen --root=FmaccVV64VFloat64VBVFVFVFSS111111_m --nodes-to-gen=1 --length=5 --dot=FmaccVV64VFloat64VBVFVFVFSS111111_m.dot --code=FmaccVV64VFloat64VBVFVFVFSS111111_m.c --seed=3735928559 --march=rv64gcv_zfh_zvfh
Can not find root 'FmaccVV64VFloat64VBVFVFVFSS111111_m' in .def file, abort.
GEN FAIL

尝试了一下创建VFLiteral.py,根据_vf来生成,但还是 Can not find root 'FmaccVV64VFloat64VBVFVFVFSS111111_m' in .def file, abort., 问题出现在C++处理CustomOperator.def.