starting to add timing to vm driver
authorJustin Wind <justin.wind@gmail.com>
Sun, 13 May 2012 16:40:54 +0000 (09:40 -0700)
committerJustin Wind <justin.wind@gmail.com>
Sun, 13 May 2012 16:40:54 +0000 (09:40 -0700)
not quite there yet, but starting to get it running at 'real time' speed, rather than as fast as possible

as-dcpu16.c
common.c
common.h
hw_lem1802.c
tests/test.dasm [moved from tests/test.s with 100% similarity]
tests/test_lem1802.dasm
vm-dcpu16.c

index 73b2fa37a662dc4c4a2dbd9219dc01706a98ac6d..37954aaf20b76fce9bb5410485c507f3e531f3fe 100644 (file)
@@ -538,8 +538,7 @@ int value_bits_(struct dynamic_array *labels, const char *operand_orig, DCPU16_W
             *nextwordused += 1;
             return 0x1e;
         } else if (errno) {
-            DEBUG_PRINTFQ("is out of range\n");
-            fprintf(stderr, "trouble with operand '%s': %s\n", operand_orig, strerror(errno));
+            /* if number wasn't parsable, just fall through and assume it's a label */
         }
 
         /* not a number? try a label */
@@ -1065,7 +1064,7 @@ int assemble_check_(struct dynamic_array *instructionps, struct dynamic_array *l
             return retval;
         }
         if (! (*instrp)->ready) {
-            fprintf(stderr, "instruction not resolvable\n");
+            fprintf(stderr, "instruction not resolvable at line %lu\n", (*instrp)->src_line);
             return -1;
         }
     }
index ce1b6c0305aa3b86b4754fdf7da5c46134dc09ad..5887c224815c43c4daadaa1eae0ce2656bb2b88e 100644 (file)
--- a/common.c
+++ b/common.c
@@ -204,3 +204,25 @@ char *strqtok_r(char *str, const char *sep, int esc, const char *quote, char **l
 
     return tok;
 }
+
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) {
+  /* Perform the carry for the later subtraction by updating y. */
+  if (x->tv_usec < y->tv_usec) {
+    int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
+    y->tv_usec -= 1000000 * nsec;
+    y->tv_sec += nsec;
+  }
+  if (x->tv_usec - y->tv_usec > 1000000) {
+    int nsec = (x->tv_usec - y->tv_usec) / 1000000;
+    y->tv_usec += 1000000 * nsec;
+    y->tv_sec -= nsec;
+  }
+
+  /* Compute the time remaining to wait.
+     tv_usec is certainly positive. */
+  result->tv_sec = x->tv_sec - y->tv_sec;
+  result->tv_usec = x->tv_usec - y->tv_usec;
+
+  /* Return 1 if result is negative. */
+  return x->tv_sec < y->tv_sec;
+}
index 80ed333868f780f0a77156a6041d3f6274329004..02db4d77fdc131f63166d63d9cdb5d0ecca7d73c 100644 (file)
--- a/common.h
+++ b/common.h
@@ -21,4 +21,6 @@ int str_to_word(char *s);
 
 char *strqtok_r(char *str, const char *sep, int esc, const char *quote, char **lastq, char **lasts);
 
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y);
+
 #endif /* COMMON_H_QPRCB1BH */
index ae0c9dd3ae9b21eede8c12c01c8bd778dd8756cc..92e5149c64d5be7b42489b4f9a371222949b1b5f 100644 (file)
@@ -17,6 +17,7 @@
 #include "chargen-4x8.h"
 #include "hw_lem1802.h"
 
+#undef DEBUG
 #ifdef DEBUG
 #define TRACE(...) do { printf("[debug] "); printf(__VA_ARGS__); printf("\n"); } while (0)
 #else /* DEBUG  */
@@ -526,7 +527,7 @@ struct dcpu16_hw *lem1802_new(struct dcpu16 *vm) {
     }
 
     ((struct lem1802_ *)(hw->data))->refresh_rate = 1666;
-    ((struct lem1802_ *)(hw->data))->blink_rate = 75000;
+    ((struct lem1802_ *)(hw->data))->blink_rate = 100000;
 
     return hw;
 }
