いよいよ自作CPUにベクトル・メモリ・アクセス命令を実装するときが来た。まずは簡単なUnit Strideロード命令を実装しようと思う。 何も考えずに、Cacheableな領域にストレートにアクセスする形式から考えていきたい。
話を簡単にするために、いつものアウト・オブ・オーダ命令発行のユニットを再利用していきたい。 こうすることによりメモリアクセスの順序違反検出やフォワーディングが大変なのは目に見えているのだが、まあ定量的に本当にどれくらい大変なのかを見てみるのも面白い思う。
とりあえず、Unit Stride LoadでLMUL=1だけに限定するのでアドレス生成もめっちゃ単純にする。
module mycpu_vlsu_address_gen import decoder_lsu_ctrl_pkg::*; import mycpu_lsu_pkg::*; ( input logic i_clk, input logic i_reset_n, input riscv_pkg::xlen_t i_rs1_base, output mycpu_pkg::vaddr_t o_vaddr ); assign o_vaddr = i_rs1_base; endmodule // mycpu_vlsu_address_gen
スカラLSUと同じ仕組みでパイプラインを作っていく。DCacheへのアクセスのみ、スカラ側にインタフェースを生やしてリクエストを出すようにする。
assign l1d_rd_if.s0_valid = r_ex1_issue.valid & (r_ex1_pipe_ctrl.op == decoder_vlsu_ctrl_pkg::OP_LOAD); assign l1d_rd_if.s0_paddr = {w_ex1_addr[riscv_pkg::PADDR_W-1:$clog2(DCACHE_DATA_B_W)], {$clog2(DCACHE_DATA_B_W){1'b0}}}; assign l1d_rd_if.s0_high_priority = 1'b0; // r_ex1_issue.l1d_high_priority;
さて、L1Dキャッシュをミスしたときの話だが、これはとりあえずスカラ側のMSHRを再利用するか悩みどころだな。 スカラ側とベクトル側のMSHRを分断してしまうと、メモリアクセスのフォワーディングやハザードのポートがあっという間に爆発してしまう。 MSHR自体はスカラのものを間借りしてもいいかな...その代わりに、LDQなどは別々に管理させてもらおう。