chiark / gitweb /
multiple cache det compression
authorian <ian>
Sat, 24 May 2008 12:30:18 +0000 (12:30 +0000)
committerian <ian>
Sat, 24 May 2008 12:30:18 +0000 (12:30 +0000)
hostside/realtime.h
hostside/simulate.c

index be9ed9047fa896d7912db9aefa3feceef6320884..5d844c7e45612605efa5aec5f8ff42b4c219bae5 100644 (file)
@@ -14,6 +14,7 @@
 #include <errno.h>
 #include <assert.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <limits.h>
 #include <stddef.h>
 #include <ctype.h>
index 0f5f9b582dc5a9a3bd517228be075a1a2490e7c7..9126994c7c33a7f703d71f1712270b40339d4839 100644 (file)
@@ -15,17 +15,20 @@ typedef void SimEventFn(void);
 int simlog_full;
 const char *simulate;
 
-static SimEventFn se_timestamp, se_timerevent;
-static SimEventFn se_serial, se_samedet, se_command, se_eof;
+static SimEventFn se_timestamp, se_timerevent, se_command;
+static SimEventFn se_serial, se_serial_detcompr, se_samedet, se_eof;
 
 static SimTimeout *simtimeouts;
 
+#define DETSAVESLN2 4
+#define DETSAVES (1<<DETSAVESLN2) /* encoded in letters so must be <=26 ! */
+
 static FILE *simoutput;
 static FILE *siminput;
 static char *sevent_buf;
 static size_t sevent_buflen;
 static int sevent_lno;
-static Byte sevent_lastdet[2];
+static Byte sevent_lastdet[DETSAVES][2];
 
 static SimEventFn *sevent_type;
 static char *sevent_data;
@@ -35,12 +38,12 @@ static struct timeval sevent_abst;
 
 /*---------- writing simulation log ----------*/
 
