All pastes #1972113 Raw Edit

Pipe File

public java v1 · immutable
#1972113 ·published 2010-10-24 19:40 UTC
rendered paste body
/** * Assignment 3 part 2 * CL Leavitt, x2p4 * modified pipe cpu.java */package Arch.Y86.Machine.Pipe.Student;import Arch.Y86.Machine.AbstractY86CPU;import Arch.Y86.Machine.MainMemory;import Machine.AbstractMainMemory;import Machine.RegisterSet;import Machine.AbstractCPU.MachineHaltException;public class CPU extends AbstractY86CPU {	public CPU(MainMemory aMem) {		super("Pipe", aMem, true);	}	/**	 * Execute one clock cycle with all stages executing in parallel.	 * 	 * @throws InvalidInstructionException	 *             if instruction is invalid (including invalid register number)	 * @throws AbstractMainMemory.InvalidAddressException	 *             if instruction attempts an invalid memory access (either	 *             instruction or data)	 * @throws MachineHaltException	 *             if instruction halts the CPU	 */	@Override	protected void cycle() throws InvalidInstructionException,			AbstractMainMemory.InvalidAddressException, MachineHaltException {		cyclePipe();	}	/**	 * Pipeline Hazard Control Logic STUDENT IMPLEMENTS THIS METHOD	 */	@Override	protected void pipelineHazardControl() {				/**CONTROL HAZARD: Conditional Jump		 * 		 * IF JUMP SHOULD NOT HAVE BEEN TAKEN: Shoot down the 2 bad instructions 		 * */       	    			if ((m.iCd.read () == I_JXX && m.iFn.read() != J_NC && (m.bch.read()) == 0))     	{    	    e.clockTransition = BUBBLE;    	    m.clockTransition = BUBBLE;    	}					/** CONTROL HAZARD: Return */		if (d.iCd.read() == I_RET || e.iCd.read() == I_RET || m.iCd.read() == I_RET) 		{			f.clockTransition = STALL;			d.clockTransition = BUBBLE;		}				/** DATA HAZARDS - LOAD USE		 *  we don't stall on register-register (write-reads) hazard with this		 *  pipe implementation, data forwarding prevents needing it. Only Load use		 *  required.		 *		 * if I'm in e, and he is in d, stall him iff he needs me 		 **/						if (d.rA.read() == e.dstM.read() || d.rB.read() == e.dstM.read()) 			{				//3rd - add one more stall				f.clockTransition = STALL;				// 2nd - stall instruction at decode until memory results are in				d.clockTransition = STALL;				// 1st Stall - fill stall vacuum at execute with NOP				e.clockTransition = BUBBLE;			}		}		/**	 * The part of the FETCH that selects the PC of the instruction to fetch	 * Writes the selected PC into the f.pc register. STUDENT CHANGES THIS	 * METHOD TO CORRECT MIS-PREDICTED PCS	 */	@Override	protected void fetch_SelectPC() 	{		// pc MUX		int pc;		pc = f.prPC.read();				/** RETURN CONTROL: Forward the correct PC to Fetch*/		if(w.iCd.read() == I_RET)		{			pc = w.valM.read();		}				/** INSERT LOGIC TO CORRECT MIS-PREDICTED PC FROM JUMPS 		 * 		 * if I'm a jump, but not an unconditional one, check bch		 * and set the proper PC		 * */		if (m.iCd.read() == I_JXX)		{			if (m.iFn.read() != J_NC)			{				 if (m.bch.read() == 0)				 {						pc = m.valP.read();				 }			}		}						f.pc.write(pc);		}	/**	 * The part of the FETCH that predicts PC value of instruction to enter	 * fetch on next clock cycle. Writes the predicted PC into the f.prPC	 * register. STUDENT CHANGES THIS METHOD TO PREDICT THE PC	 */	private void fetch_PredictPC() 	{		// prPC MUX		switch (d.iCd.readInput()) {		case I_JXX:				/** 				 * We always want to jump.				 * So I could also just let this fall into case I_CALL 				 * if (d.iFn.readInput () == J_NC) 				 * 				 */				f.prPC.write(d.valC.readInput());			break;		case I_CALL:			f.prPC.write(d.valC.readInput());			break;		default:			f.prPC.write(d.valP.readInput());		}				/*//**********  RETURN PREDICT ******		if (m.iCd.read() == I_RET) 		{ *//** find out what's going into valM *//*			f.prPC.write(w.valM.readInput()); 		}*/	}	/**	 * The FETCH stage of CPU Reads the PC from the input port of the f.pc	 * register.	 * 	 * @throws InvalidInstructionException	 *             if instruction opcode or format is invalid	 * @throws AbstractMainMemory.InvalidAddressException	 *             if current pc is invalid	 */	@Override	protected void fetch() throws InvalidInstructionException,			AbstractMainMemory.InvalidAddressException {		// determine PC		fetch_SelectPC();		int pc = f.pc.readInput();		// get opcode		d.iCd.write(mem.read(pc, 1)[0].value() >>> 4);		d.iFn.write(mem.read(pc, 1)[0].value() & 0xf);		// rA MUX		switch (d.iCd.readInput()) {		case I_RRMOVL:		case I_RMMOVL:		case I_MRMOVL:		case I_OPL:		case I_PUSHL:		case I_POPL:			d.rA.write(mem.read(pc + 1, 1)[0].value() >>> 4);			break;		default:			d.rA.write(R_NONE);		}		// rB MUX		switch (d.iCd.readInput()) {		case I_RRMOVL:		case I_IRMOVL:		case I_RMMOVL:		case I_MRMOVL:		case I_OPL:			d.rB.write(mem.read(pc + 1, 1)[0].value() & 0xf);			break;		default:			d.rB.write(R_NONE);		}		// valC MUX		switch (d.iCd.readInput()) {		case I_IRMOVL:		case I_RMMOVL:		case I_MRMOVL:			d.valC.write(mem.readIntegerUnaligned(pc + 2));			break;		case I_JXX:		case I_CALL:			d.valC.write(mem.readIntegerUnaligned(pc + 1));			break;		default:			d.valC.write(0);		}		// valP MUX		switch (d.iCd.readInput()) {		case I_NOP:		case I_HALT:		case I_RET:			d.valP.write(pc + 1);			break;		case I_RRMOVL:		case I_OPL:		case I_PUSHL:		case I_POPL:			d.valP.write(pc + 2);			break;		case I_JXX:		case I_CALL:			d.valP.write(pc + 5);			break;		case I_IRMOVL:		case I_RMMOVL:		case I_MRMOVL:			d.valP.write(pc + 6);			break;		default:		}		// predict next PC		fetch_PredictPC();	}	/**	 * Determine current value of specified register by employing data	 * forwarding, where necessary. STUDENT CHANGES THIS METHOD TO IMPLEMENT	 * DATA FORWARDING	 * 	 * @param regNum	 *            number of register being read	 * @return value of register	 * @throws Machine.RegisterSet.InvalidRegisterNumberException	 *             if register number is invalid	 */	private int decode_ReadRegisterWithForwarding(int regNum)			throws Machine.RegisterSet.InvalidRegisterNumberException {		if (regNum == R_NONE) 		{			return 0;		}		/********************** EXECUTE STAGE CHECK **********************************/		/** is e writing **/		switch (e.iCd.read()) {		case I_OPL:		case I_IRMOVL:		case I_RRMOVL: // valE = 0 + valA		case I_PUSHL: // valE = valB + -4 written back to %esp		case I_RET: // write to %esp valE = valB + 4 and dstE is %esp		case I_CALL: // same as the above ones.			if (e.dstE.read() == regNum /* dstE is this register */) {				// read vale.readinput and give it to the register.				//reg.write(regNum, m.valE.readInput());								return m.valE.readInput();			}			break;		/**		 * 		 * case I_POPL: not needed here, it will get one bubble cause the		 * soonest we know is memory and no way to forward from here. case		 * I_MRMOVL: not needed here, since at execute there is no way to		 * forward from here.		 * **/		}				/********************** MEMORY STAGE CHECK **********************************/		switch (m.iCd.read()) {		case I_OPL:		case I_IRMOVL:		case I_RRMOVL: // valE = 0 + valA		case I_PUSHL: // valE = valB + -4 written back to %esp		case I_RET: // write to %esp valE = valB + 4 and dstE is %esp		case I_CALL: // same as the above ones.			if (m.dstE.read() == regNum /* dstE is this register */) 			{				// read vale.readinput and give it to the register.				return m.valE.read();			}			break;					/** SPECIAL CASE POPL WRITE-READ and DATA LOAD HAZARD **/		case I_POPL: // write to %esp valE = valB + 4 and dstE is %esp						// num of reg that gets arithmetic op reg			if (m.dstE.read() == regNum /* dste is this register */) 			{ 				// read vale.readinput and give it to the register.				reg.write(regNum, m.valE.read());			} else if (m.dstM.read() == regNum) {				return w.valM.readInput(); // what will this be next turn																	}			break;		case I_MRMOVL:			/** LOAD USE HAZARD **/			if (m.dstM.read() == regNum) {				return w.valM.readInput();			}			break;		}				/********************** WRITE BACK CHECK **********************************/		switch (w.iCd.read()) {		case I_OPL:		case I_IRMOVL:		case I_RRMOVL: // valE = 0 + valA		case I_PUSHL: // valE = valB + -4 written back to %esp		case I_RET: // write to %esp valE = valB + 4 and dstE is %esp		case I_CALL: // same as the above ones.			if (w.dstE.read() == regNum /* dstE is this register */) {				// read vale.readinput and give it to the register.				return w.valE.read();			}			break;		case I_POPL: // write to %esp valE = valB + 4 and dstE is %esp			/** SPECIAL CASE POPL WRITE-READ and DATA LOAD HAZARD **/			if (w.dstE.read() == regNum /* dstE is this register */) { 				// read vale.readinput and give it to the register.				return w.valE.read();			} else if (w.dstM.read() == regNum) {				return w.valM.read(); // read result of what write will be																}			break;		case I_MRMOVL:			/** LOAD USE HAZARD **/			if (w.dstM.read() == regNum) {				return w.valM.read();			}			break;		}		return reg.read(regNum); // this is outside so we actually use it.	}	/**	 * The DECODE stage of CPU	 * 	 * @throws RegisterSet.InvalidRegisterNumberException	 *             if instruction attempts to access register number > 7	 */	@Override	protected void decode() throws RegisterSet.InvalidRegisterNumberException {		// pass on from previous stages		e.iCd.write(d.iCd.read());		e.iFn.write(d.iFn.read());		e.valC.write(d.valC.read());		e.valP.write(d.valP.read());		// srcA MUX		switch (d.iCd.read()) {		case I_RRMOVL:		case I_RMMOVL:		case I_OPL:		case I_PUSHL:			e.srcA.write(d.rA.read());			break;		case I_RET:		case I_POPL:			e.srcA.write(R_ESP);			break;		default:			e.srcA.write(R_NONE);		}		// srcB MUX		switch (d.iCd.read()) {		case I_RRMOVL:		case I_RMMOVL:		case I_MRMOVL:		case I_OPL:			e.srcB.write(d.rB.read());			break;		case I_CALL:		case I_RET:		case I_PUSHL:		case I_POPL:			e.srcB.write(R_ESP);			break;		default:			e.srcB.write(R_NONE);		}		// dstE MUX		switch (d.iCd.read()) {		case I_RRMOVL:		case I_IRMOVL:		case I_OPL:			e.dstE.write(d.rB.read());			break;		case I_CALL:		case I_RET:		case I_PUSHL:		case I_POPL:			e.dstE.write(R_ESP);			break;		default:			e.dstE.write(R_NONE);		}		// dstM MUX		switch (d.iCd.read()) {		case I_MRMOVL:		case I_POPL:			e.dstM.write(d.rA.read());			break;		default:			e.dstM.write(R_NONE);		}		// read valA and valB from register file (with data forwarding)		e.valA.write(decode_ReadRegisterWithForwarding(e.srcA.readInput()));		e.valB.write(decode_ReadRegisterWithForwarding(e.srcB.readInput()));	}	/**	 * The EXECUTE stage of CPU	 */	@Override	protected void execute() {		// pass on from previous stages		m.iCd.write(e.iCd.read());		m.iFn.write(e.iFn.read());		m.valA.write(e.valA.read());		m.valP.write(e.valP.read());		m.dstE.write(e.dstE.read());		m.dstM.write(e.dstM.read());		m.valC.write(e.valC.read());		// aluA MUX		int aluA;		switch (e.iCd.read()) {		case I_RRMOVL:		case I_OPL:			aluA = e.valA.read();			break;		case I_IRMOVL:		case I_MRMOVL:		case I_RMMOVL:			aluA = e.valC.read();			break;		case I_RET:		case I_POPL:			aluA = 4;			break;		case I_CALL:		case I_PUSHL:			aluA = -4;			break;		default:			aluA = 0;		}		// aluB MUX		int aluB;		switch (e.iCd.read()) {		case I_RRMOVL:		case I_IRMOVL:			aluB = 0;			break;		case I_RMMOVL:		case I_MRMOVL:		case I_OPL:		case I_CALL:		case I_RET:		case I_PUSHL:		case I_POPL:			aluB = e.valB.read();			break;		default:			aluB = 0;		}		// aluFun and setCC muxes MUX		int aluFun;		boolean setCC;		switch (e.iCd.read()) {		case I_RRMOVL:		case I_IRMOVL:		case I_RMMOVL:		case I_MRMOVL:		case I_CALL:		case I_RET:		case I_PUSHL:		case I_POPL:			aluFun = A_ADDL;			setCC = false;			break;		case I_OPL:			aluFun = e.iFn.read();			setCC = true;			break;		default:			aluFun = 0;			setCC = false;		}		// the ALU		boolean overflow;		switch (aluFun) {		case A_ADDL:			m.valE.write(aluB + aluA);			overflow = ((aluB < 0) == (aluA < 0))					&& ((m.valE.readInput() < 0) != (aluB < 0));			break;		case A_SUBL:			m.valE.write(aluB - aluA);			overflow = ((aluB < 0) != (aluA < 0))					&& ((m.valE.readInput() < 0) != (aluB < 0));			break;		case A_ANDL:			m.valE.write(aluB & aluA);			overflow = false;			break;		case A_XORL:			m.valE.write(aluB ^ aluA);			overflow = false;			break;		default:			overflow = false;		}		// CC MUX		if (setCC)			p.cc.write(((m.valE.readInput() == 0) ? 0x100 : 0)					| ((m.valE.readInput() < 0) ? 0x10 : 0)					| (overflow ? 0x1 : 0));		else			p.cc.write(p.cc.read());		// bch MUX		boolean bch;		if (e.iCd.read() == I_JXX || e.iCd.read() == I_CMOV) {			boolean zf = (p.cc.read() & 0x100) != 0;			boolean sf = (p.cc.read() & 0x010) != 0;			boolean of = (p.cc.read() & 0x001) != 0;			switch (e.iFn.read()) {			case J_NC:				bch = true;				break;			case J_LE:				bch = (sf ^ of) | zf;				break;			case J_L:				bch = sf ^ of;				break;			case J_E:				bch = zf;				break;			case J_NE:				bch = !zf;				break;			case J_GE:				bch = !(sf ^ of);				break;			case J_G:				bch = !(sf ^ of) & !zf;				break;			default:				throw new AssertionError();			}		} else			bch = true;		m.bch.write(bch ? 1 : 0);	}	/**	 * The MEMORY stage of CPU	 * 	 * @throws AbstractMainMemory.InvalidAddressException	 *             if instruction attempts to access an invalid memory address	 */	@Override	protected void memory() throws AbstractMainMemory.InvalidAddressException {		// pass on from previous stages		w.iCd.write(m.iCd.read());		w.valE.write(m.valE.read());		w.valP.write(m.valP.read());		w.dstE.write(m.dstE.read());		w.dstM.write(m.dstM.read());		w.valC.write(m.valC.read());		w.bch.write(m.bch.readInput());		// write Main Memory		switch (m.iCd.read()) {		case I_RMMOVL:		case I_PUSHL:			mem.writeInteger(m.valE.read(), m.valA.read());			break;		case I_CALL:			mem.writeInteger(m.valE.read(), m.valP.read());			break;		default:		}		// valM MUX (read main memory)		switch (m.iCd.read()) {		case I_MRMOVL:			w.valM.write(mem.readInteger(m.valE.read()));			break;		case I_RET:		case I_POPL:			w.valM.write(mem.readInteger(m.valA.read()));			break;		default:		}	}	/**	 * The WRITE BACK stage of CPU	 * 	 * @throws MachineHaltException	 *             if instruction halts the CPU (e.g., halt instruction)	 * @throws RegisterSet.InvalidRegisterNumberException	 *             if instruction attempts to access register number > 7	 */	@Override	protected void writeBack() throws MachineHaltException,			RegisterSet.InvalidRegisterNumberException {		// write valE to register file		if (w.dstE.read () != R_NONE && w.bch.readInput () == 1)		    reg.write (w.dstE.read (), w.valE.read ());		// write valM to register file		if (w.dstM.read () != R_NONE)		    reg.write (w.dstM.read (), w.valM.read ());		// the HALT instruction		if (w.iCd.read () == I_HALT)		    throw new MachineHaltException ();	}}