U< debug <context> : <debug message>
U< info : <informational message>
- U> timestamp <seconds>.<microseconds>
- U> timer-event <class>.<instance>
+ S picioh in suppressed <byte> [<byte>...]
+ S command-in <command> <args>....
+ S timestamp <seconds>.<microseconds>
+ S timer-event <class>.<instance>
======================================================================
int r;
r= gettimeofday(tv,0);
if (r) diee("gettimeofday failed");
- oprintf(UPO,"timestamp %ld.%06ld\n", tv->tv_sec, tv->tv_usec);
}
void *toev_callback(oop_source *source, struct timeval tv, void *t_v) {
TimeoutEvent *toev= t_v;
- oprintf(UPO,"timer-event %s.%s\n", toev->pclass, toev->pinst);
+ simlog("timer-event %s.%s\n",toev->pclass,toev->pinst);
+ simlog_flush();
toev->running= 0;
toev->callback(toev);
return OOP_CONTINUE;
} else {
real_mgettimeofday(tv);
}
+ simlog("timestamp %ld.%06ld\n",tv->tv_sec,tv->tv_usec);
+ simlog_flush();
}
int picio_send_noise= 1;
static const char *device= "/dev/railway";
-static const char *logcopy_fn= "+realtime.log";
+static const char *logcopy_fn;
/*---------- general event handling ----------*/
static void command_doline(ParseState *ps, CommandInput *cmdi_arg) {
int r;
- oprintf(UPO, "executing %s\n",ps->remain);
+ simlog("command-in %s\n",ps->remain);
+ simlog_flush();
ci= 0;
ci= some_needword_lookup(ps, toplevel_cmds, "command");
if (!ci) return;
+ oprintf(UPO, "executing %s\n",ci->name);
r= ci->fn(ps,ci);
switch (r) {
case 0: oprintf(UPO, "ack %s ok\n", ci->name); break;
exit(-1);
}
-void ouhex(const char *word, const Byte *command, int length) {
+void ouhexo(const char *word, const Byte *command, int length) {
oprintf(UPO, "%s", word);
- while (length) {
- oprintf(UPO, " %02x", *command++);
- length--;
- }
+ while (length--) oprintf(UPO, " %02x", *command++);
oprintf(UPO, "\n");
}
+void ouhexi(const char *word, const Byte *command, int length) {
+ simlog_serial(command,length);
+ ouhexo(word,command,length);
+}
void die_vprintf_hook(const char *fmt, va_list al) {
if (events) ovprintf(UPO, fmt, al);
}
if (!suppress && picio_send_noise >= 2)
- ouhex("picioh out", pi->d, pi->l);
+ ouhexo("picioh out", pi->d, pi->l);
/* note that the serial port is still in nonblocking mode. if
* we ever buffer up far enough that the kernel wants to make us
sys_events= oop_sys_new(); if (!sys_events) diee("oop_sys_new");
events= oop_sys_source(sys_events); massert(events);
- if (logcopy_fn[0] && strcmp(logcopy_fn,"-")) {
- cmdi.out.logcopy= fopen(logcopy_fn,"w");
- if (!cmdi.out.logcopy) diee("open log copy %s",logcopy_fn);
- }
-
+ simlog_open(logcopy_fn);
cmdin_new(&cmdi, 0);
serial_open(device);
events->on_fd(events, serial_fd, OOP_EXCEPTION, read_exception, 0);
} else {
- sim_initialise();
+ sim_initialise(logcopy_fn);
sys_events= 0;
}
/*---------- from/for realtime.c ----------*/
void oupicio(const char *dirn, const PicInsnInfo *pii, int objnum);
-void ouhex(const char *word, const Byte *command, int length);
+void ouhexi(const char *word, const Byte *command, int length);
+void ouhexo(const char *word, const Byte *command, int length);
void serial_transmit(const PicInsn *pi);
const char *simulate;
void serial_indata_process(int buf_used);
-void sim_initialise(void);
+void sim_initialise(const char *logduplicate);
void sim_run(void);
+void simlogv(const char *fmt, va_list al);
+void simlog(const char *fmt, ...);
+void simlog_serial(const Byte *data, int length);
+void simlog_flush(void);
+void simlog_open(const char *fn);
+
void mgettimeofday(struct timeval *tv); /* contains magic for simulation */
void *toev_callback(oop_source *source, struct timeval tv, void *t_v);
static SimTimeout *simtimeouts;
+static FILE *simoutput;
static FILE *siminput;
static char *sevent_buf;
static size_t sevent_buflen;
+static int sevent_lno;
static SimEventFn *sevent_type;
static char *sevent_data;
static struct timeval sevent_abst;
+/*---------- writing simulation log ----------*/
+
+void simlogv(const char *fmt, va_list al) {
+ if (simoutput==stdout) ovprintf(UPO,fmt,al);
+ else if (simoutput) vfprintf(simoutput,fmt,al);
+}
+void simlog(const char *fmt, ...) {
+ va_list al;
+ va_start(al,fmt);
+ simlogv(fmt,al);
+ va_end(al);
+}
+void simlog_flush(void) {
+ if (simoutput==stdout) obc_tryflush(UPO);
+ else if (simoutput)
+ if (ferror(simoutput) || fflush(simoutput))
+ diee("write simulation log");
+}
+void simlog_serial(const Byte *data, int length) {
+ simlog("picioh in suppressed");
+ while (length--) simlog(" %02x",*data++);
+ simlog("\n");
+ simlog_flush();
+}
+void simlog_open(const char *fn) {
+ if (!fn) fn= "+realtime.log";
+ if (!strcmp(fn,"-")) {
+ simoutput= stdout; /* we don't really use this - see vsimlog */
+ } else if (fn[0]) {
+ simoutput= fopen(fn,"w");
+ if (!simoutput) diee("open simulation log %s",fn);
+ cmdi.out.logcopy= simoutput;
+ }
+}
+
/*---------- simulation input stream parser ----------*/
static void simbad(const char *how) __attribute__((noreturn));
static void simbad(const char *how) {
- die("bad simulation (in `%s'): %s", sevent_buf, how);
+ die("simulation failed (line %d, in `%s'): %s", sevent_lno, sevent_buf, how);
}
static void sevent(void) {
return;
for (;;) {
+ sevent_lno++;
+
gr= getline(&sevent_buf,&sevent_buflen,siminput);
if (feof(siminput)) { sevent_type= se_eof; return; }
if (ferror(siminput)) diee("read simulation input failed");
assert(gr>0);
assert(sevent_buf[gr-1]=='\n');
sevent_buf[gr-1]= 0;
-
+
#define IF_ET(pfx, et) \
if (!strncmp(pfx " ", sevent_buf, sizeof(pfx)) \
&& (sevent_type=(et), p=sevent_buf+(sizeof(pfx))))
- IF_ET("executing", se_command) {
+ IF_ET("command-in", se_command) {
sevent_data= p;
return;
}
*tv= sevent_abst;
if (sevent_type==se_timestamp)
sevent_type= 0;
+ else
+ fprintf(stderr,"simulation warning -"
+ " mgettimeofday desynched at line %d\n", sevent_lno);
}
/*---------- simulation events ----------*/
/*---------- core ----------*/
-void sim_initialise(void) {
+void sim_initialise(const char *logduplicate) {
cmdi.out.logcopy= 0;
obc_init_core(&cmdi.out);
serial_fd= open("/dev/null",O_WRONLY);
if (serial_fd<0) diee("open /dev/null for dummy serial");
siminput= fopen(simulate,"r");
if (!siminput) diee("open simulation input %s",simulate);
+ if (logduplicate)
+ simlog_open(logduplicate);
}
void sim_run(void) {
+ SimEventFn *fn;
for (;;) {
sevent();
- sevent_type();
+ fn= sevent_type;
sevent_type= 0;
+ fn();
obc_tryflush(&cmdi.out);
}
}
struct timeval now;
mgettimeofday(&now);
+oprintf(DUPO("ip") " %ld.%06ld\n", now.tv_sec, now.tv_usec);
ping_seq= (now.tv_sec & 0x1fU) << 5; /* bottom 5bi of secs: period 32s */
ping_seq |= (now.tv_usec >> 15); /* top 5bi of 20bi us: res.~2^15us */
ping_toev.duration= 300;
if (sta_state == Sta_Flush) {
toev_start(&sta_toev);
- ouhex("picioh in junk", buf->d, buf->l);
+ ouhexi("picioh in junk", buf->d, buf->l);
return; /* junk absolutely everything */
}
if (PICMSG_AAARGH_P(buf->d[0])) {
- ouhex("picioh in aaargh", buf->d, buf->l);
+ ouhexi("picioh in aaargh", buf->d, buf->l);
die("PIC sent us AAARGH!");
}
if (PICMSG_HELLO_P(buf->d[0])) {
- ouhex("picioh in hello", buf->d, 1);
+ ouhexi("picioh in hello", buf->d, 1);
sta_goto(Sta_Flush);
buf->l= 1;
return;
}
if (sta_state == Sta_Off) {
- ouhex("picioh in off", buf->d, 1);
+ ouhexi("picioh in off", buf->d, 1);
buf->l= 1;
return;
}
goto found_end;
if (buf->l == sizeof(buf->d)) {
- ouhex("picioh in toolong", buf->d, buf->l);
+ ouhexi("picioh in toolong", buf->d, buf->l);
die("PIC sent packet too long");
}
buf->l= 0; /* message not yet finished, so consume nothing */
buf->l= ep - buf->d + 1;
picinsn_decode(buf, pic_reply_infos, &pii, &objnum);
suppress= pii && pii->noiselevel > picio_send_noise;
+
if (!suppress && picio_send_noise >= 2)
- ouhex("picioh in msg", buf->d, buf->l);
+ ouhexi("picioh in msg", buf->d, buf->l);
+ else
+ simlog_serial(buf->d, buf->l);
+
if (!pii) { oprintf(UPO, "picio in unknown\n"); return; }
if (!suppress)
oupicio("in",pii,objnum);
break predict_problem
break safety_panic
+#break real_mgettimeofday
+
run
# valgrind ./realtime shinkansen.speeds.record homes.record
break nmra_errchk_fail
break predict_problem
break safety_panic
+#break mgettimeofday
set args -S+realtime.log shinkansen.speeds.record homes.record
run