Do negative training when we encounter a load that has previously been

killed, but was not killed this time.
This commit is contained in:
jon
2021-04-10 08:47:05 +01:00
parent aa9e57ce10
commit 8e3fd534f9
2 changed files with 18 additions and 11 deletions

View File

@@ -55,7 +55,7 @@ typedef struct {
// the value stored in the map, and the associativity of the storage.
interface Map#(type ky, type ix, type vl, numeric type as);
method Action update(MapKeyIndex#(ky,ix) key, vl value);
method Action updateWithFunc(MapKeyIndex#(ky,ix) ki, vl value, function vl up(vl old_v, vl new_v));
method Action updateWithFunc(MapKeyIndex#(ky,ix) ki, vl value, function vl up(vl old_v, vl new_v), Bool insert);
method Maybe#(vl) lookup(MapKeyIndex#(ky,ix) lookup_key);
method Action clear;
method Bool clearDone;
@@ -79,29 +79,31 @@ Bitwise#(ix), Eq#(ix), Arith#(ix));
if (clearCount == ~0) clearReg <= False;
endrule
function Action doUpdate(MapKeyIndex#(ky,ix) ki, vl value, function vl up(vl old_v, vl new_v));
function Action doUpdate(MapKeyIndex#(ky,ix) ki, vl value, function vl up(vl old_v, vl new_v), Bool insert);
action
Bool found = False;
Bit#(TLog#(as)) way = wayNext;
MapKeyValue#(ky,vl) old = unpack(0);
if (a > 1) begin
for (Integer i = 0; i < a; i = i + 1) begin
MapKeyValue#(ky,vl) entry = mem[i].sub(ki.index);
if (entry.key == ki.key) begin
found = True;
way = fromInteger(i);
old = entry;
end
end
end
mem[way].upd(ki.index, MapKeyValue{key: ki.key, value: up(old.value, value)});
if (found || insert) mem[way].upd(ki.index, MapKeyValue{key: ki.key, value: up(old.value, value)});
wayNext <= (wayNext == fromInteger(a-1)) ? 0: wayNext + 1;
didUpdate.send;
endaction
endfunction
function vl returnNew(vl old_v, vl new_v) = new_v;
method Action update(MapKeyIndex#(ky,ix) ki, vl value) = doUpdate(ki, value, returnNew);
method Action updateWithFunc(MapKeyIndex#(ky,ix) ki, vl value, function vl up(vl old_v, vl new_v)) =
doUpdate(ki, value, up);
method Action update(MapKeyIndex#(ky,ix) ki, vl value) = doUpdate(ki, value, returnNew, True);
method Action updateWithFunc(MapKeyIndex#(ky,ix) ki, vl value, function vl up(vl old_v, vl new_v), Bool insert) =
doUpdate(ki, value, up, insert);
method Maybe#(vl) lookup(MapKeyIndex#(ky,ix) lu);
Maybe#(vl) ret = Invalid;

View File

@@ -2119,7 +2119,8 @@ module mkSplitLSQ(SplitLSQ);
doAssert(ld_specBits_deqLd[deqP] == 0,
"at commit means zero spec bits");
end
if(isValid(ld_killed_deqLd[deqP])) begin
Bool killedLd = isValid(ld_killed_deqLd[deqP]);
if(killedLd) begin
doAssert(ld_memFunc[deqP] == Ld && !ld_isMMIO_deqLd[deqP],
"must be non-MMIO Ld");
doAssert(!isValid(ld_fault_deqLd[deqP]), "cannot have fault");
@@ -2127,11 +2128,15 @@ module mkSplitLSQ(SplitLSQ);
"must be done");
doAssert(!ld_waitWPResp_deqLd[deqP],
"cannot wait for wrong path resp");
ldKillMap.updateWithFunc(unpack(ld_pc_hash[deqP]), 1, boundedPlus); // Update predictor.
end else if ((rand_count & (512-1)) == 0) begin
// "randomly" evict trained entries in the store-to-load aliasing predictor.
ldKillMap.update(unpack(ld_pc_hash[deqP]), minBound);
end
Bool rand_inv = (rand_count & (512-1)) == 0;
Bool waited = ld_waitForOlderSt[deqP]; // Don't negative train if we waited for older stores.
// Update predictor.
ldKillMap.updateWithFunc(unpack(ld_pc_hash[deqP]), // Key
waited ? 0:1, // value; don't train if we waited.
killedLd ? boundedPlus:boundedMinus, // function to combine this value with existing
killedLd || rand_inv // insert if doesn't exist
);
// remove the entry
ld_valid_deqLd[deqP] <= False;