Moiz's journal

プログラミングやFPGAなどの技術系の趣味に関するブログです

Interface誌2020年7月号に当ブログの記事と類似性の高い記事が掲載された件について

Interface誌2020年7月号に当ブログの記事と類似性の高い記事が掲載された件について

はじめに

当ブログ及びそれをもとにした同人誌「PythonとColabでできる ゼロから作るRAW現像」の内容と非常に類似性の高い記事が、私の知らない間に商用雑誌に掲載されるという事がありましたので、その経緯についてまとめます。

類似性の高い記事について

Interface誌(CQ出版社)の2020年7月号特集記事「AI時代の画像処理教科書」において、当ブログ及びそれをもとにした同人誌「PythonとColabでできる ゼロから作るRAW現像」の内容と非常に類似性の高い記事が掲載されました。私への事前連絡などはありませんでした。

具体的には特集第1章「ディジタル画像の基礎知識」において、24-25ページおよび27ページの内容が、当ブログの2018-9023の記事「ゼロから作るRAW現像その1-基本的な処理」と非常に似通っています。 類似点は単に内容の類似性にとどまらず、多くの文章はほぼそのまま、または小さな変更のみの形で雑誌記事にとりこまれていました。また、非常に似通った図も使用されています。

例1

Interface誌24ページ

イメージセンサは碁盤の目状に並んだ小さなフォトセンサの集まりでできています.1つ1つのフォトセンサは,そのままでは色の違いを識別できません.

当ブログ

画像センサーは、碁盤の目状にならんだ小さな光センサーの集まりでできています。一つ一つの光センサーはそのままでは色の違いを認識できません。

例2

Interface誌25ページ

カメラ用のイメージセンサでは,2000年代初頭までは補色フィルタや3板式もそれなりの割合で使われていたのですが,イメージセンサの性能向上やカメラの小型化,高解像度化の流れの中で,ほとんどがベイヤー配列に変わりました。

当ブログ

カメラ用センサーでは2000年代初頭までは、補色フィルターや3板方式もそれなりの割合で使われていたのですが、センサーの性能向上やカメラの小型化と高画質化の流れの中でほとんどがBayer方式にかわりました。

この他に、第4章「プログラミング体験」の内容も、当ブログと似通っています。

特集の第1章では当ブログ記事が参考文献としてあげられてはいますが、私としては量・形式ともに正当と認められている範囲を大きく逸脱していると考えました。

Interface誌の対応

この点についてTwitterでInterface誌に問い合わせたところ、以下のような記事の類似性を認める回答及び謝罪がありました。

また、別途、編集部から私の方に、直接の謝罪と、編集部として10月号に謝罪文を掲載する予定であることが伝えられました。

実際に、8月25日に発売されたInterface誌10月号171ページにおいて、「読者の皆様へ」という文章がが掲載されている事を確認しました。

この文章では、Interface誌7月号の記事と当ブログ記事の類似性が高いことを認め、対象となる記事と当ブログの内容を説明し、謝罪の言葉をのべています。

私が第一に求めたかったことは、当該の記事が私の記事を元にしたことである事を公の形で認めてもらう事でしたので、これで私としてはこの件については終了したいと思っています。

(ただし、これは当ブログについての著作権等を放棄するものではありません。)

なお、謝罪文と同時に掲載された私の同人誌の案内は私が要求したものではありませんが、上記の記事が私の記事を元にしたことを周知させるにあたって有用と判断したため、編集部の考えの通りにしてもらいました。

支援くださった方々へ

該当のブログ記事を執筆中から非常に熱心なフィードバックをくださり、同人誌にも協力していただいたからあげさん(id:karaage)には、相談に乗っていただいた上ブログ記事でこの件をとりあげていただきました。 Interface誌に謝罪が載るまではこの件について取り上げないようにしようと考えていたためにお礼が遅れてしまいましたが、からあげ氏にはこの場を借りて改めて感謝させていただきます。

