From 0ae1d8a275fa66e811d1bb4fbd38c7ae71bfab9a Mon Sep 17 00:00:00 2001 From: Peter Rugg Date: Thu, 16 Jan 2025 14:54:21 +0000 Subject: [PATCH] Clear compressed and uncompressed BTBs on mispred This fixes a wedge in the frontend: the fetch stage could get stuck in a loop, with the next address predictor deciding that the redirect PC is a compressed instruction doing a close jump. On mispredict, this would get retrained, but "mispedict" was denoted as an untaken branch to PC+2. If unlucky, PC+2 could cross an alignment boundary, causing the untaken branch to be interpreted as a long branch, leaving an old competing entry in the compressed branch BTB, which would then take priority. Fix by always marking entries in both close and long BTBs when not taken: to avoid hurting performance, this kind of update will not insert into either BTB unless already present. --- src_Core/RISCY_OOO/procs/lib/Btb.bsv | 9 +++++---- src_Core/RISCY_OOO/procs/lib/Map.bsv | 25 ++++++++++++++++++------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/lib/Btb.bsv b/src_Core/RISCY_OOO/procs/lib/Btb.bsv index 2b92d72..0fad59e 100644 --- a/src_Core/RISCY_OOO/procs/lib/Btb.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Btb.bsv @@ -120,10 +120,11 @@ module mkBtbCore(NextAddrPred#(hashSz)) pc, getBank(pc), taken, nextPc, $time);*/ CompressedTarget shortMask = -1; CapMem mask = ~zeroExtend(shortMask); - if ((pc&mask) == (nextPc&mask)) - compressedRecords[getBank(pc)].update(lookupKey(pc), VnD{v:taken, d:truncate(nextPc)}); - else - fullRecords[getBank(pc)].update(lookupKey(pc), VnD{v:taken, d:nextPc}); + let compressable = (pc&mask) == (nextPc&mask); + if (compressable || !taken) + compressedRecords[getBank(pc)].updateMayInsert(lookupKey(pc), VnD{v:taken, d:truncate(nextPc)}, taken); + if (!compressable || !taken) + fullRecords[getBank(pc)].updateMayInsert(lookupKey(pc), VnD{v:taken, d:nextPc}, taken); endrule method Action put_pc(CapMem pc); diff --git a/src_Core/RISCY_OOO/procs/lib/Map.bsv b/src_Core/RISCY_OOO/procs/lib/Map.bsv index 61bcc3a..d2583ad 100644 --- a/src_Core/RISCY_OOO/procs/lib/Map.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Map.bsv @@ -118,6 +118,7 @@ Bitwise#(ix), Eq#(ix), Arith#(ix)); endmodule interface MapSplit#(type ky, type ix, type vl, numeric type as); + method Action updateMayInsert(MapKeyIndex#(ky,ix) key, vl value, Bool insert); method Action update(MapKeyIndex#(ky,ix) key, vl value); method Action lookupStart(MapKeyIndex#(ky,ix) lookup_key); method Maybe#(vl) lookupRead; @@ -133,6 +134,7 @@ Bitwise#(ix), Eq#(ix), Arith#(ix), PrimIndex#(ix, a__)); Vector#(as, RWBramCore#(ix, ky)) updateKeys <- replicateM(mkRWBramCoreUG); Reg#(MapKeyIndex#(ky,ix)) lookupReg <- mkRegU; Reg#(MapKeyIndexValue#(ky,ix,vl)) updateReg <- mkRegU; + Reg#(Bool) updateInsert <- mkRegU; Reg#(Bool) updateFresh <- mkDReg(False); Reg#(Bit#(TLog#(as))) wayNext <- mkReg(0); Integer a = valueof(as); @@ -147,23 +149,32 @@ Bitwise#(ix), Eq#(ix), Arith#(ix), PrimIndex#(ix, a__)); if (clearCount == ~0) clearReg <= False; end else if (updateFresh) begin let u = updateReg; - Bit#(TLog#(as)) way = wayNext; + Maybe#(Bit#(TLog#(as))) hitWay = Invalid; for (Integer i = 0; i < a; i = i + 1) - if (updateKeys[i].rdResp == u.key) way = fromInteger(i); + if (updateKeys[i].rdResp == u.key) hitWay = Valid(fromInteger(i)); // Always write to both the main memory bank and the copy used for updates. /*$display("MapUpdate - index: %x, key: %x, value: %x, way: %x", u.index, u.key, u.value, way);*/ - mem[way].wrReq(u.index, MapKeyValue{key: u.key, value: u.value}); - updateKeys[way].wrReq(u.index, u.key); - wayNext <= (wayNext == fromInteger(a-1)) ? 0 : (wayNext + 1); + if (updateInsert || isValid(hitWay)) begin + let way = fromMaybe(wayNext, hitWay); + mem[way].wrReq(u.index, MapKeyValue{key: u.key, value: u.value}); + updateKeys[way].wrReq(u.index, u.key); + wayNext <= (wayNext == fromInteger(a-1)) ? 0 : (wayNext + 1); + end end endrule - method Action update(MapKeyIndex#(ky,ix) ki, vl value); + function Action updateFn(MapKeyIndex#(ky,ix) ki, vl value, Bool insert) = action updateReg <= MapKeyIndexValue{key: ki.key, index: ki.index, value: value}; updateFresh <= True; + updateInsert <= insert; for (Integer i = 0; i < a; i = i + 1) updateKeys[i].rdReq(ki.index); - endmethod + endaction; + + method Action updateMayInsert(MapKeyIndex#(ky,ix) ki, vl value, Bool insert) = + updateFn(ki, value, insert); + method Action update(MapKeyIndex#(ky,ix) ki, vl value) = + updateFn(ki, value, True); method Action lookupStart(MapKeyIndex#(ky,ix) ki); lookupReg <= ki; for (Integer i = 0; i < a; i = i + 1) mem[i].rdReq(ki.index);