3.SG2380云开发空间使用
备注:所需要的编译和执行工具的环境变量已经配置,原则上不需要自己修改相应环境变量。
3.1.编译过程 (clang)
LLVM框架提供了一系列工具。要查看这些工具,请运行:
ls /opt/LLVM/install/bin
您可能会使用的一个关键工具是clang。下面是一个例子,展示了如何使用clang将汇编文件和C文件一起编译,同时利用TPU拓展指令框架以及RISCV GNU Toolchain:
clang -static sg_mls.c sg_mls_asm.S -o vcix_mls -march=rv64imafdcv_zicsr_zifencei_zfh_zba_zbb_zvfh_xsfvfnrclipxfqf_xsfvfwmaccqqq_xsfvqmaccqoq_xsfvcp_xsgmat --gcc-toolchain=/opt/riscv --sysroot=/opt/riscv/sysroot/ -g
在这个命令中,我们编译了可执行文件vcix_mls。 如果不需要调试信息,请省略 -g 标志。
如果出现:-bash: clang: command not found 可执行如下命令解决:export PATH=$PATH:/opt/LLVM/install/bin
3.2.运行 (qemu-riscv64)
QEMU提供了一系列运行拓展指令所需要的可执行文件,我们使用用户模式下的qemu-riscv64命令。 我们将CPU模式设置为max,并将VGPR长度(vlen)设置为512位(这是一个关键的配置):
qemu-riscv64 -cpu max,vlen=512 vcix_mls
如果出现:-bash: qemu-riscv64: command not found 可执行如下命令解决:export PATH=$PATH:/opt/riscv/bin
3.3.调试 (GDB)
如果需要使用gdb进行调试,您可以使用RISCV GNU Toolchain提供的工具。请在 /opt/riscv/bin 目录中查找 gdb工具。
3.4.编程示例
在这里演示使用sg.mld(从内存载入数据到MGPR)以及sg.mld(从MGPR存储数据到内存)指令:将一段数据从a载入到MGPR,再从MGPR存储到b:
3.4.1.汇编和C分离
sg_mls.c:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
// Use extern method to use the assembly function.
extern void vcix_mls_asm(int m, int n, void *a, void *b);
int main() {
int16_t a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int16_t b[15] = {0};
vcix_mls_asm(3, 5, a, b);
// succeed if b is equal to a.
for (int i = 0; i < 15; i++) {
printf("%d ", b[i]);
}
printf("\n");
return 0;
}
sg_mls_asm.S
.global vcix_mls_asm
.section .text.vcix_mls_asm
vcix_mls_asm:
sg.mset tilem, a0
sg.mset tilen, a1
sg.mset strc, a1
sg.mld m0, a2, e16, c
sg.mst a3, m0, e16, c
ret
然后按步骤执行上述编译和运行环节(3.1.编译过程和3.2.运行),即可以获得输出结果:
# 3.1.编译过程(clang)
root@245461519eca:~# clang -static sg_mls.c sg_mls_asm.S -o vcix_mls -march=rv64imafdcv_zicsr_zifencei_zfh_zba_zbb_zvfh_xsfvfnrclipxfqf_xsfvfwmaccqqq_xsfvqmaccqoq_xsfvcp_xsgmat --gcc-toolchain=/opt/riscv --sysroot=/opt/riscv/sysroot/ -g
# 3.2.运行(qemu-riscv64)
root@4ad946a475c6:/home# qemu-riscv64 -cpu max,vlen=512 vcix_mls
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3.4.2.内联汇编
内联汇编可以让我们直接在C里面插入指令,方便调试指令效果: sg_mls.c:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main() {
int16_t a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int16_t b[15] = {0};
asm volatile("sg.mset tilem, %0" :: "r"(3));
asm volatile("sg.mset tilen, %0" :: "r"(5));
asm volatile("sg.mset strc, %0" :: "r"(5));
asm volatile("sg.mld m0, %0, e16, c" :: "r"(a));
asm volatile("sg.mst %0, m0, e16, c" :: "r"(b));
// succeed if b is equal to a.
for (int i = 0; i < 15; i++) {
printf("%d ", b[i]);
}
printf("\n");
return 0;
}
再将该C文件单独编译和执行,可以得到同样效果。