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:
Brian Taylor 2023-10-13 18:15:38 -07:00 committed by Holger Vogt
parent 182764a894
commit 4530cde8e2
5 changed files with 142 additions and 81 deletions

View File

@ -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.

View File

@ -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));

View File

@ -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) {

View File

@ -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));

View File

@ -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