📄 project2.c
字号:
return (rStation.Vj + rStation.Vk); break; case NAND: return (!(rStation.Vj & rStation.Vk)); break; case MULT: return (rStation.Vj * rStation.Vk); case LW: return (rStation.Vj + offset); //!!! CAUTION: getResult only returns an address of the LW, SW instr break; case SW: return (rStation.Vj + offset); break; case BEQ: return (statePtr->pc +1 +offset); break; default: break; }}main(int argc, char *argv[]) { FILE *filePtr; int pc, done, instr, i; char line[MAXLINELENGTH]; machineState *statePtr; int memorySize; int success, newBuf, op, halt, unit; int headRB, tailRB; int regA, regB, immed, address; int flush; int rbnum; if (argc != 2) { printf("error: usage: %s <machine-code file>\n", argv[0]); exit(1); } filePtr = fopen(argv[1], "r"); if (filePtr == NULL) { printf("error: can't open file %s", argv[1]); perror("fopen"); exit(1); } /* * Initialization, reading in program, etc. * */ /* * Allocate machine state. */ statePtr = (machineState *) malloc(sizeof(machineState)); /* * Read in the entire machine-code file into memory */ for (i=0; i<MEMSIZE; i++){ statePtr->memory[i] = 0; } pc = 0; done = 0; while (!done){ if (fgets(line, MAXLINELENGTH, filePtr) == NULL){ done = 1; } else { if (sscanf(line, "%d", &instr) != 1) { printf("error in reading address %d\n", pc); exit(1); } statePtr->memory[pc] = instr; statePtr->issue[pc] = -1; statePtr->rs[pc] = -1; statePtr->rega[pc] = -1; statePtr->regb[pc] = -1; statePtr->exe[pc] = -1; statePtr->write[pc] = -1; printInstruction(instr); pc = pc + 1; } } memorySize = pc; /* * Initialize state by giving state pc = 0, regFile[0:7] = 0, reservation.[0-11] = 0, */ for (i=0; i<NUMREGS; i++){ statePtr->regFile[i] = 0; } for (i=0; i<NUMUNITS+1; i++){ /* reservation[0-11] = 0 */ statePtr->reservation[i].busy = 0; statePtr->reservation[i].instr = -1; statePtr->reservation[i].Vj = -1; statePtr->reservation[i].Vk = -1; statePtr->reservation[i].Qj = -1; statePtr->reservation[i].Qk = -1; statePtr->reservation[i].exTimeLeft = -1; statePtr->reservation[i].reorderNum = -1; } for (i=0; i<RBSIZE; i++){ /* reorderBuf[0-4].busy = 0, headRB = tailRB = -1; */ statePtr->reorderBuf[i].busy = 0; statePtr->reorderBuf[i].instrStatus = -1; statePtr->reorderBuf[i].instr = -1; statePtr->reorderBuf[i].execUnit = -1; statePtr->reorderBuf[i].valid = -1; statePtr->reorderBuf[i].result = -1; statePtr->reorderBuf[i].storeAddress = -1; } for (i=0; i<NUMREGS; i++){ /* all regResult[0:8] are valid */ statePtr->regResult[i].valid = 1; statePtr->regResult[i].result = statePtr->regFile[i]; } statePtr->pc = 0; statePtr->cycles = 0; /************ Process instructions ***************/ while (statePtr->cycles < 33) { printState(statePtr, memorySize); /* * Decide whether to flush or commit instruction * at head of reorder buffer queue. * Check whether instruction at head queue can commit. * If not, flush reorder buffer, reservation stations * and register result status data structures. * Our default way of dealing with branches and jumps is * to predict not taken; if our prediction was wrong, * we flush everything. newPC = branch or jump target * If no flush, change state here: * On a register access, change regFile * On a store, change memory * When done with flush or commit, don't forget to free up * the reorder buffer and update the head pointer for the queue. * Done with commit. * Check all instructions in reservation stations. * Perform required actions for the following states: * For Writing Result State: * Be sure to update waiting reservation stations and * to put the result in temporary storage in the reorder buffer * At this point, free up the reservation station. * Change status to committing. */ for( i=0; i <RBSIZE; i++ ) { if( statePtr->reorderBuf[i].instrStatus == WRITINGRESULT ) { if(opcode(statePtr->reorderBuf[i].instr) == HALT) { printf("machine halted after %d\n", statePtr->cycles); exit(0); } if(opcode(statePtr->reorderBuf[i].instr) == ADD || opcode(statePtr->reorderBuf[i].instr) == NAND || opcode(statePtr->reorderBuf[i].instr) == MULT) { statePtr->regResult[statePtr->reorderBuf[i].storeAddress].result = statePtr->reorderBuf[i].result; statePtr->regFile[statePtr->reorderBuf[i].storeAddress] = statePtr->regResult[statePtr->reorderBuf[i].storeAddress].result; statePtr->regResult[statePtr->reorderBuf[i].storeAddress].valid = 1; updateRes(i, statePtr, statePtr->reorderBuf[i].result); //update all waitting reservation station } if(opcode(statePtr->reorderBuf[i].instr) == LW ) { statePtr->regResult[statePtr->reorderBuf[i].storeAddress].result = statePtr->reorderBuf[i].result; statePtr->regFile[statePtr->reorderBuf[i].storeAddress] = statePtr->regResult[statePtr->reorderBuf[i].storeAddress].result; statePtr->regResult[statePtr->reorderBuf[i].storeAddress].valid = 1; updateRes(i, statePtr, statePtr->reorderBuf[i].result); } if(opcode(statePtr->reorderBuf[i].instr) == SW ) { statePtr->memory[statePtr->reorderBuf[i].storeAddress] = statePtr->reorderBuf[i].result; } if(opcode(statePtr->reorderBuf[i].instr) == BEQ ) { } statePtr->reservation[statePtr->reorderBuf[i].execUnit].busy = 0; //empty reservation station statePtr->reservation[statePtr->reorderBuf[i].execUnit].Vj = -1; statePtr->reservation[statePtr->reorderBuf[i].execUnit].Qj = -1; statePtr->reservation[statePtr->reorderBuf[i].execUnit].Vk = -1; statePtr->reservation[statePtr->reorderBuf[i].execUnit].Qk = -1; statePtr->reservation[statePtr->reorderBuf[i].execUnit].reorderNum = -1; statePtr->reorderBuf[i].busy = 0; } } /* * For Executing State: * Decrement execution time. * When execution complete, change state to writingresult */ for( i=0; i <RBSIZE; i++ ) { if( statePtr->reorderBuf[i].instrStatus == EXECUTING ) { if (opcode(statePtr->reorderBuf[i].instr) == NOOP || opcode(statePtr->reorderBuf[i].instr) == HALT ) statePtr->reorderBuf[i].instrStatus = WRITINGRESULT; else { statePtr->reservation[statePtr->reorderBuf[i].execUnit].exTimeLeft = statePtr->reservation[statePtr->reorderBuf[i].execUnit].exTimeLeft - 1; if( statePtr->reservation[statePtr->reorderBuf[i].execUnit].exTimeLeft <= 0 ) { if(opcode(statePtr->reorderBuf[i].instr) == LW ) { //getResult() return the memory address for LW or SW statePtr->reorderBuf[i].result = statePtr->memory[getResult(statePtr->reservation[statePtr->reorderBuf[i].execUnit], statePtr)]; } if(opcode(statePtr->reorderBuf[i].instr) == SW ) { //getResult() return the actual register/memory address for LW or SW statePtr->reorderBuf[i].storeAddress = getResult(statePtr->reservation[statePtr->reorderBuf[i].execUnit], statePtr); //store register result into memory statePtr->reorderBuf[i].result = statePtr->regResult[field_rb(statePtr->reorderBuf[i].instr)].result; } if(opcode(statePtr->reorderBuf[i].instr) == BEQ ) { statePtr->reorderBuf[i].result = getResult(statePtr->reservation[statePtr->reorderBuf[i].execUnit], statePtr); if( statePtr->reservation[statePtr->reorderBuf[i].execUnit].Vj == statePtr->reservation[statePtr->reorderBuf[i].execUnit].Vk ) statePtr->pc = statePtr->reorderBuf[i].result; } if(opcode(statePtr->reorderBuf[i].instr) == ADD || opcode(statePtr->reorderBuf[i].instr) == NAND || opcode(statePtr->reorderBuf[i].instr) == MULT) { //getResult() return the actual value of ADD NAND or MULT statePtr->reorderBuf[i].result = getResult(statePtr->reservation[statePtr->reorderBuf[i].execUnit], statePtr); } statePtr->reorderBuf[i].instrStatus = WRITINGRESULT; } } } } /* * For Issuing State: * Check whether operands are available; if so, change * status to executing. */ for( i=0; i <RBSIZE; i++ ) { if( statePtr->reorderBuf[i].instrStatus == ISSUING ) { if( opcode(statePtr->reorderBuf[i].instr) == LW && statePtr->reservation[statePtr->reorderBuf[i].execUnit].Vj != -1 ) { //statePtr->reservation[statePtr->reorderBuf[i].execUnit].Qj = -1; statePtr->reorderBuf[i].instrStatus = EXECUTING; } else if(statePtr->reservation[statePtr->reorderBuf[i].execUnit].Vj != -1 && // here we only execute a instr when both Vj and Vk are available statePtr->reservation[statePtr->reorderBuf[i].execUnit].Vk != -1 ) { // statePtr->reservation[statePtr->reorderBuf[i].execUnit].Qj = -1; //statePtr->reservation[statePtr->reorderBuf[i].execUnit].Qk = -1; statePtr->reorderBuf[i].instrStatus = EXECUTING; } else if( opcode(statePtr->reorderBuf[i].instr) == NOOP || opcode(statePtr->reorderBuf[i].instr) == HALT ) statePtr->reorderBuf[i].instrStatus = EXECUTING; } } /* * Finally, when we have dealt with all instructions in the * reservations stations, we check whether we can issue * a new instruction or not. * First check for free reservation station * If reservation station was found, then look for a free * reorder buffer. * If both available reservation station and reorder buffer, * issue instruction. * * Only 1 BEQ can be issued into queue * * */ int instruction; instruction = statePtr->memory[statePtr->pc]; int unit; int reorderNum; if (opcode(instruction) == HALT) { issueInstr(instruction, 12, statePtr, 0); statePtr->rs[statePtr->pc] = unit; statePtr->issue[statePtr->pc] = statePtr->cycles; statePtr->pc = statePtr->pc +1; } else { if(( -1 != (unit = checkReservation(statePtr,instruction))) && (-1 != (reorderNum = (checkReorder(statePtr, instruction)) )) ) { //reservation station is free issueInstr(instruction, unit, statePtr, reorderNum); statePtr->issue[statePtr->pc] = statePtr->cycles; statePtr->rs[statePtr->pc] = unit; statePtr->pc = statePtr->pc +1; } } /* * Increment cycle counter */ statePtr->cycles = statePtr->cycles+ 1; } /* while (1) */ printf("machine halted\n"); printf("Total Cycles: %d\n", statePtr->cycles); printf("FETCHED:%d\n",pc); printf("RETIRED: %d\n",pc); printf("BRANCHES:\n"); printf("MISPRED: \n"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -