NaxRiscvの実装を解析しながら、SystemVerilog化することで理解を深めていこうと思う。
FetchCachePluginには、どのWayを置き換えるのかを計算するPLRUのコードが示されている。 いろいろ解析するとこれはTree PLRUを実装しているコードのようだ。しかしSpinal HDLのコードが意味不明すぎて良く理解できていない。
EvictionとUpdateのロジックに分かれていて、最初はUpdateの論理でPLRUのポインタを更新するのかと思ったら違うらしい。
なんか良く分からないのでChatGPTに実装をVerilog-HDLに変換してもらった。
module Plru #( parameter int ENTRIES = 4, // Number of cache entries, must be a power of 2 parameter bit WITH_ENTRIES_VALID = 0 // Flag to enable valid entry checking )( input logic [log2(ENTRIES)-1:0] update_id, // ID of the accessed entry input logic [log2(ENTRIES)-1:0] context_state [log2(ENTRIES)-1:0], // Current PLRU tree state input logic [ENTRIES-1:0] context_valids, // Valid entries for replacement check output logic [log2(ENTRIES)-1:0] evict_id, // ID of the entry to evict output logic [log2(ENTRIES)-1:0] update_state [log2(ENTRIES)-1:0] // Updated PLRU tree state ); logic [log2(ENTRIES)-1:0] sel [log2(ENTRIES)-1:0]; // Selection bits for eviction logic [log2(ENTRIES)-1:0] new_state [log2(ENTRIES)-1:0]; // Internal state for update logic // Eviction Logic generate genvar i; for (i = 0; i < log2(ENTRIES); i = i + 1) begin : eviction_logic logic [i:0] state_sel; assign state_sel = sel[i-1:0]; // Selection path based on previous sel values always_comb begin sel[i] = ~context_state[i][state_sel]; // Invert the state to select LRU path end if (WITH_ENTRIES_VALID) begin : valid_check // Ensure only valid entries are considered for eviction logic [1:0] notOks; assign notOks[0] = |context_valids[state_sel * 2 +: 2]; // Check valid entries in the group sel[i] = notOks[0] ? 0 : sel[i]; end end endgenerate assign evict_id = sel[log2(ENTRIES)-1]; // The final eviction ID is based on the selection path // Update Logic generate for (i = 0; i < log2(ENTRIES); i = i + 1) begin : update_logic always_comb begin if (i == 0) begin update_state[i] = context_state[i]; // Preserve current state for higher levels end update_state[i][update_id[log2(ENTRIES)-1:i]] = update_id[log2(ENTRIES)-1-i]; // Update state end end endgenerate endmodule