OCamlでもできるRISC-Vシミュレータの作り方:4日目「シミュレータ」
(元記事)
Rubyで書かれたオリジナルのシミュレータ
最後は「シミュレータ」モジュールを作成する。渡されたプログラムファイルを読み込んでメモリを初期化したのち、CPUのrunメソッドを回し続け、nop命令が5回連続で呼び出されたら停止する。
code:lib/simulator.ml
type t = { cpu : Cpu.t }
let create = { cpu = Cpu.create }
let init_with_bytes sim data = Cpu.init_memory sim data
let init_with_file sim f =
let ic = open_in_bin f in
let len = in_channel_length ic in
let b = Buffer.create len in
Buffer.add_channel b ic len;
Cpu.init_memory sim.cpu (Buffer.to_bytes b)
let start (sim : t) =
(* NOP5回で終了するまでループし続ける *)
while Cpu.run sim.cpu do
(* NOTE: 空文の書き方が分からない... *)
ignore ()
done
let dump_register label i32 =
let i = Int32.to_int i32 in
Printf.printf "%s = 0x%x (%d)" label i i
let dump_registers (sim : t) =
let cpu = sim.cpu in
print_endline
"--------------------------------------------------------------------------------";
for i = 0 to 7 do
for j = 0 to 3 do
let n = (i * 4) + j in
let label = Printf.sprintf "x%02d" n in
let v = cpu.x_registers.(n) in
if j != 0 then print_string "\t";
dump_register label v
done;
print_newline ()
done;
print_endline
"--------------------------------------------------------------------------------";
dump_register "pc" cpu.pc;
print_newline ()
作成したSimulatorモジュールを、プログラムのエントリポイントとなる bin/main.ml から呼び出すようにする。
code:bin/main.ml
open Rvsim
let usage () = print_endline "usage: rvsim path/to/rom_file"
let () =
let sim = Simulator.create in
if Array.length Sys.argv != 2 then usage ()
else (
Simulator.init_with_file sim Sys.argv.(1);
Simulator.start sim;
Simulator.dump_registers sim)
sample/4649.rom を実行してみる。x1とx2に「4649」が格納されていればOK
https://gyazo.com/b36a6833080e558b330b7c91fbe11ad3