/* Code modified by Chien-I Liao */ /* Apr 22 2005 */ /* Code for the simulated toy machine, a simulated architecture supporting variable-length partitions. THIS CODE IS TAKEN from Professor Ernie Davis with permission. */ #include #include #include #define RAMSIZE 262144 /* 2**18 address space */ #define NUMREGS 16 #define NAMESIZE 32 /* maximum size of process name */ ///////// New Macros #define MAXPROCESS 20 /* maximum number of process allowed */ #define MAXQUEUE 21 /* size of queue */ #define HALT -1 #define GOTTRAP -2 #define NORMAL 0 /* Global variables for the simulated architecture --- DO NOT CHANGE */ int mem[RAMSIZE], /* Core memory */ regs[NUMREGS], /* Number of registers */ base, /* Base register */ limit; /* limit register */ char codes[16][4] = /* Abbreviations for opcodes */ { "LOA", "STO", "CPR", "LOI", "STI", "ADD", "SUB", "MUL", "DIV", "ICR", "DCR", "GTR", "JMP", "IFZ", "JMI", "TRP" }; /* Other global variables */ int debug = 0, /* Level of debugging */ error = 0, /* Error flag */ terminate = 0, /* Termination flag */ maxinst = -1, /* Maximum number of instructions */ procindex = 0; /* Index of process */ // Modified global variables int numproc = 0, /* Number of process */ quantum = 5; /* Quantum */ //////// Process Table definition and FIFO queue declaration typedef struct process_table{ char procname[NAMESIZE]; ///// name of process int reg[NUMREGS]; ///// registers int base; ///// base register int limit; ///// limit register } PROC_TBL; PROC_TBL tbl[MAXPROCESS]; int queue[MAXQUEUE]; //////// Multiple process name char filename[MAXPROCESS][NAMESIZE]; /* name of files */ /* Extract the flags from the command line: base, debug, and maxinst. The index of the STM filename in the command is returned as the value. */ //////int parse_flags(argc,argv) //////int argc; //////char *argv[]; void parse_flags(int argc, char *argv[]) { int ibase = 0, idebug = 0, imax=0, iquan=0; ///////, ifilename=1; /* Positions of arguments in command line */ int i; for (i=1; i= 0) && (reladd < limit)) return(reladd+base); else { error = 1; printf("Error: Address out of bounds\n"); return(0); } } /* Display STM instruction for level-2 debugging */ void show_inst(op, ra, ad, rb, rc, rd) int op, ra, ad, rb, rc, rd; { printf("Process %i %s instruction 0x%X : %3s", procindex, tbl[procindex].procname, regs[0], codes[op]); switch(op) { case 0: case 1: case 13: printf(" R%i Address 0x%X", ra, ad); break; case 12: printf(" Address 0x%X", ad); break; case 2: case 3: case 4: printf(" R%i R%i", ra, rb); break; case 5: case 6: case 7: case 11: printf(" R%i R%i R%i", ra, rb, rc); break; case 8: printf(" R%i R%i R%i R%i", ra, rb, rc, rd); break; case 9: case 10: case 14: printf(" R%i ", ra); break; } printf("\n"); } /* Decompose an STM instruction into its components */ /* Note: This is considered part of the "hardware" of the virtual machine. You may not change it in any of the projects. */ void get_inst(inst, pop, pra, pad, prb, prc, prd) int inst, *pop, *pra, *pad, *prb, *prc, *prd; { *pop = inst % 16; inst = inst / 16; *pra = inst % 16; inst = inst / 16; *pad = inst % RAMSIZE; *prb = inst % 16; inst = inst / 16; *prc = inst % 16; inst = inst / 16; *prd = inst % 16; if (debug == 2) show_inst(*pop, *pra, *pad, *prb, *prc, *prd); } /* Execute an STM instruction. This is what does the actual work of carrying out the STM code */ /* Note: This is considered part of the "hardware" of the virtual machine. You may not change it in any of the projects. */ int exec_inst(op, ra, ad, rb, rc, rd) int op, ra, ad, rb, rc, rd; { int regrep = 0; /* Flag for repeated registers */ int trap = 0; switch (op) { case 0: regs[ra] = mem[phys_address(ad)]; break; case 1: mem[phys_address(ad)] = regs[ra]; break; case 2: regs[ra] = regs[rb]; break; case 3: regs[ra] = mem[phys_address(regs[rb])]; break; case 4: mem[phys_address(regs[ra])] = regs[rb]; break; case 5: regs[rc] = regs[ra] + regs[rb]; break; case 6: regs[rc] = regs[ra] - regs[rb]; break; case 7: regs[rc] = regs[ra] * regs[rb]; break; case 8: if (regs[rb] == 0) { printf("Arithmetic error: Divide by zero\n"); error = 1; } else { regs[rc] = regs[ra] / regs[rb]; regs[rd] = regs[ra] % regs[rb]; } break; case 9: regs[ra]++; break; case 10: regs[ra]--; break; case 11: regs[rc] = (regs[ra] > regs[rb]); break; case 12: regs[0] = ad; break; case 13: if (regs[ra] == 0) regs[0] = ad; break; case 14: regs[0] = regs[ra]; break; case 15: trap = 1; break; } return(trap); } /* Execute a trap */ void exec_trap() { int iread; if (debug) printf("Process %s index %i Trap: " ,tbl[procindex].procname, procindex); switch(regs[15]) { case 0: terminate=1; if (debug) printf(" Terminate\n"); break; case 1: if (debug) printf(" Read\n"); printf("Process %d %s input : " ,procindex,tbl[procindex].procname); iread = scanf("%i",®s[14]); if (debug) printf(" READ %i\n", regs[14]); if (iread ==1) regs[13]=1; else if (iread==EOF) regs[13]=0; else error=1; break; case 2: if (debug) printf("\n WRITE: "); printf("Process %d : %s output : " ,procindex,tbl[procindex].procname); printf("%i \n",regs[14]); break; default: printf("Invalid trap code\n"); error=1; break; } } /* fetch and execute an instruction of STM code */ int exec_stm() { int opcode, rega, ad, regb, regc, regd; /* Components of STML instruction */ int trap; /* flag that code executes a trap */ int padd; /* physical address */ int i; padd=phys_address(regs[0]); if (debug == 2) { printf("Registers: "); for (i=0; i<16; i++) printf(" %3i", regs[i]); printf("\n"); printf("address 0x%X instruction 0x%X\n", regs[0], mem[padd]); } get_inst(mem[padd], &opcode, ®a, &ad, ®b, ®c, ®d); /* fetch instruction */ if (!error) { regs[0]++; /* increment PC */ if (regs[0] >= limit) error=1; else { trap = exec_inst(opcode, rega, ad, regb, regc, regd); /*execute*/ if (trap) exec_trap(); /* handle trap */ } } if (terminate){ terminate=0; return HALT; } if (error){ error=0; return HALT; } if (trap) return GOTTRAP; return NORMAL; } /* main: initialize, load, execute */ int main(argc, argv) int argc; char *argv[]; { int i; int start,end; //// indicate start and end of queue; int qq; //// indicate quantum; int context_switch=0; //// flag for context switching int inst=0; //// indicate # of instruction executed initialize(argc,argv); start=0; end=numproc%MAXQUEUE; while(start!=end){ ///// Still some process to execute procindex=queue[start]; base=tbl[queue[start]].base; ///// Load process base register limit=tbl[queue[start]].limit; /// Load process limit register for(i=0;i0){ if(inst==maxinst) break; inst++; switch(exec_stm()){ case NORMAL: qq--; /// decrease quantum break; case GOTTRAP: if(debug==2) printf("Context Switch : Process %d -> Process %d\n" , queue[start], queue[(start+1)%MAXQUEUE]); for(i=0;i Process %d\n" , queue[start], queue[(start+1)%MAXQUEUE]); for(i=0;i