Kanade Electronicskanaelecom
📺

エミュレータ

cemu (Cycle level emulator) は RK16 のソフトウェアエミュレータです。tasm でビルドしたバイナリをそのまま流し込んで実行できるので、実機を作る前にプログラムや RTOS の挙動を検証できます。

構成

+------- State -------+      +-------- Hook --------+
|  imem: 65536×32bit  |      |  Serial (MMIO I/O)   |
|  dmem: 65536×16bit  | <--> |  Intr   (外部割込)   |
+---------------------+      |  Dump   (ログ出力)   |
                             +----------------------+
  • State — CPU 状態。imem (命令メモリ) と dmem (データメモリ + レジスタ) を保持
  • Hook — 命令の実行ごとに呼ばれるプラグイン。MMIO や外部割り込みの注入はここで行う

State

項目内容
imemVec<u32>命令メモリ。65536 word × 32bit
dmemVec<u16>データメモリ。65536 word × 16bit。先頭 16 word はレジスタ

 メモリアクセスは state.get(addr) / state.set(addr, val) で行います。レジスタ (PC / RA / FP / T0…) は dmem の先頭 16 word にあるので、全て同じインタフェースから読み書きできます。

実行ループ

loop {
    let (addr, code, op) = state.exec();   // 1 命令デコード&実行 (PC を進める)
    for hook in hooks.iter_mut() {
        state = hook.exec(time, addr, code, state);
    }
    if state.halt() { break; }             // 0x0010 == 1 で停止
}

 1 サイクル = 1 命令で、PC が自動的に進みます。HALT (アドレス 0x0010) に 1 が書かれたタイミングでループを抜けます。

割り込み機構

 ハードウェアの挙動と一致するように、割り込みは atomic に処理されます。

  1. 現在 PC を IRA に退避
  2. csr.ENABLE (bit 0) を 0 に落とす (多重割り込み防止)
  3. PC を割り込みベクタ 0x0004 に設定

 csr_set_flag(intr_no) で CSR の bit 8 + intr_no に発火フラグが立ち、ベクタから呼ばれる intr_dispatch() がフラグを見て対応するハンドラを呼びます。

Hook プラグイン

pub trait Hook {
    fn init(&mut self, cpu: State) -> State;
    fn exec(&mut self, time: u64, addr: u16, code: u32, cpu: State) -> State;
}

 Hook は State を受け取って State を返す関数で、外界とのやりとり (シリアル送受信、外部割り込み、ダンプ出力) を担います。

Serial

 MMIO 0x1000 / 0x1001 を介してシリアルポートをエミュレートします。

  • 0x1000 (serial_tx) に書き込まれた値を --sout ファイル (or 標準出力) に出力
  • --sin ファイルから 1 文字読み、0x1001 (serial_rx) で読まれるたびに次の文字を返す
  • 受信バッファが空のときは 0xFFFF を返す

Intr

 設定ファイル (--intr-cfg) で指定したタイミングに外部割り込みを発生させます。タイマ割り込みのシミュレーションや、時分割スケジューラの検証で使います。

Dump

 --dump-cfg で指定したアドレス範囲のメモリやレジスタを、各サイクルでログに出します。タスクスイッチの動きや TCB の更新を可視化できます。

起動

cemu \
  --sout out/serial.txt \
  --intr-cfg intr.yaml \
  --dump-cfg dump.yaml \
  out/main.bin \
  out/const.bin