タグ:V-scale ( 45 ) タグの人気記事

前回はいろいろ中途半端になったので、V-scale のシミュレーション、FPGA 上での実行に必要な環境構築の話を書き直します。
RISC-V に固有でない開発環境の話は ここ にあります。

■ 実体
僕がいじっているものは V-scale 本体 と、FPGA 用の周辺回路 に置いてあります。本体は 本家の物を fork して手を入れているものですが、本家の方は結構古いまま放置されていて最新の開発環境では使えないと思います。
本体にはそのまま実行できる ISA テストも含んでいます。これは後述する tests をアセンブルして、Intel-Hex フォーマットに変換したものです。オリジナルの tests からは src/test/input/ で make すると変換できます。FPGA 用のブートROMはソースファイルしか置いていません。後述する開発環境を使って、src/main/c で make することで作成します。
Verilog シミュレータには Model-Sim か Verilator を使います。FPGA 用の環境で端末を含めてシミュレーションするには Verilator が必須です。Veriloator のバージョンは 3.884 以降がおすすめで、 3.882 以前の物を使う場合は Makefile から ”--l2-name v” を削除してください。

■ RISC-V 開発環境
本家の GNU Compiler Toolchain を使います。コンパイラは 32bit 版と 64bit 版を両方作ることになります。以前は 64bit 版のコンパイラでも、”-m32” オプションで 32bit 用のバイナリが作れたのですが、今は出来なくなった様です。聞いた話では、以前もライブラリのリンクの時に失敗していたとのこと。僕はライブラリを使っていないので、気付いていませんでした。インストールは配布サイトにある通り。とっても時間がかかるので Newlib 用しかインストールしてません。
[追記 rv32ima に変えました。Freedom E310 にも対応するためです。c を付けると vscale が動かなくなりそうなので付けません。a はたぶん勝手に使うことはないでしょうし、付けても大丈夫と判断。]
sudo apt-get install ........
./configure --prefix=/opt/riscv --with-arch=rv32ima --with-abi=ilp32
sudo make
./configure --prefix=/opt/riscv
sudo make
■ ISA テスト
こちらも本家の riscv-tests を使います。使うのは rv32mi, rv32ui, rv32um 辺りかな。アセンブラの引数チェックが厳しくなったのか、以下のファイルに修正が必要になりました。ってか、除算系は今まで意味のあるチェックが出来ていなかったっぽいです。
modified: isa/rv32um/div.S
modified: isa/rv32um/rem.S
modified: isa/rv32um/remu.S
modified: isa/rv64ui/sll.S
modified: isa/rv64ui/slli.S
modified: isa/rv64ui/srai.S
■ 命令セットシミュレータ
これは本当にいろいろなものがあるらしいですが、一番露出の多い本家の spike を使います。と言っても、ほとんど使う機会はありませんけど。リポジトリは Frontend ServerISA Simulatorpk の3つに分かれています。 これも配布サイトにある通りで簡単にインストールできますが、ISA Simulator は最後に make するのがいいみたい。また、先述の ISA テストももちろん spike で実行できますが、流したところで何の反応も示さないのでつまらない。spike を作る時に configure のオプションに --enable-commitlog を付けて make すると、とっても不親切ではありますが命令実行ログが取れるようです。[ -l オプションを付けて実行すると実行ログが出るそうです。]こんな感じなのですが、最初の2命令は何でしょうか?
~/RISC-V/riscv-tests/isa$ spike -l --isa=RV32 rv32uf-p-ldst
warning: only got 1401946112 bytes of target mem (wanted 4026531840)
core 0: 0x0000000000001000 (0x7ffff297) auipc t0, 0x7ffff
core 0: 0x0000000000001004 (0x00028067) jr t0
core 0: 0xffffffff80000000 (0x04c0006f) j pc + 0x4c
core 0: 0xffffffff8000004c (0xf1402573) csrr a0, mhartid
core 0: 0xffffffff80000050 (0x00051063) bnez a0, pc + 0
core 0: 0xffffffff80000054 (0x30102573) csrr a0, misa
core 0: 0xffffffff80000058 (0x00055863) bgez a0, pc + 16
core 0: 0xffffffff80000068 (0x00000e13) li t3, 0
core 0: 0xffffffff8000006c (0x00000297) auipc t0, 0x0

[PR]
by tom01h | 2017-01-25 23:34 | PCとか | Trackback | Comments(0)
いずれは FPU を V-scale に組み込むと思って tests を眺めてみた。recoding.S なんていう見慣れない物がある。噂に聞くところの 内部データフォーマット 向けのテストらしい。内部フォーマットでは数ビットの付加ビットを持って、回路を簡単にしているのでしょう。
IEEE 規格との違いは” some of these extras are redundant”
  • オーバフローしても仮数をALL0にしない
  • 正確なゼロでも指数をALL0にしない
と”others are illegal”
  • サブノーマル数は桁が長すぎる
だと思う。なんだよ。頑張ってサブノーマル出るようにしたのに。
でも、recoding.S では上の2つしか検証していません。
ついでに無駄知識が付きました。deadbeef はよく見るけど、cafebabe とか a bad 1(I)dea なんてのも有るんだね。
[追記 サブノーマル数は桁が長すぎるって事は、途中で割込みとかあってメモリに退避した時と何もない時とで、演算結果が違ってくるってことになるのかな?同じプログラム流しても再現性ないってこと?]

[PR]
by tom01h | 2017-01-23 23:32 | PCとか | Trackback | Comments(0)
V-scale chip がうまく動かないので、コンソールのついているシミュレータが欲しいです。せっかく Vivado ロジックアナライザの使い方の書いてある本を買ったのですが、やっぱりシミュレーションのほうが良い。そんな訳で、シミュレータを作ろうと思います。
まず、verilog で標準入力の方法がわからない。っていうか、そんなのあるのか?調べても分からなかったので、Verilator で環境を作ることにしました。C言語なら当然の事ながら標準入力があります。
実際の構成ですが、(ここら辺はまだ、いい加減な作りで誤魔化しているのですが、)コンソールとのインターフェイス用に、 UART の隣に CPU からは同じ機能に見えるモジュールを置きました。この中にいくつかレジスタを準備して、テストベンチから直接操作します。出力レジスタにデータをセットすると画面に文字が出力されます。入力レジスタのデータの有無を確認したときは、3連続でデータが無かったらシミュレーションを停止してキー入力を待ちます。キー入力されるとシミュレーションを再開して、CPU からデータが読めるように入力レジスタにデータをセットします。
で、作ってみると… 結構速い。やっぱり Verilator すごい。こんな感じで動いています。
~/RISC-V/vscale-chip/src/main/c/bootload$ make
[省略]
~/RISC-V/vscale-chip$
make verilator-sim
[省略]
~/RISC-V/vscale-chip$ make verilator-board-test
cp src/main/c/bootload/kzload.ihex loadmem.ihex
touch ram.data3 ram.data2 ram.data1 ram.data0
sim/Vvscale_verilator_top +max-cycles=10000 --vcdfile=tmp.vcd
Running ...
kzload (kozos boot loader) started.
kzload>
run
run
run error!
kzload>
dump
dump
size: ffffffff
no data.
kzload>
q
rm ram.data3 ram.data2 ram.data1 ram.data0
まだあまり面白くありませんが、Github を更新しました。次は XMODEM もサポートしたいと思います。
[PR]
by tom01h | 2017-01-22 00:28 | PCとか | Trackback | Comments(0)
次は FMUL を追加したいのですが、その前に乗算器を改造する必要があります。前に作った乗算器は 32bit 版で、5サイクル乗算器でした。単精度 FPU では 24bit で良いので、4サイクルで終わらせたいのです。整数と FPU で乗算器を共有すると、↓みたいになります。
f0054075_22281511.png
赤枠が FPU の範囲で、3サイクルで水色と橙色の結果が1個ずつになります。4サイクル目にこれを足して1個にします。整数の場合は4サイクル目に水色と橙色の結果に加えて、余っている3個の部分積の内の1個を足します。5サイクル目が残りの2個です。赤い塗りつぶしのS(最上位の部分積の符号反転)の行き場がないかと心配したのですが、どうやらこれは常時 0の様でした(最上位の部分積は符号なし乗算でしか使わない)。
後半は FADD で作った正規化と丸めが使えます。正規化はサブノーマルが入力された時に必要です。
また、サブノーマル出力をサポートするために、指数が負になった時は正規化の前に固定ビットの右シフトをします。とりあえず 26bit で足りるかな?その後の正規化シフトでサブノーマルの位置まで左シフトすれば良いはずです。
FMUL 全体を Veriloator 用のテストベンチと共に Github に置いておきます。

