Gem5 ISA에 특별 명령어 추가하기

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 시뮬레이터에 추가되었습니다.

Comments

No comments yet. Why don’t you start the discussion?

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다