starting to add timing to vm driver
[dcpu16] / vm-dcpu16.c
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;