カテゴリ:PCとか( 107 )

まずは 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)
新しい乗算・除算器を組み込んで、V-scale chip で FPGA の合成をしてみました。左が修正前、右が修正後です。500LUT 増加ってどのくらいなんだろう?割合でみると結構大きいですね。分母はコアじゃなくてチップですからねぇ。
f0054075_22380150.pngf0054075_22380145.png

そして、ワーストスラックは若干ながら改善していました。確かに mul_div が始点だったんですが、FF出しに見えたんだけどなぁ。
CoreMark も再測定しました。ちなみに 4サイクル乗算器はインチキ RTL 記述です。
  • オリジナル IPC=0.45 1.48CMK/MHz
  • 4サイクル乗算器 IPC=0.77 2.54CMK/MHz
  • 新演算器 IPC=0.73 2.43CMK/MHz
除算の高速化の影響よりも、乗算+1の影響のほうが大きいみたいですね。あとは除算用のプレシフトかな?ノーマライザ入れておけば、FPU積み込む事があったら使えそうだし。
よく見ると+1サイクルストールしています。まぁでも、これは必要なストールかな。
[追記 モジュール別のサイズを見つけました。synth後、imple前の物ですけど。ば、倍増か…]
[追記2 それ以前にラッチ推定があったので直しました(^^;]
変更後
+------+----------------+-----------------+------+
| |Instance |Module |Cells |
+------+----------------+-----------------+------+
|1 |top | | 5044|
|17 | vscale |vscale_core | 4485|
|18 | pipeline |vscale_pipeline | 4482|
|19 | csr |vscale_csr_file | 1567|
|20 | ctrl |vscale_ctrl | 1045|
|21 | imm_gen |vscale_imm_gen | 1|
|22 | md |vscale_mul_div | 1430|
|23 | regfile |vscale_regfile | 60|
|24 | src_a_mux |vscale_src_a_mux | 32|
|25 | src_b_mux |vscale_src_b_mux | 37|
変更前
+------+----------------+-----------------+------+
| |Instance |Module |Cells |
+------+----------------+-----------------+------+

|1 |top | | 4475|
|17 | vscale |vscale_core | 3916|
|18 | pipeline |vscale_pipeline | 3913|
|19 | csr |vscale_csr_file | 1562|
|20 | ctrl |vscale_ctrl | 1135|
|21 | imm_gen |vscale_imm_gen | 1|
|22 | md |vscale_mul_div | 777|
|23 | regfile |vscale_regfile | 60|
|24 | src_a_mux |vscale_src_a_mux | 32|
|25 | src_b_mux |vscale_src_b_mux | 37|


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

乗算・除算器

遅くなりましたが、あけましておめでとうございます。
V-scale chip の FPGA ボードが動かないまま、バグの見当が付いているのに放置したままですが、題の通り別のことに興味が行っています。そういえば、除算のバグらしきものも発見したのだったけど、やっぱり放置しています[こっちはついでに直しました。]。
そもそもは CORDIC で sin/cos/arctan を求めようって話だったのですが、
CORDIC には加算器3個要るらしい→2bit/サイクル除算器と回路共用できるね→そういえば V-scale の乗算すごく遅かったな
って思考をたどって、V-scale 用にちょっと高速な乗算・除算器を作ってみようと思っています。
こんな感じでちょっとだけ贅沢に資源を積み込みます。
f0054075_17390349.png
乗算器の色の区別はこんな感じです。
f0054075_21062708.png
[完成したのでちょっと変更
Verilog にしてみると こんな感じ です。verilator で検証環境を作ってみました。
Divide by Zero のバグも併せて直して、vscale を更新しました。]

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

V-scale 開発環境の構築

V-scale を動かすのに最低限必要なもの。
V-scale 本体は、本家 UCB のが ここ にあって、僕が fork していじくっているのが ここ にあります。本家の物は最新バージョンの開発環境や tests では動きません。
開発環境は GNU Compiler Toolchain です。まあ、とにかくでかい。前回は普通に(RV64Gで?)コンパイルしたのですが、今回は RV32IM で作ります。RV64G で作っても gcc -m32 で elf32-littleriscv ができていたみたいですけどね。make してみると riscv32-unknown-elf-* になりました。まあ良いか。だめだ。tests が作れない。やっぱり RV64G で作っておく。
そして、以下のようなエラーが出ます。
./configure --prefix=/opt/riscv --with-arch=rv32im --with-abi=ilp32
sudo make
fatal error: zlib.h: そのようなファイルやディレクトリはありません
やりなおし
sudo apt-get install zlib1g-dev
sudo make
なんで続きやらずに1からやり直すんだろう…
つぎに ISA のテストに使う riscv-tests をとってきます。使うのは rv32mi, rv32ui, rv32um 辺りかな。アセンブラの引数チェックが厳しくなったのか、以下のファイルに修正が必要になりました。ってか、除算系は今まで意味のあるチェックが出来ていなかったっぽい。[追記 ゼロ除算の特殊処理が出来ていなくて商を間違うのですが、tests のバグで見つかっていませんでした。mul-div を高速版に差し替えるとともに修正しました。]
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
本家 V-scale のリポジトリには、いつの頃のか分からないけど、論理と対応した tests も入っています。マシンモードがすごく弱いけど、昔はこうだったのかな?僕のリポジトリにも比較的新しめのを入れてあります。どちらも、変換済みの物だけですけどね。[追記 僕のリポジトリには、インストール済みの tests から ihex を生成するための Makefile (かなり格好悪い記述だけど)を追加しておきました。]
ここから先はお好みで。
命令セットエミュレータはたくさん有るけど、一番最初に目に留まった spike を。それぞれが何なのかよくわかりませんが、次の3点セットです。 Frontend ServerISA Simulatorpk
ほかにも 新しいエミュレータ が出ているみたいなので、今度試してみたいと思っています。
さらに、いろいろとお手本になると思われるので、V-scale とは直接関係ないけど Rocket Chip Generator もあると良いと思います。でも、現状の WSL では Java に問題があるらしくって、chisel を動かすことができないみたいです。

[PR]
by tom01h | 2016-12-29 16:32 | PCとか | Trackback | Comments(0)

kozos on V-scale chip on ARTY

ARTY という FPGA ボード上に V-scale chip を実装して kozos という小さな OS を動かしたいっていうお話です。
ARTY は DIGILENT 社の FPGA ボードで、Xilinx 社の Artix 7 という FPGA が載っています。ここ とか ここ で1.6万円くらいで売っています。この FPGA 上に V-scale chip を載せます。ボード上には FPGA 以外にもいろいろな機能が載っているのですが、もったいないことに USB-UART くらいしか使っていません。この USB-UART チップを通して、V-scale chip の UART とパソコンの間で通信をします。↓こんなのです。
f0054075_20595195.jpg
V-scale chip は、先日紹介した V-scale という RISC-V アーキテクチャのマイコンを搭載します。マイコン以外は命令用とデータ用にシングルポート SRAM を2個と UART を搭載します。SRAM は各 16KB で、V-scale の I-Bus, D-Bus どちらからでもアクセスできます。ただし、競合によるバスストールを避けるためには命令とデータは明確に分離すべきでしょう。UART は TX,RX 用にそれぞれ4バイトの FIFO を持ちます。バスマスタ機能や割り込み発生機能は持ちません。ブロック図は下のような感じです。
f0054075_17094555.png

kozos は 組み込みOS自作入門 という本の中で作り上げていく、とても小さな OS です。もともとは H8 マイコンボード用なのですが、これを V-scale chip 向けに移植しています。OS(というかブートローダ)には次の機能があります
  1. UART を通してパソコンと通信する
  2. プロンプトを表示して、入力されたコマンドを解釈する
  3. XMODEM プロトコルで、ファイルを転送する
  4. 転送された ELF ファイルを展開して、マイコン上で実行する
本来はもっといろいろな機能があるのですが、現状はステップ6までで実現される、上の機能で満足しています。
ちゃんとは動かないけど、V-scale 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 | 2016-12-22 00:00 | PCとか | Trackback | Comments(0)