Trimmed down NEDsim to a single CPU, single thread, 64MB RAM, 64k element stack,...
authorAaron Taylor <ataylor@subgeniuskitty.com>
Fri, 9 Jul 2021 00:18:01 +0000 (17:18 -0700)
committerAaron Taylor <ataylor@subgeniuskitty.com>
Fri, 9 Jul 2021 00:18:01 +0000 (17:18 -0700)
hacks/NEDsim/NEDsim.c
hacks/NEDsim/simulator.c
hacks/NEDsim/simulator.h

index 2b576f0..73c72f9 100644 (file)
@@ -677,8 +677,16 @@ NEDsim_event(Display * dpy, Window win, void * closure, XEvent * event)
 static void
 NEDsim_free(Display * dpy, Window win, void * closure)
 {
-    // TODO: Replace all this with proper code to free everything.
     struct NEDsim * nedsim = closure;
+
+    if (nedsim->nedstate != NULL) {
+        free(nedsim->nedstate->active_thread->psw);
+        free(nedsim->nedstate->active_thread);
+        free(nedsim->nedstate->hack);
+        free(nedsim->nedstate);
+    }
+
+    // TODO: Replace all this with proper code to free everything related to the screensaver itself.
     XFreeGC(nedsim->dpy, nedsim->gc);
     free(nedsim);
 }
index 4857946..f5c56ee 100644 (file)
 #include "a.out.h"
 #include "simulator.h"
 
-int
-is_stdin_nonempty(void)
-{
-    fd_set read_fds;
-    FD_ZERO(&read_fds);
-    FD_SET(STDIN_FILENO, &read_fds);
-
-    struct timeval timeout;
-    timeout.tv_sec = 0;
-    timeout.tv_usec = 0;
-
-    int retval = select(1, &read_fds, NULL, NULL, &timeout);
-
-    if (retval == -1) {
-        /* TODO: How do I want to handle this error? */
-    }
-
-    return retval;
-}
-
 uint32_t
 generate_binary_psw(struct NEDstate * state)
 {
@@ -59,29 +39,21 @@ generate_binary_psw(struct NEDstate * state)
 void
 ram_w_byte(struct NEDstate * state, uint32_t address, uint8_t data)
 {
-    state->ram[address] = data;
+    state->ram[address-RAM_BASE_ADDRESS] = data;
 }
 
 uint8_t
 ram_r_byte(struct NEDstate * state, uint32_t address)
 {
-    return state->ram[address];
+    return state->ram[address-RAM_BASE_ADDRESS];
 }
 
 /* For now, with only a terminal for IO, we pick off IO requests when accessing RAM. */
-/* TODO: Improve this before adding any other IO devices like disks. */
 
 void
 ram_w_word(struct NEDstate * state, uint32_t address, uint32_t data)
 {
-    /* TODO: Since PC and PSW are memory mapped, they should accept writes. */
-    /*       Should writes to the PC automatically reset the syllable counter? */
-    if (address == 0x8000000) { /* SLU: XBUF */
-        printf("%c", data);
-        fflush(stdout);
-    } else if (address == 0x0 || address == 0x4) {
-        /* Intentionally empty */
-    } else if (address >= 0x20000000) {
+    if (address >= RAM_BASE_ADDRESS) {
         for (int i=3; i>=0; i--) {
             uint8_t tmp_byte = ((data >> (8*(3-i))) & 0xff);
             ram_w_byte(state,address+i,tmp_byte);
@@ -100,23 +72,7 @@ ram_r_word(struct NEDstate * state, uint32_t address)
         return state->active_thread->pc;
     } else if (address == 0xC) {        /* PSW register */
         return generate_binary_psw(state);
-    } else if (address == 0x8000004) {  /* SLU: XCSR */
-        /* TODO: Should I artificially restrict printing in the simulator? */
-        /*       It might help catch bugs like the GCC bug that slipped past SIMH. */
-        return 0b1;
-    } else if (address == 0x8000008) {  /* SLU: RBUF */
-        if (is_stdin_nonempty()) {
-            return getchar();
-        } else {
-            return (uint8_t)rand();
-        }
-    } else if (address == 0x800000C) {  /* SLU: RCSR */
-        if (is_stdin_nonempty()) {
-            return 0b1;
-        } else {
-            return 0b0;
-        }
-    } else if (address >= 0x20000000) { /* RAM */
+    } else if (address >= RAM_BASE_ADDRESS) { /* RAM */
         uint32_t word = 0;
         for (int i=0; i<4; i++) word |= (ram_r_byte(state,address+i)) << (8*(3-i));
         return word;
@@ -214,18 +170,6 @@ ned_instruction_add(struct NEDstate * state)
     set_psw_flags(stack_r(state->active_thread,0), state);
 }
 
-void
-ned_instruction_mvstck(struct NEDstate * state)
-{
-    uint32_t new_id = stack_pop(state->active_thread);
-    if (new_id < THREAD_COUNT) {
-        state->active_thread = state->thread[new_id];
-    } else {
-        printf("ERROR: Attempted MVSTCK to ID higher than THREAD_COUNT.\n");
-        state->halted = true;
-    }
-}
-
 void
 ned_instruction_shift(struct NEDstate * state)
 {
@@ -319,9 +263,9 @@ execute_syllable(struct NEDstate * state, enum syllables syllable)
             case NOT:       ned_instruction_not(state);     break;
             case XOR:       ned_instruction_xor(state);     break;
             case ADD:       ned_instruction_add(state);     break;
-            case MVSTCK:    ned_instruction_mvstck(state);  break;
+            case MVSTCK:    /* Intentionally blank */       break;
             case SHIFT:     ned_instruction_shift(state);   break;
-            case CMPSWP:    /* TODO */                      break;
+            case CMPSWP:    /* Intentionally blank */       break;
             case TEST:      ned_instruction_test(state);    break;
             case JMP:       ned_instruction_jmp(state);     break;
             case SWAP:      ned_instruction_swap(state);    break;
@@ -439,17 +383,15 @@ init_simulator(void)
 {
     struct NEDstate * state = malloc(sizeof(struct NEDstate));
     state->hack = malloc(sizeof(struct NEDhack));
-    for (size_t i=0; i < THREAD_COUNT; i++) {
-        state->thread[i] = malloc(sizeof(struct NEDthread));
-        state->thread[i]->psw = malloc(sizeof(struct NEDpsw));
-    }
+    state->thread[0] = malloc(sizeof(struct NEDthread));
+    state->thread[0]->psw = malloc(sizeof(struct NEDpsw));
     state->thread[0]->pc = 0;
     state->thread[0]->sc = 0;
     state->thread[0]->sp = 0;
     state->thread[0]->psw->zero = false;
     state->thread[0]->psw->negative = false;
-    state->thread[0]->pc = 0x20000000;  /* Data region starts 512 MB into address space. */
-    state->active_thread = state->thread[0];  /* By convention, use thread 0 for init. */
+    state->thread[0]->pc = RAM_BASE_ADDRESS;
+    state->active_thread = state->thread[0];
     state->halted = false;
     state->hack->resume_word = false;
 
@@ -457,7 +399,6 @@ init_simulator(void)
 #define AOUT_PATH "./test.out"
 
     /* Load an initial image into memory. */
-    uint32_t address = 0x20000000;
     struct exec aout_exec;
     struct nlist * symbol_table;
     uint32_t symbol_count;
@@ -466,8 +407,12 @@ init_simulator(void)
         fprintf(stderr, "ERROR: %s: %s\n", AOUT_PATH, strerror(errno));
         state->halted = true;
     }
-    parse_aout_file(input, &aout_exec, &(state->ram[address]), &symbol_table, &symbol_count);
+    parse_aout_file(input, &aout_exec, state->ram, &symbol_table, &symbol_count);
     fclose(input);
+    for (size_t i=0; i < symbol_count; i++) {
+        free(symbol_table[i].n_un.n_name);
+    }
+    free(symbol_table);
 
     return state;
 }
index 927f73b..971e76c 100644 (file)
 
 #include "./a.out.h"
 
-// TODO: Can get rid of this since I don't do a show_usage() anymore?
-#define VERSION 5
-
 /* Bytes per word. */
 #define BPW 4
 
 /* Number of stack words. */
-#define STACK_LENGTH 1048576
+#define STACK_LENGTH 65536
 
 /* Number of bytes of RAM. */
-#define RAM_LENGTH 1073741824
-
-/* Number of hardware threads. */
-#define THREAD_COUNT 8
+#define RAM_LENGTH 67108864
+#define RAM_BASE_ADDRESS 0x20000000
 
 /* Number of syllables per word. */
 #define SPW 5
@@ -58,11 +53,11 @@ struct NEDhack {
     bool resume_word;
 };
 
-// TODO: Make this a single thread before committing. Multi-thread is broken with my current main loop.
 struct NEDstate {
     bool halted;
     uint8_t ram[RAM_LENGTH];
-    struct NEDthread * thread[THREAD_COUNT];
+    /* Although NED is multi-threaded, this screensaver is restricted to a single thread. */
+    struct NEDthread * thread[1];
     struct NEDthread * active_thread;
     struct NEDhack * hack;
 };