⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpu.c

📁 一个MIPS虚拟机的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef EXTERN
#undef EXTERN
#endif
#define EXTERN extern

#include "global.h"

static char reg_table[CPU_REGISTER_NUMBER][5]=
{
	"zero","at","v0","v1","a0",
	"a1","a2","a3","t0","t1",
	"t2","t3","t4","t5","t6",
	"t7","s0","s1","s2","s3",
	"s4","s5","s6","s7","t8",
	"t9","k0","k1","gp","sp",
	"s8","ra"
};

static void cpu_reset()
{

	PC = ROM_RESET_BASE_ADDR;
}

static void  disable_cacheline(UINT32 vaddr,UINT32 phyaddr,int operation_mode)
{
	UINT32  index,word_vaddr;
	word_vaddr = vaddr & 0xfffffffc;
	
	if (is_swc()==true)
		{
			if (operation_mode == DATA_STORE)
				{
					operation_mode = INSTRUCTION_STORE;
				}
			else if (operation_mode == INSTRUCTION_STORE)
				operation_mode = DATA_STORE;
		}
	
	if (operation_mode==DATA_STORE)
		{
			index = (phyaddr & DCACHE_MASK) ;
			if ( (is_isc()==true) || (  (dcache[index].tag == word_vaddr) && (dcache[index].flag & CACHE_VALID_MASK) ))
				{
					//hit
					 dcache[index].flag = ~CACHE_VALID_MASK;
					
				}
			
			
			
		}
	else if (operation_mode==INSTRUCTION_STORE)
		{
			index = phyaddr & ICACHE_MASK;
			if ((is_isc()==true)||( (icache[index].tag == word_vaddr) && (icache[index].flag & CACHE_VALID_MASK) ))
				{
					//hit
					 icache[index].flag = ~CACHE_VALID_MASK;
				}
			
			
		}

}
/*if exception has occured, return false,else return true*/
static boolean  store_halfword_into_memory(UINT32 phyaddr,UINT16  data)
{
	UINT32 offset;
	
	if (phyaddr<=RAM_UPPER_BOUND)
		{
			//RAM
			
			offset = phyaddr - RAM_LOWER_BOUND;
			//ram[offset] = data;
			halfword2bytes(data, &ram[offset] );
			return true;
		}
	else if ((phyaddr>=CONSOLE_LOWER_ADDR)&&(phyaddr<=CONSOLE_UPPER_ADDR))
		{
			console_store_byte(phyaddr,data);
		}
	else
		{
			//bad address exception
			exception(ADES,-1);
			return false;
		}
}


static boolean store_halfword(UINT32 vaddr,UINT32 phyaddr,boolean cache_able,int operation_mode,UINT16  data)
{
	if ((phyaddr % 2)!=0)
		{
			//exception
			//bad address
			exception(ADES,-1);
			return false;
		}
	// now we store a word into memory
	// and disable cache
	if (store_halfword_into_memory(phyaddr,data))
		{
		disable_cacheline(vaddr,phyaddr,operation_mode);
		return true;
		}
	else
		return false;

	
}



static boolean  store_word_into_memory(UINT32 phyaddr,UINT32  data)
{
	UINT32 offset;
	//printf("phyaddr  %x",phyaddr);
	if (phyaddr<=RAM_UPPER_BOUND)
		{
			//RAM
			offset = phyaddr - RAM_LOWER_BOUND;
			word2bytes(data, &ram[offset] );
			return true;
		}
	else if ((phyaddr>=CONSOLE_LOWER_ADDR)&&(phyaddr<=CONSOLE_UPPER_ADDR))
		{
			console_store_byte(phyaddr,data);
		}
	else
		{
			//bad address exception
			exception(ADES,-1);
			return false;
		}
}


static boolean  store_word(UINT32 vaddr,UINT32 phyaddr,boolean cache_able,int operation_mode,UINT32  data)
{
	if ((phyaddr % 4)!=0)
		{
			//exception
			//bad address
			exception(ADES,-1);
			return  false;
		}
	// now we store a word into memory
	// and disable cache
	
	if (store_word_into_memory(phyaddr,data))
		{
			disable_cacheline(vaddr,phyaddr,operation_mode);
			return true;
		}
	else
		return false;
	
		
}

static boolean  store_byte_into_memory(UINT32 phyaddr,UINT8  data)
{
	UINT32 offset;
	
	if (phyaddr<=RAM_UPPER_BOUND)
		{
			//RAM
			offset = phyaddr - RAM_LOWER_BOUND;
			ram[offset] = data;
			return true;
			
		}
	else if ((phyaddr>=CONSOLE_LOWER_ADDR)&&(phyaddr<=CONSOLE_UPPER_ADDR))
		{
			console_store_byte(phyaddr,data);
		}
	else
		{
			//bad address exception
			exception(ADES,-1);
			return false;
		}
}




static boolean store_byte(UINT32 vaddr,UINT32 phyaddr,boolean cache_able,int operation_mode,UINT8  data)
{
	
	// now we store a byte into memory
	// and disable cache
	UINT32 word_vaddr;

	if (store_byte_into_memory(phyaddr,data))
		{
			disable_cacheline(vaddr,phyaddr,operation_mode);
			return true;
		}
	else 
		return false;
	

}





/* load a word from memory. Memory includes RAM and ROM. 
If exception occurs,return false, else return true*/
static boolean  load_word_from_memory(UINT32 phyaddr,UINT32 * data)
{
	UINT32 offset;
	//fprintf(stderr,"start load_word_from_memory\n");
	if (phyaddr<=RAM_UPPER_BOUND)
		{
			//RAM
			//fprintf(stderr,"RAM\n");
			offset = phyaddr - RAM_LOWER_BOUND;
			*data = bytes2word(&ram[offset]);
			return true;
			
		}
	else if ((phyaddr>=ROM_LOWER_BOUND) && ( phyaddr<=ROM_UPPER_BOUND))
		{
			//ROM
			//fprintf(stderr,"ROM\n");
			offset = phyaddr - ROM_LOWER_BOUND;
			//fprintf(stderr,"offset= %d\n",offset);
			*data = bytes2word(&rom[offset]);
			//fprintf(stderr,"*data = %x\n",*data );
			return true;
		}
	else if ((phyaddr>=CONSOLE_LOWER_ADDR)&&(phyaddr<=CONSOLE_UPPER_ADDR))
		{
			*data = console_load_word(phyaddr);
		}
	else
		{
			//bad address exception
			exception(ADEL,-1);
			return false;
		
		}
		
}


/*  if hit ,return true, else return false*/
static boolean load_word_from_cache(UINT32 vaddr,UINT32 phyaddr,int operation_mode,UINT32 * data)
{
	UINT32  index;
	
	if (true==is_swc())
		{
			if (DATA_LOAD ==operation_mode  )
				{
					operation_mode = INSTRUCTION_LOAD;
				}
			else if (operation_mode == INSTRUCTION_LOAD)
				operation_mode = DATA_LOAD;
		}
	
	if (DATA_LOAD == operation_mode)
		{
			index = (phyaddr & DCACHE_MASK) ;
			if ( (true ==is_isc()) || (  (dcache[index].tag == vaddr) && (dcache[index].flag & CACHE_VALID_MASK) ))
				{
					//hit
					*data = dcache[index].cache_line;
					return true;
				}
			else
				{
					//miss
					return false;
				}
		}
	else if (INSTRUCTION_LOAD==operation_mode)
		{
			index = phyaddr & ICACHE_MASK;
			if ((true ==is_isc())||( (icache[index].tag == vaddr) && (icache[index].flag & CACHE_VALID_MASK) ))
				{
					//hit
					*data = icache[index].cache_line;
					return true;
				}
			else
				{
					return false;
					
				}
		}

	
	
	
}
/*When we load a word, if cache miss ,then we must load the word form ram and set to cache*/
static void set_word_to_cache(UINT32 vaddr,UINT32 phyaddr,int operation_mode,UINT32  data)
{
	UINT32  index;
	
	if (true ==is_isc())
		{
			if (DATA_LOAD == operation_mode  )
				{
					operation_mode = INSTRUCTION_LOAD;
				}
			else if (INSTRUCTION_LOAD == operation_mode  )
				operation_mode = DATA_LOAD;
		}
	
	if (DATA_LOAD == operation_mode)
		{
			index = (phyaddr & DCACHE_MASK) ;
			dcache[index].cache_line = data;
			dcache[index].tag = vaddr;
			dcache[index].flag =CACHE_VALID_MASK;
			
		}
	else if (INSTRUCTION_LOAD ==operation_mode)
		{
			index = (phyaddr & ICACHE_MASK) ;
			icache[index].cache_line = data;
			icache[index].tag = vaddr;
			icache[index].flag =ICACHE_MASK;
		}
}

