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

📄 mmu.cpp

📁 浙江大学的悟空嵌入式系统模拟器
💻 CPP
字号:
#include "MMU.h"
#include "Exception.h"
#include "Core/System.h"
#include "Register.h"
#include "Reg_Flag.h"
#include "Reg_Utils.h"
#include "Core/System.h"
#include "Core/Board.h"
#include "Utils/Logger.h"

#define ACTUAL_SIZE 66

namespace PPC
{
	TLB::Entry TLB::entrys_[ACTUAL_SIZE] =
	{
		{0xf0000000|TLB_VALID|SZ_256M, 0, 0xf0000000,  AC_R|AC_W|AC_X|SA_G|SA_I},
		{CFG_PERIPHERAL_BASE|TLB_VALID|SZ_256M,0, 0x40000000,  AC_R|AC_W|SA_G|SA_I},
		{CFG_ISRAM_BASE|TLB_VALID|SZ_4K, 0,0x80000000,  AC_R|AC_W|AC_X },
		{(CFG_ISRAM_BASE + 0x1000)| TLB_VALID|SZ_4K, 0,0x80001000,  AC_R|AC_W|AC_X},
		{CFG_SDRAM_BASE|TLB_VALID| SZ_256M, 0,0x00000000,  AC_R|AC_W|AC_X|SA_G|SA_I},
	};

	TLB::TLB(size_t size)
	{
		size_ = size;
		reset();
	}

	void TLB::reset()
	{
		// Fix me!
		entrys_[64].ws0 = 0xfdffd000 | TLB_VALID | TS_SET | SZ_4K ;
		entrys_[64].ws0_TID = 0;
		entrys_[64].ws1 =  0x40000000;
		entrys_[64].ws2 = AC_R|AC_W|SA_G|SA_I;

		entrys_[65].ws0 = 0xfdfff000 | TLB_VALID | TS_SET | SZ_4K;
		entrys_[65].ws0_TID = 0;
		entrys_[65].ws1 = 0x48001000;
		entrys_[65].ws2 = AC_R|AC_W|SA_G|SA_I;
	}

	TLB::Entry * TLB::search(Core::u32 as, Core::u32 pid, Core::u32 ea, size_t * index)
	{

		for( size_t i = 0; i < ACTUAL_SIZE; ++i)
		{
			Core::u32 SIZE =get_SIZE(entrys_[i]);
			Core::u32 V = get_V(entrys_[i]) ;
			Core::u32 TS = get_TS(entrys_[i]);
			Core::u32 EPN = get_EPN(entrys_[i]);

			Core::u32 mask = 0xFFFFFFFF << ( 10 + get_SIZE(entrys_[i]) * 2);
			bool b;
			b = ( TS == as );
			b = ( entrys_[i].ws0_TID == pid);
			b = (( EPN & mask) == (ea & mask)); 
		   
			if( get_V(entrys_[i]) 
				&& get_TS(entrys_[i]) == as 
				&& ( entrys_[i].ws0_TID == 0 || entrys_[i].ws0_TID != 0 && entrys_[i].ws0_TID == pid)
				&& (get_EPN(entrys_[i]) & mask) == (ea & mask) )
			{
				*index = i;
				return &entrys_[i];
			}
		}	
		return NULL;
	}
	
	TLB::Entry & TLB::get_entry(size_t index)
	{
		assert(index < size_);
		return entrys_[index];
	}

	MMU::MMU()
	{
		utlb_ = new TLB(64);		
	}


	MMU::~MMU()
	{
		delete utlb_;
	}

	TLB & MMU::get_utlb()
	{
		return *utlb_;
	}

