public ControlUnitImpl(boolean pipeliningMode, MemoryBufferRegister mbr, BusController systemBus) {
		this.pipeliningMode = pipeliningMode;
		
		this.systemBus = systemBus;
		
		this.mbr = mbr;
		mar = new MAR();
		genRegisters = new RegisterFile16();
		pc = new PC();
		rCC = new ConditionCodeRegister();
		
		if (!pipeliningMode) { //If not pipelined, create standard stages
			ir = new IR();

			fetchDecodeStage = new StandardFetchDecodeStage(this.systemBus, ir, pc, genRegisters, rCC, this.mbr, mar);
			writeBackStage = new StandardWriteBackStage(this.systemBus, ir, pc, genRegisters, rCC, this.mbr, mar);
			executeStage = new StandardExecuteStage(this.systemBus, ir, pc, genRegisters, rCC,
					this.mbr, mar, writeBackStage);	
		}
		
		if (pipeliningMode) { 
			ir = new IRfile();
			
			//Queues only required if pipelining is enabled; they are used to coordinate the stages by making each 
			//stage wait until it receives the instruction from the previous stage before executing. This also
			//allows instructions to be passed from one index of the IRfile to the next in a controlled manner.
			fetchToExecuteQueue = new SynchronousQueue<Instruction>();
			executeToWriteQueue = new SynchronousQueue<Instruction>();
			
			fetchDecodeStage = new PipelinedFetchDecodeStage(this.systemBus, ir, pc, genRegisters, rCC,
					this.mbr, mar, fetchToExecuteQueue);
			
			writeBackStage = new PipelinedWriteBackStage(this.systemBus, ir, pc, genRegisters, rCC,
					this.mbr, mar, executeToWriteQueue);
			
			executeStage = new PipelinedExecuteStage(this.systemBus, ir, pc, genRegisters, rCC,
					this.mbr, mar, fetchToExecuteQueue, executeToWriteQueue, fetchDecodeStage, writeBackStage);
			
		}
		
	}