similarity index 100%
rename from tests/test.s
rename to tests/test.dasm
index 898808b10566484a10459c203362c980cd001c2a..c25858ff88ba9b7c4d7d8c8107452095b9474bba 100644 (file)
@@ -15,23 +15,33 @@ HWN [num]
     HWI [num]
 
     ; set border
-    SET B, 0x0003
+    SET B, 0x0002
     SET A, 3
     HWI [num]
 
     ; show some text
-    SET I, string
+    SET I, string1
     SET J, 0x8000
-    ; color
     SET Z, 0x1e00
-:print
-    BOR [i], Z
-    STI [j], [i]
-    IFN [I], 0
-        SET PC, print
+    JSR print
+
+    SET I, string2
+    SET Z, 0x1e80
+    JSR print
 
-:wait
-    SET PC, wait
+:done
+    SET PC, done
+
+; prints string at I to vram at J in color Z
+:print  XOR [I], Z
+        SET [J], [I]
+        XOR [I], Z
+        ADD I, 1
+        ADD J, 1
+        IFE [I], 0
+            SET PC, POP
+        SET PC, print
 
 :num dat 0x0000
-:string dat "yerf!", 0
\ No newline at end of file
+:string1 dat "yerf!", 0
+:string2 dat "ortort?", 0
\ No newline at end of file
index 6324717f0b28f9e23d1f879abe6b568fa353cd8f..367cdbc2669f81008edd4443fa4e4e39df751417 100644 (file)
@@ -7,6 +7,8 @@
 #include <errno.h>
 #include <assert.h>
 #include <sysexits.h>
+#include <time.h>
+#include <sys/time.h>
 
 #include <readline/readline.h>
 
@@ -371,11 +373,20 @@ COMMAND_HELP(set) {
     fprintf(f, "Sets addr to value.");
 }
 
+#define MICROSECONDS_PER_CYCLE 10
 COMMAND_IMPL(run) {
     struct sigaction act;
+    struct timeval run_start_tv, run_stop_tv;
+    long long run_cycle_start;
+    struct timeval start_tv, now_tv, diff_tv;
+    long long cycle_start, cycles_to_wait;
+    struct timespec sleep_time;
+
     (void)arg_count, (void)arg_vector;
 
     running_ = 1;
+    gettimeofday(&run_start_tv, NULL);
+    run_cycle_start = vm->cycle;
 
     memset(&act, 0, sizeof act);
     act.sa_handler = sigint_handler_;
@@ -387,6 +398,9 @@ COMMAND_IMPL(run) {
     }
 
     while(running_) {
+        gettimeofday(&start_tv, NULL);
+        cycle_start = vm->cycle;
+
         dcpu16_step(vm);
         if (opt_.verbose > 1)
             dcpu16_state_print(vm);
@@ -394,8 +408,36 @@ COMMAND_IMPL(run) {
             dcpu16_disassemble_print(vm, vm->reg[DCPU16_REG_PC]);
             printf("\n");
         }
+
+        /* how many cycles did this instr use? */
+        cycles_to_wait = vm->cycle - cycle_start;
+
+        if (cycles_to_wait == 0)
+            continue;
+
+        /* each cycle wants 10 microseconds */
+        
+
+        /* how much of that did we spend already */
+        gettimeofday(&now_tv, NULL);
+        timeval_subtract(&diff_tv, &now_tv, &start_tv);
+        /* do we have time to kill? */
+        if (cycles_to_wait * MICROSECONDS_PER_CYCLE > diff_tv.tv_usec) {
+            sleep_time.tv_sec = diff_tv.tv_sec;
+            sleep_time.tv_nsec = 1000 * ( (cycles_to_wait * MICROSECONDS_PER_CYCLE) - diff_tv.tv_usec);
+            sleep_time.tv_nsec = diff_tv.tv_usec * 1000;
+
+            nanosleep(&sleep_time, NULL);
+        }
     }
 
+    gettimeofday(&run_stop_tv, NULL);
+    timeval_subtract(&diff_tv, &run_stop_tv, &run_start_tv);
+    fprintf(stderr, "ran %llu cycles in %lds %dus\n",
+            vm->cycle - run_cycle_start,
+            diff_tv.tv_sec,
+            diff_tv.tv_usec);
+
     printf("interrupted...\n");
 
     return 0;