package MipsSim;
import MipsSim.Instruction.InstName;
import MipsSim.SimUtils;
import MipsSim.Instruction;
public class PipelineLatch {
//Instruction Type Enumerators
public enum PipelineStage { IF1, IF2, ID, EX, MEM1, MEM2, MEM3, WB, DONE };
//Generic Pipeline Pieces
public int NPC; //Next Sequential PC Register (NPC)
public Boolean Cond; //Result of Conditional Evaluation
public Instruction Inst; //Latch Instruction
//Pipeline Registers
public Reg LMD; //Load Memory Data Register
public Reg IR; //Instruction Register
public Reg Imm; //Sign extended immediate field of IR
public Reg ALUOutput; //Result of ALU Operation
//Temporary Registers
public Reg regA; //Temp. Register A
public Reg regB; //Temp. Register B
//Instruction Enums
public PipelineStage atStage; //Current stage of the latch in question
public PipelineLatch() {
/**
* Default constructor for Pipeline Latch Class
*/
this.NPC = -1;
this.Cond = null;
this.ALUOutput = new Reg();;
this.LMD = new Reg();;
this.IR = new Reg();;
this.Imm = new Reg();;
this.regA = new Reg();;
this.regB = new Reg();;
}
public PipelineLatch(Instruction i) {
/**
* Constructor for Pipeline Latch Class
* Sets components to null
*
* @param i latch instruction
*/
this(); //Call default constructor
this.Inst = i; //Set this instruction to the input
}
public PipelineLatch(String in) {
/**
* Constructor for Pipeline Latch Class
* Sets components to null
*
* @param in string to check for pipeline match against
*/
this(); //Call default constructor
this.atStage = checkStage(in); //Check if passed parameter matches a stage
}
public PipelineStage checkStage(String s) {
/**
* Checks to see if the incoming string is a Pipeline Stage
*
* @param s string to check against
* @return Pipeline Stage if match is found, null otherwise
*/
for(PipelineStage ps : PipelineStage.values()) {
if (ps.name().equals(s)) {
return ps;
}
}
return null;
}
public void toNextStage() {
/**
* Advances the current Pipeline Latch stage to the next stage
* in the MIPS Pipeline
*
*/
if(this.atStage != null) {
//Make sure we're not at the end of the list
// If we are, set the new current stage to null
this.atStage = this.atStage.ordinal() < PipelineStage.values().length - 1
? PipelineStage.values()[this.atStage.ordinal() + 1]
: null;
} else {
//ERROR: trying to get next stage of an unspecified latch
SimUtils.error("There was an eror trying to get next stage of an unspecified latch");
}
}
public boolean stallNeeded() {
/**
* Checks to see the necessity of a stall in the ID phase
*
* @return true or false based on the necessity of a stall
*/
/*
* Stall Conditions:
* EX/MEM.RegWrite & (EX/MEM.rd == ID/EX.rs)
* EX/MEM.RegWrite & (EX/MEM.rd == ID/EX.rt)
*
* MEM/WB.RegWrite & (MEM/WB.rd == ID/EX.rs)
* MEM/WB.RegWrite & (MEM/WB.rd == ID/EX.rt)
*
* NOTE: Because of data forwarding, only need to stall for loads!
*/
boolean needsStall = false;
for (int i = 5; i<7; i++) {
PipelineLatch otherLatch = SimUtils.getLatchAt(i);
if (otherLatch != null) {
Instruction otherInst = otherLatch.Inst;
if ((otherInst.name == InstName.LD) && (this.Inst.src1 != null)
&& (otherInst.dest.RegRef == this.Inst.src1.RegRef)) {
needsStall = true;
break;
} else if ((otherInst.name == InstName.LD) && (this.Inst.src2 != null)
&& (otherInst.dest.RegRef == this.Inst.src2.RegRef)) {
needsStall = true;
break;
}
}
}
return needsStall;
}
}