Compare commits

...

21 Commits

Author SHA1 Message Date
Nils Hölscher cf2907d1d9 Added new dev container setup to README and removed VM setup
continuous-integration/drone/push Build is failing Details
2022-07-15 07:42:26 +00:00
Nils Hölscher 65c74a1883 Better dev container 2022-07-15 07:42:04 +00:00
Nils Hölscher 73e16bd797 Added VS Code devcontainer and uptaded needed llvm versionn to 14.
continuous-integration/drone/push Build is failing Details
2022-07-15 09:10:44 +02:00
Nils Hölscher 388103da3f Updated Debug Task.
continuous-integration/drone/push Build is passing Details
2022-06-20 08:49:23 +02:00
Nils Hölscher 9146caf849 Added Unit tests to the helper scripts.
continuous-integration/drone/push Build is passing Details
2022-06-07 09:08:07 +02:00
Nils Hölscher 0079b4f0e0 removed Tests from llvm build in poolhleper.
continuous-integration/drone/push Build is passing Details
2022-05-30 13:06:51 +02:00
Nils Hölscher 2ab71cf95d Added Auto build badge to Readme.md
continuous-integration/drone/push Build is passing Details
2022-05-24 11:07:32 +02:00
Nils Hölscher 13861282b4 .
continuous-integration/drone/push Build is passing Details
2022-05-24 11:05:40 +02:00
Nils Hölscher 623818d49e moved Auto Build file
continuous-integration/drone/push Build is failing Details
2022-05-24 10:54:18 +02:00
Nils Hölscher 841dbe1070 Automated builds and better UnitTEstNames for the Future. 2022-05-24 10:46:21 +02:00
Nils Hölscher 9dca6c2f67 More Unit Tests 2022-05-17 18:37:28 +02:00
Nils Hölscher 801831a2b5 fixed Bug in helper script 2022-05-17 08:20:52 +02:00
Nils Hölscher f818f3847a newer googletest suite 2022-05-16 14:05:04 +02:00
Nils Hölscher e40e6b7893 Added file Links in readme 2022-05-16 13:46:06 +02:00
Nils Hölscher 2cdcace84b Merge branch 'UnitTest' 2022-05-16 13:44:37 +02:00
Nils Hölscher 3264029256 Updated readme for UnitTests 2022-05-16 13:44:23 +02:00
Nils Hölscher 8ea0c571e4 Added some simple UnitTests 2022-05-16 13:38:48 +02:00
Nils Hölscher 0d09aa9e45 Merge branch 'master' into UnitTest 2022-05-16 11:58:33 +02:00
Nils Hölscher 7635fb52c7 Removed dbg option for loopunrolling. 2022-05-16 11:58:20 +02:00
Nils Hölscher e7ca0a68ef better exercise description in README.md 2022-05-16 11:55:40 +02:00
Nils Hölscher 1ae6af2eb6 Merge branch 'Fix-and-Loop-unrolling-' 2022-05-06 10:05:44 +02:00
14 changed files with 508 additions and 178 deletions

12
.devcontainer/Dockerfile Normal file
View File

@ -0,0 +1,12 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.241.1/containers/ubuntu/.devcontainer/base.Dockerfile
# [Choice] Ubuntu version (use ubuntu-22.04 or ubuntu-18.04 on local arm64/Apple Silicon): ubuntu-22.04, ubuntu-20.04, ubuntu-18.04
ARG VARIANT="jammy"
FROM mcr.microsoft.com/vscode/devcontainers/base:0-${VARIANT}
# [Optional] Uncomment this section to install additional OS packages.
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends \
llvm llvm-dev clang lldb gcc gdb cmake make ninja-build
ENV LLVM_DIR=/usr/lib/llvm-14

View File

@ -0,0 +1,33 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.241.1/containers/ubuntu
{
"name": "Ubuntu",
"build": {
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick an Ubuntu version: jammy / ubuntu-22.04, focal / ubuntu-20.04, bionic /ubuntu-18.04
// Use ubuntu-22.04 or ubuntu-18.04 on local arm64/Apple Silicon.
"args": { "VARIANT": "ubuntu-22.04" }
},
"extensions": ["llvm-vs-code-extensions.vscode-clangd",
"matepek.vscode-catch2-test-adapter",
"twxs.cmake",
"vadimcn.vscode-lldb",
"xaver.clang-format",
"yzhang.markdown-all-in-one",
"shd101wyy.markdown-preview-enhanced",
"streetsidesoftware.code-spell-checker"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "uname -a",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode",
"features": {
"git": "latest",
"fish": "latest"
}
}

11
.drone.yml Normal file
View File

@ -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

79
.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",
@ -26,7 +11,7 @@
"program": "/usr/bin/opt", "program": "/usr/bin/opt",
"args": [ "args": [
"-load-pass-plugin", "-load-pass-plugin",
"${workspaceFolder}/build/libCacheAnalysisPass.so", "${workspaceFolder}/build/lib/libCacheAnalysisPass.so",
"-passes=lru-misses", "-passes=lru-misses",
"${workspaceFolder}/test/fft1.ll", "${workspaceFolder}/test/fft1.ll",
"-o", "-o",
@ -34,36 +19,36 @@
], ],
"cwd": "${workspaceFolder}" "cwd": "${workspaceFolder}"
}, },
{ // {
"name": "gdb fft1", // "name": "gdb fft1",
"type": "cppdbg",//Only Usable with C/C++ extension installed from Microsoft. // "type": "cppdbg",//Only Usable with C/C++ extension installed from Microsoft.
"request": "launch", // "request": "launch",
"program": "/usr/bin/opt", // "program": "/usr/bin/opt",
"args": [ // "args": [
"-load-pass-plugin", // "-load-pass-plugin",
"${fileDirname}/../build/libCacheAnalysisPass.so", // "${fileDirname}/../build/lib/libCacheAnalysisPass.so",
"-passes='lru-misses'", // "-passes='lru-misses'",
"${fileDirname}/../test/fft1.ll", // "${fileDirname}/../test/fft1.ll",
"-o", // "-o",
"/dev/null" // "/dev/null"
], // ],
"stopAtEntry": false, // "stopAtEntry": false,
"cwd": "${fileDirname}", // "cwd": "${fileDirname}",
"environment": [], // "environment": [],
"externalConsole": false, // "externalConsole": false,
"MIMode": "gdb", // "MIMode": "gdb",
"setupCommands": [ // "setupCommands": [
{ // {
"description": "Enable pretty-printing for gdb", // "description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing", // "text": "-enable-pretty-printing",
"ignoreFailures": true // "ignoreFailures": true
}, // },
{ // {
"description": "Set Disassembly Flavor to Intel", // "description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel", // "text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true // "ignoreFailures": true
} // }
] // ]
} // }
] ]
} }

8
.vscode/tasks.json vendored
View File

@ -3,10 +3,16 @@
// for the documentation about the tasks.json format // for the documentation about the tasks.json format
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{
"label": "config",
"type": "shell",
"command": "rm -r build ; rm complile_commands.json ; mkdir build ; cd build ; cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DLT_LLVM_INSTALL_DIR=$LLVM_DIR ..",
"group": "build"
},
{ {
"label": "build", "label": "build",
"type": "shell", "type": "shell",
"command": "./helper.sh all", "command": " cd build ; ninja ",
"group": "build" "group": "build"
}, },
] ]

View File

@ -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.
@ -46,10 +59,10 @@ endif()
# `find_package(llvm)`. So there's no need to add it here. # `find_package(llvm)`. So there's no need to add it here.
list(APPEND CMAKE_PREFIX_PATH "${LT_LLVM_INSTALL_DIR}/lib/cmake/llvm/") list(APPEND CMAKE_PREFIX_PATH "${LT_LLVM_INSTALL_DIR}/lib/cmake/llvm/")
find_package(LLVM 13.0.0 REQUIRED CONFIG) find_package(LLVM 14.0.0 REQUIRED CONFIG)
# Another sanity check # Another sanity check
if(NOT "13" VERSION_EQUAL "${LLVM_VERSION_MAJOR}") if(NOT "14" VERSION_EQUAL "${LLVM_VERSION_MAJOR}")
message(FATAL_ERROR "Found LLVM ${LLVM_VERSION_MAJOR}, but need LLVM 13") message(FATAL_ERROR "Found LLVM ${LLVM_VERSION_MAJOR}, but need LLVM 13")
endif() endif()
@ -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)

View File

@ -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)

158
README.md
View File

@ -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
@ -18,17 +26,74 @@ I am more than happy helping you install Linux on your machine.
## Setups ## Setups
The easiest Way is to use the VM Image (pw:rtsa) provided here: ### VS Code Docker dev container (recommended setup)
<https://tu-dortmund.sciebo.de/s/JbvtbtEADx92eEG/authenticate> 1.) install docker and VS Code on your Distribution. Please keep in mind Dev containers are only supported by the native version of VS Code from Microsoft!
On this VM you can simply open VS Code from the desktop and start coding. <https://docs.docker.com/get-docker/>
Following are native setups and some other unrecommended Setups are at the end of this Readme. <https://code.visualstudio.com/>
Also read the VS Code setup, which might be interesting independent from your chosen Setup. For this setup you cannot use the OSS version of VS code or the version from Snap, as the remote development extensions will not work.
### Mac Setup 2.) I recommend you install the following extensions in vs code
clangd,
Clang-Format,
CodeLLDB,
Docker and
Remote Development (Microsoft VS Code only!)
For a general C/C++ setup of VS Code (I consider good) see:
<https://ahemery.dev/2020/08/24/c-cpp-vscode/>
3.) The project comes with a pre configured dev container and should prompt you to use it after opening the project. With this you have a running setup. If not please continue reading the manual points.
3.manual.) Use the helper script to build and run a Container.
```bash
./helper.sh docker
```
This will build a docker image and run a Docker container with the current directory mounted.
The Docker container can later be started from the Docker VS Code extension.
4.manual) Attach VS Code to the container, in the Docker Tab, and start developing
### VS Code native setup
This is my personally preferred IDE setup for C/C++ and by no means needed to accomplish this exercise.
1.) Install VS Code on your Distribution or get it from Microsoft.
<https://code.visualstudio.com/>
2.) I recommend you install the following extensions in vs code
clangd,
Clang-Format,
CodeLLDB,
C++ TestMate,
Docker and
Remote Development (Microsoft VS Code only!)
For a general C/C++ setup of VS Code (I consider good) see:
<https://ahemery.dev/2020/08/24/c-cpp-vscode/>
Most parts can be skipped, as they are already integrated in this Repo.
3.a.) Set the LLVM_DIR variable to your LLVM(14) installation.
```bash
export LLVM_DIR=<path/to/your/llvm/installation>
```
3.b.) You can auto config and build by hitting Ctr+Shift+B from the IDE or use the helper script.
4.) Pressing F5 will start a debug session, make sure to set halting points.
### Mac setup
I recommend using docker and VS Code for setup. I recommend using docker and VS Code for setup.
Also check out the recommended extensions in the Docker section. Also check out the recommended extensions in the Docker section.
@ -41,7 +106,7 @@ For Mac (tested on M1 Mac mini) you can also use:
But you will need brew installed and also have to use the poolhelper script instead of the normal helper script. But you will need brew installed and also have to use the poolhelper script instead of the normal helper script.
### Setup on a Pool PC ### Setup on a pool PC
At first get an IRB account from the following link and log in: At first get an IRB account from the following link and log in:
@ -69,65 +134,7 @@ Now you have a llvm13 source build.
Remember to use the poolhelper.sh instead of the helper.sh. Remember to use the poolhelper.sh instead of the helper.sh.
### VS Code Setup
This is my personally preferred IDE setup for C/C++ and by no means needed to accomplish this exercise.
1.) Install VS Code on your Distribution or get it from Microsoft.
<https://code.visualstudio.com/>
2.) I recommend you install the following extensions in vs code
clangd,
Clang-Format,
CodeLLDB,
Docker and
Remote Development
For a general C/C++ setup of VS Code (I consider good) see:
<https://ahemery.dev/2020/08/24/c-cpp-vscode/>
Most parts can be skipped, as they are already integrated in this Repo.
3.) You can auto build by hitting Strg+Shift+B from the IDE.
4.) Pressing F5 will start a debug session, make sure to set halting points.
### Setting up Docker
1.) install docker and VS Code on your Distribution.
<https://docs.docker.com/get-docker/>
<https://code.visualstudio.com/>
For this setup you cannot use the OSS version of VS code or the version from Snap, as the remote development extensions will not work.
2.) I recommend you install the following extensions in vs code
clangd,
Clang-Format,
CodeLLDB,
Docker and
Remote Development
For a general C/C++ setup of VS Code (I consider good) see:
<https://ahemery.dev/2020/08/24/c-cpp-vscode/>
Most of the setup can be skipped
3.) Use the helper script to build and run a Container
```bash
./helper.sh docker
```
This will build a docker image and run a Docker container with the current directory mounted.
The Docker container can later be started from the Docker VS Code extension.
4.) Attach VS Code to the container, in the Docker Tab, and start developing
## Debugging ## Debugging
@ -145,11 +152,24 @@ 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.
## Use the Helper script ## 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).
## Configuring and building
The easiest way is to use the VS Code tasks in this project.
By using CTR+Shift+B you can config and then build the project.
### 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.
### Initial Setup ### Initial setup
```bash ```bash
./helper.sh all ./helper.sh all

52
UnitTest/CMakeLists.txt Normal file
View File

@ -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)

174
UnitTest/UnitTest.cpp Normal file
View File

@ -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]);
}

View File

@ -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=$LLVM_DIR ..
cd .. cd ..
cp build/compile_commands.json compile_commands.json cp build/compile_commands.json compile_commands.json
echo "==== Done! ====" echo "==== Done! ===="
@ -27,12 +27,16 @@ 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
} }
test () {
./build/bin/UnitTest --gtest_brief=1
}
allBenchs=( "adpcm" allBenchs=( "adpcm"
"bs" "bs"
"bsort100" "bsort100"
@ -103,6 +107,9 @@ case $1 in
echo "==== Please provide name of the test as second argument! ====" echo "==== Please provide name of the test as second argument! ===="
fi fi
;; ;;
t | test)
test
;;
ra | runall) ra | runall)
runall runall
;; ;;
@ -157,6 +164,7 @@ case $1 in
echo " r | run [name] Run pass on test/[name] from the test folder" echo " r | run [name] Run pass on test/[name] from the test folder"
echo " cr [name] Compile and run pass on test/[name] from the test folder" echo " cr [name] Compile and run pass on test/[name] from the test folder"
echo " ra | runall Run pass on all tests from the test folder" echo " ra | runall Run pass on all tests from the test folder"
echo " t | test Execute Unit tests, only test that Fail are printed."
exit exit
;; ;;
esac esac

View File

@ -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

View File

@ -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
@ -107,8 +105,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(),
@ -203,46 +201,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 << " ";
} }
llvm::outs() << "\n"; std::cout << "\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

View File

@ -36,13 +36,17 @@ run () {
#llvm-dis < out.bc > out.ll #llvm-dis < out.bc > out.ll
} }
test () {
./build/bin/UnitTest --gtest_brief=1
}
buildllvm() { buildllvm() {
mkdir llvm mkdir llvm
cd llvm cd llvm
wget https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.1/llvm-13.0.1.src.tar.xz wget https://github.com/llvm/llvm-project/releases/download/llvmorg-13.0.1/llvm-13.0.1.src.tar.xz
tar -xf llvm-13.0.1.src.tar.xz tar -xf llvm-13.0.1.src.tar.xz
rm llvm-13.0.1.src.tar.xz rm llvm-13.0.1.src.tar.xz
cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DLLVM_TARGETS_TO_BUILD=host llvm-13.0.1.src/ cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DLLVM_INCLUDE_TESTS=FALSE -DLLVM_TARGETS_TO_BUILD=host llvm-13.0.1.src/
make -j 4 make -j 4
export LLVM_DIR=$(pwd) >> ~/.zshrc export LLVM_DIR=$(pwd) >> ~/.zshrc
export LLVM_DIR=$(pwd) >> ~/.bashrc export LLVM_DIR=$(pwd) >> ~/.bashrc
@ -137,6 +141,9 @@ case $1 in
echo "==== Please provide name of the test as second argument! ====" echo "==== Please provide name of the test as second argument! ===="
fi fi
;; ;;
t | test)
test
;;
ra | runall) ra | runall)
runall runall
;; ;;
@ -194,6 +201,7 @@ case $1 in
echo " r | run [name] Run pass on test/[name] from the test folder" echo " r | run [name] Run pass on test/[name] from the test folder"
echo " cr [name] Compile and run pass on test/[name] from the test folder" echo " cr [name] Compile and run pass on test/[name] from the test folder"
echo " ra | runall Run pass on all tests from the test folder" echo " ra | runall Run pass on all tests from the test folder"
echo " t | test Execute Unit tests, only test that Fail are printed."
exit exit
;; ;;
esac esac