/***********************************************************************
* Functions to generate and manage random memory address
* * Orignal Author(s): Arvind Srinivasan
* * Copyright (c) 2004 Sun Microsystems, Inc.
* * This verilog model is the confidential and proprietary property of
* * Sun Microsystems, Inc., and the possession or use of this model
* * requires a written license from Sun Microsystems, Inc.
************************************************************************/
#include "vera_directc.h"
unsigned int byte_allocated
;
unsigned int calc_value();
unsigned int calc_reloc();
unsigned char check_addr_match(unsigned long long int addr
);
unsigned long long int xlate_addr( unsigned long long int addr
);
unsigned int PAGEINFO::calc_value() {
// VJH This code can be cleaned up but seems OK for now..confer with Arvind/Vernon
value
= value
& mask
& 0x0fffffff ; // Force top bits to be 0 for now-
value
= value
& mask
& 0x0fffffe0 ; // Force top bits to be 0 for now-
// HACK NEED TO CLEAN THIS
value
= value
& mask
& 0x0fffffff ; // Force top bits to be 0 for now-
value
= value
& mask
& 0x000fffff ; // Force top bits to be 0 for now-
value
= value
& mask
& 0x000fffe0 ; // Force top bits to be 0 for now-
value
= value
& mask
& 0x000fffff ; // Force top bits to be 0 for now-
value
= value
& mask
& 0x07ffffff ; // Force top bits to be 0 for now-
value
= value
& mask
& 0x07ffffe0 ; // Force top bits to be 0 for now-
value
= value
& mask
& 0x07ffffff ; // Force top bits to be 0 for now-
value
= value
& VIRTMASKH
; // for supporting 32bit address mode in Neptune
if(verbose
) printf(" MALLOC_DEBUG: Value for id - %d set to %x \n",id
,value
);
unsigned int PAGEINFO::calc_reloc() {
/* For neptune, we need to block the following address range 0xF8FFFFFF - 0xF5000000
* This belongs to the EEPROM
#define NEPT_EEPROM_BASE_MAX 0xF8FFF
#define NEPT_EEPROM_BASE_MIN 0xF5000
if((reloc
<=NEPT_EEPROM_BASE_MAX
) && ( reloc
>= NEPT_EEPROM_BASE_MIN
)) {
printf("PAGEINFO::calc_reloc ERROR Cannot find a suitable reloc for PageID - %d \n",id
);
reloc
= reloc
& 0x0fffffff; // Force top bits to be 0 for now-
reloc
= reloc
& 0x000fffff; // Force top bits to be 0 for now-
// OLD CODE reloc = reloc & 0x07ffffff; // Force top bits to be 0 for now-
// OLD CODE reloc = reloc & 0x07ffffe0; // Force top bits to be 0 for now-
// VJH Doesn't this following line over-writes the previous lines?
reloc
= reloc
& 0x07ffffff; // Force top bits to be 0 for now-
reloc
= reloc
& VIRTMASKH
; // for supporting 32bit address mode in Neptune
if(verbose
) printf(" MALLOC_DEBUG: reloc for id - %d set to %x \n",id
,reloc
);
unsigned long long int PAGEINFO::xlate_addr( unsigned long long int addr
) {
unsigned long long int retval
;
unsigned int p
= addr
& 0xfff;
unsigned long long int orig_address
;
xlate
= addr
& 0xffffffff;
xlate
= reloc
& mask
| xlate
& (mask
^ 0xffffffff);
retval
= retval
<<12 | p
;
/* This is only to check if EEPROM base address is not getting generated.*/
if((retval
<=NEPT_EEPROM_BASE_MAX
) && ( retval
>= NEPT_EEPROM_BASE_MIN
)) {
printf(" MALLOC_DEBUG: Xlated Address is within EEPROM Range!! ERROR! FIX THIS!!!\n");
if(verbose
) printf(" MALLOC_DEBUG: Xlated Address = %llx orig address - %llx \n",retval
,orig_address
);
unsigned char PAGEINFO::check_addr_match(unsigned long long int addr
){
if((addr
& mask
)==reloc
) {
static int pages_allocated
= 0; // needed to prevent user errors
static unsigned char page_bits
[32];
#define VALID_BIT (1ULL<<56)
unsigned long long *hash_mem
=NULL
;
int max_entries
=1*1024*1024;
map
< unsigned long long int,unsigned char> hash_mem
;
static int BITS_TO_IGNORE
;
int deleteHashTabEntry (unsigned long long int addr
){
// printf(" MALLOC DEBUG in deleteHashTabEntry addr = %x xx = %x \n",addr,hash_mem[addr]);
unsigned long long match
=addr
|VALID_BIT
;
printf(" AXIS_MALLOC_DEBUG: ERROR: remove entry when hash table==NULL \n"); return (0);
for (i
=0;i
<num_entries
;i
++){
printf(" AXIS_MALLOC_DEBUG: address not found ERROR \n");
if(hash_mem
.find(addr
)!=hash_mem
.end()) {
hash_mem
.erase(hash_mem
.find(addr
));
// printf(" MALLOC_DEBUG: deleteaddress - %x found \n",addr);
printf(" MALLOC_DEBUG: deleteaddress - %x not found ERROR \n",addr
);
int getHashTabEntry (unsigned long long int addr
){
unsigned long long match
=addr
|VALID_BIT
;
printf(" AXIS_MALLOC_DEBUG: get entry when hash table==NULL \n");
hash_mem
=(unsigned long long *)calloc(max_entries
,sizeof(unsigned long long));
printf(" could not calloc %d bytes \n", max_entries
*sizeof(unsigned long long)); exit(1);
for (i
=0;i
<num_entries
;i
++){
void addHashTabEntry(unsigned long long int addr
){
unsigned long long match
=addr
|VALID_BIT
;
if (num_entries
< max_entries
){
hash_mem
[num_entries
++] = match
;
for (i
=0;i
<num_entries
;i
++){
printf("ERROR: AXIS MALLOC DEBUG table is full adding %llx\n", addr
);
int getHashTabEntry (unsigned long long int addr
){
map
<unsigned long long int,unsigned char>:: iterator it
;
it
= hash_mem
.find(addr
);
// printf("MALLOC DEBUG1 getHashTabEntry addr = %llx xx = %x \n",addr,hash_mem[addr]);
// printf("MALLOC DEBUG1 getHashTabEntry return VALID addr = %llx xx = %x \n",addr,hash_mem[addr]);
void addHashTabEntry(unsigned long long int addr
){
// printf(" MALLOC DEBUG1 addHashTabEntry addr = %llx xx = %x \n",addr,hash_mem[addr]);
int check_page_match(unsigned long long int addr
, int page_id
) {
unsigned long long int addr_to_check
, mask
, value
, reloc
;
addr_to_check
= addr
>> 12; // <- this determines the block size
mask
= page
[page_id
]->mask
;
value
= page
[page_id
]->value
;
reloc
= page
[page_id
]->reloc
;
// printf(" value - %x \n",value);
// printf(" mask - %x \n",mask);
// printf(" addr_to_check - %x \n",addr_to_check);
// printf(" addr - %llx \n",addr);
if((addr_to_check
& mask
) == value
)
// printf("MAL_CPP : NO Match found\n");
int check_allocated ( unsigned long long int addr
, int no_of_blocks
,int page_id
){
int check_allocated ( unsigned long long int addr
, int no_of_blocks
,int page_id
,int alignment
){
unsigned long long int xlate_addr
;
unsigned long long int addr_with_blocks
;
block_size
= 1<<BITS_TO_IGNORE
;
// translate this address and then check
if(page
[page_id
]->xlate_on
)
xlate_addr
= page
[page_id
]->xlate_addr(addr
);
// translate this address and then check
status0
= check_page_match(addr
, page_id
);
status1
= check_page_match(addr
+ (no_of_blocks
* block_size
) ,page_id
);
if(status1
| status0
) return(1);
addr
= xlate_addr
>>BITS_TO_IGNORE
; // <- this determines the block size
for(i
=0;i
<no_of_blocks
;i
++) {
if(getHashTabEntry(addr
+ i
) == VALID
) {
return(1); // This address is already allocated
addr_with_blocks
= xlate_addr
+ no_of_blocks
* ( 1<<BITS_TO_IGNORE
);
addr
= addr_with_blocks
>>BITS_TO_IGNORE
; // <- this determines the block size
if(getHashTabEntry(addr
+ i
) == VALID
) {
return(1); // This address is already allocated
if(alignment
<block_size
) {
// Only when alignment is less than the blocks size, there are chances that
// the assigned blocks will straddle
if(getHashTabEntry(addr
+ i
) == VALID
) {
return(1); // This address is already allocated
unsigned long long int malloc_addr(int no_of_blocks
, int block_size
, unsigned int page_mask
, int page_id
,int alignment
) {
// block size has to be power of 2
unsigned long long int addr
;
unsigned int page_mask_h
;
unsigned int page_mask_l
;
// MASK sets up the range of address needed
for(int j
= 0; j
< i
; j
++) {
mask_4K
= mask_4K
| ( 1<<j
);
mask_4K
= 0xffffffff ^ mask_4K
;
value
= page
[page_id
]->value
;
page_mask
= page
[page_id
]->mask
;
page_mask_l
= ((page_mask
& 0x000fffff) << 12);
page_mask_h
= (page_mask
& 0xfff00000) >> 20;
value_h
= ((page
[page_id
]->value
& 0x000fffff) << 12);
value_l
= (page
[page_id
]->value
& 0xfff00000) >> 20;
while( status
& (cnt
< MAX_ITER
)) {
addr_43_12
= 0x0fffffff & random() & ( page_mask
^0xffffffff ) | value
;
addr_43_12
= addr_43_12
& VIRTMASKH
;
addr_43_12
= 0x000fffff & random() & ( page_mask
^0xffffffff ) | value
;
addr_43_12
= 0x07ffffff & random() & ( page_mask
^0xffffffff ) | value
;
addr
= (unsigned long long int ) (addr_43_12
& ( 0xfffffff0 | (( ( mask_4K
&0xf000)>>12 )&0xf)))<<12 ;
// printf(" MALLOC_DEBUG: 1 addr = %llx status = %d cnt = %d \n",addr,status,cnt);
/// FIX FOR RDMC addr = (addr |( ( random() & MASKL & mask_4K ) & 0xfff)) ;
addr
= (addr
|( ( random() & MASKL
& mask_4K
) & 0xfff)) ;
status
= check_allocated(addr
, no_of_blocks
,page_id
);
status
= check_allocated(addr
, no_of_blocks
,page_id
,alignment
);
// printf(" MALLOC_DEBUG: 2 addr = %llx status = %d cnt = %d \n",addr,status,cnt);
printf(" MALLOC_DEBUG: Cannot allocate Memory, Free up some locations ---\n");
// Add all the allocated entries into the hash table
page
[page_id
]->byte_allocated
= page
[page_id
]->byte_allocated
+ block_size
* no_of_blocks
;
// printf(" MALLOC_DEBUG: PageID %d - BytesAllocated - %d\n",page_id,page[page_id]->byte_allocated);
unsigned long long int addr_tobe_added
;
addr_tobe_added
= (page
[page_id
]->xlate_addr(addr
)) >> BITS_TO_IGNORE
;
for(int i
=0;i
<no_of_blocks
;i
++) {
addHashTabEntry(addr_tobe_added
+ i
);
// Add the next block if overflow is detected
addr_tobe_added
= ((page
[page_id
]->xlate_addr(addr
)) + block_size
* no_of_blocks
) >> BITS_TO_IGNORE
;
addHashTabEntry(addr_tobe_added
);
if(alignment
<block_size
) {
addr_tobe_added
= ((page
[page_id
]->xlate_addr(addr
)) + block_size
* no_of_blocks
) >> BITS_TO_IGNORE
;
addHashTabEntry(addr_tobe_added
);
int free_addr(unsigned long long int addr
, int no_of_blocks
,int page_id
){
// if return value is 0 then there has been an error
unsigned long long int addr_tobe_deleted
;
if((page_id
<0)| ( page_id
>127)) {
printf("free_addr: Incorrect PAGE ID Specified!! TB ERROR\n");
block_size
= 1 << BITS_TO_IGNORE
; // Start with some number --
addr_tobe_deleted
= addr
>> BITS_TO_IGNORE
;
for(i
=0; i
< no_of_blocks
; i
++) {
status
= deleteHashTabEntry(addr_tobe_deleted
+ i
) + status
;
if(alignment
) { // else already 4K alignment
if(alignment
<block_size
) {
status
= deleteHashTabEntry(addr_tobe_deleted
+ 1) + status
;
page
[page_id
]->byte_allocated
= page
[page_id
]->byte_allocated
- block_size
* no_of_blocks
;
printf(" AXIS MALLOC_DEBUG: NoOfBytes Freed - %d PageID %d - Current BytesAllocated - %d\n",block_size
*
no_of_blocks
, page_id
,page
[page_id
]->byte_allocated
);
printf(" MALLOC_DEBUG: NoOfBytes Freed - %d PageID %d - Current BytesAllocated - %d\n",block_size
*no_of_blocks
, page_id
,page
[page_id
]->byte_allocated
);
void set_block_size(int block_size
, int mode_32b
) {
MASKH
= mode_32b
? 0x0 : 0xff;
VIRTMASKH
= mode_32b
? 0x000fffff: 0xffffffff;
int CheckPageId(vec32
*addrh
, vec32
*addrl
) {
unsigned long long int addr
;
addr
= addrh
->d
& 0xff ; // Restrict this to 40 bits only for now
addr
= addr
| ( (unsigned long long int) addrl
->d
);
while((match
==0) && (page_id
<128)) {
match
= page
[page_id
]->check_addr_match(addr
);
if(match
) return(page_id
) ;
void MarkUsedLocations(vec32
*addrh
, vec32
*addrl
, int no_of_blocks
) {
unsigned long long int addr
;
unsigned long long int addr_tobe_added
;
addr
= addrh
->d
& 0xff ; // Restrict this to 40 bits only for now
addr
= addr
| ( (unsigned long long int) addrl
->d
);
addr_tobe_added
= addr
>>BITS_TO_IGNORE
;
printf("MALLOC DEBUG Marking Addresses from %llx to Address %llx as Used \n", addr
, (addr
+ no_of_blocks
* (1<<BITS_TO_IGNORE
)));
for(int i
=0;i
<no_of_blocks
;i
++) {
addHashTabEntry(addr_tobe_added
+ i
);
unsigned long long int xlate_addr( unsigned long long int addr
, int page_id
) {
unsigned long long int retval
;
// translate this address and then check
if(page
[page_id
]->xlate_on
) {
retval
= page
[page_id
]->xlate_addr(addr
); }
vec32
* XlateAddr( vec32
* addrh
, vec32
* addrl
, int page_id
) {
unsigned long long int init_addr
;
unsigned long long int xlateaddr
;
if(pages_allocated
== 0) {
// enable only only one page ie page0
for(int i
= 0; i
<128;i
++) {
page
[i
] = new PAGEINFO ();
init_addr
= init_addr
<<32;
init_addr
= init_addr
| addrl
->d
;
xlateaddr
= xlate_addr( init_addr
, page_id
);
retval
[0].d
= xlateaddr
& 0xffffffff;
retval
[1].d
= (unsigned long long int ) xlateaddr
>>32;;
printf(" XlateAddr:: TESTBENCH ERROR \n");
retval
[0].c
= 0xffffffff;
retval
[1].c
= 0xffffffff;
void SetExtMemBlockSize(int block_size
, int mode_32b
) {
set_block_size(block_size
,mode_32b
);
int FreeAddr (vec32
* addrh
, vec32
* addrl
, int no_of_blocks
, int page_id
){
unsigned long long int addr
;
status
= free_addr(addr
, no_of_blocks
,page_id
);
int ForcePageContexts (int page_id
, vec32
* mask
, vec32
* value
, vec32
* reloc
) {
if(pages_allocated
== 0) {
for(int i
= 0; i
<128;i
++) {
page
[i
] = new PAGEINFO ();
printf(" MALLOC_DEBUG: page id - %d greater than 128!! ERROR \n");
page
[page_id
]->valid
= 1;
page
[page_id
]->xlate_on
= 1;
page
[page_id
]->page_size
= -1;
page
[page_id
]->mask
= mask
->d
;
page
[page_id
]->value
= value
->d
;
page
[page_id
]->reloc
= reloc
->d
;
vec32
* MallocBlock(int no_of_blocks
, int page_id
, int alignment
) {
unsigned long long int addr
;
unsigned int addrl
,addrh
;
block_size
= 1 << BITS_TO_IGNORE
; // Start with some number --
if(pages_allocated
== 0) {
// enable only only one page ie page0
for(int i
= 0; i
<128;i
++) {
page
[i
] = new PAGEINFO ();
printf(" MALLOC_DEBUG: page id - %d greater than 128!! ERROR \n");
returnval
[0].c
= 0xffffffff;
returnval
[1].c
= 0xffffffff;
if(page
[page_id
]->valid
) {
// 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);
if( ( (block_size
*no_of_blocks
) + page
[page_id
]->byte_allocated
) > page
[page_id
]->page_size
) {
printf(" MALLOC_DEBUG: No Space available!!! - ERROR \n");
returnval
[0].c
= 0xffffffff;
returnval
[1].c
= 0xffffffff;
if(page
[page_id
]->xlate_on
)
page_mask
= page
[page_id
]->mask
;
printf(" MALLOC_DEBUG: malloc called with page_id - %d page_mask - %x \n",page_id
,page_mask
);
addr
= malloc_addr( no_of_blocks
, block_size
, page_mask
, page_id
,alignment
);
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
);
printf(" MALLOC_DEBUG: No Space available!!! - ERROR \n");
returnval
[0].c
= 0xffffffff;
returnval
[1].c
= 0xffffffff;
// returnval = (vec32 *) malloc(sizeof(vec32));
addrl
= addr
& 0xffffffff;
addr
= (unsigned long long int ) addr
>>32;
printf(" MALLOC_DEBUG: page id - %d Not initialized!! ERROR \n",page_id
);
// Functions to return handle to page; ( top 20bits in Address)
int check_page_handle_alloc ( unsigned int handle
) {
printf(" MALLOC_DEBUG: check_page_handle_alloc when hash table==NULL \n");
hash_mem
=(unsigned long long *)calloc(max_entries
,sizeof(unsigned long long));
printf(" could not calloc %d bytes \n", max_entries
*sizeof(unsigned long long)); exit(1);
if (hash_mem
[handle
] & VALID_BIT
)
map
< unsigned int,unsigned char> page_handle
;
int check_page_handle_alloc ( unsigned int handle
) {
map
<unsigned int,unsigned char>:: iterator it
;
it
= page_handle
.find(handle
);
// printf(" addr = %x xx = %x \n",addr,hash_mem[addr]);
if(it
!=page_handle
.end())
retval
= (vec32
*) malloc(sizeof(vec32
));
handle
= random() & 0xfffff;// 20 bits only
status
= check_page_handle_alloc(handle
);
if(verbose
) printf(" MALLOC_DEBUG: Page Handle Allocated - %x \n",handle
);
unsigned int DeletePageHandle( unsigned int handle
) {
if (hash_mem
[handle
] & VALID_BIT
){
printf(" AXIS MALLOC_DEBUG: address not found ERROR \n");
unsigned int DeletePageHandle( unsigned int handle
) {
if(page_handle
.find(handle
)!=page_handle
.end()) {
page_handle
.erase(page_handle
.find(handle
));
printf(" MALLOC_DEBUG: address not found ERROR \n");
// functions to return page masks
vec32
* GetPageMask (int id
) {
retval
= (vec32
*) malloc(sizeof(vec32
));
retval
->d
= page
[id
]->mask
;
vec32
* GetPageValue (int id
) {
retval
= (vec32
*) malloc(sizeof(vec32
));
retval
->d
= page
[id
]->value
;
vec32
* GetPageReloc (int id
) {
retval
= (vec32
*) malloc(sizeof(vec32
));
retval
->d
= page
[id
]->reloc
;
int SetConfig ( int config
, unsigned int gSeed
){
// Can have more configs here
int DeletePageContext ( int id
) {
page
[id
] = new PAGEINFO ();
int SetPageMask ( int no_of_pages
/* NoOf4KPages*/, int type
, int id
) {
static int id_assigned
= 0;
for(int i
= 0; i
<128;i
++) {
page
[i
] = new PAGEINFO ();
for(int i
= 0; i
< 32;i
++) page_bits
[i
] = 0;
printf(" MALLOC_DEBUG: ERROR- Pageid - %d already allocated - Delete this page before re-allocating \n",id
);
if(no_of_pages
== 1) { // Need 4K size
page
[id
]->mask
= 0xffffffff;
page
[id
]->mask
= page
[id
]->mask
& VIRTMASKH
;
page
[id
]->page_size
= 4096;
unsigned int value
= page
[id
]->calc_value();
unsigned int reloc
= page
[id
]->calc_reloc();
if(no_of_pages
== -1) { // get the entire memory -- only one large page is valid
page
[id
]->mask
= page
[id
]->mask
& VIRTMASKH
;
page
[id
]->page_size
= -1;
unsigned int value
= page
[id
]->calc_value();
unsigned int reloc
= page
[id
]->calc_reloc();
int no_of_4Kpages
= no_of_pages
;
no_of_4Kpages
= no_of_4Kpages
>>1;
// printf(" NoOf 0s = %d required for #%d NoOf4KPages \n",no_of_0s,no_of_pages);
// fill in appropriate number of 0s and return the mask
for(int i
= 0; i
< 32;i
++) b
[i
] = 0;
if(type
== 0 /* No holes*/) {
for(int i
= 0 ; i
< no_of_0s
; i
++) {
for(int i
= 0 ; i
< no_of_0s
; i
++) {
while(!entry_free
& (cnt
<32)) {
if(b
[index
]!=0) entry_free
= 0;
else { entry_free
= 1; b
[index
] = 1;}
// flip the appropriate bit as indicated by the index
mask
= mask
^ ( 1 << index
);
for(int i
= 0 ; i
< no_of_0s
; i
++) {
} else if(type
==INC_NOHOLES
/*Noholes*/) {
// pick up the first available 0 from bottom
while((page_bits
[index
]==1)&( index
>=0)) {
// move this index such that index+no_of_page <32
if( (index
+no_of_0s
) > 32) {
index
= index
- ( index
+ no_of_0s
-32 );
// int end_index = index + no_of_0s;
printf("MALLOC DEBUG start_index - %d end_index - %d \n",start_index
,end_index
);
for(int i
= start_index
; i
< end_index
;i
++) {
mask
= mask
^ ( 1 << (31 - i
));
for(int i
= 0; i
< 32;i
++) b
[i
] = 0;
if(type
== RANDOM_HOLES
) {
// add no of contg 0s based upon the type and leave the rest to
for(int i
= 0 ; i
< type
; i
++) {
if((no_of_0s
- type
)<0) {
printf("MALLOC USER ERROR In correct Type given!!! \n");
for(int i
= 0 ; i
< no_of_0s
- type
; i
++) {
while(!entry_free
& (cnt
<32)) {
if(b
[index
]!=0) entry_free
= 0;
else { entry_free
= 1; b
[index
] = 1;}
// flip the appropriate bit as indicated by the index
mask
= mask
^ ( 1 << index
);
printf(" MALLOC_DEBUG: ERROR - All entries are occupied in the page mask generation!! \n");
unsigned int value
= page
[id
]->calc_value();
unsigned int reloc
= page
[id
]->calc_reloc();
if(verbose
) printf(" MALLOC_DEBUG: Page Mask Derived - %x \n",mask
);
page
[id
]->page_size
= 4096*no_of_pages
;
unsigned int value
= page
[id
]->calc_value();
unsigned int reloc
= page
[id
]->calc_reloc();
unsigned long long int addr;
block_size = 512; // Start with some number --
no_of_blocks = 4; // 4 blocks of 512 bytes
set_block_size(block_size);
for( i = 0; i< 100000; i ++) {
addr = malloc_addr( no_of_blocks, block_size);
printf(" i = %d addr = %x \n",i,addr);