[PR]
by tom01h | 2017-01-21 17:54 | PCとか | Trackback | Comments(0)
まずは FADD を作ってみます。回路構造をあまり意識しない、Verilog 動作モデルから作ってみることにしました。Veriloator を使ってランダム(指数差に制限あり)の入力データを作って力尽くで検証します。回路構造は FMADD までの動作モデルがそろってから考えることにします。
RISC-V アーキテクチャで面倒くさいのは、サブノーマル数を扱わなくてはならないことです。入力側は特に難しいことはないし、レジスタ読み出し後に多少の時間の余裕があるので、あまり気にすることはありません。出力側はちょっと難しくて、正規化シフトを途中で止めなくてはなりません。正規化前指数を正規化シフト量が超えては駄目なんです。こんな感じでシフト量をマスクする実装が無駄が少なくて良いのかな?
wire [4:0] nrmsft; // expr >= nrmsft : subnormal output
assign nrmsft[4] = (sft[4])& (expr[7:4]!=4'h0);
assign nrmsft[3] = (sft[3])&((expr[7:3]&{3'h7, ~nrmsft[4], 1'b1})!=5'h00);
assign nrmsft[2] = (sft[2])&((expr[7:2]&{4'hf, ~nrmsft[4:3],1'b1})!=6'h00);
assign nrmsft[1] = (sft[1])&((expr[7:1]&{5'h1f,~nrmsft[4:2],1'b1})!=7'h00);
assign nrmsft[0] = (sft[0])&((expr[7:0]&{6'h3f,~nrmsft[4:1],1'b1})!=8'h00);

そして丸めですが、加算(減算)後の仮数が負になってしまった場合の処理が特殊です。正に戻してから丸め判定なんてのんびりした事はせず、反転前のデータを使って丸め判定します。
まずは LSB よりも下位が全部0の場合は、丸めとは関係なしに LSB に 1 を足します(×-1のため)。
sticky は×-1しても変わりません。
つぎに、round は sticky = 0 の時に、反転した後にまた元に戻ります。sticky = 1 の時は反転のままです。LSB も同様に考えます。
すると、反転した仮数部に 1 を足すか否かの判定は以下のようになります。
assign rnd = ((grs[1:0]==2'b00)| // inc
((grs[1]^grs[0]) &(grs[0]))| // rs=11
((grs[2]^(|grs[1:0]))&(grs[1]^grs[0]))); // gr=11

FADD 全体を Veriloator 用のテストベンチと共に Github に置いておきます。
あ、近傍丸め以外の事とか全然考えてないや。

[PR]
by tom01h | 2017-01-19 23:21 | PCとか | Trackback | Comments(0)
V-scale chip がまだまともに動いていませんが、FPU を追加したくなってきました。資源は前回作り直した mul_div モジュールと出来る限り共有したいと思っています。↓みたいな感じで出来たら良いな。最初は全くパイプライン化するつもりはなかったのですが、後述の理由から、今は FR ステージはパイプライン化するのが良いかと考えています。MUL はちゃんと書いてませんが、整数乗算と同じような感じで FM ステージをくるくる回ります。FM ステージと FA ステージは同じ資源を共有してパイプライン化しません。
f0054075_18112592.png
FR ステージをパイプライン化するのは、”FPU レジスタが CPU レジスタと独立している”ことと、”RISC-V アーキテクチャは FPU 例外を発生しない”ことが理由です。つまり、FPU は CPU からどれだけ遅れても構わないのです。
まずは、整数乗算パイプの確認。乗算器を新規設計したことで、演算自体は5サイクルになりました。ただ、演算の最後のステージ(M1)でレジスタへの書き戻しをしないので、追加でライトバックステージが必要になります。next 命令のライトバックステージと重ならないためには 5 サイクルストールを必要とします。
f0054075_18230935.png
この延長で FPU を考えると、FADD ですら 3サイクルピッチで嫌だなぁと思っていたのですが、FPU は別にレジスタを持っていることに気付きました。ついでに 32bit インクリメンタくらい独自の資源持っても良いかと思って、FR ステージもパイプライン化しようかと思ったのが↓です。FR ステージの最後でレジスタに書き戻しちゃうつもりです。バイパスを付ける余裕はなさそうですね。FR と WB は同時に実行しても資源の衝突はありません。
f0054075_18291105.png
FMUL と FMADD も載せておきます。ちなみに FPU の仮数は整数よりも短いので、4サイクルで乗算が出来ることを期待しています。
f0054075_18315346.png
あ、ストールするのは F じゃなくて EX だ。いや、正しくは DX だ。
こんな感じで出来たら良いなと思っていますが、正直どこから手を付けたものか悩んでいます。

[PR]
by tom01h | 2017-01-18 23:02 | PCとか | Trackback | Comments(0)

ディレイ対策します

ここはちゃんと vscale-xbar を直すべきですが、とりあえずスラックたたく。10ns サイクルに 8ns 以上出ているんです。こんなんでも動くのが不思議なくらいです。
ワーストは条件分岐に使うパスで、”条件判定 → 分岐先計算用の入力選択 → 分岐先計算 → 命令アドレス”のパスで、加算器が2段積みになっている。ここは分岐先計算器では Taken のアドレスを計算しておいて、外れた時用の PC+4 は別にインクリメンタを持つしかないかと。これで 5ns 強まで速くなりました。
同じように IF がストールしたときに PC を保持するパスを直す。命令キャンセル時にバイパスを無効にする必要ないので削除。ここで、4ns 強まで来ました。
あとは AHB メモリのライトバッファのヒット判定を1サイクル後倒しすれば 4ns は切りそうですが、その先は厳しいみたいです。

[PR]
by tom01h | 2017-01-15 23:27 | PCとか | Trackback | Comments(0)
だいぶ放置しちゃったけど、ついに V-scale chip on Arty でも kozos が動きました。
なんとなく AHB のアービタがダメなのは分かっていたのですが、よく見ると、そのダメなところを CPU でカバーしていました。おかげで1サイクル余分にストールするし、ディレイも増大していました。この時 に CPU を直したのが根本的に間違っているのですが、その直し方も不十分だったみたい。CPU を追加修正したら、一応動くようになりました。しかし、ISA テストのパタンでも Fail するのに、なんでちゃんと解析してなかったんだろうか?
ちなみに間違いの内容は、競合があったときに負けた方のマスタを待たせるんだけど、肝心のリクエストは消えちゃって再発行されないって感じです。
やはりここは、ちゃんと vscale-xbar を直すべきだとは思うのですが、ちゃんと動くように直せない。ディレイもどんどん増加していきます。
とりあえず現状で妥協して、vscalevscale-chip を更新しました。

プロンプトが出てきたら、load[改行]と打ってから、XMODEM でファイルを転送します。ここで ELF ファイルを転送すると、次の run コマンドでプログラムを実行できます。
kzload (kozos boot loader) started.
kzload> load
XMODEM receive succeeded.
dump[改行]と打つと、転送したファイルの HEXDUMP が表示されます。
run[改行]で、転送したファイル(ELF形式)を展開して実行します。
kzload> run
starting from entry point: 1900
Hello World!
>
サンプルプログラムは src/main/c/os/ 以下にあります。サンプルプログラムでは echo コマンドが使えます。転送するファイルは ELF をストリップした kozos です。ライブラリはすべて自作で、lib.c の物しか使えません。また、オリジナルでは 8kB 位までしか動かないそうです。vscale-chip ではアドレスマップを大幅変更しているのでよく分かりませんが、大体同じくらいの制限かと思います(^^;
なんか、いつまでたっても解放されない気持ちです。遊びなのに、遊びなのに…

[PR]
by tom01h | 2017-01-14 23:00 | PCとか | Trackback | Comments(0)
もともと Verilator で動いていたんだから簡単に復活できると思っていました。
でも、Intel-HEX を読むように変えたときに SystemVerilog の機能(sscanf)を使っていて、その部分が Verilator では使えませんでした。Verilator は SystemVerilog に対応しているはずですが、そもそも合成可能な Verilog しか対象にしていないはずなので、テストベンチ用の機能が使えなくても文句は言えません。readmemh とかが使えていたので、変な期待をしちゃっていました。
仕方がないので、C++ のテストベンチから無理やりメモリに書き込みます。メモリの実体を RTL から変換したファイル sim/Vvscale_verilator_top.h の中から探します。↓かな?
VL_SIG(v__DOT__DUT__DOT__hasti_mem__DOT__mem[65536],31,0);
階層は全部崩されちゃうんですかね?C++ のテストベンチからは↓のようにして書き込むことが出来ました。
verilator_top->v__DOT__DUT__DOT__hasti_mem__DOT__mem[addr] = op;
実際はエンディアン変換していてぐちゃぐちゃしてるけど。
そんなわけで無事復活したので、ここ を更新しました。Verilator ってむちゃくちゃ速くて感動しますね。でも、gtkwave が使い慣れていないのであんまり使わないと思うけど。
[追記 Verilator の新しいバージョンでは最上位階層のインスタンス名が変わっていたので対応しました。]

[PR]
by tom01h | 2017-01-12 22:00 | PCとか | Trackback | Comments(0)

CORDIC も作ってみた

ついでに CORDIC も作ってみました。でもV-scale には FPU が付いていないので、仮に追加するとしてもかなり先のことになると思います。
CORDIC で sin, cos, atan2 を計算します。CORDIC のアルゴリズムに興味があれば、適当にググってください。RTL の実装ですが、CORDIC の部分自体は簡単でした。ただ、前処理、後処理がたくさん必要になりそうです。
sin, cos の CORDIC への入力は 0~PI/2 です。それ以外の場合は前後に処理が必要です。まあ前処理でも、-PI~PI ぐらいしか対応しないでしょうね。それ以外は Invalid にするのが妥当かと思います。
atan2 の CORDIC への入力は x>=0, y>=0 で、アラインして入力する必要があります。後処理は以下。なぜ +PI なのかは理解していない。
if(x<0){r=-r+M_PI;}
if(y<0){r=-r;}
前処理、後処理と、入力データ生成部分、期待値生成と比較を c で書いています。atan の苦労は9割がたはテストベンチ側にありました。でも、こんな設計には Verilator がとっても役に立ちますね。結果は ここ に追加して置いておきます。mul_div とはまだ混ぜません。
ちなみに ここの Mixing C and assembler なんかを見ると、コンパイラに命令追加できなくても C 言語から追加命令が呼べそうな気がします。

[PR]
by tom01h | 2017-01-10 23:07 | PCとか | Trackback | Comments(0)