また、この件について、Interface誌への連絡がTwitterというオープンな手法であったために、ツイッター上でのあたたかい励ましの声を多数いただきました。

この他に、同人誌「ゼロから作るRAW現像」を支援として購入いただいた方も多数いらっしゃいました。

私自身非常に意気消沈する出来事だっただけに、こういった支援の声が大きな励みになりました。 あらためてこの件について温かい言葉をかけていただいた方、また同人誌を購入頂いた方々に、感謝したいと思います。

ありがとうございました。

ラズベリーパイ4にCLionをインストール

CLionとラズベリーパイ4

はじめに

先日まで知らなかったのですが、CLionやPyCharmはラズベリーパイで動作するようです。

とくにしかけは必要ありません。ただ配布されているパッケージをインストールするだけです。 どうやらCLionやPyCharm含めたIntelliJ系のIDEはほとんどの部分Javaで動作しているようです。

ただし、オフィシャルにサポートされているわけではないようなので、試される方は自己責任で実行ください。

また、当ブログの著者はこのブログで紹介した内容を実行した結果について、いかなる責任も負いかねます。

CLionをラズベリーパイ4にインストール

CLionをラズベリーパイ4にインストールしてみます。使用した機種はRaspberry Pi 4B 4GB版で、OSはRaspbian OSの32bit版(Buster)です。

Raspberry Pi OSの64bit版でもインストールできましたが、手順に一部細かな違いがありますので、そういった点も紹介します。

まずはLinux版のパッケージをダウンロードします。

f:id:uzusayuu:20200608054748p:plain
CLionのダウンロードページ

ダウンロードしたら解凍して、インストールしたいフォルダに移動します。 今回は/home/pi/bin/にインストールしました。

# ダウンロードしたフォルダで実行
# ファイル名はダウンロードした実際のファイルに一致させる
tar -xvf CLion-2020.1.2.tar.gz

# インストールしたいフォルダを指定。今回は~/bin/にインストールする。
mkdir -p /home/pi/bin
mv clion-2020.1.2 /home/pi/bin

Java VMがインストールされていなければ、インストールします。 自分が試したところ、64bit版のRaspberry Pi OSではデフォルトではインストールされていませんでした。

sudo apt update
sudo apt install default-jdk

あとはbinフォルダ以下のclion.shを実行します。

/home/pi/bin/clion-2020.1.2/bin/clion.sh

うまく動作すれば、プライバシーライセンスなどの確認画面が表示されますので、レビューして問題なければ許諾して進みます。

初回起動時はスクリプトの設定やプラグインの設定画面がでます。今回はデフォルトのままで進みます。

また、途中でライセンスの確認画面が出るので、ライセンスを持っている場合は入力する必要があります。なければ評価版として進めて行きます

CLionの実行環境の設定

初回の実行時、自分の環境ではこのような設定画面が表示されました。

f:id:uzusayuu:20200608054901p:plain
CLion設定、変更前

どうもバンドルされているcmakeが実行できないのが原因のようです。おそらくx86用のものしか付属しないのでしょう。

解決するためにcmakeをインストールして、CLionに設定します。

sudo apt install cmake

cmakeとgdbのパスを設定すると、のこりは自動で設定されます。

f:id:uzusayuu:20200608054945p:plain
CLion設定、変更後

これでCLionが起動できます。

f:id:uzusayuu:20200608055032p:plain
CLion起動画面

CLionの動作確認

この節は単なる動作確認です。 通常のLinuxでの動作と同じなので、CLionをご存知の方は読み飛ばしても問題ありません。

さっそくNew Projectを選んでみましょう。C++ Executableを選択して、LOCATIONをhelloにします。

f:id:uzusayuu:20200608055111p:plain
New Project

Createをクリックして次にすすみます。

すでに"Hello, world!"と表示するデフォルトのmain.cppができています。

f:id:uzusayuu:20200608055133p:plain
hello world code

右上の三角形をクリックして実行します。

f:id:uzusayuu:20200608055154p:plain
Hello world execution

Hello, world!と表示されました。動作確認成功です。

追加の設定

2回めの起動以降、外部のファイルをモニターするfsnotifierが動作しないという警告が表示されました。 これは、fsnotifierをコンパイルしてパスの設定をすることで回避できます。くわしくはこちらを参照ください。

Compiling File Watcher - IntelliJ IDEA - Confluence

上記の記事にしたがって、必要な実行ファイルを作成してCLionに設定してみます。

まず適当なフォルダを作って、その中で以下のコマンド実行して必要なファイルをダウンロードします。 これは一つ一つブラウザなどからダウンロードしても構いません

wget https://raw.githubusercontent.com/JetBrains/intellij-community/master/native/fsNotifier/linux/fsnotifier.h
wget https://raw.githubusercontent.com/JetBrains/intellij-community/master/native/fsNotifier/linux/inotify.c
wget https://raw.githubusercontent.com/JetBrains/intellij-community/master/native/fsNotifier/linux/main.c
wget https://raw.githubusercontent.com/JetBrains/intellij-community/master/native/fsNotifier/linux/make.sh
wget https://raw.githubusercontent.com/JetBrains/intellij-community/master/native/fsNotifier/linux/util.c

次にmake.shを実行します。

chmod u+x make.sh
./make.sh

32bit版だと、fsnotifier-armv7lというファイルができています。(64bit版ではfsnotifier-aarch64)

これをpycharmのbinフォルダにコピーします。 以下は先程のインストールパスの場合の例です。違うフォルダにインストールした場合は、そのフォルダにコピーしてください。

cp fsnotifier-armv7l ~/bin/clion-2020.1.2/bin/

CLionに戻って、Help -> Edit Custom Propertiesを選択します。ファイルを作るか聞かれたらYesを押して作成します。

以下の行を入力して、セーブします。

32bit版の場合

idea.filewatcher.executable.path = fsnotifier-armv7l

64bit版の場合

idea.filewatcher.executable.path = fsnotifier-aarch64

f:id:uzusayuu:20200608055221p:plain

これでfsnotifierに関する警告はでなくなると思います。

その他のIntelliJ製品

Raspbian上にPyCharm CEをインストールしてみたところ、こちらもインストールができました。

f:id:uzusayuu:20200608031309p:plain

まとめ

ラズベリーパイ4にCLionをインストールしてみました。 最低限必要な事前準備ははJava VMがインストールされている事と、cmakeなどのC++開発自体に必要な環境が構築されていることを確認することだけです。

自分自身インストールしたばかりでどんな使い勝手かまだわかりませんし、どんな不具合があるかも予想できませんが、いろいろ試してみようと思います。

Nexdock 2 を買いました

Nextdock 2 を買いました

去年注文したNexdock 2が一月ほど前に届きました。

f:id:uzusayuu:20200607144519j:plain
NexDock 2 とラズベリーパイ4

最初は癖があって使いにくいと思ったのですが、使いこなし方のコツを覚えたらだいぶ実用的になりました。

NextDock って?

NexDockというのは、FullHDモニターとキーボード、バッテリーが一体化した製品です。

nexdock.com

ノートPCとの最大の違いは、プロセッサやストレージが載っていない点です。PCや外部ディスプレイ対応のスマートフォンを接続して使うのが前提です。 私はラズベリーパイ4を接続してつかっています。

私が使っているのはNexDock 2ですが、こちらはもう注文を受け付けていないようです。 今はタッチ機能付きのNexDock Touchの注文を受け付けているようです。

使い勝手の方ですが、とっつきは良くないものの、うまく使いこなせれば悪くないと思います。 ただ、自分もなれるまで苦労したので、そういう試行錯誤や不安定さが許容できない人(例えば仕事で本格的に使いたいなど)は、事前に調査してから購入された方が良いと思います。

ラズベリーパイとの接続

ラズベリーパイとの接続には、USBケーブルと、HDMIケーブルを使います。 癖があるというのは主にこの部分に関するものです。

マニュアル通りに接続すると、NexDock2 とラズベリーパイの間の接続は*1

  • Raspberry Pi Micro HDMI 出力 -> Micro HDMI to HDMI 変換器 -> HDMIケーブル -> NexDock2 HDMI
  • Raspberry Pi USB Type-A -> 専用ケーブルのUSB Type-A端子 -> Nex Doc 2 USB Type-C
  • Raspberry Pi USB Type-C 電源 -> Type-C to Micro USB 変換器 -> 専用ケーブルのMicro USB端子 -> NexDock 2 USB Type-C

となります。(なお、ケーブルや変換器はすべて製品パッケージに含まれています。) どうもこの接続が厄介で、

  • 変換器に力がかかりやすい
  • 専用ケーブルが二股な上、硬くて扱いにくい
  • USB接続が不安定な気がする
  • 専用ケーブルがさせるNexDock 2 USB Type-Cポートは特定の一つだけで間違えやすい

といった問題がありました。とくに不安定なのは問題で、ボタンを押していないのに特定のキー入力が続いたりすることまでありました。 ただこのあたりは

  • 使いやすいMicro HDMI to HDMIケーブルにとりかえ
  • 専用ケーブルをやめ、USB Type-C ケーブルを使う

という方法で改善できました。

特に後者はマニュアルには記載がなかったのですが、NexDock2のサポートページに方法がのっていました ラズベリーパイのconfig.txtに以下の行を付け加えると、ラズベリーパイ4の電源用USB Type-C端子が、USB接続にも使えるようになるそうです。

# USB Type-C Host
dtoverlay=dwc2,dr_mode=host

ラズベリーパイの電源端子は電源専用だと思っていたので驚きました。

これで接続に必要なケーブルが2本に減り、しかも専用ケーブルを使わずにすむのでだいぶスッキリしました。 ケーブルの取り回しが楽になったので、ラズベリーパイ本体をモニター裏に貼り付ける、なんてこともやりやすくなりました。

f:id:uzusayuu:20200607150846j:plain

その他のTip

その他の問題と、改善方法を紹介します

タッチパッドが敏感すぎる

タッチパッドが大きい上に敏感なので、キー入力中についつい触れてしまうことがありました。 こちらはフォーラムで「Fn + ESCでタッチパッドが一時的にオフにできる」という投稿を見つけて解決しました。

今は画像のようにマウスと併用していますが、持ち運んでいるときなどはタッチパッドに切り替えて使うこともできます。

画像がブランクになると電源が切れる

NexDock2の電源はHDMI入力に連動しているので、ラズベリーパイの画像出力が止まると電源が切れます。 通常の接続では、ラズベリーパイの電源はNexDock2から供給されるので、ラズベリーパイの電源も切れます。 しかもよりによって、ラズベリーパイのスクリーンセーバーの初期設定は、画像出力をオフにする事になっているようです。 この組み合わせのせいで、ラズベリーパイをしばらく放置していると電源が切れている事がよくありました。

これは画像の出力がオフにならないようにすることで解決できます。 自分はxscreensaverをインストールしてスクリーンセーバーをオフにしました。

その他

あいにく自分の使っているスマートフォンは外部モニタに対応していないのですが、HDMI出力のあるものなら大概接続できるはずです。 USBで電源供給できるものなら、モバイル化するのも容易です。

たとえば、メガドラミニをつなげば、どこでもメガドラミニが!

f:id:uzusayuu:20200607152605j:plain

まとめ

癖があるので万人におすすめするものではありませんが、NexDock 2はなかなか面白いデバイスです。

特にラズベリーパイ4と接続する際は

  • config.txtの設定で、接続に必要なUSBケーブルの本数を一本にする
  • Micro HDMI to HDMIのケーブルにかえる
  • とりまわしのしやすいUSB Type-C ケーブルにかえる
  • xscreensaverを導入するなどして、画像出力がブランクにならないようにする
  • Fn+ESCを使って、不要なときはタッチパッドをオフにする

といった方法で、使い勝手を向上させる事ができました。

*1:ちなみに対応スマートフォンとの接続にはUSB Type-Cケーブル一本ですみます。

RISCVエミュレータ-ELFファイルの実行

はじめに

前回前々回のエントリーの続きです。

ゆっくりとRISCVエミュレータを作っています。

命令の追加

RV32Iの命令の殆ど(SRETとWFI以外)を処理できるようになりました。 ただし、システムレジスタ系の命令(CSRR*)は、読み書きはできるものの内部状態は実装されていません。 同じ理由でMRETも、権限の変更は行いません。

システムコールエミュレーション

ECALL命令ではシステムコールのエミュレーションを実行します。今実行できるのは以下の2つです。

システムコール 番号 処理
exit 93 終了
write 64 ファイルへの書き出し

fstat等の実装がまだなので、writeが出力するのは標準出力だけです。

ELFファイルの読み込み

簡単なELFファイルを読みこんで実行できるようになりました。 これで普通のC言語でRISCVプログラムを書いて、GCCでクロスコンパイルして、RISCVエミュレータで実行する事ができます。

RISCV用のクロスコンパイル環境はriscv-gnu-toolchainを使用しました。

github.com

実行できる命令が限られているので、このエミュレータ用のコンフィギュレーションにするには、toolのビルドのときに、

./configure --prefix=/opt/riscv --with-arch=rv32i --with-abi=ilp32

を指定して、I命令とILP32のABIを指定する必要があります。

これで、例えばこんなCプログラムが実行できます。

#include <unistd.h>

int main()
{
  write(1, "Hello, RISCV\n", 13);
  return 0;
}

コンパイルするときはriscv用コンパイラを使って、RV32IとILP32を指定して、ライブラリを静的にリンクする必要があります。 例えばこうなります。(gccにパスが通っている前提です。)

$ riscv32-unknown-elf-gcc hello.c -o hello -Wall -march=rv32i -mabi=ilp32 -static

これでhelloという名前のELF形式実行ファイルが作られます。

ちなみに-Sオプションをつけてコンパイルするとこんなアセンブラコードになります。

        .file   "hello.c"
        .option nopic
        .attribute arch, "rv32i2p0"
        .attribute unaligned_access, 0
        .attribute stack_align, 16
        .text
        .section        .rodata
        .align  2
.LC0:
        .string "Hello, RISCV\n"
        .text
        .align  2
        .globl  main
        .type   main, @function
main:
        addi    sp,sp,-16
        sw      ra,12(sp)
        sw      s0,8(sp)
        addi    s0,sp,16
        li      a2,13
        lui     a5,%hi(.LC0)
        addi    a1,a5,%lo(.LC0)
        li      a0,1
        call    write
        li      a5,0
        mv      a0,a5
        lw      ra,12(sp)
        lw      s0,8(sp)
        addi    sp,sp,16
        jr      ra
        .size   main, .-main
        .ident  "GCC: (GNU) 9.2.0"

こちらが実行結果です。

$ cmake-build-debug/RISCV_Emulator hello
Elf file name: hello
This is an Elf file
Program Header 0:Type: LOAD. Copy to 0x10000 from 0x0, size 5270. 
Memory size extended to 100000
Loaded
Program Header 1:Type: LOAD. Copy to 0x12498 from 0x1498, size 2132. Loaded
Section .bss found at 0x01cec.
Secure BSS.
Entry point is 0x10090
Section .symtab(2) found at 0x01d1c.
Number of symbols = 92, (1472 bytes)
Section .strtab found at 0x022dc.
Symbol "__global_pointer$" found at index 34.
Global Pointer Value = 0x12ca8.

Memory size extended to 800000
Execution start
Hello, RISCV
Return value: 0.

いろいろエミュレータが生成したメッセージに紛れていますが、最後に"Hello, RISCV"と表示されています。成功です。

この例ではwrite以外のシステムコールを使わずに済むように、write()を使って出力させましたが、printf()でも動作するようです。

RISCV-TESTSの実行。

前回のエントリでも触れましたが、RISCVにはRISCV-TESTSという名前の標準テストがあります。

github.com

このテストのうち、rv32ui(RV32ユーザーレベル、整数命令のみ)を実行してみたところ、LH命令にサイン拡張のバグが見つかりました。

テスト重要ですね。

他にも何個か見つかったバグを修正し、すべてのテストがパスするようになりました。

まとめ

RISCVのエミュレータC++で書いて、簡単なプログラムのELF形式実行ファイルを処理できるようになりました。

また、RISCV-TESTSのユーザーレベル整数命令テストをパスすることを確認しました。

このエミュレータのコードは私のgitリポジトリで公開しています。

github.com

RISCVエミュレータの途中経過

はじめに

前回のエントリーの続きです。

ちょっと今週来週雑用で作業ができなそうなので、忘れないように自分用の進捗メモです。 またしても読者の方々の事はあまり考えていません。

わざわざページ開いてくださった方には、もうしわけありません。いつかまとめてエントリーかきます。

このプロジェクトについて

RISC-Vのエミュレータをゆっくり作っています。最終目標はFPGA上で動作させることです。

github.com

すでに同様のものが多数あるのは知っていますが、自分の趣味と学習が目的ですので特に気にしていません。

命令の追加

命令を多数追加しました。いま実装されている命令は次のとおりです。

命令 タイプ
add rd, rs1, rs2 R
addi rd, rs1, im12 I
and rd, rs1, rs2 R
andi rd, rs1, imm12 I
beq rs1, rs2, offset B
bge rs1, rs2, offset B
bltu rs1, rs2, offset B
bne B
jal rd, offset21 J
jalr rd, offset(rs1) I
lw rd, offset(rs1) I
lui rd, imm24 U
or rd, rs1, rs2 R
ori rd, rs1, imm12 I
sll rd, rs1, rs2 R
slli rd, rs1, shamt I
slt rd, rs1, rs2 R
slti rd, rs1, imm12 I
sltiu rd, rs1, imm12 I
sltu rd, rs1, imm12 R
sra rd, rs1, imm12 R
srai rd, rs1, imm12 I
srl rd, rs1, imm12 R
srli rd, rs1, imm12 I
sub rd, rs1, rs2 R
xor rd, rs1, rs2 R
xori rd, rs1, imm12 I

結構増えました! RV32Iの50命令中、22個実装しています。

実行できるようになったもの。

命令を増やしたので、実行できるアルゴリズムが増えました。 例えばRISC-V原典にのっているインサートソートが実行できます。

// A1 is n and A3 points to array[0]
// A4 is i, A5 is j, A6 is x
addi A3, A0, 4
addi A4, ZERO, 1
// Outer Loop
bltu A4, A1, 8
jalr ZERO, RA, 0
lw A6, A3, 0
addi A2, A3, 0
addi A5, A4, 0
// Inner Loop
lw A7, A2, -4
bgte A6, A7, 20
sw A2, A7, 0
addi A5, A5, -1
addi A2, A2, -4
bne A5, ZERO, -20
// End of Inner Loop
slli A5, A5, 2
add A5, A0, A5
sw A5, A6, 0
addi A4, A4, 1
addi A3, A3, 4
jal ZERO, -64
// End of Outer Loop

レジスターA3にソートする配列へのポインター、A1にソートする要素の数を代入して読み出すとソートしてくれます。 こちら動作結果です。

Before: 116 211 664 486 472 777 429 528 290 433 136 777 502 357 160 481 731 675 802 671 427 21 949 350 997 985 960 483 836 987 126 305 551 790 791 375 919 220 255 209 6 392 339 508 101 499 989 832 174 791 856 953 164 805 655 161 142 616 644 331 955 122 636 506 265 427 233 184 999 489 746 357 881 85 865 982 584 207 167 110 998 23 415 515 180 71 676 675 39 673 6 994 795 642 853 412 421 86 949 772

After: 6 6 21 23 39 71 85 86 101 110 116 122 126 136 142 160 161 164 167 174 180 184 207 209 211 220 233 255 265 290 305 331 339 350 357 357 375 392 412 415 421 427 427 429 433 472 481 483 486 489 499 502 506 508 515 528 551 584 616 636 642 644 655 664 671 673 675 675 676 731 746 772 777 777 790 791 791 795 802 805 832 836 853 856 865 881 919 949 949 953 955 960 982 985 987 989 994 997 998 999

なんだかCPUの動作っぽくなってきました。

テストの追加

複雑になってきたのでテストを追加しました。

今回のコードではテストは主に、アセンブラ作成部分のテストと、CPUの動作のテストに分かれています。

アセンブラ部分のテスト

アセンブラ作成部分では一度符号拡張で見つけにくいエラーをだしてしまったのでカバレッジを上げることにしました。 具体的には以下の部分をランダム化したテストを各命令毎に作成しました。

  • rd
  • rs1
  • rs2
  • immediate

命令タイプによって存在しないものは除きます。 テストの内容は、

  1. ランダム化したパラメータを作成
  2. ランダム化したパラメータからバイナリ命令を作成
  3. アセンブラ機能を使ってパラーメータからバイナリ命令を作成
  4. 2で作成したものと3で作成したものを比較。

というものです。 3でテストを作成したのも自分自身なので、同じ誤解を2回している可能性はありますが、そうではないテクニカルな失敗はかなり防げます。

このテストは実装した全命令に対してそれぞれ100回ずつ行っています。

CPU部分のテスト

CPU側では上記のような命令ごとのユニットテストは難しいのですが、なるべくそれに近いものを作っています。 たとえば、add rd, rs1, rs2のテストでは、次のようなバイナリー・コードを生成します。

addi rs1, ZERO, value1 & 0xFFF
lui rs1, (value1 >> 12)
addi rs2, ZERO, value2 & 0xFFF
lui rs2, (value2 >> 12)
add rd, rs1, rs2
addi A0, rd, 0
jalr ZERO, RA, 0

ここで、value1, value2, rd, rs1, rs2はランダム化されたテストパラメータです。

これでadd rd, rs1, rs2に与えるパラメータ(レジスタの組み合わせ、レジスタの内容)のカバレージはかなり上がると思います。

ランダム化したテストはそれぞれ100回ずつ行っています。

また、同様のテストは他のR Typeの命令(cmd rd, rs1, rs2形式のもの)や、addiなどI Typeの命令(cmd rd, rs1, imm12形式のもの)でも行いました。

これらのユニットテストの他に、前回の1から10まで足し合わせるプログラムと、前述のソートプログラムをテストとして、コードを変更するたびに実行しています。

次のステップ

  • Bタイプ命令(blt等)へのランダム化テストの追加
  • LD/SW命令等の追加(+テスト)
  • 外部ファイル読み取り
  • 最小限のシステムコールのエミュレーション(テキストの表示くらいしたい)
  • システム系命令の対応
  • テストの自動化
  • MMUとか割り込みとかどうしよう(最終目標はハードウェア実装なので)

先は長いですね。

追記

記事のアップロード後早速こんな有用なコメントをいただきました。ありがとうございます。

当該のテストはこちらです。今後のTODOにいれておきます。

https://twitter.com/LDScell/status/1175905081050329088?s=20 github.com