From f9323bdb94b18879a551df2ca8c5cfa1e75bf65b Mon Sep 17 00:00:00 2001 From: yangminz Date: Mon, 14 Jun 2021 23:56:08 +0800 Subject: [PATCH] address, rb, bst --- cmd.py | 14 + src/algorithm/bst.c | 589 +++++++++++++++++++++++++ src/algorithm/redblack.c | 898 ++++----------------------------------- src/hardware/cpu/mmu.c | 4 +- src/headers/address.h | 46 +- src/headers/algorithm.h | 14 +- 6 files changed, 746 insertions(+), 819 deletions(-) create mode 100644 src/algorithm/bst.c diff --git a/cmd.py b/cmd.py index 6cd8ad4..c15aa80 100644 --- a/cmd.py +++ b/cmd.py @@ -262,6 +262,8 @@ def build(key): "-Wall", "-g", "-O0", "-Werror", "-std=gnu99", "-Wno-unused-but-set-variable", "-Wno-unused-variable", "-Wno-unused-function", "-I", "./src", "-DDEBUG_REDBLACK", + "./src/common/convert.c", + "./src/algorithm/bst.c", "./src/algorithm/redblack.c", "-o", "./bin/rb" ], @@ -276,6 +278,17 @@ def build(key): "-o", "./bin/trie" ], ], + "bst" : [ + [ + "/usr/bin/gcc-7", + "-Wall", "-g", "-O0", "-Werror", "-std=gnu99", "-Wno-unused-but-set-variable", "-Wno-unused-variable", "-Wno-unused-function", + "-I", "./src", + "-DDEBUG_BST", + "./src/algorithm/bst.c", + "./src/common/convert.c", + "-o", "./bin/bst" + ], + ], } if not key in gcc_map: @@ -294,6 +307,7 @@ def run(key): "false_sharing" : ["./bin/false_sharing"], "rb" : ["./bin/rb"], "trie" : ["./bin/trie"], + "bst" : ["./bin/bst"], } if not key in bin_map: print("input the correct binary key:", bin_map.keys()) diff --git a/src/algorithm/bst.c b/src/algorithm/bst.c new file mode 100644 index 0000000..0f0873b --- /dev/null +++ b/src/algorithm/bst.c @@ -0,0 +1,589 @@ +#include +#include +#include +#include +#include +#include +#include + +rb_node_t *bst_insert_node(rb_node_t *root, uint64_t val, rb_node_t **inserted); +rb_node_t *bst_delete_node(rb_node_t *root, rb_node_t *n, rb_node_t **replaced); + +// insert value to the tree +// return the updated tree root node +rb_node_t *bst_insert(rb_node_t *root, uint64_t val) +{ + rb_node_t *inserted; + return bst_insert_node(root, val, &inserted); +} + +rb_node_t *bst_insert_node(rb_node_t *root, uint64_t val, rb_node_t **inserted) +{ + // create + if (root == NULL) + { + root = malloc(sizeof(rb_node_t)); + + // update properties + root->parent = NULL; + root->left = NULL; + root->right = NULL; + root->value = val; + root->color = COLOR_BLACK; + + *inserted = root; + return root; + } + + // search the right place (leaf node) to insert data + rb_node_t *n = root; + + while (n != NULL) + { + if (val < n->value) + { + if (n->left == NULL) + { + // insert here + n->left = malloc(sizeof(rb_node_t)); + n->left->parent = n; + n->left->left = NULL; + n->left->right = NULL; + n->left->value = val; + n->left->color = COLOR_RED; + + *inserted = n->left; + return root; + } + else + { + n = n->left; + } + } + else if (val > n->value) + { + if (n->right == NULL) + { + // insert here + n->right = malloc(sizeof(rb_node_t)); + n->right->parent = n; + n->right->left = NULL; + n->right->right = NULL; + n->right->value = val; + n->right->color = COLOR_RED; + + *inserted = n->right; + return root; + } + else + { + n = n->right; + } + } + else + { + // equals + printf("bst insertion: existing value {%lx} being tried to inserted.\n", val); + exit(0); + } + } + + *inserted = NULL; + return root; +} + +rb_node_t *bst_delete(rb_node_t *root, rb_node_t *n) +{ + rb_node_t *replaced; + return bst_delete_node(root, n, &replaced); +} + +// delete the node +// return the updated tree root node +rb_node_t *bst_delete_node(rb_node_t *root, rb_node_t *n, rb_node_t **replaced) +{ + if (n == NULL) + { + return NULL; + } + + // in case root is deleted + rb_node_t *p = NULL; + int is_n_root = 0; + if (n == root) + { + // no parent pointer, create a dummy one + p = malloc(sizeof(rb_node_t)); + p->color = COLOR_BLACK; + p->left = n; + n->parent = p; + p->parent = NULL; + p->right = NULL; + is_n_root = 1; + } + else + { + p = n->parent; + is_n_root = 0; + } + + // the address of the to be deleted node + rb_node_t **par_child = NULL; + if (n == p->left) + { + par_child = &(p->left); + } + else + { + par_child = &(p->right); + } + + if (n->left == NULL && n->right == NULL) + { + ////////////////////////////////////////////// + // case 1: leaf node // + ////////////////////////////////////////////// + + *par_child = NULL; + free(n); + + if (is_n_root == 1) + { + root = NULL; + } + } + else if (n->left == NULL && n->right != NULL) + { + ////////////////////////////////////////////// + // case 2: one sub-tree is empty // + // 2.1: left tree is empty // + ////////////////////////////////////////////// + + // transplant the other sub-tree to the node to be deleted + *par_child = n->right; + n->right->parent = p; + free(n); + + if (is_n_root == 1) + { + root = n->right; + } + } + else if (n->left != NULL && n->right == NULL) + { + // 2.2 right tree is empty + + *par_child = n->left; + n->left->parent = p; + free(n); + + if (is_n_root == 1) + { + root = n->left; + } + } + else if (n->right->left == NULL) + { + ////////////////////////////////////////////// + // case 3: both sub-trees are not empty // + // 3.1: a simple remove will do the job // + ////////////////////////////////////////////// + + // transplant the left sub-tree + n->right->left = n->left; + n->left->parent = n->right; + + *par_child = n->right; + n->right->parent = p; + + free(n); + + if (is_n_root == 1) + { + root = n->right; + } + } + else if (n->right->left != NULL) + { + ////////////////////////////////////////////// + // 3.2: float up the tight upper bound // + // as root of sub-tree // + ////////////////////////////////////////////// + + rb_node_t *min_upper = n->right; + while (min_upper->left != NULL) + { + min_upper = min_upper->left; + } + + // float up min_upper + min_upper->parent->left = min_upper->right; + if (min_upper->right != NULL) + { + min_upper->right->parent = min_upper->parent; + } + + // transplant + min_upper->right = n->right; + n->right->parent = min_upper; + + min_upper->left = n->left; + n->left->parent = min_upper; + + min_upper->parent = p; + + *par_child = min_upper; + free(n); + + if (is_n_root == 1) + { + root = min_upper; + } + } + + // set the pointer to the address of the deleted node + rb_node_t *v = *par_child; + + if (is_n_root == 1) + { + free(p); + + if (root != NULL) + { + root->parent = NULL; + } + } + + // which node takes the place of the deleted node in parent + *replaced = *par_child; + return root; +} + +// find the node owning the target value +rb_node_t *bst_find(rb_node_t *root, uint64_t val) +{ + rb_node_t *n = root; + uint64_t n_value; + + while (n != NULL) + { + n_value = n->value; + + if (n_value == val) + { + return n; + } + else if (val < n_value) + { + n = n->left; + } + else + { + n = n->right; + } + } + + return NULL; +} + +void free_tree(rb_node_t *root) +{ + if (root == NULL) + { + return; + } + + free_tree(root->left); + free_tree(root->right); + + free(root); +} + +rb_node_t *build_tree(char *str) +{ + // (root node, left tree, right tree) + // for NULL node, # + + // sentinel to mark the unprocessed sub-tree + rb_node_t todo; + + // pointer stack + rb_node_t *stack[1000]; + int top = -1; + + int i = 0; + while (i < strlen(str)) + { + if (str[i] == '(') + { + // push the node as being processed + top ++; + stack[top] = malloc(sizeof(rb_node_t)); + stack[top]->parent = NULL; + stack[top]->left = &todo; + stack[top]->right = &todo; + + // scan the value + // (value, + int j = i + 1; + while ('0' <= str[j] && str[j] <= '9') + { + ++ j; + } + stack[top]->value = string2uint_range(str, i + 1, j - 1); + + i = j + 1; + continue; + } + else if (str[i] == ')') + { + // pop the being processed node + if (top == 0) + { + // pop root + return stack[0]; + } + + rb_node_t *p = stack[top - 1]; + rb_node_t *t = stack[top]; + top --; + + // else, pop this node + if (p->left == &todo) + { + p->left = t; + p->left->parent = p; + i ++; + continue; + } + else if (p->right == &todo) + { + p->right = t; + p->right->parent = p; + i ++; + continue; + } + + printf("node %p:%lx is not having any unprocessed sub-tree\n while %p:%lx is inserted into it.\n", + p, p->value, t, t->value); + exit(0); + } + else if (str[i] == '#') + { + if (top < 0) + { + assert(strlen(str) == 1); + return NULL; + } + + // push NULL node + // pop NULL node + if (stack[top]->left == &todo) + { + // must check parent's left node first + stack[top]->left = NULL; + i ++; + continue; + } + else if (stack[top]->right == &todo) + { + // then check parent's right node + stack[top]->right = NULL; + i ++; + continue; + } + + printf("node %p:(%lx) is not having any unprocessed sub-tree\n while NULL is inserted into it.\n", + stack[top], stack[top]->value); + exit(0); + } + else + { + // space, comma, new line + i ++; + continue; + } + } + + return NULL; +} + +int compare_tree(rb_node_t *a, rb_node_t *b) +{ + if (a == NULL && b == NULL) + { + return 1; + } + + if (a == NULL || b == NULL) + { + return 0; + } + + // both not NULL + if (a->value == b->value && a->color == b->color) + { + return compare_tree(a->left, b->left) && + compare_tree(a->right, b->right); + } + else + { + return 0; + } +} + +// #define DEBUG_BST + +#ifdef DEBUG_BST + +void test_build() +{ + printf("Testing build tree from string ...\n"); + + rb_node_t *r; + + char s[1000]; + + memset(s, 0, sizeof(char) * 1000); + strcpy(s, "#"); + r = build_tree(s); + assert(r == NULL); + free_tree(r); + + memset(s, 0, sizeof(char) * 1000); + strcpy(s, "(12, #, #)"); + r = build_tree(s); + assert(r->parent == NULL); + assert(r->left == NULL); + assert(r->right == NULL); + assert(r->value == 12); + free_tree(r); + + memset(s, 0, sizeof(char) * 1000); + strcpy(s, "(6,(3,(2,(1,#,#),#),(4,#,(5,#,#))),(7,#,(8,#,#)))"); + r = build_tree(s); + + rb_node_t *n1 = r->left->left->left; + rb_node_t *n2 = r->left->left; + rb_node_t *n3 = r->left; + rb_node_t *n4 = r->left->right; + rb_node_t *n5 = r->left->right->right; + rb_node_t *n6 = r; + rb_node_t *n7 = r->right; + rb_node_t *n8 = r->right->right; + + assert(n1->value == 1); + assert(n1->parent == n2); + assert(n1->left == NULL); + assert(n1->right == NULL); + + assert(n2->value == 2); + assert(n2->parent == n3); + assert(n2->left == n1); + assert(n2->right == NULL); + + assert(n3->value == 3); + assert(n3->parent == n6); + assert(n3->left == n2); + assert(n3->right == n4); + + assert(n4->value == 4); + assert(n4->parent == n3); + assert(n4->left == NULL); + assert(n4->right == n5); + + assert(n5->value == 5); + assert(n5->parent == n4); + assert(n5->left == NULL); + assert(n5->right == NULL); + + assert(n6->value == 6); + assert(n6->parent == NULL); + assert(n6->left == n3); + assert(n6->right == n7); + + assert(n7->value == 7); + assert(n7->parent == n6); + assert(n7->left == NULL); + assert(n7->right == n8); + + assert(n8->value == 8); + assert(n8->parent == n7); + assert(n8->left == NULL); + assert(n8->right == NULL); + + free_tree(r); + + printf("\tPass\n"); +} + +void test_delete() +{ + printf("Testing Binary Search tree insertion ...\n"); + + rb_node_t *r = build_tree("(8,(2,(1,#,#),(5,(4,(3,#,#),#),(6,#,(7,#,#)))),(13,(10,(9,#,#),(11,#,(12,#,#))),(15,(14,#,#),(18,(17,(16,#,#),#),(19,#,#)))))"); + rb_node_t *ans; + + // case 1: leaf node + bst_delete(r, r->left->left); + ans = build_tree("(8,(2,(5,(4,(3,#,#),#),(6,#,(7,#,#)))),(13,(10,(9,#,#),(11,#,(12,#,#))),(15,(14,#,#),(18,(17,(16,#,#),#),(19,#,#)))))"); + assert(compare_tree(r, ans) == 1); + free_tree(ans); + + // case 2: right NULL + bst_delete(r, r->left->right->left); + ans = build_tree("(8,(2,(5,(3,#,#),(6,#,(7,#,#)))),(13,(10,(9,#,#),(11,#,(12,#,#))),(15,(14,#,#),(18,(17,(16,#,#),#),(19,#,#)))))"); + assert(compare_tree(r, ans) == 1); + free_tree(ans); + + // case 3: left NULL + bst_delete(r, r->left->right->right); + ans = build_tree("(8,(2,(5,(3,#,#),(7,#,#))),(13,(10,(9,#,#),(11,#,(12,#,#))),(15,(14,#,#),(18,(17,(16,#,#),#),(19,#,#)))))"); + assert(compare_tree(r, ans) == 1); + free_tree(ans); + + // case 4: right child's left NULL + bst_delete(r, r->right->left); + ans = build_tree("(8,(2,(5,(3,#,#),(7,#,#))),(13,(11,(9,#,#),(12,#,#)),(15,(14,#,#),(18,(17,(16,#,#),#),(19,#,#)))))"); + assert(compare_tree(r, ans) == 1); + free_tree(ans); + + // case 5: right child's left not NULL + bst_delete(r, r->right->left); + ans = build_tree("(8,(2,(5,(3,#,#),(7,#,#))),(13,(11,(9,#,#),(12,#,#)),(16,(14,#,#),(18,(17,#,#),(19,#,#)))))"); + assert(compare_tree(r, ans) == 1); + free_tree(ans); + + free_tree(r); + + printf("\tPass\n"); +} + +void test_insert() +{ + printf("Testing Binary Search tree insertion ...\n"); + + rb_node_t *r = build_tree("(11, (2, (1,#,#), (7, (5,#,#), (8,#,#))), (14,#,(15,#,#)))"); + + // test insert + r = bst_insert(r, 4); + + // check + rb_node_t *ans = build_tree("(11, (2, (1,#,#), (7, (5,(4,#,#),#), (8,#,#))), (14,#,(15,#,#)))"); + assert(compare_tree(r, ans) == 1); + + // free + free_tree(r); + free_tree(ans); + + printf("\tPass\n"); +} + +int main() +{ + test_build(); + test_insert(); + test_delete(); +} + +#endif diff --git a/src/algorithm/redblack.c b/src/algorithm/redblack.c index 09d3789..088eb84 100644 --- a/src/algorithm/redblack.c +++ b/src/algorithm/redblack.c @@ -1,9 +1,18 @@ #include #include #include +#include #include #include +// shared with BST +rb_node_t *build_tree(char *str); +int compare_tree(rb_node_t *a, rb_node_t *b); +void free_tree(rb_node_t *root); + +rb_node_t *bst_insert_node(rb_node_t *root, uint64_t val, rb_node_t **inserted); +rb_node_t *bst_delete_node(rb_node_t *root, rb_node_t *n, rb_node_t **replaced); + // 4 kinds of rotations // return root node @@ -202,71 +211,11 @@ static rb_node_t * rb_rotate_node(rb_node_t *n, rb_node_t *p, rb_node_t *g) // insert value to the tree // return the updated tree root node -rb_node_t *rb_insert_node(rb_node_t *root, uint64_t val) +rb_node_t *rb_insert(rb_node_t *root, uint64_t val) { - // create - if (root == NULL) - { - root = malloc(sizeof(rb_node_t)); - - // update properties - root->parent = NULL; - root->left = NULL; - root->right = NULL; - root->value = val; - root->color = COLOR_BLACK; // root node is black - - return root; - } - - // search the right place (leaf node) to insert data - rb_node_t *n = root; - - while (n != NULL) - { - if (val < n->value) - { - if (n->left == NULL) - { - // insert here - n->left = malloc(sizeof(rb_node_t)); - n->left->parent = n; - n->left->left = NULL; - n->left->right = NULL; - n->left->value = val; - n->left->color = COLOR_RED; - - n = n->left; - goto BOTTOM_UP_REBALANCING; - } - else - { - n = n->left; - } - } - else - { - if (n->right == NULL) - { - // insert here - n->right = malloc(sizeof(rb_node_t)); - n->right->parent = n; - n->right->left = NULL; - n->right->right = NULL; - n->right->value = val; - n->right->color = COLOR_RED; - - n = n->right; - goto BOTTOM_UP_REBALANCING; - } - else - { - n = n->right; - } - } - } + rb_node_t *n; + root = bst_insert_node(root, val, &n); - BOTTOM_UP_REBALANCING: // fix up the inserted red node (internal node in 2-3-4 tree) while (1) { @@ -332,7 +281,7 @@ rb_node_t *rb_insert_node(rb_node_t *root, uint64_t val) // insert value to the tree // return the updated tree root node -rb_node_t *rb_delete_node(rb_node_t *root, rb_node_t *n) +rb_node_t *rb_delete(rb_node_t *root, rb_node_t *n) { if (n == NULL) { @@ -345,156 +294,8 @@ rb_node_t *rb_delete_node(rb_node_t *root, rb_node_t *n) // and we need to do color compensation rb_color_t n_color = n->color; - // in case root is deleted - rb_node_t *p = NULL; - int is_n_root = 0; - if (n == root) - { - // no parent pointer, create a dummy one - p = malloc(sizeof(rb_node_t)); - p->color = COLOR_BLACK; - p->left = n; - n->parent = p; - p->parent = NULL; - p->right = NULL; - is_n_root = 1; - } - else - { - p = n->parent; - is_n_root = 0; - } - - // the address of the to be deleted node - rb_node_t **par_child = NULL; - if (n == p->left) - { - par_child = &(p->left); - } - else - { - par_child = &(p->right); - } - - /****************************************************/ - /* The following logic is the same as BST deletion */ - /****************************************************/ - - if (n->left == NULL && n->right == NULL) - { - ////////////////////////////////////////////// - // case 1: leaf node // - ////////////////////////////////////////////// - - *par_child = NULL; - free(n); - - if (is_n_root == 1) - { - root = NULL; - } - } - else if (n->left == NULL && n->right != NULL) - { - ////////////////////////////////////////////// - // case 2: one sub-tree is empty // - // 2.1: left tree is empty // - ////////////////////////////////////////////// - - // transplant the other sub-tree to the node to be deleted - *par_child = n->right; - n->right->parent = p; - free(n); - - if (is_n_root == 1) - { - root = n->right; - } - } - else if (n->left != NULL && n->right == NULL) - { - // 2.2 right tree is empty - - *par_child = n->left; - n->left->parent = p; - free(n); - - if (is_n_root == 1) - { - root = n->left; - } - } - else if (n->right->left == NULL) - { - ////////////////////////////////////////////// - // case 3: both sub-trees are not empty // - // 3.1: a simple remove will do the job // - ////////////////////////////////////////////// - - // transplant the left sub-tree - n->right->left = n->left; - n->left->parent = n->right; - - *par_child = n->right; - n->right->parent = p; - - free(n); - - if (is_n_root == 1) - { - root = n->right; - } - } - else if (n->right->left != NULL) - { - ////////////////////////////////////////////// - // 3.2: float up the tight upper bound // - // as root of sub-tree // - ////////////////////////////////////////////// - - rb_node_t *min_upper = n->right; - while (min_upper->left != NULL) - { - min_upper = min_upper->left; - } - - // float up min_upper - min_upper->parent->left = min_upper->right; - if (min_upper->right != NULL) - { - min_upper->right->parent = min_upper->parent; - } - - // transplant - min_upper->right = n->right; - n->right->parent = min_upper; - - min_upper->left = n->left; - n->left->parent = min_upper; - - min_upper->parent = p; - - *par_child = min_upper; - free(n); - - if (is_n_root == 1) - { - root = min_upper; - } - } - - // set the pointer to the address of the deleted node - rb_node_t *v = *par_child; - - if (is_n_root == 1) - { - free(p); - - if (root != NULL) - { - root->parent = NULL; - } - } + rb_node_t *v; + root = bst_delete_node(root, n, &v); /****************************************************/ /* recoloring and restructuring */ @@ -515,8 +316,18 @@ rb_node_t *rb_delete_node(rb_node_t *root, rb_node_t *n) // 1. root rule - min_upper can be root // 2. red rule - min_upper can be a red and its child can be red // 3. black height rule - all sub-tree black height deduct 1 - + /* + g + / + p + / \ + v s + */ + + rb_node_t *g = NULL; // grandparent + rb_node_t *p = NULL; // sibling rb_node_t *s = NULL; // sibling + while (1) { p = v->parent; @@ -587,7 +398,6 @@ rb_node_t *rb_delete_node(rb_node_t *root, rb_node_t *n) // RED Sibling // adjust to black sibling - rb_node_t *g = NULL; int is_p_root = 0; if (p->parent == NULL) { @@ -663,617 +473,95 @@ rb_node_t *rb_delete_node(rb_node_t *root, rb_node_t *n) // find the node owning the target value rb_node_t *rb_find_node(rb_node_t *root, uint64_t val) { - rb_node_t *n = root; - uint64_t n_value; + return bst_find(root, val); +} - while (n != NULL) +// build binary tree +static int color_tree_dfs(rb_node_t *n, char *color, int index) +{ + if (n == NULL) { - n_value = n->value; + assert(color[index] == '#'); + return index; + } - if (n_value == val) - { - return n; - } - else if (val < n_value) - { - n = n->left; - } - else - { - n = n->right; - } + if (color[index] == 'R') + { + n->color = COLOR_RED; + } + else if (color[index] == 'B') + { + n->color = COLOR_BLACK; } - return NULL; + index = color_tree_dfs(n->left, color, index + 1); + index = color_tree_dfs(n->right, color, index + 1); + + return index; } -#ifdef DEBUG_REDBLACK +rb_node_t *build_rb_tree(char *tree, char *color) +{ + rb_node_t *r = build_tree(tree); + int index = color_tree_dfs(r, color, 0); + assert(index == strlen(color) - 1); -void test_insert() + return r; +} + +//#define DEBUG_REDBLACK + +#ifdef DEBUG_REDBLACK +void test_delete() { - // From CLRS chapter 13.3 Red-Black Tree Insertion - rb_node_t *n1 = malloc(sizeof(rb_node_t)); - rb_node_t *n2 = malloc(sizeof(rb_node_t)); - rb_node_t *n5 = malloc(sizeof(rb_node_t)); - rb_node_t *n7 = malloc(sizeof(rb_node_t)); - rb_node_t *n8 = malloc(sizeof(rb_node_t)); - rb_node_t *n11 = malloc(sizeof(rb_node_t)); - rb_node_t *n14 = malloc(sizeof(rb_node_t)); - rb_node_t *n15 = malloc(sizeof(rb_node_t)); - - n1->color = COLOR_BLACK; - n1->value = 1; - n1->parent = n2; - n1->left = NULL; - n1->right = NULL; - - n2->color = COLOR_RED; - n2->value = 2; - n2->parent = n11; - n2->left = n1; - n2->right = n7; - - n5->color = COLOR_RED; - n5->value = 5; - n5->parent = n7; - n5->left = NULL; - n5->right = NULL; - - n7->color = COLOR_BLACK; - n7->value = 7; - n7->parent = n2; - n7->left = n5; - n7->right = n8; - - n8->color = COLOR_RED; - n8->value = 8; - n8->parent = n7; - n8->left = NULL; - n8->right = NULL; - - n11->color = COLOR_BLACK; - n11->value = 11; - n11->parent = NULL; - n11->left = n2; - n11->right = n14; - - n14->color = COLOR_BLACK; - n14->value = 14; - n14->parent = n11; - n14->left = NULL; - n14->right = n15; - - n15->color = COLOR_RED; - n15->value = 15; - n15->parent = n14; - n15->left = NULL; - n15->right = NULL; + printf("Testing Red-Black tree insertion ...\n"); - // test insert - rb_node_t *r = rb_insert_node(n11, 4); - - assert(r == n7); - - assert(n1->parent == n2); - assert(n1->left == NULL); - assert(n1->right == NULL); - assert(n1->color == COLOR_BLACK); - - assert(n2->parent == n7); - assert(n2->left == n1); - assert(n2->right == n5); - assert(n2->color == COLOR_RED); - - // insert n4 here - rb_node_t *n4 = n5->left; - assert(n4 != NULL); - assert(n4->parent == n5); - assert(n4->left == NULL); - assert(n4->right == NULL); - assert(n4->color == COLOR_RED); - - assert(n5->parent == n2); - assert(n5->left != NULL); - assert(n5->right == NULL); - assert(n5->color == COLOR_BLACK); - - assert(n7->parent == NULL); - assert(n7->left == n2); - assert(n7->right == n11); - assert(n7->color == COLOR_BLACK); - - assert(n8->parent == n11); - assert(n8->left == NULL); - assert(n8->right == NULL); - assert(n8->color == COLOR_BLACK); - - assert(n11->parent == n7); - assert(n11->left == n8); - assert(n11->right == n14); - assert(n11->color == COLOR_RED); - - assert(n14->parent == n11); - assert(n14->left == NULL); - assert(n14->right == n15); - assert(n14->color == COLOR_BLACK); - - assert(n15->parent == n14); - assert(n15->left == NULL); - assert(n15->right == NULL); - assert(n15->color == COLOR_RED); - - printf("pass insertion test\n"); - - free(n1); - free(n2); - free(n4); - free(n5); - free(n7); - free(n8); - free(n11); - free(n14); - free(n15); + printf("\tPass\n"); } -void test_rotate() +void test_delete_bst() { - // malloc the nodes - rb_node_t *r = malloc(sizeof(rb_node_t)); - rb_node_t *g = malloc(sizeof(rb_node_t)); - rb_node_t *p = malloc(sizeof(rb_node_t)); - rb_node_t *n = malloc(sizeof(rb_node_t)); - rb_node_t *a = malloc(sizeof(rb_node_t)); - rb_node_t *b = malloc(sizeof(rb_node_t)); - rb_node_t *c = malloc(sizeof(rb_node_t)); - rb_node_t *d = malloc(sizeof(rb_node_t)); - - ////////////////////////// - // left rotate 1 // - ////////////////////////// - g->parent = NULL; - g->left = a; - g->right = p; - g->color = COLOR_BLACK; - - p->parent = g; - p->left = b; - p->right = n; - p->color = COLOR_RED; - - n->parent = p; - n->left = c; - n->right = d; - n->color = COLOR_RED; - - a->parent = g; - a->left = NULL; - a->right = NULL; - a->color = COLOR_BLACK; - - b->parent = p; - b->left = NULL; - b->right = NULL; - b->color = COLOR_BLACK; - - c->parent = n; - c->left = NULL; - c->right = NULL; - c->color = COLOR_BLACK; - - d->parent = n; - d->left = NULL; - d->right = NULL; - d->color = COLOR_BLACK; + printf("Testing Binary Search tree insertion ...\n"); + printf("\tPass\n"); +} - rb_rotate_node(n, p, g); - - assert(p->parent == NULL); - assert(p->left == g); - assert(p->right == n); - - assert(g->parent == p); - assert(g->left == a); - assert(g->right == b); - - assert(n->parent == p); - assert(n->left == c); - assert(n->right == d); - - ////////////////////////// - // left rotate 2 // - ////////////////////////// - r->parent = NULL; - r->left = g; - r->right = NULL; - r->color = COLOR_BLACK; - - g->parent = r; - g->left = a; - g->right = p; - g->color = COLOR_BLACK; - - p->parent = g; - p->left = b; - p->right = n; - p->color = COLOR_RED; - - n->parent = p; - n->left = c; - n->right = d; - n->color = COLOR_RED; - - a->parent = g; - a->left = NULL; - a->right = NULL; - a->color = COLOR_BLACK; - - b->parent = p; - b->left = NULL; - b->right = NULL; - b->color = COLOR_BLACK; - - c->parent = n; - c->left = NULL; - c->right = NULL; - c->color = COLOR_BLACK; - - d->parent = n; - d->left = NULL; - d->right = NULL; - d->color = COLOR_BLACK; +void test_insert() +{ + printf("Testing Red-Black tree insertion ...\n"); - rb_rotate_node(n, p, g); - - assert(p->parent == r); - assert(p->left == g); - assert(p->right == n); - - assert(g->parent == p); - assert(g->left == a); - assert(g->right == b); - - assert(n->parent == p); - assert(n->left == c); - assert(n->right == d); - - ////////////////////////// - // right rotate 1 // - ////////////////////////// - g->parent = NULL; - g->left = p; - g->right = d; - g->color = COLOR_BLACK; - - p->parent = g; - p->left = n; - p->right = c; - p->color = COLOR_RED; - - n->parent = p; - n->left = a; - n->right = b; - n->color = COLOR_RED; - - a->parent = g; - a->left = NULL; - a->right = NULL; - a->color = COLOR_BLACK; - - b->parent = p; - b->left = NULL; - b->right = NULL; - b->color = COLOR_BLACK; - - c->parent = n; - c->left = NULL; - c->right = NULL; - c->color = COLOR_BLACK; - - d->parent = n; - d->left = NULL; - d->right = NULL; - d->color = COLOR_BLACK; + rb_node_t *r = build_rb_tree( + "(11, (2, (1,#,#), (7, (5,#,#), (8,#,#))), (14,#,(15,#,#)))", + "BRB##BR##R##B#R##"); - rb_rotate_node(n, p, g); - - assert(p->parent == NULL); - assert(p->left == n); - assert(p->right == g); - - assert(n->parent == p); - assert(n->left == a); - assert(n->right == b); - - assert(g->parent == p); - assert(g->left == c); - assert(g->right == d); - - ////////////////////////// - // right rotate 2 // - ////////////////////////// - r->parent = NULL; - r->left = g; - r->right = NULL; - r->color = COLOR_BLACK; - - g->parent = r; - g->left = p; - g->right = d; - g->color = COLOR_BLACK; - - p->parent = g; - p->left = n; - p->right = c; - p->color = COLOR_RED; - - n->parent = p; - n->left = a; - n->right = b; - n->color = COLOR_RED; - - a->parent = g; - a->left = NULL; - a->right = NULL; - a->color = COLOR_BLACK; - - b->parent = p; - b->left = NULL; - b->right = NULL; - b->color = COLOR_BLACK; - - c->parent = n; - c->left = NULL; - c->right = NULL; - c->color = COLOR_BLACK; - - d->parent = n; - d->left = NULL; - d->right = NULL; - d->color = COLOR_BLACK; + // test insert + r = rb_insert(r, 4); - rb_rotate_node(n, p, g); - - assert(p->parent == r); - assert(p->left == n); - assert(p->right == g); - - assert(n->parent == p); - assert(n->left == a); - assert(n->right == b); - - assert(g->parent == p); - assert(g->left == c); - assert(g->right == d); - - ////////////////////////// - // left right rotate 1 // - ////////////////////////// - g->parent = NULL; - g->left = p; - g->right = d; - g->color = COLOR_BLACK; - - p->parent = g; - p->left = a; - p->right = n; - p->color = COLOR_RED; - - n->parent = p; - n->left = b; - n->right = c; - n->color = COLOR_RED; - - a->parent = p; - a->left = NULL; - a->right = NULL; - a->color = COLOR_BLACK; - - b->parent = n; - b->left = NULL; - b->right = NULL; - b->color = COLOR_BLACK; - - c->parent = n; - c->left = NULL; - c->right = NULL; - c->color = COLOR_BLACK; - - d->parent = g; - d->left = NULL; - d->right = NULL; - d->color = COLOR_BLACK; + // check + rb_node_t *ans = build_rb_tree( + "(7, (2, (1,#,#),(5,(4,#,#),#)), (11,(8,#,#),(14,#,(15,#,#))))", + "BRB##BR###RB##B#R##"); + assert(compare_tree(r, ans) == 1); - rb_rotate_node(n, p, g); + free_tree(r); + free_tree(ans); - assert(n->parent == NULL); - assert(n->left == p); - assert(n->right == g); - - assert(p->parent == n); - assert(p->left == a); - assert(p->right == b); - - assert(g->parent == n); - assert(g->left == c); - assert(g->right == d); - - ////////////////////////// - // left right rotate 2 // - ////////////////////////// - r->parent = NULL; - r->left = g; - r->right = NULL; - r->color = COLOR_BLACK; - - g->parent = r; - g->left = p; - g->right = d; - g->color = COLOR_BLACK; - - p->parent = g; - p->left = a; - p->right = n; - p->color = COLOR_RED; - - n->parent = p; - n->left = b; - n->right = c; - n->color = COLOR_RED; - - a->parent = p; - a->left = NULL; - a->right = NULL; - a->color = COLOR_BLACK; - - b->parent = n; - b->left = NULL; - b->right = NULL; - b->color = COLOR_BLACK; - - c->parent = n; - c->left = NULL; - c->right = NULL; - c->color = COLOR_BLACK; - - d->parent = g; - d->left = NULL; - d->right = NULL; - d->color = COLOR_BLACK; - - rb_rotate_node(n, p, g); - - assert(n->parent == r); - assert(n->left == p); - assert(n->right == g); - - assert(p->parent == n); - assert(p->left == a); - assert(p->right == b); - - assert(g->parent == n); - assert(g->left == c); - assert(g->right == d); - - ////////////////////////// - // right left rotate 1 // - ////////////////////////// - g->parent = NULL; - g->left = a; - g->right = p; - g->color = COLOR_BLACK; - - p->parent = g; - p->left = n; - p->right = d; - p->color = COLOR_RED; - - n->parent = p; - n->left = b; - n->right = c; - n->color = COLOR_RED; - - a->parent = g; - a->left = NULL; - a->right = NULL; - a->color = COLOR_BLACK; - - b->parent = n; - b->left = NULL; - b->right = NULL; - b->color = COLOR_BLACK; - - c->parent = n; - c->left = NULL; - c->right = NULL; - c->color = COLOR_BLACK; - - d->parent = p; - d->left = NULL; - d->right = NULL; - d->color = COLOR_BLACK; - - rb_rotate_node(n, p, g); - - assert(n->parent == NULL); - assert(n->left == g); - assert(n->right == p); - - assert(g->parent == n); - assert(g->left == a); - assert(g->right == b); - - assert(p->parent == n); - assert(p->left == c); - assert(p->right == d); - - ////////////////////////// - // right left rotate 2 // - ////////////////////////// - r->parent = NULL; - r->left = g; - r->right = NULL; - r->color = COLOR_BLACK; - - g->parent = r; - g->left = a; - g->right = p; - g->color = COLOR_BLACK; - - p->parent = g; - p->left = n; - p->right = d; - p->color = COLOR_RED; - - n->parent = p; - n->left = b; - n->right = c; - n->color = COLOR_RED; - - a->parent = g; - a->left = NULL; - a->right = NULL; - a->color = COLOR_BLACK; - - b->parent = n; - b->left = NULL; - b->right = NULL; - b->color = COLOR_BLACK; - - c->parent = n; - c->left = NULL; - c->right = NULL; - c->color = COLOR_BLACK; - - d->parent = p; - d->left = NULL; - d->right = NULL; - d->color = COLOR_BLACK; + printf("\tPass\n"); +} - rb_rotate_node(n, p, g); +void test_rotate() +{ + printf("Testing Red-Black tree rotation ...\n"); + + rb_node_t *r; + rb_node_t *ans; + + r = build_tree("(2,(1,#,#),(4,(3,#,#),(6,(5,#,#),(7,#,#))))"); + rb_rotate_node(r->left->left, r->left, r); - assert(n->parent == r); - assert(n->left == g); - assert(n->right == p); + ans = build_tree("(4,(2,(1,#,#),(3,#,#)),(6,(5,#,#),(7,#,#)))"); + assert(compare_tree(r, ans) == 1); - assert(g->parent == n); - assert(g->left == a); - assert(g->right == b); - - assert(p->parent == n); - assert(p->left == c); - assert(p->right == d); - - printf("pass rotation test\n"); - - // free all nodes - free(r); - free(g); - free(p); - free(n); - free(a); - free(b); - free(c); - free(d); + printf("\tPass\n"); } int main() diff --git a/src/hardware/cpu/mmu.c b/src/hardware/cpu/mmu.c index fa1c3d8..e93424b 100644 --- a/src/hardware/cpu/mmu.c +++ b/src/hardware/cpu/mmu.c @@ -15,8 +15,10 @@ #include "headers/cpu.h" #include "headers/memory.h" #include "headers/common.h" +#include "headers/address.h" +// consider this function va2pa as functional uint64_t va2pa(uint64_t vaddr) { - return vaddr % PHYSICAL_MEMORY_SPACE; + // use page table as va2pa } \ No newline at end of file diff --git a/src/headers/address.h b/src/headers/address.h index 7dcec11..4c68e1c 100644 --- a/src/headers/address.h +++ b/src/headers/address.h @@ -15,26 +15,35 @@ #include -/* - S = 2^s, s = 6 - B = 2^b, b = 6 - E is defined in sram.c, 8 - For correctness verification, E can be 1, 2, 8, 1024 - */ - #ifndef CACHE_SIMULATION_VERIFICATION /* for cache simulator verification use the marcos passed in */ #define SRAM_CACHE_INDEX_LENGTH (6) #define SRAM_CACHE_OFFSET_LENGTH (6) -#define SRAM_CACHE_TAG_LENGTH (40) +#define SRAM_CACHE_TAG_LENGTH (4) #endif #define PHYSICAL_PAGE_OFFSET_LENGTH (12) -#define PHYSICAL_PAGE_NUMBER_LENGTH (40) -#define PHYSICAL_ADDRESS_LENGTH (52) +#define PHYSICAL_PAGE_NUMBER_LENGTH (4) +#define PHYSICAL_ADDRESS_LENGTH (16) + +#define VIRTUAL_PAGE_OFFSET_LENGTH (12) +#define VIRTUAL_PAGE_NUMBER_LENGTH (9) // 9 + 9 + 9 + 9 = 36 +#define VIRTUAL_ADDRESS_LENGTH (48) + +/* ++--------+--------+--------+--------+---------------+ +| VPN3 | VPN2 | VPN1 | VPN0 | | ++--------+--------+--------+-+------+ VPO | +| TLBT | TLBI | | ++---------------+------------+------+---------------+ + | PPN | PPO | + +-------------------+--------+------+ + | CT | CI | CO | + +-------------------+--------+------+ +*/ typedef union { uint64_t address_value; @@ -53,6 +62,23 @@ typedef union }; }; + // virtual address: 48 + struct + { + union + { + uint64_t vaddr_value : VIRTUAL_ADDRESS_LENGTH; + struct + { + uint64_t VPO : VIRTUAL_PAGE_OFFSET_LENGTH; + uint64_t VPN3 : VIRTUAL_PAGE_NUMBER_LENGTH; + uint64_t VPN2 : VIRTUAL_PAGE_NUMBER_LENGTH; + uint64_t VPN1 : VIRTUAL_PAGE_NUMBER_LENGTH; + uint64_t VPN0 : VIRTUAL_PAGE_NUMBER_LENGTH; + }; + }; + }; + // sram cache: 52 struct { diff --git a/src/headers/algorithm.h b/src/headers/algorithm.h index c14c5d1..872bc3b 100644 --- a/src/headers/algorithm.h +++ b/src/headers/algorithm.h @@ -117,8 +117,16 @@ typedef struct RB_NODE_STRUCT uint64_t value; } rb_node_t; -rb_node_t *rb_insert_node(rb_node_t *root, uint64_t val); -rb_node_t *rb_delete_node(rb_node_t *root, rb_node_t *target); -rb_node_t *rb_find_node(rb_node_t *root, uint64_t val); +rb_node_t *rb_insert(rb_node_t *root, uint64_t val); +rb_node_t *rb_delete(rb_node_t *root, rb_node_t *target); +rb_node_t *rb_find(rb_node_t *root, uint64_t val); + +/*======================================*/ +/* Binary Search Tree */ +/*======================================*/ + +rb_node_t *bst_insert(rb_node_t *root, uint64_t val); +rb_node_t *bst_delete(rb_node_t *root, rb_node_t *target); +rb_node_t *bst_find(rb_node_t *root, uint64_t val); #endif