-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathheap_bank.h
189 lines (168 loc) · 6.09 KB
/
heap_bank.h
1
2
3
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
// #include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#ifndef HEAP_BANK_H
#define HEAP_BANK_H
// Register Dump
void register_dump(unsigned short *pc, unsigned int *registers) {
char temp[] = " = 0x";
printf("PC");printf("%s", temp);printf("%08x;\n", *pc);
for (int i = 0; i < 32; i ++) {
printf("R[%d]", i);printf("%s", temp);printf("%08x;\n", registers[i]);
}
}
// // Illegal Operation Helper
void illegal_operation(unsigned short *pc, unsigned int *registers, unsigned int *instruction) {
printf("Illegal Operation: 0x%08x\n", *instruction);
register_dump(pc, registers);
exit(1);
}
struct node {
struct node *next;
unsigned char size;
bool start;
unsigned char *addr;
};
typedef struct node Node;
Node* create_heap_bank(Node *head) {
Node *current_node = head;
for (int i = 0; i < 128; i++) {
current_node->addr = NULL;
current_node->size = 0;
current_node->start = 0;
if (i != 127) {
Node* new_node = (Node*)malloc(sizeof(Node));
current_node->next = new_node;
current_node = current_node->next;
} else {
current_node->next = NULL;
}
}
return head;
}
// Returns the virtual address of 1st byte
unsigned int allocate(Node *head, unsigned int *bytes_to_allocate) {
// Find consecutive banks
short required_banks = (*bytes_to_allocate / 64) + ((*bytes_to_allocate % 64 == 0) ? 0 : 1);
if (required_banks > 128) {
return 0;
}
Node *current_node = head;
Node *start_node = head;
unsigned short start_heap_bank_index = 0;
short num_banks = 0;
for (int i = 0; i < 128; i++) {
// printf("Current Bank %d size: (%u)\n", i, current_node->size);
if (current_node->size != 0) {
// Bank Occupied
num_banks = 0;
current_node = current_node->next;
start_node = &*(current_node); // set to pointer to underlying Node not the current_node pointer
start_heap_bank_index = i+1;
} else if (current_node->size == 0) {
// Bank Unoccupied
num_banks += 1;
// printf("Required Banks = (%d). Number of consecutive Banks = (%d)\n", required_banks, num_banks);
if (num_banks == required_banks) {
// printf("Start Node size = (%d), start = (%d)\n", start_node->size, start_node->start);
break;
} else {
current_node = current_node->next;
}
}
// Reached end of linked list
if (i == 127) {
start_node = NULL;
break;
}
}
// Check to see if consecutive bank exists
if (start_node == NULL) {
// printf("Start Node == NULL\n");
return 0;
}
// Assign memory for each heap_bank
current_node = start_node;
unsigned int remaining = *bytes_to_allocate;
for (int i = 0; i < required_banks; i++) {
// Determine start
if (i == 0) {
current_node->start = 1;
} else {
current_node->start = 0;
}
// Determine Size
if (remaining > 64) {
current_node->size = 64;
} else {
current_node->size = remaining;
}
// printf("Allocating to %d size is: %d, start is (%d)\n", i, current_node->size, current_node->start);
remaining = remaining - 64;
current_node->addr = (unsigned char *)malloc(current_node->size);
current_node = current_node->next;
}
return start_heap_bank_index*64 + 0xB700;
}
void free_heap_bank(Node *head, unsigned int virtual_address, unsigned short *pc, unsigned int *registers, unsigned int *instruction) {
// printf("Free memory at address (%x)\n", virtual_address);
unsigned int index = virtual_address - 0xb700;
// If index to free is not the 1st byte of a block it cannot be freed
if (index % 64 != 0) {
illegal_operation(pc, registers, instruction);
}
// Check if index supplied is the 1st byte of a start block
Node *current_node = head;
unsigned int num_iters = index / 64;
// Jump to the index node
for (int i = 0; i < num_iters; i++) {
current_node = current_node->next;
}
// Check if node is the start of a block
if (current_node->start == 0) {
illegal_operation(pc, registers, instruction);
}
// Free block
current_node->start = 0;
while (current_node->start != 1 && current_node->size != 0) {
free(current_node->addr);
current_node->addr = NULL;
current_node->size = 0;
current_node = current_node->next;
}
}
unsigned char read_byte_from_heap(Node *head, unsigned int virtual_address, unsigned short *pc, unsigned int *registers, unsigned int *instruction) {
// printf("Read from heap at address (%x)\n", virtual_address);
unsigned int index = virtual_address - 0xb700;
if (index > 8192) {
// Can't be allocated
illegal_operation(pc, registers, instruction);
}
unsigned short heap_bank_num = index / 64;
Node *current_node = head;
for (int i = 0; i < heap_bank_num; i++) {
current_node = current_node->next;
}
if (current_node->size < index % 64) {
illegal_operation(pc, registers, instruction);
}
return current_node->addr[index % 64];
}
void store_byte_in_heap(Node *head, unsigned int virtual_address, unsigned char byte, unsigned short *pc, unsigned int *registers, unsigned int *instruction) {
// printf("Write to heap at address (%x) - Byte(%x)\n", virtual_address, byte);
unsigned int index = virtual_address - 0xB700;
if (index > 8191) {
// Can't be allocated
illegal_operation(pc, registers, instruction);
}
unsigned short heap_bank_num = index / 64;
Node *current_node = head;
for (int i = 0; i < heap_bank_num; i++) {
current_node = current_node->next;
}
if (current_node->size-1 < index % 64 || current_node->size == 0) {
illegal_operation(pc, registers, instruction); // Reading from unallocated byte
}
current_node->addr[index % 64] = byte;
}
#endif