Cómo Añadir una Instrucción Personalizada a la ISA en Gem5

Extender el conjunto de instrucciones (ISA) de RISC-V añadiendo instrucciones personalizadas puede aumentar el rendimiento y optimizar para aplicaciones específicas. Este artículo guía sobre cómo añadir una instrucción «módulo» a la ISA de RISC-V, escribir un programa que utilice esta instrucción, integrarla en el compilador RISC-V y ejecutarla en Gem5 y Spike, un simulador de ISA.

Primero, es necesario instalar 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

Este comando construirá la cadena de herramientas RISC-V. A continuación, añadiremos la instrucción «módulo» con la siguiente sintaxis y semántica:

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

Abra el archivo riscv-opcodes/opcodes y añada la definición para la instrucción 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
...

Después, ejecute el siguiente comando para generar el archivo temp.h:

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

En el archivo temp.h, busque las dos líneas siguientes:

#define MATCH_MOD 0x200006b
#define MASK_MOD 0xfe00707f

Añada estas dos líneas a riscv-gnu-toolchain/riscv-binutils-gdb/include/opcode/riscv-opc.h. Continúe, modifique el archivo riscv-gnu-toolchain/riscv-binutils-gdb/opcodes/riscv-opc.c y añada la siguiente línea al array riscv_opcodes[]:

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

Recompile riscv-gnu-toolchain. Ahora, escriba un programa en C para probar:

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

Compile el programa usando el compilador RISC-V modificado:

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

Use objdump para inspeccionar la instrucción mod:

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

Para añadir la instrucción a Gem5, edite 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; }});
            ...
        }
       ...
    }
   ...
}

La coincidencia de instrucciones en el ensamblador se realiza de la siguiente manera:

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

Finalmente, para añadir la instrucción al simulador Spike, modifique riscv-isa-sim/riscv/encoding.h:

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

Cree el archivo riscv-isa-sim/riscv/insns/mod.h con el siguiente contenido:

WRITE_RD(sext_xlen(RS1 % RS2));

Añada este archivo a riscv-isa-sim/riscv/riscv.mk.in y añada la línea DEFINE_RTYPE(mod); a riscv-isa-sim/spike_main/disasm.cc. Después, recompile riscv-tools. En este punto, la instrucción «mod» se ha añadido al simulador Spike.

Comentarios

Aún no hay comentarios. ¿Por qué no comienzas el debate?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *