プロジェクトの目的
riscv-opcodesプロジェクトは、RISC-V命令セットの標準オペコードとコントロール・ステータスレジスタ(CSR)を列挙し、それらを複数の形式(C、Scala、LaTeX等)に変換するスクリプトを提供することが目的である。
このプロジェクトから生成される成果物(encoding.h、latex-tables等)は、Spike、PK、RISC-V Manualなどの他のツールやプロジェクトで使用されている。
プロジェクト構造
├── extensions # instruction opcodes
├── extensions/unratified # unratified instruction opcodes
├── encoding.h # the template encoding.h file
├── Makefile # makefile to generate artifacts
└── src/riscv_opcodes # python files to perform checks on
# the instructions and generate artifacts
ファイル命名規則
命令エンコーディングを含むファイルはrvプレフィックスで始まり、以下の規則に従う:
rv_x- 32ビットと64ビットモードで共通の拡張Xの命令rv32_x- rv32xのみに存在する命令(rv64xには存在しない)rv64_x- rv64xのみに存在する命令(rv32xには存在しない)rv_x_y- 拡張XとYの両方が利用可能な場合の命令unratified/- まだ承認されていない命令を含むディレクトリ
エンコーディング構文
プロジェクトでは3種類の命令構文をサポートしている:
- 通常命令: エンコーディング空間で一意のオペコードを持つ
- 疑似命令: 通常命令のエイリアスで、
$pseudo_opキーワードを使用 - インポート命令: 他の拡張から借用された命令で、
$importキーワードを使用
使い方
1. 基本的な使用法
# すべての拡張に対して成果物を生成 make # 特定の拡張のみを指定(例:I拡張とM拡張のみ) make EXTENSIONS='rv*_i rv*_m'
2. 特定の成果物のみを生成
# Cヘッダーファイルのみ生成 uv run riscv_opcodes -c 'rv*_i' 'rv*_m' # またはmakefileを使用 make encoding.out.h EXTENSIONS='rv*_i rv*_m'
3. 生成される成果物
encoding.out.h- Spike、PK等で使用されるヘッダーファイルinstr-table.tex- RISC-V非特権仕様書で使用されるLaTeX表priv-instr-table.tex- RISC-V特権仕様書で使用されるLaTeX表inst.chisel- Chiselコードinst.sverilog- SystemVerilogコードinst.rs- Rustコードinst.spinalhdl- SpinalHDLコードinst.go- Goコード
4. 新しい拡張の追加
- 適切な
rv*ファイルを作成(命名規則に従って) - ルートディレクトリで
makeを実行してチェックと成果物生成を確認 - プルリクエストを作成
5. デバッグログの有効化
parse.pyでデバッグログを有効にするには、level=logging.INFOをlevel=logging.DEBUGに変更する。
実際に使ってみる
- まず、 uv をダウンロードする。
$ curl -LsSf https://astral.sh/uv/install.sh | sh
$ make encoding.out.h EXTENSIONS='rv*_i rv*_m'
encoding.out.hは以下のようになっており、命令の定義なども含まれている。
/* Automatically generated by parse_opcodes. */ #ifndef RISCV_ENCODING_H #define RISCV_ENCODING_H #define MATCH_ADD 0x33 #define MASK_ADD 0xfe00707f #define MATCH_ADDI 0x13 #define MASK_ADDI 0x707f #define MATCH_ADDIW 0x1b #define MASK_ADDIW 0x707f #define MATCH_ADDW 0x3b #define MASK_ADDW 0xfe00707f #define MATCH_AND 0x7033 #define MASK_AND 0xfe00707f #define MATCH_ANDI 0x7013 #define MASK_ANDI 0x707f #define MATCH_AUIPC 0x17 /* ... 以下省略 ... */ #ifdef DECLARE_INSN DECLARE_INSN(add, MATCH_ADD, MASK_ADD) DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI) DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW) DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW) DECLARE_INSN(and, MATCH_AND, MASK_AND) DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI) DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC) /* ... 以下省略 ... */
- 例えば、ベクトル拡張を追加するにはこうなる。
make encoding.out.h EXTENSIONS='rv*_i rv*_m rv*_v'
encoding.out.hは以下のようになった:
#define MASK_VDIVU_VX 0xfc00707f #define MATCH_VFADD_VF 0x5057 #define MASK_VFADD_VF 0xfc00707f #define MATCH_VFADD_VV 0x1057 #define MASK_VFADD_VV 0xfc00707f #define MATCH_VFCLASS_V 0x4c081057 #define MASK_VFCLASS_V 0xfc0ff07f #define MATCH_VFCVT_F_X_V 0x48019057 #define MASK_VFCVT_F_X_V 0xfc0ff07f #define MATCH_VFCVT_F_XU_V 0x48011057 #define MASK_VFCVT_F_XU_V 0xfc0ff07f #define MATCH_VFCVT_RTZ_X_F_V 0x48039057 #define MASK_VFCVT_RTZ_X_F_V 0xfc0ff07f #define MATCH_VFCVT_RTZ_XU_F_V 0x48031057 /* ... 以下省略 ... */