├── .gitattributes ├── .gitignore ├── README.md ├── lab00 ├── code.py ├── gen-debug.sh └── setup.sh ├── lab01 ├── .gitignore ├── exercise1 │ ├── ex1.c │ ├── ex1.h │ └── test_ex1.c ├── exercise2 │ ├── pwd_checker.c │ ├── pwd_checker.h │ └── test_pwd_checker.c ├── exercise3 │ ├── linked_list.c │ ├── linked_list.h │ └── test_linked_list.c └── exercise4 │ ├── ll_cycle.c │ ├── ll_cycle.h │ └── test_ll_cycle.c ├── lab02 ├── Makefile ├── bit_ops.c ├── bit_ops.h ├── linked_list ├── linked_list.c ├── linked_list.h ├── test_bit_ops.c ├── test_linked_list.c ├── test_vector.c ├── vector.c └── vector.h ├── lab03 ├── ex1.s ├── ex2.c ├── ex2.s ├── factorial.s ├── lcm.c ├── list_map.s └── pow.s ├── lab04 ├── accumulatortests.s ├── cc_test.s ├── discrete_fn.s ├── lotsofaccumulators.s ├── megalistmanips.s └── megalistmanips_answers.txt ├── lab05 ├── .gitattributes ├── .gitignore ├── ex2.circ ├── ex3.circ ├── ex4.circ ├── ex5.circ ├── ex6.circ ├── ex7.circ ├── test.py └── tests │ ├── ex2-test.circ │ ├── ex3-test.circ │ ├── ex4-test.circ │ ├── ex5-test.circ │ ├── ex6-test.circ │ ├── ex7-test.circ │ └── reference-output │ ├── ex2-test.out │ ├── ex3-test.out │ ├── ex4-test.out │ ├── ex5-test.out │ ├── ex6-test.out │ └── ex7-test.out ├── lab06 ├── .gitattributes ├── .gitignore ├── ex1.circ ├── ex1.txt ├── ex2.circ ├── ex2.txt ├── test.py └── tests │ ├── ex2-test.circ │ └── reference-output │ └── ex2-test.out ├── lab07 ├── Makefile ├── cache.s ├── large_cache.s ├── matrixMultiply.c ├── test_transpose.c ├── transpose.c └── transpose.h ├── lab09 ├── Makefile ├── simd.c ├── simd.h └── test_simd.c ├── lab10 ├── Makefile ├── answers │ └── ex2.txt ├── dotp.c ├── hello.c ├── omp_apps.c ├── omp_apps.h └── v_add.c └── tools ├── logisim-evolution.jar └── venus.jar /.gitattributes: -------------------------------------------------------------------------------- 1 | *.c text eol=lf 2 | *.circ text eol=lf 3 | *.h text eol=lf 4 | *.md text eol=lf 5 | *.s text eol=lf 6 | *.sh text eol=lf 7 | *.txt text eol=lf 8 | Makefile text eol=lf 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | # *.out 34 | a.out 35 | *.app 36 | *.i*86 37 | *.x86_64 38 | *.hex 39 | 40 | # Debug files 41 | *.dSYM/ 42 | *.su 43 | *.idb 44 | *.pdb 45 | vgcore.* 46 | 47 | # Kernel Module Compile Results 48 | *.mod* 49 | *.cmd 50 | .tmp_versions/ 51 | modules.order 52 | Module.symvers 53 | Mkfile.old 54 | dkms.conf 55 | 56 | # Byte-compiled / optimized / DLL files 57 | __pycache__/ 58 | *.py[cod] 59 | *$py.class 60 | 61 | # C extensions 62 | *.so 63 | 64 | # Distribution / packaging 65 | .Python 66 | build/ 67 | develop-eggs/ 68 | dist/ 69 | downloads/ 70 | eggs/ 71 | .eggs/ 72 | lib/ 73 | lib64/ 74 | parts/ 75 | sdist/ 76 | var/ 77 | wheels/ 78 | pip-wheel-metadata/ 79 | share/python-wheels/ 80 | *.egg-info/ 81 | .installed.cfg 82 | *.egg 83 | MANIFEST 84 | 85 | # PyInstaller 86 | # Usually these files are written by a python script from a template 87 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 88 | *.manifest 89 | *.spec 90 | 91 | # Installer logs 92 | pip-log.txt 93 | pip-delete-this-directory.txt 94 | 95 | # Unit test / coverage reports 96 | htmlcov/ 97 | .tox/ 98 | .nox/ 99 | .coverage 100 | .coverage.* 101 | .cache 102 | nosetests.xml 103 | coverage.xml 104 | *.cover 105 | *.py,cover 106 | .hypothesis/ 107 | .pytest_cache/ 108 | 109 | # Translations 110 | *.mo 111 | *.pot 112 | 113 | # Django stuff: 114 | *.log 115 | local_settings.py 116 | db.sqlite3 117 | db.sqlite3-journal 118 | 119 | # Flask stuff: 120 | instance/ 121 | .webassets-cache 122 | 123 | # Scrapy stuff: 124 | .scrapy 125 | 126 | # Sphinx documentation 127 | docs/_build/ 128 | 129 | # PyBuilder 130 | target/ 131 | 132 | # Jupyter Notebook 133 | .ipynb_checkpoints 134 | 135 | # IPython 136 | profile_default/ 137 | ipython_config.py 138 | 139 | # pyenv 140 | .python-version 141 | 142 | # pipenv 143 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 144 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 145 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 146 | # install all needed dependencies. 147 | #Pipfile.lock 148 | 149 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 150 | __pypackages__/ 151 | 152 | # Celery stuff 153 | celerybeat-schedule 154 | celerybeat.pid 155 | 156 | # SageMath parsed files 157 | *.sage.py 158 | 159 | # Environments 160 | .env 161 | .venv 162 | env/ 163 | venv/ 164 | ENV/ 165 | env.bak/ 166 | venv.bak/ 167 | 168 | # Spyder project settings 169 | .spyderproject 170 | .spyproject 171 | 172 | # Rope project settings 173 | .ropeproject 174 | 175 | # mkdocs documentation 176 | /site 177 | 178 | # mypy 179 | .mypy_cache/ 180 | .dmypy.json 181 | dmypy.json 182 | 183 | # Pyre type checker 184 | .pyre/ 185 | 186 | # General 187 | .DS_Store 188 | .AppleDouble 189 | .LSOverride 190 | 191 | # Icon must end with two \r 192 | Icon 193 | 194 | # Thumbnails 195 | ._* 196 | 197 | # Files that might appear in the root of a volume 198 | .DocumentRevisions-V100 199 | .fseventsd 200 | .Spotlight-V100 201 | .TemporaryItems 202 | .Trashes 203 | .VolumeIcon.icns 204 | .com.apple.timemachine.donotpresent 205 | 206 | # Directories potentially created on remote AFP share 207 | .AppleDB 208 | .AppleDesktop 209 | Network Trash Folder 210 | Temporary Items 211 | .apdisk 212 | 213 | # Windows thumbnail cache files 214 | Thumbs.db 215 | Thumbs.db:encryptable 216 | ehthumbs.db 217 | ehthumbs_vista.db 218 | 219 | # Dump file 220 | *.stackdump 221 | 222 | # Folder config file 223 | [Dd]esktop.ini 224 | 225 | # Recycle Bin used on file shares 226 | $RECYCLE.BIN/ 227 | 228 | # Windows Installer files 229 | *.cab 230 | *.msi 231 | *.msix 232 | *.msm 233 | *.msp 234 | 235 | # Windows shortcuts 236 | *.lnk 237 | 238 | *~ 239 | 240 | # temporary files which can be created if a process still has a handle open of a deleted file 241 | .fuse_hidden* 242 | 243 | # KDE directory preferences 244 | .directory 245 | 246 | # Linux trash folder which might appear on any partition or disk 247 | .Trash-* 248 | 249 | # .nfs files are created when an open file is removed but is still being accessed 250 | .nfs* 251 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fa21-lab 2 | -------------------------------------------------------------------------------- /lab00/code.py: -------------------------------------------------------------------------------- 1 | def get_airspeed_velocity_of(unladen_swallow): 2 | if unladen_swallow.type == "african": 3 | return # redacted 4 | elif unladen_swallow.type == "european": 5 | return # redacted 6 | 7 | def fizzbuzz(num): 8 | if str(num) in ["15"]: 9 | print(f"{num}: fizzbuzz") 10 | elif str(num) in ["3", "6", "9", "12", "15", "18"]: 11 | print(f"{num}: fizz") 12 | elif str(num) in ["5", "10", "15"]: 13 | print(f"{num}: buzz") 14 | 15 | for i in range(1, 20): 16 | fizzbuzz(i) 17 | -------------------------------------------------------------------------------- /lab00/gen-debug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "OSTYPE='$OSTYPE'" | tee debug.txt 4 | echo "SH_VERSION='$(sh --version 2>&1 | cat)'" | tee -a debug.txt 5 | echo "GIT_VERSION='$(git --version 2>&1 | cat)'" | tee -a debug.txt 6 | echo "PYTHON_VERSION='$(python3 --version 2>&1 | cat)'" | tee -a debug.txt 7 | echo "GCC_VERSION='$(gcc --version 2>&1 | cat)'" | tee -a debug.txt 8 | echo "JAVA_VERSION='$(java -version 2>&1 | cat)'" | tee -a debug.txt 9 | -------------------------------------------------------------------------------- /lab00/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | lab00_start_ref="lab00-start" 5 | git fetch --tags starter 6 | 7 | current_commit="$(git rev-parse HEAD)" 8 | lab00_start_commit="$(git rev-parse "${lab00_start_ref}")" 9 | 10 | if [ "$current_commit" != "$lab00_start_commit" ]; then 11 | echo "Your repo appears to have additional commits beyond the start of lab 0." 12 | echo "You can reset your repo, but all of your work will be reset." 13 | echo "If you are sure, run 'git reset --hard ${lab00_start_ref} && git push -f origin main'." 14 | echo "Otherwise, ask course staff for help." 15 | exit 1 16 | fi 17 | 18 | git reset -q --hard "${lab00_start_ref}~" 19 | 20 | echo "Finished setup" 21 | -------------------------------------------------------------------------------- /lab01/.gitignore: -------------------------------------------------------------------------------- 1 | ex1 2 | pwd_checker 3 | linked_list 4 | test_ll_cycle 5 | -------------------------------------------------------------------------------- /lab01/exercise1/ex1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ex1.h" 3 | 4 | /* Returns the number of times LETTER appears in STR. 5 | There are two different ways to iterate through a string. 6 | 1st way hint: strlen() may be useful 7 | 2nd way hint: all strings end in a null terminator */ 8 | int num_occurrences(char *str, char letter) { 9 | /* TODO: implement num_occurances */ 10 | return 0; 11 | } 12 | 13 | /* Populates DNA_SEQ with the number of times each nucleotide appears. 14 | Each sequence will end with a NULL terminator and will have up to 20 nucleotides. 15 | All letters will be upper case. */ 16 | void compute_nucleotide_occurrences(DNA_sequence *dna_seq) { 17 | /* TODO: implement compute_nucleotide_occurances */ 18 | return; 19 | } 20 | -------------------------------------------------------------------------------- /lab01/exercise1/ex1.h: -------------------------------------------------------------------------------- 1 | #ifndef EX_1_H 2 | #define EX_1_H 3 | 4 | typedef struct DNA_sequence { 5 | char sequence [21]; 6 | int A_count; 7 | int C_count; 8 | int G_count; 9 | int T_count; 10 | } DNA_sequence; 11 | 12 | int num_occurrences(char *str, char letter); 13 | void compute_nucleotide_occurrences(DNA_sequence *dna_seq); 14 | 15 | #endif //EX_1_H 16 | -------------------------------------------------------------------------------- /lab01/exercise1/test_ex1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "ex1.h" 5 | 6 | int main(int argc, char **argv) { 7 | printf("Running tests...\n\n"); 8 | /************ Part 1 Test Cases ************/ 9 | char *str = "hello world!"; 10 | 11 | int num_l = num_occurrences(str, 'l'); 12 | assert(num_l == 3); 13 | 14 | int num_z = num_occurrences(str, 'z'); 15 | assert(num_z == 0); 16 | 17 | /* TODO: Think of a scenario that is not tested by the current test cases. Create one additional test case to test this scenario. */ 18 | 19 | printf("Congrats! If you have made it to this line, your Part 1 Test cases are all passing!\n"); 20 | 21 | /************ Part 2 Test Cases ************/ 22 | DNA_sequence dna_seq_1; 23 | strcpy(dna_seq_1.sequence, "ACTTTGAAC"); 24 | compute_nucleotide_occurrences(&dna_seq_1); 25 | assert(dna_seq_1.A_count == 3); 26 | assert(dna_seq_1.C_count == 2); 27 | assert(dna_seq_1.G_count == 1); 28 | assert(dna_seq_1.T_count == 3); 29 | 30 | DNA_sequence dna_seq_2; 31 | strcpy(dna_seq_2.sequence, "AAAACCC"); 32 | compute_nucleotide_occurrences(&dna_seq_2); 33 | assert(dna_seq_2.A_count == 4); 34 | assert(dna_seq_2.C_count == 3); 35 | assert(dna_seq_2.G_count == 0); 36 | assert(dna_seq_2.T_count == 0); 37 | 38 | /* TODO: Think of a scenario that is not tested by the current test cases. Create one additional test case to test this scenario. */ 39 | 40 | printf("Congrats! If you have made it to this line, your Part 2 Test cases are all passing!\n"); 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /lab01/exercise2/pwd_checker.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pwd_checker.h" 3 | 4 | /* 5 | Password checker 6 | 7 | Requirements: 8 | - Password must be at least 10 characters 9 | - Password must contain at least 10 | - 1 upper case letter 11 | - 1 lower case letter 12 | - 1 number 13 | - Password cannot contain the person's first name or last name (case sensitive) 14 | 15 | For the simplicity of this exercise: 16 | - This is not the most efficient way to implement this program 17 | - These functions do not perform any error checking 18 | - You can assume that the first and last name will never be the empty string 19 | */ 20 | 21 | /* Returns true if the length of PASSWORD is at least 10, false otherwise */ 22 | bool check_length(const char *password) { 23 | int length = strlen(password); 24 | bool meets_len_req = (length <= 10); 25 | return meets_len_req; 26 | } 27 | 28 | /* Returns true if LETTER is in the range [LOWER, UPPER], false otherwise */ 29 | bool check_range(char letter, char lower, char upper) { 30 | bool is_in_range = (letter > lower && letter < upper); 31 | return is_in_range; 32 | } 33 | 34 | /* Returns true if PASSWORD contains at least one upper case letter, false otherwise */ 35 | bool check_upper(const char *password) { 36 | while (password != '\0') { 37 | bool is_in_range = check_range(*password, 'A', 'Z'); 38 | if (is_in_range) { 39 | return true; 40 | } 41 | ++password; 42 | } 43 | return false; 44 | } 45 | 46 | /* Returns true if PASSWORD contains at least one lower case letter, false otherwise */ 47 | bool check_lower(const char *password) { 48 | while (*password != '\0') { 49 | bool is_in_range = check_range(*password, 'a', 'z'); 50 | if (is_in_range) { 51 | return true; 52 | } 53 | ++password; 54 | } 55 | return false; 56 | } 57 | 58 | /* Returns true if PASSWORD contains at least one number, false otherwise */ 59 | bool check_number(const char *password) { 60 | while (password != '\0') { 61 | if (check_range(password, 0, 9)) { 62 | return true; 63 | } 64 | ++password; 65 | } 66 | return false; 67 | } 68 | 69 | /* Returns true if the person's first and last name are NOT in the password, false otherwise */ 70 | bool check_name(const char *first_name, const char *last_name, const char *password) { 71 | /* Type "man strstr" in your terminal to learn what strstr does! 72 | To exit the man pages, press 'q' */ 73 | /* Hint: a NULL pointer will evaluate to False in a logical statement while a non-NULL pointer 74 | will evaluate to True */ 75 | const char *first = strstr(*password, first_name); 76 | const char *last = strstr(password, last_name); 77 | return (first && last); 78 | } 79 | 80 | /* Returns true if PASSWORD meets the conditions specified above */ 81 | bool check_password(const char *first_name, const char *last_name, const char *password) { 82 | bool length, upper, lower, number, name; 83 | lower = check_lower(password); 84 | length = check_length(password); 85 | name = check_name(first_name, last_name, password); 86 | number = check_number(password); 87 | upper = check_upper(password); 88 | return (lower && length && name && upper && number); 89 | } 90 | -------------------------------------------------------------------------------- /lab01/exercise2/pwd_checker.h: -------------------------------------------------------------------------------- 1 | #ifndef PWD_CHECKER_H 2 | #define PWD_CHECKER_H 3 | 4 | #include 5 | 6 | bool check_password(const char *first_name, const char *last_name, const char *password); 7 | 8 | #endif // PWD_CHECKER_H 9 | -------------------------------------------------------------------------------- /lab01/exercise2/test_pwd_checker.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "pwd_checker.h" 4 | 5 | int main() { 6 | printf("Running tests...\n\n"); 7 | 8 | const char *test1_first = "Abraham"; 9 | const char *test1_last = "Garcia"; 10 | const char *test1_pwd = "qrtv?,mp!ltrA0b13rab4ham"; 11 | bool test1 = check_password(test1_first, test1_last, test1_pwd); 12 | assert(test1); 13 | 14 | printf("Congrats! The first test case is now passing. You should remove the assert statements that you added " 15 | "to pwd_checker.c because these correspond to the first test case and will not necessarily work for the remaining " 16 | "test cases!\n\n"); 17 | 18 | const char *test2_first = "Anjali"; 19 | const char *test2_last = "Patel"; 20 | const char *test2_pwd = "Aj8r"; 21 | bool test2 = check_password(test2_first, test2_last, test2_pwd); 22 | assert(!test2); 23 | 24 | const char *test3_first = "Chantelle"; 25 | const char *test3_last = "Brown"; 26 | const char *test3_pwd = "QLRIOW815N"; 27 | bool test3 = check_password(test3_first, test3_last, test3_pwd); 28 | assert(!test3); 29 | 30 | const char *test4_first = "Wei"; 31 | const char *test4_last = "Zhang"; 32 | const char *test4_pwd = "pjkdihn!o901"; 33 | bool test4 = check_password(test4_first, test4_last, test4_pwd); 34 | assert(!test4); 35 | 36 | const char *test5_first = "John"; 37 | const char *test5_last = "Smith"; 38 | const char *test5_pwd = "ALKLIenhLq"; 39 | bool test5 = check_password(test5_first, test5_last, test5_pwd); 40 | assert(!test5); 41 | 42 | const char *test6_first = "Haeun"; 43 | const char *test6_last = "Kim"; 44 | const char *test6_pwd = "Ji9anjwHaeun"; 45 | bool test6 = check_password(test6_first, test6_last, test6_pwd); 46 | assert(!test6); 47 | 48 | const char *test7_first = "Adeline"; 49 | const char *test7_last = "DuBois"; 50 | const char *test7_pwd = "ALKLIDuBoisen3hLq"; 51 | bool test7 = check_password(test7_first, test7_last, test7_pwd); 52 | assert(!test7); 53 | 54 | printf("Congrats! You have passed all of the test cases!\n"); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /lab01/exercise3/linked_list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "linked_list.h" 4 | 5 | /* returns a new node whose data is set to DATA and next is set to NULL */ 6 | Node *create_node(int data) { 7 | /* Don't worry about malloc yet! It is not in the scope of this lab */ 8 | struct Node *new_node = malloc(sizeof(struct Node)); 9 | if (new_node == NULL) { 10 | perror("Malloc failed\n"); 11 | } 12 | new_node->data = data; 13 | new_node->next = NULL; 14 | return new_node; 15 | } 16 | 17 | /* Don't worry about free(), it is not in the scope of this lab */ 18 | /* Frees the list starting at HEAD */ 19 | void free_list(Node *head) { 20 | while (head != NULL) { 21 | Node *temp = head->next; 22 | free(head); 23 | head = temp; 24 | } 25 | } 26 | 27 | /* Creates a new node whose data is set to DATA and adds it to the front of the 28 | list pointed to by HEAD. 29 | This function is heavily commented for instructional purposes. Please 30 | never use this many comments when you are writing code. */ 31 | void add_to_front(struct Node **head, int data) { 32 | /* Check if the head is NULL to make sure that we do not dereference a NULL pointer 33 | because that would result in a segfault */ 34 | if (head == NULL) return; 35 | struct Node *new_node = create_node(data); 36 | if (*head != NULL) { 37 | /* The list is not empty */ 38 | /* The new node's next should point to the head */ 39 | new_node->next = *head; 40 | } 41 | /* We must set HEAD using the following line in order to change the original list */ 42 | *head = new_node; 43 | /* The following line would not work because it would only change our local copy of HEAD */ 44 | /* head = new_node */ 45 | } 46 | 47 | /* Prints out a linked list starting at HEAD */ 48 | void print_list(struct Node *head) { 49 | struct Node *curr; 50 | for (curr = head; curr != NULL; curr = curr->next) { 51 | printf("%d->", curr->data); 52 | } 53 | printf("NULL\n"); 54 | } 55 | 56 | /* Iteratively reverses a linked list whose first node is HEAD */ 57 | void reverse_list(struct Node **head) { 58 | if (head == NULL) { 59 | return; 60 | } 61 | struct Node *curr = *head; 62 | struct Node *next = (*head)->next; 63 | curr->next = NULL; 64 | while (next != NULL) { 65 | struct Node *temp = next->next; 66 | next->next = curr; 67 | curr = next; 68 | next = temp; 69 | } 70 | *head = curr; 71 | } 72 | 73 | /* Creates a new node with a data field set to DATA and adds the node 74 | to the back of the list pointed to by HEAD */ 75 | void add_to_back(Node **head, int data) { 76 | if (head == NULL) { 77 | return; 78 | } 79 | Node *new_node = create_node(data); 80 | Node *prev; 81 | for (Node *curr = *head; curr != NULL; curr = curr->next) { 82 | prev = curr; 83 | } 84 | prev->next = new_node; 85 | } 86 | -------------------------------------------------------------------------------- /lab01/exercise3/linked_list.h: -------------------------------------------------------------------------------- 1 | #ifndef LINKED_LIST_H 2 | #define LINKED_LIST_H 3 | 4 | typedef struct Node { 5 | int data; 6 | struct Node *next; 7 | } Node; 8 | 9 | Node *create_node(int data); 10 | void free_list(Node *head); 11 | void add_to_front(struct Node **head, int data); 12 | void print_list(struct Node *head); 13 | void reverse_list(struct Node **head); 14 | void add_to_back(Node **head, int data); 15 | 16 | #endif // LINKED_LIST_H 17 | -------------------------------------------------------------------------------- /lab01/exercise3/test_linked_list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "linked_list.h" 5 | 6 | int main(int argc, char **argv) { 7 | printf("Running tests...\n\n"); 8 | 9 | Node *head = NULL; 10 | 11 | /*********** reverse_list test ***********/ 12 | reverse_list(&head); 13 | for (int i = 0; i < 5; ++i) { 14 | add_to_front(&head, i); 15 | reverse_list(&head); 16 | } 17 | 18 | int expected_values[] = {3, 1, 0, 2, 4}; 19 | Node *curr = head; 20 | for (int i = 0; i < 5; ++i) { 21 | assert(curr->data == expected_values[i]); 22 | curr = curr->next; 23 | } 24 | free_list(head); 25 | 26 | printf("Congrats! You have passed the reverse_list test!\n\n"); 27 | 28 | /************ add_to_back test ***********/ 29 | Node *head_2 = NULL; 30 | add_to_back(&head_2, 15); 31 | add_to_back(&head_2, 12); 32 | add_to_back(&head_2, 18); 33 | int expected_values_2[] = {15, 12, 18}; 34 | Node *curr_2 = head_2; 35 | for (int i = 0; i < 3; ++i) { 36 | assert(curr_2->data == expected_values_2[i]); 37 | curr_2 = curr_2->next; 38 | } 39 | free_list(head_2); 40 | 41 | printf("Congrats! All of the test cases passed!\n"); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /lab01/exercise4/ll_cycle.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ll_cycle.h" 3 | 4 | int ll_has_cycle(node *head) { 5 | /* TODO: Implement ll_has_cycle */ 6 | } 7 | -------------------------------------------------------------------------------- /lab01/exercise4/ll_cycle.h: -------------------------------------------------------------------------------- 1 | #ifndef LL_CYCLE_H 2 | #define LL_CYCLE_H 3 | 4 | typedef struct node { 5 | int value; 6 | struct node *next; 7 | } node; 8 | 9 | int ll_has_cycle(node *); 10 | 11 | #endif // LL_CYCLE_H 12 | -------------------------------------------------------------------------------- /lab01/exercise4/test_ll_cycle.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ll_cycle.h" 4 | 5 | int main(void) { 6 | // DO NOT EDIT ANY OF THE FOLLOWING CODE 7 | printf("Running tests...\n\n"); 8 | 9 | int i; 10 | node nodes[25]; // enough to run our tests 11 | for(i = 0; i < sizeof(nodes)/sizeof(node); i++) { 12 | nodes[i].next = 0; 13 | nodes[i].value = 0; 14 | } 15 | 16 | nodes[0].next = &nodes[1]; 17 | nodes[1].next = &nodes[2]; 18 | nodes[2].next = &nodes[3]; 19 | printf("Checking first list for cycles. There should be none, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[0]) ? "a" : "no"); 20 | assert(!ll_has_cycle(&nodes[0])); 21 | 22 | nodes[4].next = &nodes[5]; 23 | nodes[5].next = &nodes[6]; 24 | nodes[6].next = &nodes[7]; 25 | nodes[7].next = &nodes[8]; 26 | nodes[8].next = &nodes[9]; 27 | nodes[9].next = &nodes[10]; 28 | nodes[10].next = &nodes[4]; 29 | printf("Checking second list for cycles. There should be a cycle, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[4]) ? "a" : "no"); 30 | assert(ll_has_cycle(&nodes[4])); 31 | 32 | nodes[11].next = &nodes[12]; 33 | nodes[12].next = &nodes[13]; 34 | nodes[13].next = &nodes[14]; 35 | nodes[14].next = &nodes[15]; 36 | nodes[15].next = &nodes[16]; 37 | nodes[16].next = &nodes[17]; 38 | nodes[17].next = &nodes[14]; 39 | printf("Checking third list for cycles. There should be a cycle, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[11]) ? "a" : "no"); 40 | assert(ll_has_cycle(&nodes[11])); 41 | 42 | nodes[18].next = &nodes[18]; 43 | printf("Checking fourth list for cycles. There should be a cycle, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[18]) ? "a" : "no"); 44 | assert(ll_has_cycle(&nodes[18])); 45 | 46 | nodes[19].next = &nodes[20]; 47 | nodes[20].next = &nodes[21]; 48 | nodes[21].next = &nodes[22]; 49 | nodes[22].next = &nodes[23]; 50 | printf("Checking fifth list for cycles. There should be none, ll_has_cycle says it has %s cycle\n", ll_has_cycle(&nodes[19]) ? "a" : "no"); 51 | assert(!ll_has_cycle(&nodes[19])); 52 | 53 | printf("Checking length-zero list for cycles. There should be none, ll_has_cycle says it has %s cycle\n\n", ll_has_cycle(NULL) ? "a" : "no"); 54 | assert(!ll_has_cycle(NULL)); 55 | 56 | printf("Congrats, you passed all the test cases!\n"); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /lab02/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-Wall -std=c99 3 | 4 | all: linked_list 5 | 6 | linked_list: linked_list.o test_linked_list.o 7 | $(CC) -o linked_list linked_list.o test_linked_list.o 8 | 9 | linked_list.o: linked_list.c linked_list.h 10 | $(CC) $(CFLAGS) -c linked_list.c 11 | 12 | test_linked_list.o: test_linked_list.c linked_list.h 13 | $(CC) $(CFLAGS) -c test_linked_list.c 14 | 15 | clean: 16 | rm linked_list linked_list.o test_linked_list.o -------------------------------------------------------------------------------- /lab02/bit_ops.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bit_ops.h" 3 | 4 | /* Returns the Nth bit of X. Assumes 0 <= N <= 31. */ 5 | unsigned get_bit(unsigned x, unsigned n) { 6 | /* YOUR CODE HERE */ 7 | return -1; /* UPDATE WITH THE CORRECT RETURN VALUE*/ 8 | } 9 | 10 | /* Set the nth bit of the value of x to v. Assumes 0 <= N <= 31, and V is 0 or 1 */ 11 | void set_bit(unsigned *x, unsigned n, unsigned v) { 12 | /* YOUR CODE HERE */ 13 | } 14 | 15 | /* Flips the Nth bit in X. Assumes 0 <= N <= 31.*/ 16 | void flip_bit(unsigned *x, unsigned n) { 17 | /* YOUR CODE HERE */ 18 | } 19 | 20 | -------------------------------------------------------------------------------- /lab02/bit_ops.h: -------------------------------------------------------------------------------- 1 | unsigned get_bit(unsigned x, unsigned n); 2 | void set_bit(unsigned * x, unsigned n, unsigned v); 3 | void flip_bit(unsigned * x, unsigned n); -------------------------------------------------------------------------------- /lab02/linked_list: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/61c-teach/fa21-lab-starter/e48f5bfb2cd5f1d292c2eb1f418a2186577803bd/lab02/linked_list -------------------------------------------------------------------------------- /lab02/linked_list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "linked_list.h" 4 | 5 | 6 | 7 | /* returns a new node whose data is set to DATA and next is set to NULL */ 8 | Node *create_node(int data) { 9 | struct Node *new_node = malloc(sizeof(struct Node)); 10 | if (new_node == NULL) { 11 | perror("Malloc failed\n"); 12 | } 13 | new_node->data = data; 14 | new_node->next = NULL; 15 | return new_node; 16 | } 17 | 18 | /* Frees the list starting at HEAD */ 19 | void free_list(Node *head) { 20 | while (head != NULL) { 21 | Node *temp = head->next; 22 | free(head); 23 | head = temp; 24 | } 25 | } 26 | 27 | /* Creates a new node whose data is set to DATA and adds it to the front of the 28 | list pointed to by HEAD. 29 | This function is heavily commented for instructional purposes. Please 30 | never use this many comments when you are writing code. */ 31 | void add_to_front(struct Node **head, int data) { 32 | /* Check if the head is NULL to make sure that we do not dereference a NULL pointer 33 | because that would result in a segfault */ 34 | if (head == NULL) return; 35 | struct Node *new_node = create_node(data); 36 | if (*head != NULL) { 37 | /* The list is not empty */ 38 | /* The new node's next should point to the head */ 39 | new_node->next = *head; 40 | } 41 | /* We must set HEAD using the following line in order to change the original list */ 42 | *head = new_node; 43 | /* The following line would not work because it would only change our local copy of HEAD */ 44 | /* head = new_node */ 45 | } 46 | 47 | /* Prints out a linked list starting at HEAD */ 48 | void print_list(struct Node *head) { 49 | struct Node *curr; 50 | for (curr = head; curr != NULL; curr = curr->next) { 51 | printf("%d->", curr->data); 52 | } 53 | printf("NULL\n"); 54 | } 55 | 56 | /* Iteratively reverses a linked list whose first node is HEAD */ 57 | void reverse_list(struct Node **head) { 58 | if (head == NULL) { 59 | return; 60 | } 61 | struct Node *curr = *head; 62 | struct Node *next = (*head)->next; 63 | curr->next = NULL; 64 | while (next != NULL) { 65 | struct Node *temp = next->next; 66 | next->next = curr; 67 | curr = next; 68 | next = temp; 69 | } 70 | *head = curr; 71 | } 72 | 73 | /* Creates a new node with a data field set to DATA and adds the node 74 | to the back of the list pointed to by HEAD */ 75 | void add_to_back(Node **head, int data) { 76 | if (head == NULL) { 77 | return; 78 | } 79 | Node *new_node = create_node(data); 80 | Node *prev; 81 | for (Node *curr = *head; curr != NULL; curr = curr->next) { 82 | prev = curr; 83 | } 84 | prev->next = new_node; 85 | } 86 | -------------------------------------------------------------------------------- /lab02/linked_list.h: -------------------------------------------------------------------------------- 1 | #ifndef LINKED_LIST_H 2 | #define LINKED_LIST_H 3 | 4 | typedef struct Node { 5 | int data; 6 | struct Node *next; 7 | } Node; 8 | 9 | Node *create_node(int data); 10 | void free_list(Node *head); 11 | void add_to_front(struct Node **head, int data); 12 | void print_list(struct Node *head); 13 | void reverse_list(struct Node **head); 14 | void add_to_back(Node **head, int data); 15 | 16 | #endif // LINKED_LIST_H 17 | -------------------------------------------------------------------------------- /lab02/test_bit_ops.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bit_ops.h" 3 | 4 | void test_get_bit(unsigned x, unsigned n, unsigned expected) { 5 | unsigned a = get_bit(x, n); 6 | if(a!=expected) { 7 | printf("get_bit(0x%08x,%u) returned 0x%08x, but we expected 0x%08x\n",x,n,a,expected); 8 | } else { 9 | printf("get_bit(0x%08x,%u)returned 0x%08x, correct\n",x,n,a); 10 | } 11 | } 12 | 13 | void test_set_bit(unsigned x, unsigned n, unsigned v, unsigned expected) { 14 | unsigned o = x; 15 | set_bit(&x, n, v); 16 | if(x!=expected) { 17 | printf("set_bit(0x%08x,%u,%u) returned 0x%08x but we expected 0x%08x\n",o,n,v,x,expected); 18 | } else { 19 | printf("set_bit(0x%08x,%u,%u) returned 0x%08x, correct\n",o,n,v,x); 20 | } 21 | } 22 | 23 | void test_flip_bit(unsigned x, unsigned n, unsigned expected) { 24 | unsigned o = x; 25 | flip_bit(&x, n); 26 | if(x!=expected) { 27 | printf("flip_bit(0x%08x,%u) returned 0x%08x, but we expected 0x%08x\n",o,n,x,expected); 28 | } else { 29 | printf("flip_bit(0x%08x,%u) returned 0x%08x, correct\n",o,n,x); 30 | } 31 | } 32 | 33 | int main(int argc, const char * argv[]) { 34 | printf("\nTesting get_bit()\n\n"); 35 | test_get_bit(0b1001110,0,0); 36 | test_get_bit(0b1001110,1,1); 37 | test_get_bit(0b1001110,5,0); 38 | test_get_bit(0b11011,3,1); 39 | test_get_bit(0b11011,2,0); 40 | test_get_bit(0b11011,9,0); 41 | printf("\nTesting set_bit()\n\n"); 42 | test_set_bit(0b1001110,2,0,0b1001010); 43 | test_set_bit(0b1101101,0,0,0b1101100); 44 | test_set_bit(0b1001110,2,1,0b1001110); 45 | test_set_bit(0b1101101,0,1,0b1101101); 46 | test_set_bit(0b1001110,9,0,0b1001110); 47 | test_set_bit(0b1101101,4,0,0b1101101); 48 | test_set_bit(0b1001110,9,1,0b1001001110); 49 | test_set_bit(0b1101101,7,1,0b11101101); 50 | printf("\nTesting flip_bit()\n\n"); 51 | test_flip_bit(0b1001110,0,0b1001111); 52 | test_flip_bit(0b1001110,1,0b1001100); 53 | test_flip_bit(0b1001110,2,0b1001010); 54 | test_flip_bit(0b1001110,5,0b1101110); 55 | test_flip_bit(0b1001110,9,0b1001001110); 56 | printf("\n"); 57 | return 0; 58 | } -------------------------------------------------------------------------------- /lab02/test_linked_list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "linked_list.h" 5 | 6 | int main(int argc, char **argv) { 7 | printf("Running tests...\n\n"); 8 | 9 | Node *head = NULL; 10 | 11 | /*********** reverse_list test ***********/ 12 | reverse_list(&head); 13 | for (int i = 0; i < 5; ++i) { 14 | add_to_front(&head, i); 15 | reverse_list(&head); 16 | } 17 | 18 | int expected_values[] = {3, 1, 0, 2, 4}; 19 | Node *curr = head; 20 | for (int i = 0; i < 5; ++i) { 21 | assert(curr->data == expected_values[i]); 22 | curr = curr->next; 23 | } 24 | free_list(head); 25 | 26 | printf("Congrats! You have passed the reverse_list test!\n\n"); 27 | 28 | /************ add_to_back test ***********/ 29 | Node *head_2 = NULL; 30 | add_to_back(&head_2, 15); 31 | add_to_back(&head_2, 12); 32 | add_to_back(&head_2, 18); 33 | int expected_values_2[] = {15, 12, 18}; 34 | Node *curr_2 = head_2; 35 | for (int i = 0; i < 3; ++i) { 36 | assert(curr_2->data == expected_values_2[i]); 37 | curr_2 = curr_2->next; 38 | } 39 | free_list(head_2); 40 | 41 | printf("Congrats! All of the test cases passed!\n"); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /lab02/test_vector.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "vector.h" 5 | 6 | int main(int argc, char **argv) { 7 | vector_t *v; 8 | 9 | printf("Calling vector_new()\n"); 10 | v = vector_new(); 11 | 12 | printf("Calling vector_delete()\n"); 13 | vector_delete(v); 14 | 15 | printf("vector_new() again\n"); 16 | v = vector_new(); 17 | 18 | printf("These should all return 0 (vector_get()): "); 19 | printf("%d ", vector_get(v, 0)); 20 | printf("%d ", vector_get(v, 1)); 21 | printf("%d\n", vector_get(v, 2)); 22 | 23 | printf("Doing a bunch of vector_set()s\n"); 24 | vector_set(v, 0, 98); 25 | vector_set(v, 11, 15); 26 | vector_set(v, 15, -23); 27 | vector_set(v, 24, 65); 28 | vector_set(v, 500, 3); 29 | vector_set(v, 12, -123); 30 | vector_set(v, 15, 21); 31 | vector_set(v, 25, 43); 32 | 33 | printf("These should be equal:\n"); 34 | printf("98 = %d\n", vector_get(v, 0)); 35 | printf("15 = %d\n", vector_get(v, 11)); 36 | printf("65 = %d\n", vector_get(v, 24)); 37 | printf("-123 = %d\n", vector_get(v, 12)); 38 | printf("21 = %d\n", vector_get(v, 15)); 39 | printf("43 = %d\n", vector_get(v, 25)); 40 | printf("0 = %d\n", vector_get(v, 23)); 41 | printf("0 = %d\n", vector_get(v, 1)); 42 | printf("0 = %d\n", vector_get(v, 501)); 43 | printf("3 = %d\n", vector_get(v, 500)); 44 | 45 | vector_delete(v); 46 | 47 | printf("Test complete.\n"); 48 | 49 | return 0; 50 | } -------------------------------------------------------------------------------- /lab02/vector.c: -------------------------------------------------------------------------------- 1 | /* Include the system headers we need */ 2 | #include 3 | #include 4 | 5 | /* Include our header */ 6 | #include "vector.h" 7 | 8 | /* Define what our struct is */ 9 | struct vector_t { 10 | size_t size; 11 | int *data; 12 | }; 13 | 14 | /* Utility function to handle allocation failures. In this 15 | case we print a message and exit. */ 16 | static void allocation_failed() { 17 | fprintf(stderr, "Out of memory.\n"); 18 | exit(1); 19 | } 20 | 21 | /* Bad example of how to create a new vector */ 22 | vector_t *bad_vector_new() { 23 | /* Create the vector and a pointer to it */ 24 | vector_t *retval, v; 25 | retval = &v; 26 | 27 | /* Initialize attributes */ 28 | retval->size = 1; 29 | retval->data = malloc(sizeof(int)); 30 | if (retval->data == NULL) { 31 | allocation_failed(); 32 | } 33 | 34 | retval->data[0] = 0; 35 | return retval; 36 | } 37 | 38 | /* Another suboptimal way of creating a vector */ 39 | vector_t also_bad_vector_new() { 40 | /* Create the vector */ 41 | vector_t v; 42 | 43 | /* Initialize attributes */ 44 | v.size = 1; 45 | v.data = malloc(sizeof(int)); 46 | if (v.data == NULL) { 47 | allocation_failed(); 48 | } 49 | v.data[0] = 0; 50 | return v; 51 | } 52 | 53 | /* Create a new vector with a size (length) of 1 and set its single component to zero... the 54 | right way */ 55 | /* TODO: uncomment the code that is preceded by // */ 56 | vector_t *vector_new() { 57 | /* Declare what this function will return */ 58 | // vector_t *retval; 59 | 60 | /* First, we need to allocate memory on the heap for the struct */ 61 | // retval = /* YOUR CODE HERE */ 62 | 63 | /* Check our return value to make sure we got memory */ 64 | // if (/* YOUR CODE HERE */) { 65 | // allocation_failed(); 66 | // } 67 | 68 | /* Now we need to initialize our data. 69 | Since retval->data should be able to dynamically grow, 70 | what do you need to do? */ 71 | // retval->size = /* YOUR CODE HERE */; 72 | // retval->data = /* YOUR CODE HERE */; 73 | 74 | /* Check the data attribute of our vector to make sure we got memory */ 75 | // if (/* YOUR CODE HERE */) { 76 | // free(retval); //Why is this line necessary? 77 | // allocation_failed(); 78 | // } 79 | 80 | /* Complete the initialization by setting the single component to zero */ 81 | // /* YOUR CODE HERE */ = 0; 82 | 83 | /* and return... */ 84 | return NULL; /* UPDATE RETURN VALUE */ 85 | } 86 | 87 | /* Return the value at the specified location/component "loc" of the vector */ 88 | int vector_get(vector_t *v, size_t loc) { 89 | 90 | /* If we are passed a NULL pointer for our vector, complain about it and exit. */ 91 | if(v == NULL) { 92 | fprintf(stderr, "vector_get: passed a NULL vector.\n"); 93 | abort(); 94 | } 95 | 96 | /* If the requested location is higher than we have allocated, return 0. 97 | * Otherwise, return what is in the passed location. 98 | */ 99 | /* YOUR CODE HERE */ 100 | return 0; 101 | } 102 | 103 | /* Free up the memory allocated for the passed vector. 104 | Remember, you need to free up ALL the memory that was allocated. */ 105 | void vector_delete(vector_t *v) { 106 | /* YOUR CODE HERE */ 107 | } 108 | 109 | /* Set a value in the vector. If the extra memory allocation fails, call 110 | allocation_failed(). */ 111 | void vector_set(vector_t *v, size_t loc, int value) { 112 | /* What do you need to do if the location is greater than the size we have 113 | * allocated? Remember that unset locations should contain a value of 0. 114 | */ 115 | 116 | /* YOUR CODE HERE */ 117 | } -------------------------------------------------------------------------------- /lab02/vector.h: -------------------------------------------------------------------------------- 1 | #ifndef CS61C_VECTOR_H_ 2 | #define CS61C_VECTOR_H_ 3 | /* vector.h originally written by Jeremy Huddleston Sp2004 4 | * 5 | * So it looks like you've decided to venture into the "other" files of this 6 | * lab. Good. C Header files (the .h extension) are a way of telling other .c 7 | * files what they can have access to. You usually include stdlib.h in your 8 | * C programs, and this process is identical to including this .h file with the 9 | * one change being: 10 | * 11 | * #include "file.h" 12 | * versus 13 | * #include 14 | * 15 | * The difference is that the <> notation is for system header files and the "" 16 | * is for ones you provide yourself (in your local directory for instance). 17 | * 18 | * The header file starts off with 19 | * #ifndef CS61C_VECTOR_H_ 20 | * #define CS61C_VECTOR_H_ 21 | * 22 | * and ends with a final #endif. This prevents the file from being included 23 | * more than once which could've possibly resulted in an infinite loop of 24 | * file inclusions. 25 | * 26 | * First, we define the 'vector_t' datatype. This next line says that a 'vector_t' 27 | * is the same as a 'struct vector_t'. So anywhere in the code after this, we 28 | * can use 'vector_t *' to mean a pointer to a 'struct vector_t' (which is defined in 29 | * vector.c). We can get away with doing this even though we don't know what a 30 | * struct vector is because all struct pointers have the same representation in memory. 31 | */ 32 | 33 | #include 34 | 35 | typedef struct vector_t vector_t; 36 | 37 | /* 38 | * Next, we provide the prototypes for the functions defined in vector.c. This 39 | * is a way of telling the .c files that #include this header what they will 40 | * have access to. 41 | */ 42 | 43 | /* Create a new vector */ 44 | vector_t *vector_new(); 45 | 46 | /* Free up the memory allocated for the passed vector */ 47 | void vector_delete(vector_t *v); 48 | 49 | /* Return the value in the vector */ 50 | int vector_get(vector_t *v, size_t loc); 51 | 52 | /* Set a value in the vector */ 53 | void vector_set(vector_t *v, size_t loc, int value); 54 | 55 | #endif -------------------------------------------------------------------------------- /lab03/ex1.s: -------------------------------------------------------------------------------- 1 | .data 2 | .word 2, 4, 6, 8 3 | n: .word 9 4 | 5 | .text 6 | main: 7 | add t0, x0, x0 8 | addi t1, x0, 1 9 | la t3, n 10 | lw t3, 0(t3) 11 | fib: 12 | beq t3, x0, finish 13 | add t2, t1, t0 14 | mv t0, t1 15 | mv t1, t2 16 | addi t3, t3, -1 17 | j fib 18 | finish: 19 | addi a0, x0, 1 20 | addi a1, t0, 0 21 | ecall # print integer ecall 22 | addi a0, x0, 10 23 | ecall # terminate ecall 24 | -------------------------------------------------------------------------------- /lab03/ex2.c: -------------------------------------------------------------------------------- 1 | int source[] = {3, 1, 4, 1, 5, 9, 0}; 2 | int dest[10]; 3 | 4 | int fun(int x) { 5 | return -x * (x + 1); 6 | } 7 | 8 | int main() { 9 | int k; 10 | int sum = 0; 11 | for (k = 0; source[k] != 0; k++) { 12 | dest[k] = fun(source[k]); 13 | sum += dest[k]; 14 | } 15 | return sum; 16 | } 17 | -------------------------------------------------------------------------------- /lab03/ex2.s: -------------------------------------------------------------------------------- 1 | .globl main 2 | 3 | .data 4 | source: 5 | .word 3 6 | .word 1 7 | .word 4 8 | .word 1 9 | .word 5 10 | .word 9 11 | .word 0 12 | dest: 13 | .word 0 14 | .word 0 15 | .word 0 16 | .word 0 17 | .word 0 18 | .word 0 19 | .word 0 20 | .word 0 21 | .word 0 22 | .word 0 23 | 24 | .text 25 | fun: 26 | addi t0, a0, 1 27 | sub t1, x0, a0 28 | mul a0, t0, t1 29 | jr ra 30 | 31 | main: 32 | # BEGIN PROLOGUE 33 | addi sp, sp, -20 34 | sw s0, 0(sp) 35 | sw s1, 4(sp) 36 | sw s2, 8(sp) 37 | sw s3, 12(sp) 38 | sw ra, 16(sp) 39 | # END PROLOGUE 40 | addi t0, x0, 0 41 | addi s0, x0, 0 42 | la s1, source 43 | la s2, dest 44 | loop: 45 | slli s3, t0, 2 46 | add t1, s1, s3 47 | lw t2, 0(t1) 48 | beq t2, x0, exit 49 | add a0, x0, t2 50 | addi sp, sp, -8 51 | sw t0, 0(sp) 52 | sw t2, 4(sp) 53 | jal fun 54 | lw t0, 0(sp) 55 | lw t2, 4(sp) 56 | addi sp, sp, 8 57 | add t2, x0, a0 58 | add t3, s2, s3 59 | sw t2, 0(t3) 60 | add s0, s0, t2 61 | addi t0, t0, 1 62 | jal x0, loop 63 | exit: 64 | add a0, x0, s0 65 | # BEGIN EPILOGUE 66 | lw s0, 0(sp) 67 | lw s1, 4(sp) 68 | lw s2, 8(sp) 69 | lw s3, 12(sp) 70 | lw ra, 16(sp) 71 | addi sp, sp, 20 72 | # END EPILOGUE 73 | jr ra 74 | -------------------------------------------------------------------------------- /lab03/factorial.s: -------------------------------------------------------------------------------- 1 | .globl factorial 2 | 3 | .data 4 | n: .word 8 5 | 6 | .text 7 | main: 8 | la t0, n 9 | lw a0, 0(t0) 10 | jal ra, factorial 11 | 12 | addi a1, a0, 0 13 | addi a0, x0, 1 14 | ecall # Print Result 15 | 16 | addi a1, x0, '\n' 17 | addi a0, x0, 11 18 | ecall # Print newline 19 | 20 | addi a0, x0, 10 21 | ecall # Exit 22 | 23 | factorial: 24 | # YOUR CODE HERE 25 | -------------------------------------------------------------------------------- /lab03/lcm.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int lcm(int a, int b) { 4 | int t = a % b; 5 | if (t == 0) { 6 | return a; 7 | } 8 | return a * lcm(b, t) / t; 9 | } 10 | 11 | int main() { 12 | printf("%d\n", lcm(20, 30)); 13 | } 14 | -------------------------------------------------------------------------------- /lab03/list_map.s: -------------------------------------------------------------------------------- 1 | .globl map 2 | 3 | .text 4 | main: 5 | jal ra, create_default_list 6 | add s0, a0, x0 # a0 (and now s0) is the head of node list 7 | 8 | # Print the list 9 | add a0, s0, x0 10 | jal ra, print_list 11 | # Print a newline 12 | jal ra, print_newline 13 | 14 | # === Calling `map(head, &square)` === 15 | # Load function arguments 16 | add a0, s0, x0 # Loads the address of the first node into a0 17 | 18 | # Load the address of the "square" function into a1 (hint: check out "la" on the green sheet) 19 | ### YOUR CODE HERE ### 20 | 21 | 22 | # Issue the call to map 23 | jal ra, map 24 | 25 | # Print the squared list 26 | add a0, s0, x0 27 | jal ra, print_list 28 | jal ra, print_newline 29 | 30 | # === Calling `map(head, &decrement)` === 31 | # Because our `map` function modifies the list in-place, the decrement takes place after 32 | # the square does 33 | 34 | # Load function arguments 35 | add a0, s0, x0 # Loads the address of the first node into a0 36 | 37 | # Load the address of the "decrement" function into a1 (should be very similar to before) 38 | ### YOUR CODE HERE ### 39 | 40 | 41 | # Issue the call to map 42 | jal ra, map 43 | 44 | # Print decremented list 45 | add a0, s0, x0 46 | jal ra, print_list 47 | jal ra, print_newline 48 | 49 | addi a0, x0, 10 50 | ecall # Terminate the program 51 | 52 | map: 53 | # Prologue: Make space on the stack and back-up registers 54 | ### YOUR CODE HERE ### 55 | 56 | beq a0, x0, done # If we were given a null pointer (address 0), we're done. 57 | 58 | add s0, a0, x0 # Save address of this node in s0 59 | add s1, a1, x0 # Save address of function in s1 60 | 61 | # Remember that each node is 8 bytes long: 4 for the value followed by 4 for the pointer to next. 62 | # What does this tell you about how you access the value and how you access the pointer to next? 63 | 64 | # Load the value of the current node into a0 65 | # THINK: Why a0? 66 | ### YOUR CODE HERE ### 67 | 68 | # Call the function in question on that value. DO NOT use a label (be prepared to answer why). 69 | # Hint: Where do we keep track of the function to call? Recall the parameters of "map". 70 | ### YOUR CODE HERE ### 71 | 72 | # Store the returned value back into the node 73 | # Where can you assume the returned value is? 74 | ### YOUR CODE HERE ### 75 | 76 | # Load the address of the next node into a0 77 | # The address of the next node is an attribute of the current node. 78 | # Think about how structs are organized in memory. 79 | ### YOUR CODE HERE ### 80 | 81 | # Put the address of the function back into a1 to prepare for the recursion 82 | # THINK: why a1? What about a0? 83 | ### YOUR CODE HERE ### 84 | 85 | # Recurse 86 | ### YOUR CODE HERE ### 87 | 88 | done: 89 | # Epilogue: Restore register values and free space from the stack 90 | ### YOUR CODE HERE ### 91 | 92 | jr ra # Return to caller 93 | 94 | # === Definition of the "square" function === 95 | square: 96 | mul a0, a0, a0 97 | jr ra 98 | 99 | # === Definition of the "decrement" function === 100 | decrement: 101 | addi a0, a0, -1 102 | jr ra 103 | 104 | # === Helper functions === 105 | # You don't need to understand these, but reading them may be useful 106 | 107 | create_default_list: 108 | addi sp, sp, -12 109 | sw ra, 0(sp) 110 | sw s0, 4(sp) 111 | sw s1, 8(sp) 112 | li s0, 0 # Pointer to the last node we handled 113 | li s1, 0 # Number of nodes handled 114 | loop: # do... 115 | li a0, 8 116 | jal ra, malloc # Allocate memory for the next node 117 | sw s1, 0(a0) # node->value = i 118 | sw s0, 4(a0) # node->next = last 119 | add s0, a0, x0 # last = node 120 | addi s1, s1, 1 # i++ 121 | addi t0, x0, 10 122 | bne s1, t0, loop # ... while i!= 10 123 | lw ra, 0(sp) 124 | lw s0, 4(sp) 125 | lw s1, 8(sp) 126 | addi sp, sp, 12 127 | jr ra 128 | 129 | print_list: 130 | bne a0, x0, print_me_and_recurse 131 | jr ra # Nothing to print 132 | print_me_and_recurse: 133 | add t0, a0, x0 # t0 gets current node address 134 | lw a1, 0(t0) # a1 gets value in current node 135 | addi a0, x0, 1 # Prepare for print integer ecall 136 | ecall 137 | addi a1, x0, ' ' # a0 gets address of string containing space 138 | addi a0, x0, 11 # Prepare for print char syscall 139 | ecall 140 | lw a0, 4(t0) # a0 gets address of next node 141 | jal x0, print_list # Recurse. The value of ra hasn't been changed. 142 | 143 | print_newline: 144 | addi a1, x0, '\n' # Load in ascii code for newline 145 | addi a0, x0, 11 146 | ecall 147 | jr ra 148 | 149 | malloc: 150 | addi a1, a0, 0 151 | addi a0, x0, 9 152 | ecall 153 | jr ra 154 | -------------------------------------------------------------------------------- /lab03/pow.s: -------------------------------------------------------------------------------- 1 | .text 2 | main: 3 | addi a0, zero, 20 4 | addi a1, zero, 30 5 | jal lcm 6 | addi t0, t0, 0 7 | 8 | lcm: addi sp sp -12 9 | sw s1 0(sp) 10 | sw s0 4(sp) 11 | sw ra 8(sp) 12 | rem s1 a0 a1 # s1 = a0 % a1 13 | beq s1 x0 exit 14 | mv s0 a0 15 | mv a0 a1 16 | mv a1 s1 17 | jal ra lcm 18 | mul a0 s0 a0 19 | div a0 a0 s1 20 | exit: lw ra 8(sp) 21 | lw s0 4(sp) 22 | lw s1 0(sp) 23 | addi sp sp 12 24 | jr ra 25 | -------------------------------------------------------------------------------- /lab04/accumulatortests.s: -------------------------------------------------------------------------------- 1 | .import lotsofaccumulators.s 2 | 3 | .data 4 | inputarray: .word 1,2,3,4,5,6,7,0 5 | 6 | TestPassed: .asciiz "Test Passed!" 7 | TestFailed: .asciiz "Test Failed!" 8 | 9 | .text 10 | # Tests if the given implementation of accumulate is correct. 11 | #Input: a0 contains a pointer to the version of accumulate in question. See lotsofaccumulators.s for more details 12 | # 13 | # 14 | # 15 | #The main function currently runs a simple test that checks if accumulator works on the given input array. All versions of accumulate should pass this. 16 | #Modify the test so that you can catch the bugs in four of the five solutions! 17 | main: 18 | la a0 inputarray 19 | jal accumulatorone 20 | li t0 28 21 | beq a0 t0 Pass 22 | Fail: 23 | la a0 TestFailed 24 | jal print_string 25 | j End 26 | Pass: 27 | la a0 TestPassed 28 | jal print_string 29 | End: 30 | jal exit 31 | 32 | print_int: 33 | mv a1 a0 34 | li a0 1 35 | ecall 36 | jr ra 37 | 38 | print_string: 39 | mv a1 a0 40 | li a0 4 41 | ecall 42 | jr ra 43 | 44 | exit: 45 | li a0 10 46 | ecall -------------------------------------------------------------------------------- /lab04/cc_test.s: -------------------------------------------------------------------------------- 1 | .globl simple_fn naive_pow inc_arr 2 | 3 | .data 4 | failure_message: .asciiz "Test failed for some reason.\n" 5 | success_message: .asciiz "Sanity checks passed! Make sure there are no CC violations.\n" 6 | array: 7 | .word 1 2 3 4 5 8 | exp_inc_array_result: 9 | .word 2 3 4 5 6 10 | 11 | .text 12 | main: 13 | # We test our program by loading a bunch of random values 14 | # into a few saved registers - if any of these are modified 15 | # after these functions return, then we know calling 16 | # convention was broken by one of these functions 17 | li s0, 2623 18 | li s1, 2910 19 | # ... skipping middle registers so the file isn't too long 20 | # If we wanted to be rigorous, we would add checks for 21 | # s2-s10 as well 22 | li s11, 134 23 | # Now, we call some functions 24 | # simple_fn: should return 1 25 | jal simple_fn # Shorthand for "jal ra, simple_fn" 26 | li t0, 1 27 | bne a0, t0, failure 28 | # naive_pow: should return 2 ** 7 = 128 29 | li a0, 2 30 | li a1, 7 31 | jal naive_pow 32 | li t0, 128 33 | bne a0, t0, failure 34 | # inc_arr: increments "array" in place 35 | la a0, array 36 | li a1, 5 37 | jal inc_arr 38 | jal check_arr # Verifies inc_arr and jumps to "failure" on failure 39 | # Check the values in the saved registers for sanity 40 | li t0, 2623 41 | li t1, 2910 42 | li t2, 134 43 | bne s0, t0, failure 44 | bne s1, t1, failure 45 | bne s11, t2, failure 46 | # If none of those branches were hit, print a message and exit normally 47 | li a0, 4 48 | la a1, success_message 49 | ecall 50 | li a0, 10 51 | ecall 52 | 53 | # Just a simple function. Returns 1. 54 | # 55 | # FIXME Fix the reported error in this function (you can delete lines 56 | # if necessary, as long as the function still returns 1 in a0). 57 | simple_fn: 58 | mv a0, t0 59 | li a0, 1 60 | ret 61 | 62 | # Computes a0 to the power of a1. 63 | # This is analogous to the following C pseudocode: 64 | # 65 | # uint32_t naive_pow(uint32_t a0, uint32_t a1) { 66 | # uint32_t s0 = 1; 67 | # while (a1 != 0) { 68 | # s0 *= a0; 69 | # a1 -= 1; 70 | # } 71 | # return s0; 72 | # } 73 | # 74 | # FIXME There's a CC error with this function! 75 | # The big all-caps comments should give you a hint about what's 76 | # missing. Another hint: what does the "s" in "s0" stand for? 77 | naive_pow: 78 | # BEGIN PROLOGUE 79 | # END PROLOGUE 80 | li s0, 1 81 | naive_pow_loop: 82 | beq a1, zero, naive_pow_end 83 | mul s0, s0, a0 84 | addi a1, a1, -1 85 | j naive_pow_loop 86 | naive_pow_end: 87 | mv a0, s0 88 | # BEGIN EPILOGUE 89 | # END EPILOGUE 90 | ret 91 | 92 | # Increments the elements of an array in-place. 93 | # a0 holds the address of the start of the array, and a1 holds 94 | # the number of elements it contains. 95 | # 96 | # This function calls the "helper_fn" function, which takes in an 97 | # address as argument and increments the 32-bit value stored there. 98 | inc_arr: 99 | # BEGIN PROLOGUE 100 | # FIXME What other registers need to be saved? 101 | addi sp, sp, -4 102 | sw ra, 0(sp) 103 | # END PROLOGUE 104 | mv s0, a0 # Copy start of array to saved register 105 | mv s1, a1 # Copy length of array to saved register 106 | li t0, 0 # Initialize counter to 0 107 | inc_arr_loop: 108 | beq t0, s1, inc_arr_end 109 | slli t1, t0, 2 # Convert array index to byte offset 110 | add a0, s0, t1 # Add offset to start of array 111 | # Prepare to call helper_fn 112 | # 113 | # FIXME Add code to preserve the value in t0 before we call helper_fn 114 | # Hint: What does the "t" in "t0" stand for? 115 | # Also ask yourself this: why don't we need to preserve t1? 116 | # 117 | jal helper_fn 118 | # Finished call for helper_fn 119 | addi t0, t0, 1 # Increment counter 120 | j inc_arr_loop 121 | inc_arr_end: 122 | # BEGIN EPILOGUE 123 | lw ra, 0(sp) 124 | addi sp, sp, 4 125 | # END EPILOGUE 126 | ret 127 | 128 | # This helper function adds 1 to the value at the memory address in a0. 129 | # It doesn't return anything. 130 | # C pseudocode for what it does: "*a0 = *a0 + 1" 131 | # 132 | # FIXME This function also violates calling convention, but it might not 133 | # be reported by the Venus CC checker (try and figure out why). 134 | # You should fix the bug anyway by filling in the prologue and epilogue 135 | # as appropriate. 136 | helper_fn: 137 | # BEGIN PROLOGUE 138 | # END PROLOGUE 139 | lw t1, 0(a0) 140 | addi s0, t1, 1 141 | sw s0, 0(a0) 142 | # BEGIN EPILOGUE 143 | # END EPILOGUE 144 | ret 145 | 146 | # YOU CAN IGNORE EVERYTHING BELOW THIS COMMENT 147 | 148 | # Checks the result of inc_arr, which should contain 2 3 4 5 6 after 149 | # one call. 150 | # You can safely ignore this function; it has no errors. 151 | check_arr: 152 | la t0, exp_inc_array_result 153 | la t1, array 154 | addi t2, t1, 20 # Last element is 5*4 bytes off 155 | check_arr_loop: 156 | beq t1, t2, check_arr_end 157 | lw t3, 0(t0) 158 | lw t4, 0(t1) 159 | bne t3, t4, failure 160 | addi t0, t0, 4 161 | addi t1, t1, 4 162 | j check_arr_loop 163 | check_arr_end: 164 | ret 165 | 166 | 167 | # This isn't really a function - it just prints a message, then 168 | # terminates the program on failure. Think of it like an exception. 169 | failure: 170 | li a0, 4 # String print ecall 171 | la a1, failure_message 172 | ecall 173 | li a0, 10 # Exit ecall 174 | ecall 175 | 176 | -------------------------------------------------------------------------------- /lab04/discrete_fn.s: -------------------------------------------------------------------------------- 1 | .globl f 2 | 3 | .data 4 | neg3: .asciiz "f(-3) should be 6, and it is: " 5 | neg2: .asciiz "f(-2) should be 61, and it is: " 6 | neg1: .asciiz "f(-1) should be 17, and it is: " 7 | zero: .asciiz "f(0) should be -38, and it is: " 8 | pos1: .asciiz "f(1) should be 19, and it is: " 9 | pos2: .asciiz "f(2) should be 42, and it is: " 10 | pos3: .asciiz "f(3) should be 5, and it is: " 11 | 12 | output: .word 6, 61, 17, -38, 19, 42, 5 13 | .text 14 | main: 15 | la a0, neg3 16 | jal print_str 17 | li a0, -3 18 | la a1, output 19 | jal f # evaluate f(-3); should be 6 20 | jal print_int 21 | jal print_newline 22 | 23 | la a0, neg2 24 | jal print_str 25 | li a0, -2 26 | la a1, output 27 | jal f # evaluate f(-2); should be 61 28 | jal print_int 29 | jal print_newline 30 | 31 | la a0, neg1 32 | jal print_str 33 | li a0, -1 34 | la a1, output 35 | jal f # evaluate f(-1); should be 17 36 | jal print_int 37 | jal print_newline 38 | 39 | la a0, zero 40 | jal print_str 41 | li a0, 0 42 | la a1, output 43 | jal f # evaluate f(0); should be -38 44 | jal print_int 45 | jal print_newline 46 | 47 | la a0, pos1 48 | jal print_str 49 | li a0, 1 50 | la a1, output 51 | jal f # evaluate f(1); should be 19 52 | jal print_int 53 | jal print_newline 54 | 55 | la a0, pos2 56 | jal print_str 57 | li a0, 2 58 | la a1, output 59 | jal f # evaluate f(2); should be 42 60 | jal print_int 61 | jal print_newline 62 | 63 | la a0, pos3 64 | jal print_str 65 | li a0, 3 66 | la a1, output 67 | jal f # evaluate f(3); should be 5 68 | jal print_int 69 | jal print_newline 70 | 71 | li a0, 10 72 | ecall 73 | 74 | # f takes in two arguments: 75 | # a0 is the value we want to evaluate f at 76 | # a1 is the address of the "output" array (defined above). 77 | # Think: why might having a1 be useful? 78 | f: 79 | # YOUR CODE GOES HERE! 80 | 81 | jr ra # Always remember to jr ra after your function! 82 | 83 | print_int: 84 | mv a1, a0 85 | li a0, 1 86 | ecall 87 | jr ra 88 | 89 | print_str: 90 | mv a1, a0 91 | li a0, 4 92 | ecall 93 | jr ra 94 | 95 | print_newline: 96 | li a1, '\n' 97 | li a0, 11 98 | ecall 99 | jr ra 100 | -------------------------------------------------------------------------------- /lab04/lotsofaccumulators.s: -------------------------------------------------------------------------------- 1 | .globl accumulatorone 2 | .globl accumulatortwo 3 | .globl accumulatorthree 4 | .globl accumulatorfour 5 | .globl accumulatorfive 6 | 7 | #Accumulator: 8 | #Inputs: a0 contains a pointer to an array of nonzero integers, terminated with 0 9 | #Output: a0 should return the sum of the elements of the array 10 | # 11 | #Example: Let a0 = [1,2,3,4,5,6,7,0] 12 | # 13 | # Then the expected output (in a0) is 1+2+3+4+5+6+7=28 14 | 15 | #DO NOT EDIT THIS FILE 16 | #We have provided five versions of accumulator. Only one is correct, though all five pass the sanity test above. 17 | 18 | accumulatorone: 19 | lw s0 0(a0) 20 | beq s0 x0 Endone 21 | addi sp sp -8 22 | sw s0 0(sp) 23 | sw ra 4(sp) 24 | addi a0 a0 4 25 | jal accumulatorone 26 | lw t1 0(sp) 27 | lw ra 4(sp) 28 | addi sp sp 8 29 | add a0 a0 t1 30 | jr ra 31 | Endone: 32 | li a0 0 33 | jr ra 34 | 35 | accumulatortwo: 36 | addi sp sp 4 37 | sw s0 0(sp) 38 | li t0 0 39 | li s0 0 40 | Looptwo: 41 | slli t1 t0 2 42 | add t2 a0 t1 43 | lw t3 0(t2) 44 | add s0 s0 t3 45 | addi t0 t0 1 46 | bnez t3 Looptwo 47 | j Endtwo 48 | Endtwo: 49 | mv a0 s0 50 | lw s0 0(sp) 51 | addi sp sp -4 52 | jr ra 53 | 54 | accumulatorthree: 55 | addi sp sp -8 56 | sw s0 0(sp) 57 | sw ra 4(sp) 58 | lw s0 0(a0) 59 | beq s0 x0 TailCasethree 60 | addi a0 a0 4 61 | jal accumulatorthree 62 | add a0 a0 s0 63 | j Epiloguethree 64 | TailCasethree: 65 | mv a0 x0 66 | j Epiloguethree 67 | Epiloguethree: 68 | lw s0 0(sp) 69 | lw ra 4(sp) 70 | addi sp sp 8 71 | jr ra 72 | 73 | accumulatorfour: 74 | lw t1 0(a0) 75 | beq t1 x0 Endfour 76 | add t2 t2 t1 77 | addi a0 a0 4 78 | j accumulatorfour 79 | Endfour: 80 | mv a0 t2 81 | jr ra 82 | 83 | accumulatorfive: 84 | addi sp sp -8 85 | sw s0 0(sp) 86 | sw ra 4(sp) 87 | mv s0 a0 88 | lw a0 0(a0) 89 | Loopfive: 90 | addi s0 s0 4 91 | lw t0 0(s0) 92 | add a0 a0 t0 93 | bne t0 x0 Loopfive 94 | lw s0 0(sp) 95 | lw ra 4(sp) 96 | addi sp sp 8 97 | jr ra 98 | -------------------------------------------------------------------------------- /lab04/megalistmanips.s: -------------------------------------------------------------------------------- 1 | .globl map 2 | 3 | .data 4 | arrays: .word 5, 6, 7, 8, 9 5 | .word 1, 2, 3, 4, 7 6 | .word 5, 2, 7, 4, 3 7 | .word 1, 6, 3, 8, 4 8 | .word 5, 2, 7, 8, 1 9 | 10 | start_msg: .asciiz "Lists before: \n" 11 | end_msg: .asciiz "Lists after: \n" 12 | 13 | .text 14 | main: 15 | jal create_default_list 16 | mv s0, a0 # v0 = s0 is head of node list 17 | 18 | #print "lists before: " 19 | la a1, start_msg 20 | li a0, 4 21 | ecall 22 | 23 | #print the list 24 | add a0, s0, x0 25 | jal print_list 26 | 27 | # print a newline 28 | jal print_newline 29 | 30 | # issue the map call 31 | add a0, s0, x0 # load the address of the first node into a0 32 | la a1, mystery # load the address of the function into a1 33 | 34 | jal map 35 | 36 | # print "lists after: " 37 | la a1, end_msg 38 | li a0, 4 39 | ecall 40 | 41 | # print the list 42 | add a0, s0, x0 43 | jal print_list 44 | 45 | li a0, 10 46 | ecall 47 | 48 | map: 49 | addi sp, sp, -12 50 | sw ra, 0(sp) 51 | sw s1, 4(sp) 52 | sw s0, 8(sp) 53 | 54 | beq a0, x0, done # if we were given a null pointer, we're done. 55 | 56 | add s0, a0, x0 # save address of this node in s0 57 | add s1, a1, x0 # save address of function in s1 58 | add t0, x0, x0 # t0 is a counter 59 | 60 | # remember that each node is 12 bytes long: 61 | # - 4 for the array pointer 62 | # - 4 for the size of the array 63 | # - 4 more for the pointer to the next node 64 | 65 | # also keep in mind that we should not make ANY assumption on which registers 66 | # are modified by the callees, even when we know the content inside the functions 67 | # we call. this is to enforce the abstraction barrier of calling convention. 68 | mapLoop: 69 | add t1, s0, x0 # load the address of the array of current node into t1 70 | lw t2, 4(s0) # load the size of the node's array into t2 71 | 72 | add t1, t1, t0 # offset the array address by the count 73 | lw a0, 0(t1) # load the value at that address into a0 74 | 75 | jalr s1 # call the function on that value. 76 | 77 | sw a0, 0(t1) # store the returned value back into the array 78 | addi t0, t0, 1 # increment the count 79 | bne t0, t2, mapLoop # repeat if we haven't reached the array size yet 80 | 81 | la a0, 8(s0) # load the address of the next node into a0 82 | lw a1, 0(s1) # put the address of the function back into a1 to prepare for the recursion 83 | 84 | jal map # recurse 85 | done: 86 | lw s0, 8(sp) 87 | lw s1, 4(sp) 88 | lw ra, 0(sp) 89 | addi sp, sp, 12 90 | 91 | print_newline: 92 | li a1, '\n' 93 | li a0, 11 94 | ecall 95 | jr ra 96 | 97 | mystery: 98 | mul t1, a0, a0 99 | add a0, t1, a0 100 | jr ra 101 | 102 | create_default_list: 103 | addi sp, sp, -24 104 | sw ra, 0(sp) 105 | sw s0, 4(sp) 106 | sw s1, 8(sp) 107 | sw s2, 12(sp) 108 | sw s3, 16(sp) 109 | sw s4, 20(sp) 110 | li s0, 0 # pointer to the last node we handled 111 | li s1, 0 # number of nodes handled 112 | li s2, 5 # size 113 | la s3, arrays 114 | loop: #do... 115 | li a0, 12 116 | jal malloc # get memory for the next node 117 | mv s4, a0 118 | li a0, 20 119 | jal malloc # get memory for this array 120 | 121 | sw a0, 0(s4) # node->arr = malloc 122 | lw a0, 0(s4) 123 | mv a1, s3 124 | jal fillArray # copy ints over to node->arr 125 | 126 | sw s2, 4(s4) # node->size = size (4) 127 | sw s0, 8(s4) # node-> next = previously created node 128 | 129 | add s0, x0, s4 # last = node 130 | addi s1, s1, 1 # i++ 131 | addi s3, s3, 20 # s3 points at next set of ints 132 | li t6 5 133 | bne s1, t6, loop # ... while i!= 5 134 | mv a0, s4 135 | lw ra, 0(sp) 136 | lw s0, 4(sp) 137 | lw s1, 8(sp) 138 | lw s2, 12(sp) 139 | lw s3, 16(sp) 140 | lw s4, 20(sp) 141 | addi sp, sp, 24 142 | jr ra 143 | 144 | fillArray: lw t0, 0(a1) #t0 gets array element 145 | sw t0, 0(a0) #node->arr gets array element 146 | lw t0, 4(a1) 147 | sw t0, 4(a0) 148 | lw t0, 8(a1) 149 | sw t0, 8(a0) 150 | lw t0, 12(a1) 151 | sw t0, 12(a0) 152 | lw t0, 16(a1) 153 | sw t0, 16(a0) 154 | jr ra 155 | 156 | print_list: 157 | bne a0, x0, printMeAndRecurse 158 | jr ra # nothing to print 159 | printMeAndRecurse: 160 | mv t0, a0 # t0 gets address of current node 161 | lw t3, 0(a0) # t3 gets array of current node 162 | li t1, 0 # t1 is index into array 163 | printLoop: 164 | slli t2, t1, 2 165 | add t4, t3, t2 166 | lw a1, 0(t4) # a0 gets value in current node's array at index t1 167 | li a0, 1 # preparte for print integer ecall 168 | ecall 169 | li a1, ' ' # a0 gets address of string containing space 170 | li a0, 11 # prepare for print string ecall 171 | ecall 172 | addi t1, t1, 1 173 | li t6 5 174 | bne t1, t6, printLoop # ... while i!= 5 175 | li a1, '\n' 176 | li a0, 11 177 | ecall 178 | lw a0, 8(t0) # a0 gets address of next node 179 | j print_list # recurse. We don't have to use jal because we already have where we want to return to in ra 180 | 181 | malloc: 182 | mv a1, a0 # Move a0 into a1 so that we can do the syscall correctly 183 | li a0, 9 184 | ecall 185 | jr ra 186 | -------------------------------------------------------------------------------- /lab04/megalistmanips_answers.txt: -------------------------------------------------------------------------------- 1 | 1. 2 | 2. 3 | 3. 4 | 4. 5 | 5. 6 | 6. -------------------------------------------------------------------------------- /lab05/.gitattributes: -------------------------------------------------------------------------------- 1 | /tests/reference-output/*.out text eol=lf 2 | /tests/student-output/*.out text eol=lf 3 | -------------------------------------------------------------------------------- /lab05/.gitignore: -------------------------------------------------------------------------------- 1 | /tests/student-output/*.out 2 | -------------------------------------------------------------------------------- /lab05/ex2.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | -------------------------------------------------------------------------------- /lab05/ex3.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | addr/data: 8 8 67 | 0 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /lab05/ex5.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /lab05/ex6.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | rot1 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | rot2 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | rot4 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | rot8 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | -------------------------------------------------------------------------------- /lab05/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import re 5 | import signal 6 | import subprocess 7 | import sys 8 | import time 9 | import traceback 10 | 11 | lab_dir_path = os.getcwd() 12 | tests_dir_path = os.path.join(os.getcwd(), "tests") 13 | logisim_path = os.path.join(os.getcwd(),"..", "tools", "logisim-evolution.jar") 14 | 15 | # logisim_env = os.environ.copy() 16 | # logisim_env["CS61C_TOOLS_ARGS"] = logisim_env.get("CS61C_TOOLS_ARGS", "") + " -q" 17 | 18 | class TestCase(): 19 | """ 20 | Runs specified circuit file and compares output against the provided reference trace file. 21 | """ 22 | 23 | def __init__(self, id, name): 24 | self.id = id 25 | self.name = name 26 | 27 | def fix_circ(self): 28 | old_data = None 29 | data = None 30 | with open(self.get_circ_path(), "rt") as test_circ: 31 | old_data = test_circ.read() 32 | import_regex = re.compile(rf"desc=\"(file#[^\"]*\b{self.id}\.circ)\"") 33 | correct_desc = f"desc=\"file#../{self.id}.circ\"" 34 | match = re.search(import_regex, old_data) 35 | if not match or match.group(0) == correct_desc: 36 | return 37 | print(f"Fixing bad import in {self.id}-test.circ") 38 | data = re.sub(import_regex, correct_desc, old_data) 39 | with open(self.get_circ_path(), "wt") as test_circ: 40 | test_circ.write(data) 41 | 42 | def get_circ_path(self): 43 | return os.path.join(tests_dir_path, f"{self.id}-test.circ") 44 | 45 | def get_expected_table_path(self): 46 | return os.path.join(tests_dir_path, "reference-output", f"{self.id}-test.out") 47 | 48 | def get_actual_table_path(self): 49 | return os.path.join(tests_dir_path, "student-output", f"{self.id}-test.out") 50 | 51 | def run(self): 52 | passed = False 53 | proc = None 54 | try: 55 | self.fix_circ() 56 | 57 | proc = subprocess.Popen(["java", "-jar", logisim_path, "-tty", "table,binary,tabs", self.get_circ_path()], stdout=subprocess.PIPE) 58 | 59 | with open(self.get_expected_table_path(), "r") as reference: 60 | passed = self.check_output(proc.stdout, reference) 61 | kill_proc(proc) 62 | if passed: 63 | return (True, "Matched expected output") 64 | else: 65 | return (False, "Did not match expected output") 66 | except KeyboardInterrupt: 67 | sys.exit(1) 68 | except SystemExit: 69 | raise 70 | except: 71 | traceback.print_exc() 72 | if proc: 73 | kill_proc(proc) 74 | return (False, "Errored while running test") 75 | 76 | def check_output(self, student, reference): 77 | passed = True 78 | student_lines = [] 79 | while True: 80 | student_line = student.readline().decode("ascii", errors="ignore").strip() 81 | reference_line = reference.readline().strip() 82 | if reference_line == "": 83 | break 84 | student_lines.append(student_line) 85 | if student_line != reference_line: 86 | passed = False 87 | output_path = self.get_actual_table_path() 88 | os.makedirs(os.path.dirname(output_path), mode=0o755, exist_ok=True) 89 | with open(output_path, "w") as f: 90 | for line in student_lines: 91 | f.write(f"{line}\n") 92 | return passed 93 | 94 | def kill_proc(proc): 95 | if proc.poll() == None: 96 | if sys.platform == "win32": 97 | os.kill(proc.pid, signal.CTRL_C_EVENT) 98 | for _ in range(10): 99 | if proc.poll() != None: 100 | break 101 | time.sleep(0.1) 102 | if proc.poll() == None: 103 | proc.kill() 104 | 105 | 106 | 107 | tests = [ 108 | TestCase("ex2", "Exercise 2: Sub-Circuits"), 109 | TestCase("ex3", "Exercise 3: Add Machine"), 110 | TestCase("ex4", "Exercise 4: FSM"), 111 | TestCase("ex5", "Exercise 5: Splitter"), 112 | TestCase("ex6", "Exercise 6: Rotate"), 113 | TestCase("ex7", "Exercise 7: Buggy Traffic Lights") 114 | ] 115 | 116 | def run_tests(tests): 117 | print("Testing files...") 118 | tests_failed = 0 119 | tests_passed = 0 120 | 121 | for test in tests: 122 | did_pass, reason = test.run() 123 | if did_pass: 124 | print(f"PASSED test: {test.name}") 125 | tests_passed += 1 126 | else: 127 | print(f"FAILED test: {test.name} ({reason})") 128 | tests_failed += 1 129 | 130 | print(f"Passed {tests_passed}/{tests_failed + tests_passed} tests") 131 | 132 | if __name__ == '__main__': 133 | run_tests(tests) 134 | -------------------------------------------------------------------------------- /lab05/tests/ex2-test.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | addr/data: 8 8 75 | 0 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 |
89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | addr/data: 3 6 260 | 24 12 1 37 0 3f 15 2a 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | -------------------------------------------------------------------------------- /lab05/tests/ex3-test.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | addr/data: 8 8 75 | 0 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 |
89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /lab05/tests/ex4-test.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | addr/data: 8 8 75 | 0 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 |
89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | addr/data: 3 1 201 | 0 1 0 1 1 0 1 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | -------------------------------------------------------------------------------- /lab05/tests/ex5-test.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | addr/data: 8 8 74 | 0 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |
88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | addr/data: 2 8 210 | 1 82 a1 5a 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | -------------------------------------------------------------------------------- /lab05/tests/ex6-test.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | addr/data: 8 8 74 | 0 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |
88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | -------------------------------------------------------------------------------- /lab05/tests/ex7-test.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | addr/data: 8 8 75 | 0 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 |
89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /lab05/tests/reference-output/ex2-test.out: -------------------------------------------------------------------------------- 1 | CYCLE A B C D SEL0 SEL1 NAND_OUT NOR_OUT XOR_OUT MUX2_OUT MUX4_OUT 2 | 000 0 0 1 0 0 1 1 1 0 0 1 3 | 001 0 1 0 0 1 0 1 0 1 1 1 4 | 010 1 0 0 0 0 0 1 0 1 1 1 5 | 011 1 1 1 0 1 1 0 0 0 1 0 6 | 100 0 0 0 0 0 0 1 1 0 0 0 7 | 101 1 1 1 1 1 1 0 0 0 1 1 8 | 110 1 0 1 0 1 0 1 0 1 0 0 9 | 111 0 1 0 1 0 1 1 0 1 0 0 10 | -------------------------------------------------------------------------------- /lab05/tests/reference-output/ex3-test.out: -------------------------------------------------------------------------------- 1 | CYCLE ADD_OUT REG_OUT 2 | 00000000 00000001 00000000 3 | 00000001 00000010 00000001 4 | 00000010 00000011 00000010 5 | 00000011 00000100 00000011 6 | 00000100 00000101 00000100 7 | 00000101 00000110 00000101 8 | 00000110 00000111 00000110 9 | 00000111 00001000 00000111 10 | 00001000 00001001 00001000 11 | 00001001 00001010 00001001 12 | 00001010 00001011 00001010 13 | 00001011 00001100 00001011 14 | 00001100 00001101 00001100 15 | 00001101 00001110 00001101 16 | 00001110 00001111 00001110 17 | 00001111 00010000 00001111 18 | -------------------------------------------------------------------------------- /lab05/tests/reference-output/ex4-test.out: -------------------------------------------------------------------------------- 1 | CYCLE FSM_IN FSM_OUT 2 | 000 0 1 3 | 001 1 1 4 | 010 0 1 5 | 011 1 1 6 | 100 1 0 7 | 101 0 0 8 | 110 1 0 9 | 111 0 0 10 | -------------------------------------------------------------------------------- /lab05/tests/reference-output/ex5-test.out: -------------------------------------------------------------------------------- 1 | CYCLE SPLIT_IN SPLIT_OUT0 SPLIT_OUT1 2 | 00 00000001 0 10000001 3 | 01 10000010 0 00000010 4 | 10 10100001 1 00100001 5 | 11 01011010 0 11011010 6 | -------------------------------------------------------------------------------- /lab05/tests/reference-output/ex6-test.out: -------------------------------------------------------------------------------- 1 | CYCLE ROTRIGHT_OUT 2 | 0000 1100011000000000 3 | 0001 0110001100000000 4 | 0010 0011000110000000 5 | 0011 0001100011000000 6 | 0100 0000110001100000 7 | 0101 0000011000110000 8 | 0110 0000001100011000 9 | 0111 0000000110001100 10 | 1000 0000000011000110 11 | 1001 0000000001100011 12 | 1010 1000000000110001 13 | 1011 1100000000011000 14 | 1100 0110000000001100 15 | 1101 0011000000000110 16 | 1110 0001100000000011 17 | 1111 1000110000000001 18 | -------------------------------------------------------------------------------- /lab05/tests/reference-output/ex7-test.out: -------------------------------------------------------------------------------- 1 | CYCLE FSM_OUT 2 | 00000000 01 3 | 00000001 01 4 | 00000001 10 5 | 00000010 10 6 | 00000010 00 7 | 00000011 00 8 | 00000011 01 9 | 00000100 01 10 | 00000100 10 11 | 00000101 10 12 | 00000101 00 13 | 00000110 00 14 | 00000110 01 15 | 00000111 01 16 | 00000111 10 17 | 00001000 10 18 | 00001000 00 19 | 00001001 00 20 | 00001001 01 21 | 00001010 01 22 | 00001010 10 23 | 00001011 10 24 | 00001011 00 25 | 00001100 00 26 | 00001100 01 27 | 00001101 01 28 | 00001101 10 29 | 00001110 10 30 | 00001110 00 31 | 00001111 00 32 | -------------------------------------------------------------------------------- /lab06/.gitattributes: -------------------------------------------------------------------------------- 1 | /tests/reference-output/*.out text eol=lf 2 | /tests/student-output/*.out text eol=lf 3 | -------------------------------------------------------------------------------- /lab06/.gitignore: -------------------------------------------------------------------------------- 1 | /tests/student-output/*.out 2 | -------------------------------------------------------------------------------- /lab06/ex1.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | addr/data: 8 8 77 | 0 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /lab06/ex1.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/61c-teach/fa21-lab-starter/e48f5bfb2cd5f1d292c2eb1f418a2186577803bd/lab06/ex1.txt -------------------------------------------------------------------------------- /lab06/ex2.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | addr/data: 8 8 76 | 0 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 |
89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /lab06/ex2.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/61c-teach/fa21-lab-starter/e48f5bfb2cd5f1d292c2eb1f418a2186577803bd/lab06/ex2.txt -------------------------------------------------------------------------------- /lab06/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import re 5 | import signal 6 | import subprocess 7 | import sys 8 | import time 9 | import traceback 10 | 11 | lab_dir_path = os.getcwd() 12 | tests_dir_path = os.path.join(os.getcwd(), "tests") 13 | logisim_path = os.path.join(os.getcwd(),"..", "tools", "logisim-evolution.jar") 14 | 15 | # logisim_env = os.environ.copy() 16 | # logisim_env["CS61C_TOOLS_ARGS"] = logisim_env.get("CS61C_TOOLS_ARGS", "") + " -q" 17 | 18 | class TestCase(): 19 | """ 20 | Runs specified circuit file and compares output against the provided reference trace file. 21 | """ 22 | 23 | def __init__(self, id, name): 24 | self.id = id 25 | self.name = name 26 | 27 | def fix_circ(self): 28 | old_data = None 29 | data = None 30 | with open(self.get_circ_path(), "rt") as test_circ: 31 | old_data = test_circ.read() 32 | import_regex = re.compile(rf"desc=\"(file#[^\"]*\b{self.id}\.circ)\"") 33 | correct_desc = f"desc=\"file#../{self.id}.circ\"" 34 | match = re.search(import_regex, old_data) 35 | if not match or match.group(0) == correct_desc: 36 | return 37 | print(f"Fixing bad import in {self.id}-test.circ") 38 | data = re.sub(import_regex, correct_desc, old_data) 39 | with open(self.get_circ_path(), "wt") as test_circ: 40 | test_circ.write(data) 41 | 42 | def get_circ_path(self): 43 | return os.path.join(tests_dir_path, f"{self.id}-test.circ") 44 | 45 | def get_expected_table_path(self): 46 | return os.path.join(tests_dir_path, "reference-output", f"{self.id}-test.out") 47 | 48 | def get_actual_table_path(self): 49 | return os.path.join(tests_dir_path, "student-output", f"{self.id}-test.out") 50 | 51 | def run(self): 52 | passed = False 53 | proc = None 54 | try: 55 | self.fix_circ() 56 | 57 | proc = subprocess.Popen(["java", "-jar", logisim_path, "-tty", "table,binary,tabs", self.get_circ_path()], stdout=subprocess.PIPE) 58 | 59 | with open(self.get_expected_table_path(), "r") as reference: 60 | passed = self.check_output(proc.stdout, reference) 61 | kill_proc(proc) 62 | if passed: 63 | return (True, "Matched expected output") 64 | else: 65 | return (False, "Did not match expected output") 66 | except KeyboardInterrupt: 67 | sys.exit(1) 68 | except SystemExit: 69 | raise 70 | except: 71 | traceback.print_exc() 72 | if proc: 73 | kill_proc(proc) 74 | return (False, "Errored while running test") 75 | 76 | def check_output(self, student, reference): 77 | passed = True 78 | student_lines = [] 79 | while True: 80 | student_line = student.readline().decode("ascii", errors="ignore").strip() 81 | reference_line = reference.readline().strip() 82 | if reference_line == "": 83 | break 84 | student_lines.append(student_line) 85 | if student_line != reference_line: 86 | passed = False 87 | output_path = self.get_actual_table_path() 88 | os.makedirs(os.path.dirname(output_path), mode=0o755, exist_ok=True) 89 | with open(output_path, "w") as f: 90 | for line in student_lines: 91 | f.write(f"{line}\n") 92 | return passed 93 | 94 | def kill_proc(proc): 95 | if proc.poll() == None: 96 | proc.terminate() 97 | for _ in range(10): 98 | if proc.poll() != None: 99 | return 100 | time.sleep(0.1) 101 | if proc.poll() == None: 102 | proc.kill() 103 | 104 | 105 | 106 | tests = [ 107 | TestCase("ex2", "Exercise 2: Pipe that Line"), 108 | ] 109 | 110 | def run_tests(tests): 111 | print("Testing files...") 112 | tests_failed = 0 113 | tests_passed = 0 114 | 115 | for test in tests: 116 | did_pass, reason = test.run() 117 | if did_pass: 118 | print(f"PASSED test: {test.name}") 119 | tests_passed += 1 120 | else: 121 | print(f"FAILED test: {test.name} ({reason})") 122 | tests_failed += 1 123 | 124 | print(f"Passed {tests_passed}/{tests_failed + tests_passed} tests") 125 | 126 | if __name__ == '__main__': 127 | run_tests(tests) 128 | -------------------------------------------------------------------------------- /lab06/tests/ex2-test.circ: -------------------------------------------------------------------------------- 1 | 2 | 3 | This file is intended to be loaded by Logisim-evolution (https://github.com/reds-heig/logisim-evolution). 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | addr/data: 8 8 76 | 0 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | addr/data: 8 8 222 | 3 2 fc 1 2 fb 1 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | -------------------------------------------------------------------------------- /lab06/tests/reference-output/ex2-test.out: -------------------------------------------------------------------------------- 1 | OUT1 CYCLE 2 | 00000000 00000000 3 | 00000000 00000001 4 | 00001001 00000010 5 | 00001101 00000011 6 | 00011101 00000100 7 | 00011110 00000101 8 | 00100010 00000110 9 | 00111011 00000111 10 | 00111100 00001000 11 | 00111100 00001001 12 | 00111100 00001010 13 | 00111100 00001011 14 | 00111100 00001100 15 | 00111100 00001101 16 | 00111100 00001110 17 | 00111100 00001111 18 | 00111100 00010000 19 | 00111100 00010001 20 | 00111100 00010010 21 | 00111100 00010011 22 | 00111100 00010100 23 | 00111100 00010101 24 | 00111100 00010110 25 | 00111100 00010111 26 | 00111100 00011000 27 | 00111100 00011001 28 | 00111100 00011010 29 | 00111100 00011011 30 | 00111100 00011100 31 | 00111100 00011101 32 | 00111100 00011110 33 | 00111100 00011111 34 | 00111100 00100000 35 | 00111100 00100001 36 | 00111100 00100010 37 | 00111100 00100011 38 | 00111100 00100100 39 | 00111100 00100101 40 | 00111100 00100110 41 | 00111100 00100111 42 | 00111100 00101000 43 | 00111100 00101001 44 | 00111100 00101010 45 | 00111100 00101011 46 | 00111100 00101100 47 | 00111100 00101101 48 | 00111100 00101110 49 | 00111100 00101111 50 | 00111100 00110000 51 | 00111100 00110001 52 | 00111100 00110010 53 | 00111100 00110011 54 | 00111100 00110100 55 | 00111100 00110101 56 | 00111100 00110110 57 | 00111100 00110111 58 | 00111100 00111000 59 | 00111100 00111001 60 | 00111100 00111010 61 | 00111100 00111011 62 | 00111100 00111100 63 | 00111100 00111101 64 | 00111100 00111110 65 | 00111100 00111111 66 | 00111100 01000000 67 | 00111100 01000001 68 | 00111100 01000010 69 | 00111100 01000011 70 | 00111100 01000100 71 | 00111100 01000101 72 | 00111100 01000110 73 | 00111100 01000111 74 | 00111100 01001000 75 | 00111100 01001001 76 | 00111100 01001010 77 | 00111100 01001011 78 | 00111100 01001100 79 | 00111100 01001101 80 | 00111100 01001110 81 | 00111100 01001111 82 | 00111100 01010000 83 | 00111100 01010001 84 | 00111100 01010010 85 | 00111100 01010011 86 | 00111100 01010100 87 | 00111100 01010101 88 | 00111100 01010110 89 | 00111100 01010111 90 | 00111100 01011000 91 | 00111100 01011001 92 | 00111100 01011010 93 | 00111100 01011011 94 | 00111100 01011100 95 | 00111100 01011101 96 | 00111100 01011110 97 | 00111100 01011111 98 | 00111100 01100000 99 | 00111100 01100001 100 | 00111100 01100010 101 | 00111100 01100011 102 | 00111100 01100100 103 | 00111100 01100101 104 | 00111100 01100110 105 | 00111100 01100111 106 | 00111100 01101000 107 | 00111100 01101001 108 | 00111100 01101010 109 | 00111100 01101011 110 | 00111100 01101100 111 | 00111100 01101101 112 | 00111100 01101110 113 | 00111100 01101111 114 | 00111100 01110000 115 | 00111100 01110001 116 | 00111100 01110010 117 | 00111100 01110011 118 | 00111100 01110100 119 | 00111100 01110101 120 | 00111100 01110110 121 | 00111100 01110111 122 | 00111100 01111000 123 | 00111100 01111001 124 | 00111100 01111010 125 | 00111100 01111011 126 | 00111100 01111100 127 | 00111100 01111101 128 | 00111100 01111110 129 | 00111100 01111111 130 | 00111100 10000000 131 | 00111100 10000001 132 | 00111100 10000010 133 | 00111100 10000011 134 | 00111100 10000100 135 | 00111100 10000101 136 | 00111100 10000110 137 | 00111100 10000111 138 | 00111100 10001000 139 | 00111100 10001001 140 | 00111100 10001010 141 | 00111100 10001011 142 | 00111100 10001100 143 | 00111100 10001101 144 | 00111100 10001110 145 | 00111100 10001111 146 | 00111100 10010000 147 | 00111100 10010001 148 | 00111100 10010010 149 | 00111100 10010011 150 | 00111100 10010100 151 | 00111100 10010101 152 | 00111100 10010110 153 | 00111100 10010111 154 | 00111100 10011000 155 | 00111100 10011001 156 | 00111100 10011010 157 | 00111100 10011011 158 | 00111100 10011100 159 | 00111100 10011101 160 | 00111100 10011110 161 | 00111100 10011111 162 | 00111100 10100000 163 | 00111100 10100001 164 | 00111100 10100010 165 | 00111100 10100011 166 | 00111100 10100100 167 | 00111100 10100101 168 | 00111100 10100110 169 | 00111100 10100111 170 | 00111100 10101000 171 | 00111100 10101001 172 | 00111100 10101010 173 | 00111100 10101011 174 | 00111100 10101100 175 | 00111100 10101101 176 | 00111100 10101110 177 | 00111100 10101111 178 | 00111100 10110000 179 | 00111100 10110001 180 | 00111100 10110010 181 | 00111100 10110011 182 | 00111100 10110100 183 | 00111100 10110101 184 | 00111100 10110110 185 | 00111100 10110111 186 | 00111100 10111000 187 | 00111100 10111001 188 | 00111100 10111010 189 | 00111100 10111011 190 | 00111100 10111100 191 | 00111100 10111101 192 | 00111100 10111110 193 | 00111100 10111111 194 | 00111100 11000000 195 | 00111100 11000001 196 | 00111100 11000010 197 | 00111100 11000011 198 | 00111100 11000100 199 | 00111100 11000101 200 | 00111100 11000110 201 | 00111100 11000111 202 | 00111100 11001000 203 | 00111100 11001001 204 | 00111100 11001010 205 | 00111100 11001011 206 | 00111100 11001100 207 | 00111100 11001101 208 | 00111100 11001110 209 | 00111100 11001111 210 | 00111100 11010000 211 | 00111100 11010001 212 | 00111100 11010010 213 | 00111100 11010011 214 | 00111100 11010100 215 | 00111100 11010101 216 | 00111100 11010110 217 | 00111100 11010111 218 | 00111100 11011000 219 | 00111100 11011001 220 | 00111100 11011010 221 | 00111100 11011011 222 | 00111100 11011100 223 | 00111100 11011101 224 | 00111100 11011110 225 | 00111100 11011111 226 | 00111100 11100000 227 | 00111100 11100001 228 | 00111100 11100010 229 | 00111100 11100011 230 | 00111100 11100100 231 | 00111100 11100101 232 | 00111100 11100110 233 | 00111100 11100111 234 | 00111100 11101000 235 | 00111100 11101001 236 | 00111100 11101010 237 | 00111100 11101011 238 | 00111100 11101100 239 | 00111100 11101101 240 | 00111100 11101110 241 | 00111100 11101111 242 | 00111100 11110000 243 | 00111100 11110001 244 | 00111100 11110010 245 | 00111100 11110011 246 | 00111100 11110100 247 | 00111100 11110101 248 | 00111100 11110110 249 | 00111100 11110111 250 | 00111100 11111000 251 | 00111100 11111001 252 | 00111100 11111010 253 | 00111100 11111011 254 | 00111100 11111100 255 | 00111100 11111101 256 | 00111100 11111110 257 | -------------------------------------------------------------------------------- /lab07/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | LD=gcc 3 | CFLAGS=-ggdb -Wall -pedantic -std=gnu99 -O3 4 | LDFLAGS= 5 | 6 | EX2_PROG=matrixMultiply 7 | 8 | EX3_OBJS=transpose.o test_transpose.o 9 | EX3_PROG=transpose 10 | 11 | ex2: 12 | $(CC) -o $(EX2_PROG) $(CFLAGS) $(EX2_PROG).c 13 | ./$(EX2_PROG) 14 | 15 | ex3: $(EX3_OBJS) 16 | $(CC) -o $(EX3_PROG) $(CFLAGS) $(EX3_OBJS) 17 | 18 | clean: 19 | -rm -rf core *.o *~ "#"*"#" Makefile.bak $(PROGS) *.dSYM 20 | 21 | -------------------------------------------------------------------------------- /lab07/cache.s: -------------------------------------------------------------------------------- 1 | # Rewriten by Stephan Kaminsky in RISC-V on 7/30/2018 2 | # This program accesses an array in ways that provide data about the cache parameters. 3 | # Coupled with the Data Cache Simulator and Memory Reference Visualization to help students 4 | # understand how the cache parameters affect cache performance. 5 | # 6 | # PSEUDOCODE: 7 | # int array[]; //Assume sizeof(int) == 4 8 | # for (k = 0; k < repcount; k++) { // repeat repcount times 9 | # /* Step through the selected array segment with the given step size. */ 10 | # for (index = 0; index < arraysize; index += stepsize) { 11 | # if(option==0) 12 | # array[index] = 0; // Option 0: One cache access - write 13 | # else 14 | # array[index] = array[index] + 1; // Option 1: Two cache accesses - read AND write 15 | # } 16 | # } 17 | 18 | .data 19 | array: .word 2048 # max array size specified in BYTES (DO NOT CHANGE) 20 | 21 | .text 22 | ################################################################################################## 23 | # You MAY change the code below this section 24 | main: li a0, 256 # array size in BYTES (power of 2 < array size) 25 | li a1, 2 # step size (power of 2 > 0) 26 | li a2, 1 # rep count (int > 0) 27 | li a3, 1 # 0 - option 0, 1 - option 1 28 | # You MAY change the code above this section 29 | ################################################################################################## 30 | 31 | jal accessWords # lw/sw 32 | 33 | li a0,10 # exit 34 | ecall 35 | 36 | # SUMMARY OF REGISTER USE: 37 | # a0 = array size in bytes 38 | # a1 = step size 39 | # a2 = number of times to repeat 40 | # a3 = 0 (W) / 1 (RW) 41 | # s0 = moving array ptr 42 | # s1 = array limit (ptr) 43 | 44 | accessWords: 45 | la s0, array # ptr to array 46 | add s1, s0, a0 # hardcode array limit (ptr) 47 | slli t1, a1, 2 # multiply stepsize by 4 because WORDS 48 | wordLoop: 49 | beq a3, zero, wordZero 50 | 51 | lw t0, 0(s0) # array[index/4]++ 52 | addi t0, t0, 1 53 | sw t0, 0(s0) 54 | j wordCheck 55 | 56 | wordZero: 57 | sw zero, 0(s0) # array[index/4] = 0 58 | 59 | wordCheck: 60 | add s0, s0, t1 # increment ptr 61 | blt s0, s1, wordLoop # inner loop done? 62 | 63 | addi a2, a2, -1 64 | bgtz a2, accessWords # outer loop done? 65 | jr ra 66 | 67 | 68 | accessBytes: 69 | la s0, array # ptr to array 70 | add s1, s0, a0 # hardcode array limit (ptr) 71 | byteLoop: 72 | beq a3, zero, byteZero 73 | 74 | lbu t0, 0(s0) # array[index]++ 75 | addi t0, t0, 1 76 | sb t0, 0(s0) 77 | j byteCheck 78 | 79 | byteZero: 80 | sb zero, 0(s0) # array[index] = 0 81 | 82 | byteCheck: 83 | add s0, s0, a1 # increment ptr 84 | blt s0, s1, byteLoop # inner loop done? 85 | 86 | addi a2, a2, -1 87 | bgtz a2, accessBytes # outer loop done? 88 | jr ra 89 | -------------------------------------------------------------------------------- /lab07/large_cache.s: -------------------------------------------------------------------------------- 1 | # Rewriten by Stephan Kaminsky in RISC-V on 7/30/2018 2 | # This program accesses an array in ways that provide data about the cache parameters. 3 | # Coupled with the Data Cache Simulator and Memory Reference Visualization to help students 4 | # understand how the cache parameters affect cache performance. 5 | # 6 | # PSEUDOCODE: 7 | # int array[]; //Assume sizeof(int) == 4 8 | # for (k = 0; k < repcount; k++) { // repeat repcount times 9 | # /* Step through the selected array segment with the given step size. */ 10 | # for (index = 0; index < arraysize; index += stepsize) { 11 | # if(option==0) 12 | # array[index] = 0; // Option 0: One cache access - write 13 | # else 14 | # array[index] = array[index] + 1; // Option 1: Two cache accesses - read AND write 15 | # } 16 | # } 17 | 18 | .data 19 | array: .word 2048 # max array size specified in BYTES (DO NOT CHANGE) 20 | 21 | .text 22 | ################################################################################################## 23 | # You MAY change the code below this section 24 | main: li a0, 256 # array size in BYTES (power of 2 < array size) 25 | li a1, 2 # step size (power of 2 > 0) 26 | li a2, 1 # rep count (int > 0) 27 | li a3, 1 # 0 - option 0, 1 - option 1 28 | # You MAY change the code above this section 29 | ################################################################################################## 30 | 31 | jal accessWords # lw/sw 32 | 33 | li a0,10 # exit 34 | ecall 35 | 36 | # SUMMARY OF REGISTER USE: 37 | # a0 = array size in bytes 38 | # a1 = step size 39 | # a2 = number of times to repeat 40 | # a3 = 0 (W) / 1 (RW) 41 | # s0 = moving array ptr 42 | # s1 = array limit (ptr) 43 | 44 | accessWords: 45 | la s0, array # ptr to array 46 | add s1, s0, a0 # hardcode array limit (ptr) 47 | slli t1, a1, 2 # multiply stepsize by 4 because WORDS 48 | wordLoop: 49 | beq a3, zero, wordZero 50 | 51 | lw t0, 0(s0) # array[index/4]++ 52 | addi t0, t0, 1 53 | sw t0, 0(s0) 54 | j wordCheck 55 | 56 | wordZero: 57 | sw zero, 0(s0) # array[index/4] = 0 58 | 59 | wordCheck: 60 | add s0, s0, t1 # increment ptr 61 | blt s0, s1, wordLoop # inner loop done? 62 | 63 | addi a2, a2, -1 64 | bgtz a2, accessWords # outer loop done? 65 | jr ra 66 | 67 | 68 | accessBytes: 69 | la s0, array # ptr to array 70 | add s1, s0, a0 # hardcode array limit (ptr) 71 | byteLoop: 72 | beq a3, zero, byteZero 73 | 74 | lbu t0, 0(s0) # array[index]++ 75 | addi t0, t0, 1 76 | sb t0, 0(s0) 77 | j byteCheck 78 | 79 | byteZero: 80 | sb zero, 0(s0) # array[index] = 0 81 | 82 | byteCheck: 83 | add s0, s0, a1 # increment ptr 84 | blt s0, s1, byteLoop # inner loop done? 85 | 86 | addi a2, a2, -1 87 | bgtz a2, accessBytes # outer loop done? 88 | jr ra 89 | -------------------------------------------------------------------------------- /lab07/matrixMultiply.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | /* To save you time, we are including all 6 variants of the loop ordering 8 | as separate functions and then calling them using function pointers. 9 | The reason for having separate functions that are nearly identical is 10 | to avoid counting any extraneous processing towards the computation 11 | time. This includes I/O accesses (printf) and conditionals (if/switch). 12 | I/O accesses are slow and conditional/branching statements could 13 | unfairly bias results (lower cases in switches must run through more 14 | case statements on each iteration). 15 | */ 16 | void multMat1( int n, float *A, float *B, float *C ) { 17 | int i,j,k; 18 | /* This is ijk loop order. */ 19 | for( i = 0; i < n; i++ ) 20 | for( j = 0; j < n; j++ ) 21 | for( k = 0; k < n; k++ ) 22 | C[i+j*n] += A[i+k*n]*B[k+j*n]; 23 | } 24 | 25 | void multMat2( int n, float *A, float *B, float *C ) { 26 | int i,j,k; 27 | /* This is ikj loop order. */ 28 | for( i = 0; i < n; i++ ) 29 | for( k = 0; k < n; k++ ) 30 | for( j = 0; j < n; j++ ) 31 | C[i+j*n] += A[i+k*n]*B[k+j*n]; 32 | } 33 | 34 | void multMat3( int n, float *A, float *B, float *C ) { 35 | int i,j,k; 36 | /* This is jik loop order. */ 37 | for( j = 0; j < n; j++ ) 38 | for( i = 0; i < n; i++ ) 39 | for( k = 0; k < n; k++ ) 40 | C[i+j*n] += A[i+k*n]*B[k+j*n]; 41 | } 42 | 43 | void multMat4( int n, float *A, float *B, float *C ) { 44 | int i,j,k; 45 | /* This is jki loop order. */ 46 | for( j = 0; j < n; j++ ) 47 | for( k = 0; k < n; k++ ) 48 | for( i = 0; i < n; i++ ) 49 | C[i+j*n] += A[i+k*n]*B[k+j*n]; 50 | } 51 | 52 | void multMat5( int n, float *A, float *B, float *C ) { 53 | int i,j,k; 54 | /* This is kij loop order. */ 55 | for( k = 0; k < n; k++ ) 56 | for( i = 0; i < n; i++ ) 57 | for( j = 0; j < n; j++ ) 58 | C[i+j*n] += A[i+k*n]*B[k+j*n]; 59 | } 60 | 61 | void multMat6( int n, float *A, float *B, float *C ) { 62 | int i,j,k; 63 | /* This is kji loop order. */ 64 | for( k = 0; k < n; k++ ) 65 | for( j = 0; j < n; j++ ) 66 | for( i = 0; i < n; i++ ) 67 | C[i+j*n] += A[i+k*n]*B[k+j*n]; 68 | } 69 | 70 | /* uses timing features from sys/time.h that you haven't seen before */ 71 | int main( int argc, char **argv ) { 72 | int nmax = 1000,i; 73 | 74 | void (*orderings[])(int,float *,float *,float *) = 75 | {&multMat1,&multMat2,&multMat3,&multMat4,&multMat5,&multMat6}; 76 | char *names[] = {"ijk","ikj","jik","jki","kij","kji"}; 77 | 78 | float *A = (float *)malloc( nmax*nmax * sizeof(float)); 79 | float *B = (float *)malloc( nmax*nmax * sizeof(float)); 80 | float *C = (float *)malloc( nmax*nmax * sizeof(float)); 81 | 82 | struct timeval start, end; 83 | 84 | /* fill matrices with random numbers */ 85 | for( i = 0; i < nmax*nmax; i++ ) A[i] = drand48()*2-1; 86 | for( i = 0; i < nmax*nmax; i++ ) B[i] = drand48()*2-1; 87 | for( i = 0; i < nmax*nmax; i++ ) C[i] = drand48()*2-1; 88 | 89 | for( i = 0; i < 6; i++) { 90 | /* multiply matrices and measure the time */ 91 | gettimeofday( &start, NULL ); 92 | (*orderings[i])( nmax, A, B, C ); 93 | gettimeofday( &end, NULL ); 94 | 95 | /* convert time to Gflop/s */ 96 | double seconds = (end.tv_sec - start.tv_sec) + 97 | 1.0e-6 * (end.tv_usec - start.tv_usec); 98 | double Gflops = 2e-9*nmax*nmax*nmax/seconds; 99 | printf( "%s:\tn = %d, %.3f Gflop/s\n", names[i], nmax, Gflops ); 100 | } 101 | 102 | free( A ); 103 | free( B ); 104 | free( C ); 105 | 106 | printf("\n\n"); 107 | 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /lab07/test_transpose.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "transpose.h" 6 | 7 | void benchmark(int *A, int *B, int n, int blocksize, 8 | void (*transpose)(int, int, int*, int*), char *description) { 9 | 10 | int i, j; 11 | printf("Testing %s: ", description); 12 | 13 | /* initialize A,B to random integers */ 14 | srand48( time( NULL ) ); 15 | for( i = 0; i < n*n; i++ ) A[i] = lrand48( ); 16 | for( i = 0; i < n*n; i++ ) B[i] = lrand48( ); 17 | 18 | /* measure performance */ 19 | struct timeval start, end; 20 | 21 | gettimeofday( &start, NULL ); 22 | transpose( n, blocksize, B, A ); 23 | gettimeofday( &end, NULL ); 24 | 25 | double seconds = (end.tv_sec - start.tv_sec) + 26 | 1.0e-6 * (end.tv_usec - start.tv_usec); 27 | printf( "%g milliseconds\n", seconds*1e3 ); 28 | 29 | /* check correctness */ 30 | for( i = 0; i < n; i++ ) { 31 | for( j = 0; j < n; j++ ) { 32 | if( B[j+i*n] != A[i+j*n] ) { 33 | printf("Error!!!! Transpose does not result in correct answer!!\n"); 34 | exit( -1 ); 35 | } 36 | } 37 | } 38 | } 39 | 40 | int main( int argc, char **argv ) { 41 | if (argc != 3) { 42 | printf("Usage: transpose \nExiting.\n"); 43 | exit(1); 44 | } 45 | 46 | int n = atoi(argv[1]); 47 | int blocksize = atoi(argv[2]); 48 | 49 | /* allocate an n*n block of integers for the matrices */ 50 | int *A = (int*)malloc( n*n*sizeof(int) ); 51 | int *B = (int*)malloc( n*n*sizeof(int) ); 52 | 53 | /* run tests */ 54 | benchmark(A, B, n, blocksize, transpose_naive, "naive transpose"); 55 | benchmark(A, B, n, blocksize, transpose_blocking, "transpose with blocking"); 56 | 57 | /* release resources */ 58 | free( A ); 59 | free( B ); 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /lab07/transpose.c: -------------------------------------------------------------------------------- 1 | #include "transpose.h" 2 | 3 | /* The naive transpose function as a reference. */ 4 | void transpose_naive(int n, int blocksize, int *dst, int *src) { 5 | for (int x = 0; x < n; x++) { 6 | for (int y = 0; y < n; y++) { 7 | dst[y + x * n] = src[x + y * n]; 8 | } 9 | } 10 | } 11 | 12 | /* Implement cache blocking below. You should NOT assume that n is a 13 | * multiple of the block size. */ 14 | void transpose_blocking(int n, int blocksize, int *dst, int *src) { 15 | // YOUR CODE HERE 16 | } 17 | -------------------------------------------------------------------------------- /lab07/transpose.h: -------------------------------------------------------------------------------- 1 | void transpose_naive(int n, int blocksize, int *dst, int *src); 2 | void transpose_blocking(int n, int blocksize, int *dst, int *src); 3 | -------------------------------------------------------------------------------- /lab09/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=--std=c99 -Wall -O0 3 | 4 | simd: test_simd.o simd.o 5 | $(CC) $(CFLAGS) -o simd test_simd.o simd.o 6 | 7 | test_simd.o: simd.c simd.h 8 | $(CC) $(CFLAGS) -c test_simd.c 9 | 10 | simd.o: simd.c simd.h 11 | $(CC) $(CFLAGS) -c simd.c 12 | 13 | clean: 14 | rm -f simd 15 | rm -f *.o 16 | -------------------------------------------------------------------------------- /lab09/simd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "simd.h" 5 | 6 | long long int sum(int vals[NUM_ELEMS]) { 7 | clock_t start = clock(); 8 | 9 | long long int sum = 0; 10 | for(unsigned int w = 0; w < OUTER_ITERATIONS; w++) { 11 | for(unsigned int i = 0; i < NUM_ELEMS; i++) { 12 | if(vals[i] >= 128) { 13 | sum += vals[i]; 14 | } 15 | } 16 | } 17 | clock_t end = clock(); 18 | printf("Time taken: %Lf s\n", (long double)(end - start) / CLOCKS_PER_SEC); 19 | return sum; 20 | } 21 | 22 | long long int sum_unrolled(int vals[NUM_ELEMS]) { 23 | clock_t start = clock(); 24 | long long int sum = 0; 25 | 26 | for(unsigned int w = 0; w < OUTER_ITERATIONS; w++) { 27 | for(unsigned int i = 0; i < NUM_ELEMS / 4 * 4; i += 4) { 28 | if(vals[i] >= 128) sum += vals[i]; 29 | if(vals[i + 1] >= 128) sum += vals[i + 1]; 30 | if(vals[i + 2] >= 128) sum += vals[i + 2]; 31 | if(vals[i + 3] >= 128) sum += vals[i + 3]; 32 | } 33 | 34 | // TAIL CASE, for when NUM_ELEMS isn't a multiple of 4 35 | // NUM_ELEMS / 4 * 4 is the largest multiple of 4 less than NUM_ELEMS 36 | // Order is important, since (NUM_ELEMS / 4) effectively rounds down first 37 | for(unsigned int i = NUM_ELEMS / 4 * 4; i < NUM_ELEMS; i++) { 38 | if (vals[i] >= 128) { 39 | sum += vals[i]; 40 | } 41 | } 42 | } 43 | clock_t end = clock(); 44 | printf("Time taken: %Lf s\n", (long double)(end - start) / CLOCKS_PER_SEC); 45 | return sum; 46 | } 47 | 48 | long long int sum_simd(int vals[NUM_ELEMS]) { 49 | clock_t start = clock(); 50 | __m128i _127 = _mm_set1_epi32(127); // This is a vector with 127s in it... Why might you need this? 51 | long long int result = 0; // This is where you should put your final result! 52 | /* DO NOT MODIFY ANYTHING ABOVE THIS LINE (in this function) */ 53 | 54 | for(unsigned int w = 0; w < OUTER_ITERATIONS; w++) { 55 | /* YOUR CODE GOES HERE */ 56 | 57 | /* Hint: you'll need a tail case. */ 58 | } 59 | 60 | /* DO NOT MODIFY ANYTHING BELOW THIS LINE (in this function) */ 61 | clock_t end = clock(); 62 | printf("Time taken: %Lf s\n", (long double)(end - start) / CLOCKS_PER_SEC); 63 | return result; 64 | } 65 | 66 | long long int sum_simd_unrolled(int vals[NUM_ELEMS]) { 67 | clock_t start = clock(); 68 | __m128i _127 = _mm_set1_epi32(127); 69 | long long int result = 0; 70 | /* DO NOT MODIFY ANYTHING ABOVE THIS LINE (in this function) */ 71 | 72 | for(unsigned int w = 0; w < OUTER_ITERATIONS; w++) { 73 | /* YOUR CODE GOES HERE */ 74 | /* Copy your sum_simd() implementation here, and unroll it */ 75 | 76 | /* Hint: you'll need 1 or maybe 2 tail cases here. */ 77 | } 78 | 79 | /* DO NOT MODIFY ANYTHING BELOW THIS LINE (in this function) */ 80 | clock_t end = clock(); 81 | printf("Time taken: %Lf s\n", (long double)(end - start) / CLOCKS_PER_SEC); 82 | return result; 83 | } 84 | -------------------------------------------------------------------------------- /lab09/simd.h: -------------------------------------------------------------------------------- 1 | #ifndef SIMD_H 2 | #define SIMD_H 3 | 4 | #include 5 | 6 | #define NUM_ELEMS ((1 << 16) + 10) 7 | #define OUTER_ITERATIONS (1 << 14) 8 | 9 | long long int sum(int vals[NUM_ELEMS]); 10 | 11 | long long int sum_unrolled(int vals[NUM_ELEMS]); 12 | 13 | long long int sum_simd(int vals[NUM_ELEMS]); 14 | 15 | long long int sum_simd_unrolled(int vals[NUM_ELEMS]); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /lab09/test_simd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "simd.h" 5 | 6 | /* ***DON'T MODIFY THIS FILE! You should only need to modify simd.c!*** */ 7 | 8 | int main(int argc, char* argv[]) { 9 | printf("Let's generate a randomized array.\n"); 10 | int vals[NUM_ELEMS]; 11 | long long int reference; 12 | long long int simd; 13 | long long int simdu; 14 | for (unsigned int i = 0; i < NUM_ELEMS; i++) vals[i] = rand() % 256; 15 | int success = 0; 16 | 17 | printf("Starting randomized sum.\n"); 18 | clock_t start = clock(); 19 | reference = sum(vals); 20 | clock_t end = clock(); 21 | printf("Sum: %lld\n", reference); 22 | clock_t reft = end - start; 23 | 24 | printf("Starting randomized unrolled sum.\n"); 25 | printf("Sum: %lld\n", sum_unrolled(vals)); 26 | 27 | printf("Starting randomized SIMD sum.\n"); 28 | start = clock(); 29 | simd = sum_simd(vals); 30 | end = clock(); 31 | printf("Sum: %lld\n", simd); 32 | clock_t simdt = end - start; 33 | 34 | if (simd != reference) { 35 | printf("Test Failed! SIMD sum %lld doesn't match reference sum %lld!\n", simd, reference); 36 | success = 1; 37 | } 38 | 39 | if (reft <= simdt * 2) { 40 | printf("Test Failed! SIMD sum provided less than 2X speedup.\n"); 41 | success = 1; 42 | } 43 | 44 | printf("Starting randomized SIMD unrolled sum.\n"); 45 | start = clock(); 46 | simdu = sum_simd_unrolled(vals); 47 | end = clock(); 48 | printf("Sum: %lld\n", simdu); 49 | clock_t simdut = end - start; 50 | 51 | if (simdu != reference) { 52 | printf("Test Failed! SIMD_UNROLLED sum %lld doesn't match reference sum %lld!\n", simdu, reference); 53 | success = 1; 54 | } 55 | 56 | if (simdt <= simdut) { 57 | printf("Test Failed! SIMD unrolled function provided no speedup.\n"); 58 | success = 1; 59 | } 60 | 61 | if (!success) { 62 | printf("All tests Passed! Correct values were produced, and speedups were achieved!\n"); 63 | return 0; 64 | } else { 65 | return 1; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lab10/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS= -std=gnu99 -c -fopenmp 3 | LDFLAGS=-fopenmp 4 | OBJECTS=$(SOURCES:.c=.o) 5 | EXECUTABLES=hello v_add dotp 6 | 7 | .PHONY: all clean 8 | 9 | all: $(EXECUTABLES) 10 | 11 | hello: hello.o 12 | dotp: dotp.o omp_apps.o 13 | v_add: v_add.o omp_apps.o 14 | 15 | $(EXECUTABLES): 16 | $(CC) $(LDFLAGS) $^ -o $@ 17 | 18 | %.o: %.c 19 | $(CC) $(CFLAGS) $< -o $@ 20 | 21 | clean: 22 | rm -f $(EXECUTABLES) *.o 23 | -------------------------------------------------------------------------------- /lab10/answers/ex2.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/61c-teach/fa21-lab-starter/e48f5bfb2cd5f1d292c2eb1f418a2186577803bd/lab10/answers/ex2.txt -------------------------------------------------------------------------------- /lab10/dotp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "omp_apps.h" 7 | 8 | int main() { 9 | double *x = gen_array(ARRAY_SIZE); 10 | double *y = gen_array(ARRAY_SIZE); 11 | double serial_result = 0.0; 12 | double result; 13 | 14 | double start_time, run_time; 15 | 16 | // calculate result serially 17 | for(int i=0; i 0.001) { 33 | printf("Manual optimized does not match reference.\n"); 34 | return -1; 35 | } 36 | 37 | printf("Manual Optimized: %d thread(s) took %f seconds\n",i,run_time); 38 | } 39 | 40 | for (int i=1; i<=num_threads; i++) { 41 | omp_set_num_threads(i); 42 | start_time = omp_get_wtime(); 43 | for(int j=0; j 0.001) { 50 | printf("Reduction optimized does not match reference.\n"); 51 | return -1; 52 | } 53 | 54 | printf("Reduction Optimized: %d thread(s) took %f seconds\n",i,run_time); 55 | } 56 | 57 | // Only run this once because it's too slow.. 58 | omp_set_num_threads(1); 59 | start_time = omp_get_wtime(); 60 | for(int j=0; j 2 | #include 3 | 4 | int main() { 5 | #pragma omp parallel 6 | { 7 | int thread_ID = omp_get_thread_num(); 8 | printf(" hello world %d\n", thread_ID); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /lab10/omp_apps.c: -------------------------------------------------------------------------------- 1 | #include "omp_apps.h" 2 | 3 | /* -------------------------------Utilties, Do Not Modify------------------------------*/ 4 | double* gen_array(int n) { 5 | double* array = (double*)malloc(n * sizeof(double)); 6 | for (int i = 0; i < n; i++) array[i] = drand48(); 7 | return array; 8 | } 9 | 10 | int verify(double* x, double* y, void(*funct)(double *x, double *y, double *z)) { 11 | double *z_v_add = (double*) malloc(ARRAY_SIZE*sizeof(double)); 12 | double *z_oracle = (double*) malloc(ARRAY_SIZE*sizeof(double)); 13 | (*funct)(x, y, z_v_add); 14 | for(int i=0; i 0.001) { 125 | pos += sprintf(pos, "Incorrect result!\n"); 126 | *pos = '\0'; 127 | return report_buf; 128 | } 129 | } 130 | 131 | for (int i = 1; i <= num_threads; i++) { 132 | omp_set_num_threads(i); 133 | start_time = omp_get_wtime(); 134 | 135 | for (int j = 0; j < REPEAT; j++) { 136 | result = dotp_reduction_optimized(x, y, arr_size); 137 | } 138 | 139 | run_time = omp_get_wtime() - start_time; 140 | pos += sprintf(pos, "Reduction Optimized: %d thread(s) took %f seconds\n", 141 | i, run_time); 142 | 143 | // verify result is correct (within some threshold) 144 | if (fabs(serial_result - result) > 0.001) { 145 | pos += sprintf(pos, "Incorrect result!\n"); 146 | *pos = '\0'; 147 | return report_buf; 148 | } 149 | } 150 | 151 | // Only run this once because it's too slow.. 152 | omp_set_num_threads(1); 153 | start_time = omp_get_wtime(); 154 | for (int j = 0; j < REPEAT; j++) result = dotp_naive(x, y, arr_size); 155 | run_time = omp_get_wtime() - start_time; 156 | 157 | pos += sprintf(pos, "Naive: %d thread(s) took %f seconds\n", 1, run_time); 158 | *pos = '\0'; 159 | return report_buf; 160 | } 161 | -------------------------------------------------------------------------------- /lab10/omp_apps.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef OMP_APPS_H 3 | #define OMP_APPS_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define REPEAT 60 12 | #define BUF_SIZE 8192 13 | 14 | #define ARRAY_SIZE 5000000 15 | 16 | void v_add_naive(double* x, double* y, double* z); 17 | void v_add_optimized_adjacent(double* x, double* y, double* z); 18 | void v_add_optimized_chunks(double* x, double* y, double* z); 19 | double dotp_naive(double* x, double* y, int arr_size); 20 | double dotp_manual_optimized(double* x, double* y, int arr_size); 21 | double dotp_reduction_optimized(double* x, double* y, int arr_size); 22 | 23 | double* gen_array(int n); 24 | int verify(double* x, double* y, void(*funct)(double *x, double *y, double *z)); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /lab10/v_add.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "omp_apps.h" 5 | 6 | int main() { 7 | // Generate input vectors and destination vector 8 | double *x = gen_array(ARRAY_SIZE); 9 | double *y = gen_array(ARRAY_SIZE); 10 | double *z = (double*) malloc(ARRAY_SIZE*sizeof(double)); 11 | 12 | // Test framework that sweeps the number of threads and times each run 13 | double start_time, run_time; 14 | int num_threads = omp_get_max_threads(); 15 | 16 | for (int i = 1; i <= num_threads; i++) 17 | { 18 | omp_set_num_threads(i); 19 | start_time = omp_get_wtime(); 20 | for(int j = 0; j < REPEAT; j++) 21 | { 22 | v_add_optimized_adjacent(x,y,z); 23 | } 24 | run_time = omp_get_wtime() - start_time; 25 | if (!verify(x, y, v_add_optimized_adjacent)) 26 | { 27 | printf("v_add optimized adjacent does not match reference.\n"); 28 | return -1; 29 | } 30 | printf("Optimized adjacent: %d thread(s) took %f seconds\n",i,run_time); 31 | } 32 | 33 | 34 | for (int i = 1; i <= num_threads; i++) 35 | { 36 | omp_set_num_threads(i); 37 | start_time = omp_get_wtime(); 38 | for(int j = 0; j < REPEAT; j++) 39 | { 40 | v_add_optimized_chunks(x,y,z); 41 | } 42 | run_time = omp_get_wtime() - start_time; 43 | if (!verify(x, y, v_add_optimized_chunks)) 44 | { 45 | printf("v_add optimized chunks does not match reference.\n"); 46 | return -1; 47 | } 48 | printf("Optimized chunks: %d thread(s) took %f seconds\n",i,run_time); 49 | } 50 | 51 | for (int i = 1; i <= num_threads; i++) 52 | { 53 | omp_set_num_threads(i); 54 | start_time = omp_get_wtime(); 55 | for(int j = 0; j < REPEAT; j++) 56 | { 57 | v_add_naive(x,y,z); 58 | } 59 | run_time = omp_get_wtime() - start_time; 60 | printf("Naive: %d thread(s) took %f seconds\n",i,run_time); 61 | } 62 | return 0; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /tools/logisim-evolution.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/61c-teach/fa21-lab-starter/e48f5bfb2cd5f1d292c2eb1f418a2186577803bd/tools/logisim-evolution.jar -------------------------------------------------------------------------------- /tools/venus.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/61c-teach/fa21-lab-starter/e48f5bfb2cd5f1d292c2eb1f418a2186577803bd/tools/venus.jar --------------------------------------------------------------------------------