Version using searchableSpecFifo in BTB with actual searching, but

without killing speculative elements yet. This one is full performance
in CoreMark.
This commit is contained in:
Jonathan Woodruff
2021-12-15 11:18:33 +00:00
parent 657453a0a0
commit 696f546ecb
3 changed files with 37 additions and 22 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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;