FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

オープンソース・アウトオブオーダCPU NaxRiscvを概観する (Return Address Stackのソースコードを概観する1)

NaxRiscvのRAS(Return Address Stack)に関連するソースコードを読んでいきたいと思う。

基本的にはSpinal-HDLのブロックを引っ張り出してVerilogのモジュールでまとめ上げて、わかりにくい展開されたような論理をまとめていったうえで中身を解析する。

まずはRASのメモリの部分から。RASのスタックメモリは以下のように定義されている。

(* ram_style = "distributed" *) reg [39:0] DecoderPredictionPlugin_logic_ras_mem_stack [0:15];

書き込みと読み込みの論理は単純だが、投機的な動作が不明だ:

assign DecoderPredictionPlugin_logic_ras_write_valid           = FrontendPlugin_serialized_isFireing &
                                                                 (FrontendPlugin_serialized_Frontend_DISPATCH_MASK_0 && FrontendPlugin_serialized_RAS_PUSH_0 |
                                                                  FrontendPlugin_serialized_Frontend_DISPATCH_MASK_1 && FrontendPlugin_serialized_RAS_PUSH_1);
assign DecoderPredictionPlugin_logic_ras_write_payload_address = DecoderPredictionPlugin_logic_ras_ptr_push;
assign DecoderPredictionPlugin_logic_ras_write_payload_data    = FrontendPlugin_serialized_Frontend_DISPATCH_MASK_0 && FrontendPlugin_serialized_RAS_PUSH_0 ? FrontendPlugin_serialized_PC_INC_0 :
                                                                 FrontendPlugin_serialized_Frontend_DISPATCH_MASK_1 && FrontendPlugin_serialized_RAS_PUSH_1 ? FrontendPlugin_serialized_PC_INC_1 :
                                                                 'h0;
always @(posedge clk) begin
  if(DecoderPredictionPlugin_logic_ras_write_valid) begin
    DecoderPredictionPlugin_logic_ras_mem_stack[DecoderPredictionPlugin_logic_ras_write_payload_address] <= DecoderPredictionPlugin_logic_ras_write_payload_data;
  end
end

PushとPopの論理はほとんど一緒なのだが、これでいいのかなあ?

      val ptr = new Area{
        val push = Reg(UInt(log2Up(rasDepth) bits)) init(0)
        val pop = Reg(UInt(log2Up(rasDepth) bits)) init(rasDepth-1)
        val pushIt, popIt = False

        push := push + U(pushIt) - U(popIt)
        pop  := pop + U(pushIt) - U(popIt)
      }

あとは、ROBからリスケジュールの信号がくると、それに基づいてPushとPopのポインタを戻す。

    if(CommitPlugin_logic_reschedule_reschedulePort_valid) begin
      DecoderPredictionPlugin_logic_ras_ptr_push <= DecoderPredictionPlugin_logic_ras_healPush;
      DecoderPredictionPlugin_logic_ras_ptr_pop  <= DecoderPredictionPlugin_logic_ras_healPop;
    end else begin