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

📄 sim.c

📁 计算机系统结构的讲义,浓缩了一本一千多页的书.真的是好东西.
💻 C
📖 第 1 页 / 共 5 页
字号:
          if (opPtr2->rs2 == opPtr1->rd && opPtr2->rs2Ready > cycle) {            if (machPtr->config == TOMASULO && opPtr2->rs2Ready != cycle + 1)              continue;            Tcl_DStringAppendElement(&list, "2");             sprintf(part, "%s", Units[opPtr2->unit]);            Tcl_DStringAppendElement(&list, part);          }        }        Tcl_DStringResult(interp, &list);      }    }  } else if (!(strncmp(argv[3], "inuse", 5))) {    for (opPtr1 = machPtr->opsList; opPtr1 != NULL; opPtr1 = opPtr1->nextPtr) {      if (opPtr1->unit == unit) {        int readBegin, execComplete;        readBegin = (opPtr1->rs1Ready > opPtr1->rs2Ready) ?            opPtr1->rs1Ready : opPtr1->rs2Ready;        if (cycle < readBegin) {          Tcl_DStringAppendElement(&list, "RAW");        } else if (cycle == readBegin) {          Tcl_DStringAppendElement(&list, "read");        } else {          switch (opPtr1->unit / MAX_FUNC_UNITS) {            case INT:              execComplete = machPtr->int_latency + readBegin;              break;            case FP_ADD:              execComplete = machPtr->fp_add_latency + readBegin;              break;            case FP_MUL:              if (!(strncmp(argv[3], "inuse", 5)))                execComplete = machPtr->fp_mul_latency + readBegin;              else                 execComplete = machPtr->fp_div_latency + readBegin;              break;            case FP_DIV:              execComplete = machPtr->fp_div_latency + readBegin;              break;          }          if (cycle <= execComplete)            Tcl_DStringAppendElement(&list, "exec");          else             Tcl_DStringAppendElement(&list, "WAR");                  }        Tcl_DStringResult(interp, &list);        break;      }    }  }          return TCL_OK;}/* *---------------------------------------------------------------------- * * Sim_MTraceCmd -- * *	This command turns on or off tracing in the simulator. * * Results: *	A standard Tcl result. * * Side effects: *	See the user documentation. * *---------------------------------------------------------------------- */intSim_MTraceCmd(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 && !strcmp( argv[1], "off" ) ) {	if( !machPtr->refTraceFile ) {	    sprintf( interp->result, "tracing wasn't on" );	    return TCL_ERROR;	}	fclose( machPtr->refTraceFile );	machPtr->refTraceFile = NULL;	return TCL_OK;    }    if( argc == 3 && !strcmp( argv[1], "on" ) ) {	if( machPtr->refTraceFile ) {	    sprintf( interp->result,		    "tracing already on -- turn it off first" );	    return TCL_ERROR;	}	if( !(machPtr->refTraceFile = fopen( argv[2], "a" )) ) {	    sprintf( interp->result, "couldn't open \"%s\": %s",		    argv[2], errstring() );	    return TCL_ERROR;	}	return TCL_OK;    }    sprintf( interp->result, "bad option to trace: should be 'on' <filename> or 'off'." );    return TCL_ERROR;}/* *---------------------------------------------------------------------- * * Sim_ITraceCmd -- * *	This command prints a dynamic instruction trace. * * Results: *	A standard Tcl result. * *---------------------------------------------------------------------- */intSim_ITraceCmd(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 && !strcmp( argv[1], "off" ) ) {	if( !machPtr->refInstrTraceFile ) {	    sprintf( interp->result, "tracing wasn't on" );	    return TCL_ERROR;	}	fclose( machPtr->refInstrTraceFile );	machPtr->refTraceFile = NULL;	return TCL_OK;    }    if( argc == 3 && !strcmp( argv[1], "on" ) ) {	if( machPtr->refInstrTraceFile ) {	    sprintf( interp->result,		    "instruction tracing already on -- turn it off first" );	    return TCL_ERROR;	}	if( !(machPtr->refInstrTraceFile = fopen( argv[2], "a" )) ) {	    sprintf( interp->result, "couldn't open \"%s\": %s",		    argv[2], errstring() );	    return TCL_ERROR;	}	return TCL_OK;    }    sprintf( interp->result, "bad option to trace: should be 'on' <filename> or 'off'." );    return TCL_ERROR;}static char *errstring(void){    extern int errno, sys_nerr;    extern char *sys_errlist[];    static char msgbuf[64];    if( !errno )	return "no error";    if( errno >= sys_nerr ) {	sprintf( msgbuf, "unknown error %d", errno );	return msgbuf;    }    return sys_errlist[ errno ];}/* *---------------------------------------------------------------------- * * ReadMem -- * *	Read a word from DLX memory. * * Results: *	Under normal circumstances, the result is 1 and the word at *	*valuePtr is modified to contain the DLX word at the given *	address.  If no such memory address exists, or if a stop is *	set on the memory location, then 0 is returned to signify that *	simulation should stop. * * Side effects: *	None. * *---------------------------------------------------------------------- */static intReadMem(machPtr, address, valuePtr)    register DLX *machPtr;	/* Machine whose memory is being read. */    unsigned int address;	/* Desired word address. */    int *valuePtr;		/* Store contents of given word here. */{    unsigned int index;    int result;    register MemWord *wordPtr;    index = ADDR_TO_INDEX(address);    if (index < machPtr->numWords) {	wordPtr = &machPtr->memPtr[index];	if ((wordPtr->stopList != NULL)		&& (machPtr->insCount != machPtr->firstIns)) {	    result = Stop_Execute(machPtr, wordPtr->stopList);	    if ((result != TCL_OK) || (machPtr->flags & STOP_REQUESTED)) {		return 0;	    }	}	if (machPtr->refTraceFile)	  fprintf( machPtr->refTraceFile, "0 %x\n", address );	*valuePtr = wordPtr->value;	return 1;    }    /*     * The word isn't in the main memory.  See if it is an I/O     * register.     */    if (Io_Read(machPtr, (address & ~0x3), valuePtr) == 1) {	return 1;    }    /*     * The word doesn't exist.  Register a bus error.  If interrupts     * ever get implemented for bus errors, this code will have to     * change a bit.     */    (void) BusError(machPtr, address, 0);    return 0;}/* *---------------------------------------------------------------------- * * WriteMem -- * *	Write a value into the DLX's memory. * * Results: *	If the write completed successfully then 1 is returned.  If *	any sort of problem occurred (such as an addressing error or *	a stop) then 0 is returned;  the caller should stop simulating. * * Side effects: *	The DLX memory gets updated with a new byte, halfword, or word *	value. * *---------------------------------------------------------------------- */static intWriteMem(machPtr, address, size, value)    register DLX *machPtr;	/* Machine whose memory is being read. */    unsigned int address;	/* Desired word address. */    int size;			/* Size to be written (1, 2, or 4 bytes). */    int value;			/* New value to write into memory. */{    unsigned int index;    int result;    register MemWord *wordPtr;    if (((size == 4) && (address & 0x3)) || ((size == 2) && (address & 0x1))) {	(void) AddressError(machPtr, address, 0);	return 0;    }    index = ADDR_TO_INDEX(address);    if (index < machPtr->numWords) {	wordPtr = &machPtr->memPtr[index];	if ((wordPtr->stopList != NULL)		&& (machPtr->insCount != machPtr->firstIns)) {	    result = Stop_Execute(machPtr, wordPtr->stopList);	    if ((result != TCL_OK) || (machPtr->flags & STOP_REQUESTED)) {		return 0;	    }	}	if (machPtr->refTraceFile)	  fprintf(machPtr->refTraceFile, "1 %x\n", address);	if (size == 4) {	    wordPtr->value = value;	} else if (size == 2) {	    if (address & 0x2) {		wordPtr->value = (wordPtr->value & 0xffff0000)			| (value & 0xffff);	    } else {		wordPtr->value = (wordPtr->value & 0xffff)			| (value << 16);	    }	} else {	    switch (address & 0x3) {		case 0:		    wordPtr->value = (wordPtr->value & 0x00ffffff)			    | (value << 24);		    break;		case 1:		    wordPtr->value = (wordPtr->value & 0xff00ffff)			    | ((value & 0xff) << 16);			    break;		case 2:		    wordPtr->value = (wordPtr->value & 0xffff00ff)			    | ((value & 0xff) << 8);		    break;		case 3:		    wordPtr->value = (wordPtr->value & 0xffffff00)			    | (value & 0xff);		    break;	    }	}	wordPtr->opCode = OP_NOT_COMPILED;	return 1;    }    /*     * Not in main memory.  See if it's an I/O device register.     */    if (Io_Write(machPtr, address, value, size) == 1) {	return 1;    }    (void) BusError(machPtr, address, 0);    return 0;}/* *---------------------------------------------------------------------- * * Simulate -- * *	This procedure forms the core of the simulator.  It executes *	instructions until either a break occurs or an error occurs *	(or until a single instruction has been executed, if single- *	stepping is requested). * * Results: *	A standard Tcl result. * * Side effects: *	The state of *machPtr changes in response to the simulation. *	Return information may be left in *interp. * *---------------------------------------------------------------------- */static intSimulate(machPtr, interp, singleStep)    register DLX *machPtr;		/* Machine description. */    Tcl_Interp *interp;			/* Tcl interpreter, for results and					 * break commands. */    int singleStep;			/* Non-zero means execute exactly					 * one instruction, regardless of					 * breaks found. */{    register MemWord *wordPtr;		/* Memory word for instruction. */    register unsigned int pc;		/* Current ins. address, then new					 * nextPc value. */    Op *opPtr;    unsigned int tmp;    int i, result;    char *errMsg, msg[20];    Update *updatePtr;    /*     * Can't continue from an addressing error on the program counter.     */    if ((machPtr->badPC != 0) && (machPtr->addrErrNum == machPtr->insCount)) {	sprintf(interp->result,		"address error on instruction fetch, pc = 0x%x",		machPtr->badPC);	return TCL_ERROR;    }    machPtr->flags &= ~STOP_REQUESTED;    machPtr->firstIns = machPtr->insCount;    Io_BeginSim(machPtr);    setCheckNum:    if (machPtr->callBackList != NULL) {	checkNum = machPtr->callBackList->serialNum;    } else {	checkNum = machPtr->insCount+100000;    }    if ((machPtr->badPC != 0) && (machPtr->addrErrNum > machPtr->insCount)) {	if (checkNum > machPtr->addrErrNum) {	    checkNum = machPtr->addrErrNum;	}    } else {	machPtr->badPC = 0;    }    if (singleStep) {	checkNum = machPtr->insCount+1;    }    while (1) {	int trapCaught = 0;	/*	 * Fetch an instruction, and compute the new next pc (but don't	 * store it yet, in case the instruction doesn't complete).	 */	pc = machPtr->regs[PC_REG];	if (pc >= machPtr->numWords) {	    result = BusError(machPtr, INDEX_TO_ADDR(pc), 1);	    if (result != TCL_OK) {		goto stopSimulation;	    } else {		goto endOfIns;	    }	}	if (machPtr->refTraceFile) 	  fprintf(machPtr->refTraceFile, "2 %x\n", INDEX_TO_ADDR(pc));     	if (machPtr->refInstrTraceFile) 	  fprintf(machPtr->refInstrTraceFile, "%x  %.50s\n",	    INDEX_TO_ADDR(pc),        	    Asm_Disassemble(machPtr, machPtr->memPtr[pc].value, tmp & ~0x3));		wordPtr = &machPtr->memPtr[pc];       	pc = machPtr->regs[NEXT_PC_REG]+1;	/*	 * Handle breaks on the instruction, if this isn't the first	 * instruction executed.	 */	if ((wordPtr->stopList != NULL)		&& (machPtr->insCount != machPtr->firstIns)) {	    result = Stop_Execute(machPtr, wordPtr->stopList);	    if ((result != TCL_OK) || (machPtr->flags & STOP_REQUESTED)) {		goto stopSimulation;	    }	}

⌨️ 快捷键说明

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