リセット時のPCの動きを調べるため、ifu(Instruction fetch unit)の中を追って見ました。
パイプラインの最初のフェッチ時のPCはt0pc_fなので、そこから追います。
t0pc_f への代入
sparc_ifu_fdp.vから
// F stage thread PC regs; use low power thr flop dff_ny #(49) t0_pcf_reg(.din (t0npc_bf), .clk (clk), .q (t0pc_f), .se (se), .si(), .so());
dff_nyがFFなので、t0npc_bfをclkで叩いてt0pc_fに入れています。
t0npc_bf への代入
// Select the next thread pc (for F stage) dp_mux4ds #(49) t0_pcbf_mux(.dout (t0npc_bf), .in0 ({fcl_fdp_pcoor_vec_f[0], t0pc_f[47:0]}), .in1 (nextpc_nosw_bf), .in2 (t0_trap_rb_pc_bf), .in3 ({1'b0, exu_i fu_brpc_e}), .sel0_l (fcl_fdp_tpcbf_sel_old_bf_l[0]), .sel1_l (fcl_fdp_tpcbf_sel_pcp4_bf_l[0]), .sel2_l (fcl_fdp_tpcbf_sel_trap_bf_l[0]), .sel3_l (fcl_fdp_tpcbf_sel_brpc_bf_l[0]));
t0npc_bfは、4つの入力からマルチプレクサを通して値が代入されています。
マルチプレクサ(dp_mux4ds)の中身も見てみましょう。
always @ (sel0_l or sel1_l or sel2_l or sel3_l or in0 or in1 or in2 or in3) case ({sel3_l,sel2_l,sel1_l,sel0_l}) 4'b1110 : dout = in0 ; 4'b1101 : dout = in1 ; 4'b1011 : dout = in2 ; 4'b0111 : dout = in3 ; 4'b1111 : dout = {SIZE{1'bx}} ; default : dout = {SIZE{1'bx}} ; endcase
sel3_l,sel2_l,sel1_l,sel0_lに対して、負論理で信号を選択しています。シミュレーションをしてみるとfcl_fdp_tpcbf_sel_trap_bf_lがL(アサート)なので、t0_trap_rb_pc_bfが選択されています。リセット時のPCはトラップ周りで設定されているようです。
t0_trap_rb_pc_bfへの代入
t0_trap_rb_pc_bfがトラップとロールバック用のPCです。同じく4つの値からマルチプレクサで選択されています。
// trappc mux (choose trap pc vs rollback/uTrap pc) dp_mux4ds #(49) trap_pc0_mux(.dout (t0_trap_rb_pc_bf), .in0 (tlu_ifu_trappc_w2), .in1 (pc_d_adj), .in2 (t0pc_s), .in3 (pc_w), .sel0_l (fcl_fdp_trrbpc_sel_trap_bf_l[0]), .sel1_l (fcl_fdp_trrbpc_sel_rb_bf_l[0]), .sel2_l (fcl_fdp_trrbpc_sel_pcs_bf_l[0]), .sel3_l (fcl_fdp_trrbpc_sel_err_bf_l[0]));
シミュレーションで確認してみると、fcl_fdp_trrbpc_sel_trap_bf_l[0]がL(アサート)なので、tlu_ifu_trappc_w2が選択されています。tlu_ifu_trappc_w2は、sparc_ifu_fdp.vの外にあるので次はそこを追いましょう。