Use Xspice cm_message_send to report errors rathen than printing to stderr and calling exit. When a d_process model has errors found in start(), sendheader(), and dprocess_exchangedata() these are reported, but if the model is run a SIGINT is raised. There must be a better way of stopping the simulator.
This commit is contained in:
parent
182764a894
commit
4530cde8e2
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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<argc; i++) {
|
||||
fprintf(stderr, "[%d] %s\n", i, argv[i]);
|
||||
//fprintf(stderr, "[%d] %s\n", i, argv[i]);
|
||||
if (strcmp(argv[i],"--pipe")==0) {
|
||||
#if defined(_MSC_VER) || defined(__MINGW64__)
|
||||
if ((pipein = _open("graycode_in", O_RDONLY)) < 0 || (pipeout = _open("graycode_out", O_WRONLY)) < 0)
|
||||
|
|
@ -102,9 +107,9 @@ int main(int argc, char *argv[]) {
|
|||
while(read(pipein, &in, sizeof(in)) == sizeof(in)) {
|
||||
#endif
|
||||
|
||||
if (!compute(out.dout, outlen, in.time)) {
|
||||
return 1;
|
||||
}
|
||||
if (!compute(out.dout, outlen, in.time)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW64__)
|
||||
_write(pipeout, &out, sizeof(out));
|
||||
|
|
|
|||
|
|
@ -22,13 +22,15 @@ static int compute(
|
|||
uint8_t *datain, int insz, 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;
|
||||
int inlen = D_PROCESS_DLEN(DIGITAL_IN);
|
||||
int outlen = D_PROCESS_DLEN(DIGITAL_OUT);
|
||||
|
||||
|
|
@ -61,6 +63,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
|
||||
|
|
@ -85,9 +88,10 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
(void)known_bp(argc);
|
||||
|
||||
for (i=0; i<argc; i++) {
|
||||
for (int i=0; i<argc; i++) {
|
||||
fprintf(stderr, "[%d] %s\n", i, argv[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (d_process_init(pipein, pipeout, DIGITAL_IN, DIGITAL_OUT) ) {
|
||||
#if defined(_MSC_VER) || defined(__MINGW64__)
|
||||
|
|
@ -96,9 +100,9 @@ int main(int argc, char *argv[]) {
|
|||
while(read(pipein, &in, sizeof(in)) == sizeof(in)) {
|
||||
#endif
|
||||
|
||||
if (!compute(in.din, inlen, out.dout, outlen, in.time)) {
|
||||
return 1;
|
||||
}
|
||||
if (!compute(in.din, inlen, out.dout, outlen, in.time)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW64__)
|
||||
_write(pipeout, &out, sizeof(out));
|
||||
|
|
@ -122,7 +126,7 @@ static int compute(
|
|||
uint8_t inbit0 = datain[0] & 1;
|
||||
static uint8_t count = 0;
|
||||
if (time < 0.0) {
|
||||
fprintf(stderr, "Reset prog1in4out at time %g\n", -time);
|
||||
//fprintf(stderr, "Reset prog1in4out at time %g\n", -time);
|
||||
count = 15;
|
||||
}
|
||||
if (count < 15) {
|
||||
|
|
|
|||
|
|
@ -22,13 +22,15 @@ static int compute(
|
|||
uint8_t *datain, int insz, 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;
|
||||
int inlen = D_PROCESS_DLEN(DIGITAL_IN);
|
||||
int outlen = D_PROCESS_DLEN(DIGITAL_OUT);
|
||||
|
||||
|
|
@ -61,6 +63,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
|
||||
|
|
@ -85,9 +88,10 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
(void)known_bp(argc);
|
||||
|
||||
for (i=0; i<argc; i++) {
|
||||
for (int i=0; i<argc; i++) {
|
||||
fprintf(stderr, "[%d] %s\n", i, argv[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (d_process_init(pipein, pipeout, DIGITAL_IN, DIGITAL_OUT) ) {
|
||||
#if defined(_MSC_VER) || defined(__MINGW64__)
|
||||
|
|
@ -96,9 +100,9 @@ int main(int argc, char *argv[]) {
|
|||
while(read(pipein, &in, sizeof(in)) == sizeof(in)) {
|
||||
#endif
|
||||
|
||||
if (!compute(in.din, inlen, out.dout, outlen, in.time)) {
|
||||
return 1;
|
||||
}
|
||||
if (!compute(in.din, inlen, out.dout, outlen, in.time)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW64__)
|
||||
_write(pipeout, &out, sizeof(out));
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ REFERENCED FILES
|
|||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
|
|
@ -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 <io.h>
|
||||
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; i<PARAM_SIZE(process_params); i++) {
|
||||
for (i=0; i<upper_limit; i++) {
|
||||
c_argv[c_argc++] = PARAM(process_params[i]);
|
||||
}
|
||||
}
|
||||
|
|
@ -333,18 +375,24 @@ void cm_d_process(ARGS)
|
|||
#undef C_ARGV_SIZE
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW64__)
|
||||
w_start(c_argv[0], (const char *const *)c_argv, local_process);
|
||||
errnum = w_start(c_argv[0], (const char *const *)c_argv, local_process);
|
||||
#else
|
||||
start(c_argv[0], c_argv, local_process);
|
||||
errnum = start(c_argv[0], c_argv, local_process);
|
||||
#endif
|
||||
sendheader(local_process, PORT_SIZE(in), PORT_SIZE(out));
|
||||
|
||||
if (PORT_SIZE(in) == 0) {
|
||||
if (local_process->N_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<PORT_SIZE(in); i++) {
|
||||
LOAD(in[i]) = PARAM(input_load);
|
||||
}
|
||||
|
|
@ -357,7 +405,9 @@ void cm_d_process(ARGS)
|
|||
}
|
||||
else {
|
||||
local_process = STATIC_VAR(process);
|
||||
|
||||
if (any_failed(local_process)) {
|
||||
raise(SIGINT);
|
||||
}
|
||||
clk = (Digital_State_t *) cm_event_get_ptr(0,0);
|
||||
clk_old = (Digital_State_t *) cm_event_get_ptr(0,1);
|
||||
|
||||
|
|
@ -405,7 +455,12 @@ void cm_d_process(ARGS)
|
|||
din[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<PORT_SIZE(out); i++) {
|
||||
Digital_State_t new_state = ((dout[i >> 3] >> (i & 7)) & 0x01) ? ONE : ZERO;
|
||||
|
|
@ -436,7 +491,7 @@ void cm_d_process(ARGS)
|
|||
#include <process.h>
|
||||
#include <io.h>
|
||||
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue