committed by
Holger Vogt
11 changed files with 624 additions and 0 deletions
-
55examples/xspice/d_process/README
-
7examples/xspice/d_process/clean.sh
-
4examples/xspice/d_process/compile.bat.txt
-
5examples/xspice/d_process/compile.sh
-
53examples/xspice/d_process/d_process.h
-
131examples/xspice/d_process/graycode.c
-
10examples/xspice/d_process/nggtk.tcl
-
40examples/xspice/d_process/prog-pipes.cir
-
46examples/xspice/d_process/prog1-4.cir
-
136examples/xspice/d_process/prog1in4out.c
-
137examples/xspice/d_process/prog4in1out.c
@ -0,0 +1,55 @@ |
|||||
|
The d_process Xspice model was created by Uros Platise. |
||||
|
|
||||
|
A complete, non-trivial example is located at: |
||||
|
https://www.isotel.eu/mixedsim/embedded/motorforce/index.html |
||||
|
|
||||
|
This directory contains a simple test of the d_process model. |
||||
|
|
||||
|
Compile the programs that are called from within d_process: |
||||
|
|
||||
|
./compile.sh (on Linux or Cygwin on Windows) |
||||
|
|
||||
|
In a Windows Powershell using VisualC, copy compile.bat.txt to compile.bat, |
||||
|
then use it. In a Mingw Msys shell, you can use the VisualC compiled programs, |
||||
|
or use compile.sh. In both these environments the programs need to be compiled |
||||
|
this way to use binary mode pipes. |
||||
|
|
||||
|
Run the test case (comment out the gtkwave lines or use plot if you like): |
||||
|
|
||||
|
ngspice prog1-4.cir |
||||
|
|
||||
|
To clean up: |
||||
|
|
||||
|
./clean.sh |
||||
|
|
||||
|
NOTE that the prog-pipes.cir test needs fifos created on Linux or Cygwin |
||||
|
on Windows. This is not available on Windows VisualC or Mingw builds. |
||||
|
|
||||
|
mkfifo graycode_in |
||||
|
mkfifo graycode_out |
||||
|
|
||||
|
before ngspice prog-pipes.cir, and in another shell: |
||||
|
|
||||
|
./graycode --pipe |
||||
|
|
||||
|
needs to be started. |
||||
|
|
||||
|
NOTE on debugging. On Linux or Cygwin on Windows, gdb can be attached to |
||||
|
the running d_process programs, or in --pipe mode with fifos, the graycode |
||||
|
example can be run when invoked from gdb. |
||||
|
|
||||
|
From a Windows Powershell, WinDbg can be attached to a running d_process |
||||
|
program. |
||||
|
|
||||
|
Each program prints (to stderr) its process id when started. This makes |
||||
|
it easier to know the process when attaching a debugger. |
||||
|
|
||||
|
All the programs (graycode.c, prog1in4out.c, prog4in1out.c) contain a call |
||||
|
to sleep to give you time to attach a debugger. This is enabled by: |
||||
|
|
||||
|
export GO_TO_SLEEP=1 (on Linux, Cygwin) |
||||
|
$env:go_to_sleep = '1' (on Windows Powershell) |
||||
|
|
||||
|
Don't forget to remove the environment variables after use, or the |
||||
|
prog1-4.cir will sleep (for up to 1 minute) each time you rerun it. |
||||
|
|
||||
@ -0,0 +1,7 @@ |
|||||
|
#!/bin/bash |
||||
|
set -v |
||||
|
rm -fv *.vcd *.exe *.obj |
||||
|
rm -fv prog1in4out |
||||
|
rm -fv prog4in1out |
||||
|
rm -fv graycode |
||||
|
rm -fv graycode_in graycode_out |
||||
@ -0,0 +1,4 @@ |
|||||
|
# Add /Zi for debug info |
||||
|
cl /Fe: prog1in4out.exe prog1in4out.c |
||||
|
cl /Fe: prog4in1out.exe prog4in1out.c |
||||
|
cl /Fe: graycode.exe graycode.c |
||||
@ -0,0 +1,5 @@ |
|||||
|
#!/bin/bash |
||||
|
set -v |
||||
|
gcc -Wall -Wpedantic -g -o prog1in4out prog1in4out.c |
||||
|
gcc -Wall -Wpedantic -g -o prog4in1out prog4in1out.c |
||||
|
gcc -Wall -Wpedantic -g -o graycode graycode.c |
||||
@ -0,0 +1,53 @@ |
|||||
|
/** |
||||
|
* \file |
||||
|
* \brief NgSpice D_PROCESS Interface |
||||
|
* \author Uros Platise <uros@isotel.eu> |
||||
|
*/ |
||||
|
|
||||
|
#ifndef __NGSPICE_D_PROCESS__ |
||||
|
#define __NGSPICE_D_PROCESS__ |
||||
|
|
||||
|
#include <stdio.h> |
||||
|
#if !defined(_MSC_VER) |
||||
|
#include <unistd.h> |
||||
|
#endif |
||||
|
#include <stdint.h> |
||||
|
|
||||
|
#define D_PROCESS_FORMAT_VERSION 0x01 |
||||
|
#define D_PROCESS_DLEN(x) (uint8_t)( ((x)==0) ? 0 : (((x)-1)/8 + 1) ) |
||||
|
|
||||
|
static inline int d_process_init(int pipein, int pipeout, uint8_t N_din, uint8_t N_dout) { |
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
#pragma pack(push, 1) |
||||
|
struct header_s { |
||||
|
uint8_t version, N_din, N_dout; |
||||
|
} header; |
||||
|
#pragma pack(pop) |
||||
|
#else |
||||
|
struct header_s { |
||||
|
uint8_t version, N_din, N_dout; |
||||
|
} __attribute__((packed))header; |
||||
|
#endif |
||||
|
|
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
if (_read(pipein, &header, sizeof(header)) != sizeof(header)) { |
||||
|
#else |
||||
|
if (read(pipein, &header, sizeof(header)) != sizeof(header)) { |
||||
|
#endif |
||||
|
fprintf(stderr, "Error: Incompatible ngspice d_process header size, requiring version %d\n", header.version); |
||||
|
return 0; |
||||
|
} |
||||
|
if (header.version != D_PROCESS_FORMAT_VERSION || header.N_din != N_din || header.N_dout != N_dout) { |
||||
|
fprintf(stderr, "Error: Incompatible ngspice d_process requiring version %d, number of inputs %d expected %d, and outputs %d expected %d.\n", |
||||
|
header.version, header.N_din, N_din, header.N_dout, N_dout); |
||||
|
return 0; |
||||
|
} |
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
_write(pipeout, &header, sizeof(header)); // acknowledge connection by returning back the same header |
||||
|
#else |
||||
|
write(pipeout, &header, sizeof(header)); // acknowledge connection by returning back the same header |
||||
|
#endif |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,131 @@ |
|||||
|
/* |
||||
|
The organization of this file is modelled after the motorforce example |
||||
|
developed by Uros Platise. |
||||
|
*/ |
||||
|
#include <string.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <fcntl.h> |
||||
|
#if !defined(_MSC_VER) && !defined(__MINGW64__) |
||||
|
#include <unistd.h> |
||||
|
#endif |
||||
|
#if defined(_MSC_VER) |
||||
|
#include <io.h> |
||||
|
#include <process.h> |
||||
|
#include <Windows.h> |
||||
|
#endif |
||||
|
#include "d_process.h" |
||||
|
|
||||
|
#define DIGITAL_IN 0 |
||||
|
#define DIGITAL_OUT 4 |
||||
|
|
||||
|
static int compute(uint8_t *dataout, int outsz, double time); |
||||
|
|
||||
|
static int known_bp(int iargc) |
||||
|
{ |
||||
|
return iargc; |
||||
|
} |
||||
|
|
||||
|
int main(int argc, char *argv[]) { |
||||
|
int i; |
||||
|
int outlen = D_PROCESS_DLEN(DIGITAL_OUT); |
||||
|
|
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
#pragma pack(push, 1) |
||||
|
struct in_s { |
||||
|
double time; |
||||
|
} in; |
||||
|
|
||||
|
struct out_s { |
||||
|
uint8_t dout[D_PROCESS_DLEN(DIGITAL_OUT)]; |
||||
|
} out; |
||||
|
#pragma pack(pop) |
||||
|
#else |
||||
|
struct in_s { |
||||
|
double time; |
||||
|
} __attribute__((packed)) in; |
||||
|
|
||||
|
struct out_s { |
||||
|
uint8_t dout[D_PROCESS_DLEN(DIGITAL_OUT)]; |
||||
|
} __attribute__((packed)) out; |
||||
|
#endif |
||||
|
|
||||
|
int pipein = 0; // default stdin to recv from ngspice |
||||
|
int pipeout= 1; // default stdout to send to ngspice |
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
_setmode(0, _O_BINARY); |
||||
|
_setmode(1, _O_BINARY); |
||||
|
#endif |
||||
|
|
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
fprintf(stderr, "%s pid %d\n", argv[0], _getpid()); |
||||
|
#else |
||||
|
fprintf(stderr, "%s pid %d\n", argv[0], getpid()); |
||||
|
#endif |
||||
|
|
||||
|
#if !defined(_MSC_VER) && !defined(__MINGW64__) |
||||
|
if (getenv("GO_TO_SLEEP")) { |
||||
|
sleep(40); |
||||
|
} |
||||
|
#endif |
||||
|
#if defined(__MINGW64__) |
||||
|
if (getenv("GO_TO_SLEEP")) { |
||||
|
sleep(40); |
||||
|
} |
||||
|
#endif |
||||
|
#if defined(_MSC_VER) |
||||
|
if (getenv("GO_TO_SLEEP")) { |
||||
|
Sleep(60000); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
(void)known_bp(argc); |
||||
|
|
||||
|
for (i=0; i<argc; 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) |
||||
|
#else |
||||
|
if ((pipein = open("graycode_in", O_RDONLY)) < 0 || (pipeout = open("graycode_out", O_WRONLY)) < 0) |
||||
|
#endif |
||||
|
{ |
||||
|
fprintf(stderr, "Cannot open %s named pipes\n", argv[0]); |
||||
|
return -1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (d_process_init(pipein, pipeout, DIGITAL_IN, DIGITAL_OUT) ) { |
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
while(_read(pipein, &in, sizeof(in)) == sizeof(in)) { |
||||
|
#else |
||||
|
while(read(pipein, &in, sizeof(in)) == sizeof(in)) { |
||||
|
#endif |
||||
|
|
||||
|
if (!compute(out.dout, outlen, in.time)) { |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
_write(pipeout, &out, sizeof(out)); |
||||
|
#else |
||||
|
write(pipeout, &out, sizeof(out)); |
||||
|
#endif |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
static int compute(uint8_t *dataout, int outsz, double time) |
||||
|
{ |
||||
|
static uint8_t count = 0; |
||||
|
if (count < 15) { |
||||
|
count++; |
||||
|
} else { |
||||
|
count = 0; |
||||
|
} |
||||
|
dataout[0] = (count ^ (count >> 1)) & 0x0F; |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,10 @@ |
|||||
|
# tcl script for gtkwave: show vcd file data created by ngspice |
||||
|
set nfacs [ gtkwave::getNumFacs ] |
||||
|
|
||||
|
for {set i 0} {$i < $nfacs } {incr i} { |
||||
|
set facname [ gtkwave::getFacName $i ] |
||||
|
set num_added [ gtkwave::addSignalsFromList $facname ] |
||||
|
} |
||||
|
|
||||
|
gtkwave::/Edit/UnHighlight_All |
||||
|
gtkwave::/Time/Zoom/Zoom_Full |
||||
@ -0,0 +1,40 @@ |
|||||
|
prog-pipes.cir |
||||
|
|
||||
|
*** analysis type *** |
||||
|
.tran .01us 10us |
||||
|
v1 1 0 DC 1.0 |
||||
|
v2 2 0 DC 0.0 |
||||
|
|
||||
|
.model d_osc1 d_osc (cntl_array=[-1.0 0.0 1.0 2.0] |
||||
|
+ freq_array=[1.0e6 1.0e6 4.0e6 4.0e6] |
||||
|
+ rise_delay=1.0e-6 fall_delay=2.0e-6) |
||||
|
|
||||
|
a1 1 clk1 d_osc1 |
||||
|
a2 2 clk2 d_osc1 |
||||
|
|
||||
|
ap0_4 null clk1 null [q1 q2 q3 q4] proc0 |
||||
|
.model proc0 d_process (process_file="graycode|" process_params=["--pipe"]) |
||||
|
|
||||
|
ap1_4 [clk2] clk1 null [o1 o2 o3 o4] proc1 |
||||
|
.model proc1 d_process (process_file="prog1in4out" process_params=["opt1", "qwerty"]) |
||||
|
|
||||
|
ap4_1 [o1 o2 o3 o4] clk1 null [zeros] proc2 |
||||
|
.model proc2 d_process (process_file="prog4in1out" process_params=["abc", "99"]) |
||||
|
|
||||
|
ap4_1a [q1 q2 q3 q4] clk1 null [qzeros] proc3 |
||||
|
.model proc3 d_process (process_file="prog4in1out") |
||||
|
|
||||
|
.control |
||||
|
run |
||||
|
edisplay |
||||
|
eprvcd clk1 clk2 o1 o2 o3 o4 q1 q2 q3 q4 zeros qzeros > prog1-4.vcd |
||||
|
shell gtkwave prog1-4.vcd --script nggtk.tcl & |
||||
|
* quit |
||||
|
.endc |
||||
|
.end |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
@ -0,0 +1,46 @@ |
|||||
|
prog1-4.cir |
||||
|
|
||||
|
*** analysis type *** |
||||
|
.tran .01us 10us |
||||
|
v1 1 0 DC 1.0 |
||||
|
v2 2 0 DC 0.0 |
||||
|
|
||||
|
.model d_osc1 d_osc (cntl_array=[-1.0 0.0 1.0 2.0] |
||||
|
+ freq_array=[1.0e6 1.0e6 4.0e6 4.0e6] |
||||
|
+ rise_delay=1.0e-6 fall_delay=2.0e-6) |
||||
|
|
||||
|
a1 1 clk1 d_osc1 |
||||
|
a2 2 clk2 d_osc1 |
||||
|
|
||||
|
ap0_4 null clk1 null [q1 q2 q3 q4] proc0 |
||||
|
.model proc0 d_process (process_file="graycode" process_params=["none"]) |
||||
|
|
||||
|
ap1_4 [clk2] clk1 null [o1 o2 o3 o4] proc1 |
||||
|
.model proc1 d_process (process_file="prog1in4out" process_params=["opt1", "qwerty"]) |
||||
|
|
||||
|
ap4_1 [o1 o2 o3 o4] clk1 null [zeros] proc2 |
||||
|
.model proc2 d_process (process_file="prog4in1out" process_params=["abc", "99"]) |
||||
|
|
||||
|
ap4_1a [q1 q2 q3 q4] clk1 null [qzeros] proc3 |
||||
|
.model proc3 d_process (process_file="prog4in1out") |
||||
|
|
||||
|
an1 [o1 ~o2 o3] reseto dand1 |
||||
|
.model dand1 d_and(inertial_delay=true rise_delay=1ns fall_delay=50ns) |
||||
|
|
||||
|
ap1_4a [clk2] clk1 reseto [b1 b2 b3 b4] proc4 |
||||
|
.model proc4 d_process (process_file="prog1in4out") |
||||
|
|
||||
|
.control |
||||
|
run |
||||
|
edisplay |
||||
|
eprvcd clk1 clk2 o1 o2 o3 o4 q1 q2 q3 q4 b1 b2 b3 b4 zeros qzeros reseto > prog1-4.vcd |
||||
|
shell gtkwave prog1-4.vcd --script nggtk.tcl & |
||||
|
quit |
||||
|
.endc |
||||
|
.end |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
@ -0,0 +1,136 @@ |
|||||
|
/* |
||||
|
The organization of this file is modelled after the motorforce example |
||||
|
developed by Uros Platise. |
||||
|
*/ |
||||
|
#include <string.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <fcntl.h> |
||||
|
#if !defined(_MSC_VER) && !defined(__MINGW64__) |
||||
|
#include <unistd.h> |
||||
|
#endif |
||||
|
#if defined(_MSC_VER) |
||||
|
#include <io.h> |
||||
|
#include <process.h> |
||||
|
#include <Windows.h> |
||||
|
#endif |
||||
|
#include "d_process.h" |
||||
|
|
||||
|
#define DIGITAL_IN 1 |
||||
|
#define DIGITAL_OUT 4 |
||||
|
|
||||
|
static int compute( |
||||
|
uint8_t *datain, int insz, uint8_t *dataout, int outsz, double time |
||||
|
); |
||||
|
|
||||
|
static int known_bp(int iargc) |
||||
|
{ |
||||
|
return iargc; |
||||
|
} |
||||
|
|
||||
|
int main(int argc, char *argv[]) { |
||||
|
int i; |
||||
|
int inlen = D_PROCESS_DLEN(DIGITAL_IN); |
||||
|
int outlen = D_PROCESS_DLEN(DIGITAL_OUT); |
||||
|
|
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
#pragma pack(push, 1) |
||||
|
struct in_s { |
||||
|
double time; |
||||
|
uint8_t din[D_PROCESS_DLEN(DIGITAL_IN)]; |
||||
|
} in; |
||||
|
|
||||
|
struct out_s { |
||||
|
uint8_t dout[D_PROCESS_DLEN(DIGITAL_OUT)]; |
||||
|
} out; |
||||
|
#pragma pack(pop) |
||||
|
#else |
||||
|
struct in_s { |
||||
|
double time; |
||||
|
uint8_t din[D_PROCESS_DLEN(DIGITAL_IN)]; |
||||
|
} __attribute__((packed)) in; |
||||
|
|
||||
|
struct out_s { |
||||
|
uint8_t dout[D_PROCESS_DLEN(DIGITAL_OUT)]; |
||||
|
} __attribute__((packed)) out; |
||||
|
#endif |
||||
|
|
||||
|
int pipein = 0; // default stdin to recv from ngspice |
||||
|
int pipeout= 1; // default stdout to send to ngspice |
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
_setmode(0, _O_BINARY); |
||||
|
_setmode(1, _O_BINARY); |
||||
|
#endif |
||||
|
|
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
fprintf(stderr, "%s pid %d\n", argv[0], _getpid()); |
||||
|
#else |
||||
|
fprintf(stderr, "%s pid %d\n", argv[0], getpid()); |
||||
|
#endif |
||||
|
|
||||
|
#if !defined(_MSC_VER) && !defined(__MINGW64__) |
||||
|
if (getenv("GO_TO_SLEEP")) { |
||||
|
sleep(40); |
||||
|
} |
||||
|
#endif |
||||
|
#if defined(__MINGW64__) |
||||
|
if (getenv("GO_TO_SLEEP")) { |
||||
|
sleep(40); |
||||
|
} |
||||
|
#endif |
||||
|
#if defined(_MSC_VER) |
||||
|
if (getenv("GO_TO_SLEEP")) { |
||||
|
Sleep(60000); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
(void)known_bp(argc); |
||||
|
|
||||
|
for (i=0; i<argc; i++) { |
||||
|
fprintf(stderr, "[%d] %s\n", i, argv[i]); |
||||
|
} |
||||
|
|
||||
|
if (d_process_init(pipein, pipeout, DIGITAL_IN, DIGITAL_OUT) ) { |
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
while(_read(pipein, &in, sizeof(in)) == sizeof(in)) { |
||||
|
#else |
||||
|
while(read(pipein, &in, sizeof(in)) == sizeof(in)) { |
||||
|
#endif |
||||
|
|
||||
|
if (!compute(in.din, inlen, out.dout, outlen, in.time)) { |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
_write(pipeout, &out, sizeof(out)); |
||||
|
#else |
||||
|
write(pipeout, &out, sizeof(out)); |
||||
|
#endif |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
static int compute( |
||||
|
uint8_t *datain, int insz, uint8_t *dataout, int outsz, double time |
||||
|
) |
||||
|
{ |
||||
|
static uint8_t next[2][16] = { |
||||
|
{15, 14, 0, 1, 13, 12, 2, 3, 11, 10, 4, 5, 9, 8, 6, 7}, |
||||
|
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0} |
||||
|
}; |
||||
|
uint8_t inbit0 = datain[0] & 1; |
||||
|
static uint8_t count = 0; |
||||
|
if (time < 0.0) { |
||||
|
fprintf(stderr, "Reset prog1in4out at time %g\n", -time); |
||||
|
count = 15; |
||||
|
} |
||||
|
if (count < 15) { |
||||
|
count++; |
||||
|
} else { |
||||
|
count = 0; |
||||
|
} |
||||
|
dataout[0] = (next[inbit0][count]) & 0x0F; |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,137 @@ |
|||||
|
/* |
||||
|
The organization of this file is modelled after the motorforce example |
||||
|
developed by Uros Platise. |
||||
|
*/ |
||||
|
#include <string.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <fcntl.h> |
||||
|
#if !defined(_MSC_VER) && !defined(__MINGW64__) |
||||
|
#include <unistd.h> |
||||
|
#endif |
||||
|
#if defined(_MSC_VER) |
||||
|
#include <io.h> |
||||
|
#include <process.h> |
||||
|
#include <Windows.h> |
||||
|
#endif |
||||
|
#include "d_process.h" |
||||
|
|
||||
|
#define DIGITAL_IN 4 |
||||
|
#define DIGITAL_OUT 1 |
||||
|
|
||||
|
static int compute( |
||||
|
uint8_t *datain, int insz, uint8_t *dataout, int outsz, double time |
||||
|
); |
||||
|
|
||||
|
static int known_bp(int iargc) |
||||
|
{ |
||||
|
return iargc; |
||||
|
} |
||||
|
|
||||
|
int main(int argc, char *argv[]) { |
||||
|
int i; |
||||
|
int inlen = D_PROCESS_DLEN(DIGITAL_IN); |
||||
|
int outlen = D_PROCESS_DLEN(DIGITAL_OUT); |
||||
|
|
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
#pragma pack(push, 1) |
||||
|
struct in_s { |
||||
|
double time; |
||||
|
uint8_t din[D_PROCESS_DLEN(DIGITAL_IN)]; |
||||
|
} in; |
||||
|
|
||||
|
struct out_s { |
||||
|
uint8_t dout[D_PROCESS_DLEN(DIGITAL_OUT)]; |
||||
|
} out; |
||||
|
#pragma pack(pop) |
||||
|
#else |
||||
|
struct in_s { |
||||
|
double time; |
||||
|
uint8_t din[D_PROCESS_DLEN(DIGITAL_IN)]; |
||||
|
} __attribute__((packed)) in; |
||||
|
|
||||
|
struct out_s { |
||||
|
uint8_t dout[D_PROCESS_DLEN(DIGITAL_OUT)]; |
||||
|
} __attribute__((packed)) out; |
||||
|
#endif |
||||
|
|
||||
|
int pipein = 0; // default stdin to recv from ngspice |
||||
|
int pipeout= 1; // default stdout to send to ngspice |
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
_setmode(0, _O_BINARY); |
||||
|
_setmode(1, _O_BINARY); |
||||
|
#endif |
||||
|
|
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
fprintf(stderr, "%s pid %d\n", argv[0], _getpid()); |
||||
|
#else |
||||
|
fprintf(stderr, "%s pid %d\n", argv[0], getpid()); |
||||
|
#endif |
||||
|
|
||||
|
#if !defined(_MSC_VER) && !defined(__MINGW64__) |
||||
|
if (getenv("GO_TO_SLEEP")) { |
||||
|
sleep(40); |
||||
|
} |
||||
|
#endif |
||||
|
#if defined(__MINGW64__) |
||||
|
if (getenv("GO_TO_SLEEP")) { |
||||
|
sleep(40); |
||||
|
} |
||||
|
#endif |
||||
|
#if defined(_MSC_VER) |
||||
|
if (getenv("GO_TO_SLEEP")) { |
||||
|
Sleep(60000); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
(void)known_bp(argc); |
||||
|
|
||||
|
for (i=0; i<argc; i++) { |
||||
|
fprintf(stderr, "[%d] %s\n", i, argv[i]); |
||||
|
} |
||||
|
|
||||
|
if (d_process_init(pipein, pipeout, DIGITAL_IN, DIGITAL_OUT) ) { |
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
while(_read(pipein, &in, sizeof(in)) == sizeof(in)) { |
||||
|
#else |
||||
|
while(read(pipein, &in, sizeof(in)) == sizeof(in)) { |
||||
|
#endif |
||||
|
|
||||
|
if (!compute(in.din, inlen, out.dout, outlen, in.time)) { |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
#if defined(_MSC_VER) || defined(__MINGW64__) |
||||
|
_write(pipeout, &out, sizeof(out)); |
||||
|
#else |
||||
|
write(pipeout, &out, sizeof(out)); |
||||
|
#endif |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
static int compute( |
||||
|
uint8_t *datain, int insz, uint8_t *dataout, int outsz, double time |
||||
|
) |
||||
|
{ |
||||
|
uint8_t i0 = 0, zeros = 0; |
||||
|
uint8_t inbyte = datain[0]; |
||||
|
dataout[0] = 0; |
||||
|
i0 = inbyte ^ 0x01; |
||||
|
if (i0) zeros++; |
||||
|
i0 = inbyte ^ 0x02; |
||||
|
if (i0) zeros++; |
||||
|
i0 = inbyte ^ 0x04; |
||||
|
if (i0) zeros++; |
||||
|
i0 = inbyte ^ 0x08; |
||||
|
if (i0) zeros++; |
||||
|
if (zeros == 2 || zeros == 4) { |
||||
|
dataout[0] = 0x01; |
||||
|
} else { |
||||
|
dataout[0] = 0x00; |
||||
|
} |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue