diff --git a/examples/xspice/d_process/README b/examples/xspice/d_process/README index 1be54064a..9031425c6 100644 --- a/examples/xspice/d_process/README +++ b/examples/xspice/d_process/README @@ -41,6 +41,9 @@ example can be run when invoked from gdb. From a Windows Powershell, WinDbg can be attached to a running d_process program. +To enable the debugging hooks in the programs (graycode.c, prog1in4out.c, +prog4in1out.c), edit them to #define ENABLE_DEBUGGING. + Each program prints (to stderr) its process id when started. This makes it easier to know the process when attaching a debugger. diff --git a/examples/xspice/d_process/graycode.c b/examples/xspice/d_process/graycode.c index 19216e088..835552ef2 100644 --- a/examples/xspice/d_process/graycode.c +++ b/examples/xspice/d_process/graycode.c @@ -20,10 +20,13 @@ static int compute(uint8_t *dataout, int outsz, double time); +//#define ENABLE_DEBUGGING 1 +#ifdef ENABLE_DEBUGGING static int known_bp(int iargc) { return iargc; } +#endif int main(int argc, char *argv[]) { int i; @@ -56,6 +59,7 @@ int main(int argc, char *argv[]) { _setmode(1, _O_BINARY); #endif +#ifdef ENABLE_DEBUGGING #if defined(_MSC_VER) || defined(__MINGW64__) fprintf(stderr, "%s pid %d\n", argv[0], _getpid()); #else @@ -79,9 +83,10 @@ int main(int argc, char *argv[]) { #endif (void)known_bp(argc); +#endif for (i=0; i #include #include +#include #endif #include @@ -108,16 +109,53 @@ typedef unsigned char uint8_t; typedef struct { int pipe_to_child; int pipe_from_child; + int start_failed; + int header_failed; + int exchange_failed; uint8_t N_din, N_dout; // number of inputs/outputs bytes Digital_State_t dout_old[256]; // max possible storage to track output changes } Process_t; #if defined(_MSC_VER) || defined(__MINGW64__) #include -static void w_start(char *system_command, const char *const *argv, Process_t * process); +static unsigned int w_start(char *system_command, const char *const *argv, Process_t * process); #endif -static void sendheader(Process_t * process, int N_din, int N_dout) +static void report_sendheader_message(unsigned int msg_num) +{ + static char *messages[] = { + "", + "ERROR: d_process supports max 255 input and max 255 output signals", + "ERROR: d_process when sending header", + "ERROR: d_process didn't respond to the header", + "ERROR: d_process returned invalid header version", + "ERROR: d_process header I/O mismatch N_din and N_dout counts" + }; + cm_message_send(messages[msg_num]); +} + +static void report_exchangedata_message(unsigned int msg_num) +{ + static char *messages[] = { + "", + "ERROR: d_process when writing exchange data", + "ERROR: d_process received invalid dout count when reading exchange data" + }; + cm_message_send(messages[msg_num]); +} + +static void report_start_message(unsigned int msg_num) +{ + static char *messages[] = { + "", + "ERROR: d_process process_file argument is invalid or not given", + "ERROR: d_process failed to open pipe", + "ERROR: d_process failed to fork or start process" + }; + cm_message_send(messages[msg_num]); +} + +static unsigned int sendheader(Process_t * process, int N_din, int N_dout) { #if defined(_MSC_VER) #pragma pack(push, 1) @@ -132,8 +170,7 @@ static void sendheader(Process_t * process, int N_din, int N_dout) #endif if (N_din > 255 || N_dout > 255) { - fprintf(stderr, "Error: d_process supports max 255 input and output and 255 output signals\n"); - exit(1); + return 1; } #if defined(_MSC_VER) || defined(__MINGW64__) @@ -141,8 +178,7 @@ static void sendheader(Process_t * process, int N_din, int N_dout) #else if (write(process->pipe_to_child, &header, sizeof(header)) == -1) { #endif - fprintf(stderr, "Error: d_process when sending header\n"); - exit(1); + return 2; } // Wait for echo which must return the same header to ack transfer @@ -151,25 +187,22 @@ static void sendheader(Process_t * process, int N_din, int N_dout) #else if (read(process->pipe_from_child, &header, sizeof(header)) != sizeof(header)) { #endif - fprintf(stderr, "Error: d_process didn't respond to the header\n"); - exit(1); + return 3; } if (header.version != D_PROCESS_FORMAT_VERSION) { - fprintf(stderr, "Error: d_process returned invalid version: %d\n", header.version); - exit(1); + return 4; } if (header.N_din != N_din || header.N_dout != N_dout) { - fprintf(stderr, "Error: d_process I/O mismatch: in %d vs. returned %d, out %d vs. returned %d\n", - N_din, header.N_din, N_dout, header.N_dout); - exit(1); + return 5; } process->N_din = (uint8_t)DLEN(N_din); process->N_dout = (uint8_t)DLEN(N_dout); + return 0; } -static void dprocess_exchangedata(Process_t * process, double time, uint8_t din[], uint8_t dout[]) +static unsigned int dprocess_exchangedata(Process_t * process, double time, uint8_t din[], uint8_t dout[]) { #if defined(_MSC_VER) #pragma pack(push, 1) @@ -200,8 +233,7 @@ static void dprocess_exchangedata(Process_t * process, double time, uint8_t din[ wlen = write(process->pipe_to_child, &packet, sizeof(double) + process->N_din); #endif if (wlen == -1) { - fprintf(stderr, "Error: d_process when writing exchange data\n"); - exit(1); + return 1; } #if defined(_MSC_VER) || defined(__MINGW64__) @@ -209,16 +241,14 @@ static void dprocess_exchangedata(Process_t * process, double time, uint8_t din[ #else if (read(process->pipe_from_child, dout, process->N_dout) != process->N_dout) { #endif - fprintf(stderr, - "Error: d_process received invalid dout count, expected %d\n", - process->N_dout); - exit(1); + return 2; } + return 0; } #if !defined(_MSC_VER) && !defined(__MINGW64__) -static void start(char *system_command, char * c_argv[], Process_t * process) +static unsigned int start(char *system_command, char * c_argv[], Process_t * process) { int pipe_to_child[2]; int pipe_from_child[2]; @@ -226,8 +256,7 @@ static void start(char *system_command, char * c_argv[], Process_t * process) size_t syscmd_len = strlen(system_command); if (syscmd_len == 0) { - fprintf(stderr, "Error: d_process process_file argument is not given"); - exit(1); + return 1; } if (system_command[syscmd_len-1] == '|') { char *filename_in = NULL, *filename_out = NULL; @@ -240,20 +269,20 @@ static void start(char *system_command, char * c_argv[], Process_t * process) strncpy(filename_out, system_command, syscmd_len-1); strcpy(&filename_out[syscmd_len-1], "_out"); if ((process->pipe_to_child = open(filename_in, O_WRONLY)) == -1) { - perror("open in file"); - exit(1); + return 2; } if ((process->pipe_from_child = open(filename_out, O_RDONLY)) == -1) { - perror("open out file"); - exit(1); + return 2; } if (filename_in) free(filename_in); if (filename_out) free(filename_out); } else { - if (pipe(pipe_to_child) || pipe(pipe_from_child) || (pid=fork()) ==-1) { - perror("Error: d_process cannot create pipes and fork"); - exit(1); + if (pipe(pipe_to_child) || pipe(pipe_from_child)) { + return 2; + } + if ((pid=fork()) ==-1) { + return 3; } if (pid == 0) { dup2(pipe_to_child[0],0); @@ -262,17 +291,19 @@ static void start(char *system_command, char * c_argv[], Process_t * process) close(pipe_from_child[0]); if (execv(system_command, c_argv) == -1) { - perror(system_command); - exit(1); + fprintf(stderr, + "ERROR: d_process failed to fork or start process %s\n", + system_command); + return 3; } - } - else { + } else { process->pipe_to_child = pipe_to_child[1]; process->pipe_from_child = pipe_from_child[0]; close(pipe_to_child[0]); close(pipe_from_child[1]); } } + return 0; } #endif @@ -291,10 +322,19 @@ static void cm_d_process_callback(ARGS, Mif_Callback_Reason_t reason) } } +static int any_failed(Process_t *p) +{ + if (p->start_failed || p->header_failed || p->exchange_failed) { + return 1; + } else { + return 0; + } +} void cm_d_process(ARGS) { int i; /* generic loop counter index */ + unsigned int errnum; Digital_State_t *reset, /* storage for reset value */ *reset_old; /* previous reset value */ @@ -315,16 +355,18 @@ void cm_d_process(ARGS) clk = clk_old = (Digital_State_t *) cm_event_get_ptr(0,0); reset = reset_old = (Digital_State_t *) cm_event_get_ptr(1,0); - STATIC_VAR(process) = malloc(sizeof(Process_t)); + STATIC_VAR(process) = calloc(1, sizeof(Process_t)); local_process = STATIC_VAR(process); CALLBACK = cm_d_process_callback; if (!PARAM_NULL(process_params)) { + int upper_limit; if (PARAM_SIZE(process_params) > (C_ARGV_SIZE - 2)) { - fprintf(stderr, "Error: too many process_parameters\n"); - exit(1); + upper_limit = C_ARGV_SIZE - 2; + } else { + upper_limit = PARAM_SIZE(process_params); } - for (i=0; iN_din != 0) { - fprintf(stderr, "Error: in port size mismatch\n"); - exit(1); - } + if (errnum) { + report_start_message(errnum); + local_process->start_failed = 1; + return; } + if (any_failed(local_process)) return; + errnum = sendheader(local_process, PORT_SIZE(in), PORT_SIZE(out)); + if (errnum) { + report_sendheader_message(errnum); + local_process->header_failed = 1; + return; + } + if (any_failed(local_process)) return; + for (i=0; i> 3] |= (uint8_t)(b << (i & 7)); } - dprocess_exchangedata(local_process, (ONE != *reset) ? TIME : -TIME, din, dout); + errnum = dprocess_exchangedata(local_process, (ONE != *reset) ? TIME : -TIME, din, dout); + if (errnum) { + report_exchangedata_message(errnum); + local_process->exchange_failed = 1; + return; + } for (i=0; i> 3] >> (i & 7)) & 0x01) ? ONE : ZERO; @@ -436,7 +491,7 @@ void cm_d_process(ARGS) #include #include -static void w_start(char *system_command, const char *const *argv, Process_t * process) +static unsigned int w_start(char *system_command, const char *const *argv, Process_t * process) { int pipe_to_child[2]; int pipe_from_child[2]; @@ -444,23 +499,14 @@ static void w_start(char *system_command, const char *const *argv, Process_t * p int mode = _O_BINARY; size_t syscmd_len = strlen(system_command); - if (syscmd_len == 0) { - fprintf(stderr, "Error: d_process process_file argument is not given"); - exit(1); - } - if (system_command[syscmd_len-1] == '|') { - fprintf(stderr, "Error: d_process named pipe/fifo not supported\n"); - exit(1); + if (syscmd_len == 0 || system_command[syscmd_len-1] == '|') { + return 1; } if (_pipe(pipe_to_child, 1024, mode) == -1) { - perror("pipe_to_child"); - fprintf(stderr, "Failed to open pipe_to_child\n"); - exit(1); + return 2; } if (_pipe(pipe_from_child, 1024, mode) == -1) { - perror("pipe_from_child"); - fprintf(stderr, "Failed to open pipe_from_child\n"); - exit(1); + return 2; } _dup2(pipe_to_child[0],0); @@ -471,12 +517,11 @@ static void w_start(char *system_command, const char *const *argv, Process_t * p _flushall(); pid = _spawnvp(_P_NOWAIT, system_command, argv); if (pid == -1) { - perror("spawn from d_process"); - fprintf(stderr, "Failed to spawn %s\n", system_command); - exit(1); + return 3; } process->pipe_to_child = pipe_to_child[1]; process->pipe_from_child = pipe_from_child[0]; + return 0; } #endif