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