diff --git a/os-simulator/src/main/java/com/com1032/assignment/CPUSimulator.java b/os-simulator/src/main/java/com/com1032/assignment/CPUSimulator.java
new file mode 100644
index 0000000000000000000000000000000000000000..42cbcedde65dd980bee2606e4a679a725348faea
--- /dev/null
+++ b/os-simulator/src/main/java/com/com1032/assignment/CPUSimulator.java
@@ -0,0 +1,194 @@
+/**
+ * 
+ */
+package com.com1032.assignment;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author felipedabrantes
+ *
+ */
+public class CPUSimulator extends Thread{
+	/**Processes running on CPU.*/
+	private List<PCB> cpuQueue = new ArrayList<PCB> ();
+	
+	/**The global time of the system.*/
+	private Clock globalTime = null;
+	
+	/**The hardware to use.*/
+	private Hardware hardware = null;
+
+	
+	/**
+	 * Constructor. Initialises fields.
+	 * 
+	 * @param os
+	 * @param cpuQueue
+	 */
+	public CPUSimulator(Clock globalTime, List<PCB> cpuQueue, Hardware hardware) {
+		this.cpuQueue = cpuQueue;	
+		this.globalTime = globalTime;
+		this.hardware = hardware;
+	}
+	
+	
+	@Override
+	public void run() {
+		while(true) {
+			
+			//Temporarily stop executing for however milliseconds.
+			try {
+				Thread.sleep(50);
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			}
+			
+			//Runs process in queue.
+			this.runCode();
+		}
+	}
+	
+	public void runCode() {
+		if(!this.cpuQueue.isEmpty()) {
+			
+			if(this.cpuQueue.get(0).getState() == ProcessState.RUNNING) {
+				//The process the CPU runs.
+				PCB processRunning = this.cpuQueue.get(0);
+				
+				//Split code string into lines.
+				String[] codeLines = processRunning.getCode().split("\\r\\n|\\r|\\n");
+				
+				//Increase program counter by one to run next line.
+				processRunning.increaseProgramCounter();
+				
+				//Compile and run the program counter line.
+				this.compileLine(processRunning, codeLines[processRunning.getProgramCounter()]);
+				
+				//If not blocked, then decrease remaining time and global time by one.
+				if(processRunning.getState() != ProcessState.BLOCKED) {
+					processRunning.increaseConsecutiveTimeOnCPU();
+					processRunning.decreaseRemainingTime(1);
+					
+					//Instruction takes 4 ticks. Each core in processor decreases it by 1.
+					this.globalTime.increaseTime(5 - this.hardware.getCoresPerProcessor());
+					
+					//If all code finished, then terminate process.
+					if(processRunning.getProgramCounter() == codeLines.length - 1) {
+						processRunning.setState(ProcessState.TERMINATED);
+					}
+				}
+			}
+		}
+	}
+	
+	
+	public void compileLine(PCB processRunning, String line) {
+		
+		try {
+		
+			Map<String, Integer> variables = processRunning.getVariables();
+			
+			if(line.equals("")) {
+				return;
+			}
+	
+			String command = line.split(" ")[0];
+			
+			//STORE NAME VALUE
+			if(command.toLowerCase().equals("store")) {
+				String newVariableName = line.split(" ")[1];
+				Integer newVariableValue = 0;
+				
+				if(line.split(" ")[2].startsWith("#")) {
+					newVariableValue = Integer.valueOf(line.split(" ")[2].substring(1));
+				}
+				else {
+					Integer storedVariableValue = variables.get(line.split(" ")[2]);
+					newVariableValue = storedVariableValue;
+				}
+				
+				//Store result to new variable.
+				variables.put(newVariableName, newVariableValue);
+			
+			}
+			
+			//ADD NAME VALUE1 VALUE2
+			else if(command.toLowerCase().equals("add")) {
+				String newVariableName = line.split(" ")[1];
+				Integer newVariableValue = 0;
+				
+				//Find VALUE1.
+				if(line.split(" ")[2].startsWith("#")) {
+					newVariableValue = Integer.valueOf(line.split(" ")[2].substring(1));
+				}
+				else {
+					Integer storedVariableValue = variables.get(line.split(" ")[2]);
+					newVariableValue = storedVariableValue;
+				}
+				
+				//Add VALUE2 to VALUE1.
+				if(line.split(" ")[3].startsWith("#")) {
+					newVariableValue += Integer.valueOf(line.split(" ")[3].substring(1));
+				}
+				else {
+					Integer storedVariableValue = variables.get(line.split(" ")[3]);
+					newVariableValue += storedVariableValue;
+				}
+				
+				//Store result to new variable.
+				variables.put(newVariableName, newVariableValue);
+			}
+			
+			
+			//SUB NAME VALUE1 VALUE2
+			else if(command.toLowerCase().equals("sub")) {
+				String newVariableName = line.split(" ")[1];
+				Integer newVariableValue = 0;
+				
+				//Find VALUE1.
+				if(line.split(" ")[2].startsWith("#")) {
+					newVariableValue = Integer.valueOf(line.split(" ")[2].substring(1));
+				}
+				else {
+					Integer storedVariableValue = variables.get(line.split(" ")[2]);
+					newVariableValue = storedVariableValue;
+				}
+				
+				//Subtract VALUE1 from VALUE2.
+				if(line.split(" ")[3].startsWith("#")) {
+					newVariableValue -= Integer.valueOf(line.split(" ")[3].substring(1));
+				}
+				else {
+					Integer storedVariableValue = variables.get(line.split(" ")[3]);
+					newVariableValue -= storedVariableValue;
+				}
+				
+				//Store result to new variable.
+				variables.put(newVariableName, newVariableValue);
+			}
+			
+			
+			//PRINT VALUE
+			else if(command.toLowerCase().equals("print")) {
+				processRunning.setState(ProcessState.BLOCKED);
+			}
+		}
+		
+		catch(IndexOutOfBoundsException e) {
+			StringBuffer errorMessage = new StringBuffer();
+			errorMessage.append("Error in Line ");
+			errorMessage.append(processRunning.getProgramCounter());
+			errorMessage.append(": ");
+			errorMessage.append(processRunning);
+			processRunning.setFailed(true);
+			processRunning.setState(ProcessState.TERMINATED);
+			
+			System.out.println(errorMessage);
+		}
+		
+	}
+	
+}
diff --git a/os-simulator/src/main/java/com/com1032/assignment/Hardware.java b/os-simulator/src/main/java/com/com1032/assignment/Hardware.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed11cdb69c8d151bc7f08fd4846daad5a0c35b39
--- /dev/null
+++ b/os-simulator/src/main/java/com/com1032/assignment/Hardware.java
@@ -0,0 +1,94 @@
+/**
+ * 
+ */
+package com.com1032.assignment;
+
+import java.io.File;
+import java.util.Scanner;
+
+/**
+ * @author felipedabrantes
+ *
+ */
+public class Hardware {
+	
+	private int processorNum = 0;
+	private int coresPerProcessor = 0;
+	private int RAMSize = 0;
+	private int diskSize = 0;
+	
+	
+	/**
+	 * Constructor. Initialises fields.
+	 * 
+	 * @param processorNum
+	 * @param coresPerProcessor
+	 * @param RAMSize
+	 * @param diskSize
+	 */
+	public Hardware(int processorNum, int coresPerProcessor, int RAMSize, int diskSize) {
+		this.processorNum = processorNum;
+		this.coresPerProcessor = coresPerProcessor;
+		this.RAMSize = RAMSize;
+		this.diskSize = diskSize;
+	}
+	
+	
+	/**
+	 * Constructor. Initialises fields using a text file.
+	 * 
+	 * @param fileName
+	 */
+	public Hardware() {
+		try {
+			
+			File file = new File("hardware.txt");
+			Scanner fileReader = new Scanner(file);
+			
+			this.processorNum = Integer.valueOf(fileReader.nextLine());
+			this.coresPerProcessor = Integer.valueOf(fileReader.nextLine());
+			this.RAMSize = Integer.valueOf(fileReader.nextLine());
+			this.diskSize = Integer.valueOf(fileReader.nextLine());
+			
+			//Closes file.
+			fileReader.close();
+		}
+		
+		catch(Exception e) {
+			System.out.println("Error with Hardware file.");
+		}
+	
+	}
+
+	
+	/**
+	 * @return the processorNum
+	 */
+	public int getProcessorNum() {
+		return this.processorNum;
+	}
+
+	/**
+	 * @return the coresPerProcessor
+	 */
+	public int getCoresPerProcessor() {
+		return this.coresPerProcessor;
+	}
+
+	/**
+	 * @return the rAMSize
+	 */
+	public int getRAMSize() {
+		return this.RAMSize;
+	}
+
+	/**
+	 * @return the diskSize
+	 */
+	public int getDiskSize() {
+		return this.diskSize;
+	}
+	
+	
+	
+}
diff --git a/os-simulator/src/main/java/com/com1032/assignment/IOManager.java b/os-simulator/src/main/java/com/com1032/assignment/IOManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..b2dd8884e343a67f536550feb662d30a9f14b7c4
--- /dev/null
+++ b/os-simulator/src/main/java/com/com1032/assignment/IOManager.java
@@ -0,0 +1,123 @@
+/**
+ * 
+ */
+package com.com1032.assignment;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author felipedabrantes
+ *
+ */
+public class IOManager extends Thread {
+
+	/**Processes waiting for I/O.*/
+	private List<PCB> blockedQueue = new ArrayList<PCB> ();
+	
+	
+	/**
+	 * Constructor. Initialises fields.
+	 * 
+	 * @param globalTime
+	 * @param cores
+	 * @param readyQueue
+	 * @param blockedQueue
+	 * @param terminatedQueue
+	 */
+	public IOManager(List<PCB> blockedQueue) {
+		this.blockedQueue = blockedQueue;
+	}
+	
+	
+	@Override
+	public void run() {
+		
+		while(true) {
+			try {
+				Thread.sleep(50);
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			}
+			
+			this.runBlockedProcess();
+		}
+	}
+	
+	
+	public void runBlockedProcess() {
+//		System.out.println("IO B: " + this.blockedQueue);
+//		System.out.println("CP" + this.blockedQueue.size());
+		if(!this.blockedQueue.isEmpty()) {
+			
+			if(this.blockedQueue.get(0).getState() == ProcessState.BLOCKED) {
+				//The process the CPU runs.
+				PCB processRunning = this.blockedQueue.get(0);
+				
+				//Split code string into lines.
+				String[] codeLines = processRunning.getCode().split("\\r\\n|\\r|\\n");
+				
+				//Compile and run the program counter line.
+				this.compileLine(processRunning, codeLines[processRunning.getProgramCounter()]);
+				//Decrease expected remaining time.
+				processRunning.decreaseRemainingTime(1);
+				
+				//Reset time used on CPU.
+				processRunning.resetConsecutiveTimeOnCPU();
+				
+				//If all code finished, then terminate process.
+				if(processRunning.getProgramCounter() == codeLines.length - 1) {
+					processRunning.setState(ProcessState.TERMINATED);
+				}
+				else {
+					processRunning.increaseProgramCounter();
+					processRunning.setState(ProcessState.READY);
+				}
+			}
+		}
+	}
+	
+	
+	public void compileLine(PCB processRunning, String line) {
+		
+		try {
+			Map<String, Integer> variables = processRunning.getVariables();
+			
+			String command = line.split(" ")[0];
+			
+			//PRINT VALUE
+			if(command.toLowerCase().equals("print")) {
+				Integer variableValue = null;
+				
+				if(line.split(" ")[1].startsWith("#")) {
+					variableValue = Integer.valueOf(line.split(" ")[1].substring(1));
+				}
+				else {
+					Integer storedVariableValue = variables.get(line.split(" ")[1]);
+					variableValue = storedVariableValue;
+				}
+				
+				this.print(variableValue);
+			}
+		}
+		
+		catch(Exception e) {
+			StringBuffer errorMessage = new StringBuffer();
+			errorMessage.append("Error in Line ");
+			errorMessage.append(processRunning.getProgramCounter());
+			errorMessage.append(": ");
+			errorMessage.append(processRunning);
+			processRunning.setFailed(true);
+			processRunning.setState(ProcessState.TERMINATED);
+			
+			System.out.println(errorMessage);
+		}
+	}
+	
+	
+	public void print(int value) {
+		System.out.println(value);
+	}
+
+}
diff --git a/os-simulator/src/main/java/com/com1032/pss/OSSim.java b/os-simulator/src/main/java/com/com1032/pss/OSSim.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f0b70740141938a9e6f6dac2ed8a1eefceca25f
--- /dev/null
+++ b/os-simulator/src/main/java/com/com1032/pss/OSSim.java
@@ -0,0 +1,108 @@
+package com.com1032.pss;
+/**
+ * OS.java
+ */
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+import com.com1032.assignment.Clock;
+import com.com1032.assignment.SchedulingAlgorithm;
+import com.com1032.pss.Process;
+import com.com1032.pss.ProcessSchedulerSimulator;
+
+/**
+ * @author felipedabrantes
+ *
+ */
+public class OSSim {
+
+	/**The global time of the OS.*/
+	private Clock globalTime = new Clock();
+	/**The class the handles the process scheduling.*/
+	private ProcessSchedulerSimulator pss = null;
+	/**A list of processes of the OS.*/
+	private List<Process> processes = new ArrayList<Process>();
+
+	
+	/**
+	 * Constructor. Initialises fields.
+	 */
+	public OSSim() {
+		
+		this.pss = new ProcessSchedulerSimulator(this.globalTime);
+	}
+
+	/**
+	 * @param args
+	 * @throws FileNotFoundException
+	 * @throws IOException
+	 */
+	public static void main(String[] args) throws FileNotFoundException {
+		OSSim os = new OSSim();
+
+		os.addProcess("OSInput.txt");
+		os.runProcessScheduling();
+
+	}
+
+	
+	/**
+	 * Used to a single process to OS.
+	 * @param process
+	 */
+	public void addProcess(Process process) {
+		this.processes.add(process);
+	}
+	
+	
+	/**
+	 * Used to add processes from a file to the OS.
+	 * 
+	 * @param fileName of the processes file.
+	 * 
+	 * @throws FileNotFoundException if no file is found.
+	 */
+	public void addProcess(String fileName){
+		//Tries to open file.
+		try {
+			File file = new File(fileName);
+			Scanner fileReader = new Scanner(file);
+			
+			//Reads file line by line.
+			while (fileReader.hasNextLine()) {
+				//Splits process info to make a process object.
+				String[] data = fileReader.nextLine().split(", ");
+				this.processes.add(new Process(
+						Integer.valueOf(data[0]), 
+						data[1], 
+						Integer.valueOf(data[4]), 
+						Integer.valueOf(data[3]), 
+						Integer.valueOf(data[2])));
+			}
+			
+			//Closes file.
+			fileReader.close();
+		}
+		//Ran if no file is found.
+		catch(FileNotFoundException e) {
+			System.out.println("File not found.");
+		}
+
+	}
+
+	
+	/**
+	 * Runs process scheduling simulation with processes in OS.
+	 */
+	public void runProcessScheduling() {
+		pss.addProcessToJob(this.processes);
+		pss.run(SchedulingAlgorithm.SPF, 3);
+		System.out.println(pss.getReport());
+	}
+
+}
\ No newline at end of file