From cc4c1c02f5aa57ba6b4e68e7ccff0f4982b14af8 Mon Sep 17 00:00:00 2001 From: Ross Wilson Date: Sun, 18 Oct 2015 15:34:53 +0700 Subject: [PATCH] Starting to work but still crashes --- vimlac/Makefile | 17 +- vimlac/cpu.c | 17 +- vimlac/cpu.h | 2 + vimlac/test_cpu.c | 774 +++++++++++++++++++++------------------------- 4 files changed, 373 insertions(+), 437 deletions(-) diff --git a/vimlac/Makefile b/vimlac/Makefile index a1aabea..5f461a3 100755 --- a/vimlac/Makefile +++ b/vimlac/Makefile @@ -1,25 +1,24 @@ -DEVFILES = cpu.o dcpu.o ptr.o ptp.o memory.o kb.o ttyin.o ttyout.o trace.o error.o +DEVFILES = cpu.o dcpu.o ptr.o ptp.o memory.o kb.o ttyin.o ttyout.o trace.o error.o log.o OFILES = vimlac.o $(DEVFILES) #CFLAGS=-fPIC -O2 -Wall -ansi -pedantic -std=c99 -g CFLAGS=-O2 -Wall -ansi -pedantic -std=c99 -g -test: vimlac.py vimlac - #python vimlac.py -ptr test_add.ptp -r 040 -r 0100 - ./vimlac +test: test_cpu + rm -f vimlac.log + ./test_cpu CPU.test vimlac: ${OFILES} Makefile - #gcc -o vimlac.so -shared -fPIC ${OFILES} - gcc -o vimlac ${OFILES} + gcc -o vimlac ${CFLAGS} ${OFILES} test_ptr: test_ptr.c ptr.c ptr.h Makefile - gcc -o test_ptr ptr.c test_ptr.c + gcc -o test_ptr ${CFLAGS} ptr.c test_ptr.c test_cpu: test_cpu.c $(DEVFILES) Makefile - gcc -o test_cpu $(DEVFILES) test_cpu.c + gcc -o test_cpu ${CFLAGS} $(DEVFILES) test_cpu.c test_memory: test_memory.c memory.c memory.h Makefile - gcc -o test_memory memory.c test_memory.c + gcc -o test_memory ${CFLAGS} memory.c test_memory.c clean: rm -f *.pyc *.o vimlac test_ptr test_memory *~ _#*#_.* diff --git a/vimlac/cpu.c b/vimlac/cpu.c index 73e07da..aa6a0ed 100755 --- a/vimlac/cpu.c +++ b/vimlac/cpu.c @@ -66,7 +66,7 @@ cpu_stop(void) /****************************************************************************** -Description : Functions to get various registers. +Description : Functions to get various registers and states. Parameters : Returns : Comments : @@ -92,12 +92,25 @@ cpu_get_PC(void) } +WORD +cpu_get_DS(void) +{ + return r_DS; +} + + WORD cpu_get_prev_PC(void) { return Prev_r_PC; } +bool +cpu_get_state(void) +{ + return cpu_on; +} + void cpu_set_AC(WORD new_ac) @@ -160,7 +173,7 @@ i_LAW_LWC(bool indirect, WORD address) if (indirect) { /* LWC */ - r_AC = (~address + 1) & WORD_MASK; + r_AC = ~address & WORD_MASK; trace("LWC\t %5.5o", address); } else diff --git a/vimlac/cpu.h b/vimlac/cpu.h index f8237f3..ef74296 100755 --- a/vimlac/cpu.h +++ b/vimlac/cpu.h @@ -19,6 +19,8 @@ WORD cpu_get_AC(void); WORD cpu_get_L(void); WORD cpu_get_PC(void); WORD cpu_get_prev_PC(void); +WORD cpu_get_DS(void); +bool cpu_get_state(void); void cpu_set_AC(WORD ac); void cpu_set_L(WORD l); void cpu_set_PC(WORD pc); diff --git a/vimlac/test_cpu.c b/vimlac/test_cpu.c index 500a9d2..d34b93f 100644 --- a/vimlac/test_cpu.c +++ b/vimlac/test_cpu.c @@ -58,10 +58,15 @@ #include "vimlac.h" #include "cpu.h" +#include "dcpu.h" #include "memory.h" #include "error.h" +#include "log.h" +// string comparison macro +#define STREQ(a, b) (strcmp((a), (b)) == 0) + // constants const char *LstFilename = "_#TEST#_.lst"; // LST filename const char *AsmFilename = "_#TEST#_.asm"; // ASM filename @@ -75,6 +80,7 @@ typedef struct _Command char *opcode; char *field1; char *field2; + char *orig2; } Command; typedef struct _Test @@ -84,10 +90,24 @@ typedef struct _Test Command *commands; } Test; +typedef struct _Assoc +{ + struct _Assoc *next; +} Assoc; + +bool DisplayOn = false; int UsedCycles = 0; +WORD RegAllValue = 0; +WORD MemAllValue = 0; +Assoc *RememberReg; +void +remember(Assoc *head, char *name, WORD value) +{ +} + /****************************************************************************** Description : Convert a string value into a WORD integer. Parameters : str - address of string holding [0-9] characters @@ -131,6 +151,7 @@ new_Command(char *opcode) result->next = NULL; result->field1 = NULL; result->field2 = NULL; + result->orig2 = NULL; return result; } @@ -282,6 +303,7 @@ parse_one_cmd(char *scan) char *opcode; char *field1 = NULL; char *field2 = NULL; + char *orig2 = NULL; char tmpbuff[16]; @@ -313,6 +335,7 @@ parse_one_cmd(char *scan) field2 = scan; if (*field2 == '[') { // assembler field + orig2 = new_String(field2); ++field2; while (*scan && !(*scan == ']')) ++scan; @@ -344,6 +367,8 @@ parse_one_cmd(char *scan) else result->field2 = NULL; + result->orig2 = orig2; + return result; } @@ -497,16 +522,19 @@ setreg(char *name, char *fld2) int result = 0; WORD value = str2word(fld2); - if (strcmp(name, "ac") == 0) + vlog("Setting register %s to %07o", name, value); + + if (STREQ(name, "ac")) cpu_set_AC(value); - else if (strcmp(name, "l") == 0) + else if (STREQ(name, "l")) cpu_set_L(value); - else if (strcmp(name, "pc") == 0) + else if (STREQ(name, "pc")) cpu_set_PC(value); - else if (strcmp(name, "ds") == 0) + else if (STREQ(name, "ds")) cpu_set_DS(value); else { + vlog("setreg: bad register name: %s", name); printf("setreg: bad register name: %s\n", name); result = 1; } @@ -514,6 +542,33 @@ setreg(char *name, char *fld2) return result; } +/****************************************************************************** +Description : Set the display ON or OFF. + Parameters : state - string containing 'on' or 'off' + : var2 - unused + Returns : The number of errors encountered (0 or 1). + Comments : + ******************************************************************************/ +int +setd(char *state, char *var2) +{ + vlog("Setting display '%s'", state); + + if (STREQ(state, "on")) + dcpu_start(); + else if (STREQ(state, "off")) + dcpu_stop(); + else + { + vlog("setd: bad state: %s", state); + printf("setd: bad state: %s", state); + return 1; + } + + return 0; +} + + /****************************************************************************** Description : Set a memory cell to a value; Parameters : addr - address of memory cell (string) @@ -527,6 +582,8 @@ setmem(char *addr, char *fld2) WORD address = str2word(addr); WORD value = str2word(fld2); + vlog("Setting memory at %07o to %07o", address, value); + mem_put(address, false, value); return 0; @@ -534,34 +591,86 @@ setmem(char *addr, char *fld2) /****************************************************************************** -Description : Set a memory cell to a value; - Parameters : addr - address of memory cell (string) - : fld2 - value to put into cell (string) +Description : Set all registers to a value. + Parameters : value - value to put into registers (string) + : var2 - unused Returns : The number of errors encountered (0 or 1). - Comments : Sets globals used to check after execution. + Comments : ******************************************************************************/ int -run_one(char *addr, char *fld2) +allreg(char *value, char *var2) { - WORD address = str2word(addr); + int val = str2word(value); - if (addr) - { // force PC to given address - cpu_set_PC(address); - } + vlog("Setting all registers to %07o", val); - UsedCycles = cpu_execute_one(); + RegAllValue = val; + + cpu_set_AC(val); + cpu_set_L(val && 1); + cpu_set_PC(val); + cpu_set_DS(val); return 0; } /****************************************************************************** -Description : Set a memory cell to a value; - Parameters : addr - address of memory cell (string) - : fld2 - value to put into cell (string) +Description : Set all memory locations to a value. + Parameters : value - value to put into memory (string) + : var2 - unused Returns : The number of errors encountered (0 or 1). - Comments : Sets globals used to check after execution. + Comments : + ******************************************************************************/ +int +allmem(char *value, char *var2) +{ + int val = str2word(value); + + vlog("Setting all memory to %07o", val); + + MemAllValue = val; + + for (WORD adr = 0; adr < MEM_SIZE; ++adr) + mem_put(adr, false, val); + + return 0; +} + + +/****************************************************************************** +Description : Run one instruction on the CPU. + Parameters : addr - address of memory cell (string, may be NULL) + : fld2 - unused + Returns : The number of errors encountered (0 or 1). + Comments : + ******************************************************************************/ +int +run_one(char *addr, char *fld2) +{ + WORD address = str2word(addr); + + vlog("Executing single instruction at %s", (addr) ? addr : "PC"); + + if (addr) + { // force PC to given address + cpu_set_PC(address); + } + + cpu_start(); + UsedCycles = cpu_execute_one(); + cpu_stop(); + + return 0; +} + + +/****************************************************************************** +Description : Check that the number of cycles used is as expected. + Parameters : cycles - address of memory cell (string) + : var2 - unused + Returns : The number of errors encountered (0 or 1). + Comments : ******************************************************************************/ int checkcycles(char *cycles, char *fld2) @@ -570,53 +679,182 @@ checkcycles(char *cycles, char *fld2) if (c != UsedCycles) { - printf("Test used %d cycles, exoected %d!?", UsedCycles, c); + vlog("Test used %d cycles, expected %d!?", UsedCycles, c); + printf("Test used %d cycles, expected %d!?\n", UsedCycles, c); return 1; } return 0; } -#ifdef JUNK - def checkcycles(self, cycles, var2=None): - """Check that opcode cycles used is correct.""" - if cycles != self.used_cycles: - return 'Opcode used %d cycles, expected %d' % (self.used_cycles, cycles) -#endif +/****************************************************************************** +Description : Check that a register contents is as expected. + Parameters : reg - string holding register name + : value - expected register value (string) + Returns : The number of errors encountered (0 or 1). + Comments : + ******************************************************************************/ +int +checkreg(char *reg, char *value) +{ + WORD val = str2word(value); -#ifdef JUNK -test_cpu.c:537:22: warning: implicit declaration of function 'run' is invalid in C99 [-Wimplicit-function-declaration] -error += run(fld1, fld2); -^ -test_cpu.c:539:22: warning: implicit declaration of function 'checkcycles' is invalid in C99 [-Wimplicit-function-declaration] -error += checkcycles(fld1, fld2); -^ -test_cpu.c:541:22: warning: implicit declaration of function 'checkreg' is invalid in C99 [-Wimplicit-function-declaration] -error += checkreg(fld1, fld2); -^ -test_cpu.c:543:22: warning: implicit declaration of function 'checkmem' is invalid in C99 [-Wimplicit-function-declaration] -error += checkmem(fld1, fld2); -^ -test_cpu.c:545:22: warning: implicit declaration of function 'allreg' is invalid in C99 [-Wimplicit-function-declaration] -error += allreg(fld1, fld2); -^ -test_cpu.c:547:22: warning: implicit declaration of function 'allmem' is invalid in C99 [-Wimplicit-function-declaration] -error += allmem(fld1, fld2); -^ -test_cpu.c:549:22: warning: implicit declaration of function 'checkrun' is invalid in C99 [-Wimplicit-function-declaration] -error += checkrun(fld1, fld2); -^ -test_cpu.c:551:22: warning: implicit declaration of function 'setd' is invalid in C99 [-Wimplicit-function-declaration] -error += setd(fld1, fld2); -^ -test_cpu.c:553:22: warning: implicit declaration of function 'checkd' is invalid in C99 [-Wimplicit-function-declaration] -error += checkd(fld1, fld2); -#endif + if (STREQ(reg, "ac")) + { + remember(RememberReg, reg, cpu_get_AC()); + if (cpu_get_AC() != val) + { + vlog("AC is %07o, should be %07o", cpu_get_AC(), val); + printf("AC is %07o, should be %07o\n", cpu_get_AC(), val); + return 1; + } + } + else if (STREQ(reg, "l")) + { + remember(RememberReg, reg, cpu_get_L()); + if (cpu_get_L() != val) + { + vlog("L is %02o, should be %02o", cpu_get_L(), val); + printf("L is %02o, should be %02o\n", cpu_get_L(), val); + return 1; + } + } + else if (STREQ(reg, "pc")) + { + remember(RememberReg, reg, cpu_get_PC()); + if (cpu_get_PC() != val) + { + vlog("PC is %07o, should be %07o", cpu_get_PC(), val); + printf("PC is %07o, should be %07o\n", cpu_get_PC(), val); + return 1; + } + } + else if (STREQ(reg, "ds")) + { + remember(RememberReg, reg, cpu_get_DS()); + if (cpu_get_DS() != val) + { + vlog("DS is %07o, should be %07o", cpu_get_DS(), val); + printf("DS is %07o, should be %07o\n", cpu_get_DS(), val); + return 1; + } + } + else + { + vlog("checkreg: bad register name: %s", reg); + printf("checkreg: bad register name: %s\n", reg); + return 1; + } + + return 0; +} /****************************************************************************** -Description : Run one test. +Description : Check that the display is in the correct state. + Parameters : state - string holding expected display state ('on' or 'off) + : unused - unused + Returns : The number of errors encountered (0 or 1). + Comments : + ******************************************************************************/ +int +checkd(char *state, char *unused) +{ + if ((STREQ(state, "on")) && !DisplayOn) + { + vlog("Display CPU run state is %s, should be 'ON'", + (DisplayOn ? "ON": "OFF")); + printf("Display CPU run state is %s, should be 'ON'\n", + (DisplayOn ? "ON": "OFF")); + return 1; + } + else if ((STREQ(state, "off")) && DisplayOn) + { + vlog("DCPU run state is %s, should be 'OFF'", + (DisplayOn ? "ON": "OFF")); + printf("DCPU run state is %s, should be 'OFF'\n", + (DisplayOn ? "ON": "OFF")); + return 1; + } + else + { + vlog("checkd: state should be 'on' or 'OFF', got %s", state); + printf("checkd: state should be 'on' or 'off', got %s\n", state); + return 1; + } + + return 0; +} + + +/****************************************************************************** +Description : Check that a memory address contents is as expected. + Parameters : address - memory address to check (string) + : value - expected memory value (string) + Returns : The number of errors encountered (0 or 1). + Comments : + ******************************************************************************/ +int +checkmem(char *address, char *value) +{ + WORD adr = str2word(address); + WORD val = str2word(value); + WORD memvalue = mem_get(adr, false); + + if (memvalue != val) + { + vlog("Memory at address %07o is %07o, should be %07o", + adr, memvalue, val); + printf("Memory at address %07o is %07o, should be %07o\n", + adr, memvalue, val); + return 1; + } + + return 0; +} + + +/****************************************************************************** +Description : Check that the CPU run state is as expected. + Parameters : state - the expected CPU state (string, 'ON' or 'OFF') + : unused - unused + Returns : The number of errors encountered (0 or 1). + Comments : + ******************************************************************************/ +int +checkrun(char *state, char *unused) +{ + + if (STREQ(state, "on")) + { + vlog("CPU run state is '%s', should be '%s'", + (cpu_get_state() ? "on": "off"), state); + printf("CPU run state is '%s', should be '%s'\n", + (cpu_get_state() ? "on": "off"), state); + return 1; + } + else if (STREQ(state, "off")) + { + vlog("CPU run state is '%s', should be '%s'", + (cpu_get_state() ? "on": "off"), state); + printf("CPU run state is '%s', should be '%s'\n", + (cpu_get_state() ? "on": "off"), state); + return 1; + } + else + { + vlog("checkrun: state should be 'on' or 'off', got '%s'", state); + printf("checkrun: state should be 'on' or 'off', got '%s'\n", state); + return 1; + } + + return 0; +} + + +/****************************************************************************** +Description : Run all commands in one test line. Parameters : test - pointer to a Test struct Returns : The number of errors encountered (0 or 1). Comments : @@ -625,6 +863,7 @@ int run_one_test(Test *test) { int error = 0; + char buffer[256]; for (Command *cmd = test->commands; cmd; cmd = cmd->next) { @@ -632,27 +871,34 @@ run_one_test(Test *test) char *fld1 = cmd->field1; char *fld2 = cmd->field2; - if (strcmp(opcode, "setreg"), 0) + if (fld2) + sprintf(buffer, "%s %s %07o%s", + opcode, fld1, atoi(fld2), (cmd->orig2) ? cmd->orig2 : ""); + else + sprintf(buffer, "%s %s", opcode, fld1); + LogPrefix = new_String(buffer); + + if (STREQ(opcode, "setreg")) error += setreg(fld1, fld2); - else if (strcmp(opcode, "setmem") == 0) + else if (STREQ(opcode, "setmem")) error += setmem(fld1, fld2); - else if (strcmp(opcode, "run") == 0) + else if (STREQ(opcode, "run")) error += run_one(fld1, fld2); - else if (strcmp(opcode, "checkcycles") == 0) + else if (STREQ(opcode, "checkcycles")) error += checkcycles(fld1, fld2); - else if (strcmp(opcode, "checkreg") == 0) + else if (STREQ(opcode, "checkreg")) error += checkreg(fld1, fld2); - else if (strcmp(opcode, "checkmem") == 0) + else if (STREQ(opcode, "checkmem")) error += checkmem(fld1, fld2); - else if (strcmp(opcode, "allreg") == 0) + else if (STREQ(opcode, "allreg")) error += allreg(fld1, fld2); - else if (strcmp(opcode, "allmem") == 0) + else if (STREQ(opcode, "allmem")) error += allmem(fld1, fld2); - else if (strcmp(opcode, "checkrun") == 0) + else if (STREQ(opcode, "checkrun")) error += checkrun(fld1, fld2); - else if (strcmp(opcode, "setd") == 0) + else if (STREQ(opcode, "setd")) error += setd(fld1, fld2); - else if (strcmp(opcode, "checkd") == 0) + else if (STREQ(opcode, "checkd")) error += checkd(fld1, fld2); else { @@ -676,14 +922,44 @@ int run(Test *test) { int errors = 0; + char buffer[1024]; while (test) { - printf("Test from line %d, test->next=%p\n", test->line_number, test->next); - fflush(stdout); + sprintf(buffer, "%03d", test->line_number); + LogPrefix = new_String(buffer); + strcpy(buffer, ""); + + printf("%03d:", test->line_number); + + for (Command *cscan = test->commands; cscan != NULL; cscan = cscan->next) + { + if (cscan->field2) + { + printf(" %s %s %07o%s;", + cscan->opcode, cscan->field1, atoi(cscan->field2), (cscan->orig2) ? cscan->orig2 : ""); + sprintf(buffer+strlen(buffer), " %s %s %07o%s;", + cscan->opcode, cscan->field1, atoi(cscan->field2), (cscan->orig2) ? cscan->orig2 : ""); + } + else + { + if (cscan->field1) + { + printf(" %s %s;", cscan->opcode, cscan->field1); + sprintf(buffer+strlen(buffer), " %s %s;", cscan->opcode, cscan->field1); + } + else + { + printf(" %s;", cscan->opcode); + sprintf(buffer+strlen(buffer), " %s;", cscan->opcode); + } + } + } + + vlog(buffer+1); + printf("\n"); errors += run_one_test(test); - test = test->next; } @@ -705,7 +981,7 @@ execute(char *script) // get test commands into massaged form in memory test = parse_script(script); -//#ifdef DEBUG +#ifdef DEBUG // DEBUG - print contents of 'test' for (Test *tscan = test; tscan != NULL; tscan = tscan->next) { @@ -717,7 +993,7 @@ execute(char *script) printf("\n"); fflush(stdout); } -//#endif +#endif // execute tests return run(test); @@ -763,360 +1039,6 @@ main(int argc, char *argv[]) printf("%d errors found\n", errors); - return 0; + return errors; } - -#ifdef JUNK - def allmem(self, value, ignore=None): - """Set all of memory to a value. - - Remember value to check later. - """ - - log.debug('allmem: setting memory to %07o' % value) - - self.mem_all_value = value - - for mem in range(MEMORY_SIZE): - self.memory.put(value, mem, False) - - def allreg(self, value): - """Set all registers to a value.""" - - self.reg_all_value = value - - self.cpu.AC = value - self.cpu.L = value & 1 - self.cpu.PC = value - self.cpu.DS = value - - def check_all_mem(self): - """Check memory for unwanted changes.""" - - result = [] - - for mem in range(MEMORY_SIZE): - value = self.memory.fetch(mem, False) - if mem in self.mem_values: - if value != self.mem_values[mem]: - result.append('Memory at %07o changed, is %07o, should be %07o' - % (mem, value, self.mem_values[mem])) - else: - if value != self.mem_all_value: - print('mem: %s, value: %s, self.mem_all_value: %s' - % (str(type(mem)), str(type(value)), str(type(self.mem_all_value)))) - result.append('Memory at %07o changed, is %07o, should be %07o' - % (mem, value, self.mem_all_value)) - - def check_all_regs(self): - """Check registers for unwanted changes.""" - - result = [] - - if 'ac' in self.reg_values: - if self.cpu.AC != self.reg_values['ac']: - result.append('AC changed, is %07o, should be %07o' - % (self.cpu.AC, self.reg_values['ac'])) - else: - if self.cpu.AC != self.reg_all_value: - result.append('AC changed, is %07o, should be %07o' - % (self.cpu.AC, self.reg_all_value)) - - if 'l' in self.reg_values: - if self.cpu.L != self.reg_values['l']: - result.append('L changed, is %02o, should be %02o' - % (self.cpu.L, self.reg_values['l'])) - else: - if self.cpu.L != self.reg_all_value & 1: - result.append('L changed, is %02o, should be %02o' - % (self.cpu.L, self.reg_all_value & 1)) - - if 'pc' in self.reg_values: - if self.cpu.PC != self.reg_values['pc']: - result.append('PC changed, is %07o, should be %07o' - % (self.cpu.PC, self.reg_values['pc'])) - else: - if self.cpu.PC != self.reg_all_value: - result.append('PC changed, is %07o, should be %07o' - % (self.cpu.PC, self.reg_all_value)) - - if 'ds' in self.reg_values: - if self.cpu.DS != self.reg_values['ds']: - result.append('DS changed, is %07o, should be %07o' - % (self.cpu.DS, self.reg_values['ds'])) - else: - if self.cpu.DS != self.reg_all_value: - result.append('DS changed, is %07o, should be %07o' - % (self.cpu.DS, self.reg_all_value)) - - return result - - def checkreg(self, reg, value): - """Check register is as it should be.""" - - if reg == 'ac': - self.reg_values[reg] = self.cpu.AC - if self.cpu.AC != value: - return 'AC wrong, is %07o, should be %07o' % (self.cpu.AC, value) - elif reg == 'l': - self.reg_values[reg] = self.cpu.L - if self.cpu.L != value: - return 'L wrong, is %02o, should be %02o' % (self.cpu.L, value) - elif reg == 'pc': - self.reg_values[reg] = self.cpu.PC - if self.cpu.PC != value: - return 'PC wrong, is %07o, should be %07o' % (self.cpu.PC, value) - elif reg == 'ds': - self.reg_values[reg] = self.cpu.DS - if self.cpu.DS != value: - return 'DS wrong, is %07o, should be %07o' % (self.cpu.DS, value) - else: - raise Exception('checkreg: bad register name: %s' % name) - - def checkmem(self, addr, value): - """Check a memory location is as it should be.""" - - self.mem_values[addr] = value - log.debug('checkmem: After, MemValues=%s' % str(self.mem_values)) - - memvalue = self.memory.fetch(addr, False) - if memvalue != value: - return 'Memory wrong at address %07o, is %07o, should be %07o' % (addr, memvalue, value) - - def checkcycles(self, cycles, var2=None): - """Check that opcode cycles used is correct.""" - - if cycles != self.used_cycles: - return 'Opcode used %d cycles, expected %d' % (self.used_cycles, cycles) - - def run(self, addr, var2): - """Execute instruction.""" - - if addr is not None: - # force PC to given address - self.setreg('pc', addr) - - self.used_cycles = self.cpu.execute_one_instruction() - - def checkrun(self, state, var2): - """Check CPU run state is as desired.""" - - if str(self.cpu.running).lower() != state: - return 'CPU run state is %s, should be %s' % (str(self.cpu.running), str(state)) - - def setd(self, state, var2): - """Set display state.""" - - if state == 'on': - self.display_state = True - elif state == 'off': - self.display_state = False - else: - raise Exception('setd: bad state: %s' % str(state)) - - def checkd(self, state, var2): - """Check display state is as expected.""" - - if state == 'on' and self.display_state is not True: - return 'DCPU run state is %s, should be True' % str(self.display_state) - if state == 'off' and self.display_state is True: - return 'DCPU run state is %s, should be False' % str(self.display_state) - - def debug_operation(self, op, var1, var2): - """Write operation to log file.""" - - if var1: - if var2: - log.debug('Operation: %s %s %s' % (op, var1, var2)) - else: - log.debug('Operation: %s %s' % (op, var1)) - else: - log.debug('Operation: %s' % op) - - def execute(self, test, filename): - """Execute test string in 'test'.""" - - # set globals - self.reg_values = {} - self.mem_values = {} - self.reg_all_value = 0 - self.mem_all_value = 0 - - result = [] - - self.memory = Memory.Memory() - self.cpu = MainCPU.MainCPU(self.memory, None, None, None, None, None, None, None) - self.cpu.running = True - self.display_state = False - - trace_filename = filename + '.trace' - Trace.init(trace_filename, self.cpu, None) - - # clear registers to 0 first - self.allreg(0) - - # interpret the test instructions - instructions = test.split(';') - for op in instructions: - fields = op.split(None, 2) - op = fields[0].lower() - try: - var1 = fields[1].lower() - except IndexError: - var1 = None - try: - var2 = fields[2].lower() - except IndexError: - var2 = None - - self.debug_operation(op, var1, var2) - - # change var strings into numeric values - if var1 and var1[0] in '0123456789': - if var1[0] == '0': - var1 = int(var1, base=8) - else: - var1 = int(var1) - var1 &= 0177777 - - if var2 and var2[0] in '0123456789': - if var2[0] == '0': - var2 = int(var2, base=8) - else: - var2 = int(var2) - var2 &= 0177777 - - if op == 'setreg': - r = self.setreg(var1, var2) - elif op == 'setmem': - r = self.setmem(var1, var2) - elif op == 'run': - r = self.run(var1, var2) - elif op == 'checkcycles': - r = self.checkcycles(var1, var2) - elif op == 'checkreg': - r = self.checkreg(var1, var2) - elif op == 'checkmem': - r = self.checkmem(var1, var2) - elif op == 'allreg': - r = self.allreg(var1, var2) - elif op == 'allmem': - r = self.allmem(var1, var2) - elif op == 'checkrun': - r = self.checkrun(var1, var2) - elif op == 'setd': - r = self.setd(var1, var2) - elif op == 'checkd': - r = self.checkd(var1, var2) - else: - raise Exception("Unrecognized operation '%s' in: %s" % (op, test)) - - if r is not None: - result.append(r) - - # now check all memory and regs for changes - r = self.check_all_mem() - if r: - result.append(r) - - r = self.check_all_regs() - if r: - result.extend(r) - - if result: - print(test) - print('\t' + '\n\t'.join(result)) - - self.memdump('core.txt', 0, 0200) - - def memdump(self, filename, start, number): - """Dump memory from 'start' into 'filename', 'number' words dumped.""" - - with open(filename, 'wb') as fd: - for addr in range(start, start+number, 8): - a = addr - llen = min(8, start+number - addr) - line = '%04o ' % addr - for _ in range(llen): - line += '%06o ' % self.memory.fetch(a, False) - a += 1 - fd.write('%s\n' % line) - - def main(self, filename): - """Execute CPU tests from 'filename'.""" - - log.debug("Running test file '%s'" % filename) - - # get all tests from file - with open(filename, 'rb') as fd: - lines = fd.readlines() - - # read lines, join continued, get complete tests - tests = [] - test = '' - for line in lines: - line = line[:-1] # strip newline - if not line: - continue # skip blank lines - - if line[0] == '#': # a comment - continue - - if line[0] == '\t': # continuation - if test: - test += '; ' - test += line[1:] - else: # beginning of new test - if test: - tests.append(test) - test = line - - # flush last test - if test: - tests.append(test) - - # now do each test - for test in tests: - log.debug('Executing test: %s' % test) - self.execute(test, filename) - -################################################################################ - -if __name__ == '__main__': - import sys - import getopt - - def usage(msg=None): - if msg: - print('*'*60) - print(msg) - print('*'*60) - print(__doc__) - - try: - (opts, args) = getopt.gnu_getopt(sys.argv, "h", ["help"]) - except getopt.GetoptError: - usage() - sys.exit(10) - - for opt, arg in opts: - if opt in ("-h", "--help"): - usage() - sys.exit(0) - - if len(args) != 2: - usage() - sys.exit(10) - - filename = args[1] - try: - f = open(filename) - except IOError: - print("Sorry, can't find file '%s'" % filename) - sys.exit(10) - f.close() - - test = TestCPU() - test.main(filename) -#endif