Add MODIFICATIONS note, cleanup white space.

This commit is contained in:
Brian Taylor 2023-10-04 14:46:42 -07:00 committed by Holger Vogt
parent 5c4352d02f
commit 33780055ee
2 changed files with 123 additions and 109 deletions

View File

@ -21,10 +21,10 @@ PROJECT http://isotel.eu/mixedsim
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
AUTHORS
AUTHORS
2017-2018 Uros Platse <uros@isotel.eu>
SUMMARY
@ -32,13 +32,13 @@ SUMMARY
standard unix stdin/stdout pipe to extend ngspice functionality
to the level of embedded systems.
If a process ends with | character then rather than invoking
If a process ends with | character then rather than invoking
a process it opens named pipe, process_in which is input to the
process and pipe process_out for reading back from process.
Communication between this code model and a process is in 8-bit
binary format. On start-up
0x01: version
0x00-0xFF: number of inputs, max 255, 0 means none
0x00-0xFF: number of outputs, max 255, 0 means none
@ -46,7 +46,7 @@ SUMMARY
On start:
outputs are set to uknown state and high impedance
On each rising edge of a clock and reset being low
double (8-byte): positive value of TIME if reset is low otherwise -TIME
@ -54,7 +54,7 @@ SUMMARY
ooutputs are defined by returning process
and process must return:
[output array]: output bytes, each byte packs up to 8 outputs
For example project please see: http://isotel.eu/mixedsim
@ -69,13 +69,21 @@ MODIFICATIONS
- Tested and polished ready to be published
7 April 2018 Uros Platse <uros@isotel.eu>
Removed async reset and converted it to synchronous reset only.
Removed async reset and converted it to synchronous reset only.
Code cleanup.
30 September 2023 Brian Taylor
Modify the code for Windows VisualC and Mingw.
In VisualC, #pragma pack(...) compiler directives are needed for
the struct declarations using __attribute__(packed).
Use Microsoft CRT library functions _pipe, _read, _write, _spawn.
For Windows VisualC and Mingw the pipes use binary mode, and
named pipes or fifos are not supported.
REFERENCED FILES
Inputs from and outputs to ARGS structure.
Inputs from and outputs to ARGS structure.
===============================================================================*/
@ -86,9 +94,11 @@ REFERENCED FILES
#include <stdlib.h>
#if !defined(_MSC_VER)
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include <fcntl.h>
#define D_PROCESS_FORMAT_VERSION 0x01
#define DLEN(x) (uint8_t)( ((x)==0) ? 0 : (((x)-1)/8 + 1) )
#define DIN_SIZE_MAX 256 // also represents a theoretical maximum for 8-bit input length specifier
@ -98,7 +108,7 @@ typedef unsigned char uint8_t;
typedef struct {
int pipe_to_child;
int pipe_from_child;
uint8_t N_din, N_dout; // number of inputs/outputs bytes
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;
@ -120,10 +130,10 @@ static void sendheader(Process_t * process, int N_din, int N_dout)
uint8_t version, N_din, N_dout;
} __attribute__((packed)) header = {D_PROCESS_FORMAT_VERSION, (uint8_t)N_din, (uint8_t)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);
exit(1);
}
#if defined(_MSC_VER) || defined(__MINGW64__)
@ -134,7 +144,7 @@ static void sendheader(Process_t * process, int N_din, int N_dout)
fprintf(stderr, "Error: d_process when sending header\n");
exit(1);
}
// Wait for echo which must return the same header to ack transfer
#if defined(_MSC_VER) || defined(__MINGW64__)
if (_read(process->pipe_from_child, &header, sizeof(header)) != sizeof(header)) {
@ -143,17 +153,17 @@ static void sendheader(Process_t * process, int N_din, int N_dout)
#endif
fprintf(stderr, "Error: d_process didn't respond to the header\n");
exit(1);
}
}
if (header.version != D_PROCESS_FORMAT_VERSION) {
fprintf(stderr, "Error: d_process returned invalid version: %d\n", header.version);
exit(1);
}
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);
exit(1);
}
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);
}
process->N_din = (uint8_t)DLEN(N_din);
process->N_dout = (uint8_t)DLEN(N_dout);
}
@ -174,7 +184,7 @@ static void dprocess_exchangedata(Process_t * process, double time, uint8_t din[
uint8_t din[DIN_SIZE_MAX];
} __attribute__((packed)) packet_t;
#endif
size_t dlen = 0;
int wlen = 0;
packet_t packet;
@ -218,31 +228,37 @@ static void start(char *system_command, char * c_argv[], Process_t * process)
exit(1);
}
if (system_command[syscmd_len-1] == '|') {
char filename[syscmd_len+5];
strncpy(filename, system_command, syscmd_len-1);
strcpy(&filename[syscmd_len-1], "_in");
if ( (process->pipe_to_child = open(filename, O_WRONLY)) < 0) {
perror(filename);
char *filename_in = NULL, *filename_out = NULL;
filename_in = (char *) malloc(syscmd_len + 5);
filename_out = (char *) malloc(syscmd_len + 5);
filename_in[0] = '\0';
filename_out[0] = '\0';
strncpy(filename_in, system_command, syscmd_len-1);
strcpy(&filename_in[syscmd_len-1], "_in");
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);
}
strncpy(filename, system_command, syscmd_len-1);
strcpy(&filename[syscmd_len-1], "_out");
if ( (process->pipe_from_child = open(filename, O_RDONLY)) < 0) {
perror(filename);
if ((process->pipe_from_child = open(filename_out, O_RDONLY)) == -1) {
perror("open out file");
exit(1);
}
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 (pid == 0) {
dup2(pipe_to_child[0],0);
dup2(pipe_from_child[1],1);
close(pipe_to_child[1]);
close(pipe_from_child[0]);
if (execv(system_command, c_argv) == -1) {
perror(system_command);
exit(1);
@ -259,10 +275,10 @@ static void start(char *system_command, char * c_argv[], Process_t * process)
#endif
void cm_d_process(ARGS)
void cm_d_process(ARGS)
{
int i; /* generic loop counter index */
Digital_State_t *reset, /* storage for clock value */
*reset_old; /* previous clock value */
@ -272,18 +288,18 @@ void cm_d_process(ARGS)
Process_t *local_process; /* Structure containing process vars */
if (INIT) {
if (INIT) {
char * c_argv[1024];
int c_argc = 1;
cm_event_alloc(0,sizeof(Digital_State_t));
cm_event_alloc(1,sizeof(Digital_State_t));
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) = malloc(sizeof(Process_t));
local_process = STATIC_VAR(process);
if (!PARAM_NULL(process_params)) {
for (i=0; i<PARAM_SIZE(process_params); i++) {
c_argv[c_argc++] = PARAM(process_params[i]);
@ -291,25 +307,25 @@ void cm_d_process(ARGS)
}
c_argv[0] = PARAM(process_file);
c_argv[c_argc] = NULL;
#if defined(_MSC_VER) || defined(__MINGW64__)
w_start(c_argv[0], c_argv, local_process);
#else
start(c_argv[0], c_argv, local_process);
#endif
sendheader(local_process, PORT_SIZE(in), PORT_SIZE(out));
for (i=0; i<PORT_SIZE(in); i++) {
LOAD(in[i]) = PARAM(input_load);
}
}
LOAD(clk) = PARAM(clk_load);
if ( !PORT_NULL(reset) ) {
LOAD(reset) = PARAM(reset_load);
}
}
else {
else {
local_process = STATIC_VAR(process);
clk = (Digital_State_t *) cm_event_get_ptr(0,0);
@ -340,8 +356,8 @@ void cm_d_process(ARGS)
if (*clk != *clk_old && ONE == *clk) {
uint8_t *dout, *din;
uint8_t b;
dout = malloc(local_process->N_dout * sizeof(uint8_t));
din = malloc(local_process->N_din * sizeof(uint8_t));
dout = (uint8_t *) malloc(local_process->N_dout * sizeof(uint8_t));
din = (uint8_t *) malloc(local_process->N_din * sizeof(uint8_t));
memset(din, 0, local_process->N_din);
for (i=0; i<PORT_SIZE(in); i++) {
@ -358,10 +374,10 @@ void cm_d_process(ARGS)
}
dprocess_exchangedata(local_process, (ONE != *reset) ? TIME : -TIME, din, dout);
for (i=0; i<PORT_SIZE(out); i++) {
Digital_State_t new_state = ((dout[i >> 3] >> (i & 7)) & 0x01) ? ONE : ZERO;
if (new_state != local_process->dout_old[i]) {
OUTPUT_STATE(out[i]) = new_state;
OUTPUT_STRENGTH(out[i]) = STRONG;
@ -370,7 +386,7 @@ void cm_d_process(ARGS)
}
else {
OUTPUT_CHANGED(out[i]) = FALSE;
}
}
}
free(din);
free(dout);
@ -393,19 +409,17 @@ static void w_start(char *system_command, char * c_argv[], Process_t * process)
int pipe_to_child[2];
int pipe_from_child[2];
int pid = 0;
#define USE_BINARY_MODE
#ifdef USE_BINARY_MODE
int mode = _O_BINARY;
#else
int mode = _O_TEXT;
#endif
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 (_pipe(pipe_to_child, 1024, mode) == -1) {
perror("pipe_to_child");
fprintf(stderr, "Failed to open pipe_to_child\n");

View File

@ -2,20 +2,20 @@
================================================================================
Copyright 2017-2018 Isotel d.o.o. http://www.isotel.eu
AUTHORS
AUTHORS
5 November 2017 Uros Platse <uros@isotel.eu>
SUMMARY
This file contains the interface specification file for the
This file contains the interface specification file for the
digital d_process (extends to a system process) code model.
===============================================================================*/
NAME_TABLE:
@ -32,8 +32,8 @@ Description: "input" "clock"
Direction: in in
Default_Type: d d
Allowed_Types: [d] [d]
Vector: yes no
Vector_Bounds: - -
Vector: yes no
Vector_Bounds: - -
Null_Allowed: yes no
@ -45,8 +45,8 @@ Description: "reset" "output"
Direction: in out
Default_Type: d d
Allowed_Types: [d] [d]
Vector: no yes
Vector_Bounds: - [1 -]
Vector: no yes
Vector_Bounds: - [1 -]
Null_Allowed: yes yes
@ -58,35 +58,35 @@ Parameter_Name: clk_delay reset_delay
Description: "delay from CLK" "delay from reset"
Data_Type: real real
Default_Value: 1.0e-9 1.0e-9
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: process_file
Description: "file name of the executable process"
Data_Type: string
Default_Value: "process"
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: no
Description: "file name of the executable process"
Data_Type: string
Default_Value: "process"
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: no
PARAMETER_TABLE:
Parameter_Name: process_params
Description: "parameters to be passed to an executable process"
Data_Type: string
Description: "parameters to be passed to an executable process"
Data_Type: string
Default_Value: -
Limits: -
Vector: yes
Vector_Bounds: -
Limits: -
Vector: yes
Vector_Bounds: -
Null_Allowed: yes
@ -94,50 +94,50 @@ PARAMETER_TABLE:
Parameter_Name: reset_state
Description: "default state on RESET & at DC"
Data_Type: int
Default_Value: 0
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: no
Description: "default state on RESET & at DC"
Data_Type: int
Default_Value: 0
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: no
PARAMETER_TABLE:
Parameter_Name: input_load
Description: "input loading capacitance (F)"
Data_Type: real
Default_Value: 1.0e-12
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: no
Description: "input loading capacitance (F)"
Data_Type: real
Default_Value: 1.0e-12
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: no
PARAMETER_TABLE:
Parameter_Name: clk_load
Description: "clock loading capacitance (F)"
Data_Type: real
Default_Value: 1.0e-12
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: no
Description: "clock loading capacitance (F)"
Data_Type: real
Default_Value: 1.0e-12
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: no
PARAMETER_TABLE:
Parameter_Name: reset_load
Description: "reset loading capacitance (F)"
Data_Type: real
Default_Value: 1.0e-12
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: no
Description: "reset loading capacitance (F)"
Data_Type: real
Default_Value: 1.0e-12
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: no
STATIC_VAR_TABLE: