📄 sim.c
字号:
/* * sim.c -- * * This file contains a simple Tcl-based simulator for an abridged * version of the MIPS DLX architecture. * * This file is part of DISC. It was modified by Yinong Zhang * (yinong@ecn.purdue.edu) from the file "sim.c" in the distribution * of "dlxsim" available at: * ftp://max.stanford.edu/pub/hennessy-patterson.software/dlx.tar.Z * * The original source code is copyright as follows: * * Copyright 1989 Regents of the University of California * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies. The University of California * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. * */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <tcl.h>#include "dlx.h"#include "sym.h"/* * The table below is used to translate bits 31:26 of the instruction * into a value suitable for the "opCode" field of a MemWord structure, * or into a special value for further decoding. */#define SPECIAL 120#define FPARITH 121#define IFMT 1#define JFMT 2#define RFMT 3typedef struct { int opCode; /* Translated op code. */ int format; /* Format type (IFMT or JFMT or RFMT) */} OpInfo;OpInfo opTable[] = { {SPECIAL, RFMT}, {FPARITH, RFMT}, {OP_J, JFMT}, {OP_JAL, JFMT}, {OP_BEQZ, IFMT}, {OP_BNEZ, IFMT}, {OP_BFPT, IFMT}, {OP_BFPF, IFMT}, {OP_ADDI, IFMT}, {OP_ADDUI, IFMT}, {OP_SUBI, IFMT}, {OP_SUBUI, IFMT}, {OP_ANDI, IFMT}, {OP_ORI, IFMT}, {OP_XORI, IFMT}, {OP_LHI, IFMT}, {OP_RFE, IFMT}, {OP_TRAP, IFMT}, {OP_JR, IFMT}, {OP_JALR, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_SEQI, IFMT}, {OP_SNEI, IFMT}, {OP_SLTI, IFMT}, {OP_SGTI, IFMT}, {OP_SLEI, IFMT}, {OP_SGEI, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_LB, IFMT}, {OP_LH, IFMT}, {OP_RES, IFMT}, {OP_LW, IFMT}, {OP_LBU, IFMT}, {OP_LHU, IFMT}, {OP_LF, IFMT}, {OP_LD, IFMT}, {OP_SB, IFMT}, {OP_SH, IFMT}, {OP_RES, IFMT}, {OP_SW, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_SF, IFMT}, {OP_SD, IFMT}, {OP_SEQUI, IFMT}, {OP_SNEUI, IFMT}, {OP_SLTUI, IFMT}, {OP_SGTUI, IFMT}, {OP_SLEUI, IFMT}, {OP_SGEUI, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}, {OP_RES, IFMT}};/* * the table below is used to convert the "funct" field of SPECIAL * instructions into the "opCode" field of a MemWord. */int specialTable[] = { OP_SLLI, OP_RES, OP_SRLI, OP_SRAI, OP_SLL, OP_RES, OP_SRL, OP_SRA, OP_RES, OP_RES, OP_RES, OP_RES, OP_TRAP, OP_RES, OP_RES, OP_RES, OP_SEQU, OP_SNEU, OP_SLTU, OP_SGTU, OP_SLEU, OP_SGEU, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_ADD, OP_ADDU, OP_SUB, OP_SUBU, OP_AND, OP_OR, OP_XOR, OP_RES, OP_SEQ, OP_SNE, OP_SLT, OP_SGT, OP_SLE, OP_SGE, OP_RES, OP_RES, OP_MOVI2S, OP_MOVS2I, OP_MOVF, OP_MOVD, OP_MOVFP2I, OP_MOVI2FP, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES};/* * the table below is used to convert the "funct" field of FPARITH * instructions into the "opCode" field of a MemWord. */int FParithTable[] = { OP_ADDF, OP_SUBF, OP_MULTF, OP_DIVF, OP_ADDD, OP_SUBD, OP_MULTD, OP_DIVD, OP_CVTF2D, OP_CVTF2I, OP_CVTD2F, OP_CVTD2I, OP_CVTI2F, OP_CVTI2D, OP_MULT, OP_DIV, OP_EQF, OP_NEF, OP_LTF, OP_GTF, OP_LEF, OP_GEF, OP_MULTU, OP_DIVU, OP_EQD, OP_NED, OP_LTD, OP_GTD, OP_LED, OP_GED, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES, OP_RES }; extern char *Units[]; /* * The following value is used to handle virtually all special cases * while simulating. The simulator normally executes in a fast path * where it ignores all special cases. However, after executing each * instruction it checks the current serial number (total # of instructions * executed) agains the value below. If that serial number has been * executed, then the simulator pauses to check for all possible special * conditions (stops, callbacks, errors, etc.). Thus anyone that wants * to get a special condition handled must be sure to set checkNum below * so that the special-check code will be executed. This facility means * that the simulator only has to check a single condition in its fast * path. */static int checkNum;/* * Forward declarations for procedures defined later in this file: */static void statsReset(DLX *);static int AddressError(DLX *, unsigned int, int);static char *errstring(void);static int BusError(DLX *, unsigned int, int);static void Compile(MemWord *);static int Mult(int, int, int, int *);static int Overflow(DLX *);static int ReadMem(DLX *, unsigned int, int *);static int WriteMem(DLX *, unsigned int, int, int);static int Simulate(DLX *, Tcl_Interp *, int);static int NextCycle(DLX *, Tcl_Interp *);/* *---------------------------------------------------------------------- * * Sim_Create -- * * Create a description of an DLX machine. * * Results: * The return value is a pointer to the description of the DLX * machine. * * Side effects: * The DLX structure gets allocated and initialized. Several * Tcl commands get registered for interp. * *---------------------------------------------------------------------- */DLX *Sim_Create(interp) Tcl_Interp *interp; /* Interpreter to associate with machine. */{ register DLX *machPtr; extern int Main_QuitCmd(); machPtr = (DLX *) calloc(1, sizeof(DLX)); machPtr->interp = interp; machPtr->memPtr = NULL; machPtr->memScratch = NULL; machPtr->stopList = NULL; machPtr->callBackList = NULL; machPtr->bypassList = NULL; machPtr->updateList = NULL; machPtr->opsList = NULL; machPtr->finishList = NULL; machPtr->opFree = NULL; machPtr->updateFree = NULL; machPtr->bypassFree = NULL; Tcl_LinkVar(interp, "config", (char *)&(machPtr->config), TCL_LINK_INT); Tcl_LinkVar(interp, "insCount", (char *)&(machPtr->insCount), TCL_LINK_INT); Tcl_LinkVar(interp, "backInsCount", (char *)&(machPtr->backInsCount), TCL_LINK_INT); Tcl_LinkVar(interp, "cycleCount", (char *)&(machPtr->cycleCount), TCL_LINK_INT); Tcl_LinkVar(interp, "cycleDisplayCount", (char *)&(machPtr->cycleDisplayCount), TCL_LINK_INT); Tcl_LinkVar(interp, "numWords", (char *)&(machPtr->numWords), TCL_LINK_INT); Tcl_LinkVar(interp, "num_int_units", (char *)&(machPtr->num_int_units), TCL_LINK_INT); Tcl_LinkVar(interp, "num_add_units", (char *)&(machPtr->num_add_units), TCL_LINK_INT); Tcl_LinkVar(interp, "num_mul_units", (char *)&(machPtr->num_mul_units), TCL_LINK_INT); Tcl_LinkVar(interp, "num_div_units", (char *)&(machPtr->num_div_units), TCL_LINK_INT); Tcl_LinkVar(interp, "num_load_bufs", (char *)&(machPtr->num_load_bufs), TCL_LINK_INT); Tcl_LinkVar(interp, "num_store_bufs", (char *)&(machPtr->num_store_bufs), TCL_LINK_INT); Tcl_LinkVar(interp, "int_latency", (char *)&(machPtr->int_latency), TCL_LINK_INT); Tcl_LinkVar(interp, "fp_add_latency", (char *)&(machPtr->fp_add_latency), TCL_LINK_INT); Tcl_LinkVar(interp, "fp_mul_latency", (char *)&(machPtr->fp_mul_latency), TCL_LINK_INT); Tcl_LinkVar(interp, "fp_div_latency", (char *)&(machPtr->fp_div_latency), TCL_LINK_INT); Tcl_LinkVar(interp, "load_buf_latency", (char *)&(machPtr->load_buf_latency), TCL_LINK_INT); Tcl_LinkVar(interp, "store_buf_latency", (char *)&(machPtr->store_buf_latency), TCL_LINK_INT); Tcl_LinkVar(interp, "add_ful_pipe", (char *)&(machPtr->add_ful_pipe), TCL_LINK_INT); Tcl_LinkVar(interp, "mul_ful_pipe", (char *)&(machPtr->mul_ful_pipe), TCL_LINK_INT); Tcl_LinkVar(interp, "div_ful_pipe", (char *)&(machPtr->div_ful_pipe), TCL_LINK_INT); Tcl_LinkVar(interp, "fp_div_exist", (char *)&(machPtr->fp_div_exist), TCL_LINK_INT); Tcl_LinkVar(interp, "ld_st_exist", (char *)&(machPtr->ld_st_exist), TCL_LINK_INT); Tcl_CreateCommand(interp, "asm", Asm_AsmCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "load", Asm_LoadCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "get", Gp_GetCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "put", Gp_PutCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "fget", Gp_FGetCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "fput", Gp_FPutCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "quit", Main_QuitCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "init", Sim_InitCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "stats", Sim_DumpStats, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "itrace", Sim_ITraceCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "mtrace", Sim_MTraceCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "go", Sim_GoCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "step", Sim_StepCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "cycle", Sim_CycleCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "equation", Sim_EquationCmd, (ClientData) machPtr, (void (*)()) NULL); Tcl_CreateCommand(interp, "stop", Stop_StopCmd, (ClientData) machPtr, (void (*)()) NULL); return machPtr;}void Sim_Initialize(machPtr) DLX *machPtr; /* machine description */{ MemWord *wordPtr; int i; Stop *stopPtr; CallBack *cbPtr; Bypass *bypassPtr; Update *updatePtr; Op *opPtr; while (machPtr->stopList != NULL) { stopPtr = machPtr->stopList; machPtr->stopList = stopPtr->overallPtr; free(stopPtr->command); free(stopPtr); } while (machPtr->callBackList != NULL) { cbPtr = machPtr->callBackList; machPtr->callBackList = cbPtr->nextPtr; free(cbPtr); } while (machPtr->bypassList != NULL) { bypassPtr = machPtr->bypassList; machPtr->bypassList = bypassPtr->nextPtr; Isu_FreeBypass(machPtr, bypassPtr); } while (machPtr->updateList != NULL) { updatePtr = machPtr->updateList; machPtr->updateList = updatePtr->nextPtr; Isu_FreeUpdate(machPtr, updatePtr); } while (machPtr->opsList != NULL) { opPtr = machPtr->opsList; machPtr->opsList = opPtr->nextPtr; Isu_FreeOp(machPtr, opPtr); } while (machPtr->finishList != NULL) { opPtr = machPtr->finishList; machPtr->finishList = opPtr->nextPtr; Isu_FreeOp(machPtr, opPtr); } machPtr->numChars = machPtr->numWords * 4; if (machPtr->memPtr != NULL) free(machPtr->memPtr); machPtr->memPtr = (MemWord *) calloc(1, (unsigned) (sizeof(MemWord) * machPtr->numWords)); for (i = machPtr->numWords, wordPtr = machPtr->memPtr; i > 0; i--, wordPtr++) { wordPtr->value = 0; wordPtr->opCode = OP_NOT_COMPILED; wordPtr->stopList = NULL; } if (machPtr->memScratch != NULL) free(machPtr->memScratch); machPtr->memScratch = (char *) malloc (machPtr->numChars); machPtr->endScratch = machPtr->memScratch + machPtr->numChars; for (i = 0; i < NUM_GPRS; i++) { machPtr->regs[i] = 0; } machPtr->regs[FP_STATUS] = 0; machPtr->regs[PC_REG] = 0; machPtr->regs[NEXT_PC_REG] = 1; machPtr->badPC = 0; machPtr->addrErrNum = 0; machPtr->nextIF = 0; machPtr->nextID = 1; machPtr->lastIF = -1; machPtr->cycleHead = 0; machPtr->insCount = 0; machPtr->firstIns = 0; machPtr->branchSerial = -1; machPtr->branchPC = 0; machPtr->flags = 0; machPtr->stopNum = 1; /* set up floating point stuff */ machPtr->regs[FP_STATUS] = 0; for (i = 0; i < machPtr->num_int_units; i++) machPtr->int_units[i] = 0; for (i = 0; i < machPtr->num_add_units; i++) machPtr->fp_add_units[i] = 0; for (i = 0; i < machPtr->num_div_units; i++) machPtr->fp_div_units[i] = 0; for (i = 0; i < machPtr->num_mul_units; i++) machPtr->fp_mul_units[i] = 0; for (i = 0; i < 6; i++) machPtr->load_bufs[i] = 0; for (i = 0; i < 3; i++) machPtr->store_bufs[i] = 0; machPtr->func_units[INT] = machPtr->int_units; machPtr->func_units[FP_ADD] = machPtr->fp_add_units; machPtr->func_units[FP_DIV] = machPtr->fp_div_units; machPtr->func_units[FP_MUL] = machPtr->fp_mul_units; machPtr->func_units[LOAD_BUF] = machPtr->load_bufs; machPtr->func_units[STORE_BUF] = machPtr->store_bufs; machPtr->fp_div_exist = 1; machPtr->ld_st_exist = 0; for (i = 0; i < 65; i++) { machPtr->waiting_regs[i] = 0; machPtr->sameCycle_regs[i] = 0; } machPtr->cycleCount = 1; machPtr->cycleDisplayCount = 1; machPtr->cycleDisplayMode = 0; machPtr->codeLine = 1; for (i = 0; i < 5; i++) { if (machPtr->cycleTable[i] != NULL) free(machPtr->cycleTable[i]); machPtr->cycleTable[i] = (char *)calloc(1, sizeof(char) * 500); } if (machPtr->refInstrTraceFile != NULL) fclose(machPtr->refInstrTraceFile); machPtr->refInstrTraceFile = NULL; if (machPtr->refTraceFile != NULL) fclose(machPtr->refTraceFile); machPtr->refTraceFile = NULL;/* initialize counters */ statsReset(machPtr); Tcl_DeleteHashTable(&machPtr->symbols); Tcl_InitHashTable(&machPtr->symbols, TCL_STRING_KEYS); Io_Init(machPtr); Cop0_Init(machPtr); Trap_Init_Handle(machPtr); Sym_AddSymbol(machPtr, "", "memSize", machPtr->numChars, SYM_GLOBAL);}/* *---------------------------------------------------------------------- * statsReset -- * * This procedure clears the various statistics which are kept on * dynamic execution of the code. * * Results: * None * * Side effects: * Changes the related global variables. * *---------------------------------------------------------------------- */void statsReset(machPtr) DLX *machPtr; /* machine description */{ int i; machPtr->stalls = 0; machPtr->branchYes = 0; machPtr->branchNo = 0; for (i = 0; i <= OP_LAST; i++) machPtr->operationCount[i] = 0;}intSim_InitCmd(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ DLX *machPtr = (DLX *) clientData; Sim_Initialize(machPtr); return TCL_OK; /* Never gets executed. */}/* *---------------------------------------------------------------------- * * Sim_DumpStats -- * * This procedure is invoked to process the "stats" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -