Compare commits

..

No commits in common. "1ae6af2eb68944af5791b3c8e322cf6049993f9b" and "1a9c1ccefb029e246fd1ffd718cf32c843550ff7" have entirely different histories.

7 changed files with 183 additions and 504 deletions

1
.gitignore vendored
View File

@ -7,6 +7,5 @@ build/
.gnupg .gnupg
.bash_history .bash_history
.cache/ .cache/
*.solution
compile_commands.json compile_commands.json
llvm/ llvm/

15
.vscode/launch.json vendored
View File

@ -4,21 +4,6 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{
"type": "lldb",
"request": "launch",
"name": "LLDB Unrolling",
"program": "/usr/bin/opt",
"args": [
"-load-pass-plugin",
"${workspaceFolder}/build/libCacheAnalysisPass.so",
"-passes=lru-misses",
"${workspaceFolder}/test/cnt.ll",
"-o",
"/dev/null"
],
"cwd": "${workspaceFolder}"
},
{ {
"type": "lldb", "type": "lldb",
"request": "launch", "request": "launch",

View File

@ -46,6 +46,52 @@ using namespace llvm;
// everything in an anonymous namespace. // everything in an anonymous namespace.
namespace { namespace {
std::string typeToName(Type::TypeID Id) {
switch (Id) {
case Type::TypeID::ArrayTyID:
return "ArrayTy";
case Type::TypeID::BFloatTyID:
return "BFloatTy";
case Type::TypeID::FloatTyID:
return "FloatTy";
case Type::TypeID::DoubleTyID:
return "DoubleTy";
case Type::TypeID::FixedVectorTyID:
return "FixedVectorTy";
case Type::TypeID::FP128TyID:
return "FP128Ty";
case Type::TypeID::FunctionTyID:
return "FunctionTy";
case Type::TypeID::HalfTyID:
return "HalfTy";
case Type::TypeID::IntegerTyID:
return "IntegerTy";
case Type::TypeID::LabelTyID:
return "LabelTy";
case Type::TypeID::MetadataTyID:
return "MetadataTy";
case Type::TypeID::PointerTyID:
return "PointerTy";
case Type::TypeID::PPC_FP128TyID:
return "PPC_FP128Ty";
case Type::TypeID::ScalableVectorTyID:
return "ScalableVectorTy";
case Type::TypeID::StructTyID:
return "StructTy";
case Type::TypeID::TokenTyID:
return "TokenTy";
case Type::TypeID::VoidTyID:
return "VoidTy";
case Type::TypeID::X86_AMXTyID:
return "X86_AMXTy";
case Type::TypeID::X86_FP80TyID:
return "X86_FP80Ty";
case Type::TypeID::X86_MMXTyID:
return "X86_MMXTy";
}
// should not reach here
return nullptr;
}
// New PM implementation // New PM implementation
struct CacheAnalysisPass : PassInfoMixin<CacheAnalysisPass> { struct CacheAnalysisPass : PassInfoMixin<CacheAnalysisPass> {
@ -56,7 +102,6 @@ struct CacheAnalysisPass : PassInfoMixin<CacheAnalysisPass> {
bool PrintEdgesPost = false; bool PrintEdgesPost = false;
bool DumpToDot = false; bool DumpToDot = false;
bool DumpNodes = false; bool DumpNodes = false;
bool LoopUnrolling = true;
// Assume a 4kB Cache // Assume a 4kB Cache
// with 16 Sets, associativity of 4 and Cachelines fitting two // with 16 Sets, associativity of 4 and Cachelines fitting two
@ -229,17 +274,15 @@ struct CacheAnalysisPass : PassInfoMixin<CacheAnalysisPass> {
if (PrintAddresses) if (PrintAddresses)
addressPrinter(F); addressPrinter(F);
} }
if(LoopUnrolling)
AC.unrollLoops();
AC.runMustAnalysis(EntryAddress);
if (DumpNodes)
AC.dumpNodes();
if (PrintEdgesPost) if (PrintEdgesPost)
AC.dumpEdges(); AC.dumpEdges();
if (DumpToDot) if (DumpToDot)
AC.dumpDotFile(); AC.dumpDotFile();
AC.fillAbstractCache(EntryAddress);
if (DumpNodes)
AC.dumpNodes();
outs() << "MustHits: " << AC.collectHits() << "\n"; outs() << "MustHits: " << AC.collectHits() << "\n";
//outs() << "MayMisses: " << AC.collectMisses() << "\n"; outs() << "MayMisses: " << AC.collectMisses() << "\n";
return PreservedAnalyses::all(); return PreservedAnalyses::all();
} }
}; };

View File

@ -111,30 +111,49 @@ case $1 in
docker run -i -d -v "$(pwd)"/.:/root:rw --name RTSAlab01 rtsalab01cacheanalysis docker run -i -d -v "$(pwd)"/.:/root:rw --name RTSAlab01 rtsalab01cacheanalysis
;; ;;
evaluation | eval) evaluation | eval)
run "crc" echo "Currently not available!"
echo "==== Correct crc ====" echo "But please continue to implement the must join,"
echo "MustHits: 90" echo "to the best of your abilities and check for updates!"
echo # run "fft1"
run "cnt" # echo "==== Correct fft1 ===="
echo "==== Correct cnt ====" # echo "MustHits: 16"
echo "MustHits: 28" # echo "MayMisses: 280"
echo # echo
run "duff" # run "bsort100"
echo "==== Correct duff ====" # echo "==== Correct bsort100 ===="
echo "MustHits: 78" # echo "MustHits: 1"
echo # echo "MayMisses: 41"
run "fft1" # echo
echo "==== Correct fft1 ====" # run "lms"
echo "MustHits: 74" # echo "==== Correct lms ===="
echo # echo "MustHits: 5"
run "insertsort" # echo "MayMisses: 288"
echo "==== Correct insertsort ====" # echo
echo "MustHits: 61" # run "minver"
echo # echo "==== Correct minver ===="
run "matmult" # echo "MustHits: 6"
echo "==== Correct matmult ====" # echo "MayMisses: 224"
echo "MustHits: 34" # echo
echo # run "qsort-exam"
# echo "==== Correct qsort-exam ===="
# echo "MustHits: 2"
# echo "MayMisses: 152"
# echo
# run "recursion"
# echo "==== Correct recursion ===="
# echo "MustHits: 8"
# echo "MayMisses: 8"
# echo
# run "select"
# echo "==== Correct select ===="
# echo "MustHits: 4"
# echo "MayMisses: 108"
# echo
# run "whet"
# echo "==== Correct whet ===="
# echo "MustHits: 5"
# echo "MayMisses: 265"
# echo
;; ;;
a | all) a | all)
clean clean

View File

@ -6,7 +6,6 @@
#include <cstddef> #include <cstddef>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <list>
#include <map> #include <map>
#include <ostream> #include <ostream>
#include <utility> #include <utility>
@ -45,362 +44,51 @@ public: // everything is public, because IDGAF
Nodes[Suc].Predecessors.push_back(Pre); Nodes[Suc].Predecessors.push_back(Pre);
} }
/** void addEmptyNode(unsigned int NodeAddr) {
* @brief Add an Edge to the AbstractStateGraph Nodes[NodeAddr] = AbstractState(NodeAddr);
*
* @param Pre
* @param Suc
*/
void removeEdge(unsigned int Pre, unsigned int Suc) {
Edges[Pre].remove(Suc);
Nodes[Pre].Successors.remove(Suc);
Nodes[Suc].Predecessors.remove(Pre);
} }
/** void fillAbstractCache(unsigned int NodeNr) {
* @brief Add an Empty node @NodeAddr Nodes[NodeNr].Computed = true;
*
* @param NodeAddr
* @return unsigned int
*/
unsigned int addEmptyNode(unsigned int NodeAddr) {
int I = Nodes.size();
Nodes[I] = AbstractState(NodeAddr);
return I;
}
/**
* @brief Returns True if a path From -> To exists.
*
* @param From
* @param To
* @return true
* @return false
*/
bool findPath(unsigned int From, unsigned int To) {
std::map<unsigned int, bool> Visited;
Visited[From] = false;
bool Ret = false;
for (auto Visitor : Visited) {
if (!Visitor.second) {
for (unsigned int Next : Edges[Visitor.first]) {
if (Next == To) {
return true;
}
Visited[Next] = false;
}
}
Visited[Visitor.first] = true;
}
return false;
}
/**
* @brief Removes all Nested loops from the handed LoopBody
*
* @param LoopBodyIn
* @param OrigNodeToUnrolledNode
*/
void removeNestedLoops(
std::list<unsigned int> LoopBodyIn,
std::map<unsigned int, unsigned int> OrigNodeToUnrolledNode) {
unsigned int LoopHead = LoopBodyIn.front();
unsigned int LoopTail = LoopBodyIn.back();
unsigned int NestLoopTail;
for (unsigned int NodeNr : LoopBodyIn) {
bool IsLoopHead = false;
bool FoundLoopBody = false;
unsigned int LoopBodySize = 0;
int NestLoopHead = 0;
NestLoopHead = NodeNr;
if (Nodes[NodeNr].Predecessors.size() > 1) {
IsLoopHead = true;
FoundLoopBody = false;
LoopBodySize++;
// is loop head?
for (unsigned int Pre : Nodes[NodeNr].Predecessors) {
if (Pre > NodeNr) {
// Might be loop head.
// check if all States between Pre and NodeNr are a coherent set.
for (unsigned int I = NodeNr; I < Pre; I++) {
// Check if all out going edges are in the set
for (unsigned int Succ : Nodes[I].Successors) {
if (Succ > Pre) {
// Set is not coherent
IsLoopHead = false;
break;
}
}
// check if all incoming edges are in the set.
if (IsLoopHead && I != NodeNr)
for (unsigned int Pred : Nodes[I].Predecessors) {
if (Pred < NodeNr) {
// Set is not coherent
IsLoopHead = false;
break;
}
}
FoundLoopBody = true;
LoopBodySize++;
}
NestLoopTail = Pre;
} else if (!FoundLoopBody) {
// If no coherent Loopbody exist we cannot unroll.
NestLoopHead = 0;
IsLoopHead = false;
}
if (FoundLoopBody) {
// Check if a Path between Head and Tail exists,
// if not its not a loop.
if (findPath(NestLoopHead, NestLoopTail))
removeEdge(OrigNodeToUnrolledNode[NestLoopTail],
OrigNodeToUnrolledNode[NestLoopHead]);
}
}
}
}
}
/**
* @brief Unroll Loops.
*
* @param NodeNr
*/
void unrollLoops() {
unsigned int NestedBorder = 0;
unsigned int LastNode = Nodes.size();
unsigned int IterationCounter = 0;
for (std::pair<const unsigned int, AbstractState> NodePair : Nodes) {
IterationCounter++;
if (NodePair.first == LastNode) {
break;
}
unsigned int NodeNr = NodePair.first;
// Don't unroll nested loops
if (NodeNr < NestedBorder)
continue;
bool IsLoopHead = false;
bool FoundLoopBody = false;
bool Verbose = false;
std::list<unsigned int> LoopBody;
std::list<unsigned int> AdditionalLoopTails;
if (Nodes[NodeNr].Predecessors.size() > 1) {
IsLoopHead = true;
// is loop head?
for (unsigned int Pre : Nodes[NodeNr].Predecessors) {
if (Pre > NodeNr) {
// Might be loop head.
// check if all States between Pre and NodeNr are a coherent set.
for (unsigned int I = NodeNr; I < Pre; I++) {
// Check if all out going edges are in the set
for (unsigned int Succ : Nodes[I].Successors) {
for (unsigned int PreI : Nodes[I].Predecessors) {
// Handle if we have multiple Loopheads.
if (PreI >= Pre && I != NodeNr) {
// I and Pre are Looptail.
{
if (std::find(AdditionalLoopTails.begin(),
AdditionalLoopTails.end(),
I) == AdditionalLoopTails.end()) {
AdditionalLoopTails.push_back(I);
break;
}
}
}
if (std::find(LoopBody.begin(), LoopBody.end(), I) ==
LoopBody.end())
LoopBody.push_back(I);
if (Succ > Pre) {
// Set is not coherent
IsLoopHead = false;
break;
}
}
}
// check if all incoming edges are in the set.
if (IsLoopHead && I != NodeNr)
for (unsigned int Pred : Nodes[I].Predecessors) {
if (Pred < NodeNr) {
// Set is not coherent
IsLoopHead = false;
break;
}
}
FoundLoopBody = true;
}
LoopBody.push_back(Pre);
} else if (!FoundLoopBody) {
// If no coherent Loopbody exist we cannot unroll.
LoopBody.clear();
IsLoopHead = false;
}
}
}
// Found Loop Head and Body!
// Add empty unrolled Nodes
// Map points from OrigNode To Unrolled Node.
if (FoundLoopBody) {
std::map<unsigned int, unsigned int> OrigNodeToUnrolledNode;
for (unsigned int Node : LoopBody) {
// Node to unroll
AbstractState UnrolledNode(Nodes[Node]);
UnrolledNode.setUnrolled(1);
unsigned int I = Nodes.size();
Nodes[I] = UnrolledNode;
OrigNodeToUnrolledNode[Node] = I;
assert(Nodes[OrigNodeToUnrolledNode[Node]].Unrolled == 1);
assert(Nodes[Node].Addr == Nodes[OrigNodeToUnrolledNode[Node]].Addr);
}
// LoopTail and Head have to be processed different
unsigned int LoopTail = LoopBody.back();
LoopBody.pop_back();
NestedBorder = LoopTail;
unsigned int LoopHead = LoopBody.front();
LoopBody.pop_front();
// Find State entering to LoopHead ()
unsigned int LoopHeadEntry = 0;
for (unsigned int Pre : Nodes[LoopHead].Predecessors) {
if (Pre < LoopHead) {
LoopHeadEntry = Pre;
break;
}
}
// Make LoopHeadEntry point to unrolled state instead of the loop.
addEdge(LoopHeadEntry, OrigNodeToUnrolledNode[LoopHead]);
removeEdge(LoopHeadEntry, LoopHead);
// Connect unrolled Loop to the the original Loop.
if (AdditionalLoopTails.size() == 0)
addEdge(OrigNodeToUnrolledNode[LoopTail], LoopHead);
for (auto Tail : AdditionalLoopTails)
addEdge(OrigNodeToUnrolledNode[Tail], LoopHead);
// Fix all other states
addEdge(OrigNodeToUnrolledNode[LoopBody.back()],
OrigNodeToUnrolledNode[LoopTail]);
for (unsigned int Node : LoopBody) {
for (unsigned int Pre : Nodes[Node].Predecessors) {
// if (std::find(LoopBody.begin(), LoopBody.end(), Pre) !=
// LoopBody.end())
// Add All predecessors and successors to unrolled Nodes
addEdge(OrigNodeToUnrolledNode[Pre], OrigNodeToUnrolledNode[Node]);
}
}
// Remove Nested loops in unrolled loop
removeNestedLoops(LoopBody, OrigNodeToUnrolledNode);
if (Verbose && FoundLoopBody) {
llvm::outs() << "Found LoopHead @: " << NodeNr << "\n";
llvm::outs() << "With LoopTail @: " << LoopTail << "\n";
llvm::outs() << "With Body: {\n";
int I = 1;
for (auto Node : LoopBody) {
llvm::outs() << Node << ", ";
if (!(I++ % 5)) {
llvm::outs() << "\n";
}
}
llvm::outs() << "}\n";
llvm::outs() << "Unrolled States: {\n";
I = 1;
for (auto Node : LoopBody) {
llvm::outs() << OrigNodeToUnrolledNode[Node] << ", ";
if (!(I++ % 5)) {
llvm::outs() << "\n";
}
}
llvm::outs() << "}\n";
I = 1;
llvm::outs() << "OrigNodeToUnrolledNode: {\n";
for (auto Nr : OrigNodeToUnrolledNode) {
llvm::outs() << Nr.first << "->" << Nr.second << ", ";
if (!(I++ % 3))
llvm::outs() << "\n";
}
llvm::outs() << "}\n";
}
}
}
return;
}
/**
* @brief Perform must analysis in the Graph
*
* @param NodeNr
*/
void runMustAnalysis(unsigned int NodeNr) {
// Join and call until the state converges.
Nodes[NodeNr].Computed++;
// fill all Successors, if filled Already join.
for (unsigned int SuccNr : Nodes[NodeNr].Successors) { for (unsigned int SuccNr : Nodes[NodeNr].Successors) {
if (Nodes[SuccNr].Filled) { Nodes[SuccNr];
// Join Successor with current State and its Address if (Nodes[SuccNr].Computed) {
Nodes[SuccNr].mustJoin( // Join don't call
AbstractState(Nodes[NodeNr], Address(Nodes[NodeNr].Addr))); Nodes[SuccNr].mustJoin(Nodes[NodeNr]);
Nodes[SuccNr].mustJoin(AbstractState(NodeNr));
} else { } else {
// Fill Successor with current State and its Address // Update and fill Succ
Nodes[SuccNr].fill(Nodes[NodeNr], Address(Nodes[NodeNr].Addr)); Nodes[SuccNr].fill(Nodes[NodeNr], NodeNr);
// first Fill, so set Filled fillAbstractCache(SuccNr);
Nodes[SuccNr].Filled = true;
}
// Continue Filling CFG on Successors.
for (unsigned int SuccNr : Nodes[NodeNr].Successors) {
// We can use this as we can safely assume a State has at most two successors.
// Due to branch instruction in llvmIR
if (Nodes[NodeNr].Computed > 2)
continue;
runMustAnalysis(SuccNr);
} }
} }
return; return;
} }
/**
* @brief Return number of measured Hits
*
* @return unsigned int
*/
unsigned int collectHits() { unsigned int collectHits() {
unsigned int Hits = 0; unsigned int Hits = 0;
for (auto const &E : Edges) { for (auto const &E : Edges) {
auto Predecessor = Nodes[E.first]; auto Predecessor = Nodes[E.first];
for (unsigned int SuccessorAddr : E.second) { for (unsigned int SuccessorAddr : E.second) {
// When successors Address is in predecessor, we have a Hit. // When successors Address is in predecessor, we have a Hit.
Hits += Predecessor.isHit(Address(Nodes[SuccessorAddr].Addr)) ? 1 : 0; Hits += Predecessor.isHit(Address(SuccessorAddr)) ? 1 : 0;
} }
} }
return Hits; return Hits;
} }
/**
* @brief Return number of measured Misses
*
* @return unsigned int
*/
unsigned int collectMisses() { unsigned int collectMisses() {
unsigned int Misses = 0; unsigned int Misses = 0;
for (auto const &E : Edges) { for (auto const &E : Edges) {
auto Predecessor = Nodes[E.first]; auto Predecessor = Nodes[E.first];
for (unsigned int SuccessorAddr : E.second) { for (unsigned int SuccessorAddr : E.second) {
// When successors Address is in predecessor, we have a Hit. // When successors Address is in predecessor, we have a Hit.
Misses += Predecessor.isHit(Address(Nodes[SuccessorAddr].Addr)) ? 0 : 1; Misses += Predecessor.isHit(Address(SuccessorAddr)) ? 0 : 1;
} }
} }
return Misses; return Misses;
} }
/**
* @brief Prints all Edges to Console
*
*/
void dumpEdges() { void dumpEdges() {
llvm::outs() << "Dumping Edges:\n"; llvm::outs() << "Dumping Edges:\n";
for (auto const &E : Edges) { for (auto const &E : Edges) {
@ -418,38 +106,20 @@ public: // everything is public, because IDGAF
} }
} }
/**
* @brief Dumps the Graph to a out.dot file
*
*/
void dumpDotFile() { void dumpDotFile() {
bool PrintOld = true;
std::ofstream DotFile; std::ofstream DotFile;
DotFile.open("out.dot"); DotFile.open("out.dot");
DotFile << "digraph g {" DotFile << "digraph g {"
<< "\n"; << "\n";
for (auto const &E : Edges) { for (auto const &E : Edges) {
for (unsigned int To : E.second) { for (unsigned int To : E.second) {
if (PrintOld) { DotFile << E.first << " -> " << To << "\n";
DotFile << E.first << " -> " << To << "\n";
if (Nodes[E.first].Unrolled) {
DotFile << E.first << " [color = red]\n";
}
} else {
DotFile << Nodes[E.first].Addr << "." << Nodes[E.first].Unrolled
<< " -> " << Nodes[To].Addr << "." << Nodes[To].Unrolled
<< "\n";
}
} }
} }
DotFile << "}\n"; DotFile << "}\n";
DotFile.close(); DotFile.close();
} }
/**
* @brief Prints all nodes to Console
*
*/
void dumpNodes() { void dumpNodes() {
for (auto const &E : Edges) { for (auto const &E : Edges) {
Nodes[E.first].dump(); Nodes[E.first].dump();

View File

@ -1,7 +1,6 @@
#ifndef ABSSTATE_H #ifndef ABSSTATE_H
#define ABSSTATE_H #define ABSSTATE_H
#include <algorithm>
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
#include <cstdlib> #include <cstdlib>
@ -28,10 +27,8 @@ public: // everything is public, because IDGAF
std::list<unsigned int> Predecessors; std::list<unsigned int> Predecessors;
unsigned int Addr; unsigned int Addr;
unsigned int Unrolled;
int Computed = 0; bool Computed = false;
bool Filled = false;
// Only entries below this comment are needed for the exercise. // Only entries below this comment are needed for the exercise.
@ -60,8 +57,6 @@ public: // everything is public, because IDGAF
std::map<unsigned int, Set> Sets; std::map<unsigned int, Set> Sets;
AbstractState(AbstractState const &Copy) { AbstractState(AbstractState const &Copy) {
Addr = Copy.Addr;
Unrolled = Copy.Unrolled;
for (auto S : Copy.Sets) { for (auto S : Copy.Sets) {
unsigned int SetNr = S.first; unsigned int SetNr = S.first;
for (auto E : S.second.Associativity) { for (auto E : S.second.Associativity) {
@ -73,61 +68,12 @@ public: // everything is public, because IDGAF
} }
} }
AbstractState(AbstractState const &Copy, Address Update) {
Addr = Copy.Addr;
Unrolled = Copy.Unrolled;
for (auto S : Copy.Sets) {
unsigned int SetNr = S.first;
for (auto E : S.second.Associativity) {
unsigned int Age = E.first;
for (auto B : E.second.Blocks) {
Sets[SetNr].Associativity[Age].Blocks.push_back(B);
}
}
}
this->update(Update);
}
AbstractState() {} AbstractState() {}
AbstractState(unsigned int AddressIn) { AbstractState(unsigned int AddressIn) { Addr = AddressIn; }
Addr = AddressIn;
Unrolled = 0;
}
AbstractState(unsigned int AddressIn, unsigned int UnrolledIn) { AbstractState(Address Addr) {
Addr = AddressIn; Sets[Addr.Index].Associativity[0] = {{Addr.Tag}};
Unrolled = UnrolledIn;
}
// AbstractState(Address Addr) {
// Sets[Addr.Index].Associativity[0] = {{Addr.Tag}};
// }
void setUnrolled(unsigned int In) { Unrolled = In; }
bool operator==(AbstractState In) {
for (int Index; Index < 16; Index++) {
for (int Age; Age < 4; Age++) {
for (auto E1 : Sets[Index].Associativity[Age].Blocks) {
// find E1 in In States Set and Age.
if (std::find(In.Sets[Index].Associativity[Age].Blocks.begin(),
In.Sets[Index].Associativity[Age].Blocks.end(),
E1) == In.Sets[Index].Associativity[Age].Blocks.end()) {
return false;
}
}
for (auto E2 : In.Sets[Index].Associativity[Age].Blocks) {
// find E2 in This Set and Age.
if (std::find(Sets[Index].Associativity[Age].Blocks.begin(),
Sets[Index].Associativity[Age].Blocks.end(),
E2) == Sets[Index].Associativity[Age].Blocks.end()) {
return false;
}
}
}
}
return true;
} }
/** /**
@ -165,34 +111,22 @@ public: // everything is public, because IDGAF
* @param Addr , Address * @param Addr , Address
*/ */
void update(Address Addr) { void update(Address Addr) {
// If Updated Address is of Age 0 do nothing
if (std::find(Sets[Addr.Index].Associativity[0].Blocks.begin(),
Sets[Addr.Index].Associativity[0].Blocks.end(),
Addr.Tag) != Sets[Addr.Index].Associativity[0].Blocks.end())
return;
// This loopages all entries by one. 3 <-2, 2<-1, 1<-0
for (int I = 3; I > 0; I--) { for (int I = 3; I > 0; I--) {
Sets[Addr.Index].Associativity[I] = Sets[Addr.Index].Associativity[I - 1]; Sets[Addr.Index].Associativity[I] = Sets[Addr.Index].Associativity[I - 1];
Sets[Addr.Index].Associativity[I].Blocks.remove(Addr.Tag);
} }
// entry at age 0 is updated with current address.
Sets[Addr.Index].Associativity[0].Blocks = {Addr.Tag}; Sets[Addr.Index].Associativity[0].Blocks = {Addr.Tag};
} }
/** /**
* @brief Fills the AbstractState PreState and updates with PreAddress. * @brief Updates the AbstractState with given AbstractState
* *
* @param PreState, State that fills this state. * @param UpdateState, State that gets merged into State with Age+1.
*
* @param PreAddr Address of PreState
*/ */
void fill(AbstractState PreState, Address PreAddr) { void update(AbstractState UpdateState) {
bool Verbose = false; for (auto S : UpdateState.Sets) {
// copy Pre State into this.
for (auto S : PreState.Sets) {
unsigned int Index = S.first; unsigned int Index = S.first;
for (auto E : S.second.Associativity) { for (auto E : S.second.Associativity) {
unsigned int Age = E.first; unsigned int Age = E.first + 1;
// If updated age is greater 4 The Tag is no longer in Cache. // If updated age is greater 4 The Tag is no longer in Cache.
// Due to associativity of 4 per set. // Due to associativity of 4 per set.
if (Age >= 4) if (Age >= 4)
@ -202,24 +136,34 @@ public: // everything is public, because IDGAF
} }
} }
} }
if (Verbose) { }
llvm::outs() << "Before:\n";
this->dump(); /**
} * @brief Fills the AbstractState PreState and PreAddress.
// update this with PreAddr *
this->update(PreAddr); * @param PreState, State that fills this state.
if (Verbose) { *
llvm::outs() << "Update Tag: " << PreAddr.Tag << "\n"; * @param PreAddr Address of PreState
llvm::outs() << "Update Set: " << PreAddr.Index << "\n"; */
llvm::outs() << "After:\n"; void fill(AbstractState PreState, Address PreAddr) {
this->dump(); for (auto S : PreState.Sets) {
unsigned int Index = S.first;
for (auto E : S.second.Associativity) {
unsigned int Age = E.first + 1;
// If updated age is greater 4 The Tag is no longer in Cache.
// Due to associativity of 4 per set.
if (Age >= 4)
break;
for (auto B : E.second.Blocks) {
Sets[Index].Associativity[Age].Blocks.push_back(B);
}
}
} }
Sets[PreAddr.Index].Associativity[0].Blocks.push_back(PreAddr.Tag);
} }
void dump() { void dump() {
llvm::outs() << Addr << " {\n"; llvm::outs() << Addr << " {\n";
llvm::outs() << "Unrolled: " << Unrolled << "\n";
llvm::outs() << "Computed: " << Computed << "\n";
llvm::outs() << "Predecessors: "; llvm::outs() << "Predecessors: ";
for (auto PreNr : Predecessors) { for (auto PreNr : Predecessors) {
llvm::outs() << PreNr << " "; llvm::outs() << PreNr << " ";

View File

@ -145,30 +145,49 @@ case $1 in
docker run -i -d -v "$(pwd)"/.:/root:rw --name RTSAlab01 rtsalab01cacheanalysis docker run -i -d -v "$(pwd)"/.:/root:rw --name RTSAlab01 rtsalab01cacheanalysis
;; ;;
evaluation | eval) evaluation | eval)
run "crc" echo "Currently not available!"
echo "==== Correct crc ====" echo "But please continue to implement the must join,"
echo "MustHits: 90" echo "to the best of your abilities and check for updates!"
echo # run "fft1"
run "cnt" # echo "==== Correct fft1 ===="
echo "==== Correct cnt ====" # echo "MustHits: 16"
echo "MustHits: 28" # echo "MayMisses: 280"
echo # echo
run "duff" # run "bsort100"
echo "==== Correct duff ====" # echo "==== Correct bsort100 ===="
echo "MustHits: 78" # echo "MustHits: 1"
echo # echo "MayMisses: 41"
run "fft1" # echo
echo "==== Correct fft1 ====" # run "lms"
echo "MustHits: 74" # echo "==== Correct lms ===="
echo # echo "MustHits: 5"
run "insertsort" # echo "MayMisses: 288"
echo "==== Correct insertsort ====" # echo
echo "MustHits: 61" # run "minver"
echo # echo "==== Correct minver ===="
run "matmult" # echo "MustHits: 6"
echo "==== Correct matmult ====" # echo "MayMisses: 224"
echo "MustHits: 34" # echo
echo # run "qsort-exam"
# echo "==== Correct qsort-exam ===="
# echo "MustHits: 2"
# echo "MayMisses: 152"
# echo
# run "recursion"
# echo "==== Correct recursion ===="
# echo "MustHits: 8"
# echo "MayMisses: 8"
# echo
# run "select"
# echo "==== Correct select ===="
# echo "MustHits: 4"
# echo "MayMisses: 108"
# echo
# run "whet"
# echo "==== Correct whet ===="
# echo "MustHits: 5"
# echo "MayMisses: 265"
# echo
;; ;;
a | all) a | all)
clean clean