Compare commits
16 Commits
42b533434b
...
15d236299d
Author | SHA1 | Date |
---|---|---|
Mukendi Mputu | 15d236299d | |
Mukendi Mputu | 2f682920f7 | |
Nils Hölscher | 2ab71cf95d | |
Nils Hölscher | 13861282b4 | |
Nils Hölscher | 623818d49e | |
Nils Hölscher | 841dbe1070 | |
Nils Hölscher | 9dca6c2f67 | |
Nils Hölscher | 801831a2b5 | |
Nils Hölscher | f818f3847a | |
Nils Hölscher | e40e6b7893 | |
Nils Hölscher | 2cdcace84b | |
Nils Hölscher | 3264029256 | |
Nils Hölscher | 8ea0c571e4 | |
Nils Hölscher | 0d09aa9e45 | |
Nils Hölscher | 7635fb52c7 | |
Nils Hölscher | e7ca0a68ef |
|
@ -0,0 +1,11 @@
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: llvmta-build
|
||||||
|
steps:
|
||||||
|
- name: Build
|
||||||
|
image: ls12-nvm-oma1:5000/cppdev
|
||||||
|
commands:
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DLT_LLVM_INSTALL_DIR=/usr ..
|
||||||
|
- ninja -j 2
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/clang",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++14",
|
||||||
|
"intelliSenseMode": "linux-clang-x64",
|
||||||
|
"compileCommands": "${workspaceFolder}/build/compile_commands.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
|
@ -4,21 +4,21 @@
|
||||||
// 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",
|
// "type": "lldb",
|
||||||
"request": "launch",
|
// "request": "launch",
|
||||||
"name": "LLDB Unrolling",
|
// "name": "LLDB Unrolling",
|
||||||
"program": "/usr/bin/opt",
|
// "program": "/usr/bin/opt",
|
||||||
"args": [
|
// "args": [
|
||||||
"-load-pass-plugin",
|
// "-load-pass-plugin",
|
||||||
"${workspaceFolder}/build/libCacheAnalysisPass.so",
|
// "${workspaceFolder}/build/libCacheAnalysisPass.so",
|
||||||
"-passes=lru-misses",
|
// "-passes=lru-misses",
|
||||||
"${workspaceFolder}/test/cnt.ll",
|
// "${workspaceFolder}/test/cnt.ll",
|
||||||
"-o",
|
// "-o",
|
||||||
"/dev/null"
|
// "/dev/null"
|
||||||
],
|
// ],
|
||||||
"cwd": "${workspaceFolder}"
|
// "cwd": "${workspaceFolder}"
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
"type": "lldb",
|
"type": "lldb",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
|
|
|
@ -1,6 +1,19 @@
|
||||||
cmake_minimum_required(VERSION 3.13.4)
|
cmake_minimum_required(VERSION 3.13.4)
|
||||||
project(RTSA-lab01-CacheAnalysis)
|
project(RTSA-lab01-CacheAnalysis)
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
# 0. Add GoogleTest
|
||||||
|
#===============================================================================
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(
|
||||||
|
googletest
|
||||||
|
URL
|
||||||
|
URL https://github.com/google/googletest/archive/refs/heads/main.zip
|
||||||
|
)
|
||||||
|
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||||
|
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||||
|
FetchContent_MakeAvailable(googletest)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# 1. VERIFY LLVM INSTALLATION DIR
|
# 1. VERIFY LLVM INSTALLATION DIR
|
||||||
# This is just a bit of a sanity checking.
|
# This is just a bit of a sanity checking.
|
||||||
|
@ -108,4 +121,5 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
|
||||||
# available for the sub-projects.
|
# available for the sub-projects.
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
add_subdirectory(CacheAnalysisPass) # Use your pass name here.
|
add_subdirectory(CacheAnalysisPass) # Use your pass name here.
|
||||||
|
add_subdirectory(UnitTest)
|
||||||
#add_subdirectory(lib)
|
#add_subdirectory(lib)
|
|
@ -56,7 +56,7 @@ struct CacheAnalysisPass : PassInfoMixin<CacheAnalysisPass> {
|
||||||
bool PrintEdgesPost = false;
|
bool PrintEdgesPost = false;
|
||||||
bool DumpToDot = false;
|
bool DumpToDot = false;
|
||||||
bool DumpNodes = false;
|
bool DumpNodes = false;
|
||||||
bool LoopUnrolling = false;
|
bool LoopUnrolling = true;
|
||||||
|
|
||||||
// Assume a 4kB Cache
|
// Assume a 4kB Cache
|
||||||
// with 16 Sets, associativity of 4 and Cachelines fitting two times the instruction size
|
// with 16 Sets, associativity of 4 and Cachelines fitting two times the instruction size
|
||||||
|
@ -215,15 +215,15 @@ struct CacheAnalysisPass : PassInfoMixin<CacheAnalysisPass> {
|
||||||
}
|
}
|
||||||
|
|
||||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM) {
|
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM) {
|
||||||
FunctionAnalysisManager &FAM =
|
// FunctionAnalysisManager &FAM =
|
||||||
MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
|
// MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
|
||||||
|
|
||||||
addressCollector(M);
|
addressCollector(M);
|
||||||
Function *EntryFunction;
|
// Function *EntryFunction;
|
||||||
for (Function &F : M.getFunctionList()) {
|
for (Function &F : M.getFunctionList()) {
|
||||||
// Start iterating through CFG from entry point
|
// Start iterating through CFG from entry point
|
||||||
if (F.getName().equals(EntryPoint)) {
|
if (F.getName().equals(EntryPoint)) {
|
||||||
EntryFunction = &F;
|
// EntryFunction = &F;
|
||||||
initEdges(F);
|
initEdges(F);
|
||||||
}
|
}
|
||||||
if (PrintAddresses)
|
if (PrintAddresses)
|
||||||
|
|
19
README.md
19
README.md
|
@ -1,10 +1,18 @@
|
||||||
# RTSA-lab01-CacheAnalysis
|
# RTSA-lab01-CacheAnalysis
|
||||||
|
|
||||||
|
[![Build Status](http://129.217.34.203/api/badges/nils.hoelscher/RTSA-lab01-CacheAnalysis/status.svg)](http://129.217.34.203/nils.hoelscher/RTSA-lab01-CacheAnalysis)
|
||||||
|
|
||||||
In this lab session you will learn how to implement a LRU cache in abstract representation.
|
In this lab session you will learn how to implement a LRU cache in abstract representation.
|
||||||
The Goal is to implement an LRU must Join in include/AbstractState.h.
|
|
||||||
For this we assume a "Set-Associative LRU Cache", with 16 sets an associativity of 4 and a cacheline size of two times instruction size.
|
## Exercise
|
||||||
|
Implement a LRU Must-Join as described in the lecture, WCET - Cache Analysis.
|
||||||
|
A 16 SetCache with an associativity of 4 Assumed, and cache lines can hold two memory words -> CacheSize 1024kB.
|
||||||
|
In order to do so, complete the function "mustJoin" inside [include/AbstractState.h:138](https://git.cs.tu-dortmund.de/nils.hoelscher/RTSA-lab01-CacheAnalysis/src/branch/master/include/AbstractState.h#L138).
|
||||||
|
The goal is to join the inbound state into the "this" state.
|
||||||
|
|
||||||
|
|
||||||
The Project can be build, tested and Evaluated with the "helper" script.
|
The Project can be build, tested and Evaluated with the "helper" script.
|
||||||
|
The Setup and some nice to knows are described in the following sections.
|
||||||
|
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
|
|
||||||
|
@ -82,6 +90,7 @@ This is my personally preferred IDE setup for C/C++ and by no means needed to ac
|
||||||
clangd,
|
clangd,
|
||||||
Clang-Format,
|
Clang-Format,
|
||||||
CodeLLDB,
|
CodeLLDB,
|
||||||
|
C++ TestMate,
|
||||||
Docker and
|
Docker and
|
||||||
Remote Development
|
Remote Development
|
||||||
|
|
||||||
|
@ -145,6 +154,12 @@ You can also set the following variables in the CacheAnalysisPass/CacheAnalysisP
|
||||||
|
|
||||||
Helpful to understand what the program does but not very so much for the actual exercise.
|
Helpful to understand what the program does but not very so much for the actual exercise.
|
||||||
|
|
||||||
|
## UnitTest
|
||||||
|
|
||||||
|
The best way to see what your function does is to use the [UnitTest.cpp](https://git.cs.tu-dortmund.de/nils.hoelscher/RTSA-lab01-CacheAnalysis/src/branch/master/UnitTest/UnitTest.cpp).
|
||||||
|
With "C++ TestMate" install you can simply run or debug the test from the side panel in VS Code (Flask Icon).
|
||||||
|
The "C++ TestMate" is not installed in the VM as I just added this feature now.
|
||||||
|
Please feel free to add more test cases to your liking in [UnitTest.cpp](https://git.cs.tu-dortmund.de/nils.hoelscher/RTSA-lab01-CacheAnalysis/src/branch/master/UnitTest/UnitTest.cpp).
|
||||||
## Use the Helper script
|
## Use the Helper script
|
||||||
|
|
||||||
Again if you work on a Pool PC use poolhelper.sh insted of the helper.sh script.
|
Again if you work on a Pool PC use poolhelper.sh insted of the helper.sh script.
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
cmake_minimum_required(VERSION 3.13.4)
|
||||||
|
project(UnitTest)
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
# 1. LOAD LLVM CONFIGURATION
|
||||||
|
#===============================================================================
|
||||||
|
# Set this to a valid LLVM installation dir
|
||||||
|
set(LT_LLVM_INSTALL_DIR "" CACHE PATH "LLVM installation directory")
|
||||||
|
|
||||||
|
# Add the location of LLVMConfig.cmake to CMake search paths (so that
|
||||||
|
# find_package can locate it)
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH "${LT_LLVM_INSTALL_DIR}/lib/cmake/llvm/")
|
||||||
|
|
||||||
|
# FIXME: This is a warkaround for #25. Remove once resolved and use
|
||||||
|
# find_package(LLVM 11.0.0 REQUIRED CONFIG) instead.
|
||||||
|
find_package(LLVM REQUIRED CONFIG)
|
||||||
|
|
||||||
|
# UnitTest includes headers from LLVM - update the include paths accordingly
|
||||||
|
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}, "${CMAKE_CURRENT_SOURCE_DIR}/../include")
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
# 2. LLVM-TUTOR BUILD CONFIGURATION
|
||||||
|
#===============================================================================
|
||||||
|
# Use the same C++ standard as LLVM does
|
||||||
|
set(CMAKE_CXX_STANDARD 14 CACHE STRING "")
|
||||||
|
|
||||||
|
# LLVM is normally built without RTTI. Be consistent with that.
|
||||||
|
if(NOT LLVM_ENABLE_RTTI)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
# 3. ADD THE TARGET
|
||||||
|
#===============================================================================
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
add_executable(UnitTest
|
||||||
|
# List your source files here.
|
||||||
|
UnitTest.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Allow undefined symbols in shared objects on Darwin (this is the default
|
||||||
|
# behaviour on Linux)
|
||||||
|
target_link_libraries(UnitTest
|
||||||
|
"$<$<PLATFORM_ID:Darwin>:-undefined dynamic_lookup>")
|
||||||
|
target_link_libraries(
|
||||||
|
UnitTest
|
||||||
|
gtest_main
|
||||||
|
)
|
||||||
|
include(GoogleTest)
|
||||||
|
gtest_discover_tests(UnitTest)
|
|
@ -0,0 +1,174 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "../include/AbstractCache.h"
|
||||||
|
|
||||||
|
void fillSet(AbstractState &In, unsigned int Set) {
|
||||||
|
for (int I = 0; I < 4; I++) {
|
||||||
|
In.Sets[Set].Associativity[I].Blocks.push_front(I);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Joined Set should remain the same
|
||||||
|
TEST(MustJoinTests, MustJoinSameStates) {
|
||||||
|
AbstractCache AC;
|
||||||
|
AC.addEmptyNode(0);
|
||||||
|
fillSet(AC.Nodes[0], 0);
|
||||||
|
AC.addEmptyNode(1);
|
||||||
|
fillSet(AC.Nodes[1], 0);
|
||||||
|
|
||||||
|
AC.Nodes[0].mustJoin(AC.Nodes[1]);
|
||||||
|
for (auto B : AC.Nodes[0].Sets[0].Associativity) {
|
||||||
|
uint Age = B.first;
|
||||||
|
EXPECT_EQ(AC.Nodes[0].Sets[0].Associativity[Age].Blocks.front(),
|
||||||
|
AC.Nodes[1].Sets[0].Associativity[Age].Blocks.front());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void counterFillSet(AbstractState &In, unsigned int Set) {
|
||||||
|
for (int I = 0; I < 4; I++) {
|
||||||
|
In.Sets[Set].Associativity[I].Blocks.push_front((I + 1) % 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resulting state should be
|
||||||
|
// Set[0]:
|
||||||
|
// Age[0]:
|
||||||
|
// Age[1]: 1
|
||||||
|
// Age[2]: 2
|
||||||
|
// Age[3]: 0 3
|
||||||
|
TEST(MustJoinTests, MustJoinDifferentStates) {
|
||||||
|
AbstractCache AC;
|
||||||
|
AC.addEmptyNode(0);
|
||||||
|
counterFillSet(AC.Nodes[0], 0);
|
||||||
|
AC.addEmptyNode(1);
|
||||||
|
fillSet(AC.Nodes[1], 0);
|
||||||
|
std::cout << "==Before:==\n";
|
||||||
|
AC.Nodes[0].dumpSet(0);
|
||||||
|
AC.Nodes[1].dumpSet(0);
|
||||||
|
|
||||||
|
AC.Nodes[0].mustJoin(AC.Nodes[1]);
|
||||||
|
std::cout << "\n==After:==\n";
|
||||||
|
AC.Nodes[0].dumpSet(0);
|
||||||
|
for (auto B : AC.Nodes[0].Sets[0].Associativity) {
|
||||||
|
uint Age = B.first;
|
||||||
|
switch (Age) {
|
||||||
|
case 0:
|
||||||
|
EXPECT_TRUE(AC.Nodes[0].Sets[0].Associativity[Age].Blocks.empty());
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
EXPECT_EQ(AC.Nodes[0].Sets[0].Associativity[Age].Blocks.front(), 1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
EXPECT_EQ(AC.Nodes[0].Sets[0].Associativity[Age].Blocks.front(), 2);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// this test is not very exact the Set 0 with age 3 should contain (0,3)
|
||||||
|
// in arbitrary order
|
||||||
|
EXPECT_EQ(AC.Nodes[0].Sets[0].Associativity[Age].Blocks.size(), 2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// should never be reached!
|
||||||
|
EXPECT_TRUE(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillSetHighNumbers(AbstractState &In, unsigned int Set) {
|
||||||
|
for (int I = 0; I < 4; I++) {
|
||||||
|
In.Sets[Set].Associativity[I].Blocks.push_front(10 + I);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// resulting state should be empty
|
||||||
|
TEST(MustJoinTests, MustJoinDisjunctStates) {
|
||||||
|
AbstractCache AC;
|
||||||
|
AC.addEmptyNode(0);
|
||||||
|
fillSetHighNumbers(AC.Nodes[0], 0);
|
||||||
|
AC.addEmptyNode(1);
|
||||||
|
fillSet(AC.Nodes[1], 0);
|
||||||
|
std::cout << "==Before:==\n";
|
||||||
|
AC.Nodes[0].dumpSet(0);
|
||||||
|
AC.Nodes[1].dumpSet(0);
|
||||||
|
|
||||||
|
AC.Nodes[0].mustJoin(AC.Nodes[1]);
|
||||||
|
std::cout << "\n==After:==\n";
|
||||||
|
AC.Nodes[0].dumpSet(0);
|
||||||
|
for (auto B : AC.Nodes[0].Sets[0].Associativity) {
|
||||||
|
uint Age = B.first;
|
||||||
|
EXPECT_TRUE(AC.Nodes[0].Sets[0].Associativity[Age].Blocks.empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MustJoinTests, MustJoinDisjunctStatesAllSets) {
|
||||||
|
AbstractCache AC;
|
||||||
|
AC.addEmptyNode(0);
|
||||||
|
AC.addEmptyNode(1);
|
||||||
|
for (int I = 0; I < 16; I++) {
|
||||||
|
fillSetHighNumbers(AC.Nodes[0], I);
|
||||||
|
fillSet(AC.Nodes[1], I);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "==Before:==\n";
|
||||||
|
AC.Nodes[0].dump();
|
||||||
|
AC.Nodes[1].dump();
|
||||||
|
|
||||||
|
AC.Nodes[0].mustJoin(AC.Nodes[1]);
|
||||||
|
std::cout << "\n==After:==\n";
|
||||||
|
AC.Nodes[0].dump();
|
||||||
|
for (auto Set : AC.Nodes[0].Sets) {
|
||||||
|
for (auto B : Set.second.Associativity) {
|
||||||
|
EXPECT_TRUE(B.second.Blocks.empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MustJoinTests, MustJoinDifferentStatesAllSets) {
|
||||||
|
AbstractCache AC;
|
||||||
|
AC.addEmptyNode(0);
|
||||||
|
AC.addEmptyNode(1);
|
||||||
|
for (int I = 0; I < 16; I++) {
|
||||||
|
if (I % 2)
|
||||||
|
counterFillSet(AC.Nodes[0], I);
|
||||||
|
fillSet(AC.Nodes[1], I);
|
||||||
|
}
|
||||||
|
std::cout << "==Before:==\n";
|
||||||
|
AC.Nodes[0].dump();
|
||||||
|
AC.Nodes[1].dump();
|
||||||
|
|
||||||
|
AC.Nodes[0].mustJoin(AC.Nodes[1]);
|
||||||
|
|
||||||
|
AC.Nodes[1].mustJoin(AC.Nodes[0]);
|
||||||
|
std::cout << "\n==After:==\n";
|
||||||
|
AC.Nodes[1].dump();
|
||||||
|
for (auto Set : AC.Nodes[1].Sets) {
|
||||||
|
for (auto B : Set.second.Associativity) {
|
||||||
|
uint SetNr = Set.first;
|
||||||
|
uint Age = B.first;
|
||||||
|
if (SetNr % 2) {
|
||||||
|
switch (Age) {
|
||||||
|
case 0:
|
||||||
|
EXPECT_TRUE(B.second.Blocks.empty());
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
EXPECT_EQ(B.second.Blocks.front(), 1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
EXPECT_EQ(B.second.Blocks.front(), 2);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// this test is not very exact the Set 0 with age 3 should contain
|
||||||
|
// (0,3) in arbitrary order
|
||||||
|
EXPECT_EQ(B.second.Blocks.size(), 2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// should never be reached!
|
||||||
|
EXPECT_TRUE(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EXPECT_TRUE(B.second.Blocks.empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(AC.Nodes[1] == AC.Nodes[0]);
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ config () {
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
echo "==== Configuring cmake ===="
|
echo "==== Configuring cmake ===="
|
||||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DLT_LLVM_INSTALL_DIR=$LLVM_DIR ../CacheAnalysisPass/
|
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DLT_LLVM_INSTALL_DIR=/usr ..
|
||||||
cd ..
|
cd ..
|
||||||
cp build/compile_commands.json compile_commands.json
|
cp build/compile_commands.json compile_commands.json
|
||||||
echo "==== Done! ===="
|
echo "==== Done! ===="
|
||||||
|
@ -27,7 +27,7 @@ compile () {
|
||||||
|
|
||||||
run () {
|
run () {
|
||||||
echo "==== Running $1 ===="
|
echo "==== Running $1 ===="
|
||||||
opt -load-pass-plugin build/libCacheAnalysisPass.so \
|
opt -load-pass-plugin build/lib/libCacheAnalysisPass.so \
|
||||||
-passes='lru-misses(function(loop-unroll-and-jam))' \
|
-passes='lru-misses(function(loop-unroll-and-jam))' \
|
||||||
test/$1.ll -o /dev/null
|
test/$1.ll -o /dev/null
|
||||||
#llvm-dis < out.bc > out.ll
|
#llvm-dis < out.bc > out.ll
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#ifndef ABSTRACHTCACHESTATE_H
|
#ifndef ABSTRACHTCACHESTATE_H
|
||||||
#define ABSTRACHTCACHESTATE_H
|
#define ABSTRACHTCACHESTATE_H
|
||||||
|
|
||||||
|
@ -11,9 +10,6 @@
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <llvm/IR/BasicBlock.h>
|
|
||||||
#include <llvm/Support/raw_ostream.h>
|
|
||||||
|
|
||||||
#include "AbstractState.h"
|
#include "AbstractState.h"
|
||||||
#include "Address.h"
|
#include "Address.h"
|
||||||
#include "ConcreteState.h"
|
#include "ConcreteState.h"
|
||||||
|
@ -92,7 +88,7 @@ public: // everything is public, because IDGAF
|
||||||
}
|
}
|
||||||
Visited[Visitor.first] = true;
|
Visited[Visitor.first] = true;
|
||||||
}
|
}
|
||||||
return false;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,8 +100,6 @@ public: // everything is public, because IDGAF
|
||||||
void removeNestedLoops(
|
void removeNestedLoops(
|
||||||
std::list<unsigned int> LoopBodyIn,
|
std::list<unsigned int> LoopBodyIn,
|
||||||
std::map<unsigned int, unsigned int> OrigNodeToUnrolledNode) {
|
std::map<unsigned int, unsigned int> OrigNodeToUnrolledNode) {
|
||||||
unsigned int LoopHead = LoopBodyIn.front();
|
|
||||||
unsigned int LoopTail = LoopBodyIn.back();
|
|
||||||
unsigned int NestLoopTail;
|
unsigned int NestLoopTail;
|
||||||
for (unsigned int NodeNr : LoopBodyIn) {
|
for (unsigned int NodeNr : LoopBodyIn) {
|
||||||
bool IsLoopHead = false;
|
bool IsLoopHead = false;
|
||||||
|
@ -294,34 +288,34 @@ public: // everything is public, because IDGAF
|
||||||
removeNestedLoops(LoopBody, OrigNodeToUnrolledNode);
|
removeNestedLoops(LoopBody, OrigNodeToUnrolledNode);
|
||||||
|
|
||||||
if (Verbose && FoundLoopBody) {
|
if (Verbose && FoundLoopBody) {
|
||||||
llvm::outs() << "Found LoopHead @: " << NodeNr << "\n";
|
std::cout << "Found LoopHead @: " << NodeNr << "\n";
|
||||||
llvm::outs() << "With LoopTail @: " << LoopTail << "\n";
|
std::cout << "With LoopTail @: " << LoopTail << "\n";
|
||||||
llvm::outs() << "With Body: {\n";
|
std::cout << "With Body: {\n";
|
||||||
int I = 1;
|
int I = 1;
|
||||||
for (auto Node : LoopBody) {
|
for (auto Node : LoopBody) {
|
||||||
llvm::outs() << Node << ", ";
|
std::cout << Node << ", ";
|
||||||
if (!(I++ % 5)) {
|
if (!(I++ % 5)) {
|
||||||
llvm::outs() << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
llvm::outs() << "}\n";
|
std::cout << "}\n";
|
||||||
llvm::outs() << "Unrolled States: {\n";
|
std::cout << "Unrolled States: {\n";
|
||||||
I = 1;
|
I = 1;
|
||||||
for (auto Node : LoopBody) {
|
for (auto Node : LoopBody) {
|
||||||
llvm::outs() << OrigNodeToUnrolledNode[Node] << ", ";
|
std::cout << OrigNodeToUnrolledNode[Node] << ", ";
|
||||||
if (!(I++ % 5)) {
|
if (!(I++ % 5)) {
|
||||||
llvm::outs() << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
llvm::outs() << "}\n";
|
std::cout << "}\n";
|
||||||
I = 1;
|
I = 1;
|
||||||
llvm::outs() << "OrigNodeToUnrolledNode: {\n";
|
std::cout << "OrigNodeToUnrolledNode: {\n";
|
||||||
for (auto Nr : OrigNodeToUnrolledNode) {
|
for (auto Nr : OrigNodeToUnrolledNode) {
|
||||||
llvm::outs() << Nr.first << "->" << Nr.second << ", ";
|
std::cout << Nr.first << "->" << Nr.second << ", ";
|
||||||
if (!(I++ % 3))
|
if (!(I++ % 3))
|
||||||
llvm::outs() << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
llvm::outs() << "}\n";
|
std::cout << "}\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,19 +396,19 @@ public: // everything is public, because IDGAF
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void dumpEdges() {
|
void dumpEdges() {
|
||||||
llvm::outs() << "Dumping Edges:\n";
|
std::cout << "Dumping Edges:\n";
|
||||||
for (auto const &E : Edges) {
|
for (auto const &E : Edges) {
|
||||||
llvm::outs() << E.first;
|
std::cout << E.first;
|
||||||
bool FirstPrint = true;
|
bool FirstPrint = true;
|
||||||
for (unsigned int To : E.second) {
|
for (unsigned int To : E.second) {
|
||||||
if (FirstPrint) {
|
if (FirstPrint) {
|
||||||
llvm::outs() << " -> " << To;
|
std::cout << " -> " << To;
|
||||||
FirstPrint = false;
|
FirstPrint = false;
|
||||||
} else {
|
} else {
|
||||||
llvm::outs() << ", " << To;
|
std::cout << ", " << To;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
llvm::outs() << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,5 +449,6 @@ public: // everything is public, because IDGAF
|
||||||
Nodes[E.first].dump();
|
Nodes[E.first].dump();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace
|
}; // namespace
|
||||||
#endif // ABSTRACHTCACHESTATE_H
|
#endif // ABSTRACHTCACHESTATE_H
|
|
@ -12,8 +12,6 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <llvm/Support/raw_ostream.h>
|
|
||||||
|
|
||||||
#include "Address.h"
|
#include "Address.h"
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
|
|
||||||
|
@ -103,8 +101,8 @@ public: // everything is public, because IDGAF
|
||||||
void setUnrolled(unsigned int In) { Unrolled = In; }
|
void setUnrolled(unsigned int In) { Unrolled = In; }
|
||||||
|
|
||||||
bool operator==(AbstractState In) {
|
bool operator==(AbstractState In) {
|
||||||
for (int Index; Index < 16; Index++) {
|
for (int Index = 0; Index < 16; Index++) {
|
||||||
for (int Age; Age < 4; Age++) {
|
for (int Age = 0; Age < 4; Age++) {
|
||||||
for (auto E1 : Sets[Index].Associativity[Age].Blocks) {
|
for (auto E1 : Sets[Index].Associativity[Age].Blocks) {
|
||||||
// find E1 in In States Set and Age.
|
// find E1 in In States Set and Age.
|
||||||
if (std::find(In.Sets[Index].Associativity[Age].Blocks.begin(),
|
if (std::find(In.Sets[Index].Associativity[Age].Blocks.begin(),
|
||||||
|
@ -139,34 +137,60 @@ public: // everything is public, because IDGAF
|
||||||
// TODO: Due date 08.06.2022
|
// TODO: Due date 08.06.2022
|
||||||
|
|
||||||
// Loop through all 16 sets
|
// Loop through all 16 sets
|
||||||
for (int Index; Index < 16; Index++) {
|
for (int Index = 0; Index < 16; Index++) {
|
||||||
|
|
||||||
// create a temporary set of associativity
|
// create a temporary set of associativity
|
||||||
struct Set temp_set;
|
struct Set temp_set;
|
||||||
|
struct Set current_set = Sets[Index];
|
||||||
|
struct Set incoming_set = In.Sets[Index];
|
||||||
|
|
||||||
// loop through all 4 Ages
|
// loop through all 4 Ages
|
||||||
for (int Age; Age < 4; Age++) {
|
//for (int Age = 0; Age < 4; Age++) {
|
||||||
struct Set current_set = Sets[Index];
|
|
||||||
struct Set incoming_set = In.Sets[Index];
|
|
||||||
|
|
||||||
// loop through current set and build list of all contained blocks
|
std::cout << "Block list in current set"
|
||||||
for (auto age: current_set.Associativity) {
|
<< "[" << Index << "]" << std::endl;
|
||||||
std::cout << age.first
|
// loop through current set and build list of all contained blocks
|
||||||
<< ":";
|
for (auto associativity_map : current_set.Associativity) {
|
||||||
for (auto block : age.second.Blocks)
|
|
||||||
std::cout << block << std::endl;
|
|
||||||
}
|
|
||||||
// loop through incoming set and build list of all contained blocks
|
|
||||||
for (auto E2 : In.Sets[Index].Associativity[Age].Blocks) {
|
|
||||||
|
|
||||||
}
|
int associativity_age = associativity_map.first;
|
||||||
|
std::list<unsigned int> associativity_block_list =
|
||||||
|
associativity_map.second.Blocks;
|
||||||
|
// for every element of associativity_block_list
|
||||||
|
// if find equivalent in incoming_set.Associativity.block_list
|
||||||
|
// set new_age = max(associativity_age, age);
|
||||||
|
// temp_set.Associativity.insert(std::pair<unsigned int, struct Entry>(new_age, new_entry) )
|
||||||
|
print_block_list(associativity_age, associativity_block_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sets[Index] = temp_set;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "Block list in incoming set"
|
||||||
|
<< "[" << Index << "]" << std::endl;
|
||||||
|
// loop through incoming set and build list of all contained blocks
|
||||||
|
for (auto associativity : incoming_set.Associativity) {
|
||||||
|
|
||||||
|
int age = associativity.first;
|
||||||
|
std::list<unsigned int> block_list =
|
||||||
|
associativity.second.Blocks;
|
||||||
|
print_block_list(age, block_list);
|
||||||
|
}
|
||||||
|
// for (auto E2 : In.Sets[Index].Associativity[Age].Blocks) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
Sets[Index] = temp_set;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_block_list(int age, std::list<unsigned int> list) {
|
||||||
|
|
||||||
|
std::cout << "\t" << age << " -> {";
|
||||||
|
for (auto block : list)
|
||||||
|
std::cout << block << " ";
|
||||||
|
std::cout << "}" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks if Address Addr is in Cache
|
* @brief Checks if Address Addr is in Cache
|
||||||
*
|
*
|
||||||
|
@ -228,46 +252,60 @@ public: // everything is public, because IDGAF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Verbose) {
|
if (Verbose) {
|
||||||
llvm::outs() << "Before:\n";
|
std::cout << "Before:\n";
|
||||||
this->dump();
|
this->dump();
|
||||||
}
|
}
|
||||||
// update this with PreAddr
|
// update this with PreAddr
|
||||||
this->update(PreAddr);
|
this->update(PreAddr);
|
||||||
if (Verbose) {
|
if (Verbose) {
|
||||||
llvm::outs() << "Update Tag: " << PreAddr.Tag << "\n";
|
std::cout << "Update Tag: " << PreAddr.Tag << "\n";
|
||||||
llvm::outs() << "Update Set: " << PreAddr.Index << "\n";
|
std::cout << "Update Set: " << PreAddr.Index << "\n";
|
||||||
llvm::outs() << "After:\n";
|
std::cout << "After:\n";
|
||||||
this->dump();
|
this->dump();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump() {
|
void dumpSet(unsigned int Set) {
|
||||||
llvm::outs() << Addr << " {\n";
|
std::cout << Addr << " {\n";
|
||||||
llvm::outs() << "Unrolled: " << Unrolled << "\n";
|
|
||||||
llvm::outs() << "Computed: " << Computed << "\n";
|
|
||||||
llvm::outs() << "Predecessors: ";
|
|
||||||
for (auto PreNr : Predecessors) {
|
|
||||||
llvm::outs() << PreNr << " ";
|
|
||||||
}
|
|
||||||
llvm::outs() << "\n";
|
|
||||||
|
|
||||||
llvm::outs() << "Successors: ";
|
std::cout << "Set[" << Set << "]: \n";
|
||||||
for (auto SuccNr : Successors) {
|
for (auto EntryPair : this->Sets[Set].Associativity) {
|
||||||
llvm::outs() << SuccNr << " ";
|
std::cout << " Age[" << EntryPair.first << "]: ";
|
||||||
|
for (auto Block : EntryPair.second.Blocks) {
|
||||||
|
std::cout << Block << " ";
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
llvm::outs() << "\n";
|
std::cout << "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump() {
|
||||||
|
std::cout << Addr << " {\n";
|
||||||
|
std::cout << "Unrolled: " << Unrolled << "\n";
|
||||||
|
std::cout << "Computed: " << Computed << "\n";
|
||||||
|
std::cout << "Predecessors: ";
|
||||||
|
for (auto PreNr : Predecessors) {
|
||||||
|
std::cout << PreNr << " ";
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
|
std::cout << "Successors: ";
|
||||||
|
for (auto SuccNr : Successors) {
|
||||||
|
std::cout << SuccNr << " ";
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
for (auto SetPair : Sets) {
|
for (auto SetPair : Sets) {
|
||||||
llvm::outs() << "Set[" << SetPair.first << "]: \n";
|
std::cout << "Set[" << SetPair.first << "]: \n";
|
||||||
for (auto EntryPair : SetPair.second.Associativity) {
|
for (auto EntryPair : SetPair.second.Associativity) {
|
||||||
llvm::outs() << " Age[" << EntryPair.first << "]: ";
|
std::cout << " Age[" << EntryPair.first << "]: ";
|
||||||
for (auto Block : EntryPair.second.Blocks) {
|
for (auto Block : EntryPair.second.Blocks) {
|
||||||
llvm::outs() << Block << " ";
|
std::cout << Block << " ";
|
||||||
}
|
}
|
||||||
llvm::outs() << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
llvm::outs() << "}\n";
|
std::cout << "}\n";
|
||||||
}
|
}
|
||||||
}; // namespace
|
}; // namespace
|
||||||
#endif // STATE_H
|
#endif // STATE_H
|
Loading…
Reference in New Issue