diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index ef05af9..0a17f40 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -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;