C 语言的 MIPS 流水线模拟器
MIPS Pipeline Simulator in C
我应该编写一个 C 程序,该程序采用包含一组 MIPS 指令的 .asm 文件,然后提供对每个周期中发生的情况的诊断。至于格式化等,我不需要帮助。我已经获得了涵盖该内容的代码;然而,我正在努力弄清楚如何设置我的流水线寄存器。
我已经设置了 IFID 管道并且我认为我已经正确设置了 IDEX 管道但是我不确定我是否在正确的轨道上,regFile
数组主要是我的不确定,state.regFile[(state.PC)/4];
被除以 4,因为地址是为了模仿 MIPS,是字对齐的,但我不知道我目前拥有的内容是否有意义。
这是我的主要功能的片段。
请注意,IFID
、IDEX
、EXMEM
、MEMWB
是我的管道,每个结构都包含每个管道的必要信息。
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 阶段,计算分支目标。
我应该编写一个 C 程序,该程序采用包含一组 MIPS 指令的 .asm 文件,然后提供对每个周期中发生的情况的诊断。至于格式化等,我不需要帮助。我已经获得了涵盖该内容的代码;然而,我正在努力弄清楚如何设置我的流水线寄存器。
我已经设置了 IFID 管道并且我认为我已经正确设置了 IDEX 管道但是我不确定我是否在正确的轨道上,regFile
数组主要是我的不确定,state.regFile[(state.PC)/4];
被除以 4,因为地址是为了模仿 MIPS,是字对齐的,但我不知道我目前拥有的内容是否有意义。
这是我的主要功能的片段。
请注意,IFID
、IDEX
、EXMEM
、MEMWB
是我的管道,每个结构都包含每个管道的必要信息。
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 阶段,计算分支目标。