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

📄 processor.java

📁 nachos操作系统框架
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
// PART OF THE MACHINE SIMULATION. DO NOT CHANGE.package nachos.machine;import nachos.security.*;/** * The <tt>Processor</tt> class simulates a MIPS processor that supports a * subset of the R3000 instruction set. Specifically, the processor lacks all * coprocessor support, and can only execute in user mode. Address translation * information is accessed via the API. The API also allows a kernel to set an * exception handler to be called on any user mode exception. * * <p> * The <tt>Processor</tt> API is re-entrant, so a single simulated processor * can be shared by multiple user threads. * * <p> * An instance of a <tt>Processor</tt> also includes pages of physical memory * accessible to user programs, the size of which is fixed by the constructor. */public final class Processor {    /**     * Allocate a new MIPS processor, with the specified amount of memory.     *     * @param	privilege      	encapsulates privileged access to the Nachos     *				machine.     * @param	numPhysPages	the number of pages of physical memory to     *				attach.     */    public Processor(Privilege privilege, int numPhysPages) {	System.out.print(" processor");	this.privilege = privilege;	privilege.processor = new ProcessorPrivilege();	Class clsKernel = Lib.loadClass(Config.getString("Kernel.kernel"));	Class clsVMKernel = Lib.tryLoadClass("nachos.vm.VMKernel");	usingTLB =	    (clsVMKernel != null && clsVMKernel.isAssignableFrom(clsKernel));		this.numPhysPages = numPhysPages;	for (int i=0; i<numUserRegisters; i++)	    registers[i] = 0;	mainMemory = new byte[pageSize * numPhysPages];	if (usingTLB) {	    translations = new TranslationEntry[tlbSize];	    for (int i=0; i<tlbSize; i++)		translations[i] = new TranslationEntry();	}	else {	    translations = null;	}    }    /**     * Set the exception handler, called whenever a user exception occurs.     *     * <p>     * When the exception handler is called, interrupts will be enabled, and     * the CPU cause register will specify the cause of the exception (see the     * <tt>exception<i>*</i></tt> constants).     *     * @param	exceptionHandler	the kernel exception handler.     */    public void setExceptionHandler(Runnable exceptionHandler) {	this.exceptionHandler = exceptionHandler;    }    /**     * Get the exception handler, set by the last call to     * <tt>setExceptionHandler()</tt>.     *     * @return	the exception handler.     */    public Runnable getExceptionHandler() {	return exceptionHandler;    }        /**     * Start executing instructions at the current PC. Never returns.     */    public void run() {	Lib.debug(dbgProcessor, "starting program in current thread");	registers[regNextPC] = registers[regPC] + 4;	Machine.autoGrader().runProcessor(privilege);	Instruction inst = new Instruction();		while (true) {	    try {		inst.run();	    }	    catch (MipsException e) {		e.handle();	    }	    privilege.interrupt.tick(false);	}    }    /**     * Read and return the contents of the specified CPU register.     *     * @param	number	the register to read.     * @return	the value of the register.     */    public int readRegister(int number) {	Lib.assert(number >= 0 && number < numUserRegisters);		return registers[number];    }    /**     * Write the specified value into the specified CPU register.     *     * @param	number	the register to write.     * @param	value	the value to write.     */    public void writeRegister(int number, int value) {	Lib.assert(number >= 0 && number < numUserRegisters);	if (number != 0)	    registers[number] = value;    }    /**     * Test whether this processor uses a software-managed TLB, or single-level     * paging.     *     * <p>     * If <tt>false</tt>, this processor directly supports single-level paging;     * use <tt>setPageTable()</tt>.     *     * <p>     * If <tt>true</tt>, this processor has a software-managed TLB;     * use <tt>getTLBSize()</tt>, <tt>readTLBEntry()</tt>, and     * <tt>writeTLBEntry()</tt>.     *     * <p>     * Using a method associated with the wrong address translation mechanism     * will result in an assertion failure.     *     * @return	<tt>true</tt> if this processor has a software-managed TLB.     */    public boolean hasTLB() {	return usingTLB;    }    /**     * Get the current page table, set by the last call to setPageTable().     *     * @return	the current page table.     */    public TranslationEntry[] getPageTable() {	Lib.assert(!usingTLB);	return translations;    }    /**     * Set the page table pointer. All further address translations will use     * the specified page table. The size of the current address space will be     * determined from the length of the page table array.     *     * @param	pageTable	the page table to use.     */    public void setPageTable(TranslationEntry[] pageTable) {	Lib.assert(!usingTLB);	this.translations = pageTable;    }    /**     * Return the number of entries in this processor's TLB.     *     * @return	the number of entries in this processor's TLB.     */    public int getTLBSize() {	Lib.assert(usingTLB);    	return tlbSize;    }    /**     * Returns the specified TLB entry.     *     * @param	number	the index into the TLB.     * @return	the contents of the specified TLB entry.     */    public TranslationEntry readTLBEntry(int number) {	Lib.assert(usingTLB);	Lib.assert(number >= 0 && number < tlbSize);	return new TranslationEntry(translations[number]);    }    /**     * Fill the specified TLB entry.     *     * <p>     * The TLB is fully associative, so the location of an entry within the TLB     * does not affect anything.     *     * @param	number	the index into the TLB.     * @param	entry	the new contents of the TLB entry.     */    public void writeTLBEntry(int number, TranslationEntry entry) {	Lib.assert(usingTLB);	Lib.assert(number >= 0 && number < tlbSize);	translations[number] = new TranslationEntry(entry);    }    /**     * Return the number of pages of physical memory attached to this simulated     * processor.     *     * @return	the number of pages of physical memory.     */    public int getNumPhysPages() {	return numPhysPages;    }    /**     * Return a reference to the physical memory array. The size of this array     * is <tt>pageSize * getNumPhysPages()</tt>.     *     * @return	the main memory array.     */    public byte[] getMemory() {	return mainMemory;    }    /**     * Concatenate a page number and an offset into an address.     *     * @param	page	the page number. Must be between <tt>0</tt> and     *			<tt>(2<sup>32</sup> / pageSize) - 1</tt>.     * @param	offset	the offset within the page. Must be between <tt>0</tt>     *			and     *			<tt>pageSize - 1</tt>.     * @return	a 32-bit address consisting of the specified page and offset.     */    public static int makeAddress(int page, int offset) {	Lib.assert(page >= 0 && page < maxPages);	Lib.assert(offset >= 0 && offset < pageSize);	return (page * pageSize) | offset;    }    /**     * Extract the page number component from a 32-bit address.     *     * @param	address	the 32-bit address.     * @return	the page number component of the address.     */    public static int pageFromAddress(int address) {	return (int) (((long) address & 0xFFFFFFFFL) / pageSize);    }    /**     * Extract the offset component from an address.     *     * @param	address	the 32-bit address.     * @return	the offset component of the address.     */    public static int offsetFromAddress(int address) {	return (int) (((long) address & 0xFFFFFFFFL) % pageSize);    }    private void finishLoad() {	delayedLoad(0, 0, 0);    }    /**     * Translate a virtual address into a physical address, using either a     * page table or a TLB. Check for alignment, make sure the virtual page is     * valid, make sure a read-only page is not being written, make sure the     * resulting physical page is valid, and then return the resulting physical     * address.     *     * @param	vaddr	the virtual address to translate.     * @param	size	the size of the memory reference (must be 1, 2, or 4).     * @param	writing	<tt>true</tt> if the memory reference is a write.     * @return		the physical address.     * @exception	MipsException	if a translation error occurred.     */    private int translate(int vaddr, int size, boolean writing)	throws MipsException {	if (Lib.test(dbgProcessor))	    System.out.println("\ttranslate vaddr=0x" + Lib.toHexString(vaddr)			       + (writing ? ", write" : ", read..."));	// check alignment	if ((vaddr & (size-1)) != 0) {	    Lib.debug(dbgProcessor, "\t\talignment error");	    throw new MipsException(exceptionAddressError, vaddr);	}	// calculate virtual page number and offset from the virtual address	int vpn = pageFromAddress(vaddr);	int offset = offsetFromAddress(vaddr);	TranslationEntry entry = null;	// if not using a TLB, then the vpn is an index into the table	if (!usingTLB) {	    if (translations == null || vpn >= translations.length ||		translations[vpn] == null ||		!translations[vpn].valid) {		privilege.stats.numPageFaults++;		Lib.debug(dbgProcessor, "\t\tpage fault");		throw new MipsException(exceptionPageFault, vaddr);	    }	    entry = translations[vpn];	}	// else, look through all TLB entries for matching vpn	else {	    for (int i=0; i<tlbSize; i++) {		if (translations[i].valid && translations[i].vpn == vpn) {		    entry = translations[i];		    break;		}	    }	    if (entry == null) {		privilege.stats.numTLBMisses++;		Lib.debug(dbgProcessor, "\t\tTLB miss");		throw new MipsException(exceptionTLBMiss, vaddr);	    }	}	// check if trying to write a read-only page	if (entry.readOnly && writing) {	    Lib.debug(dbgProcessor, "\t\tread-only exception");	    throw new MipsException(exceptionReadOnly, vaddr);	}	// check if physical page number is out of range	int ppn = entry.ppn;	if (ppn < 0 || ppn >= numPhysPages) {	    Lib.debug(dbgProcessor, "\t\tbad ppn");	    throw new MipsException(exceptionBusError, vaddr);	}	// set used and dirty bits as appropriate	entry.used = true;	if (writing)	    entry.dirty = true;	int paddr = (ppn*pageSize) + offset;	if (Lib.test(dbgProcessor))	    System.out.println("\t\tpaddr=0x" + Lib.toHexString(paddr));		return paddr;    }    /**     * Read </i>size</i> (1, 2, or 4) bytes of virtual memory at <i>vaddr</i>,     * and return the result.     *     * @param	vaddr	the virtual address to read from.     * @param	size	the number of bytes to read (1, 2, or 4).     * @return		the value read.     * @exception	MipsException	if a translation error occurred.     */    private int readMem(int vaddr, int size) throws MipsException {	if (Lib.test(dbgProcessor))	    System.out.println("\treadMem vaddr=0x" + Lib.toHexString(vaddr)			       + ", size=" + size);	Lib.assert(size==1 || size==2 || size==4);		int value = Lib.bytesToInt(mainMemory, translate(vaddr, size, false),				   size);	if (Lib.test(dbgProcessor))	    System.out.println("\t\tvalue read=0x" +			       Lib.toHexString(value, size*2));		return value;    }        /**     * Write <i>value</i> to </i>size</i> (1, 2, or 4) bytes of virtual memory     * starting at <i>vaddr</i>.     *     * @param	vaddr	the virtual address to write to.     * @param	size	the number of bytes to write (1, 2, or 4).     * @param	value	the value to store.     * @exception	MipsException	if a translation error occurred.     */    private void writeMem(int vaddr, int size, int value)	throws MipsException {	if (Lib.test(dbgProcessor))	    System.out.println("\twriteMem vaddr=0x" + Lib.toHexString(vaddr)			       + ", size=" + size + ", value=0x"			       + Lib.toHexString(value, size*2));	Lib.assert(size==1 || size==2 || size==4);		Lib.bytesFromInt(mainMemory, translate(vaddr, size, true), size,			 value);    }    /**     * Complete the in progress delayed load and scheduled a new one.     *     * @param	nextLoadTarget	the target register of the new load.     * @param	nextLoadValue	the value to be loaded into the new target.     * @param	nextLoadMask	the mask specifying which bits in the new     *				target are to be overwritten. If a bit in     *				<tt>nextLoadMask</tt> is 0, then the     *				corresponding bit of register     *				<tt>nextLoadTarget</tt> will not be written.     */    private void delayedLoad(int nextLoadTarget, int nextLoadValue,			     int nextLoadMask) {	// complete previous delayed load, if not modifying r0	if (loadTarget != 0) {	    int savedBits = registers[loadTarget] & ~loadMask;	    int newBits = loadValue & loadMask;	    registers[loadTarget] = savedBits | newBits;	}	// schedule next load	loadTarget = nextLoadTarget;	loadValue = nextLoadValue;	loadMask = nextLoadMask;    }    /**     * Advance the PC to the next instruction.     *

⌨️ 快捷键说明

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