I am working on creating a cache access function in C and have ran into a strange issue with an unexpected recursive call. I may just be misunderstanding recursion in this case but I'm very confused as to why this is happening. This is my current function, mem_access provides read/write to my simulated memory. This is the function:
int cache_access(cache_t *c, addr_t addr, void *value, int size, int iswrite){
int addr_offset = addr & ((1<<LOGBSIZE)-1); //all bits 0 - LOGBSIZE, anded with addr
int addr_index = (addr>>(LOGBSIZE)) & ((1<<c->cache_s)-1); // addr >> LOGBSIZE (allows for index to be low order bits), then based on cache_s we extract that number of low order bits.
int addr_tag = addr & ~((1<<(c->cache_s + LOGBSIZE))-1); //to get the tag we remove the low order bits and and with addr
cacheset_t current_set = c->cache_sets[addr_index];
int delay_total = 0;
delay_total += c->cache_delay;
for(int i = 0; i < c->cache_E; i++){
//hit
cacheline_t *line = &(current_set.lines[i]);
if(addr_tag == line->tag && line->valid == 1){
if(iswrite){
memcpy(value, line->block, size);
line->dirty = 1;
}else{
memcpy(line->block, value, size);
}
// update lru
update_LRU(¤t_set, i, c->cache_E);
return delay_total;
//miss
}else{
//index 0 in useinfo
int evict_index = ((uint8_t *)current_set.useinfo)[0];
if(current_set.lines[evict_index].dirty != 0){
//concatenation of tag and index
addr_t evict_addr = (current_set.lines[evict_index].tag) | (addr_index<<LOGBSIZE);
//write block to next lower level
if(c->cache_next == NULL){
delay_total += mem_access(evict_addr, current_set.lines[evict_index].block + addr_offset, (1 << LOGBSIZE), 1);
}else{
delay_total += cache_access(c->cache_next, evict_addr, current_set.lines[evict_index].block + addr_offset, (1<<LOGBSIZE), 1);
}
}
//recursively check lower levels in cache, reading in from either cache or memory to the block
//(assumed) source of recursive error
if(c->cache_next == NULL){
delay_total += mem_access(addr, current_set.lines[evict_index].block, (1<<LOGBSIZE), 0);
}else{
delay_total+=cache_access(c->cache_next, addr, current_set.lines[evict_index].block, (1<<LOGBSIZE), 0);
}
current_set.lines[evict_index].valid = 1;
current_set.lines[evict_index].dirty = iswrite ? 1 : 0;
current_set.lines[evict_index].tag = addr_tag;
//update line with tag and set valid to 1
line[i].valid = 1;
line[i].tag = addr_tag;
update_LRU(¤t_set, i, c->cache_E);
return delay_total;
}
}
}
When I run in GDB, this is what I am greeted with:
39 for(int i = 0; i < c->cache_E; i++){
(gdb)
41 cacheline_t *line = &(current_set.lines[i]);
(gdb)
42 if(addr_tag == line->tag && line->valid == 1){
(gdb)
58 int evict_index = ((uint8_t *)current_set.useinfo)[0];
(gdb)
59 if(current_set.lines[evict_index].dirty != 0){
(gdb)
70 if(c->cache_next == NULL){
(gdb)
71 delay_total += mem_access(addr, current_set.lines[evict_index].block, (1<<LOGBSIZE), 0);
(gdb)
75 current_set.lines[evict_index].valid = 1;
(gdb) x/16xb current_set.lines[evict_index].block
0x555555559c20: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07
0x555555559c28: 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f
(gdb) n
76 current_set.lines[evict_index].dirty = iswrite ? 1 : 0;
(gdb)
77 current_set.lines[evict_index].tag = addr_tag;
(gdb)
80 line[i].valid = 1;
(gdb)
81 line[i].tag = addr_tag;
(gdb)
83 update_LRU(¤t_set, i, c->cache_E);
(gdb)
85 return delay_total;
(gdb)
88 }
(gdb)
cache_access (c=0x55555555a580, addr=131072, value=0x7fffffffe324, size=1, iswrite=0) at cachesim.c:73
73 delay_total+=cache_access(c->cache_next,addr, value, size, 0);
(gdb) x/16xb current_set.lines[evict_index].block
0x55555555a660: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x55555555a668: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
(gdb) n
75 current_set.lines[evict_index].valid = 1;
(gdb) n
76 current_set.lines[evict_index].dirty = iswrite ? 1 : 0;
(gdb)
77 current_set.lines[evict_index].tag = addr_tag;
(gdb)
80 line[i].valid = 1;
(gdb)
81 line[i].tag = addr_tag;
(gdb)
83 update_LRU(¤t_set, i, c->cache_E);
(gdb) q
So my main question is why is this recursive call (using all parameters of the initial cache_access call) happening? It is causing the data in my block to be overwritten. Shouldn't it end after the return? Thanks for any help.