入出力 (IO)

Download Report

Transcript 入出力 (IO)

コンピュータ基礎
入出力
天野 [email protected]
I/O:入出力デバイス
一時的に
データを保存するレジスタ、
制御用のレジスタを持つ
CPU
I/O
②外部との
データ転送
制御方法
①どのように
接続するか?
命令
メモリ
データ
メモリ
I/O:
CPUと外界のやりとりを制御
一時的にデータを蓄えるバッファ
を持つハードウェアモジュール
メモリマップトI/O
0000
CPU
メモリ領域
I/O
8000
命令
メモリ
データ
メモリ
I/O領域
データメモリと同じアドレス空間に
I/Oのレジスタを割り付け、同じバス
上で接続する
FFFF
プログラムドI/O
(Isolate I/O、Separate I/O)
0000
CPU
命令
メモリ
データ
メモリ
I/O
I/O領域
独立したバスを持つ
I/O命令を持つ
IN 0
OUT 1
など、、
メモリ領域
=独立した番号空間を
持つ
FFFF
メモリマップトI/O vs.プログラムドI/O
• メモリマップドI/O
–
–
–
–
I/Oとメモリを同一の命令、アドレス空間で扱える
命令の種類が減る
ハードウェアが減る
どのような構造のCPUでも使える
• プログラムドI/O
– メモリアドレス空間中にI/Oの虫食いができない
– I/O中にメモリアクセスが可能
• Intel 86系はプログラムドI/Oでも実際にはメモリマッ
プトI/Oで動いている
I/Oデバイス
コントロールレジスタ
CPUのバス
メモリに書くように
書き込む
ステータスレジスタ
外界
データレジスタ
メモリから読むのと
同じように読み出す
データレジスタ: データの一時的な保存場所
コントロールレジスタ: I/Oに対する指示を覚えておく場所
ステータスレジスタ:I/Oの状態を覚えておく場所
データレジスタは双方向を同じ番地に割りあえてる場合もある
コントロールレジスタとステータスレジスタは同じ番地を割り当てる場合もある
例:UART 8251
• パラレル/シリアル変換を行うI/O
• モデム・端末インタフェースRS232C用
– 5bit-8bit単位でシリアル転送を行う
– ボーレートはさほど高くない(最大でも10Mbps)
• 現在でもIPとしてFPGA内で良く利用される
シリアル転送フォーマット
Start bit
D0
D1
DN
P
Stop
bit
Start bit: 0にして開始を示す
D0-DN: データ、5ビットから8ビットまで選択可能
P:パリティビット 偶数/奇数の選択可能
Stop bit: 1にして終了を示す。長さを選択可能
コントロールレジスタと
ステータスレジスタ
コントロールレジスタ
EP PEN L2 L1 0
EP: Even Parity 1: Even 0: Odd
PEN: Parity Enable 1: Enable
ステータスレジスタ
L2
0
0
1
1
L1
0
1
0
1
0
5bit
6bit
7bit
8bit
Rx Tx
RDYRDY
TxRDY: 送信終了、送信バッファ(ダブルバッファ)に書き込み可能
RxRDY:受信終了、受信バッファから読み出し可能
ハンドシェイク(送信)
I/O
TxRDY フラグ
0
1
TxRDY=1ならば
バッファ利用可能
書き込み
ハンドシェイク(送信)
I/O
TxRDY フラグ
0
1
TxRDY=0の時には
次のデータを書き込む
ことができない
TxRDY=0ならば
バッファ中にデータが存在
出力
ハンドシェイク(送信)
I/O
TxRDY フラグ
0
1
再び
TxRDY=1ならば
バッファ利用可能
書き込み
以降繰り返し
ハンドシェイク(受信)
RxRDY フラグ
I/O
1
ステータスレジスタの
RxRDY=1ならば
バッファから読み出し
可能
1の時は次のデータの
書き込みができない
フラグを使ってハザードを防ぐ
• RAWハザード:Read After Writeハザード
– 値が書き込まれるのを待って読み込む
– 二重読みを防ぐ
• WARハザード:Write After Readハザード
– 値を読む前に書きこまれることがないようにする
– 書き潰しを防ぐ
• WAWハザード:Write After Writeハザード
– これも書き潰しだが、WARがなければ普通大丈
夫
演習のI/Oインタフェース
• ディスプレイを想定
– ASCIIコードを書き込むと出力される
– ASCIIコード:英数字、記号用の8ビットコード
• man asciiで表示されるのでLinux端末でやってみて!
• 0x8000:
– 書くとデータレジスタ
– 読むとステータスレジスタ
• 最下位ビットがTxRDY, 送信完了すると1になる
例題プログラム
LDHI
r0,#0x80
LOOP: LD r1,(r0)
BEZ r1,LOOP
LDI r1,#0x41
ST r1,(r0) →
TxRDYが1になるまで
ループ
→ ポーリング
Busy Wait
これでASCIIコード0x41:Aが出力される
演習1
データメモリの0番地から並んでいる5個のデー
タをディスプレイから表示せよ。
さて、ここまでのI/O
• 16ビットのデータのうちのほんの一部しか
使ってない
– ステータスは1ビット
– データでも8ビット
→ バイトアドレッシングの導入
• ビジーウェイトって、CPUは回ってばかりで馬
鹿みたい
→ 割り込みの導入
バイトアドレッシング
16ビット幅の場合
8ビット単位でアドレスを振る→今のCPUでは最も一般的な方法
LSB
MSB
0
2
4
6
8
A
C
E
1
3
5
7
9
B
D
F
Big Endian
End
POCOは
こっち
MSB
LSB
1
3
5
7
9
B
D
F
0
2
4
6
8
A
C
E
End
Little Endian
•統一されていない
•データの順番が変わって大変なことになることも、、、
•最近は電源投入時にどちらかをセットする方法が一般化
バイトアドレッシング
32ビット幅の場合
MSB
0
4
8
C
MSB
LSB
1
5
9
D
2
6
A
E
Big Endian
3
7
B
F
3
7
B
F
End
64ビットデータでも同様
LSB
2
6
A
E
Little Endian
1
5
9
D
0
4
8
C
End
LB
Load Byte
00000 ddd sss 01100
LDと同様R型
LSB
MSB
0
2
4
6
8
A
C
E
1
3
5
7
9
B
D
F
0
レジスタr0-r7
1
•符号拡張
End
8bitを16ビットに拡張する
→CPU内では標準サイズで扱うのが
RISCの原則
LBU
Load Byte Unsigned
00000 ddd sss 01101
LSB
MSB
0
2
4
6
8
A
C
E
1
3
5
7
9
B
D
F
0
レジスタr0-r7
1
•Zero拡張
End
8bitを16ビットに拡張する
→CPU内では標準サイズで扱うのが
RISCの原則
SB
Store Byte
00000 ddd sss 01011
LSB
MSB
0
2
4
6
8
A
C
E
1
3
5
7
9
B
D
F
レジスタr0-r7
End
16ビットレジスタの下位8ビットを切って
メモリに格納
→ 上位8ビットは無視
プログラマの責任!
SBUは存在しない
ミスアラインメント
LSB
MSB
0
2
4
6
8
1
3
5
7
9
LD r0,(r1)
0
r1=0
1
レジスタr0-r7
偶数番地は問題ない
LSB
MSB
0
2
4
6
8
1
3
5
7
9
LD r0,(r1) r1=1
1
2
レジスタr0-r7
奇数番地だと2回アクセスしてくっつける必要がある
→ミスアラインメント
ミスアラインメントを許すか?
• 許す利点:
– メモリ利用効率が向上する
– レガシーコードがコンパイルしなおさずに動く
• 許す欠点:
– 動作速度が遅くなる
• メモリを2回アクセスしなければならない
– ハードウェアが複雑になる
• バイトをシフトしてくっつける必要がある
• シフト操作自体はLBの時点で必要だが、、、
• 一般に命令では許さない。データではケースバイ
ケース
• POCOでは命令、データ共に許さないことにする
割り込み(Interrupt)
• I/O側からCPUに対して割り込みを要求
• CPUはこれを受け付けると自動的にPCを割
り込み処理ルーチンの先頭に変更
• 戻り番地はどこかに保存
• 割り込み処理ルーチンを実行、終了後リター
ン命令で元のルーチンに戻る
→ 元のルーチンは割り込みが起きたことがな
かったかのように実行しなければならない
割り込みの実行
メインルーチン
EI (Enable Interrupt)
割り込み処理ルーチン
割り込み
要求信号
RTI (Return from Interrupt)
サブルーチンコールとの違いは、どこで呼ばれるか
分からない点にある
割り込み関係の命令
• EINT Enable Interrupt
00000 XXXXXX 01110
Xはdon’t care
割り込みを許可する
• RTI Return from Interrupt
00000 XXXXXX 01111
PC ← IARにし、割り込みを許可する
割り込みの実現方法
• 割り込み処理のとび先番地
– 固定番地
POCOではff00とした
• 割り込み処理ルーチンの先頭でどのI/Oが要求を出し
たか調べる必要がある
– テーブル引き
• I/O毎に飛び先を変えることができる
• 戻り番地の格納手法
– 特殊なレジスタ POCOではIAR(Interrupt
Address Register)
– ハードウェアスタック
割り込みの実装
VDD
割り込み要求線
オープンドレイン
どれかがLならばL
intreq
CPU
I/O
I/O
I/O
オープンドレインの割り込み線を使って割り込み要求を
発生する。
割り込み処理ルーチンに飛ぶときに割り込みを禁止
→ 割り込みが掛かり続けることを防止
CPUによる入力
CPU
LB
I/O
SB
メモリ
LBで一度レジスタにとってきて
SBでメモリにしまう
CPUによる出力
CPU
SB
I/O
LB
メモリ
LBで一度レジスタにとってきて
SBでI/Oのデータレジスタへ出力
Direct Memory Access(DMA)
CPU
DMA要求
許可、
バスを開放
I/O
I/Oがアドレスを指定し、
直接メモリとデータをやりとり
メモリ
終了後はバスを開放し、
CPUに割り込みを掛ける
CPUはDMAが掛かったことを
知らない
演習2
MSB
0x0
0x80
0x2
0x34
0x4
0x78
0x6
0xbc
LSB
0x12
0x56
0x9a
0xde
Big Endianのバイトアドレッシングを仮定する
以下のプログラムを実行した時のレジスタr1の値の変化を示せ
LDI r0,#0
LB r1,(r0)
LBU r1,(r0)
LD r1,(r0)
ADDI r0,#5
LB r1,(r0)
LBU r1,(r0)