/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { md_inst_t inst; register md_addr_t addr; enum md_opcode op; register int is_write; enum md_fault_type fault; // conditional-branch offset bits int offbits = 0; int twoscompl = 0; unsigned int abs_offbits = 0; // number of bits changed in a GPR int bits_changed; int dst_reg; // destination register in part 3 fprintf(stderr, "sim: ** starting functional simulation **\n"); /* set up initial default next PC */ regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); // initialize all the arrays init_arrays(); while (TRUE) { /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ /* get the next instruction to execute */ MD_FETCH_INST(inst, mem, regs.regs_PC); /* keep an instruction count */ sim_num_insn++; /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ dst_reg = O1; \ if(dst_reg > 0 && dst_reg < NUM_REGS) prev_val[dst_reg] = regs.regs_R[dst_reg]; \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); if (verbose) { myfprintf(stderr, "%10n [xor: 0x%08x] @ 0x%08p: ", sim_num_insn, md_xor_regs(®s), regs.regs_PC); md_print_insn(inst, regs.regs_PC, stderr); if (MD_OP_FLAGS(op) & F_MEM) myfprintf(stderr, " mem: 0x%08p", addr); fprintf(stderr, "\n"); /* fflush(stderr); */ } // for registers 0-31 determine the new value written to dst_reg if(dst_reg > 0 && dst_reg < NUM_REGS){ bits_changed = func_bits_chng(prev_val[dst_reg], regs.regs_R[dst_reg]); reg_contents[dst_reg] += bits_changed; num_inst_chng_bits++; } if(MD_OP_FLAGS(op) & F_COND) { g_total_cond_branches++; // increment histogram index with corresp. offset bits offbits = (regs.regs_TPC - regs.regs_PC)/8; // absolute value representation of the offbits abs_offbits = abs(regs.regs_TPC - regs.regs_PC)/8; if(offbits < 0){ // if offset is negative, simply add one bit (the signed bit) to its absolute value // this is equivalent to offbits = ceil(log10(-1*offbits)/log10(2) + 1); (trust me, I've tried it) offbits = floor(log10(abs_offbits)/log10(2) + 2) + 1; }else{ offbits = floor(log10(abs_offbits)/log10(2) + 2); } histogram[offbits]++; } if(MD_OP_FLAGS(op) & F_DIRJMP) { g_total_uncond_branches++; } if((MD_OP_FLAGS(op) & F_FCOMP) || (MD_OP_FLAGS(op) & F_FPCOND)) { g_total_fp_inst++; } if(MD_OP_FLAGS(op) & F_STORE) { g_total_store_inst++; } if(MD_OP_FLAGS(op) & F_LOAD) { g_total_ld_inst++; } if(MD_OP_FLAGS(op) & F_IMM) { g_total_imm_inst++; } if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } /* go to the next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); /* finish early? */ if (max_insts && sim_num_insn >= max_insts){ return; } } }
void do_id() { de.inst = buf.fd.inst; MD_SET_OPCODE(de.opcode, de.inst); de.NPC = buf.fd.NPC; md_inst_t inst = de.inst; switch (de.opcode) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3)\ case OP:\ de.instFlags = FLAGS;\ de.oprand.out1 = O1;\ de.oprand.out2 = O2;\ de.oprand.in1 = I1;\ de.oprand.in2 = I2;\ de.oprand.in3 = I3;\ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) #define CONNECT(OP) #include "machine.def" } de.oprand.cons.imm = IMM; de.oprand.cons.target = TARG; de.oprand.cons.shamt = SHAMT; de.reg1_data = GPR(de.oprand.in1); de.reg2_data = GPR(de.oprand.in2); de.reg3_data = GPR(de.oprand.in3); // Decide execution control signals switch (de.opcode) { #define DEFCONTROL(OP, ALUSRC1, ALUSRC2, ALUOP, REGDST, BRH_TYPE) \ case OP: \ de.ex_ctrl.ALUSrc1 = ALUSRC1; \ de.ex_ctrl.ALUSrc2 = ALUSRC2; \ de.ex_ctrl.ALUOp = ALUOP; \ de.ex_ctrl.RegDst = REGDST; \ de.mem_ctrl.Branch = BRH_TYPE; \ break; #include "pipe.def" default: panic("instruction not supported"); } de.mem_ctrl.MemRead = (de.instFlags & F_MEM) && (de.instFlags & F_LOAD); de.mem_ctrl.MemWrite = (de.instFlags & F_MEM) && (de.instFlags & F_STORE); de.wb_ctrl.RegWrite = de.ex_ctrl.RegDst != DST_NO_DST; de.wb_ctrl.MemtoReg = de.mem_ctrl.MemRead && de.wb_ctrl.RegWrite; fetch_sgn.bubble_for_decode = (de.instFlags & F_CTRL) && (de.instFlags & F_UNCOND); }
/* load program into simulated state */ void sim_load_prog(char *fname, /* program to load */ int argc, char **argv, /* program arguments */ char **envp) /* program environment */ { /* load program text and data, set up environment, memory, and regs */ ld_load_prog(fname, argc, argv, envp, ®s, mem, TRUE); #ifdef TARGET_ALPHA /* pre-decode text segment */ { unsigned i, num_insn = (ld_text_size + 3) / 4; fprintf(stderr, "** pre-decoding %u insts...", num_insn); /* allocate decoded text space */ dec = mem_create("dec"); for (i=0; i < num_insn; i++) { enum md_opcode op; md_inst_t inst; md_addr_t PC; /* compute PC */ PC = ld_text_base + i * sizeof(md_inst_t); /* get instruction from memory */ MD_FETCH_INST(inst, mem, PC); /* decode the instruction */ MD_SET_OPCODE(op, inst); /* insert into decoded opcode space */ MEM_WRITE_WORD(dec, PC << 1, (word_t)op); MEM_WRITE_WORD(dec, (PC << 1)+sizeof(word_t), inst); } fprintf(stderr, "done\n"); } #endif /* TARGET_ALPHA */ }
void print_instruction( inst_t *x ) { enum md_opcode op; if( x == NULL ) { printf( " *** bubble ***\n" ); return; } printf("%8u:", x->uid); MD_SET_OPCODE(op, x->inst); if( MD_OP_FLAGS(x->op) & F_LOAD ) { printf( "L " ); } else if( MD_OP_FLAGS(x->op) & F_CTRL ) { printf( "B" ); if( x->taken ) printf( "T " ); else printf( "N " ); } else printf( " " ); printf("0x%6x ", x->pc ); md_print_insn( x->inst, x->pc, stdout ); if( x->stalled ) printf(" *** stalled *** "); printf("\n"); // add other interesting information you want to see }
void decode(void) { md_inst_t inst; register md_addr_t addr; enum md_opcode op; register int is_write; enum md_fault_type fault; int i; int i1, i2, i3, o1, o2; inst_t *pI = g_piperegister[IF_ID_REGISTER]; if( g_piperegister[ID_EX_REGISTER] != NULL ) return; // stall if( pI == NULL ) return; // bubble if( !pI->stalled ) { // BEGIN FUNCTIONAL EXECUTION --> assert( pI->pc == regs.regs_PC ); /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; inst = pI->inst; /* keep an instruction count */ sim_num_insn++; /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); pI->op = op; /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ i1 = I1; i2 = I2; i3 = I3; o1 = O1; o2 = O2; \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); if (verbose) { myfprintf(stderr, "%10n [xor: 0x%08x] @ 0x%08p: ", sim_num_insn, md_xor_regs(®s), regs.regs_PC); md_print_insn(inst, regs.regs_PC, stderr); if (MD_OP_FLAGS(op) & F_MEM) myfprintf(stderr, " mem: 0x%08p", addr); fprintf(stderr, "\n"); /* fflush(stderr); */ } if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } /* go to the next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); // <--- END FUNCTIONAL EXECUTION // record correct next instruction address (use for branches/jumps) pI->next_pc = regs.regs_PC; // record dependencies on instructions already in the pipeline pI->src[0] = g_raw[i1]; pI->src[1] = g_raw[i2]; pI->src[2] = g_raw[i3]; // record which register(s) this instruction writes to if( o1 != DNA ) g_raw[o1] = pI; if( o2 != DNA ) g_raw[o2] = pI; pI->dst[0] = o1; pI->dst[1] = o2; // determine instruction type if( MD_OP_FLAGS(op) & F_CTRL ) pI->taken = (regs.regs_PC != (pI->pc+sizeof(md_inst_t))); } // check for RAW hazard for ( i=0; i < 3; ++i ) { // for each potential source operand... if ( pI->src[i] != NULL ) { if( pI->src[i]->donecycle > sim_cycle ) { // src[i] has not written to register file this cycle or earlier pI->stalled = 1; return; } } } if( pI->taken ) { g_fetch_redirected = 1; g_target_pc = pI->next_pc; } // move instruction from IF/ID to ID/EX register... pI->stalled = 0; pI->status = DECODED; g_piperegister[ID_EX_REGISTER] = pI; // move to ID/EX register g_piperegister[IF_ID_REGISTER] = NULL; }
/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { md_inst_t inst; register md_addr_t addr, target_PC = 0; enum md_opcode op; register int is_write; int stack_idx; enum md_fault_type fault; fprintf(stderr, "sim: ** starting functional simulation w/ predictors **\n"); /* set up initial default next PC */ SET_NPC(CPC + sizeof(md_inst_t)); /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0)) dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC, sim_num_insn, ®s, mem); while (TRUE) { /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* get the next instruction to execute */ MD_FETCH_INST(inst, mem, regs.regs_PC); /* keep an instruction count */ sim_num_insn++; /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } if (MD_OP_FLAGS(op) & F_CTRL) { md_addr_t pred_PC; struct bpred_update_t update_rec; sim_num_branches++; if (pred) { /* get the next predicted fetch address */ pred_PC = bpred_lookup( pred, regs.regs_PC, // branch addr target_PC, // target addr op, // instruction opcode MD_IS_CALL(op), // call? MD_IS_RETURN(op), // return? &update_rec, // stack an update ptr &stack_idx); // stash return stack ptr /* valid address returned from branch predictor? */ if (!pred_PC) { /* no predicted taken target, attempt not taken target */ pred_PC = regs.regs_PC + sizeof(md_inst_t); } bpred_update( pred, CPC, // branch addr NPC, // resolved branch target NPC != CPC + sizeof(md_inst_t), // taken? pred_PC != CPC + sizeof(md_inst_t), // pred taken? pred_PC == NPC, // correct pred? op, // opcode &update_rec); // predictor update pointer } } /* check for DLite debugger entry condition */ if (dlite_check_break(NPC, is_write ? ACCESS_WRITE : ACCESS_READ, addr, sim_num_insn, sim_num_insn)) { dlite_main(regs.regs_PC, NPC, sim_num_insn, ®s, mem); } /* go to the next instruction */ UPDATE_PC /* finish early? */ if (max_insts && sim_num_insn >= max_insts) return; } }
/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { md_inst_t inst; register md_addr_t addr; enum md_opcode op; register int is_write; enum md_fault_type fault; fprintf(stderr, "sim: ** starting functional simulation **\n"); /* ECE552 Pre-Assignment - BEGIN CODE*/ int r_out[2], r_in[3]; /* ECE552 Pre-Assignment - END CODE*/ /* set up initial default next PC */ regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_PC, /* !access */0, /* addr */0, 0, 0)) dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC, sim_num_insn, ®s, mem); while (TRUE) { /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ /* get the next instruction to execute */ MD_FETCH_INST(inst, mem, regs.regs_PC); /* keep an instruction count */ sim_num_insn++; /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); /* execute the instruction */ switch (op) { /* ECE552 Pre-Assignment - BEGIN CODE*/ #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ r_out[0] = (O1); r_out[1] = (O2); \ r_in[0] = (I1); r_in[1] = (I2); r_in[2] = (I3); \ SYMCAT(OP,_IMPL); \ break; /* ECE552 Pre-Assignment - END CODE*/ #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } /* ECE552 Pre-Assignment - BEGIN CODE*/ if ( (MD_OP_FLAGS(op) & F_MEM) && (MD_OP_FLAGS(op) & F_LOAD) ) { sim_num_loads++; } { int i; for (i = 0; i < 3; i++) { if (r_in[i] != DNA && reg_ready [r_in [i]] > sim_num_insn) { if ((i == 0) && (MD_OP_FLAGS(op) & F_MEM) && (MD_OP_FLAGS(op) & F_STORE)) { continue; } sim_num_lduh++; break; } } } if ((MD_OP_FLAGS(op) & F_MEM) && (MD_OP_FLAGS(op) & F_LOAD)) { if (r_out[0] != DNA) reg_ready[r_out[0]] = sim_num_insn + 2; if (r_out[1] != DNA) reg_ready[r_out[1]] = sim_num_insn + 2; } /* ECE552 Pre-Assignment - END CODE*/ if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); if (verbose) { myfprintf(stderr, "%10n [xor: 0x%08x] @ 0x%08p: ", sim_num_insn, md_xor_regs(®s), regs.regs_PC); md_print_insn(inst, regs.regs_PC, stderr); if (MD_OP_FLAGS(op) & F_MEM) myfprintf(stderr, " mem: 0x%08p", addr); fprintf(stderr, "\n"); /* fflush(stderr); */ } if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_NPC, is_write ? ACCESS_WRITE : ACCESS_READ, addr, sim_num_insn, sim_num_insn)) dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, ®s, mem); /* go to the next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); /* finish early? */ if (max_insts && sim_num_insn >= max_insts) return; } }
void do_id() { de.inst = fd.inst; if(de.inst.a == NOP){ return; } MD_SET_OPCODE(de.opcode, de.inst); de.PC = fd.PC; md_inst_t inst = de.inst; #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3)\ if (OP==de.opcode){\ de.oprand.out1 = O1;\ de.oprand.out2 = O2;\ de.oprand.in1 = I1;\ de.oprand.in2 = I2;\ de.oprand.in3 = I3;\ goto READ_OPRAND_VALUE;\ } #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) #define CONNECT(OP) #include "machine.def" READ_OPRAND_VALUE: de.Jump = 0; de.Target = 0; de.RegisterRs = RS; de.RegisterRt = RT; de.RegisterRd = RD; de.ReadData1 = GPR(de.RegisterRs); de.ReadData2 = GPR(de.RegisterRt); de.Shamt = 0; de.ExtendedImm = UIMM; de.RegDst = 0; de.RegWrite = 0; de.MemRead = 0; de.MemWrite = 0; de.MemtoReg = 0; de.Branch = 0; de.Latch = 0; /* The setting of the control lines is completely determined by the opcode fields * With reference to SimpleScalarToolSet Ver2.0*/ switch(de.opcode){ case ADD: de.Branch = 0; de.RegDst = 1; de.MemtoReg = 0; de.RegWrite = 1; de.MemRead = 0; de.MemWrite = 0; break; case ADDU: de.Branch = 0; de.RegDst = 1; de.MemtoReg = 0; de.RegWrite = 1; de.MemRead = 0; de.MemWrite = 0; break; case SUBU: de.Branch = 0; de.RegDst = 1; de.MemtoReg = 0; de.RegWrite = 1; de.MemRead = 0; de.MemWrite = 0; break; case ADDIU: de.Branch = 0; de.RegDst = 0; de.MemtoReg = 0; de.RegWrite = 1; de.MemRead = 0; de.MemWrite = 0; de.ExtendedImm = IMM; break; case ANDI: de.Branch = 0; de.RegDst = 0; de.MemtoReg = 0; de.RegWrite = 1; de.MemRead = 0; de.MemWrite = 0; de.ExtendedImm = IMM; break; case BNE: de.RegWrite = 0; de.MemRead = 0; de.MemWrite = 0; de.Branch = 1; /*Stall the pipeline, a little differect from insert "nop"*/ de.Latch = 1; de.ExtendedImm = OFS; break; case JUMP: de.Branch = 0; de.RegWrite = 0; de.MemRead = 0; de.MemWrite = 0; de.Jump = 1; de.Target = (de.PC & 0xF0000000)|(TARG<<2); break; case LUI: de.Branch = 0; de.RegDst = 0; de.RegWrite = 1; de.ExtendedImm = UIMM << 16; break; case LW: de.Branch = 0; de.RegDst = 0; de.RegWrite = 1; de.ExtendedImm = OFS; de.MemRead = 1; de.MemtoReg = 1; break; case SLL: de.Branch = 0; de.RegDst = 1; de.RegWrite = 1; de.Shamt = SHAMT; break; case SW: de.Branch = 0; de.RegWrite = 0; de.MemRead = 0; de.MemWrite = 1; de.ExtendedImm = IMM; break; case SLTI: de.Branch = 0; de.RegDst = 0; /* With regard to this instruction, the SimpleScalar Tool Set is WRONG. It should be SET_GPR(RT,(GPR(RS)<IMM)?1:0)*/ de.MemRead = 0; de.RegWrite = 1; de.ExtendedImm = IMM; break; } }
/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { md_inst_t inst; register md_addr_t addr, target_PC; enum md_opcode op; register int is_write; int stack_idx; enum md_fault_type fault; int out1, out2, in1, in2, in3; /* register names */ int v_out1, v_out2, v_in1, v_in2, v_in3;/* register values */ int vl_out1, vl_out2, vl_in1, vl_in2, vl_in3; md_addr_t addr_dispatch; /* access_address */ int m_size; /* access_size */ FILE *stream; md_addr_t predicted_PC; fprintf(stderr, "sim: ** starting functional simulation w/ predictors **\n"); /* set up initial default next PC */ regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0)) dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC, sim_num_insn, ®s, mem); while (TRUE) { /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ /* get the next instruction to execute */ mem_access(mem, Read, regs.regs_PC, &inst, sizeof(md_inst_t)); /* keep an instruction count */ sim_num_insn++; /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,CLASS,O1,O2,I1,I2,I3, \ VO1,LO1,VO2,LO2,ADDR,VI1,LI1,VI2,LI2,VI3,LI3,M_Size) \ case OP: \ in1 = I1; in2 = I2; in3 = I3; \ v_in1 = VI1; v_in2 = VI2; v_in3 = VI3; \ vl_in1 = LI1; vl_in2 = LI2; vl_in3 = LI3; \ SYMCAT(OP,_IMPL); \ out1 = O1; out2 = O2; \ v_out1 = VO1; v_out2 = VO2; \ vl_out1 = LO1; vl_out2 = LO2; \ addr_dispatch = ADDR; \ m_size = M_Size; \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "operand.def" default: panic("attempted to execute a bogus opcode"); } if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } if (MD_OP_FLAGS(op) & F_CTRL) { md_addr_t pred_PC; struct bpred_update_t update_rec; sim_num_branches++; if (pred) { /* get the next predicted fetch address */ pred_PC = bpred_lookup(pred, /* branch addr */regs.regs_PC, /* target */target_PC, /* inst opcode */op, /* call? */MD_IS_CALL(op), /* return? */MD_IS_RETURN(op), /* stash an update ptr */&update_rec, /* stash return stack ptr */&stack_idx); /* valid address returned from branch predictor? */ if (!pred_PC) { /* no predicted taken target, attempt not taken target */ pred_PC = regs.regs_PC + sizeof(md_inst_t); } bpred_update(pred, /* branch addr */regs.regs_PC, /* resolved branch target */regs.regs_NPC, /* taken? */regs.regs_NPC != (regs.regs_PC + sizeof(md_inst_t)), /* pred taken? */pred_PC != (regs.regs_PC + sizeof(md_inst_t)), /* correct pred? */pred_PC == regs.regs_NPC, /* opcode */op, /* predictor update pointer */&update_rec); } predicted_PC = pred_PC; } /* ここから下を見ればどの変数に何が入っているか分かるはず。 */ stream = stdout; fprintf(stream, "############################################################ \n"); fprintf(stream, " --- trace count(%d) \n", (int)sim_num_insn); fprintf(sim_fd, "%s, inst: `", fprintf(stream, " opcode: %s, inst: `", MD_OP_NAME(op)); md_print_insn(inst, regs.regs_PC, stream); fprintf(stream, "'\n"); myfprintf(stream, " PC: 0x%08p, NPC: 0x%08p", regs.regs_PC, regs.regs_NPC); if(pred) myfprintf(stream, " (pred_PC: 0x%08p)\n", regs.regs_PC, regs.regs_NPC, predicted_PC); else myfprintf(stream, "\n"); fprintf(stream," | in(r%02d,r%02d,r%02d),out(r%02d,r%02d),\n", in1, in2, in3, out1, out2); fprintf(stream," | IN(%8x,%8x,%8x),OUT(%8x,%8x)addr(%8x)|\n", v_in1, v_in2, v_in3, v_out1, v_out2, addr_dispatch); /* ダブルワードだった場合,この変数がセットされる */ fprintf(stream," | in(%8x,%8x,%8x),out(%8x,%8x) |\n", vl_in1, vl_in2, vl_in3, vl_out1, vl_out2); /* machine.h をみるとopから命令の種類を判別する方法が分かる。以下は例 */ if (op == MD_NOP_OP) { fprintf(stream, " NOP instruction \n"); } else if (MD_OP_FLAGS(op) & F_MEM) { fprintf(stream, " MEMORY instruction \n"); if (MD_OP_FLAGS(op) & F_STORE) fprintf(stream, " store instruction \n"); else if (MD_OP_FLAGS(op) & F_LOAD) fprintf(stream, " load instruction \n"); fprintf(stream, " ld/st address is %010x\n", addr_dispatch); fprintf(stream, " ld/st size is %2d\n", m_size); /* ロードストアがバイト単位なのか,ワード単位なのか, ハーフワード単位なのかは,opを見て判断できる。 例えば, md_op2name[op] が "sh"ならハーフワードである。 しかし、これだと面倒なのでoperand.defを改良した方が良い かも知れない。これはおまかせ。 */ /* ロードストアの詳細に関しては,machine.def を参照。 例えば,store halfの場合,(machine.def をエディタで開いて "sh"と言う文字列をサーチすれば該当箇所が見つかる) 以下のようにかかれている。*/ /* #define SH_IMPL { half_t _src; enum md_fault_type _fault; _src = (half_t)(word_t)GPR(RT); WRITE_HALF(_src, GPR(BS) + OFS, _fault); if (_fault != md_fault_none) DECLARE_FAULT(_fault); } */ /*ここで、GPR(BS)はBS番レジスタの値 OFS はオフセットを示す。 そして,GPR(RT)はRT番レジスタの値を示す。 そしてWRITE_HALF(_src, GPR(BS) + OFS, _fault);は 値 _src をアドレス GPR(BS) + OFS に書き込む事を意味する。 書き込みのサイズは,halfワードである。*/ } else if (MD_OP_FLAGS(op) & F_CTRL) { fprintf(stream, " BRANCH instruction \n"); if (MD_IS_CALL(op)) fprintf(stream, " function call \n"); else if (MD_IS_RETURN(op)) fprintf(stream, " function return \n"); else if (MD_IS_INDIR(op)) fprintf(stream, " indirect jump \n"); else if ((MD_OP_FLAGS(op) & (F_CTRL|F_DIRJMP)) == (F_CTRL|F_DIRJMP)) fprintf(stream, " direct jump \n"); } else { fprintf(stream, " other instruction \n"); } /* この応用として,いきなりopからstoreを判別するには,以下のようにすれば良い*/ if ((MD_OP_FLAGS(op) & (F_MEM|F_STORE)) == (F_MEM|F_STORE)) { /*fprintf(stream, " store instruction \n");*/ } else if ((MD_OP_FLAGS(op) & (F_MEM|F_LOAD)) == (F_MEM|F_LOAD)) { /*fprintf(stream, " load instruction \n");*/ } /* ここまで */ /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_NPC, is_write ? ACCESS_WRITE : ACCESS_READ, addr, sim_num_insn, sim_num_insn)) dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, ®s, mem); /* go to the next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); /* finish early? */ if (max_insts && sim_num_insn >= max_insts) return; } }
/* disassemble a SimpleScalar instruction */ void md_print_insn(md_inst_t inst, /* instruction to disassemble */ md_addr_t pc, /* addr of inst, used for PC-rels */ FILE *stream) /* output stream */ { enum md_opcode op; /* use stderr as default output stream */ if (!stream) stream = stderr; /* decode the instruction, assumes predecoded text segment */ MD_SET_OPCODE(op, inst); /* disassemble the instruction */ if (op == OP_NA || op >= OP_MAX) { /* bogus instruction */ fprintf(stream, "<invalid inst: 0x%08x:%08x>", inst.a, inst.b); } else { char *s; fprintf(stream, "%-10s", MD_OP_NAME(op)); s = MD_OP_FORMAT(op); while (*s) { switch (*s) { case 'd': fprintf(stream, "r%d", RD); break; case 's': fprintf(stream, "r%d", RS); break; case 't': fprintf(stream, "r%d", RT); break; case 'b': fprintf(stream, "r%d", BS); break; case 'D': fprintf(stream, "f%d", FD); break; case 'S': fprintf(stream, "f%d", FS); break; case 'T': fprintf(stream, "f%d", FT); break; case 'j': fprintf(stream, "0x%x", (pc + 8 + (OFS << 2))); break; case 'o': case 'i': fprintf(stream, "%d", IMM); break; case 'H': fprintf(stream, "%d", SHAMT); break; case 'u': fprintf(stream, "%u", UIMM); break; case 'U': fprintf(stream, "0x%x", UIMM); break; case 'J': fprintf(stream, "0x%x", ((pc & 036000000000) | (TARG << 2))); break; case 'B': fprintf(stream, "0x%x", BCODE); break; #if 0 /* FIXME: obsolete... */ case ')': /* handle pre- or post-inc/dec */ if (SS_COMP_OP == SS_COMP_NOP) fprintf(stream, ")"); else if (SS_COMP_OP == SS_COMP_POST_INC) fprintf(stream, ")+"); else if (SS_COMP_OP == SS_COMP_POST_DEC) fprintf(stream, ")-"); else if (SS_COMP_OP == SS_COMP_PRE_INC) fprintf(stream, ")^+"); else if (SS_COMP_OP == SS_COMP_PRE_DEC) fprintf(stream, ")^-"); else if (SS_COMP_OP == SS_COMP_POST_DBL_INC) fprintf(stream, ")++"); else if (SS_COMP_OP == SS_COMP_POST_DBL_DEC) fprintf(stream, ")--"); else if (SS_COMP_OP == SS_COMP_PRE_DBL_INC) fprintf(stream, ")^++"); else if (SS_COMP_OP == SS_COMP_PRE_DBL_DEC) fprintf(stream, ")^--"); else panic("bogus SS_COMP_OP"); break; #endif default: /* anything unrecognized, e.g., '.' is just passed through */ fputc(*s, stream); } s++; } } }
/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { md_inst_t inst; register md_addr_t addr; enum md_opcode op; register int is_write; enum md_fault_type fault; fprintf(stderr, "sim: ** starting functional simulation **\n"); /* set up initial default next PC */ regs.regs_PC = ld_text_base; regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_PC, /* !access */0, /* addr */0, 0, 0)) dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC, sim_num_insn, ®s, mem); while (TRUE) { /* maintain $r0 semantics */ #ifndef TARGET_ARM regs.regs_R[MD_REG_ZERO] = 0; #endif #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ if (regs.regs_PC >= ld_text_bound) { info("all instructions decoded..."); exit(0); } /* get the next instruction to execute */ MD_FETCH_INST(inst, mem, regs.regs_PC); /* keep an instruction count */ sim_num_insn++; /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); #if 0 /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3,I4) \ case OP: \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); #endif if (verbose) { myfprintf(stderr, "%10n [xor: 0x%08x] @ 0x%08p: ", sim_num_insn, md_xor_regs(®s), regs.regs_PC); md_print_insn(inst, regs.regs_PC, stderr); if (MD_OP_FLAGS(op) & F_MEM) myfprintf(stderr, " mem: 0x%08p", addr); fprintf(stderr, "\n"); myfprintf(stderr, " op: %d, inst: 0x%08x\n", op, inst); /* fflush(stderr); */ } if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_NPC, is_write ? ACCESS_WRITE : ACCESS_READ, addr, sim_num_insn, sim_num_insn)) dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, ®s, mem); /* go to the next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); /* finish early? */ if (max_insts && sim_num_insn >= max_insts) return; } }
/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { md_inst_t inst; register md_addr_t addr, target_PC; enum md_opcode op; register int is_write; int stack_idx; enum md_fault_type fault; int setPC, in_flow = FALSE, flow_index, nflow; struct md_uop_t flowtab[MD_MAX_FLOWLEN]; fprintf(stderr, "sim: ** starting functional simulation w/ predictors **\n"); /* set up initial default next PC */ regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); /* synchronize register files... */ regs.regs_R[MD_REG_PC] = regs.regs_PC; /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0)) dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC, sim_num_insn, ®s, mem); while (TRUE) { /* maintain $r0 semantics */ #ifndef TARGET_ARM regs.regs_R[MD_REG_ZERO] = 0; #endif #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; if (!in_flow) { /* keep an instruction count */ sim_num_insn++; /* get the next instruction to execute */ MD_FETCH_INST(inst, mem, regs.regs_PC); /* decode the instruction */ MD_SET_OPCODE(op, inst); if (MD_OP_FLAGS(op) & F_CISC) { /* get instruction flow */ nflow = md_get_flow(op, inst, flowtab); if (nflow > 0) { in_flow = TRUE; flow_index = 0; } else fatal("could not locate CISC flow"); sim_num_uops += nflow; } else sim_num_uops++; } if (in_flow) { op = flowtab[flow_index].op; inst = flowtab[flow_index++].inst; if (flow_index == nflow) in_flow = FALSE; } if (op == NA) panic("bogus opcode detected @ 0x%08p", regs.regs_PC); if (MD_OP_FLAGS(op) & F_CISC) panic("CISC opcode decoded"); setPC = 0; regs.regs_R[MD_REG_PC] = regs.regs_PC; /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,O3,I1,I2,I3,I4) \ case OP: \ SYMCAT(OP,_IMPL); \ break; #define DEFUOP(OP,NAME,OPFORM,RES,FLAGS,O1,O2,O3,I1,I2,I3,I4) \ case OP: \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); if (setPC != 0/* regs.regs_R[MD_REG_PC] != regs.regs_PC */) regs.regs_NPC = regs.regs_R[MD_REG_PC]; if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } if (MD_OP_FLAGS(op) & F_CTRL) { md_addr_t pred_PC; struct bpred_update_t update_rec; sim_num_branches++; if (pred) { /* get the next predicted fetch address */ pred_PC = bpred_lookup(pred, /* branch addr */regs.regs_PC, /* target */target_PC, /* inst opcode */op, /* call? */MD_IS_CALL(op), /* return? */MD_IS_RETURN(op), /* stash an update ptr */&update_rec, /* stash return stack ptr */&stack_idx); /* valid address returned from branch predictor? */ if (!pred_PC) { /* no predicted taken target, attempt not taken target */ pred_PC = regs.regs_PC + sizeof(md_inst_t); } bpred_update(pred, /* branch addr */regs.regs_PC, /* resolved branch target */regs.regs_NPC, /* taken? */regs.regs_NPC != (regs.regs_PC + sizeof(md_inst_t)), /* pred taken? */pred_PC != (regs.regs_PC + sizeof(md_inst_t)), /* correct pred? */pred_PC == regs.regs_NPC, /* opcode */op, /* predictor update pointer */&update_rec); } } /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_NPC, is_write ? ACCESS_WRITE : ACCESS_READ, addr, sim_num_insn, sim_num_insn)) dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, ®s, mem); /* go to the next instruction */ if (!in_flow) { regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); } /* finish early? */ if (max_insts && sim_num_insn >= max_insts) return; } }
/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { #ifdef USE_JUMP_TABLE /* the jump table employs GNU GCC label extensions to construct an array of pointers to instruction implementation code, the simulator then uses the table to lookup the location of instruction's implementing code, a GNU GCC `goto' extension is then used to jump to the inst's implementing code through the op_jump table; as a result, there is no need for a main simulator loop, which eliminates one branch from the simulator interpreter - crazy, no!?!? */ /* instruction jump table, this code is GNU GCC specific */ static void *op_jump[/* max opcodes */] = { &&opcode_NA, /* NA */ #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ &&opcode_##OP, #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ &&opcode_##OP, #define CONNECT(OP) #include "machine.def" }; #endif /* USE_JUMP_TABLE */ /* register allocate instruction buffer */ register md_inst_t inst; /* decoded opcode */ register enum md_opcode op; fprintf(stderr, "sim: ** starting *fast* functional simulation **\n"); /* must have natural byte/word ordering */ if (sim_swap_bytes || sim_swap_words) fatal("sim: *fast* functional simulation cannot swap bytes or words"); #ifdef USE_JUMP_TABLE regs.regs_NPC = regs.regs_PC; /* load instruction */ MD_FETCH_INST(inst, mem, regs.regs_NPC); /* jump to instruction implementation */ MD_SET_OPCODE(op, inst); goto *op_jump[op]; #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ opcode_##OP: \ /* maintain $r0 semantics */ \ regs.regs_R[MD_REG_ZERO] = 0; \ ZERO_FP_REG(); \ \ /* keep an instruction count */ \ INC_INSN_CTR(); \ \ /* locate next instruction */ \ regs.regs_PC = regs.regs_NPC; \ \ /* set up default next PC */ \ regs.regs_NPC += sizeof(md_inst_t); \ \ /* execute the instruction */ \ SYMCAT(OP,_IMPL); \ \ /* get the next instruction */ \ MD_FETCH_INST(inst, mem, regs.regs_NPC); \ \ /* jump to instruction implementation */ \ MD_SET_OPCODE(op, inst); \ goto *op_jump[op]; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ opcode_##OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { /* uncaught... */break; } #include "machine.def" opcode_NA: panic("attempted to execute a bogus opcode"); /* should not get here... */ panic("exited sim-fast main loop"); #else /* !USE_JUMP_TABLE */ /* set up initial default next PC */ regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); while (TRUE) { /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ /* keep an instruction count */ #ifndef NO_INSN_COUNT sim_num_insn++; #endif /* !NO_INSN_COUNT */ #ifdef TARGET_ALPHA /* load predecoded instruction */ op = (enum md_opcode)__UNCHK_MEM_READ(dec, regs.regs_PC << 1, word_t); inst = __UNCHK_MEM_READ(dec, (regs.regs_PC << 1)+sizeof(word_t), md_inst_t); #else /* !TARGET_ALPHA */ /* load instruction */ MD_FETCH_INST(inst, mem, regs.regs_PC); /* decode the instruction */ MD_SET_OPCODE(op, inst); #endif /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { /* uncaught... */break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } /* execute next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); } #endif /* USE_JUMP_TABLE */ }
/* disassemble an Alpha instruction */ void md_print_insn(md_inst_t inst, /* instruction to disassemble */ md_addr_t pc, /* addr of inst, used for PC-rels */ FILE *stream) /* output stream */ { enum md_opcode op; /* use stderr as default output stream */ if (!stream) stream = stderr; /* decode the instruction, assumes predecoded text segment */ MD_SET_OPCODE(op, inst); /* disassemble the instruction */ if (op <= OP_NA || op >= OP_MAX) { /* bogus instruction */ fprintf(stream, "<invalid inst: 0x%08x>", inst); } else { char *s; fprintf(stream, "%-10s", MD_OP_NAME(op)); s = MD_OP_FORMAT(op); while (*s) { switch (*s) { case 'a': fprintf(stream, "r%d", RA); break; case 'b': fprintf(stream, "r%d", RB); break; case 'c': fprintf(stream, "r%d", RC); break; case 'A': fprintf(stream, "f%d", RA); break; case 'B': fprintf(stream, "f%d", RB); break; case 'C': fprintf(stream, "f%d", RC); break; case 'o': fprintf(stream, "%d", (sword_t)SEXT(OFS)); break; case 'j': myfprintf(stream, "0x%p", pc + (SEXT(OFS) << 2) + 4); break; case 'J': myfprintf(stream, "0x%p", pc + (SEXT21(TARG) << 2) + 4); break; case 'i': fprintf(stream, "%d", (word_t)IMM); break; default: /* anything unrecognized, e.g., '.' is just passed through */ fputc(*s, stream); } s++; } } }
/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { md_inst_t inst; register md_addr_t addr; enum md_opcode op; register bool_t is_write; enum md_fault_type fault; /* set up initial default next PC */ regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_PC, /* !access */0, /* addr */0, 0, 0)) dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC, sim_num_insn, ®s, mem); /* fast forward simulator loop, performs functional simulation for FASTFWD_COUNT insts, then turns on performance (timing) simulation */ if (fastfwd_count > 0) { int icount; fprintf(stderr, "sim: ** fast forwarding %d insts **\n", fastfwd_count); fastfwding = TRUE; for (icount=0; icount < fastfwd_count; icount++) { /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ /* get the next instruction to execute */ inst = __UNCHK_MEM_READ(mem, regs.regs_PC, md_inst_t); /* set default reference address */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #undef DECLARE_FAULT #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); /* update memory access stats */ if (MD_OP_FLAGS(op) & F_MEM) { if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_NPC, is_write ? ACCESS_WRITE : ACCESS_READ, addr, sim_num_insn, sim_num_insn)) dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, ®s, mem); /* go to the next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); } } fastfwding = FALSE; if (trace_fd != NULL) { fprintf(stderr, "sim: writing EIO file initial checkpoint...\n"); if (eio_write_chkpt(®s, mem, trace_fd) != -1) panic("checkpoint code is broken"); } fprintf(stderr, "sim: ** starting functional simulation **\n"); /* set up initial default next PC */ regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); while (TRUE) { /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ /* check if checkpoint should be generated here... */ if (chkpt_active && !range_cmp_range1(&chkpt_range, regs.regs_NPC, sim_num_insn, sim_num_insn)) { fprintf(stderr, "sim: writing checkpoint file `%s' @ inst %.0f...\n", chkpt_fname, (double)sim_num_insn); /* write the checkpoint file */ eio_write_chkpt(®s, mem, chkpt_fd); /* close the checkpoint file */ eio_close(chkpt_fd); /* exit jumps to the target set in main() */ longjmp(sim_exit_buf, /* exitcode + fudge */0+1); } /* get the next instruction to execute */ inst = __UNCHK_MEM_READ(mem, regs.regs_PC, md_inst_t); /* keep an instruction count */ sim_num_insn++; /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("bogus opcode"); } if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_NPC, is_write ? ACCESS_WRITE : ACCESS_READ, addr, sim_num_insn, sim_num_insn)) dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, ®s, mem); /* go to the next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); /* finish early? */ if (max_insts && sim_num_insn >= max_insts) return; } }
/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { md_inst_t inst; register md_addr_t addr; enum md_opcode op; register int is_write; enum md_fault_type fault; /* ECE552 Assignment 1 - BEGIN CODE */ int r_in[3], r_out[2]; /* ECE552 Assignment 1 - END CODE */ fprintf(stderr, "sim: ** starting functional simulation **\n"); /* set up initial default next PC */ regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_PC, /* !access */0, /* addr */0, 0, 0)) dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC, sim_num_insn, ®s, mem); while (TRUE) { /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ /* get the next instruction to execute */ MD_FETCH_INST(inst, mem, regs.regs_PC); /* keep an instruction count */ sim_num_insn++; /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ r_out[0] = (O1); r_out[1] = (O2); \ r_in[0] = (I1); r_in[1] = (I2); r_in[2] = (I3); \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } /* ECE552 Assignment 1 - BEGIN CODE */ /* ECE552 Part 1 */ int i, counter_q1 = 0, counter_q2 = 0, counter_q3 = 0; for (i = 0; i < 3; i++) { if (r_in[i] != DNA && reg_ready_q1[r_in[i]] > sim_num_insn) { int cycle = reg_ready_q1[r_in[i]] - sim_num_insn; if (cycle == 1) { counter_q1++; } else if (cycle == 2) { counter_q1 = counter_q1 + 2; } //reset the register reg_ready_q1[r_in[i]] = DNA; } } if (counter_q1 == 1) { sim_num_one_cycle_hazard_q1++; } else if (counter_q1 >= 2) { sim_num_two_cycle_hazard_q1++; } if (r_out[0] != DNA) { reg_ready_q1[r_out[0]] = sim_num_insn + 3; } if (r_out[1] != DNA) { reg_ready_q1[r_out[1]] = sim_num_insn + 3; } sim_num_RAW_hazard_q1 = sim_num_one_cycle_hazard_q1 + sim_num_two_cycle_hazard_q1; /* ECE552 Part 2*/ for (i = 0; i < 3; i++) { if (r_in[i] != DNA && reg_ready_q2[r_in[i]] > sim_num_insn) { if ((i == 0) && (MD_OP_FLAGS(op) & F_MEM) && (MD_OP_FLAGS(op) & F_STORE)) { continue; } int cycle = reg_ready_q2[r_in[i]] - sim_num_insn; if (cycle == 1) { counter_q2++; } else if (cycle == 2) { counter_q2 = counter_q2 + 2; } //reset the register reg_ready_q2[r_in[i]] = DNA; } } if (counter_q2 == 1) { sim_num_one_cycle_hazard_q2++; } else if (counter_q2 >= 2) { sim_num_two_cycle_hazard_q2++; } if ((MD_OP_FLAGS(op) & F_MEM) && (MD_OP_FLAGS(op) & F_LOAD)) { if (r_out[0] != DNA) { reg_ready_q2[r_out[0]] = sim_num_insn + 3; } if (r_out[1] != DNA) { reg_ready_q2[r_out[1]] = sim_num_insn + 3; } } else if (!(MD_OP_FLAGS(op) & F_MEM)) { if (r_out[0] != DNA) { reg_ready_q2[r_out[0]] = sim_num_insn + 2; } if (r_out[1] != DNA) { reg_ready_q2[r_out[1]] = sim_num_insn + 2; } } sim_num_RAW_hazard_q2 = sim_num_one_cycle_hazard_q2 + sim_num_two_cycle_hazard_q2; /* ECE552 Part 3 */ if ((MD_OP_FLAGS(op) & F_MEM) && (MD_OP_FLAGS(op) & F_LOAD)) { is_current_load = true; } else if (!(MD_OP_FLAGS(op) & F_MEM) && (MD_OP_FLAGS(op) & F_LOAD)) { is_previous_load = false; } if (!(MD_OP_FLAGS(op) & F_LOAD)) { for (i = 0; i < 2; i++) { if (r_out[i] != DNA && reg_ready_q3[r_out[i]] > sim_num_insn) { int cycle = reg_ready_q3[r_out[i]] - sim_num_insn; if (cycle == 1) { //two cycle stall for non mem instruction if (is_current_load == true && is_current_load == true) { sim_num_two_cycle_hazard_q3++; } else { sim_num_one_cycle_hazard_q3++; } } else if (cycle == 2) { sim_num_two_cycle_hazard_q3++; } reg_ready_q3[r_out[i]] = DNA; counter_q3 = 1; } } if(counter_q3 == 0 && (r_out[0] != DNA || r_out[1] != DNA)) { if(is_current_load && is_previous_load && write_back_ready == sim_num_insn + 1) { sim_num_structural_hazard_q3 = sim_num_structural_hazard_q3 + 2; } else if(write_back_ready == sim_num_insn) { sim_num_structural_hazard_q3++; } } } if ((MD_OP_FLAGS(op) & F_MEM) && (MD_OP_FLAGS(op) & F_LOAD)) { if (r_out[0] != DNA) { reg_ready_q3[r_out[0]] = sim_num_insn + 3; } if (r_out[1] != DNA) { reg_ready_q3[r_out[1]] = sim_num_insn + 3; } write_back_ready = sim_num_insn + 2; is_previous_load = true; } else if (!(MD_OP_FLAGS(op) & F_MEM) && (MD_OP_FLAGS(op) & F_LOAD)) { is_previous_load = false; } sim_num_WAW_hazard_q3 = sim_num_one_cycle_hazard_q3 + sim_num_two_cycle_hazard_q3; /* ECE552 Assignment 1 - END CODE */ if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); if (verbose) { myfprintf(stderr, "%10n [xor: 0x%08x] @ 0x%08p: ", sim_num_insn, md_xor_regs(®s), regs.regs_PC); md_print_insn(inst, regs.regs_PC, stderr); if (MD_OP_FLAGS(op) & F_MEM) myfprintf(stderr, " mem: 0x%08p", addr); fprintf(stderr, "\n"); /* fflush(stderr); */ } if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_NPC, is_write ? ACCESS_WRITE : ACCESS_READ, addr, sim_num_insn, sim_num_insn)) dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, ®s, mem); /* go to the next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); /* finish early? */ if (max_insts && sim_num_insn >= max_insts) return; } }
/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { int i; md_inst_t inst; register md_addr_t addr; register int is_write; enum md_opcode op; unsigned int flags; enum md_fault_type fault; fprintf(stderr, "sim: ** starting functional simulation **\n"); /* set up initial default next PC */ regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0)) dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC, sim_num_insn, ®s, mem); while (TRUE) { /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ /* get the next instruction to execute */ mem_access(mem, Read, regs.regs_PC, &inst, sizeof(md_inst_t)); if (verbose) { myfprintf(stderr, "%10n @ 0x%08p: ", sim_num_insn, regs.regs_PC); md_print_insn(inst, regs.regs_PC, stderr); fprintf(stderr, "\n"); /* fflush(stderr); */ } /* keep an instruction count */ sim_num_insn++; /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } /* * profile this instruction */ flags = MD_OP_FLAGS(op); if (prof_ic) { enum inst_class_t ic; /* compute instruction class */ if (flags & F_LOAD) ic = ic_load; else if (flags & F_STORE) ic = ic_store; else if (flags & F_UNCOND) ic = ic_uncond; else if (flags & F_COND) ic = ic_cond; else if (flags & F_ICOMP) ic = ic_icomp; else if (flags & F_FCOMP) ic = ic_fcomp; else if (flags & F_TRAP) ic = ic_trap; else panic("instruction has no class"); /* update instruction class profile */ stat_add_sample(ic_prof, (int)ic); } if (prof_inst) { /* update instruction profile */ stat_add_sample(inst_prof, (int)op - /* skip NA */1); } if (prof_bc) { enum branch_class_t bc; /* compute instruction class */ if (flags & F_CTRL) { if ((flags & (F_CALL|F_DIRJMP)) == (F_CALL|F_DIRJMP)) bc = bc_call_dir; else if ((flags & (F_CALL|F_INDIRJMP)) == (F_CALL|F_INDIRJMP)) bc = bc_call_indir; else if ((flags & (F_UNCOND|F_DIRJMP)) == (F_UNCOND|F_DIRJMP)) bc = bc_uncond_dir; else if ((flags & (F_UNCOND|F_INDIRJMP))== (F_UNCOND|F_INDIRJMP)) bc = bc_uncond_indir; else if ((flags & (F_COND|F_DIRJMP)) == (F_COND|F_DIRJMP)) bc = bc_cond_dir; else if ((flags & (F_COND|F_INDIRJMP)) == (F_COND|F_INDIRJMP)) bc = bc_cond_indir; else panic("branch has no class"); /* update instruction class profile */ stat_add_sample(bc_prof, (int)bc); } } if (prof_am) { enum md_amode_type am; /* update addressing mode pre-probe FSM */ MD_AMODE_PREPROBE(op, fsm); /* compute addressing mode */ if (flags & F_MEM) { /* compute addressing mode */ MD_AMODE_PROBE(am, op, fsm); /* update the addressing mode profile */ stat_add_sample(am_prof, (int)am); /* addressing mode pre-probe FSM, after all loads and stores */ MD_AMODE_POSTPROBE(fsm); } } if (prof_seg) { if (flags & F_MEM) { /* update instruction profile */ stat_add_sample(seg_prof, (int)bind_to_seg(addr)); } } if (prof_tsyms) { int tindex; /* attempt to bind inst address to a text segment symbol */ sym_bind_addr(regs.regs_PC, &tindex, /* !exact */FALSE, sdb_text); if (tindex >= 0) { if (tindex > sym_ntextsyms) panic("bogus text symbol index"); stat_add_sample(tsym_prof, tindex); } /* else, could not bind to a symbol */ } if (prof_dsyms) { int dindex; if (flags & F_MEM) { /* attempt to bind inst address to a text segment symbol */ sym_bind_addr(addr, &dindex, /* !exact */FALSE, sdb_data); if (dindex >= 0) { if (dindex > sym_ndatasyms) panic("bogus data symbol index"); stat_add_sample(dsym_prof, dindex); } /* else, could not bind to a symbol */ } } if (prof_taddr) { /* add regs_PC exec event to text address profile */ stat_add_sample(taddr_prof, regs.regs_PC); } /* update any stats tracked by PC */ for (i=0; i<pcstat_nelt; i++) { counter_t newval; int delta; /* check if any tracked stats changed */ newval = STATVAL(pcstat_stats[i]); delta = newval - pcstat_lastvals[i]; if (delta != 0) { stat_add_samples(pcstat_sdists[i], regs.regs_PC, delta); pcstat_lastvals[i] = newval; } } /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_NPC, is_write ? ACCESS_WRITE : ACCESS_READ, addr, sim_num_insn, sim_num_insn)) dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, ®s, mem); /* go to the next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); /* finish early? */ if (max_insts && sim_num_insn >= max_insts) return; } }
/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { int i; md_inst_t inst; register md_addr_t addr; enum md_opcode op; register int is_write; enum md_fault_type fault; fprintf(stderr, "sim: ** starting functional simulation w/ caches **\n"); /* set up initial default next PC */ regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_PC, /* no access */0, /* addr */0, 0, 0)) dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC, sim_num_insn, ®s, mem); while (TRUE) { /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ /* get the next instruction to execute */ if (itlb) cache_access(itlb, Read, IACOMPRESS(regs.regs_PC), NULL, ISCOMPRESS(sizeof(md_inst_t)), 0, NULL, NULL, 0); if (cache_il1) cache_access(cache_il1, Read, IACOMPRESS(regs.regs_PC), NULL, ISCOMPRESS(sizeof(md_inst_t)), 0, NULL, NULL, 0); MD_FETCH_INST(inst, mem, regs.regs_PC); /* keep an instruction count */ sim_num_insn++; /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } /* update any stats tracked by PC */ for (i=0; i < pcstat_nelt; i++) { counter_t newval; int delta; /* check if any tracked stats changed */ newval = STATVAL(pcstat_stats[i]); delta = newval - pcstat_lastvals[i]; if (delta != 0) { stat_add_samples(pcstat_sdists[i], regs.regs_PC, delta); pcstat_lastvals[i] = newval; } } /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_NPC, is_write ? ACCESS_WRITE : ACCESS_READ, addr, sim_num_insn, sim_num_insn)) dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, ®s, mem); /* go to the next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); /* finish early? */ if (max_insts && sim_num_insn >= max_insts) return; } }
/* start simulation, program loaded, processor precise state initialized */ void sim_main(void) { md_inst_t inst; register md_addr_t addr; enum md_opcode op; register int is_write; enum md_fault_type fault; /* ECE552 Assignment 2 - BEGIN CODE */ int i, j; /* Initialization of tables */ for (i = 0; i < 4096; i++) { two_bit_table[i] = n; } for (i = 0; i < 8; i++) { for (j = 0; j < 64; j++) { PHT[i][j] = n; } } for (i = 0; i < 32; i++) { for (j = 0; j < 1024; j++) { GPHT[i][j] = n; } } /* ECE552 Assignment 2 - END CODE */ fprintf(stderr, "sim: ** starting functional simulation **\n"); /* set up initial default next PC */ regs.regs_NPC = regs.regs_PC + sizeof(md_inst_t); /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_PC, /* !access */0, /* addr */0, 0, 0)) dlite_main(regs.regs_PC - sizeof(md_inst_t), regs.regs_PC, sim_num_insn, ®s, mem); while (TRUE) { /* maintain $r0 semantics */ regs.regs_R[MD_REG_ZERO] = 0; #ifdef TARGET_ALPHA regs.regs_F.d[MD_REG_ZERO] = 0.0; #endif /* TARGET_ALPHA */ /* get the next instruction to execute */ MD_FETCH_INST(inst, mem, regs.regs_PC); /* keep an instruction count */ sim_num_insn++; /* set default reference address and access mode */ addr = 0; is_write = FALSE; /* set default fault - none */ fault = md_fault_none; /* decode the instruction */ MD_SET_OPCODE(op, inst); /* execute the instruction */ switch (op) { #define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \ case OP: \ SYMCAT(OP,_IMPL); \ break; #define DEFLINK(OP,MSK,NAME,MASK,SHIFT) \ case OP: \ panic("attempted to execute a linking opcode"); #define CONNECT(OP) #define DECLARE_FAULT(FAULT) \ { fault = (FAULT); break; } #include "machine.def" default: panic("attempted to execute a bogus opcode"); } /* ECE552 Assignment 2 - BEGIN CODE */ if (MD_OP_FLAGS(op) & F_COND) { int index = (regs.regs_PC >> 3) & 0xfff; int bht_index = (regs.regs_PC >> 6) & 0x1ff; int pht_index = (regs.regs_PC >> 3) & 0x7; int pht_row_index = BHT[bht_index]; int gap_pht_index = (regs.regs_PC >> 3) & 0x1f; int g_pht_row_index = GHR; if (regs.regs_NPC == regs.regs_PC + sizeof(md_inst_t)) { br_taken = 0; sim_num_mispred_static++; } else { br_taken = 1; } /* two bit saturation branch predictor */ switch(two_bit_table[index]) { case N: if (br_taken) { two_bit_table[index] = n; sim_num_mispred_2bitsat++; } break; case n: if (br_taken) { two_bit_table[index] = t; sim_num_mispred_2bitsat++; } else { two_bit_table[index] = N; } break; case t: if (br_taken) { two_bit_table[index] = T; } else { two_bit_table[index] = n; sim_num_mispred_2bitsat++; } break; case T: if (!br_taken) { two_bit_table[index] = t; sim_num_mispred_2bitsat++; } break; } /* two level adaptive branch predictor */ switch(PHT[pht_index][pht_row_index]) { case N: if (br_taken) { PHT[pht_index][pht_row_index] = n; BHT[bht_index] = ((BHT[bht_index] << 1) & 0x3f) | 0x1; sim_num_mispred_2level++; } else { BHT[bht_index] = ((BHT[bht_index] << 1) & 0x3f); } break; case n: if (br_taken) { PHT[pht_index][pht_row_index] = t; BHT[bht_index] = ((BHT[bht_index] << 1) & 0x3f) | 0x1; sim_num_mispred_2level++; } else { PHT[pht_index][pht_row_index] = N; BHT[bht_index] = ((BHT[bht_index] << 1) & 0x3f); } break; case t: if (br_taken) { PHT[pht_index][pht_row_index] = T; BHT[bht_index] = ((BHT[bht_index] << 1) & 0x3f) | 0x1; } else { PHT[pht_index][pht_row_index] = n; BHT[bht_index] = ((BHT[bht_index] << 1) & 0x3f); sim_num_mispred_2level++; } break; case T: if (br_taken) { BHT[bht_index] = ((BHT[bht_index] << 1) & 0x3f) | 0x1; } else { PHT[pht_index][pht_row_index] = t; BHT[bht_index] = ((BHT[bht_index] << 1) & 0x3f); sim_num_mispred_2level++; } break; } /* open ended branch predictor */ switch(GPHT[gap_pht_index][g_pht_row_index]) { case N: if (br_taken) { GPHT[gap_pht_index][g_pht_row_index] = n; GHR = ((GHR << 1) & 0x3ff) | 0x1; sim_num_mispred_openend++; } else { GHR = ((GHR << 1) & 0x3ff); } break; case n: if (br_taken) { GPHT[gap_pht_index][g_pht_row_index] = t; GHR = ((GHR << 1) & 0x3ff) | 0x1; sim_num_mispred_openend++; } else { GPHT[gap_pht_index][g_pht_row_index] = N; GHR = ((GHR << 1) & 0x3ff); } break; case t: if (br_taken) { GPHT[gap_pht_index][g_pht_row_index] = T; GHR = ((GHR << 1) & 0x3ff) | 0x1; } else { GPHT[gap_pht_index][g_pht_row_index] = n; GHR = ((GHR << 1) & 0x3ff); sim_num_mispred_openend++; } break; case T: if (br_taken) { GHR = ((GHR << 1) & 0x3ff) | 0x1; } else { GPHT[gap_pht_index][g_pht_row_index] = t; GHR = ((GHR << 1) & 0x3ff); sim_num_mispred_openend++; } break; } sim_num_br++; } /* ECE552 Assignment 2 - END CODE */ if (fault != md_fault_none) fatal("fault (%d) detected @ 0x%08p", fault, regs.regs_PC); if (verbose) { myfprintf(stderr, "%10n [xor: 0x%08x] @ 0x%08p: ", sim_num_insn, md_xor_regs(®s), regs.regs_PC); md_print_insn(inst, regs.regs_PC, stderr); if (MD_OP_FLAGS(op) & F_MEM) myfprintf(stderr, " mem: 0x%08p", addr); fprintf(stderr, "\n"); /* fflush(stderr); */ } if (MD_OP_FLAGS(op) & F_MEM) { sim_num_refs++; if (MD_OP_FLAGS(op) & F_STORE) is_write = TRUE; } /* check for DLite debugger entry condition */ if (dlite_check_break(regs.regs_NPC, is_write ? ACCESS_WRITE : ACCESS_READ, addr, sim_num_insn, sim_num_insn)) dlite_main(regs.regs_PC, regs.regs_NPC, sim_num_insn, ®s, mem); /* go to the next instruction */ regs.regs_PC = regs.regs_NPC; regs.regs_NPC += sizeof(md_inst_t); /* finish early? */ if (max_insts && sim_num_insn >= max_insts) return; }