/* CPU.java
*
* This class models a MIPS CPU with 32 64-bit General Purpose Register.
* (c) 2006 Andrea Spadaccini, Simona Ullo, Antonella Scandura, Massimo Trubia (FPU modifications)
*
* This file is part of the EduMIPS64 project, and is released under the GNU
* General Public License.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.edumips64.core;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.logging.Level;
import org.edumips64.core.fpu.EXNotAvailableException;
import org.edumips64.core.fpu.FPDividerNotAvailableException;
import org.edumips64.core.fpu.FPFunctionalUnitNotAvailableException;
import org.edumips64.core.fpu.FPInvalidOperationException;
import org.edumips64.core.fpu.FPPipeline;
import org.edumips64.core.fpu.MemoryNotAvailableException;
import org.edumips64.core.is.AddressErrorException;
import org.edumips64.core.is.BUBBLE;
import org.edumips64.core.is.BreakException;
import org.edumips64.core.is.HaltException;
import org.edumips64.core.is.Instruction;
import org.edumips64.core.is.JumpException;
import org.edumips64.core.is.RAWException;
import org.edumips64.core.is.TwosComplementSumException;
import org.edumips64.core.is.WAWException;
import org.edumips64.utils.*;
/** This class models a MIPS CPU with 32 64-bit General Purpose Registers.
* @author Andrea Spadaccini, Simona Ullo, Antonella Scandura, Massimo Trubia (FPU modifications)
*/
public class CPU {
private Memory mem;
private Register[] gpr;
private static final Logger logger = Logger.getLogger(CPU.class.getName());
/** FPU Elements*/
private RegisterFP[] fpr;
private Instruction lastFPInstructionInEx;
public enum FPExceptions {INVALID_OPERATION, DIVIDE_BY_ZERO, UNDERFLOW, OVERFLOW}
public enum FPRoundingMode { TO_NEAREST, TOWARD_ZERO, TOWARDS_PLUS_INFINITY, TOWARDS_MINUS_INFINITY}
private FCSRRegister FCSR;
public static List<String> knownFPInstructions; // set of Floating point instructions that must pass through the FPU pipeline
private FPPipeline fpPipe;
private List<String> terminatingInstructionsOPCodes;
/** Program Counter*/
private Register pc, old_pc;
private Register LO, HI;
/** Pipeline stage*/
public enum PipeStage {IF, ID, EX, MEM, WB}
/** CPU status.
* READY - the CPU has been initialized but the symbol table hasn't been
* already filled by the Parser. This means that you can't call the step()
* method, or you'll get a StoppedCPUException.
*
* RUNNING - the CPU is executing a program, you can call the step()
* method, and the CPU will fetch additional instructions from the symbol
* table
*
* STOPPING - the HALT instruction has entered in the pipeline. This means
* that no additional instructions must be fetched but the instructions
* that are already in the pipeline must be executed. THe step() method can
* be called, but won't fetch any other instruction
*
* HALTED - the HALT instruction has passed the WB stage, and the step()
* method can't be executed.
* */
public enum CPUStatus {READY, RUNNING, STOPPING, HALTED}
private CPUStatus status;
/** CPU pipeline, each stage contains an Instruction object*/
private Map<PipeStage, Instruction> pipe;
/** The current stage of the pipeline.*/
private PipeStage currentPipeStage;
/** The code and data sections limits*/
public static final int CODELIMIT = 16384; // 16 bit bus (2^12 / 4)
public static final int DATALIMIT = 8192; // 16 bit bus (2^12 / 8)
/** Simulator configuration */
private ConfigStore config;
/** Statistics */
private int cycles, instructions, RAWStalls, WAWStalls, dividerStalls, funcUnitStalls, memoryStalls, exStalls;
/** BUBBLE */
private Instruction bubble;
/** CycleBuilder. Representation of all state transitions that happened inside the CPU. Needed for UIs, but
* stored here because it needs to be invoked every time the CPU does one step. */
private CycleBuilder builder;
public CPU(Memory memory, ConfigStore config) {
this.config = config;
bubble = new BUBBLE();
logger.info("Creating the CPU...");
cycles = 0;
status = CPUStatus.READY;
mem = memory;
logger.info("Got Memory instance..");
// Registers initialization
gpr = new Register[32];
gpr[0] = new R0();
for (int i = 1; i < 32; i++) {
gpr[i] = new Register("R" + i);
}
pc = new Register("PC");
old_pc = new Register("Old PC");
LO = new Register("LO");
HI = new Register("HI");
//Floating point registers initialization
fpr = new RegisterFP[32];
for (int i = 0; i < 32; i++) {
fpr[i] = new RegisterFP();
}
FCSR = new FCSRRegister();
configFPExceptionsAndRM();
fpPipe = new FPPipeline();
fpPipe.reset();
// Pipeline initialization
pipe = new HashMap<>();
clearPipe();
currentPipeStage = PipeStage.IF;
//FPU initialization
FPUConfigurator conf = new FPUConfigurator();
knownFPInstructions = conf.getFPArithmeticInstructions();
terminatingInstructionsOPCodes = conf.getTerminatingInstructions();
// CycleBuilder.
this.builder = new CycleBuilder(this);
logger.info("CPU Created.");
}
// SETTING PROPERTIES ------------------------------------------------------------------
/** Sets the CPU status.
* @param status a CPUStatus value
*/
public void setStatus(CPUStatus status) {
logger.info("Changing CPU status to " + status.name());
this.status = status;
}
/** Sets the flag bits of the FCSR
* @param tag a string value between V Z O U I
* @param value a binary value
*/
public void setFCSRFlags(String tag, int value) throws IrregularStringOfBitsException {
FCSR.setFCSRFlags(tag, value);
}
/** Sets the cause bits of the FCSR
* @param tag a string value between V Z O U I
* @param value a binary value
*/
public void setFCSRCause(String tag, int value) throws IrregularStringOfBitsException {
FCSR.setFCSRCause(tag, value);
}
/** Sets the selected FCC bit of the FCSR
* @param cc condition code is an int value in the range [0,7]
* @param condition the binary value of the relative bit
*/
public void setFCSRConditionCode(int cc, int condition) throws IrregularStringOfBitsException {
FCSR.setFCSRConditionCode(cc, condition);
}
//GETTING PROPERTIES -----------------------------------------------------------------
public CycleBuilder getCycleBuilder() {
return builder;
}
/** Gets the CPU status
* @return status a CPUStatus value representing the current CPU status
*/
public CPUStatus getStatus() {
return status;
}
private void clearPipe() {
pipe.put(PipeStage.IF, null);
pipe.put(PipeStage.ID, null);
pipe.put(PipeStage.EX, null);
pipe.put(PipeStage.MEM, null);
pipe.put(PipeStage.WB, null);
}
public Register[] getRegisters() {
return gpr;
}
public RegisterFP[] getRegistersFP() {
return fpr;
}
/** This method returns a specific GPR
* @param index the register number (0-31)
*/
public Register getRegister(int index) {
return gpr[index];
}
public RegisterFP getRegisterFP(int index) {
return fpr[index];
}
/** Returns true if the specified functional unit is filled by an instruction, false when the contrary happens.
* No controls are carried out on the legality of parameters, for mistaken parameters false is returned
* @param funcUnit The functional unit to check. Legal values are "ADDER", "MULTIPLIER", "DIVIDER"
* @param stage The integer that refers to the stage of the functional unit.
* ADDER [1,4], MULTIPLIER [1,7], DIVIDER [any] */
public boolean isFuncUnitFilled(String funcUnit, int stage) {
return fpPipe.isFuncUnitFilled(funcUnit, stage);
}
/** Returns true if the pipeline is empty. In this case, if CPU is in stopping state
* we can halt the pipeline. The sufficient condition in order to return true is that fpPipe doesn't work
* and it hadn't issued any instrution now in the MEM stage */
private boolean isPipelinesEmpty() {
boolean empty = pipe.get(PipeStage.ID) == null || pipe.get(PipeStage.ID).getName().equals(" ");
empty = empty && (pipe.get(PipeStage.EX) == null || pipe.get(PipeStage.EX).getName().equals(" "));
empty = empty && (pipe.get(PipeStage.MEM) == null || pipe.get(PipeStage.MEM).getName().equals(" "));
// WB is not checked because currently this method is called before the
// instruction in WB is removed from the pipeline.
empty = empty && fpPipe.isEmpty();
return empty;
}
/** Returns the instruction of the specified functional unit , null if it is empty.
* No controls are carried out on the legality of parameters, for mistaken parameters null is returned
* @param funcUnit The functional unit to check. Legal values are "ADDER", "MULTIPLIER", "DIVIDER"
* @param stage The integer that refers to the stage of the functional unit.
* ADDER [1,4], MULTIPLIER [1,7], DIVIDER [any] */
public Instruction getInstructionByFuncUnit(String funcUnit, int stage) {
return fpPipe.getInstructionByFuncUnit(funcUnit, stage);
}
/** Gets the Floating Point Control Status Register*/
public FCSRRegister getFCSR() {
return FCSR;
}
/** Gets the selected FCC bit of the FCSR
* @param cc condition code is an int value in the range [0,7]
*/
public int getFCSRConditionCode(int cc) {
return FCSR.getFCSRConditionCode(cc);
}
/** Gets the current rounding mode readeng the FCSR
* @return the rounding mode */
public FPRoundingMode getFCSRRoundingMode() {
return FCSR.getFCSRRoundingMode();
}
/** Gets the current computing step of the divider*/
public int getDividerCounter() {
return fpPipe.getDividerCounter();
}
/** Gets the integer pipeline
* @return an HashMap
*/
public Map<PipeStage, Instruction> getPipeline() {
return pipe;
}
// Includes FP instructions and bubbles. Used by CycleBuilder.
public int getInstructionCount() {
int count = 0;
for (Instruction i : pipe.values()) {
if (i != null) {
count++;
}
}
return count + fpPipe.size();
}
/** Returns the number of cycles performed by the CPU.
* @return an integer
*/
public int getCycles() {
return cycles;
}
/** Returns the number of instructions executed by the CPU
* @return an integer
*/
public int getInstructions() {
return instructions;
}
/** Returns the number of RAW Stalls that happened inside the pipeline
* @return an integer
*/
public int getRAWStalls() {
return RAWStalls;
}
/** Returns the number of WAW stalls that happened inside the pipeline
* @return an integer
*/
public int getWAWStalls() {
return WAWStalls;
}
/** Returns the number of Structural Stalls (Divider not available) that happened inside the pipeline
* @return an integer
*/
public int getStructuralStallsDivider() {
return dividerStalls;
}
/** Returns the number of Structural Stalls (Memory not available) that happened inside the pipeline
* @return an integer
*/
public int getStructuralStallsMemory() {
return memoryStalls;
}
/** Returns the number of Structural Stalls (EX not available) that happened inside the pipeline
* @return an integer
*/
public int getStructuralStallsEX() {
return exStalls;
}
/** Returns the number of Structural Stalls (FP Adder and FP Multiplier not available) that happened inside the pipeline
* @return an integer
*/
public int getStructuralStallsFuncUnit() {
return funcUnitStalls;
}
/** Gets the floating point unit enabled exceptions
* @return true if exceptionName is enabled, false in the other case
*/
public boolean getFPExceptions(FPExceptions exceptionName) {
return FCSR.getFPExceptions(exceptionName);
}
/** Gets the Program Counter register
* @return a Register object
*/
public Register getPC() {
return pc;
}
/** Gets the Last Program Counter register
* @return a Register object
*/
public Register getLastPC() {
return old_pc;
}
/** Gets the LO register. It contains integer results of doubleword division
* @return a Register object
*/
public Register getLO() {
return LO;
}
/** Gets the HI register. It contains integer results of doubleword division
* @return a Register object
*/
public Register getHI() {
return HI;
}
/** Gets the structural stall counter
*@return the memory stall counter
*/
public int getMemoryStalls() {
return memoryStalls;
}
/** This method performs a single pipeline step
*/
public void step() throws AddressErrorException, HaltException, IrregularWriteOperationException, StoppedCPUException, MemoryElementNotFoundException, IrregularStringOfBitsException, TwosComplementSumException, SynchronousException, BreakException, NotAlignException, WAWException, MemoryNotAvailableException, FPDividerNotAvailableException, FPFunctionalUnitNotAvailableException {
configFPExceptionsAndRM();
String syncex;
if (status != CPUStatus.RUNNING && status != CPUStatus.STOPPING) {
throw new StoppedCPUException();
}
try {
// Stages are executed from the last one (WB) to the first one (IF). After the
// logic for the given stage is executed, the instruction is moved to the next
// stage (except for WB, where the instruction is discarded.
logger.info("\n\nStarting cycle " + ++cycles + "\n---------------------------------------------");
// WB: Write-back stage.
stepWB();
// MEM: Memory access stage.
stepMEM();
// EX: Execution/effective address stage.
// Returns the code of the synchronous exception that can happen at this
// stage, so the rest of the step can continue and, at the end, the
// exception can be thrown.
syncex = stepEX();
// ID: instruction decode / register fetch stage
stepID();
// IF: instruction fetch stage.
stepIF();
if (syncex != null) {
throw new SynchronousException(syncex);
}
} catch (JumpException ex) {
logger.info("Executing a Jump.");
try {
if (pipe.get(PipeStage.IF) != null) {
logger.info("Executing the IF() method of the instruction in IF.");
pipe.get(PipeStage.IF).IF();
}
} catch (BreakException bex) {
logger.info("Caught a BREAK after a Jump: ignoring it.");
}
// A J-Type instruction has just modified the Program Counter. We need to
// put in the IF stage the instruction the PC points to
pipe.put(PipeStage.IF, mem.getInstruction(pc));
pipe.put(PipeStage.EX, pipe.get(PipeStage.ID));
pipe.put(PipeStage.ID, bubble);
old_pc.writeDoubleWord((pc.getValue()));
pc.writeDoubleWord((pc.getValue()) + 4);
} catch (RAWException ex) {
if (currentPipeStage == PipeStage.ID) {
pipe.put(PipeStage.EX, bubble);
}
RAWStalls++;
logger.info("RAW stalls incremented to " + RAWStalls);
} catch (WAWException ex) {
logger.info(fpPipe.toString());
if (currentPipeStage == PipeStage.ID) {
pipe.put(PipeStage.EX, bubble);
}
WAWStalls++;
logger.info("WAW stalls incremented to " + RAWStalls);
} catch (FPDividerNotAvailableException ex) {
if (currentPipeStage == PipeStage.ID) {
pipe.put(PipeStage.EX, bubble);
}
dividerStalls++;
} catch (FPFunctionalUnitNotAvailableException ex) {
if (currentPipeStage == PipeStage.ID) {
pipe.put(PipeStage.EX, bubble);
}
funcUnitStalls++;
} catch (EXNotAvailableException ex) {
exStalls++;
} catch (SynchronousException ex) {
logger.info("Exception: " + ex.getCode());
throw ex;
} catch (HaltException ex) {
pipe.put(PipeStage.WB, null);
throw ex;
} finally {
builder.step();
logger.info("End of cycle " + cycles + "\n---------------------------------------------\n" + pipeLineString() + "\n");
}
}
private void changeStage(PipeStage newStatus) {
logger.info(newStatus.toString() + " STAGE: " + pipe.get(newStatus) + "\n================================");
currentPipeStage = newStatus;
}
// Individual stages.
private void stepIF() throws IrregularStringOfBitsException, HaltException, IrregularWriteOperationException, BreakException {
// We don't have to execute any methods, but we must get the new
// instruction from the symbol table.
changeStage(PipeStage.IF);
logger.info("CPU Status: " + status.name());
boolean breaking = false;
if (status == CPUStatus.RUNNING) {
if (pipe.get(PipeStage.IF) != null) { //rispetto a dinmips scambia le load con le IF
try {
logger.info("Executing IF() for " + pipe.get(PipeStage.IF));
pipe.get(PipeStage.IF).IF();
} catch (BreakException exc) {
breaking = true;
}
}
logger.info("Moving " + pipe.get(PipeStage.IF) + " to ID");
pipe.put(PipeStage.ID, pipe.get(PipeStage.IF));
Instruction next_if = mem.getInstruction(pc);
logger.info("Fetched new instruction " + next_if);
old_pc.writeDoubleWord((pc.getValue()));
pc.writeDoubleWord((pc.getValue()) + 4);
logger.info("New Program Counter value: " + pc.toString());
logger.info("Putting " + next_if + "in IF.");
pipe.put(PipeStage.IF, next_if);
} else {
pipe.put(PipeStage.ID, bubble);
}
if (breaking) {
logger.info("Re-throwing the BREAK exception");
throw new BreakException();
}
}
private void stepID() throws TwosComplementSumException, WAWException, IrregularStringOfBitsException, FPInvalidOperationException, BreakException, HaltException, RAWException, IrregularWriteOperationException, JumpException, FPDividerNotAvailableException, FPFunctionalUnitNotAvailableException, EXNotAvailableException {
changeStage(PipeStage.ID);
if (pipe.get(PipeStage.ID) != null) {
boolean isFP = knownFPInstructions.contains(pipe.get(PipeStage.ID).getName());
// Check if the desired unit (FP or not) is available.
if (isFP && (fpPipe.putInstruction(pipe.get(PipeStage.ID), true) != 0)) {
if (pipe.get(PipeStage.ID).getName().compareToIgnoreCase("DIV.D") == 0) {
throw new FPDividerNotAvailableException();
} else {
throw new FPFunctionalUnitNotAvailableException();
}
} else if (!isFP && (pipe.get(PipeStage.EX) != null && pipe.get(PipeStage.EX).getName().compareTo(" ") != 0)) {
throw new EXNotAvailableException();
}
logger.info("Executing ID() for " + pipe.get(PipeStage.ID));
// Can change the CPU status from RUNNING to STOPPING.
pipe.get(PipeStage.ID).ID();
if (isFP) {
logger.info("Moving " + pipe.get(PipeStage.ID) + " to the FP pipeline.");
fpPipe.putInstruction(pipe.get(PipeStage.ID), false);
} else {
logger.info("Moving " + pipe.get(PipeStage.ID) + " to EX");
pipe.put(PipeStage.EX, pipe.get(PipeStage.ID));
}
pipe.put(PipeStage.ID, null);
}
}
private String stepEX() throws SynchronousException, HaltException, NotAlignException, TwosComplementSumException, IrregularWriteOperationException, AddressErrorException, IrregularStringOfBitsException {
changeStage(PipeStage.EX);
// Used for exception handling
boolean masked = config.getBoolean(ConfigKey.SYNC_EXCEPTIONS_MASKED);
boolean terminate = config.getBoolean(ConfigKey.SYNC_EXCEPTIONS_TERMINATE);
// Code of the synchronous exception that happens in EX.
String syncex = null;
Instruction completedFpInstruction = fpPipe.getCompletedInstruction();
Instruction instruction;
boolean shouldExecuteFP = completedFpInstruction != null;
// if there will be a stall because a lot of instructions would fill the MEM stage, the EX()
// method cannot be called because the integer instruction in EX cannot be moved.
if (!shouldExecuteFP) {
instruction = pipe.get(PipeStage.EX);
} else {
//a structural stall has to be raised if the EX stage contains an instruction different from a bubble or other fu's contain instructions (counter of structural stalls must be incremented)
if ((pipe.get(PipeStage.EX) != null && !(pipe.get(PipeStage.EX).getName().compareTo(" ") == 0)) || fpPipe.getNReadyToExitInstr() > 1) {
memoryStalls++;
}
instruction = completedFpInstruction;
// Keep track of the last FP instruction in EX.
lastFPInstructionInEx = instruction;
}
// Execute the instruction, and handle synchronous exceptions.
if (instruction != null) {
try {
logger.info("Executing EX() for " + instruction);
instruction.EX();
} catch (SynchronousException e) {
if (masked) {
logger.info("[EXCEPTION] [MASKED] " + e.getCode());
} else {
if (terminate) {
logger.info("Terminating due to an unmasked exception");
throw new SynchronousException(e.getCode());
} else {
// We must complete this cycle, but we must notify the user.
// If the syncex string is not null, the CPU code will throw
// the exception at the end of the step
syncex = e.getCode();
}
}
}
}
Instruction toMove = shouldExecuteFP ? lastFPInstructionInEx : pipe.get(PipeStage.EX);
logger.info("Moving " + toMove + " to MEM");
pipe.put(PipeStage.MEM, toMove);
if (!shouldExecuteFP) {
pipe.put(PipeStage.EX, null);
}
// Shift instructions in the fpPipe.
fpPipe.step();
// Return the code of the synchronous exception (if any).
return syncex;
}
private void stepMEM() throws HaltException, NotAlignException, IrregularWriteOperationException, MemoryElementNotFoundException, AddressErrorException, IrregularStringOfBitsException {
changeStage(PipeStage.MEM);
if (pipe.get(PipeStage.MEM) != null) {
logger.info("Executing MEM() for " + pipe.get(PipeStage.MEM));
pipe.get(PipeStage.MEM).MEM();
}
logger.info("Moving " + pipe.get(PipeStage.MEM) + " to WB");
pipe.put(PipeStage.WB, pipe.get(PipeStage.MEM));
pipe.put(PipeStage.MEM, null);
}
private void stepWB() throws IrregularStringOfBitsException, HaltException {
changeStage(PipeStage.WB);
if (pipe.get(PipeStage.WB) != null) {
boolean terminatorInstrInWB = terminatingInstructionsOPCodes.contains(pipe.get(PipeStage.WB).getRepr().getHexString());
//we have to execute the WB method only if some conditions occur
//the current instruction in WB is a terminating instruction and the fpPipe is working
boolean notWBable = terminatorInstrInWB && !fpPipe.isEmpty();
//the current instruction in WB is a terminating instruction, the fpPipe doesn't work because it has just issued an instruction and it is in the MEM stage
notWBable = notWBable || (terminatorInstrInWB && !pipe.get(PipeStage.MEM).getName().equals(" "));
if (!pipe.get(PipeStage.WB).getName().equals(" ")) {
instructions++;
}
if (!notWBable) {
logger.info("Executing WB() for " + pipe.get(PipeStage.WB));
pipe.get(PipeStage.WB).WB();
}
// Move the instruction in WB out of the pipeline.
logger.info("Instruction " + pipe.get(PipeStage.WB) + " has been completed. Removing it.");
pipe.put(PipeStage.WB, null);
//if the pipeline is empty and it is into the stopping state (because a long latency instruction was executed) we can halt the cpu when computations finished
if (isPipelinesEmpty() && getStatus() == CPUStatus.STOPPING) {
logger.info("Pipeline is empty and we are in STOPPING --> going to HALTED.");
setStatus(CPU.CPUStatus.HALTED);
throw new HaltException();
}
}
}
/** This method resets the CPU components (GPRs, memory,statistics,
* PC, pipeline and Symbol table).
* It resets also the Dinero Tracefile object associated to the current
* CPU.
*/
public void reset() {
// Reset CPU state.
status = CPUStatus.READY;
cycles = 0;
instructions = 0;
RAWStalls = 0;
WAWStalls = 0;
dividerStalls = 0;
funcUnitStalls = 0;
exStalls = 0;
memoryStalls = 0;
// Reset registers.
for (int i = 0; i < 32; i++) {
gpr[i].reset();
}
//reset FPRs
for (int i = 0; i < 32; i++) {
fpr[i].reset();
}
try {
// Reset the FCSR condition codes.
for (int cc = 0; cc < 8; cc++) {
setFCSRConditionCode(cc, 0);
}
// Reset the FCSR flags.
setFCSRFlags("V", 0);
setFCSRFlags("O", 0);
setFCSRFlags("U", 0);
setFCSRFlags("Z", 0);
// Reset the FCSR cause bits.
setFCSRCause("V", 0);
setFCSRCause("O", 0);
setFCSRCause("U", 0);
setFCSRCause("Z", 0);
} catch (IrregularStringOfBitsException ex) {
ex.printStackTrace();
}
LO.reset();
HI.reset();
// Reset program counter
pc.reset();
old_pc.reset();
// Reset the memory.
mem.reset();
// Reset pipeline
clearPipe();
// Reset FP pipeline
fpPipe.reset();
// Reset CycleBuilder
builder.reset();
logger.info("CPU Resetted");
}
/** Test method that returns a string containing the status of the pipeline.
* @return string representation of the pipeline status
*/
public String pipeLineString() {
String s = "";
s += "IF:\t" + pipe.get(PipeStage.IF) + "\n";
s += "ID:\t" + pipe.get(PipeStage.ID) + "\n";
s += "EX:\t" + pipe.get(PipeStage.EX) + "\n";
s += "MEM:\t" + pipe.get(PipeStage.MEM) + "\n";
s += "WB:\t" + pipe.get(PipeStage.WB) + "\n";
return s;
}
/** Test method that returns a string containing the values of every
* register.
* @return string representation of the register file contents
*/
public String gprString() {
String s = "";
int i = 0;
for (Register r : gpr) {
s += "Register " + i++ + ":\t" + r.toString() + "\n";
}
return s;
}
public boolean isEnableForwarding() {
return config.getBoolean(ConfigKey.FORWARDING);
}
/** Test method that returns a string containing the values of every
* FPR.
* @return a string
*/
private String fprString() {
String s = "";
int i = 0;
for (RegisterFP r: fpr) {
s += "FP Register " + i++ + ":\t" + r.toString() + "\n";
}
return s;
}
private void configFPExceptionsAndRM() {
try {
FCSR.setFPExceptions(CPU.FPExceptions.INVALID_OPERATION, config.getBoolean(ConfigKey.FP_INVALID_OPERATION));
FCSR.setFPExceptions(CPU.FPExceptions.OVERFLOW, config.getBoolean(ConfigKey.FP_OVERFLOW));
FCSR.setFPExceptions(CPU.FPExceptions.UNDERFLOW, config.getBoolean(ConfigKey.FP_UNDERFLOW));
FCSR.setFPExceptions(CPU.FPExceptions.DIVIDE_BY_ZERO, config.getBoolean(ConfigKey.FP_DIVIDE_BY_ZERO));
//setting the rounding mode
if (config.getBoolean(ConfigKey.FP_NEAREST)) {
FCSR.setFCSRRoundingMode(FPRoundingMode.TO_NEAREST);
} else if (config.getBoolean(ConfigKey.FP_TOWARDS_ZERO)) {
FCSR.setFCSRRoundingMode(FPRoundingMode.TOWARD_ZERO);
} else if (config.getBoolean(ConfigKey.FP_TOWARDS_PLUS_INFINITY)) {
FCSR.setFCSRRoundingMode(FPRoundingMode.TOWARDS_PLUS_INFINITY);
} else if (config.getBoolean(ConfigKey.FP_TOWARDS_MINUS_INFINITY)) {
FCSR.setFCSRRoundingMode(FPRoundingMode.TOWARDS_MINUS_INFINITY);
}
} catch (IrregularStringOfBitsException ex) {
Logger.getLogger(CPU.class.getName()).log(Level.SEVERE, null, ex);
}
}
public String toString() {
String s = "";
s += mem.toString() + "\n";
s += pipeLineString();
s += gprString();
s += fprString();
return s;
}
/** Private class, representing the R0 register */
// TODO: DEVE IMPOSTARE I SEMAFORI?????
private class R0 extends Register {
public R0() {
super("R0");
}
public long getValue() {
return (long) 0;
}
public String getBinString() {
return "0000000000000000000000000000000000000000000000000000000000000000";
}
public String getHexString() {
return "0000000000000000";
}
public void setBits(String bits, int start) {
}
public void writeByteUnsigned(int value) {}
public void writeByte(int value, int offset) {}
public void writeHalfUnsigned(int value) {}
public void writeHalf(int value) {}
public void writeHalf(int value, int offset) {}
public void writeWordUnsigned(long value) {}
public void writeWord(int value) {}
public void writeWord(long value, int offset) {}
public void writeDoubleWord(long value) {}
}
}