(この記事は ESM Advent Calendar 2021 の12月11日の記事です)
こんにちは。永和システムマネジメントの内角低め担当、はたけやまです。
今回はRubyで作ったRISC-Vシミュレータをご紹介します。
RISC-VはCPUの命令セットアーキテクチャ(ISA)のひとつで、使用料のかからないオープンソースライセンスで提供されていることや、命令セットの美しさから最近注目を集めています。
RISC-Vの仕様にはワード幅(32ビット、64ビット)や浮動小数点数サポートの有無など、いくつかの命令セット仕様がありますが、今回は32ビット整数演算のみをサポートする「RV32I」のサブセットを実装します。
では早速作っていきましょう。まずは命令を格納するメモリを作ります。
class Memory
WORD_SIZE = 4
attr_accessor :data
def initialize(data = nil)
@data = data
end
def read(addr)
word = @data.slice(addr, WORD_SIZE)
# RISC-Vはリトルエンディアンなので、「V = little endian unsigned 32bit」でメモリの内容を読み込む
word.unpack("V").first
end
end
Momoryの使い方はこんな感じ、1度のreadで1ワード(32ビット)のデータを読み込みます。
memory = Memory.new("\\x93\\x00\\x01\\x01\\x94\\x00\\x01\\x01")
printf "%08x", memory.read(0)
#=> 01010093
printf "%08x", memory.read(4)
#=> 01010094
RISC-Vの命令は以下のようなフォーマットになっています。
「opcode」「funct3」「funct7」は命令の判別に、「rd」「rs1」「rs2」は操作対象のレジスタ番号の指定に、「imm」は即値に利用されます。