⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sim.c

📁 计算机系统结构的讲义,浓缩了一本一千多页的书.真的是好东西.
💻 C
📖 第 1 页 / 共 5 页
字号:
Sim_DumpStats(clientData, interp, argc, argv)    ClientData clientData;    Tcl_Interp *interp;			/* Current interpreter. */    int argc;				/* Number of arguments. */    char **argv;			/* Argument strings. */{    return TCL_OK;}/* *---------------------------------------------------------------------- * * Sim_GoCmd -- * *	This procedure is invoked to process the "go" Tcl command. *	See the user documentation for details on what it does. * * Results: *	A standard Tcl result. * * Side effects: *	See the user documentation. * *---------------------------------------------------------------------- */intSim_GoCmd(clientData, interp, argc, argv)    ClientData clientData;    Tcl_Interp *interp;			/* Current interpreter. */    int argc;				/* Number of arguments. */    char **argv;			/* Argument strings. */{    DLX *machPtr = (DLX *) clientData;    int effectiveCycleCount;    if (argc > 2) {	sprintf(interp->result,		"too many args:  should be \"%.50s\" [address]", argv[0]);	return TCL_ERROR;    }    if (argc == 2) {	char *end;	int newPc;	if (Sym_EvalExpr(machPtr, (char *) NULL, argv[1], 0, &newPc, &end)		!= TCL_OK) {	    return TCL_ERROR;	  }	if ((*end != 0) || (newPc & 0x3)) {	    sprintf(interp->result,		    "\"%.50s\" isn't a valid starting address", argv[1]);	    return TCL_ERROR;	}	machPtr->regs[PC_REG] = ADDR_TO_INDEX(newPc);	machPtr->regs[NEXT_PC_REG] = machPtr->regs[PC_REG] + 1;	machPtr->flags = 0;	machPtr->badPC = 0;    }     Tcl_VarEval(machPtr->interp, "ChangeCycleTitle 0; set fastmode 1",         (char *)NULL);    if (machPtr->config == BASICPIPE) {       effectiveCycleCount = machPtr->nextIF;    } else {      effectiveCycleCount = machPtr->cycleCount;    }    if (machPtr->cycleDisplayMode &&             machPtr->cycleDisplayCount < effectiveCycleCount) {        while (machPtr->cycleDisplayCount < effectiveCycleCount) {            NextCycle (machPtr, interp);        }    }     machPtr->cycleDisplayMode = 0;    return Simulate(machPtr, interp, 0);}/* *---------------------------------------------------------------------- * * Sim_StepCmd -- * *	This procedure is invoked to process the "step" Tcl command. *	See the user documentation for details on what it does. * * Results: *	A standard Tcl result. * * Side effects: *	See the user documentation. * *---------------------------------------------------------------------- */intSim_StepCmd(clientData, interp, argc, argv)    ClientData clientData;    Tcl_Interp *interp;			/* Current interpreter. */    int argc;				/* Number of arguments. */    char **argv;			/* Argument strings. */{    DLX *machPtr = (DLX *) clientData;    int effectiveCycleCount;    if (argc > 2) {	sprintf(interp->result,		"too many args:  should be \"%.50s\" [address]", argv[0]);	return TCL_ERROR;    }    if (argc == 2) {	char *end;	int newPc;	if (Sym_EvalExpr(machPtr, (char *) NULL, argv[1], 0, &newPc, &end)		!= TCL_OK) {	    return TCL_ERROR;	}	if ((*end != 0) || (newPc & 0x3)) {	    sprintf(interp->result,		    "\"%.50s\" isn't a valid address", argv[1]);	    return TCL_ERROR;	}	machPtr->regs[PC_REG] = ADDR_TO_INDEX(newPc);	machPtr->regs[NEXT_PC_REG] = machPtr->regs[PC_REG] + 1;	machPtr->flags = 0;	machPtr->badPC = 0;      }    Tcl_VarEval(machPtr->interp, "ChangeCycleTitle 0; set fastmode 0",         (char *)NULL);    if (machPtr->config == BASICPIPE) {       effectiveCycleCount = machPtr->nextIF + 1;    } else {      effectiveCycleCount = machPtr->cycleCount;    }    if (machPtr->cycleDisplayMode &&             machPtr->cycleDisplayCount < effectiveCycleCount) {        while (machPtr->cycleDisplayCount < effectiveCycleCount) {            NextCycle (machPtr, interp);        }        machPtr->cycleDisplayMode = 0;        return TCL_OK;    } else {        machPtr->cycleDisplayMode = 0;        return Simulate(machPtr, interp, 1);    }}/* *---------------------------------------------------------------------- * * Sim_CycleCmd -- * *      This procedure is invoked to process the "cycle" Tcl command. *      See the user documentation for details on what it does. * * Results: *      A standard Tcl result. * * Side effects: *      See the user documentation. * *---------------------------------------------------------------------- */intSim_CycleCmd(clientData, interp, argc, argv)    ClientData clientData;    Tcl_Interp *interp;                 /* Current interpreter. */    int argc;                           /* Number of arguments. */    char **argv;                        /* Argument strings. */{    DLX *machPtr = (DLX *) clientData;	    if (argc > 2) {	sprintf(interp->result,		"too many args:  should be \"%.50s\" [address]", argv[0]);	return TCL_ERROR;    }    if (argc == 2) {	char *end;	int newPc;	if (Sym_EvalExpr(machPtr, (char *) NULL, argv[1], 0, &newPc, &end)		!= TCL_OK) {	    return TCL_ERROR;	  }	if ((*end != 0) || (newPc & 0x3)) {	    sprintf(interp->result,		    "\"%.50s\" isn't a valid starting address", argv[1]);	    return TCL_ERROR;	}	machPtr->regs[PC_REG] = ADDR_TO_INDEX(newPc);	machPtr->regs[NEXT_PC_REG] = machPtr->regs[PC_REG] + 1;	machPtr->flags = 0;	machPtr->badPC = 0;    }     if (!machPtr->cycleDisplayMode) {        if (machPtr->config == BASICPIPE)          machPtr->cycleDisplayCount = machPtr->lastIF + 1;        else           machPtr->cycleDisplayCount = machPtr->cycleCount;        machPtr->cycleDisplayMode = 1;    }    Tcl_VarEval(machPtr->interp, "ChangeCycleTitle 1; set fastmode 0",         (char *)NULL);    return NextCycle(machPtr, interp);}/* *---------------------------------------------------------------------- * * Sim_CallBack -- * *	Arrange for a particular procedure to be invoked after a given *	number of instructions have been simulated. * * Results: *	None. * * Side effects: *	After numIns instructions have been executed, proc will be *	invoked in the following way: * *	void *	proc(clientData, machPtr) *	    ClientData clientData; *	    DLX *machPtr; *	{ *	} * *	The clientData and machPtr arguments will be the same as those *	passed to this procedure. *---------------------------------------------------------------------- */voidSim_CallBack(machPtr, numIns, proc, clientData)    DLX *machPtr;		/* Machine of interest. */    int numIns;			/* Call proc after this many instructions				 * have been executed in machPtr. */    void (*proc)();		/* Procedure to call. */    ClientData clientData;	/* Arbitrary one-word value to pass to proc. */{    register CallBack *cbPtr;    cbPtr = (CallBack *) calloc(1, sizeof(CallBack));    cbPtr->serialNum = machPtr->insCount + numIns;    cbPtr->proc = proc;    cbPtr->clientData = clientData;    if ((machPtr->callBackList == NULL) ||	    (cbPtr->serialNum < machPtr->callBackList->serialNum)) {	cbPtr->nextPtr = machPtr->callBackList;	machPtr->callBackList = cbPtr;    } else {	register CallBack *cbPtr2;	for (cbPtr2 = machPtr->callBackList; cbPtr2->nextPtr != NULL;		cbPtr2 = cbPtr2->nextPtr) {	    if (cbPtr->serialNum < cbPtr2->nextPtr->serialNum) {		break;	    }	}	cbPtr->nextPtr = cbPtr2->nextPtr;	cbPtr2->nextPtr = cbPtr;    }    if (cbPtr->serialNum < checkNum) {	checkNum = cbPtr->serialNum;    }}/* *---------------------------------------------------------------------- * * Sim_Stop -- * *	Arrange for the execution of the machine to stop after the *	current instruction. * * Results: *	None. * * Side effects: *	The machine will stop executing (if it was executing in the *	first place). * *---------------------------------------------------------------------- */voidSim_Stop(machPtr)    DLX *machPtr;			/* Machine to stop. */{    machPtr->flags |= STOP_REQUESTED;    checkNum = machPtr->insCount + 1;}/* *---------------------------------------------------------------------- * * Sim_GetPC -- * *	This procedure computes the current program counter for *	machPtr. * * Results: *	The return value is the current program counter for the *	machine.  This is a bit tricky to compute because the PC *	is stored as an index, and there may have been an unaligned *	value put in the PC. * * Side effects: *	None. * *---------------------------------------------------------------------- */unsigned intSim_GetPC(machPtr)    register DLX *machPtr;		/* Machine whose PC is wanted. */{    if ((machPtr->badPC != 0) && (machPtr->insCount >= machPtr->addrErrNum)) {	return machPtr->badPC;    }    return INDEX_TO_ADDR(machPtr->regs[PC_REG]);}intSim_EquationCmd(clientData, interp, argc, argv)    ClientData clientData;    Tcl_Interp *interp;			/* Current interpreter. */    int argc;				/* Number of arguments. */    char **argv;			/* Argument strings. */{  DLX *machPtr = (DLX *) clientData;	  int unit;  int cycle;  Op *opPtr1, *opPtr2;  Tcl_DString list;  char part[20];  if (argc != 4) {    interp->result = "wrong # args";    return TCL_ERROR;  }   unit = atoi(argv[1]);  cycle = atoi(argv[2]);   Tcl_DStringInit(&list);        if (!(strcmp(argv[3], "issue"))) {    for (opPtr1 = machPtr->opsList; opPtr1 != NULL; opPtr1 = opPtr1->nextPtr) {      if (opPtr1->unit == unit) {        if (opPtr1->rs1 != -1 && opPtr1->rs1 < 64) {          if (opPtr1->rs1 < 32)             sprintf(part, "R%d", opPtr1->rs1);          else              sprintf(part, "F%d", opPtr1->rs1 - 32);          Tcl_DStringAppendElement(&list, part);          if (opPtr1->rs1Ready)            Tcl_DStringAppendElement(&list, "1");          else          Tcl_DStringAppendElement(&list, "0");        } else {          Tcl_DStringAppendElement(&list, "");          Tcl_DStringAppendElement(&list, "0");        }        if (opPtr1->rs2 != -1 && opPtr1->rs2 < 64) {          if (opPtr1->rs2 < 32)             sprintf(part, "R%d", opPtr1->rs2);          else              sprintf(part, "F%d", opPtr1->rs2 - 32);          Tcl_DStringAppendElement(&list, part);          if (opPtr1->rs2Ready)            Tcl_DStringAppendElement(&list, "1");          else          Tcl_DStringAppendElement(&list, "0");        } else {          Tcl_DStringAppendElement(&list, "");          Tcl_DStringAppendElement(&list, "0");        }        if (opPtr1->resultType != NON_OP && opPtr1->rd < 64) {          if (opPtr1->rd < 32)             sprintf(part, "R%d", opPtr1->rd);          else              sprintf(part, "F%d", opPtr1->rd - 32);          Tcl_DStringAppendElement(&list, part);        } else {          Tcl_DStringAppendElement(&list, "");        }        Tcl_DStringResult(interp, &list);        break;      }    }  } else if (!(strcmp(argv[3], "write"))) {    for (opPtr1 = machPtr->finishList; opPtr1 != NULL; opPtr1 = opPtr1->nextPtr) {      if (opPtr1->resultType != NON_OP && opPtr1->unit == unit &&           opPtr1->rdReady == cycle) {        if (machPtr->waiting_regs[opPtr1->rd] == 0) {          if (opPtr1->rd < 32)             sprintf(part, "R%d", opPtr1->rd);          else              sprintf(part, "F%d", opPtr1->rd - 32);          Tcl_DStringAppendElement(&list, part);        } else {          Tcl_DStringAppendElement(&list, "");        }        for (opPtr2 = machPtr->opsList; opPtr2 != NULL; opPtr2 = opPtr2->nextPtr) {           if (opPtr2->rs1 == opPtr1->rd && opPtr2->rs1Ready > cycle) {            if (machPtr->config == TOMASULO && opPtr2->rs1Ready != cycle + 1)              continue;            Tcl_DStringAppendElement(&list, "1");             sprintf(part, "%s", Units[opPtr2->unit]);            Tcl_DStringAppendElement(&list, part);          }        }        for (opPtr2 = machPtr->opsList; opPtr2 != NULL; opPtr2 = opPtr2->nextPtr) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -