FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

「30日でできる!OS自作入門」を読み始めた (21日目. OSを守る)

30日でできる! OS自作入門

30日でできる! OS自作入門

30日でできる!21日目はOSを守る。目的がなんだかわからなくなってきたが、要するにアプリケーションを呼び出した後にどのように処理をするか、ということなのだが、APIを処理するための割り込みを用意してそこをすべて通過させるようにする。

最初結構手こずったが、最終的にはちゃんと動かすことができた。

f:id:msyksphinz:20180425235957p:plain

bim2hrbを使わない分、アセンブラを使うプログラムはHariMainラベルを追加したり、ちょっと改造する必要があるな。

hello2.hrb: hello2.nas 
    nasm -felf32 $^ -o tmp.o -l $@.lst
    ld -m elf_i386 -e HariMain -n -Thrb.ld -static -o $@ tmp.o

crack2.hrb: crack2.nas
    nasm -felf32 $^ -o tmp.o -l $^.lst
    ld -m elf_i386 -e HariMain -n -Thrb.ld -static -o $@ tmp.o
[BITS    32]
      GLOBAL    HariMain
      
HariMain:   ; ラベルを挿入したり。
    mov     edx,2
    mov     ebx, msg
    int     0x40
    mov     edx, 4
    int     0x40

msg:
    db      "hello", 0

hrb.ld は以下のように設定した。

  • hrb.ld
OUTPUT_FORMAT("binary");

SECTIONS
{
    .head 0x0 : {
        LONG(49 * 64 * 1024)  /*  0 : stack+.data+heap の大きさ(4KBの倍数) */
        LONG(0x69726148)      /*  4 : シグネチャ "Hari" */
        LONG(0)               /*  8 : mmarea の大きさ(4KBの倍数) */
        LONG(0x310000)        /* 12 : スタック初期値&.data転送先 */
        LONG(SIZEOF(.data))   /* 16 : .dataサイズ */
        LONG(LOADADDR(.data)) /* 20 : .dataの初期値列のファイル位置 */
        LONG(0xE9000000)      /* 24 : 0xE9000000 */
        LONG(HariMain - 0x20) /* 28 : エントリアドレス - 0x20 */
        LONG(0)               /* 32 : heap領域(malloc領域)開始アドレス */
    }

    .text : { *(.text) }

    .data 0x310000 : AT ( ADDR(.text) + SIZEOF(.text) ) {
        *(.data)
        *(.rodata*)
        *(.bss)
    }

    /DISCARD/ : { *(.eh_frame) }

}

Amazon EC2 F1インスタンス ハンズオン 参加

大崎にあるXilinxさんで開催されたAmazon EC2 F1インスタンスのハンズオンに参加してきました。

EC2 F1インスタンスに興味を持ったのは、RISC-VのFireSimがもともとF1インスタンスを対象としているから。

また、大きめのデザインを開発しても、なかなか大きなFPGAって高価で手が出ない。F1インスタンスならタイムシェアリングでコストを下げられるのではないか、ということでやり方を勉強するために参加してみた。

参加するにあたり、結構厚めの資料を頂いた。手順としては、かなりきめ細かく、

EC2のインスタンスの起動方法などは、そこまできめ細かく教えてくれなくてもいいよ...と思うくらいにきめ細かいのだけれども、逆にセキュリティグループの話とかしっかり聞けて、これまで結構あいまいにしていた部分などがすっきりした気がする。

これは個人の意見だが、FPGAアクセラレーションされている、っていうのは、手元にFPGAがあってそれが動いて、初めて実感できる気がする。 だから、バージニアのどこかにあるFPGAボードで自分のデザインが動いて、ログとして~~だけ高速化されました、っていうのは正直ちょっと実感がわかない。 ましては元のソースコードOpenCLとなると、本当に..?ってなってしまう。

今回の資料では、いろいろコマンドをたたいてみてコンソールを確認しながら実際にF1インスタンスを動かしていく。 ハンズオンなので仕方がないのだが、とりあえず動かしてみて予定通りの結果が出ればOK、それよりももうちょっと中身を見てみたい... まあそれは自分でMakefile読んでください、って感じなのだろう。

まあやり方はそれでいいのだろうけども、バージニアインスタンスってやはり距離の問題か非常にレスポンスが悪くて、実際にここで開発する、というわけにはいかない。

じゃあどうやってF1インスタンスを活用すればいいのだろう?ってセミナー中にいろいろ考えていたのだが、

  • SDAccelでC/C++のコードを書く、またはVerilogを書いてF1インスタンスで動かす場合、

  • 実際のコーディングはローカル(または日本のサーバ)で行う (でないとレスポンスが遅くてやってられない)

  • 例えば、リグレッションテストを行いたい場合、F1インスタンスを立ち上げる(そして、専用のディスクを復帰させる)
  • 自分のコードをF1インスタンスに付随しているx86フロントエンドに流し込む。
  • コンパイルを行い、Amazon AFIを作成する(通常これがめっちゃ時間かかる)
  • FPGAに流し込み実行する。結果を回収する。

っていうフローを構築しておかないと絶対に使い物にならない。 だいたいこんな感じのフローになるのかな?これをちゃんと構築しないと、コストばかりかかってストレスばかり溜まりそう(東京インスタンスは出来ないのですかね...)

f:id:msyksphinz:20180425234904p:plain
図. Amazon F1インスタンスの使い方?(想像)

そのためには、自分の環境構築用のスクリプトなどが入った専用のディスクは保持しておかなければならないし、そこはちょっとコストが発生する。

あとはデバッグ環境も気になった。どうやら通常のLogic Analyzerも使えるようでそれは一安心。

さらに今回はSDAccelを使ったデザインを触ってみたが、やはり純粋VerilogのデザインをF1インスタンスで流せるような環境がうれしいよね。 というわけでAmazon F1 HDKなどもちょっと気になるところだ。見ていきたい。

github.com

2018年のRISC-V Workshopのスケジュールが公開されました

f:id:msyksphinz:20180421185728p:plain

2018年のRISC-V Workshopのスケジュールが公開されたようです。

日本でもRISC-V Day Tokyoの第2回が開催のようですね。

riscv.org

RISC-V Summitってなんだ?

関連記事

RISC-VツールセットをインストールしたDockerコンテナ作成(3. 自作RISC-Vエミュレータのリグレッション)

f:id:msyksphinz:20180418005224p:plain
f:id:msyksphinz:20180424020355p:plain

RISC-V 対応の自作エミュレータを作成している。テストパタンセットであるriscv-toolsがかなりPassできるようになってきた。

前回RISC-Vのツールセットが入ったDockerコンテナを用意したので、RISC-Vのテストパタンセットを動作させてみる。

以下のようなDockerを起動するためのスクリプトを用意した。riscv_issは自作RISC-Vエミュレータの場所だ。

  • run_docker_test.sh
#!/bin/sh

sudo docker run -v ${PWD}/riscv_iss:/root/riscv_iss\
         -v ${PWD}/scripts:/root/scripts \
         -it msyksphinz/riscv-docker \
         /root/scripts/test_run.sh

ここで読んでいる test_run.sh は以下のような構成にしている。

  • test_run.sh
#!/bin/sh

export RISCV=/opt/riscv/

cd /root/riscv_iss/build_riscv_iss/isa_test/
make ISA_DIR=/riscv/riscv64-unknown-elf/share/riscv-tests/isa/

このようにしてRISC-V自作エミュレータディレクトリを外部ボリュームとしてDockerに接続し、リグレッションを実行した。

リグレッション結果は riscv_iss/build_riscv_iss/isa_test/result.txt に保存されている。無事にリグレッション成功だ!400本あるテストパタンのうち、Failしたのは以下の十数本だけだった。

  • riscv_iss/build_riscv_iss/isa_test/result.txt.txt
sc_forest_iss                  Fail
rv32mi-p-ma_fetch              Fail
rv64uc-v-rvc                   Fail
rv32si-p-sbreak                Fail
rv64uc-p-rvc                   Fail
rv32ua-v-lrsc                  Fail
rv32si-p-ma_fetch              Fail
rv32uc-p-rvc                   Fail
rv64ua-p-lrsc                  Fail
rv32mi-p-breakpoint            Fail
rv32uc-v-rvc                   Fail
rv64si-p-wfi                   Fail
rv64mi-p-access                Fail
rv32ua-p-lrsc                  Fail
rv64mi-p-ma_addr               Fail
rv32si-p-wfi                   Fail
rv32si-p-dirty                 Fail
rv64si-p-dirty                 Fail
rv64ua-v-lrsc                  Fail
rv32mi-p-mcsr                  Fail
rv64si-p-ma_fetch              Fail
rv32mi-p-shamt                 Fail
rv32mi-p-sbreak                Fail
rv32mi-p-ma_addr               Fail
rv64mi-p-illegal               Fail
rv64mi-p-ma_fetch              Fail
rv64mi-p-breakpoint            Fail
rv32mi-p-illegal               Fail
rv64ud-p-move                  Fail

RISC-VツールセットをインストールしたDockerコンテナ作成(2. RISC-Vコンテナの作成)

f:id:msyksphinz:20180418005224p:plain

RISC-V 対応の自作エミュレータを作成している。テストパタンセットであるriscv-toolsがかなりPassできるようになってきた。

満足したところで公開したいので、一応リグレッションテストをいつでも実行できるような状態にしておきたい。

とりあえず自分で色々改造できるDockerのコンテナを持っておきたい。 このため、自分のRISC-VツールをインストールしたDockerコンテナを構築した。

これを使って、常にそのコンテナを呼び出すことによってRISC-Vのツールを呼び出すことができ、それに外部ボリュームとして自作エミュレータを接続することでRISC-Vのツールセットを使ったテストができるような環境を構築しておく。

f:id:msyksphinz:20180424020355p:plain

やっていることは非常に単純なはずなのだが、なにぶんDockerはあまり慣れていないので常にトラブルが頻発する。

っていうか自宅のネットが遅すぎてDockerのためにUbuntuをダウンロードしたり、パッケージをダウンロードするのが非常に遅い... 一度Dockefileを間違えて修正すると一からコンテナを作り始めたのには閉口した。もう一回あのRISC-Vの大量のパッケージ群をダウンロードしなおしかよ...

とりあえず以下のようなDockerfileと、リグレッション用のスクリプトを用意している。

  • Dockerfile
# Pull base image (use Wily for now).
FROM ubuntu:17.10

# Set the maintainer
MAINTAINER msyksphinz

# Install some base tools that we will need to get the risc-v
# toolchain working.
RUN apt update && apt install -y \
  autoconf \
  automake \
  autotools-dev \
  bc \
...
# Make a working folder and set the necessary environment variables.
ENV RISCV /riscv
ENV NUMJOBS 4
RUN mkdir -p $RISCV

# Add the GNU utils bin folder to the path.
ENV PATH $RISCV/bin:$PATH

# Obtain the RISCV-tools repo which consists of a number of submodules
# so make sure we get those too.
WORKDIR /opt/riscv
RUN git clone https://github.com/riscv/riscv-tools.git && \
  cd riscv-tools && git submodule update --init --recursive

RUN apt update && apt install -y pkg-config libbfd-dev device-tree-compiler zlib1g-dev libz-dev 

# Now build the toolchain for RISCV. Set -j 1 to avoid issues on VMs.
WORKDIR /opt/riscv/riscv-tools
ENV MAKEFLAGS="-j4"
RUN ./build.sh

ちなみにずーっと以下のエラーで悩まされ続けていたのだが、libexpat-devパッケージをダウンロードすることで解消可能らしい。 riscv-tools の情報は古いな...

RUN apt update && apt install -y pkg-config libbfd-dev device-tree-compiler zlib1g-dev libz-dev libexpat-dev

そして、ボリュームのマウントおよびコンテナの起動を行うためのスクリプトを用意した。

  • run_docker_test.sh
#!/bin/sh

sudo docker run -v ${PWD}/riscv_iss:/root/riscv_iss\
     -v ${PWD}/scripts:/root/scripts \
     -it msyksphinz/riscv-docker \
     /root/scripts/test_run.sh

そしてtest_run.shは実際にテストを行うスクリプトだ。

  • test_run.sh
#!/bin/sh

export RISCV=/opt/riscv/

cd /root/riscv_iss/build_riscv_iss/isa_test/
make ISA_DIR=/root/

技術書典4に参加してきました

普段はイベントに参加することはあまりないのだけれども、技術書典4は面白そうだったので参加してきました。

とりあえず会場についてビックリ。整理券なんて配布しているのか! 整理券を受け取ってから、入場まで1~2時間くらいかかりそうだったので会場を離れていたら、結構すぐに入場できるようになった。

が、とりあえず人が多い!移動するのも一苦労だ。行ったことないけどコミケもこんな感じなのかなー。

f:id:msyksphinz:20180422151129j:plain

とりあえず低レイヤあたりの本を探した。System Programmingの本とか(これは紙版が無かったので電子版)、OS自作の本とかを探して購入。

特にこれ、すごいなーと思ったのは、とくにどのプラットフォームを参考にすることもなく自作OSを作った話。 こういうのすごくあこがれる。これを読んでRISC-Vに移植とかできたら最高だな。

f:id:msyksphinz:20180422235858p:plain

初めてのイベントは、とりあえず人が多すぎてゆっくり出来ないので、これだったら電子版をネットで買ったほうが良い気がしてきた...

次回は参加するかどうか微妙ですね。会場が広くならない限り。

RISC-Vの32bitモードと64bitモードの動作の違いについて

RISC-V にはRV32とRV64のモードが存在しており、これはアドレッシングモードのみを示しているものと思いがちだが、

と決められている。

For RV32, the x registers are 32 bits wide, and for RV64, they are 64 bits wide.

というわけで、シミュレータを開発する場合は、32ビットのモードと64ビットのモードを両方サポートしなければならないのだが、これを riscv-isa-sim で実現するためにはどのようになっているのだろうか。

自作シミュレータでは、C++のtemplateを利用して32ビットモードと64ビットモードのコードを両方用意していたのだが、面倒なので統一できるところは統一したい。

riscv-isa-sim における32bitモードと64bitモードのサポートについて

たとえば、riscv-isa-sim において add 命令の動作については以下のように定義されている。

WRITE_RD(sext_xlen(RS1 + RS2));
#define sext_xlen(x) (((sreg_t)(x) << (64-xlen)) >> (64-xlen))
#define zext_xlen(x) (((reg_t)(x) << (64-xlen)) >> (64-xlen))

つまり、sext_xlen を使って、32bitモードの場合は64ビットのうち上位はすべて符号ビットで埋めるようにしている。

基本的に32bitモードで整数命令を動かす場合にはこの方式で動作しているようだ。 たとえば、テストパタン内で、sub命令をテストする場合 (以下は自作シミュレータのログ)

        50:U:MBar:[80000134][P80000134] 40208f33 : sub        r30,r01,r02          ra=>00000003 fp=>00000007 t4<=fffffffc
        51:U:MBar:[80000138][P80000138] ffc00e93 : addi       r29,r00,ffc          zero=>00000000 t3<=fffffffc
        52:U:MBar:[8000013c][P8000013c] 00400193 : addi       r03,r00,004          zero=>00000000 s1<=00000004
        53:U:MBar:[80000140][P80000140] 47df1e63 : bne        r30,r29,35           t4=>fffffffc t3=>fffffffc

sub命令の結果はt4<=fffffffcだが、実際にはt4<=fffffffffffffffc であり、基本的に比較命令などももISSとしてはすべて64ビットで比較するようになっている。

これに対応させることで、自作シミュレータでもかなりのパタンをパスできるようになった。

400本近くあるパタンのうち、落ちているのは以下のみとなった。

$ grep Fail result.txt
rv64si-p-dirty                 Fail
rv64uc-v-rvc                   Fail
rv64mi-p-ma_fetch              Fail
rv32si-p-sbreak                Fail
rv64uc-p-rvc                   Fail
rv32ua-v-lrsc                  Fail
rv32si-p-ma_fetch              Fail
rv64ua-p-lrsc                  Fail
rv32mi-p-breakpoint            Fail
rv32uc-p-rvc                   Fail
rv32mi-p-ma_fetch              Fail
rv64si-p-wfi                   Fail
rv32mi-p-mcsr                  Fail
rv32ua-p-lrsc                  Fail
rv32si-p-wfi                   Fail
rv64si-p-ma_fetch              Fail
rv32si-p-dirty                 Fail
rv64ua-v-lrsc                  Fail
rv64mi-p-ma_addr               Fail
rv32mi-p-sbreak                Fail
rv32mi-p-ma_addr               Fail
rv32uc-v-rvc                   Fail
rv32mi-p-shamt                 Fail
rv64mi-p-breakpoint            Fail
rv64mi-p-illegal               Fail
rv32mi-p-illegal               Fail
rv64ud-p-move                  Fail

f:id:msyksphinz:20180421185728p:plain