| @@ -0,0 +1,41 @@ | ||
| # | ||
| # Makefile for the Linux simulator | ||
| # | ||
| ######################################################## | ||
|
|
||
| PROGRAM = Simulator | ||
|
|
||
| # Compilation Details | ||
| SHELL = /bin/sh | ||
| CC = cc | ||
| STDCFLAGS = -g -c -Wall | ||
| INCLUDES = | ||
| LIBRARIES = | ||
|
|
||
| ${PROGRAM}: Simulator.o ComputerSystem.o MainMemory.o OperatingSystem.o Processor.o Buses.o Messages.o | ||
| $(CC) -o ${PROGRAM} Simulator.o ComputerSystem.o MainMemory.o OperatingSystem.o Processor.o Buses.o Messages.o $(LIBRARIES) | ||
|
|
||
| Simulator.o: Simulator.c Simulator.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) Simulator.c | ||
|
|
||
| Messages.o: Messages.c Messages.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) Messages.c | ||
|
|
||
| ComputerSystem.o: ComputerSystem.c ComputerSystem.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) ComputerSystem.c | ||
|
|
||
| MainMemory.o: MainMemory.c MainMemory.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) MainMemory.c | ||
|
|
||
| OperatingSystem.o: OperatingSystem.c OperatingSystem.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) OperatingSystem.c | ||
|
|
||
| Processor.o: Processor.c Processor.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) Processor.c | ||
|
|
||
|
|
||
| Buses.o: Buses.c Buses.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) Buses.c | ||
|
|
||
| clean: | ||
| rm -f $(PROGRAM) *.o *~ core |
| @@ -0,0 +1,57 @@ | ||
| #include "Messages.h" | ||
|
|
||
| #include <stdio.h> | ||
| #include <string.h> | ||
|
|
||
| #define MSGMAXIMUMLENGTH 132 | ||
| #define MESSAGES_FILE "messages.txt" | ||
| #define NUMBEROFMSGS 64 | ||
|
|
||
|
|
||
|
|
||
| int Messages_Load_Messages() { | ||
| char lineRead[MSGMAXIMUMLENGTH]; | ||
| FILE *mf; | ||
| char *number, *text; | ||
| int msgNumber; | ||
| int lineNumber=0;; | ||
| int numberErrorMessages=0; | ||
| int rc; | ||
|
|
||
| mf=fopen(MESSAGES_FILE, "r"); | ||
| if (mf==NULL) { | ||
| printf("Verbose messages unavailable\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| while (fgets(lineRead, MSGMAXIMUMLENGTH, mf) != NULL) { | ||
| lineNumber++; | ||
| number=strtok(lineRead,","); | ||
| rc=sscanf(number,"%d",&msgNumber); | ||
| if (rc==0){ | ||
| printf("Illegal Message Number in line %d of file %s\n",lineNumber,MESSAGES_FILE); | ||
| continue; | ||
| } | ||
|
|
||
| text=strtok(NULL,"\n"); | ||
| if (text==NULL){ | ||
| printf("Illegal Message Format in line %d of file %s\n",lineNumber,MESSAGES_FILE); | ||
| continue; | ||
| } | ||
| strcpy(DebugMessages[numberErrorMessages].format,text); | ||
| DebugMessages[numberErrorMessages++].number=msgNumber; | ||
|
|
||
|
|
||
| } | ||
| fclose(mf); | ||
| return numberErrorMessages; | ||
| } | ||
|
|
||
| int Messages_Get_Pos(int number) { | ||
| int pos; | ||
|
|
||
| for (pos=0; DebugMessages[pos].number !=-1; pos++) | ||
| if (DebugMessages[pos].number==number) return pos; | ||
|
|
||
| return -1; | ||
| } |
| @@ -0,0 +1,17 @@ | ||
| #ifndef MESSAGES_H | ||
| #define MESSAGES_H | ||
|
|
||
| #define NUMBEROFMSGS 64 | ||
|
|
||
| typedef struct { | ||
| int number; | ||
| char format[60]; | ||
| } DEBUG_MESSAGES; | ||
|
|
||
| DEBUG_MESSAGES DebugMessages[NUMBEROFMSGS]; | ||
|
|
||
| int Messages_Get_Pos(int number); | ||
| int Messages_Load_Messages(); | ||
|
|
||
| #endif | ||
|
|
| @@ -0,0 +1,68 @@ | ||
| #include "OperatingSystem.h" | ||
| #include "MainMemory.h" | ||
| #include "Processor.h" | ||
| #include "Buses.h" | ||
| #include <stdio.h> | ||
| #include <string.h> | ||
| #include <ctype.h> | ||
| #include <stdlib.h> | ||
|
|
||
| // Function that processes the contents of the file named by the first argument | ||
| // in order to load it in main memory from the address given as the second | ||
| // argument | ||
| // IT IS NOT NECESSARY TO COMPLETELY UNDERSTAND THIS FUNCTION | ||
|
|
||
| int OperatingSystem_LoadProgram(FILE *programFile, int initialAddress) { | ||
|
|
||
| char lineRead[LINEMAXIMUMLENGTH]; | ||
| char *token0, *token1, *token2; | ||
| int isComment=1; | ||
| int programSize; | ||
| MEMORYCELL data; | ||
|
|
||
| // Read the first number as the size of the program. Skip all comments. | ||
| while (isComment==1) { | ||
| if (fgets(lineRead, LINEMAXIMUMLENGTH, programFile) == NULL) { | ||
| return PROGRAMNOTVALID; | ||
| } | ||
| else | ||
| if (lineRead[0]!='/') { // Line IS NOT a comment | ||
| isComment=0; | ||
| programSize=atoi(strtok(lineRead," ")); | ||
| if (programSize>MAINMEMORYSIZE) | ||
| return PROGRAMNOTVALID; | ||
| } | ||
| } | ||
|
|
||
| Processor_SetMAR(initialAddress); | ||
| while (fgets(lineRead, LINEMAXIMUMLENGTH, programFile) != NULL) { | ||
| // REMARK: if lineRead is greater than TAMANIOMAXIMOLINEA in number of characters, the program | ||
| // loading does not work | ||
| data.operationCode=' '; data.operand1=data.operand2=0; | ||
| token0=strtok(lineRead," "); | ||
| if ((token0!=NULL) && (token0[0]!='/')&& (token0[0]!='\n')) { | ||
| // I have an instruction with, at least, an operation code | ||
| data.operationCode=tolower(token0[0]); | ||
| token1=strtok(NULL," "); | ||
| if ((token1!=NULL) && (token1[0]!='/')) { | ||
| // I have an instruction with, at least, an operand | ||
| data.operand1=atoi(token1); | ||
| token2=strtok(NULL," "); | ||
| if ((token2!=NULL) && (token2[0]!='/')) { | ||
| // The read line is similar to 'sum 2 3 //coment' | ||
| // I have an instruction with two operands | ||
| data.operand2=atoi(token2); | ||
| } | ||
| } | ||
|
|
||
| Processor_SetMBR(&data); | ||
| // Send data to main memory using the system buses | ||
| Buses_write_DataBus_From_To(CPU, MAINMEMORY); | ||
| Buses_write_AddressBus_From_To(CPU, MAINMEMORY); | ||
| // Tell the main memory controller to write | ||
| MainMemory_writeMemory(); | ||
| Processor_SetMAR(Processor_GetMAR()+1); | ||
| } | ||
| } | ||
| return SUCCESS; | ||
| } |
| @@ -0,0 +1,15 @@ | ||
| #ifndef OPERATINGSYSTEM_H | ||
| #define OPERATINGSYSTEM_H | ||
|
|
||
| #include <stdio.h> | ||
|
|
||
| #define SUCCESS 1 | ||
| #define PROGRAMDOESNOTEXIST -1 | ||
| #define PROGRAMNOTVALID -2 | ||
|
|
||
| #define LINEMAXIMUMLENGTH 150 | ||
|
|
||
| // Functions prototypes | ||
| int OperatingSystem_LoadProgram(FILE *, int); | ||
|
|
||
| #endif |
| @@ -0,0 +1,167 @@ | ||
| #include "Processor.h" | ||
| #include "ComputerSystem.h" | ||
| #include "Buses.h" | ||
| #include "MainMemory.h" | ||
| #include <stdio.h> | ||
| #include <string.h> | ||
| #include <stdlib.h> | ||
|
|
||
| // Local Functions prototypes | ||
| void Processor_FetchInstruction(); | ||
| void Processor_DecodeAndExecuteInstruction(); | ||
| void Processor_ManageInterrupts(); | ||
|
|
||
|
|
||
| // Processor registers | ||
| int registerPC_CPU; // Program counter | ||
| int registerAccumulator_CPU; // Accumulator | ||
| MEMORYCELL registerIR_CPU; // Instruction register | ||
| unsigned int registerPSW_CPU; // Processor state word | ||
| int registerMAR_CPU; // Memory Address Register | ||
| MEMORYCELL registerMBR_CPU; // Memory Buffer Register | ||
|
|
||
| // Initialize processor registers | ||
| void Processor_InitializeRegisters(int regPC, int regAcum, unsigned int regPSW) { | ||
| registerPC_CPU=regPC; | ||
| registerAccumulator_CPU=regAcum; | ||
| registerPSW_CPU=regPSW; | ||
| } | ||
|
|
||
| // This is the instruction cycle loop (fetch, decoding, execution, etc.). | ||
| // The processor stops working when an POWEROFF signal is stored in its | ||
| // PSW register | ||
| void Processor_InstructionCycleLoop() { | ||
|
|
||
| while (registerPSW_CPU!=POWEROFF) { | ||
| Processor_FetchInstruction(); | ||
| Processor_DecodeAndExecuteInstruction(); | ||
| Processor_ManageInterrupts(); | ||
| } | ||
| } | ||
|
|
||
| // Fetch an instruction from main memory and put it in the IR register | ||
| void Processor_FetchInstruction() { | ||
|
|
||
| // The instruction must be located at the memory address pointed by the PC register | ||
| registerMAR_CPU=registerPC_CPU; | ||
| // Send to the main memory controller the address in which the reading has to take place: use the address bus for this | ||
| Buses_write_AddressBus_From_To(CPU, MAINMEMORY); | ||
| // Tell the main memory controller to read | ||
| MainMemory_readMemory(); | ||
| // All the read data is stored in the MBR register. Because it is an instruction | ||
| // we have to copy it to the IR register | ||
| memcpy((void *) (®isterIR_CPU), (void *) (®isterMBR_CPU), sizeof(MEMORYCELL)); | ||
| // Show initial part of HARDWARE message with Operation Code and operands | ||
| ComputerSystem_DebugMessage(1, HARDWARE, registerIR_CPU.operationCode, registerIR_CPU.operand1, registerIR_CPU.operand2); | ||
|
|
||
| } | ||
|
|
||
| // Decode and execute the instruction in the IR register | ||
| void Processor_DecodeAndExecuteInstruction() { | ||
|
|
||
| switch (registerIR_CPU.operationCode) { | ||
|
|
||
| // Instruction ADD | ||
| case 'a': registerAccumulator_CPU= registerIR_CPU.operand1 + registerIR_CPU.operand2; | ||
| registerPC_CPU++; | ||
| break; | ||
|
|
||
| // Instruction SUB | ||
| case 's': registerAccumulator_CPU= registerIR_CPU.operand1 - registerIR_CPU.operand2; | ||
| registerPC_CPU++; | ||
| break; | ||
|
|
||
|
|
||
| // Instruction NOP | ||
| case 'n': registerPC_CPU++; | ||
| break; | ||
|
|
||
| // Instruction JUMP | ||
| case 'j': registerPC_CPU+= registerIR_CPU.operand1; | ||
| break; | ||
|
|
||
| // Instruction ZJUMP | ||
| case 'z': if (registerAccumulator_CPU==0) | ||
| registerPC_CPU+= registerIR_CPU.operand1; | ||
| else | ||
| registerPC_CPU++; | ||
| break; | ||
|
|
||
| // Instruction WRITE | ||
| case 'w': registerMBR_CPU.operationCode= registerMBR_CPU.operand1= registerMBR_CPU.operand2= registerAccumulator_CPU; | ||
| registerMAR_CPU=registerIR_CPU.operand1; | ||
| // Send to the main memory controller the data to be written: use the data bus for this | ||
| Buses_write_DataBus_From_To(CPU, MAINMEMORY); | ||
| // Send to the main memory controller the address in which the writing has to take place: use the address bus for this | ||
| Buses_write_AddressBus_From_To(CPU, MAINMEMORY); | ||
| // Tell the main memory controller to write | ||
| MainMemory_writeMemory(); | ||
| registerPC_CPU++; | ||
| break; | ||
|
|
||
| // Instruction READ | ||
| case 'r': registerMAR_CPU=registerIR_CPU.operand1; | ||
| // Send to the main memory controller the address in which the reading has to take place: use the address bus for this | ||
| Buses_write_AddressBus_From_To(CPU, MAINMEMORY); | ||
| // Tell the main memory controller to read | ||
| MainMemory_readMemory(); | ||
| // Copy the read data to the accumulator register | ||
| registerAccumulator_CPU= registerMBR_CPU.operand1; | ||
| registerPC_CPU++; | ||
| break; | ||
|
|
||
| // Instruction INC | ||
| case 'i': registerAccumulator_CPU+= registerIR_CPU.operand1; | ||
| registerPC_CPU++; | ||
| break; | ||
|
|
||
| // Instruction HALT | ||
| case 'h': registerPSW_CPU=POWEROFF; | ||
| break; | ||
|
|
||
| //Instruction MEMADD | ||
| case 'm': registerMAR_CPU=registerIR_CPU.operand1; | ||
| // Send to the main memory controller the address in which the reading has to take place: use the address bus for this | ||
| Buses_write_AddressBus_From_To(CPU, MAINMEMORY); | ||
| // Tell the main memory controller to read | ||
| MainMemory_readMemory(); | ||
| //Perform the addition | ||
| registerAccumulator_CPU = registerIR_CPU.operand1 + registerIR_CPU.operand2; | ||
| registerPC_CPU++; | ||
| break; | ||
|
|
||
| // Unknown instruction | ||
| default : registerPC_CPU++; | ||
| break; | ||
| } | ||
| // Show final part of HARDWARE message with CPU registers | ||
| ComputerSystem_DebugMessage(3,HARDWARE,registerPC_CPU,registerAccumulator_CPU, registerPSW_CPU); | ||
| } | ||
|
|
||
| // Hardware interrup processing | ||
| // Our primitive processor DOES NOT SUPPORT interrupts | ||
| void Processor_ManageInterrupts() { | ||
|
|
||
| } | ||
|
|
||
| // Getter for the registerMAR_CPU | ||
| int Processor_GetMAR() { | ||
| return registerMAR_CPU; | ||
| } | ||
|
|
||
| // Setter for the registerMAR_CPU | ||
| void Processor_SetMAR(int data) { | ||
| registerMAR_CPU=data; | ||
| } | ||
|
|
||
| // pseudo-getter for the registerMBR_CPU | ||
| void Processor_GetMBR(MEMORYCELL *toRegister) { | ||
| memcpy((void*) toRegister, (void *) (®isterMBR_CPU), sizeof(MEMORYCELL)); | ||
| } | ||
|
|
||
| // pseudo-setter for the registerMBR_CPU | ||
| void Processor_SetMBR(MEMORYCELL *fromRegister) { | ||
| memcpy((void*) (®isterMBR_CPU), (void *) fromRegister, sizeof(MEMORYCELL)); | ||
| } | ||
|
|
||
|
|
| @@ -0,0 +1,18 @@ | ||
| #ifndef PROCESSOR_H | ||
| #define PROCESSOR_H | ||
|
|
||
| #include "MainMemory.h" | ||
|
|
||
| #define POWEROFF 1 | ||
|
|
||
| // Functions prototypes | ||
| void Processor_InitializeRegisters(int, int, unsigned int); | ||
| void Processor_InstructionCycleLoop(); | ||
|
|
||
| // Buses needs to access MAR and MBR | ||
| int Processor_GetMAR(); | ||
| void Processor_SetMAR(int); | ||
| void Processor_GetMBR(MEMORYCELL *); | ||
| void Processor_SetMBR(MEMORYCELL *); | ||
|
|
||
| #endif |
| @@ -0,0 +1,24 @@ | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include "Simulator.h" | ||
| #include "ComputerSystem.h" | ||
|
|
||
|
|
||
| int main(int argc, char *argv[]) { | ||
|
|
||
| // Our Computer System is very primitive. It is monoprogrammed | ||
| // so it can only execute one program per simulation session. | ||
| // The program to be executed is specified in the function | ||
| // ComputerSystem_PowerOn() | ||
|
|
||
| if (argc != 2) { | ||
| printf("USE: Simulator <sections to be debugged>\n"); | ||
| exit(-1); | ||
| } | ||
|
|
||
| // The simulation starts | ||
| ComputerSystem_PowerOn(argc, argv); | ||
| // The simulation ends | ||
| ComputerSystem_PowerOff(); | ||
| return 0; | ||
| } |
| @@ -0,0 +1,14 @@ | ||
| #ifndef SIMULATOR_H | ||
| #define SIMULATOR_H | ||
|
|
||
|
|
||
| // Overall constants | ||
|
|
||
| // Monoprogrammed system (a very primitive one) | ||
| #define MAXNUMPROCESSES 1 | ||
|
|
||
| // Maximum number of user programs in command line (not used in this version) | ||
| #define MAXNUMUSERPROGRAMS 20 | ||
|
|
||
|
|
||
| #endif |
| @@ -0,0 +1,3 @@ | ||
| 1,%c %d %d | ||
| 3,(PC: @R%d@@, Accumulator: @R%d@@, PSW: @R%d@@)\n | ||
| 4,(@REND of the simulation@@)\n |
| @@ -0,0 +1,7 @@ | ||
| // Mi primer programa | ||
| 55 // Tamanio del programa en posiciones de memoria | ||
| MEM ADD 10 0 | ||
| INC -1 | ||
| ZJUMP 2 // Si el registro acumulador==0, saltar dos posiciones de memoria hacia adelante | ||
| JUMP -2 // Saltar dos posiciones de memoria hacia atr�s | ||
| HALT |
| @@ -0,0 +1,32 @@ | ||
| # 1 "MyAspect.c" | ||
| # 1 "<built-in>" | ||
| # 1 "<command-line>" | ||
| # 1 "/usr/include/stdc-predef.h" 1 3 4 | ||
| # 1 "<command-line>" 2 | ||
| # 1 "MyAspect.c" | ||
| # 1 "Clock.h" 1 | ||
|
|
||
|
|
||
|
|
||
|
|
||
| void Clock_Update(); | ||
| int Clock_GetTime(); | ||
| # 2 "MyAspect.c" 2 | ||
| # 1 "Asserts.h" 1 | ||
| # 37 "Asserts.h" | ||
| int Asserts_LoadAsserts(); | ||
| void Asserts_CheckAsserts(); | ||
| # 3 "MyAspect.c" 2 | ||
|
|
||
|
|
||
| before(): execution(void Processor_FetchInstruction()) { | ||
| Clock_Update(); | ||
| } | ||
|
|
||
| after(): execution(void Processor_DecodeAndExecuteInstruction()){ | ||
| Asserts_CheckAsserts(); | ||
| } | ||
|
|
||
| before(): execution(void OperatingSystem_InterruptLogic(int)){ | ||
| Clock_Update(); | ||
| } |
| @@ -0,0 +1,79 @@ | ||
|
|
||
| struct JoinPoint { | ||
| void** (*fp) (struct JoinPoint *); | ||
| void ** args; | ||
| int argsCount; | ||
| const char ** argsType; | ||
| void * (*arg)(int, struct JoinPoint *); | ||
| const char * (*argType)(int , struct JoinPoint *); | ||
| void ** retValue; | ||
| const char * retType; | ||
| const char * funcName ; | ||
| const char * targetName ; | ||
| const char * fileName ; | ||
| const char * kind ; | ||
| void * excep_return ; | ||
| }; | ||
|
|
||
| struct __UTAC__EXCEPTION { | ||
| void * jumpbuf ; | ||
| unsigned long long int prtValue ; | ||
| int pops; | ||
| struct __UTAC__CFLOW_FUNC { | ||
| int (*func)(int,int) ; | ||
| int val ; | ||
| struct __UTAC__CFLOW_FUNC * next; | ||
| } * cflowfuncs; | ||
| }; | ||
|
|
||
| extern void __utac__exception__cf_handler_set(void * exception, int (*cflow_func)(int, int), int val) ; | ||
| extern void __utac__exception__cf_handler_free(void * exception); | ||
| extern void __utac__exception__cf_handler_reset(void * exception) ; | ||
| extern void * __utac__error_stack_mgt(void * env , int mode, int count) ; | ||
|
|
||
| # 1 "MyAspect.c" | ||
| # 1 "<built-in>" | ||
| # 1 "<command-line>" | ||
| # 1 "/usr/include/stdc-predef.h" 1 3 4 | ||
| # 1 "<command-line>" 2 | ||
| # 1 "MyAspect.c" | ||
| # 5 "Clock.h" 1 | ||
| void Clock_Update(); | ||
| #line 6 "Clock.h" | ||
| int Clock_GetTime(); | ||
| # 2 "MyAspect.c" 2 | ||
| # 1 "Asserts.h" 1 | ||
| # 37 "Asserts.h" | ||
| int Asserts_LoadAsserts(); | ||
| #line 38 "Asserts.h" | ||
| void Asserts_CheckAsserts(); | ||
| #line 5 "MyAspect.c" | ||
| inline void __utac_acc__Aspect__1(void) { | ||
|
|
||
|
|
||
|
|
||
| #line 6 "MyAspect.c" | ||
| Clock_Update(); } | ||
|
|
||
|
|
||
| #line 9 "MyAspect.c" | ||
| inline void __utac_acc__Aspect__2(void) { | ||
|
|
||
|
|
||
|
|
||
| #line 10 "MyAspect.c" | ||
| Asserts_CheckAsserts(); } | ||
|
|
||
|
|
||
| #line 13 "MyAspect.c" | ||
| inline void __utac_acc__Aspect__3(void) { | ||
|
|
||
|
|
||
|
|
||
| #line 14 "MyAspect.c" | ||
| Clock_Update(); } | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
| @@ -0,0 +1,339 @@ | ||
| #include "Asserts.h" | ||
| #include <string.h> | ||
| #include <stdio.h> | ||
| #include "MainMemory.h" | ||
| #include "Clock.h" | ||
| #include "ComputerSystemBase.h" | ||
| #include "MMU.h" | ||
|
|
||
| extern MEMORYCELL mainMemory[]; | ||
| extern int registerPC_CPU; // Program counter | ||
| extern int registerAccumulator_CPU; // Accumulator | ||
| extern MEMORYCELL registerIR_CPU; // Instruction register | ||
| extern unsigned int registerPSW_CPU; // Processor state word | ||
| extern int registerMAR_CPU; // Memory Address Register | ||
| extern MEMORYCELL registerMBR_CPU; // Memory Buffer Register | ||
| extern int executingProcessID; // Executing process PID | ||
|
|
||
|
|
||
| char *elements[]={ | ||
| "RMEM_OP", | ||
| "RMEM_O1", | ||
| "RMEM_O2", | ||
| "AMEM_OP", | ||
| "AMEM_O1", | ||
| "AMEM_O2", | ||
| "PC", | ||
| "ACC", | ||
| "IR_OP", | ||
| "IR_O1", | ||
| "IR_O2", | ||
| "PSW", | ||
| "MAR", | ||
| "MBR_OP", | ||
| "MBR_O1", | ||
| "MBR_O2", | ||
| "MMU_BS", | ||
| "MMU_LM", | ||
| "MMU_MAR", | ||
| "MMEM_MAR", | ||
| "MMBR_OP", | ||
| "MMBR_O1", | ||
| "MMBR_O2", | ||
| "XPID", | ||
| NULL}; | ||
|
|
||
| struct assert { | ||
| int time; | ||
| int value; | ||
| char element[E_SIZE]; // Se almacenará lo arriba indicado o MEM si es un elemento de memoria (o RMEM y AMEM en su caso) | ||
| int address; | ||
| } asserts[MAX_ASSERTS]; | ||
|
|
||
| extern int GEN_ASSERTS; | ||
|
|
||
| int elementNumber(char *cmp) { | ||
| int n=0; | ||
|
|
||
| while ((elements[n]!=NULL) && strcmp(cmp, elements[n])) | ||
| n++; | ||
|
|
||
| if (elements[n]==NULL) return -1; | ||
| else return n; | ||
|
|
||
| } | ||
|
|
||
| void strcmpSpaces(char *target, char *src, int nChars) { | ||
| int l, s, t; | ||
|
|
||
| l=strlen(src); | ||
| t=0; | ||
| for (s=0; (t<nChars-1) && (s<l); s++) { | ||
| if (src[s]!=' ') target[t++]=src[s]; | ||
| } | ||
| target[t]=0; | ||
| } | ||
|
|
||
| int Asserts_LoadAsserts() { | ||
| // leer el fichero e ir almacenando en cada elemento lo que sea; | ||
| struct assert a; | ||
|
|
||
| char lineRead[MAXIMUMLENGTH]; | ||
| FILE *mf; | ||
| char *time, *element, *value, *address; | ||
| char svalue[E_SIZE]; | ||
|
|
||
|
|
||
| int lineNumber=0;; | ||
| int numberAsserts=0; | ||
| int rc; | ||
| int en; | ||
|
|
||
| mf=fopen(ASSERTS_FILE, "r"); | ||
| if (mf==NULL) { | ||
| asserts[0].time=-1; | ||
| return -1; | ||
| } | ||
|
|
||
| while (fgets(lineRead,MAXIMUMLENGTH, mf) != NULL) { | ||
| lineNumber++; | ||
| // Leemos hasta 4 elementos por aserto | ||
| time=strtok(lineRead,","); | ||
| if (time==NULL){ | ||
| printf("Illegal Assert in line %d of file %s\n",lineNumber,ASSERTS_FILE); | ||
| continue; | ||
| } | ||
|
|
||
| element=strtok(NULL,","); | ||
| if (element==NULL){ | ||
| printf("Illegal Assert in line %d of file %s\n",lineNumber,ASSERTS_FILE); | ||
| continue; | ||
| } | ||
|
|
||
| value=strtok(NULL,","); | ||
| if (value==NULL){ | ||
| printf("Illegal Assert in line %d of file %s\n",lineNumber,ASSERTS_FILE); | ||
| continue; | ||
| } | ||
| address=strtok(NULL,"\n"); | ||
|
|
||
| //printf("-> %s, %s, %s, %s\n",time, element, value, address); | ||
|
|
||
| strcmpSpaces(a.element, element,E_SIZE); | ||
| if (strcmp(time,"*")) { | ||
| rc=sscanf(time,"%d",&a.time); | ||
| if (rc==0){ | ||
| printf("Illegal time format in line %d of file %s\n",lineNumber,ASSERTS_FILE); | ||
| continue; | ||
| } | ||
| } | ||
| else a.time=-33; // All the instants of time. | ||
|
|
||
| //printf("-%s-\n",a.element); | ||
| // Si vamos a verificar un código de operación leemos un char (RMEM_OP, AMEM_OP,IR_OP, MBR_OP, MMBR_OP) | ||
| en=elementNumber(a.element); | ||
| if ((en==RMEM_OP) || (en==AMEM_OP) || (en==IR_OP) || (en==MBR_OP) || (en==MMBR_OP)) { | ||
| strcmpSpaces(svalue, value,E_SIZE); | ||
| rc=sscanf(svalue,"%c",(char *) &a.value); | ||
|
|
||
| } | ||
| else | ||
| rc=sscanf(value,"%d",&a.value); | ||
|
|
||
| if (rc==0){ | ||
| printf("Illegal expected value format in line %d of file %s (%s)\n",lineNumber,ASSERTS_FILE,value); | ||
| continue; | ||
| } | ||
|
|
||
| // Si vamos a verificar una posición de memoria leemos la dirección (RMEM_OP, RMEM_O1, RMEM_O2, AMEM_OP, AMEM_O1, AMEM_O2) | ||
| en=elementNumber(a.element); | ||
| if ((en==RMEM_OP) || (en==RMEM_O1) || (en==RMEM_O2) || (en==AMEM_OP) || (en==AMEM_O1) || (en==AMEM_O2)) { | ||
| if (address==NULL){ | ||
| printf("Illegal Assert in line %d of file %s\n",lineNumber,ASSERTS_FILE); | ||
| continue; | ||
| } | ||
| rc=sscanf(address,"%d",&a.address); | ||
| if (rc==0){ | ||
| printf("Illegal address format in line %d of file %s\n",lineNumber,ASSERTS_FILE); | ||
| continue; | ||
| } | ||
| } | ||
| else a.address=0; | ||
|
|
||
| asserts[numberAsserts++]=a; | ||
| //printf("-> %d, %s, %d, %d\n",a.time, a.element, a.value, a.address); | ||
| } | ||
| fclose(mf); | ||
| asserts[numberAsserts].time=-1; // Para indicar el fin de los asertos | ||
| return numberAsserts; | ||
| } | ||
|
|
||
|
|
||
| void genAssertMsg(int time, char *ele, int realValue, int addr) { | ||
| int en; | ||
|
|
||
| printf("%d, %s",time, ele); | ||
| en=elementNumber(ele); | ||
|
|
||
| if ((en==RMEM_OP) || (en==AMEM_OP) || (en==IR_OP) || (en==MBR_OP)) | ||
| printf(", %c",realValue); | ||
| else | ||
| printf(", %d", realValue); | ||
|
|
||
| if ((en==RMEM_OP) || (en==RMEM_O1) || (en==RMEM_O2) || (en==AMEM_OP) || (en==AMEM_O1) || (en==AMEM_O2)) | ||
| printf(", %d", addr); | ||
|
|
||
| printf("\n"); | ||
| } | ||
|
|
||
| void assertMsg(int time, char *ele, int expectedValue, int realValue, int addr) { | ||
| int en; | ||
|
|
||
| if (GEN_ASSERTS) { | ||
| genAssertMsg(time, ele, realValue,addr); | ||
| return; | ||
| } | ||
|
|
||
| // printf("Assert failed. Time: %d; Element: %s; ", time, ele); | ||
| ComputerSystem_DebugMessage(90,ERROR, time, ele); | ||
| en=elementNumber(ele); | ||
|
|
||
| if ((en==RMEM_OP) || (en==AMEM_OP) || (en==IR_OP) || (en==MBR_OP)) | ||
| // printf("Expected: '%c'; Real: '%c'", expectedValue, realValue); | ||
| ComputerSystem_DebugMessage(91,ERROR, expectedValue, realValue); | ||
| else | ||
| // printf("Expected: %d; Real: %d", expectedValue, realValue); | ||
| ComputerSystem_DebugMessage(92,ERROR, expectedValue, realValue); | ||
|
|
||
| if ((en==RMEM_OP) || (en==RMEM_O1) || (en==RMEM_O2) || (en==AMEM_OP) || (en==AMEM_O1) || (en==AMEM_O2)) | ||
| // printf("; Memory address: %d", addr); | ||
| ComputerSystem_DebugMessage(93,ERROR, addr); | ||
|
|
||
| // printf("\n"); | ||
| ComputerSystem_DebugMessage(98, ERROR, "\n"); | ||
| } | ||
|
|
||
|
|
||
| void Asserts_CheckAsserts(){ | ||
| int na=0; | ||
| int op; | ||
| int globalCounter=Clock_GetTime(); | ||
| MEMORYCELL data; | ||
|
|
||
| //printf("Checking asserts for time %d\n",globalCounter); | ||
|
|
||
| while (asserts[na].time!=-1) { | ||
|
|
||
| // if ((asserts[na].time==globalCounter) || (asserts[na].time==-33)) { | ||
| if ((asserts[na].time==globalCounter) || (asserts[na].time==-33)) { | ||
|
|
||
| op=elementNumber(asserts[na].element); | ||
| //printf("There is one assert for time %d: %d\n",globalCounter, op); | ||
| switch (op) { | ||
| case RMEM_OP: | ||
| if ((mainMemory[MMU_GetBase()+asserts[na].address].operationCode!=(char)asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"RMEM_OP",asserts[na].value,mainMemory[MMU_GetBase()+asserts[na].address].operationCode,asserts[na].address); | ||
| break; | ||
| case RMEM_O1: | ||
| if ((mainMemory[MMU_GetBase()+asserts[na].address].operand1!=(char)asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"RMEM_O1",asserts[na].value,mainMemory[MMU_GetBase()+asserts[na].address].operand1,asserts[na].address); | ||
| break; | ||
| case RMEM_O2: | ||
| if ((mainMemory[MMU_GetBase()+asserts[na].address].operand2!=(char)asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"RMEM_O2",asserts[na].value,mainMemory[MMU_GetBase()+asserts[na].address].operand2,asserts[na].address); | ||
| break; | ||
| case AMEM_OP: | ||
| if ((mainMemory[asserts[na].address].operationCode!=(char)asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"AMEM_OP",asserts[na].value,mainMemory[asserts[na].address].operationCode,asserts[na].address); | ||
| break; | ||
| case AMEM_O1: | ||
| if ((mainMemory[asserts[na].address].operand1!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"AMEM_01",asserts[na].value,mainMemory[asserts[na].address].operand1,asserts[na].address); | ||
| break; | ||
| case AMEM_O2: | ||
| if ((mainMemory[asserts[na].address].operand2!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"AMEM_02",asserts[na].value,mainMemory[asserts[na].address].operand2,asserts[na].address); | ||
| break; | ||
| case PC: | ||
| if ((registerPC_CPU!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"PC",asserts[na].value,registerPC_CPU,0); | ||
| break; | ||
| case ACC: | ||
| if ((registerAccumulator_CPU!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"ACC",asserts[na].value,registerAccumulator_CPU,0); | ||
| break; | ||
| case IR_OP: | ||
| if ((registerIR_CPU.operationCode!=(char) asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"IR_OP",asserts[na].value,registerIR_CPU.operationCode,0); | ||
| break; | ||
| case IR_O1: | ||
| if ((registerIR_CPU.operand1!= asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"IR_01",asserts[na].value,registerIR_CPU.operand1,0); | ||
| break; | ||
| case IR_O2: | ||
| if ((registerIR_CPU.operand2!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"IR_02",asserts[na].value,registerIR_CPU.operand2,0); | ||
| break; | ||
| case PSW: | ||
| if ((registerPSW_CPU!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"PSW",asserts[na].value,registerPSW_CPU,0); | ||
| break; | ||
| case MAR: | ||
| if ((registerMAR_CPU!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MAR",asserts[na].value,registerMAR_CPU,0); | ||
| break; | ||
| case MBR_OP: | ||
| if ((registerMBR_CPU.operationCode!=(char) asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MBR_OP",asserts[na].value,registerMBR_CPU.operationCode,0); | ||
| break; | ||
| case MBR_O1: | ||
| if ((registerMBR_CPU.operand1!= asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MBR_O1",asserts[na].value,registerMBR_CPU.operand1,0); | ||
| break; | ||
| case MBR_O2: | ||
| if ((registerMBR_CPU.operand2!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MBR_02",asserts[na].value,registerMBR_CPU.operand2,0); | ||
| break; | ||
| case MMU_BS: | ||
| if ((MMU_GetBase()!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMU_BS",asserts[na].value,MMU_GetBase(),0); | ||
| break; | ||
| case MMU_LM: | ||
| if ((MMU_GetLimit()!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMU_LM",asserts[na].value,MMU_GetLimit(),0); | ||
| break; | ||
| case MMU_MAR: | ||
| if ((MMU_GetMAR()!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMU_MAR",asserts[na].value,MMU_GetMAR(),0); | ||
| break; | ||
| case MMEM_MAR: | ||
| if ((MainMemory_GetMAR()!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMEM_MAR",asserts[na].value,MainMemory_GetMAR(),0); | ||
| break; | ||
| case MMBR_OP: | ||
| MainMemory_GetMBR(&data); | ||
| if ((data.operationCode!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMBR_OP",asserts[na].value,data.operationCode,0); | ||
| break; | ||
| case MMBR_O1: | ||
| MainMemory_GetMBR(&data); | ||
| if ((data.operand1!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMBR_O1",asserts[na].value,data.operand1,0); | ||
| break; | ||
| case MMBR_O2: | ||
| MainMemory_GetMBR(&data); | ||
| if ((data.operand2!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMBR_O2",asserts[na].value,data.operand2,0); | ||
| break; | ||
| case XPID: | ||
| if ((executingProcessID!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"XPID",asserts[na].value,executingProcessID,0); | ||
| break; | ||
| default: ; | ||
|
|
||
| } | ||
| } | ||
| na++; | ||
|
|
||
| } | ||
| } |
| @@ -0,0 +1,39 @@ | ||
| #ifndef CHECKASSERTS_H | ||
| #define CHECKASSERTS_H | ||
|
|
||
| #define MAX_ASSERTS 500 | ||
| #define MAXIMUMLENGTH 64 | ||
| #define ASSERTS_FILE "asserts" | ||
| #define E_SIZE 8 | ||
|
|
||
|
|
||
|
|
||
| #define RMEM_OP 0 | ||
| #define RMEM_O1 1 | ||
| #define RMEM_O2 2 | ||
| #define AMEM_OP 3 | ||
| #define AMEM_O1 4 | ||
| #define AMEM_O2 5 | ||
| #define PC 6 | ||
| #define ACC 7 | ||
| #define IR_OP 8 | ||
| #define IR_O1 9 | ||
| #define IR_O2 10 | ||
| #define PSW 11 | ||
| #define MAR 12 | ||
| #define MBR_OP 13 | ||
| #define MBR_O1 14 | ||
| #define MBR_O2 15 | ||
| #define MMU_BS 16 | ||
| #define MMU_LM 17 | ||
| #define MMU_MAR 18 | ||
| #define MMEM_MAR 19 | ||
| #define MMBR_OP 20 | ||
| #define MMBR_O1 21 | ||
| #define MMBR_O2 22 | ||
| #define XPID 23 | ||
|
|
||
| // Functions prototypes | ||
| int Asserts_LoadAsserts(); | ||
| void Asserts_CheckAsserts(); | ||
| #endif |
| @@ -0,0 +1,71 @@ | ||
| #include "Buses.h" | ||
| #include "MMU.h" | ||
| #include "Processor.h" | ||
| #include "MainMemory.h" | ||
| #include <string.h> | ||
| #include <stdlib.h> | ||
|
|
||
| // Function that simulates the delivery of an address by means of the address bus | ||
| // from a hardware component register to another hardware component register | ||
| int Buses_write_AddressBus_From_To(int fromRegister, int toRegister) { | ||
| int data; | ||
| switch (fromRegister) { | ||
| case MMU: | ||
| data=MMU_GetMAR(); | ||
| break; | ||
| case CPU: | ||
| data=Processor_GetMAR(); | ||
| break; | ||
| default: | ||
| return Bus_FAIL; | ||
| } | ||
|
|
||
| switch (toRegister) { | ||
| case MAINMEMORY: | ||
| if (fromRegister==MAINMEMORY) | ||
| return Bus_FAIL; | ||
| MainMemory_SetMAR(data); | ||
| break; | ||
| case MMU: | ||
| if (fromRegister==MMU) | ||
| return Bus_FAIL; | ||
| MMU_SetMAR(data); | ||
| break; | ||
| default: | ||
| return Bus_FAIL; | ||
| } | ||
| return Bus_SUCCESS; | ||
| } | ||
|
|
||
| // Function that simulates the delivery of memory word by means of the data bus | ||
| // from a hardware component register to another hardware component register | ||
| int Buses_write_DataBus_From_To(int fromRegister, int toRegister) { | ||
| MEMORYCELL data; | ||
| switch (fromRegister) { | ||
| case MAINMEMORY: | ||
| MainMemory_GetMBR(&data); | ||
| break; | ||
| case CPU: | ||
| Processor_GetMBR(&data); | ||
| break; | ||
| default: | ||
| return Bus_FAIL; | ||
| } | ||
|
|
||
| switch (toRegister) { | ||
| case MAINMEMORY: | ||
| if (fromRegister==MAINMEMORY) | ||
| return Bus_FAIL; | ||
| MainMemory_SetMBR(&data); | ||
| break; | ||
| case CPU: | ||
| if (fromRegister==CPU) | ||
| return Bus_FAIL; | ||
| Processor_SetMBR(&data); | ||
| break; | ||
| default: | ||
| return Bus_FAIL; | ||
| } | ||
|
|
||
| return Bus_SUCCESS; | ||
| } |
| @@ -0,0 +1,13 @@ | ||
| #ifndef BUSES_H | ||
| #define BUSES_H | ||
|
|
||
| enum BusConnection { MAINMEMORY, MMU, CPU, INPUTDEVICE, OUTPUTDEVICE }; | ||
|
|
||
| #define Bus_SUCCESS 1 | ||
| #define Bus_FAIL -1 | ||
|
|
||
| // Functions prototypes | ||
| int Buses_write_AddressBus_From_To(int, int); | ||
| int Buses_write_DataBus_From_To(int, int); | ||
|
|
||
| #endif |
| @@ -0,0 +1,16 @@ | ||
| #include "Clock.h" | ||
| #include "Processor.h" | ||
| #include "ComputerSystem.h" | ||
|
|
||
| int tics=0; | ||
|
|
||
| void Clock_Update() { | ||
| tics++; | ||
| ComputerSystem_DebugMessage(97,CLOCK,tics); | ||
| } | ||
|
|
||
|
|
||
| int Clock_GetTime() { | ||
|
|
||
| return tics; | ||
| } |
| @@ -0,0 +1,8 @@ | ||
| #ifndef Clock_H | ||
| #define Clock_H | ||
|
|
||
| // Functions prototypes | ||
| void Clock_Update(); | ||
| int Clock_GetTime(); | ||
|
|
||
| #endif |
| @@ -0,0 +1,66 @@ | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include "ComputerSystem.h" | ||
| #include "OperatingSystem.h" | ||
| #include "ComputerSystemBase.h" | ||
| #include "Processor.h" | ||
| #include "Messages.h" | ||
| #include "Asserts.h" | ||
|
|
||
| // Functions prototypes | ||
| void ComputerSystem_PrintProgramList(); | ||
| // Array that contains basic data about all daemons | ||
| // and all user programs specified in the command line | ||
| PROGRAMS_DATA *programList[PROGRAMSMAXNUMBER]; | ||
|
|
||
| // Powers on of the Computer System. | ||
| void ComputerSystem_PowerOn(int argc, char *argv[]) { | ||
|
|
||
| // Load debug messages | ||
| int nm=0; | ||
| nm=Messages_Load_Messages(nm,TEACHER_MESSAGES_FILE); | ||
| nm=Messages_Load_Messages(nm,STUDENT_MESSAGES_FILE); | ||
| printf("%d Messages Loaded\n",nm); | ||
|
|
||
| int na=Asserts_LoadAsserts(); | ||
| if (na==-1) | ||
| printf("Asserts file unavailable\n"); | ||
| else | ||
| printf("%d Asserts Loaded\n",na); | ||
|
|
||
| // Obtain a list of programs in the command line | ||
| int daemonsBaseIndex = ComputerSystem_ObtainProgramList(argc, argv); | ||
|
|
||
| //Show the loaded user programs | ||
| ComputerSystem_PrintProgramList(); | ||
|
|
||
| // Request the OS to do the initial set of tasks. The last one will be | ||
| // the processor allocation to the process with the highest priority | ||
| OperatingSystem_Initialize(daemonsBaseIndex); | ||
|
|
||
|
|
||
| // Tell the processor to begin its instruction cycle | ||
| Processor_InstructionCycleLoop(); | ||
|
|
||
| } | ||
|
|
||
| // Powers off the CS (the C program ends) | ||
| void ComputerSystem_PowerOff() { | ||
| // Show message in red colour: "END of the simulation\n" | ||
| ComputerSystem_DebugMessage(99,SHUTDOWN); | ||
| exit(0); | ||
| } | ||
|
|
||
| ///////////////////////////////////////////////////////// | ||
| // New functions below this line ////////////////////// | ||
| void ComputerSystem_PrintProgramList() { | ||
| int i; | ||
| PROGRAMS_DATA program; | ||
| ComputerSystem_DebugMessage(101, INIT); | ||
| for( i = 0; i < PROGRAMSMAXNUMBER; i++){ | ||
| if(i != 0 && programList[i] != NULL){ | ||
| program = *programList[i]; | ||
| ComputerSystem_DebugMessage(102, INIT, program.executableName, program.arrivalTime); | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,43 @@ | ||
| #ifndef COMPUTERSYSTEM_H | ||
| #define COMPUTERSYSTEM_H | ||
|
|
||
| #include "Simulator.h" | ||
| #include "ComputerSystemBase.h" | ||
|
|
||
| // Functions prototypes | ||
| void ComputerSystem_PowerOn(int argc, char *argv[]); | ||
| void ComputerSystem_PowerOff(); | ||
| // void ComputerSystem_ObtainProgramList(int argc, char *argv[]); | ||
|
|
||
| // Sections in which we divide our simulator in terms of | ||
| // debugging messages that show its internal working details | ||
|
|
||
| #define ALL 'a' // Show all the messages corresponding to calls to the ComputerSystem_DebugMessage() function | ||
| #define NONE 'n' // Do not show any message (not apply for ERROR messages) | ||
| #define INTERRUPT 'i' // Only messages related to interruptions | ||
| #define HARDWARE 'h' // Only messages related to the hardware | ||
| #define SYSFILE 'f' // Only messages related to the file system of the operating system | ||
| #define SYSPROC 'p' // Only messages related to the process management system of the operating system | ||
| #define SYSMEM 'm' // Only messages related to the memory management system of the operating system | ||
| #define INIT 't' // Only messages related to the initialization of the operating system | ||
| #define SHUTDOWN 'd' // Only messages related to the process of powering off the operating system | ||
| #define LONGTERMSCHEDULE 'l' // Only messages related to the long term scheduler of the operating system | ||
| #define SHORTTERMSCHEDULE 's' // Only messages related to the short term scheduler of the operating system | ||
| #define ERROR 'e' // Error messages | ||
| #define CLOCK 'c' // Clock time messages | ||
|
|
||
| // Basic data to collect about every program to be created | ||
| // User programs specified in the command line: name of the file, the time of its arrival time | ||
| // to the system (0, by default), and type USERPROGRAM | ||
| // Daemon programs of type DAEMONPROGRAM | ||
| typedef struct ProgramData { | ||
| char *executableName; | ||
| unsigned int arrivalTime; | ||
| unsigned int type; | ||
| } PROGRAMS_DATA; | ||
|
|
||
| // This "extern" declarations enables other source code files to gain access | ||
| // to the variables "programList", etc. | ||
| extern PROGRAMS_DATA *programList[PROGRAMSMAXNUMBER]; | ||
|
|
||
| #endif |
| @@ -0,0 +1,198 @@ | ||
| #include <string.h> | ||
| #include <stdarg.h> | ||
| #include <stdlib.h> | ||
| #include <ctype.h> | ||
| #include "ComputerSystem.h" | ||
| #include "ComputerSystemBase.h" | ||
| #include "Processor.h" | ||
| #include "Heap.h" | ||
| #include "OperatingSystemBase.h" | ||
| #include "Messages.h" | ||
|
|
||
| // Functions prototypes | ||
|
|
||
| int GEN_ASSERTS=0; | ||
| // String specified in the command line to tell the simulator which of its | ||
| // sections are interesting for the user so it must show debug messages | ||
| // related to them | ||
| char *debugLevel; | ||
|
|
||
| // Only one colour messages. Set to 1 for more colours checking uppercase in debugLevel | ||
| int COLOURED = 0 ; | ||
|
|
||
| // Fill in the array named userProgramsList with the information given | ||
| // by the user in the command line | ||
| // IT IS NOT NECESSARY TO COMPLETELY UNDERSTAND THIS FUNCTION | ||
| int ComputerSystem_ObtainProgramList(int argc, char *argv[]) { | ||
|
|
||
| int i; | ||
| int count=1; // 0 reserved for sipid | ||
| PROGRAMS_DATA *progData; | ||
|
|
||
| // To remember the simulator sections to be message-debugged | ||
| debugLevel = argv[1]; | ||
| for (i=0; i< strlen(debugLevel);i++) | ||
| if (isupper(debugLevel[i])){ | ||
| COLOURED = 1; | ||
| debugLevel[i]=tolower(debugLevel[i]); | ||
| } | ||
|
|
||
| if (strchr(debugLevel,'g')) | ||
| GEN_ASSERTS=1; | ||
|
|
||
| for (i=0; i<PROGRAMSMAXNUMBER;i++) | ||
| programList[i]=NULL; | ||
|
|
||
| // Store the names of the programs | ||
| for (i = 2; i < argc && count<PROGRAMSMAXNUMBER;) { // check number of programs < PROGRAMSMAXNUMBER | ||
| progData=(PROGRAMS_DATA *) malloc(sizeof(PROGRAMS_DATA)); | ||
| // Save file name | ||
| progData->executableName = (char *) malloc((strlen(argv[i])+1)*sizeof(char)); | ||
| strcpy(progData->executableName,argv[i]); | ||
| i++; | ||
| // Default arrival time: 0 | ||
| progData->arrivalTime = 0; | ||
| // Try to store the arrival time if exists | ||
| if ((i < argc) | ||
| && (sscanf(argv[i], "%d", &(progData->arrivalTime)) == 1)) | ||
| // An arrival time has been read. Increment i | ||
| i++; | ||
|
|
||
| // Defaul user programs | ||
| progData->type=USERPROGRAM; | ||
|
|
||
| // Store the structure in the list | ||
| programList[count]=progData; | ||
|
|
||
| count++; // There is one program more | ||
| } | ||
| return count; // Next place for new programs | ||
| } | ||
|
|
||
| // Function used to show messages with details of the internal working of | ||
| // the simulator | ||
| // IT IS NOT NECESSARY TO UNDERSTAND ALL THE DETAILS OF THIS FUNCTION | ||
| void ComputerSystem_DebugMessage(int msgNo, char section, ...) { | ||
|
|
||
| va_list lp; | ||
| char c, *format; | ||
| int count, youHaveToContinue, colour=0; | ||
|
|
||
| int pos; | ||
|
|
||
| pos=Messages_Get_Pos(msgNo); | ||
| if (pos==-1) { | ||
| printf("Debug Message %d not defined\n",msgNo); | ||
| return; | ||
| } | ||
| format=DebugMessages[pos].format; | ||
|
|
||
| va_start(lp, section); | ||
|
|
||
| if ((strchr(debugLevel, ALL) != NULL) // Print the message because the user specified ALL | ||
| || section == ERROR // Always print ERROR section | ||
| || (strchr(debugLevel,section)) != NULL){ // or the section argument is included in the debugLevel string | ||
|
|
||
| for (count = 0, youHaveToContinue = 1; youHaveToContinue == 1; count++) { | ||
| //printf("(%c)",format[count]); | ||
| switch (format[count]) { | ||
| case '\\':count++; | ||
| switch (format[count]) { | ||
| case 'n': printf("\n"); | ||
| break; | ||
| case 't': printf("\t"); | ||
| break; | ||
| default: printf("\%c", format[count]); | ||
| } // switch Control Chars | ||
| break; | ||
| // case '%': | ||
| case '@': // Next color char | ||
| count++; | ||
| switch (format[count]) { | ||
| case 'R': // Text in red | ||
| if (COLOURED){ | ||
| printf("%c[%d;%dm", 0x1B, 1, 31); | ||
| if (!colour) colour=1; | ||
| } | ||
| break; | ||
| case 'G': // Text in green | ||
| if (COLOURED){ | ||
| printf("%c[%d;%dm", 0x1B, 1, 32); | ||
| if (!colour) colour=1; | ||
| } | ||
| break; | ||
| case 'Y': // Text in yellow | ||
| if (COLOURED){ | ||
| printf("%c[%d;%dm", 0x1B, 1, 33); | ||
| if (!colour) colour=1; | ||
| } | ||
| break; | ||
| case 'B': // Text in blue | ||
| if (COLOURED){ | ||
| printf("%c[%d;%dm", 0x1B, 1, 34); | ||
| if (!colour) colour=1; | ||
| } | ||
| break; | ||
| case 'M': // // Text in magenta | ||
| if (COLOURED){ | ||
| printf("%c[%d;%dm", 0x1B, 1, 35); | ||
| if (!colour) colour=1; | ||
| } | ||
| break; | ||
| case 'C': // Text in cyan | ||
| if (COLOURED){ | ||
| printf("%c[%d;%dm", 0x1B, 1, 36); | ||
| if (!colour) colour=1; | ||
| } | ||
| break; | ||
| case 'W': // Text in white | ||
| if (COLOURED){ | ||
| printf("%c[%d;%dm", 0x1B, 1, 37); | ||
| if (!colour) colour=1; | ||
| } | ||
| break; | ||
| case '@': // Text without color | ||
| if (COLOURED && colour) | ||
| printf("%c[%dm", 0x1B, 0); | ||
| break; | ||
| } // switch colors chars | ||
| break; | ||
| case '%': | ||
| count++; | ||
| switch (format[count]) { | ||
| case 's': | ||
| printf("%s",va_arg(lp, char *)); | ||
| // if (colour) | ||
| // printf("%c[%dm", 0x1B, 0); | ||
| break; | ||
| case 'd': | ||
| printf("%d",va_arg(lp, int)); | ||
| // if (colour) | ||
| // printf("%c[%dm", 0x1B, 0); | ||
| break; | ||
| case 'f': | ||
| printf("%f",va_arg(lp, double)); | ||
| // if (colour) | ||
| // printf("%c[%dm", 0x1B, 0); | ||
| break; | ||
| case 'c': | ||
| c = (char) va_arg(lp, int); | ||
| printf("%c", c); | ||
| // if (colour) | ||
| // printf("%c[%dm", 0x1B, 0); | ||
| break; | ||
| default: | ||
| youHaveToContinue = 0; | ||
| } // switch format chars | ||
| break; | ||
| default:if (format[count]==0) | ||
| youHaveToContinue=0; | ||
| else | ||
| printf("%c",format[count]); | ||
| } // switch | ||
| } // for | ||
| va_end(lp); | ||
| } // if | ||
| if (COLOURED && colour) | ||
| printf("%c[%dm", 0x1B, 0); | ||
| } // ComputerSystem_DebugMessage() |
| @@ -0,0 +1,12 @@ | ||
| #ifndef COMPUTERSYSTEMBASE_H | ||
| #define COMPUTERSYSTEMBASE_H | ||
|
|
||
| #include "ComputerSystem.h" | ||
|
|
||
| // Functions prototypes | ||
| int ComputerSystem_ObtainProgramList(int , char *[]); | ||
| void ComputerSystem_DebugMessage(int, char , ...); | ||
|
|
||
| // This "extern" declarations enables other source code files to gain access to the variables | ||
|
|
||
| #endif |
| @@ -0,0 +1,108 @@ | ||
| #include "Heap.h" | ||
| #include <stdlib.h> | ||
|
|
||
| // Internal Functions prototypes | ||
| void Heap_swap_Up(int, int[], int); | ||
| void Heap_swap_Down(int, int[], int, int); | ||
|
|
||
|
|
||
| // Insertion of a PID into a binary heap | ||
| // info: PID to insert | ||
| // heap: Binary heap to insert: user o daemon ready queue, sleeping queue, ... | ||
| // queueType: QUEUE_PRIORITY, ... | ||
| // numElem: number of elements actually into the queue, if successfull is increased by one | ||
| // limit: max size of the queue | ||
| // return 0/-1 ok/fail | ||
| int Heap_add(int info, int heap[], int queueType, int *numElem, int limit) { | ||
| if (*numElem >= limit || info<0) | ||
| return -1; | ||
| heap[*numElem]=info; | ||
| Heap_swap_Up(*numElem, heap, queueType); | ||
| (*numElem)++; | ||
| return 0; | ||
| } | ||
|
|
||
| // Extract the more priority item | ||
| // heap: Binary heap to extract: user o daemon ready queue, sleeping queue, ... | ||
| // queueType: QUEUE_PRIORITY, ... | ||
| // numElem: number of elements actually into the queue, if successfull is decremented by one | ||
| // return more priority item into the queue | ||
| int Heap_poll(int heap[], int queueType, int *numElem) { | ||
| int info = heap[0]; | ||
| if (*numElem==0) | ||
| return -1; // no hay elementos en la cola de prioridad | ||
| else { | ||
| heap[0]=heap[*numElem-1]; | ||
| Heap_swap_Down(0, heap, queueType, *numElem); | ||
| (*numElem)--; | ||
| } | ||
| return info; | ||
| } | ||
|
|
||
| // Return top value of heap | ||
| // heap: Binary heap to get top value | ||
| // numElem: number of elements actually into the queue | ||
| // return more priority item, but not extract from heap | ||
| int Heap_getFirst(int heap[], int numElem) { | ||
| if (numElem>0) | ||
| return heap[0]; | ||
| else | ||
| return -1; | ||
| } | ||
|
|
||
| // Auxiliar function for implementation of binary heaps | ||
| void Heap_swap_Up(int p, int heap[], int queueType) { | ||
| if (p > 0) { // if not at the top... | ||
| int padre = abs(p - 1) / 2; // integer operation | ||
| if (Heap_compare(heap[p],heap[padre],queueType)>0) { // less than father... | ||
| int aux = heap[padre]; | ||
| heap[padre] = heap[p]; | ||
| heap[p] = aux; | ||
| Heap_swap_Up(padre, heap, queueType); | ||
| } // if not less, don't switch | ||
| } // at the top... | ||
| } | ||
|
|
||
| // Auxiliar function for implementation of binary heaps | ||
| void Heap_swap_Down(int p, int heap[], int queueType, int numElem) { | ||
| int izq = 2*p+1; | ||
| int der = 2*p+2; | ||
| int aux = heap[p]; | ||
|
|
||
| if (der < numElem) // 2 childs... | ||
| if ((Heap_compare(heap[izq],heap[der], queueType)>0) && (Heap_compare(heap[p],heap[izq],queueType)<0)){ // Switch with left-child if rigth-child greather | ||
| heap[p] = heap[izq]; | ||
| heap[izq] = aux; | ||
| Heap_swap_Down(izq, heap, queueType, numElem); | ||
| } else { // rigth | ||
| if (Heap_compare(heap[p],heap[der], queueType)<0) { // Switch with rigth-child | ||
| heap[p] = heap[der]; | ||
| heap[der] = aux; | ||
| Heap_swap_Down(der, heap, queueType, numElem); | ||
| } | ||
| } | ||
| else if (izq<numElem) { // only left-child... | ||
| if (Heap_compare(heap[p],heap[izq], queueType)<0){ // Switch with left-child | ||
| heap[p] = heap[izq]; | ||
| heap[izq] = aux; | ||
| Heap_swap_Down(izq, heap, queueType, numElem); | ||
| } // Less than left-child, don't switch | ||
| } // leaf-node... | ||
| } | ||
|
|
||
| // Auxiliar for priority comparations | ||
| int Heap_compare_priority(int uno, int dos) { | ||
| return processTable[dos].priority-processTable[uno].priority; | ||
| } | ||
|
|
||
| // Auxiliar for generic comparations | ||
| int Heap_compare(int uno, int dos, int queueType) { | ||
|
|
||
| switch (queueType) { | ||
| case QUEUE_PRIORITY: | ||
| return Heap_compare_priority(uno, dos); | ||
| default: | ||
| return 0; // | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,13 @@ | ||
| #ifndef HEAP_H | ||
| #define HEAP_H | ||
|
|
||
| #include "OperatingSystem.h" | ||
|
|
||
| #define QUEUE_PRIORITY 1 | ||
|
|
||
|
|
||
| int Heap_poll(int[], int, int*); | ||
| int Heap_add(int, int[], int , int*, int); | ||
| int Heap_compare(int, int, int); | ||
| int Heap_getFirst(int[], int); | ||
| #endif |
| @@ -0,0 +1,105 @@ | ||
| #include "MMU.h" | ||
| #include "Buses.h" | ||
| #include "Processor.h" | ||
| #include <string.h> | ||
|
|
||
| // The base register | ||
| int registerBase_MMU; | ||
|
|
||
| // The limit register | ||
| int registerLimit_MMU; | ||
|
|
||
| // The MAR register | ||
| int registerMAR_MMU; | ||
|
|
||
| // Logical address is in registerMAR_MMU. If correct, physical address is produced | ||
| // by adding logical address and base register | ||
| int MMU_readMemory() { | ||
|
|
||
| if (Processor_PSW_BitState(EXECUTION_MODE_BIT)){ // Protected mode | ||
| if (registerMAR_MMU < MAINMEMORYSIZE){ | ||
| // Send to the main memory HW the physical address to write in | ||
| Buses_write_AddressBus_From_To(MMU, MAINMEMORY); | ||
| // Tell the main memory HW to read | ||
| MainMemory_readMemory(); | ||
| return MMU_SUCCESS; | ||
| } | ||
| else { | ||
| return MMU_FAIL; | ||
| } | ||
| } | ||
| else // Non-Protected mode | ||
| if (registerMAR_MMU<registerLimit_MMU) { | ||
| // Physical address = logical address + base register | ||
| registerMAR_MMU+=registerBase_MMU; | ||
| // Send to the main memory HW the physical address to write in | ||
| Buses_write_AddressBus_From_To(MMU, MAINMEMORY); | ||
| // Tell the main memory HW to read | ||
| MainMemory_readMemory(); | ||
| return MMU_SUCCESS; | ||
| } | ||
| else { | ||
| return MMU_FAIL; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| // Logical address is in registerMAR_MMU. If correct, physical address is produced | ||
| // by adding logical address and base register | ||
| int MMU_writeMemory() { | ||
|
|
||
| if (Processor_PSW_BitState(EXECUTION_MODE_BIT)) // Protected mode | ||
| if (registerMAR_MMU < MAINMEMORYSIZE) { | ||
| // Send to the main memory HW the physical address to write in | ||
| Buses_write_AddressBus_From_To(MMU, MAINMEMORY); | ||
| // Tell the main memory HW to read | ||
| MainMemory_writeMemory(); | ||
| return MMU_SUCCESS; | ||
| } | ||
| else { | ||
| return MMU_FAIL; | ||
| } | ||
| else // Non-Protected mode | ||
| if (registerMAR_MMU<registerLimit_MMU) { | ||
| // Physical address = logical address + base register | ||
| registerMAR_MMU+=registerBase_MMU; | ||
| // Send to the main memory HW the physical address to read from | ||
| Buses_write_AddressBus_From_To(MMU, MAINMEMORY); | ||
| // Tell the main memory HW to write | ||
| MainMemory_writeMemory(); | ||
| return MMU_SUCCESS; | ||
| } | ||
| else { | ||
| return MMU_FAIL; | ||
| } | ||
| } | ||
|
|
||
| // Setter for registerMAR_MMU | ||
| void MMU_SetMAR (int newMAR) { | ||
| registerMAR_MMU = newMAR; | ||
| } | ||
|
|
||
| // Getter for registerMAR_MMU | ||
| int MMU_GetMAR () { | ||
| return registerMAR_MMU; | ||
| } | ||
|
|
||
| // Setter for registerBase_MMU | ||
| void MMU_SetBase (int newBase) { | ||
| registerBase_MMU = newBase; | ||
| } | ||
|
|
||
| // Getter for registerBase_MMU | ||
| int MMU_GetBase () { | ||
| return registerBase_MMU; | ||
| } | ||
|
|
||
| // Setter for registerLimit_MMU | ||
| void MMU_SetLimit (int newLimit) { | ||
| registerLimit_MMU = newLimit; | ||
| } | ||
|
|
||
| // Getter for registerLimit_MMU | ||
| int MMU_GetLimit () { | ||
| return registerLimit_MMU; | ||
| } |
| @@ -0,0 +1,20 @@ | ||
| #ifndef MMU_H | ||
| #define MMU_H | ||
|
|
||
| #define MMU_SUCCESS 1 | ||
| #define MMU_FAIL -1 | ||
|
|
||
| // Functions prototypes | ||
| int MMU_readMemory(); | ||
| int MMU_writeMemory(); | ||
|
|
||
| int MMU_GetMAR(); | ||
| void MMU_SetMAR(int); | ||
| void MMU_SetBase(int); | ||
| void MMU_SetLimit(int); | ||
|
|
||
| // Used for Asserts | ||
| int MMU_GetBase(); | ||
| int MMU_GetLimit(); | ||
|
|
||
| #endif |
| @@ -0,0 +1,51 @@ | ||
| #include "MainMemory.h" | ||
| #include "Processor.h" | ||
| #include "Buses.h" | ||
| #include <string.h> | ||
|
|
||
| // Main memory can be simulated by a memory cell array | ||
| MEMORYCELL mainMemory[MAINMEMORYSIZE]; | ||
|
|
||
| // Main memory has a MAR register whose value identifies where | ||
| // the next read/write operation will take place | ||
| int registerMAR_MainMemory; | ||
|
|
||
| // It also has a register that plays the rol of a buffer for the mentioned operations | ||
| MEMORYCELL registerMBR_MainMemory; | ||
|
|
||
| // To read the contents of a memory cell, the MAR register must point (index) it | ||
| // The result of the operation is sent to the processor MBR register by using the | ||
| // data bus | ||
| void MainMemory_readMemory() { | ||
|
|
||
| memcpy((void *) (®isterMBR_MainMemory), (void *) (&mainMemory[registerMAR_MainMemory]), sizeof(MEMORYCELL)); | ||
| Buses_write_DataBus_From_To(MAINMEMORY, CPU); | ||
| } | ||
|
|
||
| // To write in a memory cell, the MAR and MBR registers are used, set by the processor, | ||
| // as described previously | ||
| void MainMemory_writeMemory() { | ||
|
|
||
| memcpy((void *) (&mainMemory[registerMAR_MainMemory]), (void *) (®isterMBR_MainMemory), sizeof(MEMORYCELL)); | ||
| } | ||
|
|
||
| // Getter for the registerMAR_MainMemory | ||
| int MainMemory_GetMAR() { | ||
| return registerMAR_MainMemory; | ||
| } | ||
|
|
||
| // Setter for registerMAR_MainMemory | ||
| void MainMemory_SetMAR(int addr) { | ||
| registerMAR_MainMemory=addr; | ||
| } | ||
|
|
||
| // pseudo-getter for the registerMBR_MainMemory | ||
| void MainMemory_GetMBR(MEMORYCELL *toRegister) { | ||
| memcpy((void*) toRegister, (void *) (®isterMBR_MainMemory), sizeof(MEMORYCELL)); | ||
| } | ||
|
|
||
| // pseudo-setter for the registerMBR_MainMemory | ||
| void MainMemory_SetMBR(MEMORYCELL *fromRegister) { | ||
| memcpy((void*) (®isterMBR_MainMemory), (void *) fromRegister, sizeof(MEMORYCELL)); | ||
| } | ||
|
|
| @@ -0,0 +1,24 @@ | ||
| #ifndef MAINMEMORY_H | ||
| #define MAINMEMORY_H | ||
|
|
||
| // Main memory size (number of memory cells) | ||
| #define MAINMEMORYSIZE 300 | ||
|
|
||
| // A memory cell is capable of storing a structure of the | ||
| // MEMORYCELL TYPE | ||
| typedef struct { | ||
| char operationCode; | ||
| int operand1; | ||
| int operand2; | ||
| } MEMORYCELL; | ||
|
|
||
| // Function prototypes | ||
| void MainMemory_readMemory(); | ||
| void MainMemory_writeMemory(); | ||
|
|
||
| int MainMemory_GetMAR(); | ||
| void MainMemory_SetMAR(int); | ||
| void MainMemory_GetMBR(MEMORYCELL *); | ||
| void MainMemory_SetMBR(MEMORYCELL *); | ||
|
|
||
| #endif |
| @@ -0,0 +1,74 @@ | ||
| # | ||
| # Makefile for the Linux Simulator | ||
| # | ||
| ######################################################## | ||
|
|
||
| PROGRAM = Simulator | ||
|
|
||
| # Compilation Details | ||
| SHELL = /bin/sh | ||
| CC = cc | ||
| STDCFLAGS = -g -c -Wall -std=gnu90 | ||
| INCLUDES = | ||
| LIBRERIAS = | ||
| ACC = /usr/share/ACC/bin/acc | ||
|
|
||
| ${PROGRAM}: Simulator.o Aspect.o Buses.o Asserts.o Clock.o ComputerSystem.o ComputerSystemBase.o Heap.o MainMemory.o Messages.o MMU.o OperatingSystemAspect.o OperatingSystemBase.o ProcessorAspect.o | ||
| $(CC) -o ${PROGRAM} Simulator.o Aspect.o Buses.o Asserts.o Clock.o ComputerSystem.o ComputerSystemBase.o Heap.o MainMemory.o Messages.o MMU.o OperatingSystemAspect.o OperatingSystemBase.o ProcessorAspect.o $(LIBRERIAS) | ||
|
|
||
| Simulator.o: Simulator.c Simulator.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) Simulator.c | ||
|
|
||
| Asserts.o: Asserts.c Asserts.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) Asserts.c | ||
|
|
||
| ComputerSystem.o: ComputerSystem.c ComputerSystem.h ComputerSystemBase.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) ComputerSystem.c | ||
|
|
||
| ComputerSystemBase.o: ComputerSystemBase.c ComputerSystemBase.h ComputerSystem.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) ComputerSystemBase.c | ||
|
|
||
| Messages.o: Messages.c Messages.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) Messages.c | ||
|
|
||
| MainMemory.o: MainMemory.c MainMemory.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) MainMemory.c | ||
|
|
||
| OperatingSystemAspect.o: OperatingSystemAspect.mc Aspect.acc | ||
| $(ACC) OperatingSystemAspect.mc Aspect.acc | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) -L /tmp/ACC/lib -lacc OperatingSystemAspect.c | ||
|
|
||
| OperatingSystemAspect.mc: OperatingSystem.c OperatingSystem.h | ||
| $(CC) -E $(INCLUDES) OperatingSystem.c > OperatingSystemAspect.mc | ||
|
|
||
| OperatingSystemBase.o: OperatingSystemBase.c OperatingSystemBase.h OperatingSystem.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) OperatingSystemBase.c | ||
|
|
||
| ProcessorAspect.o: ProcessorAspect.mc Aspect.acc | ||
| $(ACC) ProcessorAspect.mc Aspect.acc | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) -L /tmp/ACC/lib -lacc ProcessorAspect.c | ||
|
|
||
| ProcessorAspect.mc: Processor.c Processor.h | ||
| $(CC) -E $(INCLUDES) Processor.c > ProcessorAspect.mc | ||
|
|
||
| Aspect.o: Aspect.acc | ||
| $(ACC) Aspect.acc | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) -L /tmp/ACC/lib -lacc Aspect.c | ||
|
|
||
| Aspect.acc: OperatingSystem.h Processor.h Asserts.h MyAspect.c | ||
| $(CC) -E $(INCLUDES) MyAspect.c > Aspect.acc | ||
|
|
||
| Buses.o: Buses.c Buses.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) Buses.c | ||
|
|
||
| MMU.o: MMU.c MMU.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) MMU.c | ||
|
|
||
| Clock.o: Clock.c Clock.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) Clock.c | ||
|
|
||
| Heap.o: Heap.c Heap.h | ||
| $(CC) $(STDCFLAGS) $(INCLUDES) Heap.c | ||
|
|
||
| clean: | ||
| rm -f $(PROGRAM) *.o *~ *.mc *.acc Aspect.c ProcessorAspect.c OperatingSystemAspect.c core |
| @@ -0,0 +1,56 @@ | ||
| #include <stdio.h> | ||
| #include <string.h> | ||
| #include "Messages.h" | ||
|
|
||
| #define MSGMAXIMUMLENGTH 132 | ||
|
|
||
| DEBUG_MESSAGES DebugMessages[NUMBEROFMSGS] = {[0 ... NUMBEROFMSGS-1] {-1,""}}; | ||
|
|
||
| int Messages_Load_Messages(int position, char * nameFileMessage) { | ||
|
|
||
| char lineRead[MSGMAXIMUMLENGTH]; | ||
| FILE *mf; | ||
| char *number, *text; | ||
| int msgNumber; | ||
| int lineNumber=0;; | ||
| int rc; | ||
|
|
||
| mf=fopen(nameFileMessage, "r"); | ||
| if (mf==NULL) { | ||
| printf("Verbose messages unavailable\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| while (fgets(lineRead, MSGMAXIMUMLENGTH, mf) != NULL) { | ||
| lineNumber++; | ||
| number=strtok(lineRead,","); | ||
| if ((number!=NULL) && (number[0]!='/') && (number[0]!='\n')) { | ||
| rc=sscanf(number,"%d",&msgNumber); | ||
| if (rc==0){ | ||
| printf("Illegal Message Number in line %d of file %s\n",lineNumber,nameFileMessage); | ||
| continue; | ||
| } | ||
|
|
||
| text=strtok(NULL,"\n"); | ||
| if (text==NULL){ | ||
| printf("Illegal Message Format in line %d of file %s\n",lineNumber,nameFileMessage); | ||
| continue; | ||
| } | ||
|
|
||
| strcpy(DebugMessages[position].format,text); | ||
| DebugMessages[position++].number=msgNumber; | ||
| } | ||
| } | ||
| fclose(mf); | ||
| return position; | ||
| } | ||
|
|
||
| int Messages_Get_Pos(int number) { | ||
| int pos; | ||
|
|
||
| for (pos=0; DebugMessages[pos].number !=-1; pos++) | ||
| if (DebugMessages[pos].number==number) | ||
| return pos; | ||
|
|
||
| return -1; | ||
| } |
| @@ -0,0 +1,20 @@ | ||
| #ifndef MESSAGES_H | ||
| #define MESSAGES_H | ||
|
|
||
| #define NUMBEROFMSGS 64 | ||
|
|
||
| #define STUDENT_MESSAGES_FILE "messagesSTD.txt" | ||
| #define TEACHER_MESSAGES_FILE "messagesTCH.txt" | ||
|
|
||
| typedef struct { | ||
| int number; | ||
| char format[120]; | ||
| } DEBUG_MESSAGES; | ||
|
|
||
| extern DEBUG_MESSAGES DebugMessages[NUMBEROFMSGS]; | ||
|
|
||
| int Messages_Get_Pos(int number); | ||
| int Messages_Load_Messages(int, char *); | ||
|
|
||
| #endif | ||
|
|
| @@ -0,0 +1,16 @@ | ||
| #include "Clock.h" | ||
| #include "Asserts.h" | ||
|
|
||
|
|
||
| before(): execution(void Processor_FetchInstruction()) { | ||
| Clock_Update(); | ||
| } | ||
|
|
||
| after(): execution(void Processor_DecodeAndExecuteInstruction()){ | ||
| Asserts_CheckAsserts(); | ||
| } | ||
|
|
||
| before(): execution(void OperatingSystem_InterruptLogic(int)){ | ||
| Clock_Update(); | ||
| } | ||
|
|
| @@ -0,0 +1,70 @@ | ||
| #ifndef OPERATINGSYSTEM_H | ||
| #define OPERATINGSYSTEM_H | ||
|
|
||
| #include "ComputerSystem.h" | ||
| #include <stdio.h> | ||
|
|
||
|
|
||
| #define SUCCESS 1 | ||
| #define PROGRAMDOESNOTEXIST -1 | ||
| #define PROGRAMNOTVALID -2 | ||
|
|
||
| #define USERPROGRAM (unsigned int) 0 | ||
| #define DAEMONPROGRAM (unsigned int) 1 | ||
|
|
||
| #define MAXLINELENGTH 150 | ||
|
|
||
| #define PROCESSTABLEMAXSIZE 4 | ||
|
|
||
| #define INITIALPID 0 | ||
|
|
||
| // In this version, every process occupies a 60 positions main memory chunk | ||
| // so we can use 60 positions for OS code and the system stack | ||
| #define MAINMEMORYSECTIONSIZE (MAINMEMORYSIZE / (PROCESSTABLEMAXSIZE+1)) | ||
|
|
||
| #define NOFREEENTRY -3 | ||
| #define TOOBIGPROCESS -4 | ||
|
|
||
| #define NOPROCESS -1 | ||
| #define NUMBEROFQUEUES 2 | ||
| #define USERPROCESSQUEUE 0 | ||
| #define DAEMONSQUEUE 1 | ||
|
|
||
| //Constants for the statesNames | ||
| #define NEW_STATE 0 | ||
| #define READY_STATE 1 | ||
| #define EXECUTING_STATE 2 | ||
| #define BLOCKED_STATE 3 | ||
| #define EXIT_STATE 4 | ||
|
|
||
| // Enumerated type containing all the possible process states | ||
| enum ProcessStates { NEW, READY, EXECUTING, BLOCKED, EXIT}; | ||
|
|
||
| // Enumerated type containing the list of system calls and their numeric identifiers | ||
| enum SystemCallIdentifiers { SYSCALL_END=3,SYSCALL_YIELD=4, SYSCALL_PRINTEXECPID=5}; | ||
|
|
||
| // A PCB contains all of the information about a process that is needed by the OS | ||
| typedef struct { | ||
| int busy; | ||
| int initialPhysicalAddress; | ||
| int processSize; | ||
| int state; | ||
| int priority; | ||
| int copyOfPCRegister; | ||
| unsigned int copyOfPSWRegister; | ||
| int programListIndex; | ||
| int queueID; | ||
| } PCB; | ||
|
|
||
| // These "extern" declaration enables other source code files to gain access | ||
| // to the variable listed | ||
| extern PCB processTable[PROCESSTABLEMAXSIZE]; | ||
| extern int OS_address_base; | ||
| extern int sipID; | ||
|
|
||
| // Functions prototypes | ||
| void OperatingSystem_Initialize(); | ||
| void OperatingSystem_InterruptLogic(int); | ||
|
|
||
|
|
||
| #endif |
| @@ -0,0 +1,160 @@ | ||
| #include "OperatingSystemBase.h" | ||
| #include "OperatingSystem.h" | ||
| #include "Processor.h" | ||
| #include "Buses.h" | ||
| #include <string.h> | ||
| #include <ctype.h> | ||
| #include <stdlib.h> | ||
|
|
||
| // Code that students should NOT touch | ||
| int OperatingSystem_lineBeginsWithANumber(char *); | ||
|
|
||
| // Search for a free entry in the process table. The index of the selected entry | ||
| // will be used as the process identifier | ||
| int OperatingSystem_ObtainAnEntryInTheProcessTable() { | ||
|
|
||
| int orig=INITIALPID%PROCESSTABLEMAXSIZE; | ||
| int index=0; | ||
| int entry; | ||
|
|
||
| while (index<PROCESSTABLEMAXSIZE) { | ||
| entry = (orig+index)%PROCESSTABLEMAXSIZE; | ||
| if (processTable[entry].busy==0) | ||
| return entry; | ||
| else | ||
| index++; | ||
| } | ||
| return NOFREEENTRY; | ||
| } | ||
|
|
||
|
|
||
| // Returns the size of the program, stored in the program file | ||
| int OperatingSystem_ObtainProgramSize(FILE **programFile, char *program) { | ||
|
|
||
| char lineRead[MAXLINELENGTH]; | ||
| int isComment=1; | ||
| int programSize; | ||
|
|
||
| *programFile= fopen(program, "r"); | ||
|
|
||
| // Check if programFile exists | ||
| if (*programFile==NULL) | ||
| return PROGRAMDOESNOTEXIST; | ||
|
|
||
| // Read the first number as the size of the program. Skip all comments. | ||
| while (isComment==1) { | ||
| if (fgets(lineRead, MAXLINELENGTH, *programFile) == NULL) | ||
| return PROGRAMNOTVALID; | ||
| else | ||
| if (lineRead[0]!='/' && lineRead[0]!='\n') { // Line IS NOT a comment | ||
| isComment=0; | ||
| if (OperatingSystem_lineBeginsWithANumber(lineRead)) | ||
| programSize=atoi(strtok(lineRead," ")); | ||
| else | ||
| return PROGRAMNOTVALID; | ||
| } | ||
| } | ||
| // Only sizes above 0 are allowed | ||
| if (programSize<=0) | ||
| return PROGRAMNOTVALID; | ||
| else | ||
| return programSize; | ||
| } | ||
|
|
||
|
|
||
| // Returns the priority of the program, stored in the program file | ||
| int OperatingSystem_ObtainPriority(FILE *programFile) { | ||
|
|
||
| char lineRead[MAXLINELENGTH]; | ||
| int isComment=1; | ||
| int processPriority; | ||
|
|
||
| // Read the second number as the priority of the program. Skip all comments. | ||
| while (isComment==1) { | ||
| if (fgets(lineRead, MAXLINELENGTH, programFile) == NULL) | ||
| return PROGRAMNOTVALID; | ||
| else | ||
| if (lineRead[0]!='/' && lineRead[0]!='\n') { // Line IS NOT a comment | ||
| isComment=0; | ||
| if (OperatingSystem_lineBeginsWithANumber(lineRead)) | ||
| processPriority=atoi(strtok(lineRead," ")); | ||
| else | ||
| return PROGRAMNOTVALID; | ||
| } | ||
| } | ||
| return processPriority; | ||
| } | ||
|
|
||
|
|
||
| // Function that processes the contents of the file named by the first argument | ||
| // in order to load it in main memory from the address given as the second | ||
| // argument | ||
| // IT IS NOT NECESSARY TO COMPLETELY UNDERSTAND THIS FUNCTION | ||
|
|
||
| int OperatingSystem_LoadProgram(FILE *programFile, int initialAddress, int size) { | ||
|
|
||
| char lineRead[MAXLINELENGTH]; | ||
| char *token0, *token1, *token2; | ||
| MEMORYCELL data; | ||
| int nbInstructions = 0; | ||
|
|
||
| Processor_SetMAR(initialAddress); | ||
| while (fgets(lineRead, MAXLINELENGTH, programFile) != NULL) { | ||
| // REMARK: if lineRead is greater than MAXLINELENGTH in number of characters, the program | ||
| // loading does not work | ||
| data.operationCode=' ';data.operand1=data.operand2=0; | ||
| token0=strtok(lineRead," "); | ||
| if (token0!=NULL && token0[0]!='/' && token0[0]!='\n') { | ||
| // I have an instruction with, at least, an operation code | ||
| data.operationCode=tolower(token0[0]); | ||
| token1=strtok(NULL," "); | ||
| if (token1!=NULL && token1[0]!='/') { | ||
| // I have an instruction with, at least, an operand | ||
| data.operand1=atoi(token1); | ||
| token2=strtok(NULL," "); | ||
| if (token2!=NULL && token2[0]!='/') { | ||
| // The read line is similar to 'sum 2 3 //coment' | ||
| // I have an instruction with two operands | ||
| data.operand2=atoi(token2); | ||
| } | ||
| } | ||
|
|
||
| // More instructions than size... | ||
| if (++nbInstructions > size){ | ||
| return TOOBIGPROCESS; | ||
| } | ||
|
|
||
| Processor_SetMBR(&data); | ||
| // Send data to main memory using the system buses | ||
| Buses_write_DataBus_From_To(CPU, MAINMEMORY); | ||
| Buses_write_AddressBus_From_To(CPU, MAINMEMORY); | ||
| // Tell the main memory controller to write | ||
| MainMemory_writeMemory(); | ||
| Processor_SetMAR(Processor_GetMAR()+1); | ||
| } | ||
| } | ||
| return SUCCESS; | ||
| } | ||
|
|
||
|
|
||
| // Auxiliar for check that line begins with positive number | ||
| int OperatingSystem_lineBeginsWithANumber(char * line) { | ||
| int i; | ||
|
|
||
| for (i=0; i<strlen(line) && line[i]==' '; i++); // Don't consider blank spaces | ||
| // If is there a digit number... | ||
| if (i<strlen(line) && isdigit(line[i])) | ||
| // It's a positive number | ||
| return 1; | ||
| else | ||
| return 0; | ||
| } | ||
|
|
||
|
|
||
| void OperatingSystem_ReadyToShutdown(){ | ||
| // Simulation must finish (done by modifying the PC of the System Idle Process so it points to its 'halt' instruction, | ||
| // located at the last memory position used by that process, and dispatching sipId (next ShortTermSheduled) | ||
| processTable[sipID].copyOfPCRegister=processTable[sipID].initialPhysicalAddress+processTable[sipID].processSize-1; | ||
|
|
||
| } | ||
|
|
| @@ -0,0 +1,14 @@ | ||
| #ifndef OPERATINGSYSTEMBASE_H | ||
| #define OPERATINGSYSTEMBASE_H | ||
|
|
||
| #include "ComputerSystem.h" | ||
| #include <stdio.h> | ||
|
|
||
| // Prototypes of OS functions that students should not change | ||
| int OperatingSystem_ObtainAnEntryInTheProcessTable(); | ||
| int OperatingSystem_ObtainProgramSize(FILE **, char *); | ||
| int OperatingSystem_ObtainPriority(FILE *); | ||
| int OperatingSystem_LoadProgram(FILE *, int, int); | ||
| void OperatingSystem_ReadyToShutdown(); | ||
|
|
||
| #endif |
| @@ -0,0 +1,8 @@ | ||
| 11 | ||
| YRET // Initial Operation for OS | ||
| // Here interrupt vector | ||
| OS 2 // SysCall Interrupt | ||
| YRET | ||
| OS 6 // Exception Interrupt | ||
| YRET | ||
|
|
| @@ -0,0 +1,52 @@ | ||
| #ifndef PROCESSOR_H | ||
| #define PROCESSOR_H | ||
|
|
||
| #include "MainMemory.h" | ||
|
|
||
| #define INTERRUPTTYPES 10 | ||
|
|
||
| // Enumerated type that connects bit positions in the PSW register with | ||
| // processor events and status | ||
| enum PSW_BITS {POWEROFF_BIT=0, ZERO_BIT=1, NEGATIVE_BIT=2, OVERFLOW_BIT=3, EXECUTION_MODE_BIT=7}; | ||
|
|
||
| // Enumerated type that connects bit positions in the interruptLines with | ||
| // interrupt types | ||
| enum INT_BITS {SYSCALL_BIT=2, EXCEPTION_BIT=6}; | ||
|
|
||
| // Functions prototypes | ||
| void Processor_InitializeInterruptVectorTable(); | ||
| void Processor_InstructionCycleLoop(); | ||
| void Processor_CopyInSystemStack(int, int); | ||
| int Processor_CopyFromSystemStack(int); | ||
| unsigned int Processor_PSW_BitState(const unsigned int); | ||
| char * Processor_ShowPSW(); | ||
|
|
||
| // The OS needs to access MAR and MBR registers to save the context of | ||
| // the process to which the processor is being assigned | ||
| // Buses needs to access MAR and MBR | ||
| int Processor_GetMAR(); | ||
| void Processor_SetMAR(int); | ||
| void Processor_GetMBR(MEMORYCELL *); | ||
| void Processor_SetMBR(MEMORYCELL *); | ||
| // int Processor_GetMBR_Value(); | ||
|
|
||
| // The OS needs to access the accumulator register to restore the context of | ||
| // the process to which the processor is being assigned and to save the context | ||
| // of the process being preempted for another ready process | ||
| // void Processor_SetAccumulator(int); | ||
| // int Processor_GetAccumulator(); | ||
|
|
||
| // The OS needs to access the PC register to restore the context of | ||
| // the process to which the processor is being assigned | ||
| void Processor_SetPC(int); | ||
|
|
||
| // The OS needs to access register A to when executing the system call management | ||
| // routine, so it will be able to know the invoked system call identifier | ||
| int Processor_GetRegisterA(); | ||
|
|
||
| // The OS needs to access the PSW register to restore the context of | ||
| // the process to which the processor is being assigned | ||
| void Processor_SetPSW(unsigned int); | ||
|
|
||
| unsigned int Processor_GetPSW(); | ||
| #endif |
| @@ -0,0 +1,21 @@ | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include "Simulator.h" | ||
| #include "ComputerSystem.h" | ||
|
|
||
|
|
||
| int main(int argc, char *argv[]) { | ||
|
|
||
| // We now have a multiprogrammed computer system | ||
| // No more than PROGRAMSMAXNUMBER in the command line | ||
| if ((argc < 3) || (argc>PROGRAMSMAXNUMBER+2)) { | ||
| printf("USE: Simulator <sections to be debugged> <program1> [<program2> <program3> ....] \n"); | ||
| exit(-1); | ||
| } | ||
|
|
||
| // The simulation starts | ||
| ComputerSystem_PowerOn(argc, argv); | ||
| // The simulation ends | ||
| ComputerSystem_PowerOff(); | ||
| return 0; | ||
| } |
| @@ -0,0 +1,11 @@ | ||
| #ifndef SIMULADOR_H | ||
| #define SIMULADOR_H | ||
|
|
||
|
|
||
| // General constants for the simulation | ||
|
|
||
| // Maximum number of programs in the command line plus daemons programs | ||
| #define PROGRAMSMAXNUMBER 20 | ||
|
|
||
|
|
||
| #endif |
| @@ -0,0 +1,9 @@ | ||
| // System Idle Process | ||
| // run NOP + JUMP to NOP indefinitely | ||
| 4 // Program size in memory cells | ||
| 100 // Priority of process (very low priority) | ||
|
|
||
| ADD 1301 417 | ||
| NOP | ||
| JUMP -1 // Jump to NOP | ||
| HALT |
| @@ -0,0 +1,200 @@ | ||
| 20 Messages Loaded | ||
| Asserts file unavailable | ||
| User program list: | ||
| Program [programWhichDoesNotExist] with arrival time [0] | ||
| Program [programInvalidPriority] with arrival time [0] | ||
| Program [programInvalidSize] with arrival time [0] | ||
| Program [programTooBig] with arrival time [0] | ||
| Program [programWithTooManyInstructions] with arrival time [0] | ||
| Program [programMEMADD] with arrival time [0] | ||
| Process [0] created from program [SystemIdleProcess] | ||
| ERROR: Program [programWhichDoesNotExist] is not valid [---it does not exist---] | ||
| ERROR: Program [programInvalidPriority] is not valid [---it does not exist---] | ||
| ERROR: Program [programInvalidSize] is not valid [---invalid priority or size---] | ||
| ERROR: Program [programTooBig] is too big | ||
| ERROR: Program [programWithTooManyInstructions] is too big | ||
| ERROR: Program [programMEMADD] is not valid [---invalid priority or size---] | ||
| New Tick (1) | ||
| y 0 0 (PC: 0, Accumulator: 0, PSW: 130 [--------X-----Z-]) | ||
| New Tick (2) | ||
| a 100 6 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (3) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (4) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (5) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (6) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (7) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (8) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (9) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (10) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (11) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (12) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (13) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (14) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (15) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (16) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (17) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (18) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (19) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (20) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (21) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (22) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (23) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (24) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (25) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (26) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (27) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (28) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (29) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (30) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (31) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (32) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (33) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (34) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (35) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (36) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (37) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (38) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (39) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (40) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (41) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (42) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (43) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (44) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (45) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (46) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (47) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (48) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (49) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (50) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (51) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (52) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (53) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (54) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (55) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (56) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (57) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (58) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (59) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (60) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (61) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (62) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (63) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (64) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (65) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (66) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (67) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (68) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (69) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (70) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (71) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (72) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (73) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (74) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (75) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (76) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (77) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (78) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (79) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (80) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (81) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (82) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (83) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (84) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (85) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (86) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (87) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (88) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (89) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (90) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (91) | ||
| n 0 0 (PC: 2, Accumulator: 106, PSW: 128 [--------X-------]) | ||
| New Tick (92) | ||
| j -1 0 (PC: 1, Accumulator: 106, PSW: 128 [--------X-------]) |
| @@ -0,0 +1,2 @@ | ||
| NOP | ||
| TRAP 3 |
| @@ -0,0 +1,18 @@ | ||
| // Students created messages | ||
| // Format: numberOfMessage,textPrintfFormatedWithColourCodes | ||
| // | ||
| // numbers of messages greather than 100 for students | ||
| // | ||
| 101,User program list:\n | ||
| 102,\tProgram [@B%s@@] with arrival time [@B%d@@]\n | ||
| 103,@RERROR: There are not free entries in the process table for the program [%s]\n@@ | ||
| 104,@RERROR: Program [%s] is not valid [%s]\n@@ | ||
| 105,@RERROR: Program [%s] is too big\n@@ | ||
| 106,Ready-to-run process queue: \n | ||
| 107,[@G%d@@,%d] | ||
| 108,\n | ||
| 110,Process [@G%d@@] moving from the [@G%s@@] state to the [@G%s@@] state\n | ||
| 111,New process [@G%d@@] moving to the [@G%s@@]\n | ||
| 112,\tUSER: | ||
| 113,\tDAEMONS: | ||
| 1100,PETA AQUI REDIOS |
| @@ -0,0 +1,28 @@ | ||
| // Processor messages | ||
| 1,%c %d %d | ||
| 2,_ _ _ | ||
| 3, (PC: @R%d@@, Accumulator: @R%d@@, PSW: @R%d@@ [@R%s@@])\n | ||
|
|
||
|
|
||
| // OperatingSystem messages | ||
| 21,@RERROR: Missing SIP program!@@\n | ||
| 22,@GProcess [%d] created from program [%s]@@\n | ||
| 23,@RProcess [%d] has generated an exception and is terminating@@\n | ||
| 24,@RProcess [%d] has the processor assigned@@\n | ||
| 25,@RProcess [%d] has requested to terminate@@\n | ||
|
|
||
| // Assert system messages | ||
| 90,@RAssert failed. Time:@@ %d@R; Element:@@ %s; | ||
| 91,@R Expected:@@ %c@R; Real:@@ %c | ||
| 92,@R Expected:@@ %d@R; Real:@@ %d | ||
| 93,@R; Memory address:@@ %d | ||
|
|
||
| // Time | ||
| 97,New Tick (%d)\n | ||
|
|
||
| // Formating and generic messages | ||
| 98,%s | ||
|
|
||
| // ComputerSystem messages | ||
| 99,@REND of the simulation@@\n | ||
|
|
| @@ -0,0 +1,4 @@ | ||
| -3 | ||
| 2 | ||
| ADD 10 1 | ||
| HALT |
| @@ -0,0 +1,9 @@ | ||
| 55 | ||
|
|
||
| ADD 0 0 | ||
| MEMADD 1 33 | ||
| WRITE 33 | ||
| INC -7 | ||
| ZJUMP 2 | ||
| JUMP -4 | ||
| HALT |
| @@ -0,0 +1,7 @@ | ||
|
|
||
| 65 | ||
| 2 | ||
| ADD 100 6 | ||
| WRITE 7 | ||
| NOP | ||
| TRAP 3 |
| @@ -0,0 +1,7 @@ | ||
|
|
||
| 1 | ||
| 2 | ||
| ADD 100 6 | ||
| WRITE 7 | ||
| NOP | ||
| TRAP 3 |
| @@ -0,0 +1,7 @@ | ||
|
|
||
| 30 | ||
| 5 | ||
| NOP | ||
| ADD 10 -13 | ||
| WRITE 15 | ||
| TRAP 3 |
| @@ -0,0 +1,7 @@ | ||
|
|
||
| 30 | ||
| -1 | ||
| NOP | ||
| ADD 10 -13 | ||
| WRITE 15 | ||
| TRAP 3 |
| @@ -0,0 +1,7 @@ | ||
|
|
||
| 1 | ||
| 2 | ||
| ADD 100 6 | ||
| WRITE 7 | ||
| NOP | ||
| TRAP 3 |
| @@ -0,0 +1,2 @@ | ||
| The 12 exercise has been implemented (not tested), except from the check of the process type (as the exercise 11 was not finished) | ||
| The log will be empty, as I did not have time to execute them. |
| @@ -0,0 +1,394 @@ | ||
| #include "Asserts.h" | ||
| #include <string.h> | ||
| #include <stdio.h> | ||
| #include "MainMemory.h" | ||
| #include "Clock.h" | ||
| #include "ComputerSystemBase.h" | ||
| #include "MMU.h" | ||
| #include "Heap.h" | ||
|
|
||
| extern MEMORYCELL mainMemory[]; | ||
| extern int registerPC_CPU; // Program counter | ||
| extern int registerAccumulator_CPU; // Accumulator | ||
| extern MEMORYCELL registerIR_CPU; // Instruction register | ||
| extern unsigned int registerPSW_CPU; // Processor state word | ||
| extern int registerMAR_CPU; // Memory Address Register | ||
| extern MEMORYCELL registerMBR_CPU; // Memory Buffer Register | ||
| extern int executingProcessID; // Executing process PID | ||
|
|
||
|
|
||
| char *elements[]={ | ||
| "RMEM_OP", | ||
| "RMEM_O1", | ||
| "RMEM_O2", | ||
| "AMEM_OP", | ||
| "AMEM_O1", | ||
| "AMEM_O2", | ||
| "PC", | ||
| "ACC", | ||
| "IR_OP", | ||
| "IR_O1", | ||
| "IR_O2", | ||
| "PSW", | ||
| "MAR", | ||
| "MBR_OP", | ||
| "MBR_O1", | ||
| "MBR_O2", | ||
| "MMU_BS", | ||
| "MMU_LM", | ||
| "MMU_MAR", | ||
| "MMEM_MAR", | ||
| "MMBR_OP", | ||
| "MMBR_O1", | ||
| "MMBR_O2", | ||
| "XPID", | ||
| NULL}; | ||
|
|
||
| ASSERT_DATA asserts[MAX_ASSERTS]; | ||
|
|
||
| // MontÃculo de asertos | ||
| int assertsQueue[MAX_ASSERTS]; | ||
| int numOfElementsInAssertsQueue=0; | ||
|
|
||
| // La lista de asertos en todos los instantes está al final de la assertsQueue metida al revés | ||
| int beginOfAllTimeAsserts=MAX_ASSERTS; | ||
|
|
||
| // prototype functions | ||
| int Asserts_IsThereANewAssert(int); | ||
| void Asserts_CheckOneAssert(int); | ||
|
|
||
| extern int GEN_ASSERTS; | ||
|
|
||
| int elementNumber(char *cmp) { | ||
| int n=0; | ||
|
|
||
| while ((elements[n]!=NULL) && strcmp(cmp, elements[n])) | ||
| n++; | ||
|
|
||
| if (elements[n]==NULL) return -1; | ||
| else return n; | ||
|
|
||
| } | ||
|
|
||
| void strcmpSpaces(char *target, char *src, int nChars) { | ||
| int l, s, t; | ||
|
|
||
| l=strlen(src); | ||
| t=0; | ||
| for (s=0; (t<nChars-1) && (s<l); s++) { | ||
| if (src[s]!=' ') target[t++]=src[s]; | ||
| } | ||
| target[t]=0; | ||
| } | ||
|
|
||
| int Asserts_LoadAsserts() { | ||
| // leer el fichero e ir almacenando en cada elemento lo que sea; | ||
| ASSERT_DATA a; | ||
|
|
||
| char lineRead[MAXIMUMLENGTH]; | ||
| FILE *mf; | ||
| char *time, *element, *value, *address; | ||
| char svalue[E_SIZE]; | ||
|
|
||
|
|
||
| int lineNumber=0;; | ||
| int numberAsserts=0; | ||
| int rc; | ||
| int en; | ||
|
|
||
| mf=fopen(ASSERTS_FILE, "r"); | ||
| if (mf==NULL) { | ||
| asserts[0].time=-1; | ||
| return -1; | ||
| } | ||
|
|
||
| while (fgets(lineRead,MAXIMUMLENGTH, mf) != NULL && numberAsserts<MAX_ASSERTS) { | ||
| lineNumber++; | ||
| // Leemos hasta 4 elementos por aserto | ||
| time=strtok(lineRead,","); | ||
| if (time==NULL){ | ||
| printf("Illegal Assert in line %d of file %s\n",lineNumber,ASSERTS_FILE); | ||
| continue; | ||
| } | ||
|
|
||
| if ((time[0]=='/') || (time[0]=='\n')) | ||
| continue; | ||
|
|
||
| element=strtok(NULL,","); | ||
| if (element==NULL){ | ||
| printf("Illegal Assert in line %d of file %s\n",lineNumber,ASSERTS_FILE); | ||
| continue; | ||
| } | ||
|
|
||
| value=strtok(NULL,","); | ||
| if (value==NULL){ | ||
| printf("Illegal Assert in line %d of file %s\n",lineNumber,ASSERTS_FILE); | ||
| continue; | ||
| } | ||
| address=strtok(NULL,"\n"); | ||
|
|
||
| //printf("-> %s, %s, %s, %s\n",time, element, value, address); | ||
|
|
||
| strcmpSpaces(a.element, element,E_SIZE); | ||
| if (strcmp(time,"*")) { | ||
| rc=sscanf(time,"%d",&a.time); | ||
| if (rc==0){ | ||
| printf("Illegal time format in line %d of file %s\n",lineNumber,ASSERTS_FILE); | ||
| continue; | ||
| } | ||
| } | ||
| else a.time=-33; // All the instants of time. | ||
|
|
||
| //printf("-%s-\n",a.element); | ||
| // Si vamos a verificar un código de operación leemos un char (RMEM_OP, AMEM_OP,IR_OP, MBR_OP, MMBR_OP) | ||
| en=elementNumber(a.element); | ||
| if ((en==RMEM_OP) || (en==AMEM_OP) || (en==IR_OP) || (en==MBR_OP) || (en==MMBR_OP)) { | ||
| strcmpSpaces(svalue, value,E_SIZE); | ||
| rc=sscanf(svalue,"%c",(char *) &a.value); | ||
|
|
||
| } | ||
| else | ||
| rc=sscanf(value,"%d",&a.value); | ||
|
|
||
| if (rc==0){ | ||
| printf("Illegal expected value format in line %d of file %s (%s)\n",lineNumber,ASSERTS_FILE,value); | ||
| continue; | ||
| } | ||
|
|
||
| // Si vamos a verificar una posición de memoria leemos la dirección (RMEM_OP, RMEM_O1, RMEM_O2, AMEM_OP, AMEM_O1, AMEM_O2) | ||
| en=elementNumber(a.element); | ||
| if ((en==RMEM_OP) || (en==RMEM_O1) || (en==RMEM_O2) || (en==AMEM_OP) || (en==AMEM_O1) || (en==AMEM_O2)) { | ||
| if (address==NULL){ | ||
| printf("Illegal Assert in line %d of file %s\n",lineNumber,ASSERTS_FILE); | ||
| continue; | ||
| } | ||
| rc=sscanf(address,"%d",&a.address); | ||
| if (rc==0){ | ||
| printf("Illegal address format in line %d of file %s\n",lineNumber,ASSERTS_FILE); | ||
| continue; | ||
| } | ||
| } | ||
| else a.address=0; | ||
|
|
||
| asserts[numberAsserts]=a; | ||
|
|
||
| if (a.time!=-33) | ||
| // Lo mete en cola de asertos | ||
| Heap_add(numberAsserts,assertsQueue,QUEUE_ASSERTS,&numOfElementsInAssertsQueue,MAX_ASSERTS); | ||
| else | ||
| // Lo mete en lista al final y guarda donde empiezan los asertos sin tiempo | ||
| assertsQueue[--beginOfAllTimeAsserts]=numberAsserts; | ||
|
|
||
| numberAsserts++; | ||
| } | ||
| fclose(mf); | ||
| if (numberAsserts==MAX_ASSERTS) | ||
| printf("Warning maximun number of asserts reached !!! (%d)\n",numberAsserts); | ||
| else | ||
| asserts[numberAsserts].time=-1; // Para indicar el fin de los asertos (sobrarÃa) | ||
| return numberAsserts; | ||
| } | ||
|
|
||
|
|
||
| void genAssertMsg(int time, char *ele, int realValue, int addr) { | ||
| int en; | ||
|
|
||
| printf("%d, %s",time, ele); | ||
| en=elementNumber(ele); | ||
|
|
||
| if ((en==RMEM_OP) || (en==AMEM_OP) || (en==IR_OP) || (en==MBR_OP)) | ||
| printf(", %c",realValue); | ||
| else | ||
| printf(", %d", realValue); | ||
|
|
||
| if ((en==RMEM_OP) || (en==RMEM_O1) || (en==RMEM_O2) || (en==AMEM_OP) || (en==AMEM_O1) || (en==AMEM_O2)) | ||
| printf(", %d", addr); | ||
|
|
||
| printf("\n"); | ||
| } | ||
|
|
||
| void assertMsg(int time, char *ele, int expectedValue, int realValue, int addr) { | ||
| int en; | ||
|
|
||
| if (GEN_ASSERTS) { | ||
| genAssertMsg(time, ele, realValue,addr); | ||
| return; | ||
| } | ||
|
|
||
| // printf("Assert failed. Time: %d; Element: %s; ", time, ele); | ||
| ComputerSystem_DebugMessage(90,ERROR, time, ele); | ||
| en=elementNumber(ele); | ||
|
|
||
| if ((en==RMEM_OP) || (en==AMEM_OP) || (en==IR_OP) || (en==MBR_OP)) | ||
| // printf("Expected: '%c'; Real: '%c'", expectedValue, realValue); | ||
| ComputerSystem_DebugMessage(91,ERROR, expectedValue, realValue); | ||
| else | ||
| // printf("Expected: %d; Real: %d", expectedValue, realValue); | ||
| ComputerSystem_DebugMessage(92,ERROR, expectedValue, realValue); | ||
|
|
||
| if ((en==RMEM_OP) || (en==RMEM_O1) || (en==RMEM_O2) || (en==AMEM_OP) || (en==AMEM_O1) || (en==AMEM_O2)) | ||
| // printf("; Memory address: %d", addr); | ||
| ComputerSystem_DebugMessage(93,ERROR, addr); | ||
|
|
||
| // printf("\n"); | ||
| ComputerSystem_DebugMessage(98, ERROR, "\n"); | ||
| } | ||
|
|
||
|
|
||
| void Asserts_CheckAsserts(){ | ||
| int na; | ||
| int globalCounter=Clock_GetTime(); | ||
|
|
||
| // Checking unique time asserts | ||
| while (Asserts_IsThereANewAssert(globalCounter)>0) { | ||
| na=Heap_poll(assertsQueue,QUEUE_ASSERTS,&numOfElementsInAssertsQueue); | ||
| // if ((asserts[na].time==globalCounter) || (asserts[na].time==-33)) { | ||
| if ((asserts[na].time==globalCounter)/* || (asserts[na].time==-33)*/) { | ||
| Asserts_CheckOneAssert(na); | ||
| } | ||
| else { | ||
| ComputerSystem_DebugMessage(95,ERROR,asserts[na].time,asserts[na].element); | ||
| } | ||
| } | ||
|
|
||
| na=beginOfAllTimeAsserts; | ||
|
|
||
| // Checking asserts for all time | ||
| while (na<MAX_ASSERTS) { | ||
| Asserts_CheckOneAssert(assertsQueue[na++]); | ||
| } | ||
| } | ||
|
|
||
| void Asserts_CheckOneAssert(int na){ | ||
| MEMORYCELL data; | ||
| int op=elementNumber(asserts[na].element); | ||
| int globalCounter=Clock_GetTime(); | ||
|
|
||
| switch (op) { | ||
| case RMEM_OP: | ||
| if ((mainMemory[MMU_GetBase()+asserts[na].address].operationCode!=(char)asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"RMEM_OP",asserts[na].value,mainMemory[MMU_GetBase()+asserts[na].address].operationCode,asserts[na].address); | ||
| break; | ||
| case RMEM_O1: | ||
| if ((mainMemory[MMU_GetBase()+asserts[na].address].operand1!=(char)asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"RMEM_O1",asserts[na].value,mainMemory[MMU_GetBase()+asserts[na].address].operand1,asserts[na].address); | ||
| break; | ||
| case RMEM_O2: | ||
| if ((mainMemory[MMU_GetBase()+asserts[na].address].operand2!=(char)asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"RMEM_O2",asserts[na].value,mainMemory[MMU_GetBase()+asserts[na].address].operand2,asserts[na].address); | ||
| break; | ||
| case AMEM_OP: | ||
| if ((mainMemory[asserts[na].address].operationCode!=(char)asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"AMEM_OP",asserts[na].value,mainMemory[asserts[na].address].operationCode,asserts[na].address); | ||
| break; | ||
| case AMEM_O1: | ||
| if ((mainMemory[asserts[na].address].operand1!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"AMEM_01",asserts[na].value,mainMemory[asserts[na].address].operand1,asserts[na].address); | ||
| break; | ||
| case AMEM_O2: | ||
| if ((mainMemory[asserts[na].address].operand2!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"AMEM_02",asserts[na].value,mainMemory[asserts[na].address].operand2,asserts[na].address); | ||
| break; | ||
| case PC: | ||
| if ((registerPC_CPU!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"PC",asserts[na].value,registerPC_CPU,0); | ||
| break; | ||
| case ACC: | ||
| if ((registerAccumulator_CPU!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"ACC",asserts[na].value,registerAccumulator_CPU,0); | ||
| break; | ||
| case IR_OP: | ||
| if ((registerIR_CPU.operationCode!=(char) asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"IR_OP",asserts[na].value,registerIR_CPU.operationCode,0); | ||
| break; | ||
| case IR_O1: | ||
| if ((registerIR_CPU.operand1!= asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"IR_01",asserts[na].value,registerIR_CPU.operand1,0); | ||
| break; | ||
| case IR_O2: | ||
| if ((registerIR_CPU.operand2!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"IR_02",asserts[na].value,registerIR_CPU.operand2,0); | ||
| break; | ||
| case PSW: | ||
| if ((registerPSW_CPU!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"PSW",asserts[na].value,registerPSW_CPU,0); | ||
| break; | ||
| case MAR: | ||
| if ((registerMAR_CPU!=asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MAR",asserts[na].value,registerMAR_CPU,0); | ||
| break; | ||
| case MBR_OP: | ||
| if ((registerMBR_CPU.operationCode!=(char) asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MBR_OP",asserts[na].value,registerMBR_CPU.operationCode,0); | ||
| break; | ||
| case MBR_O1: | ||
| if ((registerMBR_CPU.operand1!= asserts[na].value)|| GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MBR_O1",asserts[na].value,registerMBR_CPU.operand1,0); | ||
| break; | ||
| case MBR_O2: | ||
| if ((registerMBR_CPU.operand2!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MBR_02",asserts[na].value,registerMBR_CPU.operand2,0); | ||
| break; | ||
| case MMU_BS: | ||
| if ((MMU_GetBase()!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMU_BS",asserts[na].value,MMU_GetBase(),0); | ||
| break; | ||
| case MMU_LM: | ||
| if ((MMU_GetLimit()!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMU_LM",asserts[na].value,MMU_GetLimit(),0); | ||
| break; | ||
| case MMU_MAR: | ||
| if ((MMU_GetMAR()!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMU_MAR",asserts[na].value,MMU_GetMAR(),0); | ||
| break; | ||
| case MMEM_MAR: | ||
| if ((MainMemory_GetMAR()!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMEM_MAR",asserts[na].value,MainMemory_GetMAR(),0); | ||
| break; | ||
| case MMBR_OP: | ||
| MainMemory_GetMBR(&data); | ||
| if ((data.operationCode!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMBR_OP",asserts[na].value,data.operationCode,0); | ||
| break; | ||
| case MMBR_O1: | ||
| MainMemory_GetMBR(&data); | ||
| if ((data.operand1!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMBR_O1",asserts[na].value,data.operand1,0); | ||
| break; | ||
| case MMBR_O2: | ||
| MainMemory_GetMBR(&data); | ||
| if ((data.operand2!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"MMBR_O2",asserts[na].value,data.operand2,0); | ||
| break; | ||
| case XPID: | ||
| if ((executingProcessID!=asserts[na].value) || GEN_ASSERTS) | ||
| assertMsg(globalCounter,"XPID",asserts[na].value,executingProcessID,0); | ||
| break; | ||
| default: ; | ||
|
|
||
| } | ||
| } | ||
|
|
||
| // This function returns: | ||
| // -1 if no asserts in assertsQueue | ||
| // 1 if any asserts is now | ||
| // 0 else | ||
| // considered by CheckAsserts to compare at the current time | ||
| int Asserts_IsThereANewAssert(int currentTime) { | ||
| #ifdef QUEUE_ASSERTS | ||
| int indexInAsserts = Heap_getFirst(assertsQueue,numOfElementsInAssertsQueue); | ||
|
|
||
| if (indexInAsserts < 0) | ||
| return -1; // No new asserts to check | ||
|
|
||
| if (asserts[indexInAsserts].time <= currentTime) | ||
| return 1; // There'is new assert | ||
| #endif | ||
| return 0; // No assert in current time | ||
| } | ||
|
|
||
| void Asserts_TerminateAssertions(){ | ||
| if (numOfElementsInAssertsQueue) | ||
| // printf("Warning, numOfElementsInAssertsQueue unchecked asserts in Asserts queue !!! ); | ||
| ComputerSystem_DebugMessage(94,ERROR,numOfElementsInAssertsQueue); | ||
| }; |
| @@ -0,0 +1,50 @@ | ||
| #ifndef CHECKASSERTS_H | ||
| #define CHECKASSERTS_H | ||
|
|
||
| #define MAX_ASSERTS 500 | ||
| #define MAXIMUMLENGTH 64 | ||
| #define ASSERTS_FILE "asserts" | ||
| #define E_SIZE 8 | ||
|
|
||
|
|
||
|
|
||
| #define RMEM_OP 0 | ||
| #define RMEM_O1 1 | ||
| #define RMEM_O2 2 | ||
| #define AMEM_OP 3 | ||
| #define AMEM_O1 4 | ||
| #define AMEM_O2 5 | ||
| #define PC 6 | ||
| #define ACC 7 | ||
| #define IR_OP 8 | ||
| #define IR_O1 9 | ||
| #define IR_O2 10 | ||
| #define PSW 11 | ||
| #define MAR 12 | ||
| #define MBR_OP 13 | ||
| #define MBR_O1 14 | ||
| #define MBR_O2 15 | ||
| #define MMU_BS 16 | ||
| #define MMU_LM 17 | ||
| #define MMU_MAR 18 | ||
| #define MMEM_MAR 19 | ||
| #define MMBR_OP 20 | ||
| #define MMBR_O1 21 | ||
| #define MMBR_O2 22 | ||
| #define XPID 23 | ||
|
|
||
| typedef struct { | ||
| int time; | ||
| int value; | ||
| char element[E_SIZE]; // Se almacenará lo arriba indicado o MEM si es un elemento de memoria (o RMEM y AMEM en su caso) | ||
| int address; | ||
| } ASSERT_DATA; | ||
|
|
||
| // Functions prototypes | ||
| int Asserts_LoadAsserts(); | ||
| void Asserts_CheckAsserts(); | ||
| void Asserts_TerminateAssertions(); | ||
|
|
||
| extern ASSERT_DATA asserts[MAX_ASSERTS]; | ||
|
|
||
| #endif |