📄 sim.c
字号:
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 + -