RISC-VのLinuxブート環境を構築したので、次にこれをRTL環境で実行している。
別のコンフィグレーションで実行するとLinuxのブート途中で止まってしまった。これはLR/SCの更新論理がLSUのパイプラインの別々のところにあることによるものだった。 LSU0のLR/SC情報をアップデートしても、LSU1で別のLR/SCを実行したら失敗してしまう。そりゃそうだ。
MR8(0x0000000080013090)=>0000000000000060 GPR[15](76) <= 0000000000000060 2998382 : 2259197 : PC=[0000000080007a3c] (M,45,02) 0000953e c.add a0, a5 GPR[10](149) <= 0000000080018060 2998382 : 2259198 : PC=[0000000080007a3e] (M,45,04) 0000460d c.li a2, 3 GPR[12](93) <= 0000000000000003 11993534 : L1D Load-In : 80017f00(01532) : 00000000_8000087c_00000000_80018000_00000000_8000087c_00000000_80018000_00000000_8000087c_00000000_80018000_00000000_8000087c_00000000_80018000 11993534 : Load ISS Check : 80017f00 : 00000000_00000000_0000006e_65726574_6e756f63_6d2c6e65_7265746e_756f6373_00000000_8000087c_00000000_80018000_00000000_80018000_00000000_00000000 11993538 : L1D Stq Store : 80017f00(01532) : ________________________________________________________________________00000000_8000087c_00000000_80018000____________________________________ 11993538 : STQ ISS Check : 80017f00 : 00000000_00000000_0000006e_65726574_6e756f63_6d2c6e65_7265746e_756f6373_00000000_8000087c_00000000_80018000_00000000_80018000_00000000_00000000 2998390 : 2259199 : PC=[0000000080007a40] (M,46,01) 00004589 c.li a1, 2 GPR[11](181) <= 0000000000000002 2998390 : 2259200 : PC=[0000000080007a42] (M,46,02) e98fb0ef jal pc - 0x4968 GPR[01](53) <= 0000000080007a46 2998420 : 2259201 : PC=[00000000800030da] (M,47,01) 00001141 c.addi sp, -16 GPR[02](70) <= 0000000080017f00 2998420 : 2259202 : PC=[00000000800030dc] (M,47,02) 0000e422 c.sdsp s0, 8(sp) MW8(0x0000000080017f08)=>0000000080017f20 2998420 : 2259203 : PC=[00000000800030de] (M,47,04) 00000800 c.addi4spn s0, sp, 16 GPR[08](190) <= 0000000080017f10 2998420 : 2259204 : PC=[00000000800030e0] (M,47,08) 000087aa c.mv a5, a0 GPR[15](186) <= 0000000080018060 11993698 : L1D Load-In : 80017f00(01532) : 00000000_80017f20_00000000_00000000_00000000_80017f20_00000000_00000000_00000000_80017f20_00000000_00000000_00000000_80017f20_00000000_00000000 11993698 : Load ISS Check : 80017f00 : 00000000_00000000_0000006e_65726574_6e756f63_6d2c6e65_7265746e_756f6373_00000000_8000087c_00000000_80018000_00000000_80017f20_00000000_00000000 11993702 : L1D Stq Store : 80017f00(01532) : ____________________________________________________________________________________________________________00000000_80017f20__________________ 11993702 : STQ ISS Check : 80017f00 : 00000000_00000000_0000006e_65726574_6e756f63_6d2c6e65_7265746e_756f6373_00000000_8000087c_00000000_80018000_00000000_80017f20_00000000_00000000 2998426 : RTL(48,1) Exception Cause = CSR Update Flush(27) PC=0000800030e2, Inst=0f50000f, fence iorw,ow 2998426 : 2259205 : PC=[00000000800030e2] (M,48,01) 0f50000f fence iorw,ow 2998464 : 2259206 : PC=[00000000800030e6] (M,54,01) 1407b52f lr.d a0, (a5) MR8(0x0000000080018060)=>0000000000000002 GPR[10](69) <= 0000000000000002 2998464 : 2259207 : PC=[00000000800030ea] (M,54,02) 00b51563 bne a0, a1, pc + 10 2998474 : 2259208 : PC=[00000000800030ee] (M,55,01) 1cc7b72f sc.d a4, a2, (a5) MW8(0x0000000080018060)=>0000000000000003 ========================================== Wrong GPR[14](142): RTL = 0000000000000001, ISS = 0000000000000000 ==========================================
修正のため、LR/SCの情報を管理するためのインタフェースとモジュールを作った。
generate for (genvar p_idx = 0; p_idx < msrh_conf_pkg::LSU_INST_NUM; p_idx++) begin : lsu_port_loop assign w_lr_update_valids[p_idx] = lrsc_if[p_idx].lr_update_valid; assign w_sc_check_valids [p_idx] = lrsc_if[p_idx].sc_check_valid; assign w_lrsc_paddr_array[p_idx] = lrsc_if[p_idx].paddr; assign lrsc_if[p_idx].sc_success = w_sc_success; end endgenerate bit_oh_or #(.T(msrh_pkg::paddr_t), .WORDS(msrh_conf_pkg::LSU_INST_NUM)) u_lr_addr_sel (.i_oh(w_lr_update_valids), .i_data(w_lrsc_paddr_array), .o_selected(w_lr_paddr_sel)); bit_oh_or #(.T(msrh_pkg::paddr_t), .WORDS(msrh_conf_pkg::LSU_INST_NUM)) u_sc_addr_sel (.i_oh(w_sc_check_valids), .i_data(w_lrsc_paddr_array), .o_selected(w_sc_paddr_sel)); always_ff @ (posedge i_clk, negedge i_reset_n) begin if (!i_reset_n) begin r_lr_registered_valid <= 1'b0; r_lr_paddr <= 'h0; end else begin if (|w_lr_update_valids) begin r_lr_registered_valid <= 1'b1; r_lr_paddr <= w_lr_paddr_sel; end else if (|w_sc_check_valids) begin r_lr_registered_valid <= 1'b0; end end end assign w_sc_success = r_lr_registered_valid & (r_lr_paddr == w_sc_paddr_sel);
これでもう一度シミュレーションを流してみる。