/* * dlx.h -- * * Declarations of structures used to simulate the MIPS * architecture. * * 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. * * $Header: /user1/ouster/mipsim/RCS/dlx.h,v 1.8 89/11/20 10:56:41 ouster Exp $ SPRITE (Berkeley) * * Incorporates additions from Bart Massey (bart@cs.uoregon.edu) to add * a trace command that produces output for use with the dinero utility. * * This file was modified as part of Masters Project by Yueh-Lin Liu * (yueh@cs.bu.edu) under the supervision of professor Azer Bestavros * (best@cs.bu.edu) to incorporate the simulator of scoreboarding and * Tomasulo's simulator. * */ #ifndef _MIPS #define _MIPS #define MEMSIZE 16384 #ifndef _TCL #include #endif #ifndef _HASH #include #endif #ifndef _MIPSIM_IO #include "io.h" #endif #ifndef _COP0 #include "cop0.h" #endif #define MAX_FP_UNITS 4 /* Maximum allowable number of any particular type of floating point unit. */ #define MAX_LOAD_UNITS 10 #define MAX_VECT_UNITS 8 /* * The following structure is used for each "stop" that has * been requested for a machine. */ typedef struct Stop { char *command; /* Tcl command to execute, or NULL if * this is a simple stop. */ int number; /* Number that identifies this stop for * deletion purposes. */ unsigned int address; /* Address (in DLX memory) of memory word * associated with stop. */ struct Stop *nextPtr; /* Next in list of stops associated with * same memory location (NULL for end of * list). */ struct Stop *overallPtr; /* Next in list of all stops set for * machine (NULL for end of list). */ } Stop; /* * Each memory word is represented by a structure of the following * format. In order to interpret instructions efficiently, they * get decoded into several fields on the first execution after each * change to the word. */ typedef struct { int value; /* Contents of the memory location. */ short opCode; /* Type of instruction. This is NOT * the same as the opcode field from the * instruction: see #defines below * for details. */ char rs1, rs2, rd; /* Three registers from instruction. */ int extra; /* Immediate or target or shamt field * or offset. Immediates are sign-extended. */ Stop *stopList; /* List of stops to invoke whenever * this memory location is accessed. */ } MemWord; /* * For each callback registered through Sim_CallBack, there is a structure * of the following form: */ typedef struct CallBack { int serialNum; /* Call the procedure after executing the * instruction with this serial number. */ void (*proc)(); /* Procedure to call. */ ClientData clientData; /* Argument to pass to proc. */ struct CallBack *nextPtr; /* Next callback in list of all those * associated with this machine. NULL * means end of list. */ } CallBack; /* * For each pending floating point operation, there is a structure of the * following form: */ typedef struct FPop { int type; /* type of operation */ int unit; /* fp unit number */ int dest; /* destination register */ int resultType; /* see FP_*_OP values */ long result[2]; /* Result[0] is result of single precision operation, both elements used for double precision. A single precision float, and a long integer must be the same size. */ int ready; /* cycle when result will be ready */ struct FPop *nextPtr; /* Next FPop in the list of all those * associated with this machine. NULL * means end of list. */ } FPop; /* * For each pipeline stage there is the a structure of the following form: */ typedef struct InstrInExec { short valid; /* indicates if there is an instruction in this stage */ MemWord *InstrPtr; /* instructiom itself */ long rs1[2]; /* value of the first operand if register */ long rs2[2]; /* value of the second operand if register */ int stalled; /* 1 if instruction is stalled after this stage */ int res_exists; /* 1 if the instruction produces a result */ int pc; /* next pc */ int result; /* result of computation */ FPop *FPPtr; /* information about fp operation */ struct InstrInExec *nextPtr; } InstrInExec; /* * This structure is used to store the values for bypassing */ typedef struct { int rd; /* destination register */ int resultType; /* type of result (integer, single-precision fp, double-precision fp */ long result[2]; /* value to bypass */ int available; /* YES, if the value is available at beginning of clock cycle */ int stage; /* from which pipeline stage */ } res_for_bypass; /* The maximum allowed vector length */ #define MAX_MVL 1024 /* The type for a vector register*/ typedef double VR[MAX_MVL]; /* * For each pending vector operation, there is a structure of the * following form: */ #define NONE -1 typedef struct Vectop { int unitType; /* vector unit type */ int unit; /* vector unit number */ int source1; /* first vector operand or NONE */ int source2; /* second vector operand or NONE */ int dest; /* destination register; or NONE */ int resultType; /* shows if the result is VECTOR, MASK or UNIMP*/ VR *result; /* result of the vector operation if VECTOR*/ char *vm; /* mask result of vector operation */ int ready; /* cycle when result will be ready */ int read; /* cycle when the operands will be read */ struct Vectop *nextPtr; /* Next Vectop in the list of all those * associated with this machine. NULL * means end of list. */ } Vectop; typedef struct InstrStatus { int pc,tag; MemWord *InstrPtr; int is, ro, ex, wr; struct InstrStatus *next; }InstrStatus; /* * This is for scoreboard struct types * */ typedef struct{ int choose; /*1 if is in table */ int FUno; InstrInExec *InstrInExecPtr; int FUname; int busy; char *name; int Fi, Fj, Fk; int Qj, Qk; int Rj, Rk; InstrStatus *UpdatePtr; int stalls; int status; int flags; }FUscript; typedef struct{ FUscript *fu_div_unit[MAX_FP_UNITS]; FUscript *fu_add_unit[MAX_FP_UNITS]; FUscript *fu_mul_unit[MAX_FP_UNITS]; FUscript *fu_int_unit; int FPReg[32]; InstrStatus *LPtr; InstrStatus *RPtr; }Scoreboard; /* * This is for tomasulo struct types * */ typedef struct{ int type; int RSno; InstrInExec *InstrInExecPtr; int RSname; int busy; char *name; int Vj,Vk; int Qj, Qk; int address; InstrStatus *UpdatePtr; int stalls; int status; int flags; int token; }RSscript; typedef struct{ RSscript *fu_load_unit[MAX_LOAD_UNITS]; RSscript *fu_store_unit[MAX_LOAD_UNITS]; RSscript *fu_add_unit[MAX_FP_UNITS]; RSscript *fu_mul_unit[MAX_FP_UNITS]; RSscript *special; int Qi[32]; int busy[32]; int address; InstrStatus *LPtr; InstrStatus *RPtr; }Tomasulo; /* * The structure below describes the state of an DLX machine. */ #define NUM_GPRS 64 #define NUM_VRS 8 #define MAX_NUM_VRS 16 #define PC_REG (NUM_GPRS) #define NEXT_PC_REG (NUM_GPRS+1) #define TOTAL_REGS (NUM_GPRS+2) #define MVL 64 /* * Type of vector operation: whether the result is VECTOR, MASK or UNIMPortant; * whether the source operands are * vector(V), floating point(F), integer(I) */ #define VECTOR_VV 1 #define MASK_VV 2 #define VECTOR_DV 3 #define MASK_DV 4 #define VECTOR_IV 5 #define MASK_IV 6 #define VECTOR_II 7 #define UNIMP_IV 8 #define UNIMP_VV 9 #define UNIMP_DV 10 /* default values for number of fp units and latencies */ #define NUM_ADD_UNITS 3 /* Number of fp adder units. */ #define NUM_DIV_UNITS 1 /* Number of fp divider units. */ #define NUM_MUL_UNITS 2 /* Number of fp multiplier units. */ #define NUM_LOAD_UNITS 6 /* Number of fp load units. */ #define NUM_STORE_UNITS 3 /* Number of fp store units. */ #define FP_ADD_LATENCY 2 /* Latency for an FP add. */ #define FP_DIV_LATENCY 40 /* Latency for an FP divide. */ #define FP_MUL_LATENCY 10 /* Latency for an FP multiply. */ #define FP_LOAD_LATENCY 2 /* Latency for an FP load. */ #define FP_STORE_LATENCY 2 /* Latency for an FP store. */ /* default values for number of vector units and startup costs */ #define NUM_VECT_ADD 1 /* Number of vector adder units. */ #define NUM_VECT_DIV 1 /* Number of vector divider units. */ #define NUM_VECT_MUL 1 /* Number of vector multiplier units. */ #define NUM_VECT_LOAD 1 /* Number of vector load units. */ #define NUM_VECT_COMP 1 /* Number of vector comparison units. */ #define VECT_ADD_STARTUP 6 /* Start-up for a vector add. */ #define VECT_DIV_STARTUP 20 /* Start-up for a vector divide. */ #define VECT_MUL_STARTUP 7 /* Start-up for a vector multiply. */ #define VECT_LOAD_STARTUP 12 /* Start-up for a vector load. */ #define VECT_COMP_STARTUP 6 /* Start-up for a vector comparison. */ #define VECT_DEPEND_STALLS 4 /* Number of stalls if a vector computation depends on uncompleted computation */ #define FP_ADD 0 #define FP_DIV 1 #define FP_MUL 2 #define FP_SUB 3 #define INT_MUL 4 #define INT_UMUL 5 #define INT_DIV 6 #define INT_UDIV 7 #define FP_INT_OP 0 #define FP_SINGLE_FP_OP 1 #define FP_DOUBLE_FP_OP 2 #define VECT_ADD 0 #define VECT_DIV 1 #define VECT_MUL 2 #define VECT_LOAD 3 #define VECT_COMP 4 #define VECT_STORE 5 #define NOT_VECT 6 #define VECTOR 1 #define MASK 2 #define UNIMP 3 #define IFMT 1 #define JFMT 2 #define RFMT 3 /* pipeline stages */ #define IF 0 #define ID 1 #define EX 2 #define MEM 3 #define WB 4 #define DONE 5 #define EX_FP 6 #define MEM_FP 7 #define WB_FP 8 #define DONE_FP 9 #define YES 1 #define NO 0 #define CYC_CNT_RESET 16384 /* How often to reset the cycle count to prevent wrap around problems. */ #define FD_SIZE 32 /* Number of simulated file descriptors */ /* * OpCode values for MemWord structs. These are straight from the MIPS * manual except for the following special values: * * OP_NOT_COMPILED - means the value of the memory location has changed * so the instruction needs to be recompiled. * OP_UNIMP - means that this instruction is legal, but hasn't * been implemented in the simulator yet. * OP_RES - means that this is a reserved opcode (it isn't * supported by the architecture). */ #define OP_ADD 1 #define OP_ADDI 2 #define OP_ADDU 3 #define OP_ADDUI 4 #define OP_AND 5 #define OP_ANDI 6 #define OP_BEQZ 7 #define OP_BFPF 8 #define OP_BFPT 9 #define OP_BNEZ 10 #define OP_J 11 #define OP_JAL 12 #define OP_JALR 13 #define OP_JR 14 #define OP_LB 15 #define OP_LBU 16 #define OP_LD 17 #define OP_LF 18 #define OP_LH 19 #define OP_LHI 20 #define OP_LHU 21 #define OP_LW 22 #define OP_MOVD 23 #define OP_MOVF 24 #define OP_MOVFP2I 25 #define OP_MOVI2FP 26 #define OP_MOVI2S 27 #define OP_MOVS2I 28 #define OP_OR 29 #define OP_ORI 30 #define OP_RFE 31 #define OP_SB 32 #define OP_SD 33 #define OP_SEQ 34 #define OP_SEQI 35 #define OP_SEQU 36 #define OP_SEQUI 37 #define OP_SF 38 #define OP_SGE 39 #define OP_SGEI 40 #define OP_SGEU 41 #define OP_SGEUI 42 #define OP_SGT 43 #define OP_SGTI 44 #define OP_SGTU 45 #define OP_SGTUI 46 #define OP_SH 47 #define OP_SLE 48 #define OP_SLEI 49 #define OP_SLEU 50 #define OP_SLEUI 51 #define OP_SLL 52 #define OP_SLLI 53 #define OP_SLT 54 #define OP_SLTI 55 #define OP_SLTU 56 #define OP_SLTUI 57 #define OP_SNE 58 #define OP_SNEI 59 #define OP_SNEU 60 #define OP_SNEUI 61 #define OP_SRA 62 #define OP_SRAI 63 #define OP_SRL 64 #define OP_SRLI 65 #define OP_SUB 66 #define OP_SUBI 67 #define OP_SUBU 68 #define OP_SUBUI 69 #define OP_SW 70 #define OP_SYNC 71 #define OP_TRAP 72 #define OP_XOR 73 #define OP_XORI 74 #define OP_NOP 75 #define OP_ADDD 80 #define OP_ADDF 81 #define OP_CVTD2F 82 #define OP_CVTD2I 83 #define OP_CVTF2D 84 #define OP_CVTF2I 85 #define OP_CVTI2D 86 #define OP_CVTI2F 87 #define OP_DIV 88 #define OP_DIVD 89 #define OP_DIVF 90 #define OP_DIVU 91 #define OP_EQD 92 #define OP_EQF 93 #define OP_GED 94 #define OP_GEF 95 #define OP_GTD 96 #define OP_GTF 97 #define OP_LED 98 #define OP_LEF 99 #define OP_LTD 100 #define OP_LTF 101 #define OP_MULT 102 #define OP_MULTD 103 #define OP_MULTF 104 #define OP_MULTU 105 #define OP_NED 106 #define OP_NEF 107 #define OP_SUBD 108 #define OP_SUBF 109 #define OP_ADDSV 115 #define OP_ADDV 116 #define OP_CVI 117 #define OP_CVM 118 #define OP_DIVSV 119 #define OP_DIVV 120 #define OP_DIVVS 121 #define OP_LV 122 #define OP_LVI 123 #define OP_LVWS 124 #define OP_MOVF2S 125 #define OP_MOVS2F 126 #define OP_MULTSV 127 #define OP_MULTV 128 #define OP_POP 129 #define OP_SEQSV 130 #define OP_SEQV 131 #define OP_SGESV 132 #define OP_SGEV 133 #define OP_SGTSV 134 #define OP_SGTV 135 #define OP_SLESV 136 #define OP_SLEV 137 #define OP_SLTSV 138 #define OP_SLTV 139 #define OP_SNESV 140 #define OP_SNEV 141 #define OP_SUBSV 142 #define OP_SUBV 143 #define OP_SUBVS 144 #define OP_SV 145 #define OP_SVI 146 #define OP_SVWS 147 /* special "opcodes", give these values after the above op values */ #define OP_NOT_COMPILED 149 #define OP_UNIMP 150 #define OP_RES 151 #define OP_LAST 152 /* type of machine being simulated */ #define VECTOR 1 #define PIPE 2 #define SCORE 3 #define TOMASULO 4 typedef struct { Tcl_Interp *interp; /* Interpreter associated with machine (used * for interpreting commands, returning * errors, etc.) */ int machine; /* type of machine simulated: regular DLX, vector machine, pipelined machine */ int numWords; /* Number of words of memory simulated for * this machine. */ int numChars; /* Number of characters of memory */ MemWord *memPtr; /* Array of MemWords, sufficient to provide * memSize bytes of storage. */ char *memScratch; /* Scratchpad for use by trap handlers */ char *endScratch; /* Pointer to the end of the scratch pad */ int fd_map[FD_SIZE]; /* maps simulated fd's to actual fd's. * mainly protects the real standard * input, output, and error from the * program. A value of -1 means that * fd is not currently in use. */ int regs[TOTAL_REGS]; /* General-purpose registers, followed by * hi and lo multiply-divide registers, * followed by program counter and next * program counter. Both pc's are stored * as indexes into the memPtr array. */ unsigned int badPC; /* If an addressing error occurs during * instruction fetch, this value records * the bad address. 0 means no addressing * error is pending. */ int addrErrNum; /* If badPC is non-zero, this gives the * serial number (insCount value) of the * instruction after which the addressing * error is to be registered. */ int loadReg1, loadReg2; /* For loads, register loaded by last instruction. * used to watch for stalls (0 means last * instruction was not a load). loadReg2 is * used when a load double is done. */ int loadValue1, loadValue2; /* For loads, register value to load on next * cycle. */ int insCount; /* Count of total # of instructions executed * in this machine (i.e. serial number of * current instruction). */ int firstIns; /* Serial number corresponding to first * instruction executed in particular run; * used to ignore stops on first ins. */ int branchSerial; /* Serial number of most recent branch/jump * instruction; used to set BD bit during * exceptions. */ int branchPC; /* PC of instruction given by "branchSerial": * also used during exceptions. */ int flags; /* Used to indicate special conditions during * simulation (for greatest speed, should * normally be zero). See below for * definitions. */ int stopNum; /* Used to assign increasing reference * numbers to stops. */ Stop *stopList; /* First in chain of all spies and stops * associated with this machine (NULL means * none). */ CallBack *callBackList; /* First in linked list of all callbacks * currently registered for this machine, * sorted in increasing order of serialNum. */ Hash_Table symbols; /* Records addresses of all symbols read in * by assembler for machine. */ IoState ioState; /* I/O-related information for machine (see * io.h and io.c for details). */ Cop0 cop0; /* State of coprocessor 0 (see cop0.h and * cop0.c for details). */ /* statistics */ int stalls; /* Counts pipeline stalls */ int loadStalls; /* Counts load stalls */ int FPstalls; /* Counts floating point stalls */ int Vstalls; /* Counts vector stalls */ int branchYes; /* Count taken branches. */ int branchNo; /* Count not taken branches. */ int numb_bypass; /* Number of bypassed values */ int operationCount [OP_LAST+1]; /* Dynamic instruction counts */ /* pipeline stuff */ InstrInExec *stages[10]; /* each element of the array - an instruction which is in the certain pipeline stage at the moment */ /* scoreboard stuff */ res_for_bypass *bypass[6]; /* array for bypassing values: pointers from 0 to 2 point to the integer values available, from 3 to 5 - fp values */ /* floating point stuff */ int num_add_units; /* Number FP add units for this machine. */ int num_div_units; /* Number FP divide units for this machine. */ int num_mul_units; /* Number FP multiply units for this machine. */ int fp_add_latency; /* FP add/subtract latency for this machine. */ int fp_div_latency; /* FP divide latency for this machine. */ int fp_mul_latency; /* FP multiply latency for this machine. */ int num_load_units; /* Number FP load units for this machine. */ int num_store_units; /* Number FP store units for this machine. */ int fp_load_latency; /* FP load latency for this machine. */ int fp_store_latency; /* FP store latency for this machine. */ Scoreboard *score; /* scoreboarding data */ Tomasulo *tomasulo; /*tomasulo data */ int FPstatusReg; /* Floating point status register. Written on floating point compares, read on BFPT and BFPF instructions. */ int fp_add_units [MAX_FP_UNITS]; /* 0 means unit is available, otherwise number indicates cycle count when the adder will complete its current operation. */ int fp_div_units [MAX_FP_UNITS]; /* 0 means unit is available, otherwise number indicates cycle count when the divider will complete its current operation. */ int fp_mul_units [MAX_FP_UNITS]; /* 0 means unit is available, otherwise number indicates cycle count when the multiplier will complete its current operation. */ int *fp_units[3]; /* Top level array structure used to access fp_add_units, fp_div_units, and fp_mul_units. */ int waiting_FPRs[32]; /* A non-zero value in element i means FP register i is waiting for a result from an FP unit. The value indicates the cycle count when the result will be ready. */ InstrInExec *Pipe_FPopsList; /* First in a linked list of all floating point operationsin the EX stage of fp pipeline associated with this machine; NULL means none. */ FPop *FPopsList; /* First in a linked list of all pending floating point operations associated with this machine; NULL means none. */ int cycleCount; /* Keep track of how many cycles have been executed to monitor floating point units. */ int checkFP; /* Similar to the checkNum variable in sim.c. Represents the next cycle count at which some FP unit will complete an operation. Allows for quick checking in fast path. */ /* vector stuff */ VR* VRegs; /* Vector registers */ int mvl; /* Maximum vector length */ int num_vrs; /* number of vector registers */ int num_vect_add; /* Number vector add units for this machine. */ int num_vect_div; /* Number vector divide units for this machine. */ int num_vect_mul; /* Number vector multiply units for this machine. */ int num_vect_load; /* Number vector load units for this machine. */ int num_vect_comp; /* Number vector comparison units for this machine. */ int vect_add_startup; /* Vector add/subtract startup for this machine. */ int vect_div_startup; /* Vector divide startup for this machine. */ int vect_mul_startup; /* Vector multiply startup for this machine. */ int vect_load_startup; /* Vector load startup for this machine. */ int vect_comp_startup; /* Vector comparison startup for this machine. */ int VLR; /* General-purpose vector-length-register*/ char *VM; /* Floating Point vector-mask register */ short VM_Loaded; /* 0 - if vector-mask is loaded, 1 - otherwise */ int vect_add_units [MAX_VECT_UNITS]; /* shows which vector element is in the each pipeline stage of the vector add unit */ int vect_div_units [MAX_VECT_UNITS]; /* shows which vector element is in the each pipeline stage of the vector divide unit */ int vect_mul_units [MAX_VECT_UNITS]; /* shows which vector element is in the each pipeline stage of the vector multiply unit */ int vect_load_units [MAX_VECT_UNITS]; /* shows which vector element is in the each pipeline stage of the vector load unit */ int vect_comp_units [MAX_VECT_UNITS]; /* shows which vector element is in the each pipeline stage of the vector comparison unit */ int *vect_units[5]; /* Top level array structure used to access vect_add_units, vect_div_units, vect_mul_units, vect_load_units and vect_comp_units.*/ int waiting_VectRs [NUM_VRS + 1]; /* A non-zero value in element i means Vector register i is waiting for a result from a Vector unit (the last value is for the vector-mask register). The value indicates the cycle count when the result will be ready.*/ int being_read_VectRs [NUM_VRS + 1]; /* A non-zero value in element i means Vector register i is being read from. The value indicates the cycle count when the register will be read. */ Vectop *VectopsList; /* First in a linked list of all pending vector operations associated with this machine; NULL means none. */ int checkVect; /* Similar to the checkNum variable in sim.c. Represents the next cycle count at which some vector unit will complete an operation. Allows for quick checking in fast path. */ FILE *refTraceFile; /* Pointer to a file into which to write memory references for the cache simulator. */ } DLX; /* * Flag values for DLX structures: * * STOP_REQUESTED: 1 means that the "stop" command has been * executed and execution should stop ASAP. * */ #define STOP_REQUESTED 0x4 /* * Conversion between DLX addresses and indexes, which are stored * in pc/nextPc fields of DLX structures and also used to address * the memPtr values: */ #define INDEX_TO_ADDR(index) ((unsigned) (index << 2)) #define ADDR_TO_INDEX(addr) (addr >> 2) /* * Miscellaneous definitions: */ #define SIGN_BIT 0x80000000 #define R31 31 /* * Tcl command procedures provided by the simulator: */ extern int Gp_GetCmd(), Gp_PutCmd(); extern int Gp_FGetCmd(), Gp_FPutCmd(); extern int Gp_VGetCmd(), Gp_VPutCmd(); extern int Sim_GoCmd(), Sim_StepCmd(); extern int Stop_StopCmd(), Sim_DumpStats(); extern int Sim_TraceCmd(); /* * Other procedures that are exported from one file to another: */ extern void Sim_CallBack(); extern DLX * Sim_Create(); extern unsigned int Sim_GetPC(); extern void Sim_Stop(); extern int Stop_Execute(); extern void LoadVector(); extern void StoreVector(); extern void VectorArithmetic(); extern void MoveMask(); extern Vectop *mallocVectop(); extern void freeFPop(); extern int Vectissue(); extern int AddressError(); extern int ReadMem(); extern int WriteMem(); #endif /* _MIPS */