FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Snipersim 8.1をRISC-V対応でビルドさせる方法試行 (4. riscv-opcodesを使った自動化)

github.com

msyksphinz.hatenablog.com

RISC-Vの拡張を増やしたい場合、以下のようにしてターゲットとなるファイルの指定を増やす。

cat riscv/riscv-tools/riscv-opcodes/opcodes \\
    riscv/riscv-tools/riscv-opcodes/opcodes-rvc \\
    riscv/riscv-tools/riscv-opcodes/rv_zba \\
    riscv/riscv-tools/riscv-opcodes/rv_zbb | \\
python3 riscv/scripts/generate_decoder.py /dev/stdin \\
    > decoder_lib/riscv_decoder_generated.h

分類の関数は、さすがに自分で組まないといけないが…

def classify_instruction(name):
    # ...既存の分類...
    elif name.startswith(('andn', 'orn', 'clz', 'ctz')):
        return 'bitmanip'
    # ...

より多くの命令に対応させるために、以下のようにしてデコーダを生成した。

cat riscv/riscv-opcodes-latest/extensions/rv_i \
    riscv/riscv-opcodes-latest/extensions/rv64_i \
    riscv/riscv-opcodes-latest/extensions/rv_m \
    riscv/riscv-opcodes-latest/extensions/rv64_m \
    riscv/riscv-opcodes-latest/extensions/rv_a \
    riscv/riscv-opcodes-latest/extensions/rv64_a \
    riscv/riscv-opcodes-latest/extensions/rv_f \
    riscv/riscv-opcodes-latest/extensions/rv64_f \
    riscv/riscv-opcodes-latest/extensions/rv_d \
    riscv/riscv-opcodes-latest/extensions/rv64_d \
    riscv/riscv-opcodes-latest/extensions/rv_c \
    riscv/riscv-opcodes-latest/extensions/rv64_c \
    riscv/riscv-opcodes-latest/extensions/rv64_zba \
    riscv/riscv-opcodes-latest/extensions/rv64_zbb \
    riscv/riscv-opcodes-latest/extensions/rv64_zbs \
    riscv/riscv-opcodes-latest/extensions/rv_v | \
python3 riscv/scripts/generate_decoder.py /dev/stdin > \
    decoder_lib/riscv_decoder_generated.

ちゃんとデコーダは生成できるが、より詳細なデータは正しく生成できない。これは riscv-opcodes にも存在していない情報だということか…

これらは、 generate_decoder.py を無理やり改造することで対応するが、あまりきれいじゃないな。

def classify_instruction(name):
    """Classify instruction by type"""
    if name.startswith(('beq', 'bne', 'blt', 'bge', 'bltu', 'bgeu', 'c.beqz', 'c.bnez')):
        return 'branch'
    elif name.startswith(('jal', 'jalr', 'c.j', 'c.jal')):
        return 'jump'
    # Load instructions (scalar + vector)
    elif name.startswith(('lb', 'lh', 'lw', 'ld', 'lbu', 'lhu', 'lwu', 'flw', 'fld', 
                          'c.lw', 'c.ld', 'c.lwsp', 'c.ldsp', 'c.flw', 'c.fld', 'c.flwsp', 'c.fldsp',
                          'vle', 'vlse', 'vluxei', 'vloxei', 'vl1re', 'vl2re', 'vl4re', 'vl8re',
                          'vlm.v', 'vle8.v', 'vle16.v', 'vle32.v', 'vle64.v')):
        return 'load'
    # Store instructions (scalar + vector)
    elif name.startswith(('sb', 'sh', 'sw', 'sd', 'fsw', 'fsd', 
                          'c.sw', 'c.sd', 'c.swsp', 'c.sdsp', 'c.fsw', 'c.fsd', 'c.fswsp', 'c.fsdsp',
                          'vsuxei', 'vsoxei', 'vsse',
                          'vsm.v', 'vse8.v', 'vse16.v', 'vse32.v', 'vse64.v')) and not name.startswith('vset'):
        return 'store'
    elif name.startswith(('lr.', 'sc.', 'amo')):
        return 'atomic'
    elif name.startswith(('mul', 'div', 'rem')):
        return 'muldiv'
    elif name.startswith(('fadd', 'fsub', 'fmul', 'fdiv', 'fmadd', 'fmsub', 'fnmadd', 'fnmsub', 'fmin', 'fmax', 'fsqrt', 'fld', 'fsd', 'flw', 'fsw', 'fcvt', 'fmv', 'feq', 'flt', 'fle', 'fclass', 'fsgnj')):
        return 'float'
    elif name.startswith(('fence', 'ecall', 'ebreak')):
        return 'fence'
    elif name.startswith(('andn', 'orn', 'xnor', 'clz', 'ctz', 'cpop', 'max', 'min', 'sext', 'zext', 'rol', 'ror', 'rev8', 'orc.b', 'bclr', 'bext', 'binv', 'bset', 'clmul', 'sh1add', 'sh2add', 'sh3add')):
        return 'bitmanip'
    elif name.startswith('c.'):
        return 'compressed'
    elif name.startswith('v'):
        return 'vector'
    else:
        return 'alu'