	Core::Memory_Result MMU::access(Core::Memory_Access_Type type, 
			Core::u32 start, size_t size, Core::Bytecode_Type & buffer)
	{
		Core::u32 as;
		if( type == DATA_READ || type == DATA_WRITE )
			as = REG_BIT_IS_SET(MSR, Reg_Flag::MSR_DS) ? 1 : 0;
		else if(type = INSTR_READ)
			as = REG_BIT_IS_SET(MSR, Reg_Flag::MSR_IS) ? 1 : 0;
		else
			assert(0); 
		
		PPC_u32 pid = REG_TO_INT(REG(PID)) & 0x000000ff;
		size_t index;
		TLB::Entry * entry = utlb_->search(as, pid, start, &index);
		if( entry )
		{
			switch( type )
			{
			case INSTR_READ:
				if( REG_BIT_IS_SET(MSR, Reg_Flag::MSR_PR) && TLB::get_UX(*entry) == 0
					|| ! REG_BIT_IS_SET(MSR, Reg_Flag::MSR_PR) && TLB::get_SX(*entry) == 0)
				{
					//an Execute Access Control exception type Instruction Storage interrupt is taken.
					Exception_Mgr::instance()->handle(Exception::EXC_ISI);
					return ACCESS_FAULT;
				}
				break;
			case DATA_READ:
				if( REG_BIT_IS_SET(MSR, Reg_Flag::MSR_PR) && TLB::get_UW(*entry) == 0
					|| !REG_BIT_IS_SET(MSR, Reg_Flag::MSR_PR) && TLB::get_SW(*entry) == 0)
				{
					//an Write Access Control exception type Data Storage interrupt is taken.
					Exception_Mgr::instance()->handle(Exception::EXC_DSI);		
					return ACCESS_FAULT;
				}
				break;
			case DATA_WRITE:
				if( REG_BIT_IS_SET(MSR, Reg_Flag::MSR_PR) && TLB::get_UR(*entry) == 0
					|| !REG_BIT_IS_SET(MSR, Reg_Flag::MSR_PR) && TLB::get_SR(*entry) == 0)
				{
					//an Read Access Control exception type Data Storage interrupt is taken.
					Exception_Mgr::instance()->handle(Exception::EXC_DSI);	
					return ACCESS_FAULT;
				}
				break;
			}

			
		}
		else
		{
			if( type == DATA_READ || type == DATA_WRITE )
				Exception_Mgr::instance()->handle(Exception::EXC_DATA_TLB);// data tlb exc
			else if(type = INSTR_READ)
				Exception_Mgr::instance()->handle(Exception::EXC_INSTR_TLB);// instr tlb exc

			return ACCESS_FAULT;
		}
		
		// assume 32bit real address , the ERPN domain of tlb entry is 0000
		Core::u32 mask = 0xFFFFFFFF  << ( 10 + TLB::get_SIZE(*entry) * 2);
		Core::u32 ra =( TLB::get_RPN(*entry) & mask ) | ( start & ~mask );
		
		PPC_TRACE_2("physical addr: ", (Core::u32 *)ra, "\n");
	
		Core::Memory<Core::u32> * mem = (Core::Memory<Core::u32> *)Core::Wukong_Get_System().get_memory(ra);
		
		assert(mem);

		if (mem->is_mapped())
		{
			Core::Board<Core::u32> * board = (Core::Board<Core::u32> *)(Core::Wukong_Get_System().get_board());
			assert(board);
			Core::Memory_Result io_result = board->io_dispatch(type, ra, size, buffer);
			if(io_result == IO_RW)
			{
				Core::u32 value = 0;
				Core::Wukong_Get_System().convert_to_bytecode(value, buffer);
			}
		}

		if(!mem->test_fit(ra) || !mem->test_fit(ra + (Core::u32)size - 1))
		return ACCESS_FAULT;

		if(type == Core::Memory<Core::u32>::MEMORY_WRITE && mem->is_readonly())
			return ACCESS_FAULT;


		if( type == DATA_READ || type == INSTR_READ)
			mem->unchecked_access(Core::Memory_32Bit::MEMORY_READ, ra, size, buffer);
		else
			mem->unchecked_access(Core::Memory_32Bit::MEMORY_WRITE, ra, size, buffer);
		return ACCESS_SUCCESSFUL;

	}
	
} // namespace PPC

⌨️ 快捷键说明

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