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

📄 sim.c

📁 计算机系统结构的讲义,浓缩了一本一千多页的书.真的是好东西.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  * 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 + -