/*load a word from phyaddr..*/
static boolean load_word(UINT32 vaddr,UINT32 phyaddr,boolean cache_able,int operation_mode,UINT32 * data)
{
	if ((phyaddr % 4)!=0)
		{
			//exception
			//bad address
			exception(ADEL,-1);
			return  false;
		}
	if (true  == cache_able)
		{
			//load a word from cache.
			if (load_word_from_cache(vaddr, phyaddr,operation_mode, data))
				return true;
		}

		/*now, cache miss or cache_able=false ,load from ram*/
		
			//load a word from ram
		if (load_word_from_memory(phyaddr, data))
			{
				//printf("*data %x \n",*data);
				// set the word to cache.
				// Now we only set the cache line if and only if we load a word.
				// That means when loading a hb or byte, we do not set the cache line.
				if (cache_able==true )
					set_word_to_cache(vaddr,phyaddr,operation_mode,*data);
				return true;
			}
		
	
			
		
	
}
static boolean  load_byte_from_memory(UINT32 phyaddr,UINT8 * data)
{
	UINT32 offset;
	//UINT8 byte_offset;  
	
	//byte_offset = phyaddr & 0x00000003;
	//phyaddr = phyaddr & 0xfffffffc;

	if (phyaddr<=RAM_UPPER_BOUND)
		{
			//RAM
			offset = phyaddr - RAM_LOWER_BOUND;
			*data  = ram[offset];
					
		}
	else if ((phyaddr>=CONSOLE_LOWER_ADDR)&&(phyaddr<=CONSOLE_UPPER_ADDR))
		{
			*data =console_load_byte();
		}
	else if ((phyaddr>=ROM_LOWER_BOUND) && ( phyaddr<=ROM_UPPER_BOUND))
		{
			//ROM
			offset = phyaddr - ROM_LOWER_BOUND;
			*data  =  rom[offset];
			
		}
	else
		{
			//bad address exception
			exception(ADEL,-1);
			return false;
		}
}
static boolean load_byte_from_cache(UINT32 vaddr,UINT32 phyaddr,int operation_mode,UINT8 * data)
{
	UINT32  index,word_vaddr;
	/*because we just fetch byte form cache. So we must get the offset of cache line.*/
	UINT8 cache_line_offset;  
	
	
	cache_line_offset = vaddr & 0x00000003;
	/*set the  last 2 bits to zero*/
	word_vaddr = vaddr & 0xfffffffc;
	//vaddr = vaddr & 0xfffffffc;
	
	if (true==is_swc())
		{
			if (DATA_LOAD==operation_mode  )
				{
					operation_mode = INSTRUCTION_LOAD;
				}
			else if (INSTRUCTION_LOAD == operation_mode  )
				operation_mode = DATA_LOAD;
		}
	
	if (DATA_LOAD==operation_mode)
		{
			index = (phyaddr & DCACHE_MASK) ;
			if ( (true==is_isc()) || (  (dcache[index].tag == word_vaddr) && (dcache[index].flag & CACHE_VALID_MASK) ))
				{
					//hit
					*data = get_byte_from_word(dcache[index].cache_line,cache_line_offset);
					return true;
				}
			else
				{
					//miss
				
					return false;
				}
		}
	else if (INSTRUCTION_LOAD==operation_mode)
		{
			index = phyaddr & ICACHE_MASK;
			if ((true==is_isc())||( (icache[index].tag == word_vaddr) && (icache[index].flag & CACHE_VALID_MASK) ))
				{
					//hit
					*data = get_byte_from_word(icache[index].cache_line,cache_line_offset);
					return true;
				}
			else
				{
					return false;
					
				}
		}

}
static boolean load_byte(UINT32 vaddr,UINT32 phyaddr,boolean cache_able,int operation_mode,UINT8 * data)
{
	if (true == cache_able )
		{
			//load a byte from cache.
			if (load_byte_from_cache(vaddr, phyaddr,operation_mode, data))
				return true;
		}
		/*now, cache miss or cache_able=false ,load from ram*/
		{
			//load a byte from ram

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -