<   2017年 01月 ( 16 )   > この月の画像一覧

FMADD の動作モデルも作ってみます。アラインは乗算結果の時は幅を広げて、加数の時はシフト量を増やします。ノーマライズは幅を広げる必要はないですが、シフト量は増やします。ここまで出来ると、大雑把に必要な資源の見積もりができます。まぁ、最初に予想していたのとそれほど違いなく出来そうです。また、残りの命令はチョイ変で済みそうなので、これで回路を意識した記述に手を付けられます。
testfloat だと、mulAdd の検証はかなりたくさんのパタンを必要とするようで、-level 2 を指定するといつ終わるんだろう?って感じです。Verilator は結構速いみたいで testfloat で入力データと期待値生成しながら走らせているのですが、CPU 使用率の比較はこんな感じになっています。
f0054075_13082097.png

[PR]
by tom01h | 2017-01-30 00:19 | PCとか | Trackback | Comments(0)
FPU の Verilog モデルを作成中ですが、自作ランダム検証ではなく、Berkeley TestFloat を使った検証を試してみます。これを使うと丸めモードを変更したり、フラグの期待値生成も簡単に出来るし、Intel CPU だと問題のある FMADD の期待値生成のことも考えずに済みます。
testfloat_gen を使って入力と期待値が生成できるようなので、そのフォーマットに合わせてテストベンチを作り直しました。入力データが特殊な時の処理とか、フラグ生成とかいろいろ追加が必要でしたが、これで品質が大きく向上するはずです。実際、FADD でバグ見つかりましたし…
こんな感じで流せます。結構時間かかります。
~/RISC-V/FunctionalUnit$ ../testfloat/berkeley-testfloat-3/build/Linux-x86_64-GCC/testfloat_gen -level 2 -f32_add | ./sim/Vfadd > log
~/RISC-V/FunctionalUnit$ ../testfloat/berkeley-testfloat-3/build/Linux-x86_64-GCC/testfloat_gen -level 2 -f32_mul | ./sim/Vfmul > log
仕様書をちゃんと確認してみると、tininess 検出は丸め後だったみたいです。で、試してみたんだけど、これって softfloat のほうが間違っているよね?結果が最小値なのにアンダーフローしてるし。サブノーマルの仮数が長すぎるまま判定しようと思って間違っているのだと思いますtininess の検出は結果を見て判断することにして、検証を続けようと思います。 [追記 僕の理解が間違っていたみたいなので、SoftFloat を元に戻してモデル記述を修正しました。]
~/RISC-V/testfloat/berkeley-testfloat-3/build/Linux-x86_64-GCC$ ./testfloat_gen -f32_mul|grep "[80]0800000 03$"
00800000 3F7FFFFF 00800000 03
00800000 BF7FFFFF 80800000 03
00FFFFFF 3F000000 00800000 03
00FFFFFF BF000000 80800000 03
3F000000 00FFFFFF 00800000 03
3F000000 80FFFFFF 80800000 03
3F7FFFFF 00800000 00800000 03
3F7FFFFF 80800000 80800000 03
80800000 3F7FFFFF 80800000 03
80800000 BF7FFFFF 00800000 03
80FFFFFF 3F000000 80800000 03
80FFFFFF BF000000 00800000 03
BF000000 00FFFFFF 80800000 03
BF000000 80FFFFFF 00800000 03
BF7FFFFF 00800000 80800000 03
BF7FFFFF 80800000 00800000 03

[PR]
by tom01h | 2017-01-29 00:07 | PCとか | Trackback | Comments(0)
演算器のモデルを作成中ですが、パイプラインへ追加する方法の調査を兼ねて、転送命令を追加してみようと思います。命令では FLW, FSW, FMV, FSGNJ の 4命令で、 tests で言うと次の3個です。
  • rv32uf-p-ldst
  • rv32uf-p-move
  • rv32uf-p-sgnj
はじめは FSGNJ(サインインジェクション)は後で良いと思ったけど、普通のレジスタ間転送はこの命令を使う模様です。で、普通のレジスタ間の転送命令が目に付かなかったせいで FPU にバイパスは不要と思っていたのですが、やっぱり必要だと思い知らされました。そりゃまぁそうですよね。でもとりあえず、バイパスは保留にしておきます。
まず、F Register と fcsr を追加、MISAを変更します。整数側のロードストアを見よう見まねで FLW,FSW を作ります。ここで rv32mi-p-csr が落ちました。mstatus.FS が Off(00) の時の FPU命令は不当命令になるらしいです。数日前に命令ログの出し方を覚えた spike が早くも役に立ちました。
FMV(整数レジスタとの転送)も似たような実装で動くのですが、rv32uf-p-move は FSGNJ も動かないと通らないみたいです。そんなわけで数行前の考えに至った次第です。
して、rv32uf-p-sgnj もついでに通しておこうと思ったのですが、今度はあまりちゃんと定義の無い fsflags なんて命令が出てきました。これって、CSR のアドレス 0 の fcsr.flag のエリアスに対する csrs 命令ってことで良いのかな?
mstatus.FS とか fpsr の更新の事はまだ考えていないですが、ここまでやって 3個の tests が通りました。と言っても、FS 更新していないから本当はダメなんですけどね。

[PR]
by tom01h | 2017-01-28 00:27 | PCとか | Trackback | Comments(0)
前回はいろいろ中途半端になったので、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 辺りかな。
アセンブラの引数チェックが厳しくなったのか、以下のファイルに修正が必要になりました。ってか、除算系は今まで意味のあるチェックが出来ていなかったっぽいです。

■ 命令セットシミュレータ
これは本当にいろいろなものがあるらしいですが、一番露出の多い本家の 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)