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

📄 cpu.cpp

📁 浙江大学的悟空嵌入式系统模拟器
💻 CPP
字号:
/**
 *  Copyright (c) 2005 Zhejiang University, P.R.China
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */ 

//=============================================================================
/**
 *  \file    Processor/PPC/CPU.cpp
 *
 *  \author  Chenfeng Zhou <ini_autumn@163.com>
 *
 *  Created:     <2005-02-08 14:10:08 by Cheney Chow>
 *  Last update: <2005-02-09 20:51:10 by Cheney Chow>
 *
 *  $Id: CPU.cpp,v 1.1 2005/06/16 06:01:44 qilj Exp $
 */
//=============================================================================

#include <iostream>
#include <cstdio>
#include <string>
#include "CPU.h"
#include "Utils/Logger.h"
#include "Utils/Debug.h"
#include "Register.h"
#include "Exception.h"
#include "Utils/Logger.h"
#include "Core/Log.h"
#include "Core/Helper.h"
#include "Core/ConfigFile.h"
#include "Reg_Flag.h"
#include "Reg_Utils.h"
#include "MMU.h"

namespace PPC {

	PPC_CPU::PPC_CPU (Core::Instruction_Set &instru_set, PPC_MMU *mmu)
        : Core::CPU_32Bit (instru_set, mmu)
        , reg_file_adaptor_ (reg_file_.get())
 
    {
#ifdef PPC_DEBUG
		if (PPC::Logger::instance()->init_logfile(Core::Host_Machine::get_log_path() + "\\log.txt") < 0) {
			std::cout<<"open log error";
			exit(0);
		}
#endif
		init_cpu();
    }
    
    PPC_CPU::~PPC_CPU () {}

	void PPC_CPU::on_create()
	{}

    void PPC_CPU::run ()
    {

		if ( OS_LINUX == os_type () )
			switch_mmu();

		running_ = true;

		while (running_) {
			npc_ = pc_ + 4;

 			current_instr_ = fetch_instruction(pc_);

			//if (pc_ == 0xc000124c)
			//	Logger::instance()->enable_trace();

#if defined(UNIT_TEST)
			// if it's 'rfi', we exit; just for unit test;
			if (current_instr_ == 0x4c000064)
				return;
#endif

			if ( OS_UCOS == os_type() ) { 
				if (ucos_ee_handler()) {
					pc_ = npc_;
					continue;
				}
			}

			get_instr_set().execute_instruction (current_instr_);

			post_routine ();

			//For debug
			//DUMP_CPU_STATE;

			pc_ = npc_;
			// Todo: some exception jobs
			
		}
    }

	void PPC_CPU::post_routine ()
	{
		cpu_state_.ops++;
		cpu_state_.ptb++;

		
		if (OS_UCOS == os_type ()) {
			if (cpu_state_.pdec == 0) {
				cpu_state_.pdec = (Core::u64)0xf0;

				if (cpu_state_.enable_ee) {
				//if (REG_BIT_IS_SET(MSR, Reg_Flag::MSR_EE)) {
					Exception_Mgr::instance()->pend_exception(Exception::EXC_DEC);
				}
			}
			else
				cpu_state_.pdec--;

			//if (cpu_state_.enable_ee)
				Exception_Mgr::instance()->handle_pending_exception ();
		}
	}

    int PPC_CPU::init_cpu ()
    {
		init_reg_file ();

		/// loader set pc...
		/// no pc-initialization job need to be done when we use ELF_LOADER;

		init_cpu_state ();

        return PPC_SUCCESS;
    }

    int PPC_CPU::init_reg_file ()
    {
        reg_file_adaptor_.init();
		
		//! Register CPU as 440GP Rev. B
		//!
		//! Different CPU types don't have same time frequency
		//! even when they have same version number but different
		//! Reversion number;
		reg_file_adaptor_[PVR].convert_from_int(0x40000440); 

		return 0;
    }

	void PPC_CPU::init_cpu_state()
	{
		cpu_state_.ops = 0;

		cpu_state_.ptb = 0;
		cpu_state_.pdec = 0xf0;

		cpu_state_.enable_ee = false;

		cpu_state_.cpu_stop = false;

		Core::Config_File * cf = Core::Wukong_Get_System().get_config();
		PPC_ASSERT(cf);

		std::string cf_os;
		cf->read("/kernel/name", cf_os);
		
		cpu_state_.os = (cf_os == "UCOS")? OS_UCOS : OS_LINUX;
		
	}

    PPC_Instr_T PPC_CPU::fetch_instruction(PPC_Address_T pc)
    {
		Core::u32 res;
		Core::Bytecode_Type buffer;

		/**
		 * For Linux:
		 * If there's an instruction page fault, mmu raise an exception;
		 * npc is reset, and we then fetch the instruction at the begin of 
		 * corresponding exception_handler's code.
		 * 
		 * For Ucos:
		 * There's no mmu, so there's no page fault considered.
		 */

		Core::Memory_Access_Type read_type = (OS_UCOS == os_type())? 
												Core::Memory_32Bit::MEMORY_READ :
												MMU::INSTR_READ;

		if (MMU::ACCESS_FAULT == get_mmu().access(read_type,
												  (Core::u32)pc, 
												  4, buffer))
			get_mmu().access(MMU::INSTR_READ, (Core::u32)npc_, 4, buffer);

		Core::Wukong_Get_System().convert_from_bytecode(buffer, res);

		return (PPC_Instr_T)res;
    }
    
} // namespace PPC

⌨️ 快捷键说明

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