ZynqMPのブートとパワーマネージメント : (ZynqMP Boot and Power Management)Mr. Vengineer
?
2016年2月20日(金)のZynq Ultrasclae+ MPSoC 勉強会で使った資料です。
追記) 2016.05.08
公式ARM Trusted Firmwareのサイトに、Zynq UltraScale+ MPSoCの実装が追加されていていることを明記した
This is the material I used at Zynq Ultrasclae + MPSoC SIG on 20th February (Friday).
Addendum) 2016.05.08
We stated that the implementation of Zynq UltraScale + MPSoC was added to the official ARM Trusted Firmware site.
IMAX3: Amazing Dataflow-Centric CGRA and its Applications
I present this slide to all hungry engineers who are tired of CPU, GPU, FPGA, tensor core, AI core, who want some challenging one with no black box inside, and who want to improve by themselves.
13. 31.1:Sharing RAM with the CPU
CPU16 cpu(
.clk(clk),
.reset(reset),
.hold(hold), //input
.busy(busy),
.address(address_bus),
.data_in(to_cpu),
.data_out(from_cpu),
.write(write_enable));
CPUはholdを確認すると、busy出力をアサート。
hold信号がクリアされるまで待機。
その後、実行を再開。
tile_rendererがRAMからデータを読み取る前に、
hold信号をCPUに送信。
設計上、CPUはこの信号に応答して停止するまで
最大5クロックサイクルかかることがあるため、
RAMからの読み取りを開始する前に、必ず5サイク
ルholdをアサート。// state 1: select opcode address
S_SELECT: begin
write <= 0;
if (hold) begin
busy <= 1;
state <= S_SELECT;
14. 31.1:Sharing RAM with the CPU
tile_renderer
ram_busy CPUへ
// lookup char and attr
always @(posedge clk) begin
// time to read a row?
if (vpos[2:0] == 7) begin
// read row_base from page table (2 bytes)
case (hpos)
// assert busy 5 cycles before first RAM read
HLOAD-8: ram_busy <= 1;
// deassert BUSY and increment row counter
HLOAD+34: begin
ram_busy <= 0;
end
15. 31.2:The Tile Renderer State Machine
The tile renderer has two conceptual parts:
the fill stage and the output stage.
fillステージの時にRAMからデータを読み込み、
内部バッファへライト
reg [15:0] row_buffer[0:31] タイルデータを保持
hposおよびvpos信号を使用してバッファへライト
16. 31.2:The Tile Renderer State Machine
// start loading cells from RAM at this hpos value
// first column read will be ((HLOAD-2) % 32)
parameter HLOAD = 272;
HLOAD定数は、読み始める水平位置を定義
タイルは8x8なので、8スキャンラインごとに
RAMから読み取る。
// time to read a row?
if (vpos[2:0] == 7) begin
17. 31.2:The Tile Renderer State Machine
case(hpos)
HLOAD-8:ram_busy信号をアサートしてCPUに停止の準備を開始するよう指示。
CPUに停止するまでに5サイクルを与え、現在の命令を終了させる。
// assert busy 5 cycles before first RAM read
HLOAD-8: ram_busy <= 1;
HLOAD-3で、ram_addr(RAMアドレスバスに接続されている)を
ページテーブルの現在のエントリに設定。
// set address for row in page base table
HLOAD-3: ram_addr <= {page_base, 3’b000, row};
19. 31.2:The Tile Renderer State Machine
コピー操作は、HLOADからHLOAD + 33まで。
HLOAD+34: begin
ram_busy <= 0;
row <= row + 1;
end
同期RAMの読み出しは2サイクルかかる。(アドレスバスの設定+同期RAMデータの待機)。
if (hpos >= HLOAD && hpos < HLOAD+34) begin
// set address bus to (row_base + hpos)
ram_addr <= row_base + 16'(hpos[4:0]);
// store value on data bus from (row_base + hpos - 2)
// which was read two cycles ago
row_buffer[hpos[4:0] - 2] <= ram_read;
end
28. 32.4: Sprites and Slots
NB - フレームあたりのスプライトの最大数。
MB - 最大スロット数(スキャンラインあたりのスプライト)。
NB = 5は2の5乗。32スプライト。
parameter NB = 5;// 2^NB == number of sprites
parameter MB = 3;// 2^MB == slots per scanline
localparam N = 1<<NB;// number of sprites
localparam M = 1<<MB;// slots per scanline
スプライトデータがRAMから読み込まれた後もそのコピーを 保持するローカルメモリ
// copy of sprite data from RAM (N entries)
reg [7:0] sprite_xpos[0:N-1];// X positions
reg [7:0] sprite_ypos[0:N-1];// Y positions
reg [7:0] sprite_attr[0:N-1];// attributes
29. 32.4: Sprites and Slots
スロットがアクティブであるかどうかを示すブール値のマークを付けて、
スキャンラインごとのスロットについて同様のデータを保持
// M sprite slots
reg [7:0] line_xpos[0:M-1];// X pos for M slots
reg [7:0] line_yofs[0:M-1];// Y pos for M slots
reg [7:0] line_attr[0:M-1];// attr for M slots
reg line_active[0:M-1];// slot active?
30. 32.5: Lodaing Sprite Data From RAM
if (reset || vpos[8]) begin
// load sprites from RAM on line 260 // 8 cycles per sprite
// do first sprite twice b/c CPU might still be busy
if (vpos == 260 && hpos < N*2+8) begin
ram_busy <= 1;
case (hpos[0])
0: begin
ram_addr <= {load_index, 1'b0};
// load X and Y position (2 cycles ago)
sprite_xpos[load_index] <= ram_data[7:0];
sprite_ypos[load_index] <= ram_data[15:8];
end
1: begin
ram_addr <= {load_index, 1'b1};
// load attribute (2 cycles ago)
sprite_attr[load_index] <= ram_data[7:0];
end
endcase
end
最初の数個のスプライトは、
CPUがビジー状態(停止するまで最大5サ
イクルかかる可能性がある)なので
破損している可能性があり。
他のスプライトがすべて読み取られた後に、
それらを再度読み取り。
31. 32.6: Itrating The Sprite List
各スキャンラインの始めに、すべてのスプライトをスキャンし、
どれがこのスキャンラインと交差するかを判断。
それから、Yオフセットを保存し、アクティブにして、sprite_to_lineマッピングを更新。
スプライトごとに2サイクル。
32. 32.6: Itrating The Sprite List
各スキャンラインの始めに、すべてのスプライトをスキャンし、
どれがこのスキャンラインと交差するかを判断します。
それから、Yオフセットを保存し、アクティブにして、
sprite_to_lineマッピングを更新します。
これはスプライトごとに2サイクルかかります。
end else if (hpos < N*2) begin
// setup vars for next phase
k <= 0;
romload <= 0;
// select the sprites that will appear in this scanline
case (hpos[0])
0: z <= 8'(vpos - sprite_ypos[i]); // compute Y offset of sprite relative to scanline
1: begin
// sprite is active if Y offset is 0..15
if (z < 16) begin
line_xpos[j] <= sprite_xpos[i]; // save X pos
line_yofs[j] <= z; // save Y offset
line_attr[j] <= sprite_attr[i]; // save attr
line_active[j] <= 1; // mark sprite active
j <= j + 1; // inc counter
end
i <= i + 1; // inc main array counter
end
endcase
34. 32.7: Sprite Setup
if (out_bitmap == 0) begin
case (romload)
0: begin
rom_addr <= {4'b0, line_attr[k][7:4], line_yofs[k]}; // set ROM address and fetch bitmap
end
1: begin
// load scanline buffer offset to write
write_ofs <= {~vpos[0], line_xpos[k]};
// fetch 0 if sprite is inactive
out_bitmap <= line_active[k] ? rom_data : 0;
// load attribute for sprite
out_attr <= line_attr[k];
// disable sprite for next scanline
line_active[k] <= 0;
// go to next sprite in 2ndary buffer
k <= k + 1;
end
endcase
romload <= !romload;