📄 issue.c
字号:
/* * issue.c -- * * This file contains issue engines for different DLX processors. * * This file is part of DISC. It was written by Yinong Zhang * (yinong@ecn.purdue.edu) * */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "dlx.h"#define getcolor(x) Colors[(x) & 0x000f]char *operationNames[] = { "NOP", "ADD", "ADDI", "ADDU", "ADDUI", "AND", "ANDI", "BEQZ", "BFPF", "BFPT", "BNEZ", "J", "JAL", "JALR", "JR", "LB", "LBU", "LD", "LF", "LH", "LHI", "LHU", "LW", "MOVD", "MOVF", "MOVFP2I", "MOVI2FP", "MOVI2S", "MOVS2I", "OR", "ORI", "RFE", "SB", "SD", "SEQ", "SEQI", "SEQU", "SEQUI", "SF", "SGE", "SGEI", "SGEU", "SGEUI", "SGT", "SGTI", "SGTU", "SGTUI", "SH", "SLE", "SLEI", "SLEU", "SLEUI", "SLL", "SLLI", "SLT", "SLTI", "SLTU", "SLTUI", "SNE", "SNEI", "SNEU", "SNEUI", "SRA", "SRAI", "SRL", "SRLI", "SUB", "SUBI", "SUBU", "SUBUI", "SW", "TRAP", "XOR", "XORI", "", "", "", "","", "", /* There must be at least one empty string between the last integer operation * and the first floating point operation. */ "ADDD", "ADDF", "CVTD2F", "CVTD2I", "CVTF2D", "CVTF2I", "CVTI2D", "CVTI2F", "DIV", "DIVD", "DIVF", "DIVU", "EQD", "EQF", "GED", "GEF", "GTD", "GTF", "LED", "LEF", "LTD", "LTF", "MULT", "MULTD", "MULTF", "MULTU", "NED", "NEF", "SUBD", "SUBF", "" };char *Units[] = {" Int1 ", " Int2 ", " Int3 ", " Int4 ", " Int5 ", " Int6 ", " Int7 ", " Int8 "," Add1 ", " Add2 ", " Add3 ", " Add4 ", " Add5 ", " Add6 ", " Add7 ", " Add8 ", " Div1 ", " Div2 ", " Div3 ", " Div4 "," Div5 ", " Div6 ", " Div7 ", " Div8 "," Mult1", " Mult2", " Mult3", " Mult4"," Mult5", " Mult6", " Mult7", " Mult8", " Load1", " Load2", " Load3", " Load4", " Load5", " Load6", " Load7", " Load8"};char *Colors[] ={"Goldenrod ", "SlateBlue ", "Red ", "Purple ","Turquoise ", "Blue ", "LightSeaGreen ", "IndianRed ","Magenta ", "VioletRed ", "YellowGreen ", "DeepSkyBlue ","HotPink ", "SaddleBrown ", "DarkSeaGreen ", "Maroon "}; char *functionTypes[] = {"int", "add", "div", "mul", "load", "store"}; /* * Forward declarations for procedures defined later in this file: */static void GenEightBit(char *);static Op *WhichOp(DLX *, int);static Op *mallocOp(DLX *);static Update *mallocUpdate(DLX *);static Bypass *mallocBypass(DLX *);static void BypassInsert(DLX *, int, int, int); static void GenUpdateStruct(DLX *, char *, int, int, int, int, char *, char *, char *, char *, char *);static voidGenEightBit(str) char *str;{ char temp[20]; int i; int len; temp[0] = '\0'; len = strlen(str); for (i = 0; i < (7 - len)/2.0; i++) strcat(temp, " "); strcat(temp, str); for (i = 0; i < (8 - len)/2.0; i++) strcat(temp, " "); temp[8] = '\0'; strcpy(str, temp);}static voidGenUpdateStruct(machPtr, w, displayLater, actionType, displayCycle, readyCycle, part1, part2, part3, part4, part5) DLX *machPtr; /* Machine description. */ char *w; int displayLater; int actionType; int displayCycle; int readyCycle; char *part1; char *part2; char *part3; char *part4; char *part5;{ Update *updatePtr, *uPtr; if (!displayLater) { Tcl_SetVar(machPtr->interp, "msg", part1, TCL_GLOBAL_ONLY); switch (actionType) { case INSERT_HIGHLIGHT: Tcl_VarEval(machPtr->interp, "InsertAndHighLight ", w, "$msg", (char *)NULL); break; case HIGHLIGHT_CODE: Tcl_VarEval(machPtr->interp, "HighLightCodeLine ", "$msg", (char *)NULL); break; case DELETE_INSERT: Tcl_VarEval(machPtr->interp, "DeleteAndInsert ", w, "$msg", (char *)NULL); break; case ADD_END: Tcl_VarEval(machPtr->interp, "AddToEnd ", w, "$msg", (char *)NULL); break; case SHOW_LINE: goto InsertList; } return; } InsertList: updatePtr = mallocUpdate(machPtr); strcpy(updatePtr->w, w); updatePtr->actionType = actionType; updatePtr->displayCycle = displayCycle; updatePtr->readyCycle = readyCycle; strcpy(updatePtr->msg, part1); strcat(updatePtr->msg, part2); strcat(updatePtr->msg, part3); strcat(updatePtr->msg, part4); strcat(updatePtr->msg, part5); if (machPtr->updateList == NULL || updatePtr->displayCycle < machPtr->updateList->displayCycle) { updatePtr->nextPtr = machPtr->updateList; machPtr->updateList = updatePtr; } else { for (uPtr = machPtr->updateList; uPtr->nextPtr != NULL; uPtr = uPtr->nextPtr) if (updatePtr->displayCycle < uPtr->nextPtr->displayCycle) break; updatePtr->nextPtr = uPtr->nextPtr; uPtr->nextPtr = updatePtr; }}Op *Isu_Issue(machPtr, wordPtr, unitType, rs1Type, rs2Type, rdType) DLX *machPtr; /* Machine description. */ MemWord *wordPtr; int unitType; int rs1Type; int rs2Type; int rdType;{ Op *opPtr, *opPtr2; int i,j; int wait; int soonest; int num_units; int latency; int load_store = 0; int regType, regNumber; Update *updatePtr; char msg[80], part1[40]; switch (machPtr->config) { case BASICPIPE: { Bypass *bypassPtr; int result_buf1 = TOTAL_REGS; int result_buf2 = TOTAL_REGS; int result_buf3 = TOTAL_REGS; int mem_buf0 = TOTAL_REGS; int mem_buf1 = TOTAL_REGS; int IF, ID, EX, MEM, WB; int rdReady; int rs1; int ful_pipe = 0; int branch = 0; int fpbypass_to_store = 0; int k; char *instrcolor; char linelist[200], linecolorlist[200]; char textlist[100], textcolorlist[200]; char rectlist[200], rectcolorlist[200]; char *cycleTemp; IF = machPtr->nextIF; ID = machPtr->nextID; instrcolor = getcolor(IF); switch (unitType) { case LOAD_BUF: case STORE_BUF: load_store = 1; num_units = machPtr->num_int_units; latency = 2; unitType = INT; break; case INT: num_units = machPtr->num_int_units; latency = 1; break; case BRANCH: branch = 1; num_units = machPtr->num_int_units; latency = 1; unitType = INT; break; case FP_ADD: num_units = machPtr->num_add_units; latency = machPtr->fp_add_latency; ful_pipe = machPtr->add_ful_pipe; break; case FP_MUL: num_units = machPtr->num_mul_units; latency = machPtr->fp_mul_latency; ful_pipe = machPtr->mul_ful_pipe; break; case FP_DIV: latency = machPtr->fp_div_latency; if (machPtr->fp_div_exist) { num_units = machPtr->num_div_units; ful_pipe = machPtr->div_ful_pipe; } else { /* POSSIBLE BUG. Visualization of block diagram do not know how to show this. */ unitType = FP_MUL; num_units = machPtr->num_mul_units; ful_pipe = machPtr->mul_ful_pipe; } break; } issueCheck0: wait = 0; /* check for WAW hazard */ if (rdType != NON_OP && machPtr->waiting_regs[wordPtr->rd]) wait = machPtr->waiting_regs[wordPtr->rd]; /* check for RAW hazard */ if (rs1Type != NON_OP && rs1Type != IMM_OP && machPtr->waiting_regs[wordPtr->rs1] > wait) wait = machPtr->waiting_regs[wordPtr->rs1]; /* for any store instr, the value of rs2 is required at the MEM stage, so the value of wait should be "machPtr->waiting_regs[wordPtr->rs2]-1". Also, note that for load instr, rs2Type is NON_OP */ if (rs2Type != NON_OP && rs2Type != IMM_OP && machPtr->waiting_regs[wordPtr->rs2] > wait) wait = machPtr->waiting_regs[wordPtr->rs2] - load_store; /* check for structural hazard */ for (i = 0, soonest = 0x7fffffff; i < num_units; i++) { if (!(j = machPtr->func_units[unitType][i])) break; else if (j < soonest) soonest = j; } if (i == num_units && (soonest > wait)) wait = soonest; /* check for multiple wirtes to FP reg file in the same cycle rdReady is the clock cycle for the last EX stage */ if (rdType && wordPtr->rd >= 32 && wordPtr->rd < 64) { soonest = wait ? wait : machPtr->cycleCount; /* load instructions "completes" in MEM stage, therefore, 1 (load_sotre) must be subtracted from rdReady. */ rdReady = soonest + latency - load_store; opPtr2 = machPtr->opsList; while (opPtr2 != NULL) { if (rdReady == opPtr2->rdReady && opPtr2->resultType && opPtr2->rd >=32 && opPtr2->rd < 64) { soonest++; rdReady++; wait = soonest; opPtr2 = opPtr2->nextPtr; } else if (rdReady > opPtr2->rdReady) { opPtr2 = opPtr2->nextPtr; } else { break; } } } if (wait > machPtr->cycleCount) { machPtr->cycleCount = wait; Isu_WriteBack(machPtr); goto issueCheck0; } sprintf(part1, "%d", wordPtr->line); Tcl_VarEval(machPtr->interp, "HighLightCodeLine ", part1, (char *)NULL); EX = machPtr->cycleCount + 1; while (machPtr->bypassList != NULL && machPtr->bypassList->displayCycle < EX) { bypassPtr = machPtr->bypassList; machPtr->bypassList = bypassPtr->nextPtr; Isu_FreeBypass(machPtr, bypassPtr); } while (machPtr->bypassList != NULL && machPtr->bypassList->displayCycle == EX) { bypassPtr = machPtr->bypassList; machPtr->bypassList = bypassPtr->nextPtr; switch (bypassPtr->buffer) { case RESULT_BUF1: result_buf1 = bypassPtr->reg; break; case RESULT_BUF2: result_buf2 = bypassPtr->reg; break; case RESULT_BUF3: result_buf3 = bypassPtr->reg; break; case MEM_BUF0: mem_buf0 = bypassPtr->reg; break; case MEM_BUF1: mem_buf1 = bypassPtr->reg; break; } Isu_FreeBypass(machPtr, bypassPtr); } /* when a branch depends on a previous ALU operation or previous two loads, there is a data hazard. */ if (branch && rs1Type == INT_OP) { rs1 = wordPtr->rs1; if (rs1 == mem_buf1 || rs1 == result_buf1) { machPtr->cycleCount++; ID = machPtr->cycleCount; EX = ID + 1; Isu_WriteBack(machPtr); while (machPtr->bypassList != NULL && machPtr->bypassList->displayCycle < EX) { bypassPtr = machPtr->bypassList; machPtr->bypassList = bypassPtr->nextPtr; Isu_FreeBypass(machPtr, bypassPtr); } } } /* Now, machPtr->cycleCount is one less than the EX stage clock cycle. (not always the same as ID stage clock cycle) */ opPtr = mallocOp(machPtr); opPtr->unit = unitType * MAX_FUNC_UNITS + i; opPtr->resultType = rdType; opPtr->rdReady = machPtr->cycleCount + latency; machPtr->nextIF = ID; machPtr->nextID = EX; if (unitType == INT) { MEM = EX + 1; WB = EX + 2; } else { MEM = opPtr->rdReady + 1; WB = opPtr->rdReady + 2; } if (!machPtr->cycleDisplayMode) { sprintf(msg, "%d;", IF); Tcl_VarEval(machPtr->interp, ".bas.datapath.counter configure -text ", msg, ".bas.block.counter configure -text ", msg, (char *)NULL); } if (rs1Type != NON_OP && rs1Type != IMM_OP) { switch (rs1Type) { case INT_OP: *((int *)&(opPtr->source1[0])) = *((int *)&(machPtr->regs[wordPtr->rs1])); break; case SFP_OP: *((float *)&(opPtr->source1[0])) = *((float *)&(machPtr->regs[wordPtr->rs1])); break; case DFP_OP: *((double *)&(opPtr->source1[0])) = *((double *)&(machPtr->regs[wordPtr->rs1])); break; } } if (rs2Type != NON_OP && rs2Type != IMM_OP) { switch (rs2Type) { case INT_OP: *((int *)&(opPtr->source2[0])) = *((int *)&(machPtr->regs[wordPtr->rs2])); break; case SFP_OP: *((float *)&(opPtr->source2[0])) = *((float *)&(machPtr->regs[wordPtr->rs2])); break; case DFP_OP: *((double *)&(opPtr->source2[0])) = *((double *)&(machPtr->regs[wordPtr->rs2])); break; } } if (load_store) opPtr->address = opPtr->source1[0] + wordPtr->extra; if (ful_pipe) machPtr->func_units[unitType][i] = 0; else machPtr->func_units[unitType][i] = opPtr->rdReady; if (machPtr->opsList == NULL || opPtr->rdReady < machPtr->opsList->rdReady) { opPtr->nextPtr = machPtr->opsList; machPtr->opsList = opPtr; } else { for (opPtr2 = machPtr->opsList; opPtr2->nextPtr != NULL; opPtr2 = opPtr2->nextPtr) if (opPtr->rdReady < opPtr2->nextPtr->rdReady) break; opPtr->nextPtr = opPtr2->nextPtr; opPtr2->nextPtr = opPtr; } opPtr->rd = wordPtr->rd; if (rdType && wordPtr->rd) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -