//==================================================================== // // 5 stage pipeline: IF, ID, EX, MEM, WB // Instructions: register-register ALU instructions with 2 register ids // register-immediate ALU instructions with 2 register ids // store instructions // load instructions // jump instructions // branch instructions // ALU exceptions // return from ALU exceptions // // Author: Aaron Kobayashi (baudburn at instructor dot net) // // Date: 11/01/02 // //==================================================================== (bit phi1 phi2 phi3 phi4 Flush Flush_bar //Regwrite bits RegWrite IF_RegWrite IF_ID_RegWrite ID_EX_RegWrite EX_MEM_RegWrite MEM_WB_RegWrite write_PC write_RegFile_In RegsEql_MEMD1 RegsEql_MEMD2 RegsEql_WBD1 RegsEql_WBD2 fwd_MEMD1 fwd_MEMD2 fwd_WBD1 fwd_WBD2 FwdSelector_D1 FwdSelector_D2 //Register-Immediate Bits use_Imm IF_ID_use_Imm ID_EX_use_Imm //Store Instruction Bits MemWrite IF_MemWrite IF_ID_MemWrite ID_EX_MemWrite EX_MEM_MemWrite write_DMem_In //Load Instruction Bits MemToReg IF_ID_MemToReg ID_EX_MemToReg EX_MEM_MemToReg MEM_WB_MemToReg ID_StallReg ID_StallReg1 ID_StallReg2 ID_WriteResult EX_WriteResult ID_StallTmp ID_Stall ID_Stall_bar stall_PC IF_ID_phi4 //For Bubbles ID_MemWrite ID_RegWrite //Jump Instruction Bits stall_PC2 IF_Squash_bar ID_Squash_bar EX_Squash_bar is_Jump IF_is_Jump IF_ID_is_Jump ID_is_Jump ID_EX_is_Jump EX_is_Jump EX_MEM_is_Jump EX_RegWrite EX_MemWrite ID_WriteOrJump IF_ID_JumpOrStall //Branch Instruction Bits is_Branch IF_is_Branch ID_is_Branch IF_ID_is_Branch ID_EX_is_Branch EX_is_taken_branch EX_use_TargetPC EX_use_TargetPC2 EX_MEM_use_TargetPC EX_MEM_use_TargetPC_bar EX_TakeBranch ID_WrJmpBr //ALU Exception bits allow_ALU_exceptions IF_allow_ALU_exceptions IF_ID_allow_ALU_exceptions ID_allow_ALU_exceptions ID_EX_allow_ALU_exceptions raised_ALU_Exception is_ALU_Exception EX_is_ALU_Exception EX_MEM_is_ALU_Exception EX_MEM_is_ALU_Exception_bar MEM_WB_is_ALU_Exception_bar write_RegFile_In1 write_DMem_In1 EX_MEM_Branch IsException write_EPC ID_WrJmpBrEx //return from ALU Exception bits is_ReturnFromException IF_is_ReturnFromException IF_ID_is_ReturnFromException ID_is_ReturnFromException ID_EX_is_ReturnFromException EX_is_ReturnFromException EX_MEM_is_ReturnFromException EX_MEM_is_ReturnFromException_bar MEM_WB_is_ReturnFromException_bar return_to_EPC write_IsException_a write_IsException MEM_RegWrite MEM_MemWrite write_RegFile_In2 EX_MEM_use_TargetPC1 stall_PC3 IF_ID_JumpOrStall2 write_EPC1 MEM_is_ALU_Exception ) (term PC sequentialPC SrcReg1 SrcReg2 DestReg Op Data1 Data2 //Inst. Fetch / Decode IF_ID_SrcReg1 IF_ID_SrcReg2 IF_ID_DestReg IF_ID_Op //Decode / Execute ID_EX_SrcReg1 ID_EX_SrcReg2 ID_EX_DestReg ID_EX_Op ID_EX_Data1 ID_EX_Data2 //For forwarding FwMux_D1 FwMux_D2 EX_Data1 EX_Data2 Result EX_MEM_Result EX_MEM_DestReg MEM_WB_Result MEM_WB_DestReg //For Reg-Immediate Imm IF_ID_Imm ID_EX_Imm ALU_Data2 //For Store Instructions NextMemState PresentMemState //We have to add opcode and Data2 forwarding to the MEM stage EX_DestAddr EX_MEM_DestAddr EX_MEM_Op //For Load Instructions ReadData MEM_WB_ReadData WriteData //Jump Terms nextPC EX_TargetPC EX_MEM_TargetPC IF_ID_sequentialPC ID_EX_sequentialPC //Exception Terms ExceptionHandler IF_ID_PC ID_EX_PC EX_MEM_PC EPC nextPCtmp //Return from Exception Terms nextPCtmp2 ) (input phi1 phi2 phi3 phi4 Flush) // IF Stage Logic // ============================================ //--- Define the PC as a nontransparent latch Flush_bar = (not Flush) //Logic to stall the PC if we are inserting bubbles into the pipeline stall_PC = (and Flush_bar ID_Stall_bar) //Logic to handle stalling the PC if we are waiting for an address to //be calculated stall_PC2 = (or stall_PC EX_MEM_use_TargetPC) stall_PC3 = (or stall_PC2 return_to_EPC) write_PC = (and phi4 stall_PC3) (latch PC PC // memory definition name (inport write_PC (nextPC) ) (outport phi1 (PC) ) ) sequentialPC = (PCAdder PC) ExceptionHandler = (ALU_Exception_Handler) //Figure out the next PC value nextPCtmp = (mux EX_MEM_use_TargetPC EX_MEM_TargetPC sequentialPC) nextPCtmp2= (mux EX_MEM_is_ALU_Exception ExceptionHandler nextPCtmp) nextPC = (mux return_to_EPC EPC nextPCtmp2) //--- Define the instruction memory (memory IMem IMem // memory definition name (outport phi2 PC (SrcReg1 SrcReg2 DestReg Op RegWrite Imm use_Imm MemWrite is_Jump is_Branch MemToReg allow_ALU_exceptions is_ReturnFromException) ) ) //Logic for handling squashing of data in the IF stage IF_Squash_bar = (and Flush_bar EX_MEM_use_TargetPC_bar) // Handle flush of pipeline and squash of data for RegWrites IF_RegWrite = (and RegWrite IF_Squash_bar) // Handle flush of pipeline and squash of data for MemWrites IF_MemWrite = (and MemWrite IF_Squash_bar) // Handle squashing jump instructions also IF_is_Jump = (and is_Jump IF_Squash_bar) // Handle squashing branch instructions aswell IF_is_Branch = (and is_Branch IF_Squash_bar) // Handle squashing for ALU Exceptions IF_allow_ALU_exceptions = (and allow_ALU_exceptions IF_Squash_bar) // Handle squashing for return from ALU Exceptions IF_is_ReturnFromException = (and is_ReturnFromException IF_Squash_bar) // ID Stage Logic // ============================================ // Since we are stalling at the IF_ID latch, we need to only latch // new data if we are ok to do so IF_ID_JumpOrStall = (or ID_Stall_bar EX_MEM_use_TargetPC) IF_ID_JumpOrStall2= (or IF_ID_JumpOrStall return_to_EPC) IF_ID_phi4 = (and phi4 IF_ID_JumpOrStall2) //--- Define the IF/ID latch (latch IF_ID IF_ID // memory definition name (inport IF_ID_phi4 (SrcReg1 SrcReg2 DestReg Op IF_RegWrite Imm use_Imm IF_MemWrite MemToReg sequentialPC IF_is_Jump IF_is_Branch PC IF_allow_ALU_exceptions IF_is_ReturnFromException ) ) (outport phi1 (IF_ID_SrcReg1 IF_ID_SrcReg2 IF_ID_DestReg IF_ID_Op IF_ID_RegWrite IF_ID_Imm IF_ID_use_Imm IF_ID_MemWrite IF_ID_MemToReg IF_ID_sequentialPC IF_ID_is_Jump IF_ID_is_Branch IF_ID_PC IF_ID_allow_ALU_exceptions IF_ID_is_ReturnFromException ) ) ) //--- Define the register file write_RegFile_In1 = (and phi2 MEM_WB_RegWrite) write_RegFile_In2 = (and write_RegFile_In1 MEM_WB_is_ReturnFromException_bar) write_RegFile_In = (and write_RegFile_In2 MEM_WB_is_ALU_Exception_bar) (memory RegFile RegFile // memory definition name (inport write_RegFile_In MEM_WB_DestReg (WriteData) ) (outport phi3 IF_ID_SrcReg1 (Data1) ) (outport phi3 IF_ID_SrcReg2 (Data2) ) ) //Load-Interlock Logic - Based on information obtained on page A-34 of //H+P //Check if load destination register is one of the source registers //in ID ID_StallReg1 = (= IF_ID_SrcReg1 ID_EX_DestReg) ID_StallReg2 = (= IF_ID_SrcReg2 ID_EX_DestReg) //If it is in either case, we might have to stall ID_StallReg = (or ID_StallReg1 ID_StallReg2) //Check if we will be saving the result, of it it is a jump //if so we will need to stall ID_WriteResult = (or IF_ID_RegWrite IF_ID_MemWrite) ID_WriteOrJump = (or ID_WriteResult IF_ID_is_Jump) ID_WrJmpBr = (or ID_WriteOrJump IF_ID_is_Branch) ID_WrJmpBrEx = (or ID_WrJmpBr IF_ID_allow_ALU_exceptions) //Check if the result in the EX stage will be saved to both memory and //to a register file. If it will not be saved to a register, there is //no reason to stall the pipeline EX_WriteResult = (and ID_EX_RegWrite ID_EX_MemToReg) //If we will be saving the result of the op in the ID stage and the op //in the EX stage will be written to memory, we will stall ID_StallTmp = (and ID_StallReg ID_WrJmpBrEx) ID_Stall = (and ID_StallTmp EX_WriteResult) ID_Stall_bar = (not ID_Stall) //If we have to stall, we need to insert a bubble in the pipeline. //This can be done by not writing back an operation to either the //registers or the memory. We also need to handle the case when we //need to squash instructions from a branch ID_Squash_bar = (and EX_MEM_use_TargetPC_bar ID_Stall_bar) ID_MemWrite = (and IF_ID_MemWrite ID_Squash_bar) ID_RegWrite = (and IF_ID_RegWrite ID_Squash_bar) ID_is_Jump = (and IF_ID_is_Jump ID_Squash_bar) ID_is_Branch = (and IF_ID_is_Branch ID_Squash_bar) ID_allow_ALU_exceptions = (and IF_ID_allow_ALU_exceptions ID_Squash_bar) ID_is_ReturnFromException = (and IF_ID_is_ReturnFromException ID_Squash_bar) // EX Stage Logic // ============================================ //--- Define the ID/EX latch (latch ID_EX ID_EX // memory definition name (inport phi4 (IF_ID_SrcReg1 IF_ID_SrcReg2 IF_ID_DestReg IF_ID_Op ID_RegWrite Data1 Data2 IF_ID_Imm IF_ID_use_Imm ID_MemWrite IF_ID_MemToReg IF_ID_sequentialPC ID_is_Jump ID_is_Branch ID_allow_ALU_exceptions IF_ID_PC ID_is_ReturnFromException ) ) (outport phi1 (ID_EX_SrcReg1 ID_EX_SrcReg2 ID_EX_DestReg ID_EX_Op ID_EX_RegWrite ID_EX_Data1 ID_EX_Data2 ID_EX_Imm ID_EX_use_Imm ID_EX_MemWrite ID_EX_MemToReg ID_EX_sequentialPC ID_EX_is_Jump ID_EX_is_Branch ID_EX_allow_ALU_exceptions ID_EX_PC ID_EX_is_ReturnFromException ) ) ) //Forwarding Logic for Data1 //Fowarding Logic from MEM stage RegsEql_MEMD1 = (= EX_MEM_DestReg ID_EX_SrcReg1) fwd_MEMD1 = (and RegsEql_MEMD1 MEM_RegWrite) FwMux_D1 = (mux fwd_MEMD1 EX_MEM_Result WriteData) //Forwarding Logic for WB Stage RegsEql_WBD1 = (= MEM_WB_DestReg ID_EX_SrcReg1) fwd_WBD1 = (and RegsEql_WBD1 MEM_WB_RegWrite) //Select Forwarded data or New Data FwdSelector_D1 = (or fwd_MEMD1 fwd_WBD1) EX_Data1 = (mux FwdSelector_D1 FwMux_D1 ID_EX_Data1) //Forwarding Logic for Data2 //Fowarding Logic from MEM stage RegsEql_MEMD2 = (= EX_MEM_DestReg ID_EX_SrcReg2) fwd_MEMD2 = (and RegsEql_MEMD2 MEM_RegWrite) FwMux_D2 = (mux fwd_MEMD2 EX_MEM_Result WriteData) //Forwarding Logic for WB Stage RegsEql_WBD2 = (= MEM_WB_DestReg ID_EX_SrcReg2) fwd_WBD2 = (and RegsEql_WBD2 MEM_WB_RegWrite) //Select Forwarded data or New Data FwdSelector_D2 = (or fwd_MEMD2 fwd_WBD2) EX_Data2 = (mux FwdSelector_D2 FwMux_D2 ID_EX_Data2) //Select between Immediate and Register Data ALU_Data2 = (mux ID_EX_use_Imm ID_EX_Imm EX_Data2) //Destination for Store Instructions EX_DestAddr = (buf EX_Data2) //Compute ALU Result = (ALU ID_EX_Op EX_Data1 ALU_Data2) //Check for exceptions raised_ALU_Exception = (ALU_Exception ID_EX_Op EX_Data1 ALU_Data2) //Calculate Branch direction //Determine the address we are jumping to EX_TargetPC = (SelectTargetPC ID_EX_Op EX_Data1 ID_EX_sequentialPC) EX_TakeBranch = (TakeBranchALU ID_EX_Op EX_Data1 EX_DestAddr) //Check this one for validity EX_is_taken_branch = (and EX_TakeBranch ID_EX_is_Branch) EX_use_TargetPC = (or EX_is_taken_branch ID_EX_is_Jump) //Stalling is no longer an issue at this point, but we still need to be //able to squash instructions EX_Squash_bar = (buf EX_MEM_use_TargetPC_bar) EX_RegWrite = (and ID_EX_RegWrite EX_Squash_bar) EX_MemWrite = (and ID_EX_MemWrite EX_Squash_bar) EX_is_Jump = (and ID_EX_is_Jump EX_Squash_bar) EX_use_TargetPC2 = (and EX_use_TargetPC EX_Squash_bar) EX_is_ALU_Exception = (and ID_EX_allow_ALU_exceptions EX_Squash_bar) EX_is_ReturnFromException = (and ID_EX_is_ReturnFromException EX_Squash_bar) is_ALU_Exception = (and raised_ALU_Exception EX_is_ALU_Exception) // MEM Stage Logic // ============================================ //--- Define the ID/EX latch (latch EX_MEM EX_MEM // memory definition name (inport phi4 (Result ID_EX_DestReg EX_RegWrite EX_MemWrite EX_DestAddr ID_EX_Op ID_EX_MemToReg EX_TargetPC EX_is_Jump EX_use_TargetPC2 is_ALU_Exception ID_EX_PC EX_is_ReturnFromException ) ) (outport phi1 (EX_MEM_Result EX_MEM_DestReg EX_MEM_RegWrite EX_MEM_MemWrite EX_MEM_DestAddr EX_MEM_Op EX_MEM_MemToReg EX_MEM_TargetPC EX_MEM_is_Jump EX_MEM_Branch EX_MEM_is_ALU_Exception EX_MEM_PC EX_MEM_is_ReturnFromException ) ) ) EX_MEM_is_ALU_Exception_bar = (not EX_MEM_is_ALU_Exception) //--- The data memory, abstracted as a finite state machine // that does not satisfy the forwarding property of the // memory semantics write_DMem_In1 = (and phi4 MEM_MemWrite) write_DMem_In = (and write_DMem_In1 EX_MEM_is_ALU_Exception_bar) (latch DMem DMem // memory definition name (inport write_DMem_In (NextMemState) ) (outport phi1 (PresentMemState) ) ) //--- the next memory state will depend on // -PresentMemState, the present state of the data memory // -Result, the ALU Result (e.g., used as address) // -Data2, the data to be written to that address // -Op, the opcode, as specifying the type of the store // in order to be able to model byte-accesses NextMemState = (DMem_Update PresentMemState EX_MEM_Result EX_MEM_DestAddr EX_MEM_Op) //--- model a read from address Result of the Data Memory; // the opcode, Op, allows us to model byte-accesses ReadData = (DMem_Read PresentMemState EX_MEM_Result EX_MEM_Op) //Handle branching or exception EX_MEM_use_TargetPC1 = (or EX_MEM_is_ALU_Exception EX_MEM_Branch) EX_MEM_use_TargetPC = (or EX_MEM_use_TargetPC1 return_to_EPC) //its easier to work with the inverse of is_Jump. In this stage, find //out if we are jumping. If we are, we will have to squash all the //instructions in the pipeline (this is a simple implimentation) EX_MEM_use_TargetPC_bar = (not EX_MEM_use_TargetPC) //--- Architectural state for handling exceptions write_EPC1 = (and phi4 EX_MEM_is_ALU_Exception) write_EPC = (and write_EPC1 EX_MEM_is_ReturnFromException_bar) //--- Define the EPC (latch EPC EPC // memory definition name (inport write_EPC (EX_MEM_PC) ) (outport phi1 (EPC) ) ) MEM_is_ALU_Exception = (and EX_MEM_is_ReturnFromException_bar EX_MEM_is_ALU_Exception) write_IsException_a = (or EX_MEM_is_ALU_Exception EX_MEM_is_ReturnFromException) write_IsException = (and phi4 write_IsException_a) //--- Define the EPC (latch IsException IsException // memory definition name (inport write_IsException (MEM_is_ALU_Exception) ) (outport phi1 (IsException) ) ) return_to_EPC = (and EX_MEM_is_ReturnFromException IsException) //Logic to handle squashing of RFE EX_MEM_is_ReturnFromException_bar = (not EX_MEM_is_ReturnFromException) MEM_RegWrite = (and EX_MEM_RegWrite EX_MEM_is_ReturnFromException_bar) MEM_MemWrite = (and EX_MEM_MemWrite EX_MEM_is_ReturnFromException_bar) // WB Stage Logic // ============================================ (latch MEM_WB MEM_WB // memory definition name (inport phi4 (EX_MEM_DestReg MEM_RegWrite EX_MEM_Result ReadData EX_MEM_MemToReg EX_MEM_is_ALU_Exception_bar EX_MEM_is_ReturnFromException_bar ) ) (outport phi1 (MEM_WB_DestReg MEM_WB_RegWrite MEM_WB_Result MEM_WB_ReadData MEM_WB_MemToReg MEM_WB_is_ALU_Exception_bar MEM_WB_is_ReturnFromException_bar ) ) ) WriteData = (mux MEM_WB_MemToReg MEM_WB_ReadData MEM_WB_Result)