From 879ea09e9d12fc51ae9deecca19df5cbc96847c9 Mon Sep 17 00:00:00 2001 From: giorgioajmone Date: Mon, 29 Jul 2024 13:54:54 +0200 Subject: [PATCH] feat: checkpoint-working-paraflex --- components/BranchPredictor/BTB.cpp | 98 +++++++++---------- components/BranchPredictor/BTB.hpp | 1 + components/BranchPredictor/BTBSet.cpp | 8 ++ components/BranchPredictor/BTBSet.hpp | 2 + .../BranchPredictor/BranchPredictor.cpp | 13 ++- components/BranchPredictor/TAGEImpl.hpp | 59 +++++++++-- components/CMPCache/InfiniteDirectory.hpp | 4 +- components/CMPCache/StdArray.hpp | 4 +- components/Cache/StdArray.hpp | 3 + components/FastCMPCache/InfiniteDirectory.cpp | 5 +- components/uFetch/uFetchImpl.cpp | 3 + 11 files changed, 137 insertions(+), 63 deletions(-) diff --git a/components/BranchPredictor/BTB.cpp b/components/BranchPredictor/BTB.cpp index f86837b3..0fdbadcc 100644 --- a/components/BranchPredictor/BTB.cpp +++ b/components/BranchPredictor/BTB.cpp @@ -8,7 +8,8 @@ BTB::BTB(int32_t aBTBSets, int32_t aBTBAssoc) { // aBTBSize must be a power of 2 DBG_Assert(((aBTBSets - 1) & (aBTBSets)) == 0); - theBTB.resize(aBTBSets); + theBTB.resize(aBTBSets, BTBSet(aBTBAssoc)); + theIndexMask = aBTBSets - 1; // ! Shouldn't it be log2(aBTBSets) ? } @@ -123,57 +124,56 @@ BTB::saveState() const { //DBG_Assert(false, (<< "Don't know how to save type " << block->theBranchType)); break; } - checkpoint[i][j] = {{"PC", (uint64_t)block->thePC}, {"target", (uint64_t)block->theTarget}, {"type", (uint8_t)type}}; + if(block->valid){ + checkpoint[i][j] = {{"PC", (uint64_t)block->thePC}, {"target", (uint64_t)block->theTarget}, {"type", (uint8_t)type}}; + } } } return checkpoint; } -// void -// BTB::loadState(json checkpoint) -//{ -// -// for (size_t set = 0; set < (size_t)theBTBSets; set++) { -// -// size_t blockSize = checkpoint.at(set).size(); -// -// theBTB[set].get().clear(); -// -// for (size_t block = 0; block < blockSize; block++) { -// uint64_t aPC = checkpoint.at(set).at(block)["PC"]; -// uint64_t aTarget = checkpoint.at(set).at(block)["target"]; -// uint64_t aType = checkpoint.at(set).at(block)["type"]; -// -// switch (aType) { -// case 0: -// theBTB[set].push_back( -// BTBEntry(VirtualMemoryAddress(aPC), kNonBranch, VirtualMemoryAddress(aTarget))); -// break; -// case 1: -// theBTB[set].push_back( -// BTBEntry(VirtualMemoryAddress(aPC), kConditional, VirtualMemoryAddress(aTarget))); -// break; -// case 2: -// theBTB[set].push_back( -// BTBEntry(VirtualMemoryAddress(aPC), kUnconditional, VirtualMemoryAddress(aTarget))); -// break; -// case 3: -// theBTB[set].push_back(BTBEntry(VirtualMemoryAddress(aPC), kCall, VirtualMemoryAddress(aTarget))); -// break; -// case 4: -// theBTB[set].push_back( -// BTBEntry(VirtualMemoryAddress(aPC), kIndirectReg, VirtualMemoryAddress(aTarget))); -// break; -// case 5: -// theBTB[set].push_back( -// BTBEntry(VirtualMemoryAddress(aPC), kIndirectCall, VirtualMemoryAddress(aTarget))); -// break; -// case 6: -// theBTB[set].push_back(BTBEntry(VirtualMemoryAddress(aPC), kReturn, -// VirtualMemoryAddress(aTarget))); break; -// default: DBG_Assert(false, (<< "Don't know how to load type" << aType)); break; -// } -// } -// } -// } \ No newline at end of file + +void +BTB::loadState(json checkpoint) { + + for (size_t set = 0; set < (size_t)theBTBSets; set++) { + + size_t blockSize = checkpoint.at(set).size(); + + theBTB[set].invalidateAll(); + + for (size_t block = 0; block < blockSize; block++) { + uint64_t aPC = checkpoint.at(set).at(block)["PC"]; + uint64_t aTarget = checkpoint.at(set).at(block)["target"]; + uint8_t aType = checkpoint.at(set).at(block)["type"]; + + switch (aType) { + case 0: + theBTB[set].insert(BTBEntry(VirtualMemoryAddress(aPC), kNonBranch, VirtualMemoryAddress(aTarget))); + break; + case 1: + theBTB[set].insert(BTBEntry(VirtualMemoryAddress(aPC), kConditional, VirtualMemoryAddress(aTarget))); + break; + case 2: + theBTB[set].insert(BTBEntry(VirtualMemoryAddress(aPC), kUnconditional, VirtualMemoryAddress(aTarget))); + break; + case 3: + theBTB[set].insert(BTBEntry(VirtualMemoryAddress(aPC), kCall, VirtualMemoryAddress(aTarget))); + break; + case 4: + theBTB[set].insert(BTBEntry(VirtualMemoryAddress(aPC), kIndirectReg, VirtualMemoryAddress(aTarget))); + break; + case 5: + theBTB[set].insert(BTBEntry(VirtualMemoryAddress(aPC), kIndirectCall, VirtualMemoryAddress(aTarget))); + break; + case 6: + theBTB[set].insert(BTBEntry(VirtualMemoryAddress(aPC), kReturn, VirtualMemoryAddress(aTarget))); + break; + default: + //DBG_Assert(false, (<< "Don't know how to load type" << aType)); + break; + } + } + } +}; \ No newline at end of file diff --git a/components/BranchPredictor/BTB.hpp b/components/BranchPredictor/BTB.hpp index 5d3bbdfe..7d3e92ac 100644 --- a/components/BranchPredictor/BTB.hpp +++ b/components/BranchPredictor/BTB.hpp @@ -39,6 +39,7 @@ class BTB bool update(BranchFeedback const& aFeedback); json saveState() const; + void loadState(json checkpoint); }; #endif \ No newline at end of file diff --git a/components/BranchPredictor/BTBSet.cpp b/components/BranchPredictor/BTBSet.cpp index 1d563b7c..331cebba 100644 --- a/components/BranchPredictor/BTBSet.cpp +++ b/components/BranchPredictor/BTBSet.cpp @@ -72,4 +72,12 @@ BTBSet::invalidate(VirtualMemoryAddress anAddress) // TODO: Update replacementQueue for invalidation } } +} + +void +BTBSet::invalidateAll() +{ + for (uint32_t i = 0; i < blocks.size(); ++i) { + blocks[i].valid = false; + } } \ No newline at end of file diff --git a/components/BranchPredictor/BTBSet.hpp b/components/BranchPredictor/BTBSet.hpp index 034b5e24..30faf6c1 100644 --- a/components/BranchPredictor/BTBSet.hpp +++ b/components/BranchPredictor/BTBSet.hpp @@ -35,6 +35,8 @@ class BTBSet // [MADHUR] Invalidate entry if present void invalidate(VirtualMemoryAddress anAddress); + + void invalidateAll(); }; #endif \ No newline at end of file diff --git a/components/BranchPredictor/BranchPredictor.cpp b/components/BranchPredictor/BranchPredictor.cpp index 7193a361..1665da6e 100644 --- a/components/BranchPredictor/BranchPredictor.cpp +++ b/components/BranchPredictor/BranchPredictor.cpp @@ -157,7 +157,18 @@ BranchPredictor::feedback(VirtualMemoryAddress anAddress, } -void BranchPredictor::loadState(std::string const& aDirName) {} +void BranchPredictor::loadState(std::string const& aDirName) { + std::string fname(aDirName); + fname += "/bpred-" + boost::padded_string_cast<2, '0'>(theIndex) + ".json"; + std::ifstream ifs(fname.c_str()); + + json checkpoint; + ifs >> checkpoint; + + theBTB.loadState(checkpoint["btb"]); + theTage.loadState(checkpoint["tage"]); + ifs.close(); +} void BranchPredictor::saveState(std::string const& aDirName) { std::string fname(aDirName); diff --git a/components/BranchPredictor/TAGEImpl.hpp b/components/BranchPredictor/TAGEImpl.hpp index 45cd4de0..9e795f77 100644 --- a/components/BranchPredictor/TAGEImpl.hpp +++ b/components/BranchPredictor/TAGEImpl.hpp @@ -857,10 +857,10 @@ class PREDICTOR { json checkpoint; checkpoint["PWIN"] = PWIN; - checkpoint["tick"] = TICK; - checkpoint["seed"] = Seed; - checkpoint["phist"] = phist; - checkpoint["ghist"] = ghist.to_string(); + checkpoint["TICK"] = TICK; + checkpoint["SEED"] = Seed; + checkpoint["PHIST"] = phist; + checkpoint["GHIST"] = ghist.to_string(); checkpoint["LOGB"] = LOGB; checkpoint["NHIST"] = NHIST; checkpoint["LOGG"] = LOGG; @@ -930,9 +930,54 @@ class PREDICTOR { } void loadState(json checkpoint) { - } -}; -} // namespace SharedTypes + DBG_Assert(LOGB == checkpoint["LOGB"]); + DBG_Assert(NHIST == checkpoint["NHIST"]); + DBG_Assert(LOGG == checkpoint["LOGG"]); + DBG_Assert(TBITS == checkpoint["TBITS"]); + DBG_Assert(MAXHIST == checkpoint["MAXHIST"]); + DBG_Assert(MINHIST == checkpoint["MINHIST"]); + DBG_Assert(CBITS == checkpoint["CBITS"]); + + PWIN = checkpoint["PWIN"]; + TICK = checkpoint["TICK"]; + Seed = checkpoint["SEED"]; + phist = checkpoint["PHIST"]; + ghist = history_t(checkpoint["GHIST"].get()); + + // bimodal table + for (int i = 0; i < (1 << LOGB); i++) { + btable[i].hyst = checkpoint["btable"][i]["hyst"]; + btable[i].pred = checkpoint["btable"][i]["pred"]; + } + + for (int i = 0; i < NHIST; i++) { + for (int j = 0; j < (1 << LOGG); j++) { + gtable[i][j].ctr = checkpoint["gtable"][i][j]["ctr"]; + gtable[i][j].tag = checkpoint["gtable"][i][j]["tag"]; + gtable[i][j].ubit = checkpoint["gtable"][i][j]["ubit"]; + } + }; + + for (int i = 0; i < NHIST; i++) { + ch_i[i].comp = checkpoint["ch_i"][i]["comp"]; + ch_i[i].CLENGTH = checkpoint["ch_i"][i]["c_length"]; + ch_i[i].OLENGTH = checkpoint["ch_i"][i]["o_length"]; + } + + for (int j = 0; j < 2; j++) { + for (int i = 0; i < NHIST; i++) { + ch_t[j][i].comp = checkpoint["ch_t"][j][i]["comp"]; + ch_t[j][i].OLENGTH = checkpoint["ch_t"][j][i]["o_length"]; + ch_t[j][i].OUTPOINT = checkpoint["ch_t"][j][i]["out_point"]; + } + } + + for (int i = 0; i < NHIST; i++) { + m[i] = checkpoint["m"][i]; + } + }; +}; // namespace SharedTypes } // namespace Flexus +} #endif // PREDICTOR_H_SEEN \ No newline at end of file diff --git a/components/CMPCache/InfiniteDirectory.hpp b/components/CMPCache/InfiniteDirectory.hpp index bd137222..0fa672da 100644 --- a/components/CMPCache/InfiniteDirectory.hpp +++ b/components/CMPCache/InfiniteDirectory.hpp @@ -275,8 +275,10 @@ class InfiniteDirectory : public AbstractDirectory<_State, _EState> for (uint32_t i{0}; i < cache_size; i++) { uint64_t address = checkpoint.at(i)["tag"]; - std::bitset sharers ((uint64_t)checkpoint.at(i)["sharers"]); + std::bitset sharers (checkpoint.at(i)["sharers"].get()); + DBG_Assert(sharers.size() <= theNumSharers, (<< "Sharers size mismatch")); + // It's stupid but that's the only way to workaround this object SimpleDirectoryState state(theNumSharers); state = sharers; diff --git a/components/CMPCache/StdArray.hpp b/components/CMPCache/StdArray.hpp index 72f59d72..a0b0f615 100644 --- a/components/CMPCache/StdArray.hpp +++ b/components/CMPCache/StdArray.hpp @@ -672,8 +672,8 @@ class StdArray : public AbstractArray<_State> json checkpoint; ifs >> checkpoint; - uint8_t associativity = checkpoint["associativity"]; - uint32_t set_count = checkpoint["tags"].size(); + DBG_Assert((uint64_t)theAssociativity == checkpoint["associativity"]); + DBG_Assert((uint64_t)theNumSets == checkpoint["tags"].size()); for (int32_t i{0}; i < theNumSets; i++) { diff --git a/components/Cache/StdArray.hpp b/components/Cache/StdArray.hpp index e9727717..6393bb2b 100644 --- a/components/Cache/StdArray.hpp +++ b/components/Cache/StdArray.hpp @@ -527,6 +527,9 @@ class StdArray : public AbstractArray<_State> json checkpoint; is >> checkpoint; + DBG_Assert((uint64_t)theAssociativity == checkpoint["associativity"]); + DBG_Assert((uint64_t)setCount == checkpoint["tags"].size()); + for (int32_t i{0}; i < setCount; i++) { theSets[i]->load_set_from_ckpt(checkpoint, theIndex, i, theTagShift, setIndexShift); } diff --git a/components/FastCMPCache/InfiniteDirectory.cpp b/components/FastCMPCache/InfiniteDirectory.cpp index 1c1001c6..08097fd3 100644 --- a/components/FastCMPCache/InfiniteDirectory.cpp +++ b/components/FastCMPCache/InfiniteDirectory.cpp @@ -314,9 +314,8 @@ class InfiniteDirectory : public AbstractDirectory { for (; iter != theDirectory.end(); iter++) { uint64_t dirAddress = iter->second->address; - uint64_t sharers = iter->second->sharers.getSharers().to_ullong(); - - checkpoint[i++] = {{"tag", dirAddress}, {"sharers", sharers}}; + + checkpoint[i++] = {{"tag", dirAddress}, {"sharers", iter->second->sharers.getSharers().to_string()}}; DBG_(Trace, (<< "Directory saving block: " << dirAddress)); diff --git a/components/uFetch/uFetchImpl.cpp b/components/uFetch/uFetchImpl.cpp index a545168d..7ea41454 100644 --- a/components/uFetch/uFetchImpl.cpp +++ b/components/uFetch/uFetchImpl.cpp @@ -121,6 +121,9 @@ struct SimCache ifs >> checkpoint; uint32_t tag_shift = LOG2(theCache.sets()); + DBG_Assert((uint64_t)theCacheAssoc == checkpoint["associativity"]); + DBG_Assert((uint64_t)theCache.sets() == checkpoint["tags"].size()); + for (std::size_t i{0}; i < theCache.sets(); i++) { for (uint32_t j = 0; j < checkpoint["tags"].at(i).size(); j++) { bool dirty = checkpoint["tags"].at(i).at(j)["dirty"];