(この記事は ESM Advent Calendar 2021 の12月11日の記事です)

はじめに

こんにちは。永和システムマネジメントの内角低め担当、はたけやまです。

今回はRubyで作ったRISC-Vシミュレータをご紹介します。

Untitled

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」は即値に利用されます。