-static Byte simlog_lastdet[2];
+static Byte simlog_lastdet[DETSAVES][2];
+static uint32_t simlog_detcompr_lcongx;
 
 void simlogv(const char *fmt, va_list al) {
   if (simoutput==stdout) ovprintf(UPO,fmt,al);
   else if (simoutput) vfprintf(simoutput,fmt,al);
-  simlog_lastdet[0]= 0;
 }
 void simlog(const char *fmt, ...) {
   va_list al;
@@ -54,6 +57,7 @@ void simlog_flush(void) {
     if (ferror(simoutput) || fflush(simoutput))
       diee("write simulation log");
 }
+
 void simlog_serial(const Byte *data, int length) {
   static Byte db0, db1;
   int is_det;
@@ -62,27 +66,29 @@ void simlog_serial(const Byte *data, int length) {
 
   db0= data[0] & ~PICMSG_DETECT_01;
 
-  /* optimise consecutive dithering detects into just 0 and 1 msgs */
   is_det= PICMSG_DETECT0_P(db0) && length==2 && !((db1=data[1]) & 0x80);
   if (is_det) {
-    if (db0==simlog_lastdet[0] && data[1]==simlog_lastdet[1]) {
-      simlog("%d\n",!!(data[0] & PICMSG_DETECT_01));
-      goto set_lastdet;
-    }
-    simlog("picioh in suppressed-detect");
+    int i;
+    for (i=0; i<DETSAVES; i++)
+      if (simlog_lastdet[i][0]==db0 && simlog_lastdet[i][1]==db1) {
+       simlog("%c\n", ((data[0] & PICMSG_DETECT_01) ? 'A' : 'a') + i);
+       simlog_flush();
+       return;
+      }
+    /* not found, choose a slot to replace */
+    simlog_detcompr_lcongx += 5;     /* WP Linear_congruential_generator */
+    simlog_detcompr_lcongx *= 69069; /* values are those also used by GCC */
+    i= (simlog_detcompr_lcongx >> (30 - DETSAVESLN2)) &
+       ((1UL << DETSAVESLN2)-1);
+    simlog_lastdet[i][0]= db0;
+    simlog_lastdet[i][1]= db1;
+    simlog("picioh in detcompr%c", 'A' + i);
   } else {
     simlog("picioh in suppressed");
   }
-
   while (length--) simlog(" %02x",*data++);
   simlog("\n");
   simlog_flush();
-
- set_lastdet:
-  if (is_det) {
-    simlog_lastdet[0]= db0;
-    simlog_lastdet[1]= db1;
-  }
 }
 void simlog_open(const char *fn) {
   if (!fn) fn= "+realtime.log";
@@ -119,31 +125,35 @@ static void sevent(void) {
     assert(sevent_buf[gr-1]=='\n');
     sevent_buf[gr-1]= 0;
 
-    if ((sevent_buf[0] & ~1)=='0' && !sevent_buf[1]) {
+    if (gr==2 && CTYPE(isalpha,sevent_buf[0])) {
       sevent_type= se_samedet;
       sevent_data= &sevent_buf[0];
       return;
     }
 
 #define IF_ET(pfx, et)                                                 \
-    if (!strncmp(pfx " ", sevent_buf, sizeof(pfx))                     \
-       && (sevent_type=(et), p=sevent_buf+(sizeof(pfx))))
+    if (!strncmp(pfx, sevent_buf, sizeof(pfx)-1)                       \
+       && (sevent_type=(et), p=sevent_buf+sizeof(pfx)-1))
 
-    IF_ET("command-in", se_command) {
+    IF_ET("command-in ", se_command) {
       sevent_data= p;
       return;
     }
-    IF_ET("picioh in", se_serial) {
+    IF_ET("picioh in detcompr", se_serial_detcompr) {
+      sevent_data= p;
+      return;
+    }
+    IF_ET("picioh in ", se_serial) {
       p= strchr(p,' ');
       if (!p) simbad("missing space after `in'");
       sevent_data= p+1;
       return;
     }
-    IF_ET("timer-event", se_timerevent) {
+    IF_ET("timer-event ", se_timerevent) {
       sevent_data= p;
       return;
     }
-    IF_ET("timestamp", se_timestamp) {
+    IF_ET("timestamp ", se_timestamp) {
       int n, r;
       n=-1;
       r= sscanf(p,"%ld.%ld%n", &sevent_abst.tv_sec, &sevent_abst.tv_usec, &n);
@@ -208,47 +218,64 @@ static void se_timerevent(void) {
   toev_callback(0, sevent_abst, toev);
 }
 
-static void se_serial(void) {
-  int buf_used;
+static int unhex(const char *str, Byte *buf, int buf_len) {
   char c[3], *ep;
+  int buf_used;
   const char *p;
 
   c[2]= 0;
-  for (p=sevent_data, buf_used=serial_buf.l;
+  for (p=str, buf_used=0;
        ;
        ) {
     if (*p==' ') p++;
     if (!(c[0]= *p++)) break;
     if (!(c[1]= *p++)) simbad("odd number of hex digits");
 
-    if (buf_used==sizeof(serial_buf.d)) simbad("serial_buf overrun");
+    if (buf_used==buf_len) simbad("serial_buf overrun");
 
-    serial_buf.d[buf_used++]= strtoul(c,&ep,16);
+    buf[buf_used++]= strtoul(c,&ep,16);
     if (*ep) simbad("bad hex");
   }
-  if (buf_used>=2) {
-    Byte db0= serial_buf.d[buf_used-2] & ~PICMSG_DETECT_01;
-    if (PICMSG_DETECT0_P(db0)) {
-      sevent_lastdet[0]= db0;
-      sevent_lastdet[1]= serial_buf.d[buf_used-1];
-    }
-  }
-  serial_indata_process(buf_used);
+  return buf_used;
 }
-
-static void se_samedet(void) {
+static void se_serial(void) {
   int buf_used;
 
   buf_used= serial_buf.l;
-  if (buf_used >= sizeof(serial_buf.d)-1) simbad("samedet serial_buf overrun");
-  if (!sevent_lastdet[0]) simbad("samedet but no previous det");
-  if (sevent_lastdet[1] & 0x80) simbad("samedet but bad previous det");
-  serial_buf.d[buf_used++]= sevent_lastdet[0] |
-                           (sevent_data[0]=='1' ? PICMSG_DETECT_01 : 0);
-  serial_buf.d[buf_used++]= sevent_lastdet[1];
+  buf_used += unhex(sevent_data, serial_buf.d + buf_used,
+                   sizeof(serial_buf.d) - buf_used);
+  serial_indata_process(buf_used);
+}
+
+static void serial_detevent(Byte m[2], Byte or_m0) {
+  int buf_used;
+  buf_used= serial_buf.l+2;
+  if (buf_used > sizeof(serial_buf.d)) simbad("serial_buf det overrun");
+  serial_buf.d[serial_buf.l]=   m[0] | or_m0;
+  serial_buf.d[serial_buf.l+1]= m[1];
   serial_indata_process(buf_used);
 }
 
+static void se_serial_detcompr(void) {
+  int i, l;
+
+  i= *sevent_data++ - 'A';
+  if (i<0 || i>=DETSAVES) simbad("detcompr bad slot specifier");
+  l= unhex(sevent_data, sevent_lastdet[i], 2);
+  if (l!=2) simbad("detcompr wrong message length");
+  serial_detevent(sevent_lastdet[i],0);
+  sevent_lastdet[i][0] &= ~PICMSG_DETECT_01;
+}
+static void se_samedet(void) {
+  int i, d;
+  i= *sevent_data - 'a';
+  d= *sevent_data < 'a'; /* A is before a */
+  if (d) i -= 'A'-'a';
+  if (i<0 || i>=DETSAVES || !sevent_lastdet[i][0]) simbad("detsame bad slot");
+  serial_detevent(sevent_lastdet[i], d ? PICMSG_DETECT_01 : 0);
+}
+
 static void se_command(void) {
   ParseState ps;
   ps.remain= sevent_data;