はじめに
RISC-VなGPGPUであるVortexを深堀する (その4)として、SIMT な部分と WARP な部分を実装している部分をみていきます。
VX_dispatch
VX_dispatch は、VX_issue の中に下記のようにインスタンスされています。
VX_dispatch dispatch ( .clk (clk), .reset (dispatch_reset), .ibuffer_if (dispatch_if), .gpr_rsp_if (gpr_rsp_if), .alu_req_if (alu_req_if), .lsu_req_if (lsu_req_if), .csr_req_if (csr_req_if), `ifdef EXT_F_ENABLE .fpu_req_if (fpu_req_if), `endif .gpu_req_if (gpu_req_if) );
VX_dispatch の中の、VX_lzc の cnt_o が Thread (tid) になっています
VX_lzc #( .N (`NUM_THREADS) ) tid_select ( .in_i (ibuffer_if.tmask), .cnt_o (tid), `UNUSED_PIN (valid_o) );
この tid が SIMT なポイントです。tid が使われているのは、
tid => alu_req_if.tid
と
wire [31:0] csr_rs1_data = gpr_rsp_if.rs1_data[tid];
です。GPR と ALU を選択するために使っているようです。
VX_alu_unit の 下記の部分で、alu_req.tid が使われています。
wire [31:0] br_dest = add_result[alu_req_if.tid]; wire [32:0] cmp_result = sub_result[alu_req_if.tid];
WARP な部分は?
WARP な部分は、VX_warp_sched ですね。Thread の tid と同じように VX_lzc を使っていますね。
VX_lzc #( .N (`NUM_WARPS) ) wid_select ( .in_i (ready_warps), .cnt_o (schedule_wid), .valid_o (schedule_valid) );
下記のコードで、schedule_tmask と scedule_pc を得ています。
assign {schedule_tmask, schedule_pc} = schedule_data[schedule_wid];
schedule_tmask と scedule_pc は、最終的に、ifetch_req_if.tmask と ifetch_req_if.PC になっています。
VX_pipe_register #( .DATAW (1 + `UUID_BITS + `NUM_THREADS + 32 + `NW_BITS), .RESETW (1) ) pipe_reg ( .clk (clk), .reset (reset), .enable (!stall_out), .data_in ({schedule_valid, instr_uuid, schedule_tmask, schedule_pc, schedule_wid}), .data_out ({ifetch_req_if.valid, ifetch_req_if.uuid, ifetch_req_if.tmask, ifetch_req_if.PC, ifetch_req_if.wid}) );
ifetch_req_if は、VX_icache_stage に接続して、I-Cache に繋がっています。
VX_icache_stage #( .CORE_ID(CORE_ID) ) icache_stage ( `SCOPE_BIND_VX_fetch_icache_stage .clk (clk), .reset (reset), .icache_rsp_if (icache_rsp_if), .icache_req_if (icache_req_if), .ifetch_req_if (ifetch_req_if), .ifetch_rsp_if (ifetch_rsp_if) );
おわりに
次回は、RISC-VなGPGPUである Vortex を深堀する (その5)として、Vortex の runtime をみてみます。