├── traces.7z ├── Static-T ├── predictor ├── results ├── makefile └── predictor.cpp ├── Dynamic-BM ├── predictor ├── makefile ├── results └── predictor.cpp ├── Static-NT ├── predictor ├── results ├── makefile └── predictor.cpp ├── Dynamic-GSHARE ├── predictor ├── results ├── makefile └── predictor.cpp ├── Branch Prediction Programming Report.docx ├── Dynamic-NN ├── results └── AdaptivePredictor.py ├── LICENSE ├── .vscode └── settings.json ├── .gitignore └── README.md /traces.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saivittalb/branch-prediction-programming/HEAD/traces.7z -------------------------------------------------------------------------------- /Static-T/predictor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saivittalb/branch-prediction-programming/HEAD/Static-T/predictor -------------------------------------------------------------------------------- /Dynamic-BM/predictor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saivittalb/branch-prediction-programming/HEAD/Dynamic-BM/predictor -------------------------------------------------------------------------------- /Static-NT/predictor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saivittalb/branch-prediction-programming/HEAD/Static-NT/predictor -------------------------------------------------------------------------------- /Dynamic-GSHARE/predictor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saivittalb/branch-prediction-programming/HEAD/Dynamic-GSHARE/predictor -------------------------------------------------------------------------------- /Branch Prediction Programming Report.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saivittalb/branch-prediction-programming/HEAD/Branch Prediction Programming Report.docx -------------------------------------------------------------------------------- /Static-T/results: -------------------------------------------------------------------------------- 1 | 88.3724 2 | 58.1501 3 | 56.3637 4 | 94.9918 5 | 50.1466 6 | 63.455 7 | 39.4872 8 | 33.935 9 | 39.1215 10 | 38.0891 11 | 37.6188 12 | 39.6208 13 | 39.1208 14 | 38.7541 15 | 38.3617 16 | 39.2372 17 | -------------------------------------------------------------------------------- /Static-NT/results: -------------------------------------------------------------------------------- 1 | 12.6276 2 | 42.8499 3 | 44.6363 4 | 6.00817 5 | 50.8534 6 | 37.545 7 | 61.5128 8 | 67.065 9 | 61.8785 10 | 62.9109 11 | 63.3812 12 | 61.3792 13 | 61.8792 14 | 62.2459 15 | 62.6383 16 | 61.7628 17 | -------------------------------------------------------------------------------- /Dynamic-NN/results: -------------------------------------------------------------------------------- 1 | 99.167699446 2 | 99.0375091503 3 | 94.0876745932 4 | 99.7180795752 5 | 98.922666136 6 | 95.1044055202 7 | 97.1894180235 8 | 97.6137475312 9 | 95.9857717083 10 | 97.1377508602 11 | 96.9478647676 12 | 96.0559916884 13 | 96.7566237986 14 | 96.36469231 15 | 96.9232207022 16 | 96.8132693058 17 | -------------------------------------------------------------------------------- /Dynamic-GSHARE/results: -------------------------------------------------------------------------------- 1 | 99 98 99 99 99 99 99 99 99 2 | 89 93 93 93 94 90 91 91 94 3 | 86 85 85 84 83 82 80 79 78 4 | 99 99 99 99 99 99 99 99 99 5 | 91 91 88 90 88 89 88 87 87 6 | 89 89 88 88 88 88 87 87 87 7 | 88 88 88 87 87 86 86 85 85 8 | 85 84 83 82 82 81 81 80 79 9 | 86 86 85 85 84 83 83 83 83 10 | 80 80 78 78 76 74 75 74 73 11 | 80 80 78 78 76 74 74 74 73 12 | 83 82 81 81 80 79 79 78 78 13 | 92 91 92 91 91 92 92 92 92 14 | 82 81 80 79 78 76 76 76 75 15 | 80 79 78 77 76 74 74 73 73 16 | 82 81 79 79 78 76 76 75 74 17 | -------------------------------------------------------------------------------- /Static-NT/makefile: -------------------------------------------------------------------------------- 1 | # Specify the compiler 2 | GXX=g++ -g -w 3 | 4 | # Specifiy the target 5 | all: predictor 6 | 7 | # Specify the object files that the target depends on 8 | # Also, specify the object files needed to create the executable 9 | predictor: predictor.o 10 | $(GXX) predictor.o -o predictor 11 | 12 | # Specify how the object files should be created from source files 13 | predictor.o: predictor.cpp 14 | $(GXX) -c predictor.cpp 15 | 16 | # Specify the object files and executables that are generated 17 | # and need to be removed to re-compile the whole thing 18 | clean: 19 | rm -f *.o *~ core out.txt predictor -------------------------------------------------------------------------------- /Static-T/makefile: -------------------------------------------------------------------------------- 1 | # Specify the compiler 2 | GXX=g++ -g -w 3 | 4 | # Specifiy the target 5 | all: predictor 6 | 7 | # Specify the object files that the target depends on 8 | # Also, specify the object files needed to create the executable 9 | predictor: predictor.o 10 | $(GXX) predictor.o -o predictor 11 | 12 | # Specify how the object files should be created from source files 13 | predictor.o: predictor.cpp 14 | $(GXX) -c predictor.cpp 15 | 16 | # Specify the object files and executables that are generated 17 | # and need to be removed to re-compile the whole thing 18 | clean: 19 | rm -f *.o *~ core out.txt predictor -------------------------------------------------------------------------------- /Dynamic-BM/makefile: -------------------------------------------------------------------------------- 1 | # Specify the compiler 2 | GXX=g++ -g -w 3 | 4 | # Specifiy the target 5 | all: predictor 6 | 7 | # Specify the object files that the target depends on 8 | # Also, specify the object files needed to create the executable 9 | predictor: predictor.o 10 | $(GXX) predictor.o -o predictor 11 | 12 | # Specify how the object files should be created from source files 13 | predictor.o: predictor.cpp 14 | $(GXX) -c predictor.cpp 15 | 16 | # Specify the object files and executables that are generated 17 | # and need to be removed to re-compile the whole thing 18 | clean: 19 | rm -f *.o *~ core out.txt predictor -------------------------------------------------------------------------------- /Dynamic-GSHARE/makefile: -------------------------------------------------------------------------------- 1 | # Specify the compiler 2 | GXX=g++ -g -w 3 | 4 | # Specifiy the target 5 | all: predictor 6 | 7 | # Specify the object files that the target depends on 8 | # Also, specify the object files needed to create the executable 9 | predictor: predictor.o 10 | $(GXX) predictor.o -o predictor 11 | 12 | # Specify how the object files should be created from source files 13 | predictor.o: predictor.cpp 14 | $(GXX) -c predictor.cpp 15 | 16 | # Specify the object files and executables that are generated 17 | # and need to be removed to re-compile the whole thing 18 | clean: 19 | rm -f *.o *~ core out.txt predictor -------------------------------------------------------------------------------- /Dynamic-BM/results: -------------------------------------------------------------------------------- 1 | 97.3898 97.1735 97.5924 98.5526 99.0689 99.1537 99.1514 2 | 70.1561 73.2736 77.3801 79.043 80.7047 80.7044 80.7041 3 | 69.6721 72.0028 71.7969 77.4014 78.9097 82.1645 83.4267 4 | 99.083 99.0864 99.2127 99.4907 99.6771 99.7997 99.814 5 | 62.3554 66.1172 69.9684 79.2522 84.7318 87.8304 88.9967 6 | 75.2004 78.0164 79.1881 83.4142 85.6503 87.3727 88.7874 7 | 69.3364 72.1877 75.3225 81.4888 84.3361 86.8709 89.6572 8 | 67.914 71.6493 75.122 80.1342 81.2575 83.3785 86.282 9 | 68.6388 71.9049 74.1819 79.1977 81.1226 83.7136 85.6946 10 | 64.123 66.6608 66.7959 70.2126 73.382 77.2518 81.0027 11 | 63.6535 65.9515 65.9765 70.1592 73.5372 77.6433 81.4321 12 | 64.2323 66.7068 67.2551 73.7209 77.0126 80.8422 83.8718 13 | 76.6917 79.7219 84.2057 87.7979 90.361 91.0364 91.4518 14 | 65.5207 67.7632 68.0172 72.2421 75.0359 78.5441 81.9181 15 | 64.5354 66.6142 66.2372 69.5679 72.6615 76.738 80.7206 16 | 62.9662 65.0859 65.1831 71.0118 75.0727 79.4349 83.0028 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Sai Vittal B 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Static-T/predictor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * EE 318 - Computer Architecture and Design 3 | * Assignment 1 - Branch Prediction Programming 4 | * 5 | * @code `Static-T` (Static Always Taken) 6 | * @author Sai Vittal B 7 | * @copyright 2021 8 | * MIT License 9 | */ 10 | 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | int main (int argc, char *argv[]) { 16 | if (argc != 3) { 17 | cerr << "ERROR: Provide a file name for both input and output files.\n"; 18 | return 0; 19 | } 20 | 21 | ifstream fileIn(argv[1]); 22 | if (!fileIn.is_open()) { 23 | cerr << "ERROR: The input file does not exist.\n"; 24 | return 1; 25 | } 26 | 27 | ofstream fileOut(argv[2], std::ios::out | std::ios::app); 28 | if (!fileOut.is_open()) { 29 | cerr << "ERROR: The output file does not exist.\n"; 30 | return 2; 31 | } 32 | 33 | // Create Counters 34 | int alwaysT = 0; 35 | int iCount = 0; 36 | 37 | while (!fileIn.eof()) { 38 | // Reading Trace File 39 | // format: address(hex)\ T/NT(actual branch direction) 40 | long long address; 41 | fileIn >> hex >> address; 42 | if (fileIn.fail()) break; 43 | 44 | char branchTaken; 45 | fileIn >> branchTaken; 46 | if (fileIn.fail()) break; 47 | 48 | fileIn.ignore(256, '\n'); 49 | 50 | if (branchTaken == '1') { 51 | alwaysT++; 52 | } 53 | 54 | iCount++; //Instruction Count 55 | } 56 | 57 | //Calculate the accuracy rate of predictor 58 | float accurateT = ((float)alwaysT * 100 / iCount + 0.5f); 59 | 60 | fileOut << accurateT << endl; 61 | 62 | fileIn.close(); 63 | fileOut.close(); 64 | } 65 | -------------------------------------------------------------------------------- /Static-NT/predictor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * EE 318 - Computer Architecture and Design 3 | * Assignment 1 - Branch Prediction Programming 4 | * 5 | * @code `Static-NT` (Static Always Not Taken) 6 | * @author Sai Vittal B 7 | * @copyright 2021 8 | * MIT License 9 | */ 10 | 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | int main (int argc, char *argv[]) { 16 | if (argc != 3) { 17 | cerr << "ERROR: Provide a file name for both input and output files.\n"; 18 | return 0; 19 | } 20 | 21 | ifstream fileIn(argv[1]); 22 | if (!fileIn.is_open()) { 23 | cerr << "ERROR: The input file does not exist.\n"; 24 | return 1; 25 | } 26 | 27 | ofstream fileOut(argv[2], std::ios::out | std::ios::app); 28 | if (!fileOut.is_open()) { 29 | cerr << "ERROR: The output file does not exist.\n"; 30 | return 2; 31 | } 32 | 33 | // Create Counters 34 | int alwaysNT = 0; 35 | int iCount = 0; 36 | 37 | while (!fileIn.eof()) { 38 | // Reading Trace File 39 | // format: address(hex)\ T/NT(actual branch direction) 40 | long long address; 41 | fileIn >> hex >> address; 42 | if (fileIn.fail()) break; 43 | 44 | char branchTaken; 45 | fileIn >> branchTaken; 46 | if (fileIn.fail()) break; 47 | 48 | fileIn.ignore(256, '\n'); 49 | 50 | if (branchTaken == '0') { 51 | alwaysNT++; 52 | } 53 | 54 | iCount++; //Instruction Count 55 | } 56 | 57 | //Calculate the accuracy rate of predictor 58 | float accurateNT = ((float)alwaysNT * 100 / iCount + 0.5f); 59 | 60 | fileOut << accurateNT << endl; 61 | 62 | fileIn.close(); 63 | fileOut.close(); 64 | } 65 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "iostream": "cpp", 4 | "ios": "cpp", 5 | "__bit_reference": "cpp", 6 | "__config": "cpp", 7 | "__debug": "cpp", 8 | "__errc": "cpp", 9 | "__functional_base": "cpp", 10 | "__hash_table": "cpp", 11 | "__locale": "cpp", 12 | "__mutex_base": "cpp", 13 | "__node_handle": "cpp", 14 | "__nullptr": "cpp", 15 | "__split_buffer": "cpp", 16 | "__string": "cpp", 17 | "__threading_support": "cpp", 18 | "__tuple": "cpp", 19 | "algorithm": "cpp", 20 | "array": "cpp", 21 | "atomic": "cpp", 22 | "bit": "cpp", 23 | "bitset": "cpp", 24 | "cctype": "cpp", 25 | "chrono": "cpp", 26 | "cmath": "cpp", 27 | "complex": "cpp", 28 | "cstdarg": "cpp", 29 | "cstddef": "cpp", 30 | "cstdint": "cpp", 31 | "cstdio": "cpp", 32 | "cstdlib": "cpp", 33 | "cstring": "cpp", 34 | "ctime": "cpp", 35 | "cwchar": "cpp", 36 | "cwctype": "cpp", 37 | "deque": "cpp", 38 | "exception": "cpp", 39 | "fstream": "cpp", 40 | "functional": "cpp", 41 | "initializer_list": "cpp", 42 | "iomanip": "cpp", 43 | "iosfwd": "cpp", 44 | "istream": "cpp", 45 | "iterator": "cpp", 46 | "limits": "cpp", 47 | "locale": "cpp", 48 | "memory": "cpp", 49 | "mutex": "cpp", 50 | "new": "cpp", 51 | "optional": "cpp", 52 | "ostream": "cpp", 53 | "ratio": "cpp", 54 | "sstream": "cpp", 55 | "stack": "cpp", 56 | "stdexcept": "cpp", 57 | "streambuf": "cpp", 58 | "string": "cpp", 59 | "string_view": "cpp", 60 | "system_error": "cpp", 61 | "tuple": "cpp", 62 | "type_traits": "cpp", 63 | "typeinfo": "cpp", 64 | "unordered_map": "cpp", 65 | "utility": "cpp", 66 | "vector": "cpp" 67 | }, 68 | "python.pythonPath": "/usr/local/bin/python3" 69 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Removing traces folder for storage space 2 | traces/ 3 | 4 | ### C++ ### 5 | # Prerequisites 6 | *.d 7 | 8 | # Compiled Object files 9 | *.slo 10 | *.lo 11 | *.o 12 | *.obj 13 | 14 | # Precompiled Headers 15 | *.gch 16 | *.pch 17 | 18 | # Linker files 19 | *.ilk 20 | 21 | # Debugger Files 22 | *.pdb 23 | 24 | # Compiled Dynamic libraries 25 | *.so 26 | *.dylib 27 | *.dll 28 | 29 | # Fortran module files 30 | *.mod 31 | *.smod 32 | 33 | # Compiled Static libraries 34 | *.lai 35 | *.la 36 | *.a 37 | *.lib 38 | 39 | # Executables 40 | *.exe 41 | *.out 42 | *.app 43 | 44 | ### macOS ### 45 | # General 46 | .DS_Store 47 | .AppleDouble 48 | .LSOverride 49 | 50 | # Icon must end with two \r 51 | Icon 52 | 53 | 54 | # Thumbnails 55 | ._* 56 | 57 | # Files that might appear in the root of a volume 58 | .DocumentRevisions-V100 59 | .fseventsd 60 | .Spotlight-V100 61 | .TemporaryItems 62 | .Trashes 63 | .VolumeIcon.icns 64 | .com.apple.timemachine.donotpresent 65 | 66 | # Directories potentially created on remote AFP share 67 | .AppleDB 68 | .AppleDesktop 69 | Network Trash Folder 70 | Temporary Items 71 | .apdisk 72 | 73 | ### Python ### 74 | # Byte-compiled / optimized / DLL files 75 | __pycache__/ 76 | *.py[cod] 77 | *$py.class 78 | 79 | # C extensions 80 | 81 | # Distribution / packaging 82 | .Python 83 | build/ 84 | develop-eggs/ 85 | dist/ 86 | downloads/ 87 | eggs/ 88 | .eggs/ 89 | parts/ 90 | sdist/ 91 | var/ 92 | wheels/ 93 | pip-wheel-metadata/ 94 | share/python-wheels/ 95 | *.egg-info/ 96 | .installed.cfg 97 | *.egg 98 | MANIFEST 99 | 100 | # PyInstaller 101 | # Usually these files are written by a python script from a template 102 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 103 | *.manifest 104 | *.spec 105 | 106 | # Installer logs 107 | pip-log.txt 108 | pip-delete-this-directory.txt 109 | 110 | # Unit test / coverage reports 111 | htmlcov/ 112 | .tox/ 113 | .nox/ 114 | .coverage 115 | .coverage.* 116 | .cache 117 | nosetests.xml 118 | coverage.xml 119 | *.cover 120 | *.py,cover 121 | .hypothesis/ 122 | .pytest_cache/ 123 | pytestdebug.log 124 | 125 | # Translations 126 | *.mo 127 | *.pot 128 | 129 | # Django stuff: 130 | *.log 131 | local_settings.py 132 | db.sqlite3 133 | db.sqlite3-journal 134 | 135 | # Flask stuff: 136 | instance/ 137 | .webassets-cache 138 | 139 | # Scrapy stuff: 140 | .scrapy 141 | 142 | # Sphinx documentation 143 | docs/_build/ 144 | doc/_build/ 145 | 146 | # PyBuilder 147 | target/ 148 | 149 | # Jupyter Notebook 150 | .ipynb_checkpoints 151 | 152 | # IPython 153 | profile_default/ 154 | ipython_config.py 155 | 156 | # pyenv 157 | .python-version 158 | 159 | # pipenv 160 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 161 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 162 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 163 | # install all needed dependencies. 164 | #Pipfile.lock 165 | 166 | # poetry 167 | #poetry.lock 168 | 169 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 170 | __pypackages__/ 171 | 172 | # Celery stuff 173 | celerybeat-schedule 174 | celerybeat.pid 175 | 176 | # SageMath parsed files 177 | *.sage.py 178 | 179 | # Environments 180 | # .env 181 | .env/ 182 | .venv/ 183 | env/ 184 | venv/ 185 | ENV/ 186 | env.bak/ 187 | venv.bak/ 188 | pythonenv* 189 | 190 | # Spyder project settings 191 | .spyderproject 192 | .spyproject 193 | 194 | # Rope project settings 195 | .ropeproject 196 | 197 | # mkdocs documentation 198 | /site 199 | 200 | # mypy 201 | .mypy_cache/ 202 | .dmypy.json 203 | dmypy.json 204 | 205 | # Pyre type checker 206 | .pyre/ 207 | 208 | # pytype static type analyzer 209 | .pytype/ 210 | 211 | # operating system-related files 212 | # file properties cache/storage on macOS 213 | *.DS_Store 214 | # thumbnail cache on Windows 215 | Thumbs.db 216 | 217 | # profiling data 218 | .prof 219 | 220 | 221 | ### vscode ### 222 | .vscode/* 223 | !.vscode/settings.json 224 | !.vscode/tasks.json 225 | !.vscode/launch.json 226 | !.vscode/extensions.json 227 | *.code-workspace -------------------------------------------------------------------------------- /Dynamic-NN/AdaptivePredictor.py: -------------------------------------------------------------------------------- 1 | """ 2 | * EE 318 - Computer Architecture and Design 3 | * Assignment 1 - Branch Prediction Programming 4 | * 5 | * @code `Dynamic-NN` (Dynamic Adaptive Neural Network using Perceptrons) 6 | * @author Sai Vittal B 7 | * @copyright 2021 8 | * MIT License 9 | """ 10 | 11 | import sys 12 | import os 13 | from collections import deque 14 | import time 15 | 16 | class Perceptron: 17 | weights = [] 18 | N = 0 19 | bias = 0 20 | threshold = 0 21 | 22 | def __init__(self, N): 23 | self.N = N 24 | self.bias = 0 25 | self.threshold = 2 * N + 14 # optimal threshold depends on history length 26 | self.weights = [0] * N 27 | 28 | def predict(self, global_branch_history): 29 | running_sum = self.bias 30 | for i in range(0, self.N): # dot product of branch history with the weights 31 | running_sum += global_branch_history[i] * self.weights[i] 32 | prediction = -1 if running_sum < 0 else 1 33 | return (prediction, running_sum) 34 | 35 | def update(self, prediction, actual, global_branch_history, running_sum): 36 | if (prediction != actual) or (abs(running_sum) < self.threshold): 37 | self.bias = self.bias + (1 * actual) 38 | for i in range(0, self.N): 39 | self.weights[i] = self.weights[i] + (actual * global_branch_history[i]) 40 | 41 | 42 | def perceptron_pred(trace, l=1, tablesize=None): 43 | global_branch_history = deque([]) 44 | global_branch_history.extend([0] * l) 45 | 46 | p_list = {} 47 | num_correct = 0 48 | 49 | for br in trace: # iterating through each branch 50 | if tablesize: 51 | index = hash(br[0]) % tablesize 52 | else: 53 | index = hash(br[0]) 54 | 55 | if index not in p_list: # if no previous branch from this memory location 56 | p_list[index] = Perceptron(l) 57 | results = p_list[index].predict(global_branch_history) 58 | pr = results[0] 59 | running_sum = results[1] 60 | actual_value = 1 if br[1] else -1 61 | p_list[index].update(pr, actual_value, global_branch_history, running_sum) 62 | global_branch_history.appendleft(actual_value) 63 | global_branch_history.pop() 64 | if pr == actual_value: 65 | num_correct += 1 66 | return num_correct, len(p_list) 67 | 68 | def getTableSize(ratio,k): 69 | return int(ratio * k) 70 | 71 | fileIn = str(input('Provide the filepath for the trace (along with quotes " "): ')) 72 | assert os.path.exists(fileIn), 'ERROR: The input file does not exist.' 73 | with open(fileIn, 'r') as branchfile: 74 | trace = [] 75 | for line in branchfile.readlines(): 76 | tok = line.split(' ') 77 | trace.append([tok[0], int(tok[1])]) 78 | 79 | num_correct, num_p = perceptron_pred(trace, 5) 80 | print('\nLength of Perceptrons list: ' + str(num_p) + '\n') 81 | 82 | # Used if the number of unique addresses are not known 83 | results = [] 84 | for i in range (1, 50): 85 | start_time = time.time() 86 | num_correct, num_p = perceptron_pred(trace, i) 87 | end_time = time.time() 88 | results.append((num_correct/float(len(trace)), end_time - start_time)) 89 | print('i:' + str(i) + ' --> ') 90 | print(results[-1]) 91 | print('\nAccuracy: ' + str(num_correct/float(len(trace))*100) + '\n') 92 | fileOut = open('results', 'a') 93 | fileOut.write(str(num_correct/float(len(trace))*100) + '\n') 94 | fileOut.close() 95 | 96 | # Used if the number of unique addresses are known 97 | """ ratios = [i*.033 for i in range(1, 31)] 98 | results = [] 99 | for ratio in ratios: 100 | uniqueAddr = 33 # define number of unique addresses 101 | tablesize = getTableSize(ratio, uniqueAddr) 102 | start_time = time.time() 103 | num_correct, num_p = perceptron_pred(trace, 5, tablesize=tablesize) 104 | end_time = time.time() 105 | results.append((num_correct/float(len(trace)), end_time - start_time, ratio, tablesize)) 106 | print('ratio:' + str(ratio) + ' --> ') 107 | print(results[-1]) 108 | print('\nAccuracy: ' + str(num_correct/float(len(trace))*100) + '\n') 109 | fileOut = open('results', 'a') 110 | fileOut.write(str(num_correct/float(len(trace))*100) + '\n') 111 | fileOut.close() """ 112 | -------------------------------------------------------------------------------- /Dynamic-GSHARE/predictor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * EE 318 - Computer Architecture and Design 3 | * Assignment 1 - Branch Prediction Programming 4 | * 5 | * @code `Dynamic-GSHARE` (Dynamic Bimodal with Global Branch History) 6 | * @author Sai Vittal B 7 | * @copyright 2021 8 | * MIT License 9 | */ 10 | 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | int main(int argc, char *argv[]) { 16 | bool twoBitSaturatingCountersPredictor (int * table, int index, char taken); 17 | 18 | if (argc != 3) { 19 | cerr << "ERROR: Provide a file name for both input and output files.\n"; 20 | return 0; 21 | } 22 | 23 | ifstream fileIn(argv[1]); 24 | if (!fileIn.is_open()) { 25 | cerr << "ERROR: The input file does not exist.\n"; 26 | return 1; 27 | } 28 | 29 | ofstream fileOut(argv[2], std::ios::out | std::ios::app); 30 | if (!fileOut.is_open()) { 31 | cerr << "ERROR: The output file does not exist.\n"; 32 | return 2; 33 | } 34 | 35 | // Gshare Predictor 36 | int globalReg = 0; 37 | int **gtable = new int*[9]; // Prediction table for 2 to 10 bit global register 38 | for (int i = 0; i < 9; i++) { 39 | gtable[i] = new int[1024]; 40 | } 41 | 42 | // Initialize prediction table 43 | // Gshare Prediction Table set to Strongly Taken (11) 44 | for (int i = 0; i < 1024; i++) { 45 | gtable[0][i] = gtable[1][i] = gtable[2][i] = gtable[3][i] = gtable[4][i] = 46 | gtable[5][i] = gtable[6][i] = gtable[7][i] = gtable[8][i] = 3; 47 | } 48 | 49 | // Create Counters 50 | int gCounter[9] = {0}; 51 | int iCount = 0; 52 | 53 | while (!fileIn.eof()) { 54 | // Reading Trace File 55 | // format: address(hex)\ T/NT(actual branch direction) 56 | long long address; 57 | fileIn >> hex >> address; 58 | if (fileIn.fail()) break; 59 | 60 | char branchTaken; 61 | fileIn >> branchTaken; 62 | if (fileIn.fail()) break; 63 | 64 | fileIn.ignore(256, '\n'); 65 | 66 | int index = address % 1024; 67 | 68 | // Gshare Predictor (2 - 10 bits global register) 69 | for (int i = 2; i <= 10; i++) { 70 | int cutOff = 1 << i; //Use to obtain bits from global register 71 | gCounter[i - 2] += twoBitSaturatingCountersPredictor (gtable[i - 2], (index) ^ (globalReg % cutOff), branchTaken); 72 | } 73 | 74 | globalReg = globalReg << 1; 75 | if (branchTaken == '1') { 76 | globalReg++; 77 | } 78 | globalReg &= 1023; //Keep global register to 10 bits 79 | 80 | iCount++; //Instruction Count 81 | } 82 | 83 | //Calculate the accuracy rate of predictor 84 | float accurateG[9] = {0}; 85 | 86 | for (int i = 2; i <= 9; i++) { 87 | accurateG[i - 2] = (int)((float)gCounter[i - 2] * 100 / iCount + 0.5f); 88 | fileOut << accurateG[i - 2] << " "; 89 | } 90 | accurateG[10 - 2] = (int)((float)gCounter[10 - 2] * 100 / iCount + 0.5f); 91 | fileOut << accurateG[10 - 2] << endl; 92 | 93 | fileIn.close(); 94 | fileOut.close(); 95 | 96 | for (int i = 0; i < 9; i++) { 97 | delete [] gtable[i]; 98 | } 99 | delete [] gtable; 100 | } 101 | 102 | /** 103 | * Predictor using 2 bit saturating counters 104 | * Update the entry in table base on the actual branch direction 105 | * (11 - Strongly Taken, 10 - Weakly Taken, 01 - Weakly Not-Taken, 00 - Strongly Not-Taken) 106 | * 107 | * @param table prediction table 108 | * @param index locate the entry in prediction table 109 | * @param taken actual branch direction 110 | * @return whether entry in the table matches actual branch direction 111 | */ 112 | bool twoBitSaturatingCountersPredictor (int * table, int index, char taken) { 113 | bool correct = 0; 114 | int state = table[index] % 4; 115 | if (taken == '1') { 116 | switch (state) { 117 | case 0: 118 | case 1: 119 | table[index]++; 120 | break; 121 | case 2: 122 | table[index]++; 123 | case 3: 124 | correct = 1; 125 | break; 126 | } 127 | } else { 128 | switch (state) { 129 | case 0: 130 | correct = 1; 131 | break; 132 | case 1: 133 | correct = 1; 134 | case 2: 135 | case 3: 136 | table[index]--; 137 | break; 138 | } 139 | } 140 | return correct; 141 | } 142 | -------------------------------------------------------------------------------- /Dynamic-BM/predictor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * EE 318 - Computer Architecture and Design 3 | * Assignment 1 - Branch Prediction Programming 4 | * 5 | * @code `Dynamic-BM` (Dynamic Bimodal 2-bit Saturating Counters) 6 | * @author Sai Vittal B 7 | * @copyright 2021 8 | * MIT License 9 | */ 10 | 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | int main (int argc, char *argv[]) { 16 | bool twoBitSaturatingCountersPredictor (int * table, int index, char taken); 17 | 18 | if (argc != 3) { 19 | cerr << "ERROR: Provide a file name for both input and output files.\n"; 20 | return 0; 21 | } 22 | 23 | ifstream fileIn(argv[1]); 24 | if (!fileIn.is_open()) { 25 | cerr << "ERROR: The input file does not exist.\n"; 26 | return 1; 27 | } 28 | 29 | ofstream fileOut(argv[2], std::ios::out | std::ios::app); 30 | if (!fileOut.is_open()) { 31 | cerr << "ERROR: The output file does not exist.\n"; 32 | return 2; 33 | } 34 | 35 | // Prediction table for 2-bit Bimodal Predictor 36 | int *table8 = new int[8]; 37 | int *table16 = new int[16]; 38 | int *table32 = new int[32]; 39 | int *table128 = new int[128]; 40 | int *table256 = new int[256]; 41 | int *table512 = new int[512]; 42 | int *table1024 = new int[1024]; 43 | 44 | // Initialize prediction table 45 | // 2-bit Bimodal Prediction Table set to Strongly Taken (11) 46 | for (int i = 0; i < 8; i++) { 47 | table8[i] = table16[i] = table32[i] = table128[i] = table256[i] = table512[i] = table1024[i] = 7; 48 | } 49 | for (int i = 8; i < 16; i++) { 50 | table16[i] = table32[i] = table128[i] = table256[i] = table512[i] = table1024[i] = 7; 51 | } 52 | for (int i = 16; i < 32; i++) { 53 | table32[i] = table128[i] = table256[i] = table512[i] = table1024[i] = 7; 54 | } 55 | for (int i = 32; i < 128; i++) { 56 | table128[i] = table256[i] = table512[i] = table1024[i] = 7; 57 | } 58 | for (int i = 128; i < 256; i++) { 59 | table256[i] = table512[i] = table1024[i] = 7; 60 | } 61 | for (int i = 256; i < 512; i++) { 62 | table512[i] = table1024[i] = 7; 63 | } 64 | for (int i = 512; i < 1024; i++) { 65 | table1024[i] = 7; 66 | } 67 | 68 | // Create Counters 69 | int bimodal2bit8 = 0, bimodal2bit16 = 0, bimodal2bit32 = 0, bimodal2bit128 = 0, 70 | bimodal2bit256 = 0, bimodal2bit512 = 0, bimodal2bit1024 = 0; 71 | int iCount = 0; 72 | 73 | while (!fileIn.eof()) { 74 | // Reading Trace File 75 | // format: address(hex)\ T/NT(actual branch direction) 76 | long long address; 77 | fileIn >> hex >> address; 78 | if (fileIn.fail()) break; 79 | 80 | char branchTaken; 81 | fileIn >> branchTaken; 82 | if (fileIn.fail()) break; 83 | 84 | fileIn.ignore(256, '\n'); 85 | 86 | //2 bit Bimodal Predictor with various table size 87 | bimodal2bit8 += twoBitSaturatingCountersPredictor (table8, address % 8, branchTaken); 88 | bimodal2bit16 += twoBitSaturatingCountersPredictor (table16, address % 16, branchTaken); 89 | bimodal2bit32 += twoBitSaturatingCountersPredictor (table32, address % 32, branchTaken); 90 | bimodal2bit128 += twoBitSaturatingCountersPredictor (table128, address % 128, branchTaken); 91 | bimodal2bit256 += twoBitSaturatingCountersPredictor (table256, address % 256, branchTaken); 92 | bimodal2bit512 += twoBitSaturatingCountersPredictor (table512, address % 512, branchTaken); 93 | bimodal2bit1024 += twoBitSaturatingCountersPredictor (table1024, address % 1024, branchTaken); 94 | 95 | iCount++; //Instruction Count 96 | } 97 | 98 | //Calculate the accuracy rate of predictor 99 | float accurate2bit8 = ((float)bimodal2bit8 * 100 / iCount + 0.5f); 100 | float accurate2bit16 = ((float)bimodal2bit16 * 100 / iCount + 0.5f); 101 | float accurate2bit32 = ((float)bimodal2bit32 * 100 / iCount + 0.5f); 102 | float accurate2bit128 = ((float)bimodal2bit128 * 100 / iCount + 0.5f); 103 | float accurate2bit256 = ((float)bimodal2bit256 * 100 / iCount + 0.5f); 104 | float accurate2bit512 = ((float)bimodal2bit512 * 100 / iCount + 0.5f); 105 | float accurate2bit1024 = ((float)bimodal2bit1024 * 100 / iCount + 0.5f); 106 | 107 | fileOut << accurate2bit8 << " " << accurate2bit16 << " " << accurate2bit32 << " " << accurate2bit128 108 | << " " << accurate2bit256 << " " << accurate2bit512 << " " << accurate2bit1024 << endl; 109 | 110 | fileIn.close(); 111 | fileOut.close(); 112 | 113 | delete [] table8; 114 | delete [] table16; 115 | delete [] table32; 116 | delete [] table128; 117 | delete [] table256; 118 | delete [] table512; 119 | delete [] table1024; 120 | } 121 | 122 | /** 123 | * Predictor using 2 bit saturating counters 124 | * Update the entry in table base on the actual branch direction 125 | * (11 - Strongly Taken, 10 - Weakly Taken, 01 - Weakly Not-Taken, 00 - Strongly Not-Taken) 126 | * 127 | * @param table prediction table 128 | * @param index locate the entry in prediction table 129 | * @param taken actual branch direction 130 | * @return whether entry in the table matches actual branch direction 131 | */ 132 | bool twoBitSaturatingCountersPredictor (int * table, int index, char taken) { 133 | bool correct = 0; 134 | int state = table[index] % 4; 135 | if (taken == '1') { 136 | switch (state) { 137 | case 0: 138 | case 1: 139 | table[index]++; 140 | break; 141 | case 2: 142 | table[index]++; 143 | case 3: 144 | correct = 1; 145 | break; 146 | } 147 | } else { 148 | switch (state) { 149 | case 0: 150 | correct = 1; 151 | break; 152 | case 1: 153 | correct = 1; 154 | case 2: 155 | case 3: 156 | table[index]--; 157 | break; 158 | } 159 | } 160 | return correct; 161 | } 162 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Branch Prediction Programming 2 | [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) 3 | [![PR's Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)](http://makeapullrequest.com) 4 | [![GitHub followers](https://img.shields.io/github/followers/saivittalb.svg?style=social&label=Follow)](https://github.com/saivittalb?tab=followers) 5 | [![Twitter Follow](https://img.shields.io/twitter/follow/saivittalb.svg?style=social)](https://twitter.com/saivittalb) 6 | 7 | Implementation of several Branch Prediction algorithms and analysis on their effectiveness on real-world program traces. 8 | 9 | The following algorithms were implemented: 10 | 11 | - **Static ALWAYS TAKEN Branch Predictor (Static-T)**: All branches are predicted to be taken 12 | - **Static ALWAYS NOT TAKEN Branch Predictor (Static-NT)**: All branches are predicted to be not taken. 13 | - **Dynamic BIMODAL Branch Predictor (Dynamic-BM)**: The simplest dynamic branch direction predictor is an array of 2^n two-bit saturating counters. 14 | - **Dynamic BIMODAL Branch Predictor with Global Branch History (Dynamic-GSHARE)**: A more advanced dynamic branch predictor that uses the history of recently executed branches to predict the next branch. 15 | - **Dynamic NEURAL NETWORK using Perceptrons (Dynamic-NN)**: An adaptive neural network that contains dynamic predictor which uses a list of perceptrons to perform branch predictions. This designed unique algorithm can work on any hardware and trace. 16 | 17 | Developed as a part of an assignment for the course EE 318 – Computer Architecture and Design. 18 | 19 | ###### Note 20 | Developed with C++ and Python 3.9.2. 21 | Editor used was Visual Studio Code 1.55.1. 22 | 23 | ## Table of contents 24 | 25 | * [License](#license) 26 | * [Setup](#setup) 27 | * [Traces](#traces) 28 | * [Static and Dynamic predictors (except Dynamic Neural Network)](#static-and-dynamic-predictors-except-Dynamic-Neural-network) 29 | * [Dynamic Neural Network](#dynamic-neural-network) 30 | * [Results](#results) 31 | * [Static-T](#static-t) 32 | * [Static-NT](#static-nt) 33 | * [Dynamic-BM](#dynamic-bm) 34 | * [Dynamic-GSHARE](#dynamic-gshare) 35 | * [Dynamic-NN](#dynamic-nn) 36 | * [Contributing](#contributing) 37 | 38 | ## License 39 | This project is licensed under the MIT License, a short and simple permissive license with conditions only requiring preservation of copyright and license notices. Licensed works, modifications and larger works may be distributed under different terms and without source code. 40 | 41 |

Copyright (c) 2021 Sai Vittal B. All rights reserved.

42 | 43 | ## Setup 44 | 45 | ### Traces 46 | Traces used are available via a compressed file named ```traces.7z```. Download this repo and unzip the file to get access to 16 unique traces. 47 | 48 | ### Static and Dynamic predictors (except Dynamic Neural Network) 49 | - Run the following commands in terminal/console window: 50 | ```bash 51 | $ cd 52 | $ make 53 | $ ./predictor 54 | ``` 55 | 56 | ```InputFilename``` is the path to your input trace file containing branch outcomes in the following format: address 1/0 (1 = taken, 0 = not taken). 57 | ```OutputFilename``` is the file where the result is printed to. 58 | 59 | ### Dynamic Neural Network 60 | - Install Python 3.9.2 (preferred). 61 | - Run the following command in terminal/console window: 62 | ```bash 63 | $ python AdaptivePredictor.py 64 | ``` 65 | - The above would return the following statement where you are required to provide the input filepath: 66 | ```bash 67 | Provide the filepath for the trace (along with quotes " "): "" 68 | ``` 69 | 70 | ## Results 71 | 72 | Results can viewed in the ```results``` file in each predictor folder. It contains the accuracy of that predictor in a line-by-line fashion for the 16 traces. 73 | 74 | #### Comparison in decreasing reliablity: Dynamic-NN >> Dynamic-GSHARE > Dynamic-BM >> Static-T >= Static-NT 75 | 76 | Results are also showcased in the MS Word document named ```Branch Prediction Programming Report.docx```. 77 | 78 | The output formats in the ```results``` file for each predictor are explained below. 79 | 80 | ### Static-T 81 | Direct accuracy reported in single value for a trace. 82 | 83 | ### Static-NT 84 | Direct accuracy reported in single value for a trace. 85 | 86 | ### Dynamic-BM 87 | Direct accuracy reported with 7 different table size (8, 16, 32, 128, 256, 512, and 1024 entries) for a trace. 88 | 89 | ### Dynamic-GSHARE 90 | Direct accuracy reported with 9 different global register size range from 2 bits to 10 bits for a table size of 1024 entries for a trace. 91 | 92 | ### Dynamic-NN 93 | Direct accuracy reported in a single value when the number of unique addresses are unknown for a trace. If the number of unique addresses are known for a trace, then a commented out function in the code file ```AdaptivePredictor.py``` can be used to achieve accuracy in that scenario. 94 | 95 | ## Contributing 96 | - Fork this project by clicking the ```Fork``` button on top right corner of this page. 97 | - Open terminal/console window. 98 | - Clone the repository by running following command in git: 99 | ```bash 100 | $ git clone https://github.com/[YOUR-USERNAME]/branch-prediction-programming.git 101 | ``` 102 | - Add all changes by running this command. 103 | ```bash 104 | $ git add . 105 | ``` 106 | - Or to add specific files only, run this command. 107 | ```bash 108 | $ git add path/to/your/file 109 | ``` 110 | - Commit changes by running these commands. 111 | ```bash 112 | $ git commit -m "DESCRIBE YOUR CHANGES HERE" 113 | 114 | $ git push origin 115 | ``` 116 | - Create a Pull Request by clicking the ```New pull request``` button on your repository page. 117 | 118 | [![ForTheBadge built-with-love](http://ForTheBadge.com/images/badges/built-with-love.svg)](https://GitHub.com/saivittalb/) 119 | [![ForTheBadge powered-by-electricity](http://ForTheBadge.com/images/badges/powered-by-electricity.svg)](http://ForTheBadge.com) 120 | 121 |

Copyright (c) 2021 Sai Vittal B. All rights reserved.

122 |

Made with ❤ by Sai Vittal B

123 | --------------------------------------------------------------------------------