RISC-V 명령어 집합 아키텍처(ISA)에 사용자 정의 명령어를 추가하면 특정 애플리케이션의 성능을 향상시키고 최적화할 수 있습니다. 이 글에서는 RISC-V ISA에 “modulo” 명령어를 추가하고, 이 명령어를 사용하는 프로그램을 작성하고, RISC-V 컴파일러에 통합하고, Gem5 및 Spike ISA 시뮬레이터에서 실행하는 방법을 안내합니다.
먼저, riscv-tools를 설치해야 합니다.
$ git clone https://github.com/riscv/riscv-tools.git
$ git submodule update --init --recursive
$ export RISCV=/path/to/install/riscv/toolchain
$ ./build.sh
이 명령어는 RISC-V 툴체인을 빌드합니다. 다음으로, 다음과 같은 구문 및 의미를 가진 “modulo” 명령어를 추가합니다.
mod r1, r2, r3
Semantics: R[r1] = R[r2] % R[r3]
riscv-opcodes/opcodes
파일을 열고 mod
명령어에 대한 정의를 추가합니다.
sra rd rs1 rs2 31..25=32 14..12=5 6..2=0x0C 1..0=3
...
mod rd rs1 rs2 31..25=1 14..12=0 6..2=0x1A 1..0=3
...
그런 다음, 다음 명령어를 실행하여 temp.h
파일을 생성합니다.
cat opcodes-pseudo opcodes opcodes-rvc opcodes-rvc-pseudo opcodes-custom | ./parse-opcodes -c > ~/temp.h
temp.h
파일에서 다음 두 줄을 찾습니다.
#define MATCH_MOD 0x200006b
#define MASK_MOD 0xfe00707f
이 두 줄을 riscv-gnu-toolchain/riscv-binutils-gdb/include/opcode/riscv-opc.h
에 추가합니다. 계속해서 riscv-gnu-toolchain/riscv-binutils-gdb/opcodes/riscv-opc.c
파일을 수정하고 riscv_opcodes[]
배열에 다음 줄을 추가합니다.
const struct riscv_opcode riscv_opcodes[] = {
...,
{"mod", "I", "rd,rs1,rs2", MATCH_MOD, MASK_MOD, match_opcode, 0},
...
};
riscv-gnu-toolchain
을 다시 컴파일합니다. 이제 테스트를 위한 C 프로그램을 작성합니다.
#include <stdio.h>
int main() {
int a, b, c;
a = 5;
b = 2;
asm volatile ("mod %[z], %[x], %[y]nt"
: [z] "=r" (c)
: [x] "r" (a), [y] "r" (b));
if (c != 1) {
printf("n[[FAILED]]n");
return -1;
}
printf("n[[PASSED]]n");
return 0;
}
수정된 RISC-V 컴파일러를 사용하여 프로그램을 컴파일합니다.
$ riscv64-unknown-elf-gcc mod.c -o mod
objdump
를 사용하여 mod
명령어를 확인합니다.
$ riscv64-unknown-elf-objdump -dC mod > mod.dump
Gem5에 명령어를 추가하려면 arch/riscv/decoder.isa
를 수정합니다.
0x33: decode FUNCT3 {
format ROp {
0x0: decode FUNCT7 {
0x0: add({{ Rd = Rs1_sd + Rs2_sd; }});
...
0x10: mod({{ Rd = Rs1_sd % Rs2_sd; }});
...
}
...
}
...
}
어셈블러에서 명령어 매칭은 다음과 같이 수행됩니다.
((insn ^ op->match) & op->mask) == 0;
마지막으로 Spike 시뮬레이터에 명령어를 추가하려면 riscv-isa-sim/riscv/encoding.h
를 수정합니다.
#define MATCH_MOD 0x200006b
#define MASK_MOD 0xfe00707f
...
DECLARE_INSN(mod, MATCH_MOD, MASK_MOD)
riscv-isa-sim/riscv/insns/mod.h
파일을 다음 내용으로 생성합니다.
WRITE_RD(sext_xlen(RS1 % RS2));
이 파일을 riscv-isa-sim/riscv/riscv.mk.in
에 추가하고 DEFINE_RTYPE(mod);
줄을 riscv-isa-sim/spike_main/disasm.cc
에 추가합니다. 그런 다음 riscv-tools
를 다시 컴파일합니다. 이제 “mod” 명령어가 Spike 시뮬레이터에 추가되었습니다.