#/* $begin pipe-all-hcl */ #################################################################### # HCL Description of Control for Pipelined Y86 Processor # # Copyright (C) Randal E. Bryant, David R. O'Hallaron, 2002 # #################################################################### ## This is a solution to the single write port problem ## Overall strategy: IPOPL passes through pipe, ## treated as stack pointer increment, but not incrementing the PC ## On refetch, modify fetched icode to indicate an instruction "IPOP2", ## which reads from memory. #################################################################### # C Include's. Don't alter these # #################################################################### quote '#include ' quote '#include "isa.h"' quote '#include "pipeline.h"' quote '#include "stages.h"' quote '#include "sim.h"' quote 'int sim_main(int argc, char *argv[]);' quote 'int main(int argc, char *argv[]){return sim_main(argc,argv);}' #################################################################### # Declarations. Do not change/remove/delete any of these # #################################################################### ##### Symbolic representation of Y86 Instruction Codes ############# intsig INOP 'I_NOP' intsig IHALT 'I_HALT' intsig IRRMOVL 'I_RRMOVL' intsig IIRMOVL 'I_IRMOVL' intsig IRMMOVL 'I_RMMOVL' intsig IMRMOVL 'I_MRMOVL' intsig IOPL 'I_ALU' intsig IJXX 'I_JMP' intsig ICALL 'I_CALL' intsig IRET 'I_RET' intsig IPUSHL 'I_PUSHL' intsig IPOPL 'I_POPL' # 1W: Special instruction code for second try of popl intsig IPOP2 'I_POP2' ##### Symbolic representation of Y86 Registers referenced explicitly ##### intsig RESP 'REG_ESP' # Stack Pointer intsig RNONE 'REG_NONE' # Special value indicating "no register" ##### ALU Functions referenced explicitly ########################## intsig ALUADD 'A_ADD' # ALU should add its arguments ##### Signals that can be referenced by control logic ############## ##### Pipeline Register F ########################################## intsig F_predPC 'pc_curr->pc' # Predicted value of PC ##### Intermediate Values in Fetch Stage ########################### intsig f_icode 'if_id_next->icode' # Fetched instruction code intsig f_ifun 'if_id_next->ifun' # Fetched instruction function intsig f_valC 'if_id_next->valc' # Constant data of fetched instruction intsig f_valP 'if_id_next->valp' # Address of following instruction ## 1W: Provide access to the PC value for the current instruction intsig f_pc 'f_pc' # Address of fetched instruction ##### Pipeline Register D ########################################## intsig D_icode 'if_id_curr->icode' # Instruction code intsig D_rA 'if_id_curr->ra' # rA field from instruction intsig D_rB 'if_id_curr->rb' # rB field from instruction intsig D_valP 'if_id_curr->valp' # Incremented PC ##### Intermediate Values in Decode Stage ######################### intsig d_srcA 'id_ex_next->srca' # srcA from decoded instruction intsig d_srcB 'id_ex_next->srcb' # srcB from decoded instruction intsig d_rvalA 'd_regvala' # valA read from register file intsig d_rvalB 'd_regvalb' # valB read from register file ##### Pipeline Register E ########################################## intsig E_icode 'id_ex_curr->icode' # Instruction code intsig E_ifun 'id_ex_curr->ifun' # Instruction function intsig E_valC 'id_ex_curr->valc' # Constant data intsig E_srcA 'id_ex_curr->srca' # Source A register ID intsig E_valA 'id_ex_curr->vala' # Source A value intsig E_srcB 'id_ex_curr->srcb' # Source B register ID intsig E_valB 'id_ex_curr->valb' # Source B value intsig E_dstE 'id_ex_curr->deste' # Destination E register ID intsig E_dstM 'id_ex_curr->destm' # Destination M register ID ##### Intermediate Values in Execute Stage ######################### intsig e_valE 'ex_mem_next->vale' # valE generated by ALU boolsig e_Bch 'ex_mem_next->takebranch' # Am I about to branch? ##### Pipeline Register M ##### intsig M_icode 'ex_mem_curr->icode' # Instruction code intsig M_ifun 'ex_mem_curr->ifun' # Instruction function intsig M_valA 'ex_mem_curr->vala' # Source A value intsig M_dstE 'ex_mem_curr->deste' # Destination E register ID intsig M_valE 'ex_mem_curr->vale' # ALU E value intsig M_dstM 'ex_mem_curr->destm' # Destination M register ID boolsig M_Bch 'ex_mem_curr->takebranch' # Branch Taken flag ##### Intermediate Values in Memory Stage ########################## intsig m_valM 'mem_wb_next->valm' # valM generated by memory ##### Pipeline Register W ########################################## intsig W_icode 'mem_wb_curr->icode' # Instruction code intsig W_dstE 'mem_wb_curr->deste' # Destination E register ID intsig W_valE 'mem_wb_curr->vale' # ALU E value intsig W_dstM 'mem_wb_curr->destm' # Destination M register ID intsig W_valM 'mem_wb_curr->valm' # Memory M value #################################################################### # Control Signal Definitions. # #################################################################### ################ Fetch Stage ################################### ## What address should instruction be fetched at int f_pc = [ # Mispredicted branch. Fetch at incremented PC M_icode == IJXX && !M_Bch : M_valA; # Completion of RET instruction. W_icode == IRET : W_valM; # Default: Use predicted value of PC 1 : F_predPC; ]; # Does fetched instruction require a regid byte? bool need_regids = f_icode in { IRRMOVL, IOPL, IPUSHL, IPOPL, IPOP2, IIRMOVL, IRMMOVL, IMRMOVL }; # Does fetched instruction require a constant word? bool need_valC = f_icode in { IIRMOVL, IRMMOVL, IMRMOVL, IJXX, ICALL }; bool instr_valid = f_icode in { INOP, IHALT, IRRMOVL, IIRMOVL, IRMMOVL, IMRMOVL, IOPL, IJXX, ICALL, IRET, IPUSHL, IPOPL, IPOP2 }; # Predict next value of PC int new_F_predPC = [ f_icode in { IJXX, ICALL } : f_valC; # First time through popl. Refetch popl f_icode == IPOPL && D_icode != IPOPL: f_pc; 1 : f_valP; ]; ## W1: To split ipopl into two cycles, need to be able to ## modify fetched value of icode, so that it will be IPOP2 ## when fetched for second time. # Set code for fetched instruction int new_D_icode = [ ## Can detected refetch of ipopl, since now have ## IPOPL as icode for instruction in decode. f_icode == IPOPL && D_icode == IPOPL : IPOP2; 1 : f_icode; ]; ################ Decode Stage ###################################### ## W1: Strategy. Decoding of popl rA should be treated the same ## as would iaddl $4, %esp ## Decoding of pop2 rA treated same as mrmovl -4(%esp), rA ## What register should be used as the A source? int new_E_srcA = [ D_icode in { IRRMOVL, IRMMOVL, IOPL, IPUSHL } : D_rA; D_icode in { IPOPL, IRET } : RESP; 1 : RNONE; # Don't need register ]; ## What register should be used as the B source? int new_E_srcB = [ D_icode in { IOPL, IRMMOVL, IMRMOVL } : D_rB; D_icode in { IPUSHL, IPOPL, ICALL, IRET, IPOP2 } : RESP; 1 : RNONE; # Don't need register ]; ## What register should be used as the E destination? int new_E_dstE = [ D_icode in { IRRMOVL, IIRMOVL, IOPL} : D_rB; D_icode in { IPUSHL, IPOPL, ICALL, IRET } : RESP; 1 : RNONE; # Don't need register ]; ## What register should be used as the M destination? int new_E_dstM = [ D_icode in { IMRMOVL, IPOP2 } : D_rA; 1 : RNONE; # Don't need register ]; ## What should be the A value? ## Forward into decode stage for valA int new_E_valA = [ D_icode in { ICALL, IJXX } : D_valP; # Use incremented PC d_srcA == E_dstE : e_valE; # Forward valE from execute d_srcA == M_dstM : m_valM; # Forward valM from memory d_srcA == M_dstE : M_valE; # Forward valE from memory d_srcA == W_dstM : W_valM; # Forward valM from write back d_srcA == W_dstE : W_valE; # Forward valE from write back 1 : d_rvalA; # Use value read from register file ]; int new_E_valB = [ d_srcB == E_dstE : e_valE; # Forward valE from execute d_srcB == M_dstM : m_valM; # Forward valM from memory d_srcB == M_dstE : M_valE; # Forward valE from memory d_srcB == W_dstM : W_valM; # Forward valM from write back d_srcB == W_dstE : W_valE; # Forward valE from write back 1 : d_rvalB; # Use value read from register file ]; ################ Execute Stage ##################################### ## Select input A to ALU int aluA = [ E_icode in { IRRMOVL, IOPL } : E_valA; E_icode in { IIRMOVL, IRMMOVL, IMRMOVL } : E_valC; E_icode in { ICALL, IPUSHL, IPOP2 } : -4; E_icode in { IRET, IPOPL } : 4; # Other instructions don't need ALU ]; ## Select input B to ALU int aluB = [ E_icode in { IRMMOVL, IMRMOVL, IOPL, ICALL, IPUSHL, IRET, IPOPL, IPOP2 } : E_valB; E_icode in { IRRMOVL, IIRMOVL } : 0; # Other instructions don't need ALU ]; ## Set the ALU function int alufun = [ E_icode == IOPL : E_ifun; 1 : ALUADD; ]; ## Should the condition codes be updated? bool set_cc = E_icode == IOPL; ################ Memory Stage ###################################### ## Select memory address int mem_addr = [ M_icode in { IRMMOVL, IPUSHL, ICALL, IMRMOVL, IPOP2 } : M_valE; M_icode in { IRET } : M_valA; # Other instructions don't need address ]; ## Set read control signal bool mem_read = M_icode in { IMRMOVL, IPOP2, IRET }; ## Set write control signal bool mem_write = M_icode in { IRMMOVL, IPUSHL, ICALL }; ################ Write back stage ################################## ## 1W: For this problem, we introduce a multiplexor that merges ## valE and valM into a single value for writing to register port E. ## DO NOT CHANGE THIS LOGIC ## Merge both write back sources onto register port E int w_dstE = [ ## writing from valM W_dstM != RNONE : W_dstM; 1: W_dstE; ]; int w_valE = [ W_dstM != RNONE : W_valM; 1: W_valE; ]; ## Set so that register port M is never used. int w_dstM = RNONE; int w_valM = 0; ################ Pipeline Register Control ######################### # Should I stall or inject a bubble into Pipeline Register F? # At most one of these can be true. bool F_bubble = 0; bool F_stall = # Conditions for a load/use hazard E_icode in { IMRMOVL, IPOP2 } && E_dstM in { d_srcA, d_srcB } || # Stalling at fetch while ret passes through pipeline IRET in { D_icode, E_icode, M_icode }; # Should I stall or inject a bubble into Pipeline Register D? # At most one of these can be true. bool D_stall = # Conditions for a load/use hazard E_icode in { IMRMOVL, IPOP2 } && E_dstM in { d_srcA, d_srcB }; bool D_bubble = # Mispredicted branch (E_icode == IJXX && !e_Bch) || # Stalling at fetch while ret passes through pipeline # but not condition for a load/use hazard !(E_icode in { IMRMOVL, IPOPL } && E_dstM in { d_srcA, d_srcB }) && IRET in { D_icode, E_icode, M_icode }; # Should I stall or inject a bubble into Pipeline Register E? # At most one of these can be true. bool E_stall = 0; bool E_bubble = # Mispredicted branch (E_icode == IJXX && !e_Bch) || # Conditions for a load/use hazard E_icode in { IMRMOVL, IPOP2 } && E_dstM in { d_srcA, d_srcB}; # Should I stall or inject a bubble into Pipeline Register M? # At most one of these can be true. bool M_stall = 0; bool M_bubble = 0; #/* $end pipe-all-hcl */