这部分感觉写着很有意思,写之前一脸懵逼,写完后对cache方面的知识确实有了飞一般地认知,希望后面的学弟学妹们不要照抄,关键部分注释我都写得比较明白,还是要理解为主,希望大家都能自己写写,这个挺好玩的
那么话不多说,代码放这里了
cache.h
#ifndef CACHE #define CACHE #include "mips.h" #include <stdio.h> #include <stdbool.h> #include <stdint.h> typedef struct { bool valid; uint32_t lru;//2 bytes uint32_t tag;//21 bytes uint32_t mem[32]; }cache_line; typedef struct { cache_line line[4]; }cache_set; typedef struct { cache_set set[64]; }Cache; extern Cache cache; void init(); void cache_write(uint32_t address); uint32_t cache_read(uint32_t address); extern int delay; #endif
cache.c
#include "cache.h" #include "pipe.h" #include "shell.h" #include "mips.h" #include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> Cache cache; int delay = 0; void init(){ int i =0, j = 0; for(i=0;i<64;i++){ for(j=0;j<4;j++){ cache.set[i].line[j].valid = 0; cache.set[i].line[j].lru = 0; } } } uint32_t cache_read(uint32_t address){ uint32_t set = (address >>5) &(0x3F);//6 bytes of block uint32_t inoffset = address & (0x1f);//loc of line ,5 bytes uint32_t tag = address >> 11 ;//tag 21 bytes uint32_t word=0; int flag_lru=0; int write_line=0; for(int i=0;i<4;i++){ if(cache.set[set].line[i].valid==1){//judge is valid if(cache.set[set].line[i].tag == tag){//judge is tag right flag_lru=cache.set[set].line[i].lru; write_line=i; uint32_t j=inoffset; word= (cache.set[set].line[i].mem[j]<<0) | (cache.set[set].line[i].mem[j+1]<<8) | (cache.set[set].line[i].mem[j+2]<<16) | (cache.set[set].line[i].mem[j+3]<<24); break; } } } //cache hit if(write_line!=-1){ for(int i=0;i<4;i++){ if(i!=write_line){ if(cache.set[set].line[i].lru<flag_lru){ cache.set[set].line[i].lru++; } } } return word; } //cache miss delay = 49; cache_write(address); return 0; } void cache_write(uint32_t address){ uint32_t inoffset= address & 0x1F;//loc of line ,5 bytes uint32_t set= (address >>5) &(0x3F);//6 bytes of block uint32_t tag=address >>11;//tag 21 bytes uint32_t start_line= (address >> 5)<<5;//the loc of write line int write_line= -1; int flag_lru=0; for(int i=0;i<4;i++){ if(cache.set[set].line[i].valid==0){//find the line in the set which isn't been written,initialize the line flag_lru=cache.set[set].line[i].lru; cache.set[set].line[i].tag = tag;//new line ,the lru is zero cache.set[set].line[i].valid = 1;//the line is changed cache.set[set].line[i].lru = 0;//update the lru write_line = i; break; } } //cache hit,every lru++,expect write line if(write_line!=-1){ for(int i=0;i<4;i++){ if(write_line!=i){ if(flag_lru>cache.set[set].line[i].lru) cache.set[set].line[i].lru++; } } } else if(write_line==-1){//cache miss,the cache is full now,it should be replaced with one line uint8_t max_lru = 0; for(int i=0;i<4;i++){ cache.set[set].line[i].lru++;//every lru ++,because cache miss if(max_lru<=cache.set[set].line[i].lru){//find the max_lru and write_line index in the lines of sets max_lru = cache.set[set].line[i].lru; write_line = i; } } //init the replaced line again cache.set[set].line[write_line].tag = tag;//replace the origional tag with new tag cache.set[set].line[write_line].valid = 1;//the line is changed cache.set[set].line[write_line].lru = 0; //new line ,the lru is zero } //read from memory and write on the write_line for(int i = 0;i<8;i++){ uint32_t word = mem_read_32(start_line);//the mem block size is 32 bytes cache.set[set].line[write_line].mem[i*4] = (uint8_t)(word>>0) &0xFF;//load low 8 bytes total 32 bytes each times from memory to write_lines cache.set[set].line[write_line].mem[i*4+1] = (uint8_t)(word>>8) &0xFF; cache.set[set].line[write_line].mem[i*4+2] = (uint8_t)(word>>16)&0xFF; cache.set[set].line[write_line].mem[i*4+3] = (uint8_t)(word>>24)&0xFF; start_line+=4; } }
cache_data.h
#ifndef CACHEDATA #define CACHEDATA #include "stdio.h" #include "mips.h" #include "stdbool.h" #include "stdint.h" typedef struct { bool valid; bool dirty; uint32_t lru; uint32_t tag; uint32_t mem[32]; }cache_data_line; typedef struct { cache_data_line data_line[8]; }cache_data_set; typedef struct { cache_data_set data_set[256]; }Cache_data; extern Cache_data cache_data; extern int cache_data_delay; void data_init(); void cache_data_write(uint32_t address,uint32_t write); void cache_data_GetFromMem(uint32_t address); uint32_t cache_data_read(uint32_t address); #endif
cache_data.c
#include "cache_data.h" #include "pipe.h" #include "shell.h" #include "mips.h" #include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> Cache_data cache_data; int cache_data_delay = 0; void data_init(){ int i =0, j = 0; for(i=0;i<256;i++) { for(j=0;j<8;j++) { cache_data.data_set[i].data_line[j].valid = 0; cache_data.data_set[i].data_line[j].lru = 0; cache_data.data_set[i].data_line[j].dirty = 0; } } } uint32_t cache_data_read(uint32_t address){ uint32_t inoffset = address & (0x1F);//get the low 5 bytes uint32_t set = (address >>5) &(0xFF);//get 5-12 bytes uint32_t tag = address >> 13 ;//get tag bytes for(int i=0;i<8;i++){ if(cache_data.data_set[set].data_line[i].valid==1){ if(cache_data.data_set[set].data_line[i].tag == tag){ uint32_t word = (cache_data.data_set[set].data_line[i].mem[inoffset]<<0) | (cache_data.data_set[set].data_line[i].mem[inoffset+1]<<8) | (cache_data.data_set[set].data_line[i].mem[inoffset+2]<<16) | (cache_data.data_set[set].data_line[i].mem[inoffset+3]<<24); return word; }