C 语言的 MIPS 流水线模拟器

MIPS Pipeline Simulator in C

我应该编写一个 C 程序,该程序采用包含一组 MIPS 指令的 .asm 文件,然后提供对每个周期中发生的情况的诊断。至于格式化等,我不需要帮助。我已经获得了涵盖该内容的代码;然而,我正在努力弄清楚如何设置我的流水线寄存器。

我已经设置了 IFID 管道并且我认为我已经正确设置了 IDEX 管道但是我不确定我是否在正确的轨道上,regFile 数组主要是我的不确定,state.regFile[(state.PC)/4]; 被除以 4,因为地址是为了模仿 MIPS,是字对齐的,但我不知道我目前拥有的内容是否有意义。

这是我的主要功能的片段。

请注意,IFIDIDEXEXMEMMEMWB 是我的管道,每个结构都包含每个管道的必要信息。

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 */
}
}

(state.PC)/4 获取指令的数组索引是有意义的。但是,它作为寄存器文件的索引没有意义。

您实际上必须解码您刚刚在 IF 阶段获取的 指令 。指令中的位域索引到寄存器文件中。立即数显然不是来自寄存器文件,而是来自指令,因为这就是立即数的意思。

该指令也不应重新获取(如 newState.IDEX.instr = state.instMem[(state.PC)/4]; 中发生的那样),因为您可能需要终止它(一个分支必须终止至少一条已经在管道中的指令,但事实证明那里不正确,如果你没有延迟槽则有两个)。

作为一般提示,如果我是你,我会查看任何涵盖经典 RISC 流水线的书籍中的流水线图,例如 Patterson & Hennessy Computer Organization Design。

我这里有一个示例,部分由我在 SIM-PL(也来自 UvA)中制作(基于阿姆斯特丹大学以前存在的架构)。

你可以在这里看到ID阶段甚至没有使用PC。它只是将其传递到 EX 阶段,计算分支目标。