From 696f546ecbac3ad5042158c1172963db69d8a58f Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Wed, 15 Dec 2021 11:18:33 +0000 Subject: [PATCH] Version using searchableSpecFifo in BTB with actual searching, but without killing speculative elements yet. This one is full performance in CoreMark. --- .../RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv | 2 +- src_Core/RISCY_OOO/procs/lib/Btb.bsv | 31 ++++++++++++++----- src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv | 26 +++++++--------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index 788fc1c..d5383e0 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -854,7 +854,7 @@ module mkFetchStage(FetchStage); // only when misprediction happens, i.e., train by dec is already at // wrong path. TrainNAP train = fromMaybe(validValue(napTrainByDec.wget), napTrainByExe.wget); - nextAddrPred.update(train.pc, train.nextPc, train.nextPc != addPc(train.pc, 2)); + nextAddrPred.update(train.pc, train.nextPc, train.nextPc != addPc(train.pc, 2), ?); endrule // Security: we can flush when front end is empty, i.e. diff --git a/src_Core/RISCY_OOO/procs/lib/Btb.bsv b/src_Core/RISCY_OOO/procs/lib/Btb.bsv index 335d1ab..a245fb2 100644 --- a/src_Core/RISCY_OOO/procs/lib/Btb.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Btb.bsv @@ -42,6 +42,7 @@ import Map::*; import Vector::*; import CHERICC_Fat::*; import CHERICap::*; +import SpecFifo::*; export NextAddrPred(..); export mkBtb; @@ -49,7 +50,7 @@ export mkBtb; interface NextAddrPred#(numeric type hashSz); method Action put_pc(CapMem pc); interface Vector#(SupSizeX2, Maybe#(CapMem)) pred; - method Action update(CapMem pc, CapMem brTarget, Bool taken); + method Action update(CapMem pc, CapMem brTarget, Bool taken, SpecBits specBits); // security method Action flush; method Bool flush_done; @@ -109,9 +110,23 @@ module mkBtbCore(NextAddrPred#(hashSz)) function MapKeyIndex#(HashedTag#(hashSz),BtbIndex) lookupKey(CapMem pc) = MapKeyIndex{key: hash(getTag(pc)), index: getIndex(pc)}; + Bool lazyEnq = True; + Bool unguarded_insert = True; + function Maybe#(CapMem) match_record(BtbAddr pc, BtbUpdate update); + if (update.taken && (getBtbAddr(update.pc) == pc)) return Valid(update.nextPc); + else return Invalid; + endfunction + SearchableSpecFifo#(4, BtbUpdate, CapMem, BtbAddr) updateQ <- mkSearchableSpecFifoCF( + lazyEnq, + unguarded_insert, + match_record + ); + // no flush, accept update - (* fire_when_enabled, no_implicit_conditions *) - rule canonUpdate(updateEn.wget matches tagged Valid .upd); + (* fire_when_enabled *) + rule canonUpdate; + BtbUpdate upd = updateQ.first.data; + updateQ.deq; let pc = upd.pc; let nextPc = upd.nextPc; let taken = upd.taken; @@ -126,7 +141,6 @@ module mkBtbCore(NextAddrPred#(hashSz)) endrule method Action put_pc(CapMem pc); - addr_reg <= pc; // Start SupSizeX2 BTB lookups, but ensure to lookup in the appropriate // bank for the alignment of each potential branch. for (Integer i = 0; i < valueOf(SupSizeX2); i = i + 1) begin @@ -134,6 +148,7 @@ module mkBtbCore(NextAddrPred#(hashSz)) fullRecords[a.bank].lookupStart(MapKeyIndex{key: hash(a.tag), index: a.index}); compressedRecords[a.bank].lookupStart(MapKeyIndex{key: hash(a.tag), index: a.index}); end + addr_reg <= pc; endmethod method Vector#(SupSizeX2, Maybe#(CapMem)) pred; @@ -142,14 +157,16 @@ module mkBtbCore(NextAddrPred#(hashSz)) if (fullRecords[i].lookupRead matches tagged Valid .r) ppcs[i] = r.v ? Valid(r.d):Invalid; if (compressedRecords[i].lookupRead matches tagged Valid .r) - ppcs[i] = r.v ? Valid({truncateLSB(addr_reg),r.d}):Invalid; + ppcs[i] = r.v ? Valid({truncateLSB(pack(addr_reg)),r.d}):Invalid; + if (updateQ.search(getBtbAddr(addr_reg)) matches tagged Valid .next_pc) + ppcs[i] = Valid(next_pc); end ppcs = rotateBy(ppcs,unpack(-getBtbAddr(addr_reg).bank)); // Rotate firstBank down to zeroeth element. return ppcs; endmethod - method Action update(CapMem pc, CapMem nextPc, Bool taken); - updateEn.wset(BtbUpdate {pc: pc, nextPc: nextPc, taken: taken}); + method Action update(CapMem pc, CapMem nextPc, Bool taken, SpecBits specBits); + updateQ.enq(ToSpecFifo {spec_bits: specBits, data: BtbUpdate {pc: pc, nextPc: nextPc, taken: taken}}); endmethod `ifdef SECURITY diff --git a/src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv b/src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv index 99ac140..4e48188 100644 --- a/src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv +++ b/src_Core/RISCY_OOO/procs/lib/SpecFifo.bsv @@ -413,8 +413,6 @@ endmodule interface SearchableSpecFifo#( numeric type size, type t, - numeric type validPortNum, // valid EHR port num - numeric type sbPortNum, // specBits EHR port num type searchOut, type searchIn ); method Action enq(ToSpecFifo#(t) x); @@ -429,15 +427,12 @@ module mkSearchableSpecFifoCF#( Bool unguarded_insert, // only for probabalistic applications function Maybe#(searchOut) search_f(searchIn w, t x) )( - SearchableSpecFifo#(size, t, validPortNum, sbPortNum, searchOut, searchIn) + SearchableSpecFifo#(size, t, searchOut, searchIn) ) provisos ( Alias#(idxT, Bit#(TLog#(size))), Bits#(t, _tsz), FShow#(t) ); - // correct spec is always the last - Integer sbCorrectSpecPort = valueof(sbPortNum) - 1; - Ehr#(3, Vector#(size, Bool)) valid <- mkEhr(replicate(False)); Vector#(size, Reg#(t)) row <- replicateM(mkConfigRegU); Ehr#(3, Vector#(size, SpecBits)) specBits <- mkEhr(?); @@ -511,13 +506,16 @@ module mkSearchableSpecFifoCF#( valid_for_enq = valid[2][enqP]; end - method Action enq(ToSpecFifo#(t) x) if (empty_for_enq || enqP != deqP_for_enq); - // [sizhuo] I don't think valid bit needs to be checked here - doAssert(!valid_for_enq, "enq entry cannot be valid"); - row[enqP] <= x.data; - valid[2][enqP] <= True; - specBits[2][enqP] <= x.spec_bits; - enqP <= getNextPtr(enqP); + Bool notFull = empty_for_enq || enqP != deqP_for_enq; + method Action enq(ToSpecFifo#(t) x) if (notFull || unguarded_insert); + if (notFull) begin + // [sizhuo] I don't think valid bit needs to be checked here + doAssert(!valid_for_enq, "enq entry cannot be valid"); + row[enqP] <= x.data; + valid[2][enqP] <= True; + specBits[2][enqP] <= x.spec_bits; + enqP <= getNextPtr(enqP); + end endmethod method Action deq if (valid[1][deqP]); @@ -535,7 +533,7 @@ module mkSearchableSpecFifoCF#( method Maybe#(searchOut) search(searchIn in); Maybe#(searchOut) ret = Invalid; for(Integer i = 0; i < valueOf(size); i = i + 1) - if (valid[i][0]) + if (valid[0][i]) if (search_f(in, row[i]) matches tagged Valid .y) ret = Valid(y); return ret;