Jak Dodać Własną Instrukcję do ISA w Gem5

Rozszerzenie zestawu instrukcji (ISA) RISC-V o instrukcje niestandardowe może zwiększyć wydajność i zoptymalizować określone aplikacje. Ten artykuł pokazuje, jak dodać instrukcję „modulo” do RISC-V ISA, napisać program korzystający z tej instrukcji, zintegrować ją z kompilatorem RISC-V i uruchomić na Gem5 i Spike, symulatorze ISA.

Najpierw zainstaluj 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

To polecenie zbuduje toolchain RISC-V. Następnie dodamy instrukcję „modulo” o następującej składni i semantyce:

mod r1, r2, r3 
Semantics: R[r1] = R[r2] % R[r3]

Otwórz plik riscv-opcodes/opcodes i dodaj definicję instrukcji 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
...

Następnie uruchom następujące polecenie, aby utworzyć plik temp.h:

cat opcodes-pseudo opcodes opcodes-rvc opcodes-rvc-pseudo opcodes-custom | ./parse-opcodes -c > ~/temp.h

W pliku temp.h znajdź następujące dwie linie:

#define MATCH_MOD 0x200006b
#define MASK_MOD 0xfe00707f

Dodaj te dwie linie do riscv-gnu-toolchain/riscv-binutils-gdb/include/opcode/riscv-opc.h. Następnie zmodyfikuj plik riscv-gnu-toolchain/riscv-binutils-gdb/opcodes/riscv-opc.c i dodaj następującą linię do tablicy riscv_opcodes[]:

const struct riscv_opcode riscv_opcodes[] = {
    ...,
    {"mod", "I", "rd,rs1,rs2", MATCH_MOD, MASK_MOD, match_opcode, 0},
    ...
};

Skompiluj ponownie riscv-gnu-toolchain. Teraz napisz program w C, aby przetestować:

#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;
}

Skompiluj program za pomocą zmodyfikowanego kompilatora RISC-V:

$ riscv64-unknown-elf-gcc mod.c -o mod

Użyj objdump, aby sprawdzić instrukcję mod:

$ riscv64-unknown-elf-objdump -dC mod > mod.dump

Aby dodać instrukcję do Gem5, edytuj 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; }});
            ...
        }
       ...
    }
   ...
}

Dopasowanie instrukcji w asemblerze odbywa się w następujący sposób:

((insn ^ op->match) & op->mask) == 0;

Na koniec, aby dodać instrukcję do symulatora Spike, zmodyfikuj riscv-isa-sim/riscv/encoding.h:

#define MATCH_MOD 0x200006b
#define MASK_MOD 0xfe00707f
...
DECLARE_INSN(mod, MATCH_MOD, MASK_MOD)

Utwórz plik riscv-isa-sim/riscv/insns/mod.h z następującą zawartością:

WRITE_RD(sext_xlen(RS1 % RS2));

Dodaj ten plik do riscv-isa-sim/riscv/riscv.mk.in i dodaj linię DEFINE_RTYPE(mod); do riscv-isa-sim/spike_main/disasm.cc. Następnie skompiluj ponownie riscv-tools. Teraz instrukcja „mod” została dodana do symulatora Spike.

Comments

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

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *