Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | /*********************************************************************** |
2 | * Functions to generate and manage random memory address | |
3 | * * Orignal Author(s): Arvind Srinivasan | |
4 | * * Modifier(s): | |
5 | * * Project(s): Neptune | |
6 | * * | |
7 | * * Copyright (c) 2004 Sun Microsystems, Inc. | |
8 | * * | |
9 | * * All Rights Reserved. | |
10 | * * | |
11 | * * This verilog model is the confidential and proprietary property of | |
12 | * * Sun Microsystems, Inc., and the possession or use of this model | |
13 | * * requires a written license from Sun Microsystems, Inc. | |
14 | * * | |
15 | ************************************************************************/ | |
16 | ||
17 | #include <iostream> | |
18 | #include <stdio.h> | |
19 | ||
20 | #ifdef N2_AXIS | |
21 | #else | |
22 | #include <map> | |
23 | using namespace std; | |
24 | #endif | |
25 | ||
26 | #include "vera_directc.h" | |
27 | ||
28 | #define MASKL 0xffffffff | |
29 | #define MAX_ITER 1000 | |
30 | #define VALID 1 | |
31 | ||
32 | #define NOHOLES 0 | |
33 | #define INC_NOHOLES 100 | |
34 | #define RANDOM_HOLES 200 | |
35 | ||
36 | #if defined(__cplusplus) | |
37 | extern "C" { | |
38 | #endif | |
39 | ||
40 | ||
41 | unsigned int MASKH ; | |
42 | unsigned int VIRTMASKH ; | |
43 | ||
44 | static int verbose; | |
45 | class PAGEINFO { | |
46 | public: | |
47 | unsigned int mask; | |
48 | unsigned int value; | |
49 | unsigned int reloc; | |
50 | int id; | |
51 | int xlate_on; | |
52 | int valid; | |
53 | unsigned int byte_allocated; | |
54 | int page_size; | |
55 | unsigned int calc_value(); | |
56 | unsigned int calc_reloc(); | |
57 | unsigned char check_addr_match(unsigned long long int addr); | |
58 | unsigned long long int xlate_addr( unsigned long long int addr); | |
59 | PAGEINFO() { | |
60 | valid = 0; | |
61 | mask = 0; | |
62 | xlate_on = 0; | |
63 | byte_allocated = 0; | |
64 | } | |
65 | ||
66 | }; | |
67 | unsigned int PAGEINFO::calc_value() { | |
68 | value = random(); | |
69 | // VJH This code can be cleaned up but seems OK for now..confer with Arvind/Vernon | |
70 | #ifdef NEPTUNE | |
71 | if(id<64) { | |
72 | value = value & mask & 0x0fffffff ; // Force top bits to be 0 for now- | |
73 | } else | |
74 | value = value & mask & 0x0fffffe0 ; // Force top bits to be 0 for now- | |
75 | // HACK NEED TO CLEAN THIS | |
76 | value = value & mask & 0x0fffffff ; // Force top bits to be 0 for now- | |
77 | #else | |
78 | #ifdef N2_FC | |
79 | if(id<64) { | |
80 | value = value & mask & 0x000fffff ; // Force top bits to be 0 for now- | |
81 | } else | |
82 | value = value & mask & 0x000fffe0 ; // Force top bits to be 0 for now- | |
83 | ||
84 | value = value & mask & 0x000fffff ; // Force top bits to be 0 for now- | |
85 | #else | |
86 | if(id<64) { | |
87 | value = value & mask & 0x07ffffff ; // Force top bits to be 0 for now- | |
88 | } else | |
89 | value = value & mask & 0x07ffffe0 ; // Force top bits to be 0 for now- | |
90 | ||
91 | value = value & mask & 0x07ffffff ; // Force top bits to be 0 for now- | |
92 | #endif | |
93 | #endif | |
94 | value = value & VIRTMASKH; // for supporting 32bit address mode in Neptune | |
95 | if(verbose) printf(" MALLOC_DEBUG: Value for id - %d set to %x \n",id,value); | |
96 | return(value); | |
97 | } | |
98 | unsigned int PAGEINFO::calc_reloc() { | |
99 | /* For neptune, we need to block the following address range 0xF8FFFFFF - 0xF5000000 | |
100 | * This belongs to the EEPROM | |
101 | * | |
102 | */ | |
103 | ||
104 | #define NEPT_EEPROM_BASE_MAX 0xF8FFF | |
105 | #define NEPT_EEPROM_BASE_MIN 0xF5000 | |
106 | ||
107 | ||
108 | #ifdef NEPTUNE | |
109 | int match; | |
110 | int i; | |
111 | match =0; | |
112 | i=0; | |
113 | while(match==0) { | |
114 | reloc = random(); | |
115 | reloc = reloc & mask; | |
116 | if((reloc<=NEPT_EEPROM_BASE_MAX) && ( reloc >= NEPT_EEPROM_BASE_MIN)) { | |
117 | // continue | |
118 | i++; | |
119 | if(i>1000) { | |
120 | // cannot converge... | |
121 | printf("PAGEINFO::calc_reloc ERROR Cannot find a suitable reloc for PageID - %d \n",id); | |
122 | reloc = 0; | |
123 | } | |
124 | } else { match=1; } | |
125 | } | |
126 | #else | |
127 | reloc = random(); | |
128 | reloc = reloc & mask; | |
129 | #endif | |
130 | ||
131 | ||
132 | #ifdef NEPTUNE | |
133 | reloc = reloc & 0x0fffffff; // Force top bits to be 0 for now- | |
134 | #else | |
135 | #ifdef N2_FC | |
136 | reloc = reloc & 0x000fffff; // Force top bits to be 0 for now- | |
137 | #else | |
138 | ||
139 | // OLD CODE if(id<64) { | |
140 | // OLD CODE reloc = reloc & 0x07ffffff; // Force top bits to be 0 for now- | |
141 | // OLD CODE } else | |
142 | // OLD CODE reloc = reloc & 0x07ffffe0; // Force top bits to be 0 for now- | |
143 | // VJH Doesn't this following line over-writes the previous lines? | |
144 | // | |
145 | reloc = reloc & 0x07ffffff; // Force top bits to be 0 for now- | |
146 | #endif | |
147 | #endif | |
148 | reloc = reloc & VIRTMASKH; // for supporting 32bit address mode in Neptune | |
149 | if(verbose) printf(" MALLOC_DEBUG: reloc for id - %d set to %x \n",id,reloc); | |
150 | return(reloc); | |
151 | } | |
152 | ||
153 | unsigned long long int PAGEINFO::xlate_addr( unsigned long long int addr) { | |
154 | ||
155 | unsigned int xlate; | |
156 | unsigned long long int retval; | |
157 | unsigned int p = addr & 0xfff; | |
158 | unsigned long long int orig_address; | |
159 | orig_address = addr; | |
160 | addr = addr >> 12; | |
161 | xlate = addr & 0xffffffff; | |
162 | xlate = reloc & mask | xlate & (mask ^ 0xffffffff); | |
163 | retval = xlate; | |
164 | retval = retval <<12 | p; | |
165 | #ifdef NEPTUNE | |
166 | /* This is only to check if EEPROM base address is not getting generated.*/ | |
167 | if((retval<=NEPT_EEPROM_BASE_MAX) && ( retval >= NEPT_EEPROM_BASE_MIN)) { | |
168 | printf(" MALLOC_DEBUG: Xlated Address is within EEPROM Range!! ERROR! FIX THIS!!!\n"); | |
169 | retval = 0; | |
170 | } | |
171 | #endif | |
172 | if(verbose) printf(" MALLOC_DEBUG: Xlated Address = %llx orig address - %llx \n",retval,orig_address); | |
173 | return(retval); | |
174 | ||
175 | } | |
176 | unsigned char PAGEINFO::check_addr_match(unsigned long long int addr){ | |
177 | addr = addr>>12; | |
178 | if(valid ) { | |
179 | if((addr& mask)==reloc) { | |
180 | return(1); | |
181 | } else { | |
182 | return(0); | |
183 | } | |
184 | } else return(0); | |
185 | ||
186 | } | |
187 | ||
188 | PAGEINFO *page[128]; | |
189 | static int pages_allocated = 0; // needed to prevent user errors | |
190 | static unsigned char page_bits[32]; | |
191 | ||
192 | #ifdef N2_AXIS | |
193 | #define VALID_BIT (1ULL<<56) | |
194 | unsigned long long *hash_mem=NULL; | |
195 | int num_entries; | |
196 | int max_entries=1*1024*1024; | |
197 | #else | |
198 | map< unsigned long long int,unsigned char> hash_mem; | |
199 | #endif | |
200 | ||
201 | static int BITS_TO_IGNORE; | |
202 | ||
203 | int deleteHashTabEntry (unsigned long long int addr){ | |
204 | ||
205 | // printf(" MALLOC DEBUG in deleteHashTabEntry addr = %x xx = %x \n",addr,hash_mem[addr]); | |
206 | #ifdef N2_AXIS | |
207 | unsigned long long match=addr|VALID_BIT; | |
208 | int i; | |
209 | if (!hash_mem){ | |
210 | printf(" AXIS_MALLOC_DEBUG: ERROR: remove entry when hash table==NULL \n"); return (0); | |
211 | } | |
212 | for (i=0;i<num_entries;i++){ | |
213 | if (hash_mem[i]==match){ | |
214 | hash_mem[i]=0ULL; | |
215 | return 1; | |
216 | } | |
217 | } | |
218 | printf(" AXIS_MALLOC_DEBUG: address not found ERROR \n"); | |
219 | return(0); | |
220 | ||
221 | #else | |
222 | if(hash_mem.find(addr)!=hash_mem.end()) { | |
223 | hash_mem.erase(hash_mem.find(addr)); | |
224 | // printf(" MALLOC_DEBUG: deleteaddress - %x found \n",addr); | |
225 | return(1); | |
226 | } else { | |
227 | printf(" MALLOC_DEBUG: deleteaddress - %x not found ERROR \n",addr); | |
228 | return(0); | |
229 | } | |
230 | #endif | |
231 | ||
232 | } | |
233 | ||
234 | #ifdef N2_AXIS | |
235 | int getHashTabEntry (unsigned long long int addr){ | |
236 | unsigned long long match=addr|VALID_BIT; | |
237 | int i; | |
238 | if (!hash_mem){ | |
239 | printf(" AXIS_MALLOC_DEBUG: get entry when hash table==NULL \n"); | |
240 | hash_mem=(unsigned long long *)calloc(max_entries,sizeof(unsigned long long)); | |
241 | if (!hash_mem){ | |
242 | printf(" could not calloc %d bytes \n", max_entries*sizeof(unsigned long long)); exit(1); | |
243 | } | |
244 | } | |
245 | for (i=0;i<num_entries;i++){ | |
246 | if (hash_mem[i]==match){ | |
247 | return VALID; | |
248 | } | |
249 | } | |
250 | return(0); | |
251 | } | |
252 | void addHashTabEntry(unsigned long long int addr){ | |
253 | ||
254 | unsigned long long match=addr|VALID_BIT; | |
255 | int i; | |
256 | if (num_entries < max_entries){ | |
257 | hash_mem[num_entries++] = match; | |
258 | return; | |
259 | }else { | |
260 | for (i=0;i<num_entries;i++){ | |
261 | if (!hash_mem[i]){ | |
262 | hash_mem[i]=match; | |
263 | return; | |
264 | } | |
265 | } | |
266 | } | |
267 | printf("ERROR: AXIS MALLOC DEBUG table is full adding %llx\n", addr); | |
268 | } | |
269 | #else | |
270 | int getHashTabEntry (unsigned long long int addr){ | |
271 | map<unsigned long long int,unsigned char>:: iterator it; | |
272 | it = hash_mem.find(addr); | |
273 | // printf("MALLOC DEBUG1 getHashTabEntry addr = %llx xx = %x \n",addr,hash_mem[addr]); | |
274 | ||
275 | if(it!=hash_mem.end()) { | |
276 | // printf("MALLOC DEBUG1 getHashTabEntry return VALID addr = %llx xx = %x \n",addr,hash_mem[addr]); | |
277 | return(VALID); | |
278 | } | |
279 | else return(0); | |
280 | } | |
281 | ||
282 | void addHashTabEntry(unsigned long long int addr){ | |
283 | ||
284 | hash_mem[addr] = 1; | |
285 | // printf(" MALLOC DEBUG1 addHashTabEntry addr = %llx xx = %x \n",addr,hash_mem[addr]); | |
286 | } | |
287 | #endif | |
288 | ||
289 | int check_page_match(unsigned long long int addr, int page_id) { | |
290 | unsigned long long int addr_to_check, mask , value, reloc; | |
291 | ||
292 | addr_to_check = addr >> 12; // <- this determines the block size | |
293 | mask = page[page_id]->mask; | |
294 | value = page[page_id]->value; | |
295 | reloc = page[page_id]->reloc; | |
296 | ||
297 | // printf(" value - %x \n",value); | |
298 | // printf(" mask - %x \n",mask); | |
299 | // printf(" addr_to_check - %x \n",addr_to_check); | |
300 | // printf(" addr - %llx \n",addr); | |
301 | ||
302 | // add your function | |
303 | if((addr_to_check & mask) == value) | |
304 | return(0); | |
305 | else { | |
306 | // printf("MAL_CPP : NO Match found\n"); | |
307 | return(1); | |
308 | } | |
309 | } | |
310 | ||
311 | ||
312 | ||
313 | #ifdef N2_AXIS | |
314 | int check_allocated ( unsigned long long int addr, int no_of_blocks,int page_id){ | |
315 | #else | |
316 | int check_allocated ( unsigned long long int addr, int no_of_blocks,int page_id,int alignment){ | |
317 | #endif | |
318 | ||
319 | int i; | |
320 | unsigned long long int xlate_addr; | |
321 | unsigned long long int addr_with_blocks; | |
322 | unsigned int block_size; | |
323 | int status0,status1; | |
324 | ||
325 | if(addr == 0) return(1); | |
326 | ||
327 | ||
328 | block_size = 1<<BITS_TO_IGNORE; | |
329 | ||
330 | // | |
331 | ||
332 | // translate this address and then check | |
333 | if(page[page_id]->xlate_on) | |
334 | xlate_addr = page[page_id]->xlate_addr(addr); | |
335 | else xlate_addr = addr; | |
336 | ||
337 | // translate this address and then check | |
338 | status0 = check_page_match(addr, page_id); | |
339 | status1 = check_page_match(addr + (no_of_blocks* block_size) ,page_id); | |
340 | if(status1 | status0) return(1); | |
341 | ||
342 | ||
343 | addr = xlate_addr >>BITS_TO_IGNORE; // <- this determines the block size | |
344 | for(i=0;i<no_of_blocks;i++) { | |
345 | if(getHashTabEntry(addr + i) == VALID ) { | |
346 | return(1); // This address is already allocated | |
347 | } | |
348 | } | |
349 | addr_with_blocks = xlate_addr + no_of_blocks* ( 1<<BITS_TO_IGNORE); | |
350 | ||
351 | addr = addr_with_blocks >>BITS_TO_IGNORE; // <- this determines the block size | |
352 | ||
353 | #ifdef N2_AXIS | |
354 | for(i=0;i<1;i++) { | |
355 | if(getHashTabEntry(addr + i) == VALID ) { | |
356 | return(1); // This address is already allocated | |
357 | } | |
358 | } | |
359 | #else | |
360 | if(alignment<block_size) { | |
361 | // Only when alignment is less than the blocks size, there are chances that | |
362 | // the assigned blocks will straddle | |
363 | for(i=0;i<1;i++) { | |
364 | if(getHashTabEntry(addr + i) == VALID ) { | |
365 | return(1); // This address is already allocated | |
366 | } | |
367 | } | |
368 | } | |
369 | #endif | |
370 | ||
371 | return(0); | |
372 | ||
373 | } | |
374 | ||
375 | ||
376 | unsigned long long int malloc_addr(int no_of_blocks, int block_size, unsigned int page_mask, int page_id,int alignment) { | |
377 | ||
378 | // block size has to be power of 2 | |
379 | ||
380 | unsigned long long int addr; | |
381 | unsigned int page_mask_h; | |
382 | unsigned int page_mask_l; | |
383 | ||
384 | unsigned int value_h; | |
385 | unsigned int value_l; | |
386 | ||
387 | // MASK sets up the range of address needed | |
388 | // | |
389 | addr =0; | |
390 | int cnt; | |
391 | int status; | |
392 | ||
393 | int i; | |
394 | unsigned int a; | |
395 | i = 0; | |
396 | a = alignment>>1; | |
397 | while(a) { | |
398 | a = a>>1; | |
399 | i++; | |
400 | } | |
401 | unsigned int mask_4K; | |
402 | mask_4K = 0x0; | |
403 | for(int j = 0; j < i; j ++) { | |
404 | mask_4K = mask_4K | ( 1<<j); | |
405 | } | |
406 | mask_4K = 0xffffffff ^ mask_4K; | |
407 | ||
408 | unsigned int value; | |
409 | value = page[page_id]->value; | |
410 | page_mask = page[page_id]->mask ; | |
411 | ||
412 | page_mask_l = ((page_mask & 0x000fffff) << 12); | |
413 | page_mask_h = (page_mask & 0xfff00000) >> 20; | |
414 | ||
415 | value_h = ((page[page_id]->value & 0x000fffff) << 12); | |
416 | value_l = (page[page_id]->value & 0xfff00000) >> 20; | |
417 | ||
418 | unsigned int addr_43_12; | |
419 | ||
420 | cnt =0; | |
421 | status =1; | |
422 | while( status & (cnt < MAX_ITER)) { | |
423 | #ifdef NEPTUNE | |
424 | addr_43_12 = 0x0fffffff & random() & ( page_mask ^0xffffffff ) | value; | |
425 | addr_43_12 = addr_43_12 & VIRTMASKH; | |
426 | #else | |
427 | #ifdef N2_FC | |
428 | addr_43_12 = 0x000fffff & random() & ( page_mask ^0xffffffff ) | value; | |
429 | #else | |
430 | addr_43_12 = 0x07ffffff & random() & ( page_mask ^0xffffffff ) | value; | |
431 | #endif | |
432 | #endif | |
433 | addr = (unsigned long long int ) (addr_43_12 & ( 0xfffffff0 | (( ( mask_4K&0xf000)>>12 )&0xf)))<<12 ; | |
434 | // printf(" MALLOC_DEBUG: 1 addr = %llx status = %d cnt = %d \n",addr,status,cnt); | |
435 | /// FIX FOR RDMC addr = (addr |( ( random() & MASKL & mask_4K ) & 0xfff)) ; | |
436 | addr = (addr |( ( random() & MASKL & mask_4K ) & 0xfff)) ; | |
437 | #ifdef N2_AXIS | |
438 | status = check_allocated(addr, no_of_blocks,page_id); | |
439 | #else | |
440 | status = check_allocated(addr, no_of_blocks,page_id,alignment); | |
441 | #endif | |
442 | // printf(" MALLOC_DEBUG: 2 addr = %llx status = %d cnt = %d \n",addr,status,cnt); | |
443 | cnt ++; | |
444 | } | |
445 | if(cnt==MAX_ITER) { | |
446 | printf(" MALLOC_DEBUG: Cannot allocate Memory, Free up some locations ---\n"); | |
447 | return(0); | |
448 | } | |
449 | ||
450 | // Add all the allocated entries into the hash table | |
451 | ||
452 | page[page_id]->byte_allocated = page[page_id]->byte_allocated + block_size* no_of_blocks; | |
453 | // printf(" MALLOC_DEBUG: PageID %d - BytesAllocated - %d\n",page_id,page[page_id]->byte_allocated); | |
454 | ||
455 | unsigned long long int addr_tobe_added; | |
456 | ||
457 | addr_tobe_added = (page[page_id]->xlate_addr(addr)) >> BITS_TO_IGNORE; | |
458 | ||
459 | for(int i =0;i<no_of_blocks;i++) { | |
460 | addHashTabEntry(addr_tobe_added + i); | |
461 | } | |
462 | // Add the next block if overflow is detected | |
463 | #ifdef N2_AXIS | |
464 | addr_tobe_added = ((page[page_id]->xlate_addr(addr)) + block_size* no_of_blocks) >> BITS_TO_IGNORE; | |
465 | addHashTabEntry(addr_tobe_added); | |
466 | #else | |
467 | if(alignment<block_size) { | |
468 | addr_tobe_added = ((page[page_id]->xlate_addr(addr)) + block_size* no_of_blocks) >> BITS_TO_IGNORE; | |
469 | addHashTabEntry(addr_tobe_added); | |
470 | } | |
471 | #endif | |
472 | ||
473 | return(addr); | |
474 | } | |
475 | ||
476 | int free_addr(unsigned long long int addr, int no_of_blocks,int page_id){ | |
477 | // if return value is 0 then there has been an error | |
478 | int status,i; | |
479 | unsigned long long int addr_tobe_deleted; | |
480 | int block_size; | |
481 | unsigned int alignment; | |
482 | ||
483 | if((page_id<0)| ( page_id>127)) { | |
484 | printf("free_addr: Incorrect PAGE ID Specified!! TB ERROR\n"); | |
485 | return(-1); | |
486 | } | |
487 | block_size = 1 << BITS_TO_IGNORE; // Start with some number -- | |
488 | ||
489 | alignment = addr&0xfff; | |
490 | addr_tobe_deleted = addr >> BITS_TO_IGNORE; | |
491 | ||
492 | status = 0; | |
493 | for(i =0; i< no_of_blocks; i ++) { | |
494 | status = deleteHashTabEntry(addr_tobe_deleted + i) + status; | |
495 | } | |
496 | if(alignment) { // else already 4K alignment | |
497 | if(alignment<block_size) { | |
498 | status = deleteHashTabEntry(addr_tobe_deleted + 1) + status; | |
499 | } | |
500 | } | |
501 | ||
502 | if(status) { | |
503 | page[page_id]->byte_allocated = page[page_id]->byte_allocated - block_size* no_of_blocks; | |
504 | if(verbose) | |
505 | #ifdef N2_AXIS | |
506 | printf(" AXIS MALLOC_DEBUG: NoOfBytes Freed - %d PageID %d - Current BytesAllocated - %d\n",block_size* | |
507 | no_of_blocks, page_id,page[page_id]->byte_allocated); | |
508 | #else | |
509 | printf(" MALLOC_DEBUG: NoOfBytes Freed - %d PageID %d - Current BytesAllocated - %d\n",block_size*no_of_blocks, page_id,page[page_id]->byte_allocated); | |
510 | #endif | |
511 | } | |
512 | return(status); | |
513 | } | |
514 | ||
515 | void set_block_size(int block_size, int mode_32b) { | |
516 | ||
517 | BITS_TO_IGNORE = -1; | |
518 | ||
519 | MASKH = mode_32b? 0x0 : 0xff; | |
520 | VIRTMASKH = mode_32b? 0x000fffff: 0xffffffff; | |
521 | ||
522 | int blocks; | |
523 | blocks = block_size; | |
524 | while(blocks) { | |
525 | BITS_TO_IGNORE++; | |
526 | blocks = blocks >>1; | |
527 | } | |
528 | ||
529 | ||
530 | } | |
531 | ||
532 | ||
533 | int CheckPageId(vec32 *addrh, vec32 *addrl) { | |
534 | int page_id = -1; | |
535 | unsigned long long int addr; | |
536 | int match; | |
537 | ||
538 | addr = addrh->d & 0xff ; // Restrict this to 40 bits only for now | |
539 | addr = addr<<32; | |
540 | addr = addr | ( (unsigned long long int) addrl->d ); | |
541 | ||
542 | match =0; | |
543 | page_id=-1; | |
544 | while((match==0) && (page_id<128)) { | |
545 | page_id++; | |
546 | match = page[page_id]->check_addr_match(addr); | |
547 | } | |
548 | if(match) return(page_id) ; | |
549 | else return(-1); | |
550 | ||
551 | } | |
552 | void MarkUsedLocations(vec32 *addrh, vec32 *addrl, int no_of_blocks) { | |
553 | ||
554 | unsigned long long int addr; | |
555 | unsigned long long int addr_tobe_added; | |
556 | ||
557 | addr = addrh->d & 0xff ; // Restrict this to 40 bits only for now | |
558 | addr = addr<<32; | |
559 | addr = addr | ( (unsigned long long int) addrl->d ); | |
560 | ||
561 | addr_tobe_added = addr >>BITS_TO_IGNORE; | |
562 | if(verbose) { | |
563 | printf("MALLOC DEBUG Marking Addresses from %llx to Address %llx as Used \n", addr, (addr + no_of_blocks* (1<<BITS_TO_IGNORE))); | |
564 | } | |
565 | ||
566 | for(int i =0;i<no_of_blocks;i++) { | |
567 | addHashTabEntry(addr_tobe_added + i); | |
568 | } | |
569 | } | |
570 | unsigned long long int xlate_addr( unsigned long long int addr, int page_id ) { | |
571 | unsigned long long int retval; | |
572 | // translate this address and then check | |
573 | if(page[page_id]->xlate_on) { | |
574 | retval = page[page_id]->xlate_addr(addr); } | |
575 | else retval = addr; | |
576 | ||
577 | return(retval); | |
578 | } | |
579 | ||
580 | ||
581 | vec32* XlateAddr( vec32 * addrh, vec32 * addrl, int page_id) { | |
582 | unsigned long long int init_addr; | |
583 | unsigned long long int xlateaddr; | |
584 | vec32 retval[2]; | |
585 | ||
586 | if(pages_allocated == 0) { | |
587 | // enable only only one page ie page0 | |
588 | for(int i = 0; i <128;i++) { | |
589 | page[i] = new PAGEINFO (); | |
590 | page[i]->valid = 1; | |
591 | page[i]->xlate_on = 0; | |
592 | page[i]->page_size = -1; | |
593 | page[i]->mask = 0; | |
594 | page[i]->value = 0x0; | |
595 | } | |
596 | pages_allocated = 1; | |
597 | } | |
598 | ||
599 | if(page_id <128) { | |
600 | init_addr = addrh->d; | |
601 | init_addr = init_addr <<32; | |
602 | init_addr = init_addr | addrl->d; | |
603 | xlateaddr = xlate_addr( init_addr, page_id); | |
604 | retval[0].d = xlateaddr & 0xffffffff; | |
605 | retval[0].c = 0x0; | |
606 | retval[1].d = (unsigned long long int ) xlateaddr>>32;; | |
607 | retval[1].c = 0x0; | |
608 | return(retval); | |
609 | } else { | |
610 | printf(" XlateAddr:: TESTBENCH ERROR \n"); | |
611 | retval[0].d = 0; | |
612 | retval[0].c = 0xffffffff; | |
613 | retval[1].d = 0; | |
614 | retval[1].c = 0xffffffff; | |
615 | return(retval); | |
616 | } | |
617 | } | |
618 | ||
619 | ||
620 | void SetExtMemBlockSize(int block_size, int mode_32b) { | |
621 | ||
622 | set_block_size(block_size,mode_32b); | |
623 | ||
624 | } | |
625 | ||
626 | ||
627 | ||
628 | int FreeAddr (vec32 * addrh, vec32 * addrl, int no_of_blocks, int page_id){ | |
629 | ||
630 | unsigned long long int addr; | |
631 | int status; | |
632 | addr = addrh->d; | |
633 | addr = addr <<32; | |
634 | addr = addr | addrl->d; | |
635 | status = free_addr(addr, no_of_blocks,page_id); | |
636 | return(status); | |
637 | } | |
638 | ||
639 | int ForcePageContexts (int page_id, vec32 * mask, vec32 * value, vec32 * reloc) { | |
640 | if(pages_allocated == 0) { | |
641 | for(int i = 0; i <128;i++) { | |
642 | page[i] = new PAGEINFO (); | |
643 | page[i]->valid = 1; | |
644 | page[i]->xlate_on = 0; | |
645 | page[i]->page_size = -1; | |
646 | page[i]->mask = 0; | |
647 | page[i]->value = 0x0; | |
648 | } | |
649 | pages_allocated = 1; | |
650 | } | |
651 | if(page_id>=128) { | |
652 | printf(" MALLOC_DEBUG: page id - %d greater than 128!! ERROR \n"); | |
653 | return(-1); | |
654 | } | |
655 | page[page_id]->valid = 1; | |
656 | page[page_id]->xlate_on = 1; | |
657 | page[page_id]->page_size = -1; | |
658 | page[page_id]->mask = mask->d; | |
659 | page[page_id]->value = value->d; | |
660 | page[page_id]->reloc = reloc->d; | |
661 | ||
662 | return(1); | |
663 | } | |
664 | ||
665 | vec32* MallocBlock(int no_of_blocks, int page_id, int alignment ) { | |
666 | ||
667 | unsigned long long int addr; | |
668 | vec32 returnval[2]; | |
669 | unsigned int addrl,addrh; | |
670 | unsigned int page_mask; | |
671 | ||
672 | int block_size; | |
673 | block_size = 1 << BITS_TO_IGNORE; // Start with some number -- | |
674 | ||
675 | if(pages_allocated == 0) { | |
676 | // enable only only one page ie page0 | |
677 | for(int i = 0; i <128;i++) { | |
678 | page[i] = new PAGEINFO (); | |
679 | page[i]->valid = 1; | |
680 | page[i]->xlate_on = 0; | |
681 | page[i]->page_size = -1; | |
682 | page[i]->mask = 0; | |
683 | page[i]->value = 0x0; | |
684 | } | |
685 | pages_allocated = 1; | |
686 | } | |
687 | ||
688 | if(page_id>=128) { | |
689 | printf(" MALLOC_DEBUG: page id - %d greater than 128!! ERROR \n"); | |
690 | returnval[0].d = 0; | |
691 | returnval[0].c = 0xffffffff; | |
692 | returnval[1].d = 0; | |
693 | returnval[1].c = 0xffffffff; | |
694 | return(returnval); | |
695 | } | |
696 | if(page[page_id]->valid) { | |
697 | // printf(" MALLOC_DEBUG: page_id - %d bytes_allocated - %d , page_size - %d \n",page_id,page[page_id]->byte_allocated,page[page_id]->page_size); | |
698 | if( ( (block_size*no_of_blocks) + page[page_id]->byte_allocated ) > page[page_id]->page_size) { | |
699 | printf(" MALLOC_DEBUG: No Space available!!! - ERROR \n"); | |
700 | returnval[0].d = 0; | |
701 | returnval[0].c = 0xffffffff; | |
702 | returnval[1].d = 0; | |
703 | returnval[1].c = 0xffffffff; | |
704 | return(returnval); | |
705 | } | |
706 | ||
707 | if(page[page_id]->xlate_on) | |
708 | page_mask = page[page_id]->mask; | |
709 | else page_mask = 0; | |
710 | ||
711 | #ifdef N2_AXIS | |
712 | #else | |
713 | if(verbose) | |
714 | printf(" MALLOC_DEBUG: malloc called with page_id - %d page_mask - %x \n",page_id,page_mask); | |
715 | #endif | |
716 | ||
717 | addr = malloc_addr( no_of_blocks, block_size, page_mask, page_id,alignment); | |
718 | if(verbose) | |
719 | printf(" MALLOC_DEBUG: Virtual Allocated address = %llx with NoOfBlock - %d page_mask - %x page_id - %d BytesAllocated - %d Page Size - %d ByteAlignment - %d \n",addr,no_of_blocks, page_mask,page_id,page[page_id]->byte_allocated,page[page_id]->page_size, alignment); | |
720 | if(addr==0) { | |
721 | printf(" MALLOC_DEBUG: No Space available!!! - ERROR \n"); | |
722 | returnval[0].d = 0; | |
723 | returnval[0].c = 0xffffffff; | |
724 | returnval[1].d = 0; | |
725 | returnval[1].c = 0xffffffff; | |
726 | return(returnval); | |
727 | } | |
728 | ||
729 | // returnval = (vec32 *) malloc(sizeof(vec32)); | |
730 | addrl = addr & 0xffffffff; | |
731 | addr = (unsigned long long int ) addr>>32; | |
732 | addrh = addr; | |
733 | returnval[0].d = addrl; | |
734 | returnval[0].c = 0; | |
735 | returnval[1].d = addrh; | |
736 | returnval[1].c = 0; | |
737 | } else { | |
738 | printf(" MALLOC_DEBUG: page id - %d Not initialized!! ERROR \n",page_id); | |
739 | returnval[0].d = 0; | |
740 | returnval[0].c = 0; | |
741 | returnval[1].d = 0; | |
742 | returnval[1].c = 0; | |
743 | } | |
744 | ||
745 | return(returnval); | |
746 | ||
747 | ||
748 | } | |
749 | ||
750 | ||
751 | ||
752 | // Functions to return handle to page; ( top 20bits in Address) | |
753 | #ifdef N2_AXIS | |
754 | int check_page_handle_alloc ( unsigned int handle) { | |
755 | if (!hash_mem){ | |
756 | printf(" MALLOC_DEBUG: check_page_handle_alloc when hash table==NULL \n"); | |
757 | hash_mem=(unsigned long long *)calloc(max_entries,sizeof(unsigned long long)); | |
758 | if (!hash_mem){ | |
759 | printf(" could not calloc %d bytes \n", max_entries*sizeof(unsigned long long)); exit(1); | |
760 | } | |
761 | ||
762 | } | |
763 | if (hash_mem[handle] & VALID_BIT) | |
764 | return(VALID); | |
765 | else return(0); | |
766 | } | |
767 | #else | |
768 | map< unsigned int,unsigned char> page_handle; | |
769 | int check_page_handle_alloc ( unsigned int handle) { | |
770 | map<unsigned int,unsigned char>:: iterator it; | |
771 | it = page_handle.find(handle); | |
772 | // printf(" addr = %x xx = %x \n",addr,hash_mem[addr]); | |
773 | if(it!=page_handle.end()) | |
774 | return(VALID); | |
775 | else return(0); | |
776 | } | |
777 | #endif | |
778 | vec32* GetPageHandle() { | |
779 | unsigned int handle; | |
780 | vec32 *retval; | |
781 | retval = (vec32 *) malloc(sizeof(vec32)); | |
782 | int status; | |
783 | status = 1; | |
784 | while(status) { | |
785 | handle = random() & 0xfffff;// 20 bits only | |
786 | status = check_page_handle_alloc(handle); | |
787 | } | |
788 | #ifdef N2_AXIS | |
789 | #else | |
790 | page_handle[handle] = 1; | |
791 | #endif | |
792 | if(verbose) printf(" MALLOC_DEBUG: Page Handle Allocated - %x \n",handle); | |
793 | retval->d = handle; | |
794 | retval->c = 0; | |
795 | return(retval); | |
796 | } | |
797 | ||
798 | #ifdef N2_AXIS | |
799 | unsigned int DeletePageHandle( unsigned int handle) { | |
800 | if (hash_mem[handle] & VALID_BIT){ | |
801 | hash_mem[handle] =0; | |
802 | return(1); | |
803 | } else { | |
804 | printf(" AXIS MALLOC_DEBUG: address not found ERROR \n"); | |
805 | return(0); | |
806 | } | |
807 | } | |
808 | #else | |
809 | unsigned int DeletePageHandle( unsigned int handle) { | |
810 | if(page_handle.find(handle)!=page_handle.end()) { | |
811 | page_handle.erase(page_handle.find(handle)); | |
812 | return(1); | |
813 | } else { | |
814 | printf(" MALLOC_DEBUG: address not found ERROR \n"); | |
815 | return(0); | |
816 | } | |
817 | } | |
818 | #endif | |
819 | ||
820 | // functions to return page masks | |
821 | ||
822 | vec32 * GetPageMask (int id) { | |
823 | vec32 *retval; | |
824 | retval = (vec32 *) malloc(sizeof(vec32)); | |
825 | if(page[id]->valid) { | |
826 | retval->d = page[id]->mask; | |
827 | } else | |
828 | retval->d = 0; | |
829 | retval->c = 0; | |
830 | return(retval); | |
831 | } | |
832 | vec32 * GetPageValue (int id) { | |
833 | vec32 *retval; | |
834 | retval = (vec32 *) malloc(sizeof(vec32)); | |
835 | if(page[id]->valid) { | |
836 | retval->d = page[id]->value; | |
837 | } else | |
838 | retval->d = 0; | |
839 | retval->c = 0; | |
840 | return(retval); | |
841 | } | |
842 | vec32 * GetPageReloc (int id) { | |
843 | vec32 *retval; | |
844 | retval = (vec32 *) malloc(sizeof(vec32)); | |
845 | if(page[id]->valid) { | |
846 | retval->d = page[id]->reloc; | |
847 | } else | |
848 | retval->d = 0; | |
849 | retval->c = 0; | |
850 | return(retval); | |
851 | ||
852 | } | |
853 | int SetConfig ( int config, unsigned int gSeed ){ | |
854 | srandom(gSeed); | |
855 | if(config == 1) { | |
856 | verbose = 1; | |
857 | } | |
858 | else { | |
859 | verbose = 0; | |
860 | } | |
861 | // Can have more configs here | |
862 | return 0; | |
863 | } | |
864 | ||
865 | int DeletePageContext ( int id) { | |
866 | if(pages_allocated) { | |
867 | delete page[id]; | |
868 | page[id] = new PAGEINFO (); | |
869 | page[id]->xlate_on = 1; | |
870 | return(1); | |
871 | } else return(0); | |
872 | } | |
873 | int SetPageMask ( int no_of_pages /* NoOf4KPages*/, int type, int id) { | |
874 | ||
875 | ||
876 | ||
877 | static int id_assigned = 0; | |
878 | unsigned char b[32]; | |
879 | static int init= 0; | |
880 | unsigned int mask; | |
881 | int entry_free; | |
882 | int cnt; | |
883 | int index; | |
884 | int status; | |
885 | if(!init) { | |
886 | for(int i = 0; i <128;i++) { | |
887 | page[i] = new PAGEINFO (); | |
888 | page[i]->xlate_on = 1; | |
889 | } | |
890 | init = 1; | |
891 | pages_allocated = 1; | |
892 | #ifdef N2_AXIS | |
893 | #else | |
894 | for(int i = 0; i < 32;i++) page_bits[i] = 0; | |
895 | #endif | |
896 | } | |
897 | ||
898 | if(page[id]->valid) { | |
899 | printf(" MALLOC_DEBUG: ERROR- Pageid - %d already allocated - Delete this page before re-allocating \n",id); | |
900 | return(-1); | |
901 | } | |
902 | ||
903 | ||
904 | if(no_of_pages == 1) { // Need 4K size | |
905 | ||
906 | page[id]->mask = 0xffffffff; | |
907 | page[id]->mask = page[id]->mask & VIRTMASKH; | |
908 | page[id]->id = id; | |
909 | page[id]->page_size = 4096; | |
910 | unsigned int value = page[id]->calc_value(); | |
911 | unsigned int reloc = page[id]->calc_reloc(); | |
912 | page[id]->valid = 1; | |
913 | status = 1; | |
914 | return(status); | |
915 | } | |
916 | if(no_of_pages == -1) { // get the entire memory -- only one large page is valid | |
917 | id = 0; // force to 0 | |
918 | page[id]->mask = 0; | |
919 | page[id]->mask = page[id]->mask & VIRTMASKH; | |
920 | page[id]->page_size = -1; | |
921 | page[id]->xlate_on = 0; | |
922 | page[id]->id = id; | |
923 | unsigned int value = page[id]->calc_value(); | |
924 | unsigned int reloc = page[id]->calc_reloc(); | |
925 | page[id]->valid = 1; | |
926 | status =1 ; | |
927 | return(status); | |
928 | } | |
929 | ||
930 | cnt = 0; | |
931 | int no_of_0s; | |
932 | no_of_0s = 0; | |
933 | int no_of_4Kpages = no_of_pages; | |
934 | while(no_of_4Kpages) { | |
935 | no_of_0s++; | |
936 | no_of_4Kpages = no_of_4Kpages>>1; | |
937 | } | |
938 | // printf(" NoOf 0s = %d required for #%d NoOf4KPages \n",no_of_0s,no_of_pages); | |
939 | ||
940 | // fill in appropriate number of 0s and return the mask | |
941 | ||
942 | #ifdef N2_AXIS | |
943 | for(int i = 0; i < 32;i++) b[i] = 0; | |
944 | ||
945 | if(type == 0 /* No holes*/) { | |
946 | mask = 0xffffffff; | |
947 | for(int i = 0 ; i < no_of_0s; i ++) { | |
948 | mask = mask ^ ( 1 << i); | |
949 | } | |
950 | cnt = 0; | |
951 | } else { | |
952 | mask = 0xffffffff; | |
953 | for(int i = 0 ; i < no_of_0s; i ++) { | |
954 | entry_free = 0; | |
955 | cnt = 0; | |
956 | while(!entry_free & (cnt <32)) { | |
957 | index = random() % 32; | |
958 | cnt ++; | |
959 | if(b[index]!=0) entry_free = 0; | |
960 | else { entry_free = 1; b[index] = 1;} | |
961 | } | |
962 | // flip the appropriate bit as indicated by the index | |
963 | mask = mask ^ ( 1 << index); | |
964 | } | |
965 | } | |
966 | #else | |
967 | if(type== NOHOLES) { | |
968 | mask = 0xffffffff; | |
969 | for(int i = 0 ; i < no_of_0s; i ++) { | |
970 | mask = mask ^ ( 1 << i); | |
971 | } | |
972 | cnt = 0; | |
973 | } else if(type==INC_NOHOLES/*Noholes*/) { | |
974 | // pick up the first available 0 from bottom | |
975 | index = 31; | |
976 | while((page_bits[index]==1)&( index >=0)) { | |
977 | index--; | |
978 | } | |
979 | ||
980 | // move this index such that index+no_of_page <32 | |
981 | if( (index+no_of_0s) > 32) { | |
982 | index = index - ( index + no_of_0s -32 ); | |
983 | } | |
984 | int start_index = index; | |
985 | // int end_index = index + no_of_0s; | |
986 | int end_index = 32; | |
987 | mask = 0xffffffff; | |
988 | printf("MALLOC DEBUG start_index - %d end_index - %d \n",start_index,end_index); | |
989 | for(int i= start_index; i< end_index;i++) { | |
990 | mask = mask ^ ( 1 << (31 - i)); | |
991 | page_bits[i] = 1; | |
992 | } | |
993 | } else { | |
994 | for(int i = 0; i < 32;i++) b[i] = 0; | |
995 | ||
996 | if(type== RANDOM_HOLES) { | |
997 | mask = 0xffffffff; | |
998 | } else { | |
999 | // add no of contg 0s based upon the type and leave the rest to | |
1000 | // random | |
1001 | mask = 0xffffffff; | |
1002 | for(int i = 0 ; i < type; i ++) { | |
1003 | mask = mask ^ ( 1 << i); | |
1004 | b[i] = 1; | |
1005 | } | |
1006 | if((no_of_0s - type)<0) { | |
1007 | printf("MALLOC USER ERROR In correct Type given!!! \n"); | |
1008 | status = -1; | |
1009 | return(status); | |
1010 | } | |
1011 | } | |
1012 | for(int i = 0 ; i < no_of_0s - type; i ++) { | |
1013 | entry_free = 0; | |
1014 | cnt = 0; | |
1015 | while(!entry_free & (cnt <32)) { | |
1016 | index = random() % 32; | |
1017 | cnt ++; | |
1018 | if(b[index]!=0) entry_free = 0; | |
1019 | else { entry_free = 1; b[index] = 1;} | |
1020 | } | |
1021 | // flip the appropriate bit as indicated by the index | |
1022 | mask = mask ^ ( 1 << index); | |
1023 | } | |
1024 | } | |
1025 | #endif | |
1026 | if(cnt >= 32) { | |
1027 | printf(" MALLOC_DEBUG: ERROR - All entries are occupied in the page mask generation!! \n"); | |
1028 | page[id]->valid = 0; | |
1029 | page[id]->mask = 0; | |
1030 | page[id]->id = id; | |
1031 | page[id]->page_size = 0; | |
1032 | unsigned int value = page[id]->calc_value(); | |
1033 | unsigned int reloc = page[id]->calc_reloc(); | |
1034 | page[id]->valid = 1; | |
1035 | status = -1; | |
1036 | return(status); | |
1037 | ||
1038 | } | |
1039 | ||
1040 | if(verbose) printf(" MALLOC_DEBUG: Page Mask Derived - %x \n",mask); | |
1041 | page[id]->mask = mask; | |
1042 | page[id]->id = id; | |
1043 | page[id]->page_size = 4096*no_of_pages ; | |
1044 | unsigned int value = page[id]->calc_value(); | |
1045 | unsigned int reloc = page[id]->calc_reloc(); | |
1046 | page[id]->valid = 1; | |
1047 | status = 1; | |
1048 | return(status); | |
1049 | } | |
1050 | ||
1051 | /* | |
1052 | int main() { | |
1053 | ||
1054 | ||
1055 | int i; | |
1056 | unsigned long long int addr; | |
1057 | int block_size; | |
1058 | int no_of_blocks; | |
1059 | ||
1060 | block_size = 512; // Start with some number -- | |
1061 | no_of_blocks = 4; // 4 blocks of 512 bytes | |
1062 | ||
1063 | ||
1064 | set_block_size(block_size); | |
1065 | ||
1066 | for( i = 0; i< 100000; i ++) { | |
1067 | addr = malloc_addr( no_of_blocks, block_size); | |
1068 | printf(" i = %d addr = %x \n",i,addr); | |
1069 | ||
1070 | } | |
1071 | ||
1072 | ||
1073 | return(1); | |
1074 | } | |
1075 | ||
1076 | */ | |
1077 | #if defined(__cplusplus) | |
1078 | } /* extern "C" */ | |
1079 | #endif | |
1080 |