Search code examples
cmipspipeline

MIPS Pipeline Simulator in C


I'm supposed to write a C program that takes an .asm file that contains a set of MIPS instructions and then provides a diagnostic of what occurs during each cycle. As far as formatting, etc I won't need help. I've been given code that covers that; however I'm struggling figuring out how to set up my pipeline registers.

I have the IFID pipeline set up and I think I have the IDEX pipeline set up correctly but I'm unsure if I'm on the right track, the regFile array is mainly what I'm unsure about, the state.regFile[(state.PC)/4]; is divided by 4 due to the fact that the addresses, meant to mimic MIPS, are word aligned but I don't know if what I currently have even makes sense.

Here is a snippet of my main function.

Note that IFID, IDEX, EXMEM, MEMWB are my pipelines and are structs each containing the necessary information for each pipeline.

void run(){

  stateType state;           /* Contains the state of the entire pipeline before the cycle executes */ 
  stateType newState;        /* Contains the state of the entire pipeline after the cycle executes */
  initState(&state);         /* Initialize the state of the pipeline */

   while (1) {

    printState(&state);

/* If a halt instruction is entering its WB stage, then all of the legitimate */
/* instruction have completed. Print the statistics and exit the program. */
    if (get_opcode(state.MEMWB.instr) == HALT) {
        printf("Total number of cycles executed: %d\n", state.cycles);
        /* Remember to print the number of stalls, branches, and mispredictions! */
        exit(0);
    }

    newState = state;     /* Start by making newState a copy of the state before the cycle */
    newState.cycles++;

/* Modify newState stage-by-stage below to reflect the state of the pipeline after the cycle has executed */

    /* --------------------- IF stage --------------------- */

    /* Setting IFIDs instruction equal to the instruction found at address state.PC*/
    newState.IFID.instr = state.instMem[(state.PC)/4];
    /* Setting IFID's PCPlus4 to state.PC + 4 */
    newState.IFID.PCPlus4 = state.PC + 4;
    /* Update PC */
    newState.PC = state.PC +  4;

    /* --------------------- ID stage --------------------- */       

    newState.IDEX.instr = state.instMem[(state.PC)/4];
    newState.IDEX.PCPlus4 = state.PC + 8;
    newState.IDEX.readData1 = state.regFile[(state.PC)/4];
    newState.IDEX.readData2 = state.regFile[(state.PC)/4];
    newState.IDEX.immed = state.regFile[(state.PC)/4];
    newState.IDEX.rsReg = state.regFile[(state.PC)/4];
    newState.IDEX.rtReg = state.regFile[(state.PC)/4];
    newState.IDEX.rdReg = state.regFile[(state.PC)/4];
    newState.IDEX.branchTarget = state.regFile[(state.PC)/4];


    /* --------------------- EX stage --------------------- */
    newState.EXMEM.instr = state.instrMem[(state.PC)/4];
    newState.EXMEM.PCPlus4 = state.PC + 12;


    /* --------------------- MEM stage --------------------- */


    /* --------------------- WB stage --------------------- */


    state = newState;    /* The newState now becomes the old state before we execute the next cycle */
}
}

Solution

  • (state.PC)/4 makes sense to get the array index of the instruction. However, it does not make sense as an index into the register file.

    You actually have to decode the instruction, which you just fetched in the IF stage. The bitfields in the instruction index into the register file. The immediate obviously doesn't come from the register file, it comes from the instruction, because that's what immediate means.

    The instruction also shouldn't be re-fetched (as happens in newState.IDEX.instr = state.instMem[(state.PC)/4];), because you may need to kill it (a branch has to kill at least one instruction that is already in the pipeline but turns out to be there incorrectly, two if you don't have the delay slot).

    As a general tip, if I were you I'd look at the pipeline diagram in any book that covers the classic RISC pipeline, for example Patterson & Hennessy Computer Organization Design.

    I have an example here, made partly by me (based on previously existing architectures by the University of Amsterdam) in SIM-PL (which is also from UvA).

    pipeline

    You can see here that the ID stage doesn't even use PC. It just passes it on to the EX stage, which calculates the branch target.