Do negative training when we encounter a load that has previously been
killed, but was not killed this time.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user