Merge pull request #36 from h-chal/fix_rv64mi-p-access

fix: cache full virtual address for TLB micro-cache

(cherry picked from commit a79a4502c0e689058e6a2ffafd75b507c57ed3b9)
This commit is contained in:
Rishiyur S. Nikhil
2025-05-08 19:14:57 -04:00
committed by Jessica Clarke
parent ed011ac0fe
commit 8fc12c1dee

View File

@@ -520,10 +520,24 @@ module mkFetchStage(FetchStage);
nextAddrPred.put_pc(pc_reg[pc_final_port]);
endrule
Reg#(Vector#(PageBuffSize,Maybe#(Vpn))) buffered_translation_virt_pc <- mkReg(replicate(Invalid));
Reg#(Vector#(PageBuffSize,Maybe#(Addr))) buffered_translation_virt_pc <- mkReg(replicate(Invalid));
Reg#(Vector#(PageBuffSize,TlbResp)) buffered_translation_tlb_resp <- mkRegU;
Reg#(Bit#(TLog#(PageBuffSize))) buffered_translation_count <- mkRegU;
function Maybe#(UInt#(TLog#(PageBuffSize))) matchingVpnOrInvalidAddress(Addr pc);
// Maybe return an entry with the same VPN or same full PC if its an invalid address.
if (validVirtualAddress(pc)) begin
// Compare VPNs.
function Maybe#(Vpn) getVpnIfPossible(Maybe#(Addr) maybePc);
if (maybePc matches tagged Valid .pc) getVpnIfPossible = Valid(getVpn(pc));
else getVpnIfPossible = Invalid;
endfunction
matchingVpnOrInvalidAddress = findElem(Valid(getVpn(pc)), map(getVpnIfPossible, buffered_translation_virt_pc));
end else
// Compare entire PCs.
matchingVpnOrInvalidAddress = findElem(Valid(pc), buffered_translation_virt_pc);
endfunction
rule invalidate_buffered_translation(!iTlb.flush_done);
buffered_translation_virt_pc <= replicate(Invalid);
endrule
@@ -536,9 +550,10 @@ module mkFetchStage(FetchStage);
translateAddress.deq;
if (iTlb.flush_done) begin
// Check if, because of pipelining, we already have this vpn.
Bool found = elem(Valid(getVpn(translateAddress.first)), buffered_translation_virt_pc);
if (!found) begin
buffered_translation_virt_pc[buffered_translation_count] <= Valid(getVpn(translateAddress.first));
let pc = translateAddress.first;
if (!isValid(matchingVpnOrInvalidAddress(pc))) begin
// If we don't have this VPN or the PC is invalid and doesn't match in full:
buffered_translation_virt_pc[buffered_translation_count] <= Valid(pc);
buffered_translation_tlb_resp[buffered_translation_count] <= tr;
buffered_translation_count <= buffered_translation_count + 1;
end
@@ -570,8 +585,11 @@ module mkFetchStage(FetchStage);
Maybe#(CapMem) pred_next_pc = pred_future_pc[posLastSupX2];
// Search the last few translations to look for a match.
Maybe#(UInt#(TLog#(PageBuffSize))) m_buff_match_idx = findElem(Valid(getVpn(getAddr(pc))), buffered_translation_virt_pc);
Maybe#(UInt#(TLog#(PageBuffSize))) m_buff_match_idx = matchingVpnOrInvalidAddress(getAddr(pc));
if (m_buff_match_idx matches tagged Valid .buff_match_idx) begin
// Invalidate the buffered TLB response if it was for an invalid virtual address.
if (!validVirtualAddress(getAddr(pc)))
buffered_translation_virt_pc[buff_match_idx] <= Invalid;
let next_fetch_pc = fromMaybe(addPc(pc, 2 * (zeroExtend(posLastSupX2) + 1)), pred_next_pc);
let pc_idxs <- pcBlocks.insertAndReserve(truncateLSB(pc), truncateLSB(next_fetch_pc));
PcIdx pc_idx = pc_idxs.inserted;