Upload
ito-takahiro
View
1.779
Download
3
Embed Size (px)
DESCRIPTION
http://open-archo.org
Citation preview
Open Design Computer Project FPGAでコンピュータを作ってみた
伊藤 剛浩 川田 裕貴
http://open-arch.org/
伊藤 剛浩 @cpu_labs
筑波大学 情報学群 情報科学類
システム情報工学研究科 産学間連携推進室
Open Design Computer Project : ハードウェア担当
2011年度IPA認定スーパークリエータ
Verilog HDL SVA 回路設計 基板アートワーク等
川田 裕貴 @hktechno
筑波大学 情報学群 情報科学類
システム情報工学研究科 産学間連携推進室
Open Design Computer Project : ソフトウェア担当
2011年度IPA認定スーパークリエータ
gcc, Binutils の MIST32 向け移植
Open Design Computer Project
http://open-arch.org/
Open Design Computer
• Open Processor Architecture
– MIST32
• Open Source Processor
– MIST1032ISA
– MIST1032SA
• Open Development Environment
– Binutils
– gcc
Agenda
FPGAと回路設計
Out of Orderコアの実装
開発環境について
FPGAとは
• Field Programmable Gate Array
• つまり書き換えることができるハードウェア
• 最近安くなってきた
• もはや一家に一台レベル
–買いましょう
– http://www.terasic.com.tw/
全ては並列動作のために
• 回路は並列動作させなきゃ意味が無い!
–逐次だけやりたいんだったらプロセッサを使え
–スループットを常に念頭に
• プログラミングではない!!!
–全て並列動作
–結構大変
–プログラミングより地味
–配線、配線、敗戦…
HDL : Verilog HDL
module addr( input [31:0] a, input [31:0] b, iniput ci, output [31:0] x, output co); assign {co, x} = a + b + ci; endmodule
Synthesize / Place&Rout
• Synthesize : 論理合成
– HDLから回路図レベルまで落とす
–要らないロジックを消す
–早くするためにロジックを追加
• Place&Rout : 配置配線
– FPGA上のどこに配置するか
–位置によってfmaxが変わる
気をつけること
• 非同期回路はできるだけ作らない –非同期回路は難易度up
– Synopsys Design Constraints(.sdc)でクロックドメインの定義
• スループットを稼ごう – FPGAのIOは遅い
–レイテンシではなくスループットを重視する
• マクロブロックを積極的に利用 – Memory, FIFO系は使ったほうが良い
FPGAに関するまとめ
• HDLレベルでの記述でok
–回路図レベルとか大規模開発出来ません
• 回路で作るなら並列に動かすことを心がける
–プログラミング的感覚は論外!
• IOは遅い
–スループットをどれだけ稼ぐかがキーポイント!
• あまり難しいことを考えない
– FPGAなんだから何度も書き換えできるし
Agenda
FPGAと回路設計
Out of Orderコアの実装とデバッグ
開発環境について
Out of Order Execution
• 実行ハードウェアを複数持つことが前提
• メモリからはプログラム順に入る(In Order)
• 実行の順序は動的に変化(Out Of Order)
– WAW/WARを排除
–必要なデータさえ揃えば実行
• 実行の完了Commit処理にて(In Order)
–割り込み対応のため
Atom : Bonnellのパイプライン
• In Order Core
• Decode
• Queue
• Dispatch
• Execute
• Writeback
Atom : Silvermontのパイプライン
• Out of Order Core
• Decode
• Queue
• Scheduler(RN/ROB/RS)
• Execute
• Writeback(CDB)
Out Of Order実行
• 今回はTomasuloのアルゴリズム
– Rename / Reservation Station / Re Order Buffer
– Frontend / Backendで回路を分離 -> 結構重要!
Register Renaming
• レジスタファイルの拡張
• ARF(LRF) : Architecture Register File – Architectureで定義されているレジスタセット
• PRF : Physical Register File – 物理的にプロセッサが持つレジスタファイル
• Renaming Table – ARFとPRFの対応付け
Register Renaming実装
ARF Id PRF Id
R0 p-R12
R1 p-R3
Rn p-Rn
Instruction
Source
Next Stage
Source Destination Destination
• Source Operand
– Renaming Tableを元にARF-PRF変換
• Destination Operand
– Renaming TableのARFに対する新たなPRFの割り当て
Frontend -> Reservation Station
• Out of Order実行されたデータを新しく入ってきた命令に適用
–命令はデータを必要としていない
• そのままRSに格納
–命令はデータを必要としている
• CDBから必要とするデータが流れてきた
• PRFに必要なデータが格納されている
Reservation Station -> Ex
Rs ID 演算タイプ Source1 Valid
Source2 Valid
Source1 Source2
0 2項演算 1 0 10 Invalid-r0
1 単項演算 1 1 5 5
n 2項演算 0 0 Invalid-r0 Invalid-r2
[実行不可] : Register0を待ち受けている [実行可能] : 全てのデータは揃っている [実行不可] : Register0, 1を待ち受けている
• 命令の実行に必要なデータが揃うまで待つ
–常にExecuteのCDBを監視
• 必要データが揃ったら実行ステージへ送る
Reservation Station : 実装
Rs ID Source1 Valid
Source2 Valid
Source1 Source2
0 1 0 10 Invalid-r0
1 1 1 5 10
n 0 0 Invalid-r0 Invalid-r2
Priority Encoder
Register File
Data
p-R0 20
p-R1 0
p-Rn 10
CDB
From Backend
Re Order Buffer
• つじつま合わせ
– Robがないと割り込み対応が面倒
• 命令が読まれた順を保持(R-Pointer)
• 実行し終わった命令にフラグ付け(実行完了フラグ)
• 以下すべての命令が実行し終わったところを指すポインタ(C-Pointer)
Re Order Bufferの実装
OoOの問題点
• とにかくデカイ
–連想メモリの塊
–ブロードキャストとかしてる
– FPGAになんか入れられなry
• 超えられない壁
– ILP / Power / Memory Wall
MIST32でのアプローチ : CDB/Rs/Rob/Rn
• CDBの幅を32bitに固定 基本Flagも流さない
–多倍長演算は以下により実現
命令レベル並列化のまとめ
• 命令を実行するにはデータが揃えば良い
• ハザードを回避するために実行順序を変える
• つじつま合わせに苦労する
• 連想メモリがー
• FPGAへの実装には向かない!!!
Agenda
FPGAと回路設計
Out of Orderコアの実装とデバッグ
開発環境について
MIST32の開発環境
とりあえずCで何か開発できる環境
• gcc(コンパイラ)
– C++はまだコンパイルできません
– newlibの移植が完全に終わってない
–標準ライブラリなし
• binutils(as, objdump)
–超重要
– Llvmは暇な時にやりたい
gccとbinutilsの移植
• 少しだけ移植方法を書き溜めてます
– まだまだ足りないので、暇な時に絶賛追記中
– http://open-arch.org/software/assembler
– http://open-arch.org/software/compiler
• binutils
– cgenを使うと楽
• gcc
– RTLからアセンブラへのパターンを書く(.md)
– Prologue, epilogueは既存アーキをとにかく参考にする
(define_expand "movqi" [(set (match_operand:QI 0 "nonimmediate_operand" "") (match_operand:QI 1 "general_operand" ""))] "" " { if (MEM_P (operands[0])) operands[1] = force_reg (QImode, operands[1]); }")
(define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") (plus:SI (match_operand:SI 1 "register_operand" "%0,0") (match_operand:SI 2 "nonmemory_operand" "r,I")))] "" "@ add¥t%0, %2 add¥t%0, %2" )
バグ戦争…
ソフトウェアの問題なのか…
ハードウェアの問題なのか…
どっちかわからないwww ウェーイ(☝ ՞ਊ ՞)☝
という問題が起きるわけです
デバッグ環境
• printfデバッグ – I/Oの初期化が完了し、そこまで動けば
• ソフトウェアシミュレーター – オレオレシミュレータ – ハードウェア要因のデバッグは不可能(比較は可能)
• RTLシミュレーション – とっても時間が書かる
• 勘と目grep – 非常に重要。あきらめない。 – 最後の砦
00000470 <genrand_int31>: 470: 11 00 03 c0 push rbase 474: 11 00 03 e0 push rret 478: 18 00 03 c0 srspr rbase 47c: 0e e0 03 a0 lih rtmp,0x0 480: 0d 40 47 a0 wl16 rtmp,0x220 484: 20 70 03 e2 movepc rret,8 488: 14 40 03 a0 b rtmp,#al 48c: 08 30 00 01 shr r0,0x1 490: 12 00 03 e0 pop rret 494: 12 00 03 c0 pop rbase 498: 14 40 03 e0 b rret,#al
00000470 <genrand_int31>: 470: 11 00 03 c0 push rbase 474: 11 00 03 e0 push rret 478: 18 00 03 c0 srspr rbase 47c: 0e e0 03 a0 lih rtmp,0x0 480: 0d 40 47 a0 wl16 rtmp,0x220 484: 20 70 03 e2 movepc rret,8 488: 14 40 03 a0 b rtmp,#al 48c: 08 30 00 01 shr r0,0x1 490: 12 00 03 e0 pop rret 494: 12 00 03 c0 pop rbase 498: 14 40 03 e0 b rret,#al
00000470 <genrand_int31>: 470: 11 00 03 c0 push rbase 474: 11 00 03 e0 push rret 478: 18 00 03 c0 srspr rbase 47c: 0e e0 03 a0 lih rtmp,0x0 480: 0d 40 47 a0 wl16 rtmp,0x220 484: 20 70 03 e2 movepc rret,8 488: 14 40 03 a0 b rtmp,#al 48c: 08 30 00 01 shr r0,0x1 490: 12 00 03 e0 pop rret 494: 12 00 03 c0 pop rbase 498: 14 40 03 e0 b rret,#al
ソフトウェアシミュレータ
ELFを読み込んで、配置して、実行 エミュレータといったほうが正しいかも https://github.com/techno/mist32-simulator
• 対応してるI/Oデバイス
– タイマ – シリアル – VGAディスプレイ – PS/2キーボード – SDカード(MMC)
シミュレータの中
• 命令はソフトウェアシミュレーション – X86の命令に変換しているわけではない – 完全に変換するのは余計に大変 – 速度を求めていない…
• 内部的な仮想メモリ – ページ単位に区切ってアクセスがあったら割り当てる
• Memory Mapped I/O – I/O領域にLoad/Storeが掛かったら専用命令にフックする
– MIST32はあるアドレス以上はすべてI/Oなので、振り分けがかなり楽
命令のエミュレーション
• めんどくさいこと
• フラグ – Carryフラグはどうやって生成するの
– Carry = msb((dest & scr) | (~result & (dest | src)))
– Overflow = msb(~(dest ^ src) & (dest ^ result))
• エンディアン – MIST32はビッグエンディアン
– バイトアクセスはエンディアン変換しただけではうまくいかない
エンディアン変換の落とし穴
• Big Endian: 00 11 22 33
• Little Endian: 33 22 11 00
• 00 11 22 33
• ^^ == 0
• 33 22 11 00
• ^^ == ??
I/Oのエミュレーション
• ディスプレイ – ノートPCでエミュレーションさせたくない – 描画と処理を同時にやると思い – ネットワーク経由で表示クライアントを接続可能 – msgpackとかおしゃれなものを使ってる – クライアントはGTK+(cairo)で描画
• シリアル(UART) – MkfifoしたFIFOに吐かせる – catすれば通信が見える – とりあえずok
セキュリティ
• あんまり考えてなかったり… • PC, SPがちょっと辺
– 専用命令でしか操作できない
• Return pointerがレジスタ • MMUでNX bitなどはサポート • カーネル専用のページテーブルを持つ
– 有効活用できるかどうか怪しい
何かいいアイデアがあれば Pull requestお待ちしています