Compare commits
2 Commits
b260b4bc27
...
d5ef8a3660
| Author | SHA1 | Date |
|---|---|---|
|
|
d5ef8a3660 | |
|
|
8e0622434f |
|
|
@ -1428,7 +1428,6 @@ AC_CONFIG_FILES([Makefile
|
|||
src/xspice/mif/Makefile
|
||||
src/xspice/evt/Makefile
|
||||
src/xspice/enh/Makefile
|
||||
src/xspice/ipc/Makefile
|
||||
src/xspice/idn/Makefile
|
||||
src/xspice/verilog/Makefile
|
||||
src/xspice/vhdl/Makefile
|
||||
|
|
|
|||
|
|
@ -163,7 +163,6 @@ ngspice_LDADD += \
|
|||
xspice/mif/libmifxsp.la \
|
||||
xspice/evt/libevtxsp.la \
|
||||
xspice/enh/libenhxsp.la \
|
||||
xspice/ipc/libipcxsp.la \
|
||||
xspice/idn/libidnxsp.la
|
||||
endif
|
||||
ngspice_LDADD += $(XSPICEDLLIBS)
|
||||
|
|
@ -459,7 +458,6 @@ if XSPICE_WANTED
|
|||
libspice_la_LIBADD += \
|
||||
xspice/evt/libevtxsp.la \
|
||||
xspice/enh/libenhxsp.la \
|
||||
xspice/ipc/libipcxsp.la \
|
||||
xspice/idn/libidnxsp.la
|
||||
endif
|
||||
libspice_la_LIBADD += $(XSPICEDLLIBS)
|
||||
|
|
@ -586,7 +584,6 @@ if XSPICE_WANTED
|
|||
libngspice_la_LIBADD += \
|
||||
xspice/evt/libevtxsp.la \
|
||||
xspice/enh/libenhxsp.la \
|
||||
xspice/ipc/libipcxsp.la \
|
||||
xspice/idn/libidnxsp.la
|
||||
endif
|
||||
libngspice_la_LIBADD += $(XSPICEDLLIBS)
|
||||
|
|
|
|||
|
|
@ -244,13 +244,6 @@ inp_list(FILE *file, struct card *deck, struct card *extras, int type)
|
|||
bool useout = (file == cp_out);
|
||||
int i = 1;
|
||||
|
||||
/* gtri - wbk - 03/07/91 - Don't use 'more' type output if ipc enabled */
|
||||
#ifdef XSPICE
|
||||
if (g_ipc.enabled)
|
||||
useout = FALSE;
|
||||
#endif
|
||||
/* gtri - end - 03/07/91 */
|
||||
|
||||
if (useout) {
|
||||
out_init();
|
||||
file = cp_more;
|
||||
|
|
@ -1474,10 +1467,6 @@ inp_dodeck(
|
|||
|
||||
if (dd->error) {
|
||||
char *p, *q;
|
||||
#ifdef XSPICE
|
||||
/* add setting of ipc syntax error flag */
|
||||
g_ipc.syntax_error = IPC_TRUE;
|
||||
#endif
|
||||
p = dd->error;
|
||||
fflush(stdout);
|
||||
do {
|
||||
|
|
|
|||
|
|
@ -1355,53 +1355,24 @@ static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name
|
|||
else {
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - modify - 12/12/90 - wbk - read from mailbox if ipc
|
||||
* enabled */
|
||||
|
||||
/* If IPC is not enabled, do equivalent of what SPICE did before
|
||||
*/
|
||||
if (!g_ipc.enabled) {
|
||||
if (call_depth == 0 && line_count == 0) {
|
||||
line_count++;
|
||||
if (fgets(big_buff, 5000, fp))
|
||||
buffer = copy(big_buff);
|
||||
}
|
||||
else {
|
||||
buffer = readline(fp);
|
||||
if (!buffer)
|
||||
break;
|
||||
}
|
||||
if (call_depth == 0 && line_count == 0) {
|
||||
line_count++;
|
||||
if (fgets(big_buff, 5000, fp))
|
||||
buffer = copy(big_buff);
|
||||
}
|
||||
else {
|
||||
/* else, get the line from the ipc channel. */
|
||||
/* We assume that newlines are not sent by the client */
|
||||
/* so we add them here */
|
||||
char ipc_buffer[1025]; /* Had better be big enough */
|
||||
int ipc_len;
|
||||
Ipc_Status_t ipc_status =
|
||||
ipc_get_line(ipc_buffer, &ipc_len, IPC_WAIT);
|
||||
if (ipc_status == IPC_STATUS_END_OF_DECK) {
|
||||
buffer = NULL;
|
||||
buffer = readline(fp);
|
||||
if (!buffer)
|
||||
break;
|
||||
}
|
||||
else if (ipc_status == IPC_STATUS_OK) {
|
||||
buffer = TMALLOC(char, strlen(ipc_buffer) + 3);
|
||||
strcpy(buffer, ipc_buffer);
|
||||
strcat(buffer, "\n");
|
||||
}
|
||||
else { /* No good way to report this so just die */
|
||||
fprintf(stderr, "Error: IPC status not o.k.\n");
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* gtri - end - 12/12/90 */
|
||||
#else
|
||||
|
||||
buffer = readline(fp);
|
||||
if (!buffer) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,14 +213,6 @@ printres(char *name)
|
|||
called = TRUE;
|
||||
}
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - 12/12/90 - wbk - record cpu time used for ipc */
|
||||
g_ipc.cpu_time = (double) last_msec;
|
||||
g_ipc.cpu_time /= 1000.0;
|
||||
g_ipc.cpu_time += (double) last_sec;
|
||||
/* gtri - end - 12/12/90 */
|
||||
#endif
|
||||
|
||||
yy = TRUE;
|
||||
#else
|
||||
if (!name || eq(name, "totalcputime"))
|
||||
|
|
|
|||
|
|
@ -323,14 +323,6 @@ static int dosim(
|
|||
if (if_sens_run(ft_curckt->ci_ckt, ww, ft_curckt->ci_symtab) == 1) {
|
||||
/* The circuit was interrupted somewhere. */
|
||||
fprintf(cp_err, "%s simulation interrupted\n", what);
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - 12/12/90 - wbk - record error and return errchk */
|
||||
g_ipc.run_error = IPC_TRUE;
|
||||
if (g_ipc.enabled) {
|
||||
ipc_send_errchk();
|
||||
}
|
||||
/* gtri - end - 12/12/90 */
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
ft_curckt->ci_inprogress = FALSE;
|
||||
|
|
@ -342,14 +334,6 @@ static int dosim(
|
|||
if (err == 1) {
|
||||
/* The circuit was interrupted somewhere. */
|
||||
fprintf(cp_err, "%s simulation interrupted\n", what);
|
||||
#ifdef XSPICE
|
||||
/* record error and return errchk */
|
||||
g_ipc.run_error = IPC_TRUE;
|
||||
if (g_ipc.enabled) {
|
||||
ipc_send_errchk();
|
||||
}
|
||||
/* gtri - end - 12/12/90 */
|
||||
#endif
|
||||
err = 0;
|
||||
}
|
||||
else if (err == 2) {
|
||||
|
|
|
|||
|
|
@ -62,16 +62,9 @@ ACan(CKTcircuit* ckt, int restart)
|
|||
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */
|
||||
|
||||
/* Tell the beginPlot routine what mode we're in */
|
||||
g_ipc.anal_type = IPC_ANAL_AC;
|
||||
|
||||
/* Tell the code models what mode we're in */
|
||||
g_mif_info.circuit.anal_type = MIF_DC;
|
||||
g_mif_info.circuit.anal_init = MIF_TRUE;
|
||||
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
/* start at beginning */
|
||||
|
|
@ -152,40 +145,6 @@ ACan(CKTcircuit* ckt, int restart)
|
|||
else
|
||||
fprintf(stdout, "\n Linear circuit, option noopac given: no OP analysis\n");
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff */
|
||||
|
||||
/* Send the operating point results for Mspice compatibility */
|
||||
if (g_ipc.enabled)
|
||||
{
|
||||
/* Call CKTnames to get names of nodes/branches used by
|
||||
BeginPlot */
|
||||
/* Probably should free nameList after this block since
|
||||
called again... */
|
||||
error = CKTnames(ckt, &numNames, &nameList);
|
||||
if (error) return(error);
|
||||
|
||||
/* We have to do a beginPlot here since the data to return is
|
||||
* different for the DCOP than it is for the AC analysis.
|
||||
* Moreover the begin plot has not even been done yet at this
|
||||
* point...
|
||||
*/
|
||||
SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob,
|
||||
ckt->CKTcurJob->JOBname,
|
||||
NULL, IF_REAL,
|
||||
numNames, nameList, IF_REAL,
|
||||
&acPlot);
|
||||
txfree(nameList);
|
||||
|
||||
ipc_send_dcop_prefix();
|
||||
CKTdump(ckt, 0.0, acPlot);
|
||||
ipc_send_dcop_suffix();
|
||||
|
||||
SPfrontEnd->OUTendPlot(acPlot);
|
||||
}
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG;
|
||||
error = CKTload(ckt);
|
||||
if (error) return(error);
|
||||
|
|
@ -376,21 +335,8 @@ ACan(CKTcircuit* ckt, int restart)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
|
||||
|
||||
if (g_ipc.enabled)
|
||||
ipc_send_data_prefix(freq);
|
||||
|
||||
error = CKTacDump(ckt, freq, acPlot);
|
||||
|
||||
if (g_ipc.enabled)
|
||||
ipc_send_data_suffix();
|
||||
|
||||
/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
|
||||
#else
|
||||
error = CKTacDump(ckt, freq, acPlot);
|
||||
#endif
|
||||
if (error) {
|
||||
UPDATE_STATS(DOING_AC);
|
||||
return(error);
|
||||
|
|
|
|||
|
|
@ -157,51 +157,15 @@ CKTdoJob(CKTcircuit* ckt, int reset, TSKtask* task)
|
|||
if (!error)
|
||||
error = CKTunsetup(ckt);
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - 12/12/90 - wbk - set ipc syntax error flag */
|
||||
if (error) g_ipc.syntax_error = IPC_TRUE;
|
||||
/* gtri - end - 12/12/90 */
|
||||
#endif
|
||||
|
||||
if (!error)
|
||||
error = CKTsetup(ckt);
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - 12/12/90 - wbk - set ipc syntax error flag */
|
||||
if (error) g_ipc.syntax_error = IPC_TRUE;
|
||||
/* gtri - end - 12/12/90 */
|
||||
#endif
|
||||
|
||||
if (!error)
|
||||
error = CKTtemp(ckt);
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - 12/12/90 - wbk - set ipc syntax error flag */
|
||||
if (error) g_ipc.syntax_error = IPC_TRUE;
|
||||
/* gtri - end - 12/12/90 */
|
||||
#endif
|
||||
|
||||
if (error) {
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - 12/12/90 - wbk - return if syntax errors from parsing */
|
||||
if (g_ipc.enabled) {
|
||||
if (g_ipc.syntax_error)
|
||||
;
|
||||
else {
|
||||
/* else, send (GO) errchk status if we got this far */
|
||||
/* Caller is responsible for sending NOGO status if we returned earlier */
|
||||
ipc_send_errchk();
|
||||
}
|
||||
}
|
||||
/* gtri - end - 12/12/90 */
|
||||
#endif
|
||||
|
||||
|
||||
return error;
|
||||
|
||||
|
||||
}/* if error */
|
||||
}
|
||||
}
|
||||
|
||||
error2 = OK;
|
||||
|
|
|
|||
|
|
@ -35,18 +35,13 @@ DCop(CKTcircuit *ckt, int notused)
|
|||
NG_IGNORE(notused);
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff and initialize anal_init and anal_type */
|
||||
|
||||
/* Tell the beginPlot routine what mode we're in */
|
||||
g_ipc.anal_type = IPC_ANAL_DCOP;
|
||||
|
||||
/* Tell the code models what mode we're in */
|
||||
g_mif_info.circuit.anal_type = MIF_DC;
|
||||
|
||||
g_mif_info.circuit.anal_init = MIF_TRUE;
|
||||
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
error = CKTnames(ckt,&numNames,&nameList);
|
||||
if(error) return(error);
|
||||
|
|
@ -114,31 +109,17 @@ DCop(CKTcircuit *ckt, int notused)
|
|||
|
||||
}
|
||||
#endif
|
||||
|
||||
converged = CKTload(ckt);
|
||||
#ifdef XSPICE
|
||||
/* gtri - modify - wbk - 12/19/90 - Send IPC data delimiters */
|
||||
|
||||
if(g_ipc.enabled)
|
||||
ipc_send_dcop_prefix();
|
||||
|
||||
CKTdump(ckt, 0.0, plot);
|
||||
|
||||
if (ckt->CKTsoaCheck)
|
||||
error = CKTsoaCheck(ckt);
|
||||
|
||||
if(g_ipc.enabled)
|
||||
ipc_send_dcop_suffix();
|
||||
|
||||
/* gtri - end - wbk */
|
||||
#else
|
||||
if(converged == 0) {
|
||||
CKTdump(ckt, 0.0, plot);
|
||||
if (ckt->CKTsoaCheck)
|
||||
error = CKTsoaCheck(ckt);
|
||||
} else {
|
||||
fprintf(stderr,"error: circuit reload failed.\n");
|
||||
}
|
||||
#endif
|
||||
CKTdump(ckt, 0.0, plot);
|
||||
if (ckt->CKTsoaCheck)
|
||||
error = CKTsoaCheck(ckt);
|
||||
} else {
|
||||
fprintf(stderr,"error: circuit reload failed.\n");
|
||||
}
|
||||
|
||||
SPfrontEnd->OUTendPlot (plot);
|
||||
return(converged);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,15 +84,6 @@ DCpss(CKTcircuit *ckt,
|
|||
|
||||
int ltra_num;
|
||||
CKTnode *node;
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff */
|
||||
Ipc_Boolean_t ipc_firsttime = IPC_TRUE;
|
||||
Ipc_Boolean_t ipc_secondtime = IPC_FALSE;
|
||||
Ipc_Boolean_t ipc_delta_cut = IPC_FALSE;
|
||||
double ipc_last_time = 0.0;
|
||||
double ipc_last_delta = 0.0;
|
||||
/* gtri - end - wbk - 12/19/90 - Add IPC stuff */
|
||||
#endif
|
||||
|
||||
/* New variables */
|
||||
int j, oscnNode;
|
||||
|
|
@ -216,15 +207,12 @@ DCpss(CKTcircuit *ckt,
|
|||
#endif
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff and set anal_init and anal_type */
|
||||
/* Tell the beginPlot routine what mode we're in */
|
||||
g_ipc.anal_type = IPC_ANAL_TRAN;
|
||||
/* set anal_init and anal_type */
|
||||
|
||||
/* Tell the code models what mode we're in */
|
||||
g_mif_info.circuit.anal_type = MIF_DC;
|
||||
|
||||
g_mif_info.circuit.anal_init = MIF_TRUE;
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
/* Time Domain plot start and prepared to be filled in later */
|
||||
|
|
@ -298,35 +286,18 @@ DCpss(CKTcircuit *ckt,
|
|||
#endif
|
||||
|
||||
/* If no convergence reached - NO valid Operating Point */
|
||||
if(converged != 0) return(converged);
|
||||
if(converged != 0)
|
||||
return(converged);
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff */
|
||||
|
||||
/* Send the operating point results for Mspice compatibility */
|
||||
if(g_ipc.enabled) {
|
||||
ipc_send_dcop_prefix();
|
||||
CKTdump(ckt, 0.0, job->PSSplot_td);
|
||||
ipc_send_dcop_suffix();
|
||||
}
|
||||
|
||||
/* gtri - end - wbk */
|
||||
|
||||
/* gtri - add - wbk - 12/19/90 - set anal_init and anal_type */
|
||||
|
||||
g_mif_info.circuit.anal_init = MIF_TRUE;
|
||||
|
||||
/* Tell the code models what mode we're in */
|
||||
g_mif_info.circuit.anal_type = MIF_TRAN;
|
||||
|
||||
/* gtri - end - wbk */
|
||||
|
||||
/* gtri - begin - wbk - Add Breakpoint stuff */
|
||||
|
||||
/* Initialize the temporary breakpoint variables to infinity */
|
||||
g_mif_info.breakpoint.current = HUGE_VAL;
|
||||
g_mif_info.breakpoint.last = HUGE_VAL;
|
||||
|
||||
/* gtri - end - wbk - Add Breakpoint stuff */
|
||||
#endif
|
||||
ckt->CKTstat->STATtimePts ++;
|
||||
|
||||
|
|
@ -434,52 +405,16 @@ DCpss(CKTcircuit *ckt,
|
|||
return(error);
|
||||
}
|
||||
#ifdef XSPICE
|
||||
/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
|
||||
|
||||
if ((g_ipc.enabled) || wantevtdata) {
|
||||
if (wantevtdata) {
|
||||
|
||||
if (pss_state == PSS)
|
||||
{
|
||||
/* Send event-driven results */
|
||||
EVTdump(ckt, IPC_ANAL_TRAN, 0.0);
|
||||
|
||||
/* Then follow with analog results... */
|
||||
|
||||
/* Test to see if delta was cut by a breakpoint, */
|
||||
/* a non-convergence, or a too large truncation error */
|
||||
if(ipc_firsttime)
|
||||
ipc_delta_cut = IPC_FALSE;
|
||||
else if(ckt->CKTtime < (ipc_last_time + (0.999 * ipc_last_delta)))
|
||||
ipc_delta_cut = IPC_TRUE;
|
||||
else
|
||||
ipc_delta_cut = IPC_FALSE;
|
||||
|
||||
/* Record the data required to check for delta cuts */
|
||||
ipc_last_time = ckt->CKTtime;
|
||||
ipc_last_delta = MIN(ckt->CKTdelta, ckt->CKTmaxStep);
|
||||
|
||||
/* Send results data if time since last dump is greater */
|
||||
/* than 'mintime', or if first or second timepoints, */
|
||||
/* or if delta was cut */
|
||||
if( (ckt->CKTtime >= (g_ipc.mintime + g_ipc.last_time)) ||
|
||||
ipc_firsttime || ipc_secondtime || ipc_delta_cut ) {
|
||||
|
||||
ipc_send_data_prefix(ckt->CKTtime);
|
||||
CKTdump(ckt, ckt->CKTtime, job->PSSplot_td);
|
||||
ipc_send_data_suffix();
|
||||
|
||||
if(ipc_firsttime) {
|
||||
ipc_firsttime = IPC_FALSE;
|
||||
ipc_secondtime = IPC_TRUE;
|
||||
} else if(ipc_secondtime) {
|
||||
ipc_secondtime = IPC_FALSE;
|
||||
}
|
||||
|
||||
g_ipc.last_time = ckt->CKTtime;
|
||||
}
|
||||
/* Send event-driven results */
|
||||
EVTdump(ckt, IPC_ANAL_TRAN, 0.0);
|
||||
}
|
||||
} else
|
||||
/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
|
||||
|
||||
#endif
|
||||
|
||||
if (pss_state == PSS)
|
||||
|
|
|
|||
|
|
@ -99,13 +99,6 @@ DCtran(CKTcircuit *ckt,
|
|||
int ltra_num;
|
||||
CKTnode *node;
|
||||
#ifdef XSPICE
|
||||
/* IPC stuff */
|
||||
Ipc_Boolean_t ipc_firsttime = IPC_TRUE;
|
||||
Ipc_Boolean_t ipc_secondtime = IPC_FALSE;
|
||||
Ipc_Boolean_t ipc_delta_cut = IPC_FALSE;
|
||||
double ipc_last_time = 0.0;
|
||||
double ipc_last_delta = 0.0;
|
||||
|
||||
/* xspice_breakpoints_processed 0:
|
||||
XSPICE models didn't have breakpoints in [last_accepted_time, CKTtime].
|
||||
xspice_breakpoints_processed 1:
|
||||
|
|
@ -176,13 +169,9 @@ DCtran(CKTcircuit *ckt,
|
|||
#endif
|
||||
|
||||
#ifdef XSPICE
|
||||
/* Add IPC stuff and set anal_init and anal_type */
|
||||
/* Tell the beginPlot routine what mode we're in */
|
||||
g_ipc.anal_type = IPC_ANAL_TRAN;
|
||||
|
||||
/* set anal_init and anal_type */
|
||||
/* Tell the code models what mode we're in */
|
||||
g_mif_info.circuit.anal_type = MIF_DC;
|
||||
|
||||
g_mif_info.circuit.anal_init = MIF_TRUE;
|
||||
#endif
|
||||
/* Scan ckt->CKTnodes and create list of node names */
|
||||
|
|
@ -279,13 +268,6 @@ DCtran(CKTcircuit *ckt,
|
|||
return(converged);
|
||||
}
|
||||
#ifdef XSPICE
|
||||
/* IPC stuff: Send the operating point results */
|
||||
if(g_ipc.enabled) {
|
||||
ipc_send_dcop_prefix();
|
||||
CKTdump(ckt, 0.0, job->TRANplot);
|
||||
ipc_send_dcop_suffix();
|
||||
}
|
||||
|
||||
/* set anal_init and anal_type */
|
||||
g_mif_info.circuit.anal_init = MIF_TRUE;
|
||||
|
||||
|
|
@ -420,59 +402,21 @@ DCtran(CKTcircuit *ckt,
|
|||
UPDATE_STATS(DOING_TRAN);
|
||||
return(error);
|
||||
}
|
||||
|
||||
#ifdef XSPICE
|
||||
|
||||
/* Send IPC stuff */
|
||||
if ((g_ipc.enabled) || wantevtdata) {
|
||||
|
||||
/* Send evt data stuff in shared library */
|
||||
if (wantevtdata) {
|
||||
/* Send event-driven results */
|
||||
EVTdump(ckt, IPC_ANAL_TRAN, 0.0);
|
||||
|
||||
/* Then follow with analog results... */
|
||||
|
||||
/* Test to see if delta was cut by a breakpoint, */
|
||||
/* a non-convergence, or a too large truncation error */
|
||||
if(ipc_firsttime)
|
||||
ipc_delta_cut = IPC_FALSE;
|
||||
else if(ckt->CKTtime < (ipc_last_time + (0.999 * ipc_last_delta)))
|
||||
ipc_delta_cut = IPC_TRUE;
|
||||
else
|
||||
ipc_delta_cut = IPC_FALSE;
|
||||
|
||||
/* Record the data required to check for delta cuts */
|
||||
ipc_last_time = ckt->CKTtime;
|
||||
ipc_last_delta = MIN(ckt->CKTdelta, ckt->CKTmaxStep);
|
||||
|
||||
/* Send results data if time since last dump is greater */
|
||||
/* than 'mintime', or if first or second timepoints, */
|
||||
/* or if delta was cut */
|
||||
if( (ckt->CKTtime >= (g_ipc.mintime + g_ipc.last_time)) ||
|
||||
ipc_firsttime || ipc_secondtime || ipc_delta_cut ) {
|
||||
|
||||
if (wantevtdata)
|
||||
CKTdump(ckt, ckt->CKTtime, job->TRANplot);
|
||||
else {
|
||||
ipc_send_data_prefix(ckt->CKTtime);
|
||||
CKTdump(ckt, ckt->CKTtime, job->TRANplot);
|
||||
ipc_send_data_suffix();
|
||||
}
|
||||
|
||||
if(ipc_firsttime) {
|
||||
ipc_firsttime = IPC_FALSE;
|
||||
ipc_secondtime = IPC_TRUE;
|
||||
} else if(ipc_secondtime) {
|
||||
ipc_secondtime = IPC_FALSE;
|
||||
}
|
||||
|
||||
g_ipc.last_time = ckt->CKTtime;
|
||||
}
|
||||
/* End of Send IPC stuff*/
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
/* Output the data of the current accepted time point */
|
||||
if((ckt->CKTmode&MODEUIC && ckt->CKTtime > 0 && ckt->CKTtime >= ckt->CKTinitTime)
|
||||
|| (!(ckt->CKTmode&MODEUIC) && ckt->CKTtime >= ckt->CKTinitTime))
|
||||
CKTdump(ckt, ckt->CKTtime, job->TRANplot);
|
||||
|
||||
/* Output the data of the current accepted time point */
|
||||
if ((ckt->CKTmode & MODEUIC && ckt->CKTtime > 0 && ckt->CKTtime >= ckt->CKTinitTime)
|
||||
|| (!(ckt->CKTmode & MODEUIC) && ckt->CKTtime >= ckt->CKTinitTime)) {
|
||||
CKTdump(ckt, ckt->CKTtime, job->TRANplot);
|
||||
}
|
||||
#ifdef XSPICE
|
||||
/* Update event queues/data for accepted timepoint */
|
||||
/* Note: this must be done AFTER sending results to SI so it can't
|
||||
|
|
|
|||
|
|
@ -165,17 +165,12 @@ DCtrCurv(CKTcircuit *ckt, int restart)
|
|||
#endif
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */
|
||||
|
||||
/* Tell the beginPlot routine what mode we're in */
|
||||
g_ipc.anal_type = IPC_ANAL_DCTRCURVE;
|
||||
|
||||
/* Tell the code models what mode we're in */
|
||||
g_mif_info.circuit.anal_type = MIF_DC;
|
||||
|
||||
g_mif_info.circuit.anal_init = MIF_TRUE;
|
||||
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
error = CKTnames(ckt, &numNames, &nameList);
|
||||
|
|
@ -383,18 +378,10 @@ DCtrCurv(CKTcircuit *ckt, int restart)
|
|||
ckt->CKTtime = ckt->CKTtemp - CONSTCtoK;
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff */
|
||||
|
||||
/* If first time through, call CKTdump to output Operating Point info */
|
||||
/* for Mspice compatibility */
|
||||
|
||||
if (((g_ipc.enabled) || wantevtdata) && firstTime) {
|
||||
ipc_send_dcop_prefix();
|
||||
if (wantevtdata && firstTime) {
|
||||
CKTdump(ckt, 0.0, plot);
|
||||
ipc_send_dcop_suffix();
|
||||
}
|
||||
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
#ifdef WANT_SENSE2
|
||||
|
|
@ -435,25 +422,11 @@ DCtrCurv(CKTcircuit *ckt, int restart)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - modify - wbk - 12/19/90 - Send IPC delimiters */
|
||||
|
||||
if (g_ipc.enabled)
|
||||
ipc_send_data_prefix(ckt->CKTtime);
|
||||
#endif
|
||||
|
||||
CKTdump(ckt,ckt->CKTtime,plot);
|
||||
|
||||
if (ckt->CKTsoaCheck)
|
||||
error = CKTsoaCheck(ckt);
|
||||
|
||||
#ifdef XSPICE
|
||||
if (g_ipc.enabled)
|
||||
ipc_send_data_suffix();
|
||||
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
if (ckt->CKTstate1 && ckt->CKTstate0) {
|
||||
|
|
|
|||
|
|
@ -65,16 +65,9 @@ NOISEan(CKTcircuit* ckt, int restart)
|
|||
runDesc* plot = NULL;
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */
|
||||
|
||||
/* Tell the beginPlot routine what mode we're in */
|
||||
g_ipc.anal_type = IPC_ANAL_NOI;
|
||||
|
||||
/* Tell the code models what mode we're in */
|
||||
g_mif_info.circuit.anal_type = MIF_DC;
|
||||
g_mif_info.circuit.anal_init = MIF_TRUE;
|
||||
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
#ifdef KLU
|
||||
|
|
@ -193,15 +186,15 @@ NOISEan(CKTcircuit* ckt, int restart)
|
|||
#endif
|
||||
|
||||
#ifdef KLU
|
||||
if (ckt->CKTmatrix->CKTkluMODE)
|
||||
{
|
||||
/* Conversion from Complex Matrix to Real Matrix */
|
||||
for (i = 0 ; i < DEVmaxnum ; i++)
|
||||
if (DEVices [i] && DEVices [i]->DEVbindCSCComplexToReal && ckt->CKThead [i])
|
||||
DEVices [i]->DEVbindCSCComplexToReal (ckt->CKThead [i], ckt) ;
|
||||
if (ckt->CKTmatrix->CKTkluMODE)
|
||||
{
|
||||
/* Conversion from Complex Matrix to Real Matrix */
|
||||
for (i = 0 ; i < DEVmaxnum ; i++)
|
||||
if (DEVices [i] && DEVices [i]->DEVbindCSCComplexToReal && ckt->CKThead [i])
|
||||
DEVices [i]->DEVbindCSCComplexToReal (ckt->CKThead [i], ckt) ;
|
||||
|
||||
ckt->CKTmatrix->SMPkluMatrix->KLUmatrixIsComplex = KLUmatrixReal ;
|
||||
}
|
||||
ckt->CKTmatrix->SMPkluMatrix->KLUmatrixIsComplex = KLUmatrixReal ;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If no event-driven instances, do what SPICE normally does */
|
||||
|
|
@ -220,43 +213,8 @@ NOISEan(CKTcircuit* ckt, int restart)
|
|||
else {
|
||||
fprintf(stdout, "\n Linear circuit, option noopac given: no OP analysis\n");
|
||||
}
|
||||
|
||||
#ifdef XSPICE
|
||||
} // end of no XSPICE event-driven instances
|
||||
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff */
|
||||
|
||||
/* Send the operating point results for Mspice compatibility */
|
||||
if (g_ipc.enabled)
|
||||
{
|
||||
/* Call CKTnames to get names of nodes/branches used by
|
||||
BeginPlot */
|
||||
/* Probably should free nameList after this block since
|
||||
called again... */
|
||||
error = CKTnames(ckt, &numNames, &nameList);
|
||||
if (error) return(error);
|
||||
|
||||
/* We have to do a beginPlot here since the data to return is
|
||||
* different for the DCOP than it is for the AC analysis.
|
||||
* Moreover the begin plot has not even been done yet at this
|
||||
* point...
|
||||
*/
|
||||
SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob,
|
||||
ckt->CKTcurJob->JOBname,
|
||||
NULL, IF_REAL,
|
||||
numNames, nameList, IF_REAL,
|
||||
&noiPlot);
|
||||
txfree(nameList);
|
||||
|
||||
ipc_send_dcop_prefix();
|
||||
CKTdump(ckt, 0.0, noiPlot);
|
||||
ipc_send_dcop_suffix();
|
||||
|
||||
SPfrontEnd->OUTendPlot(noiPlot);
|
||||
}
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
/* Patch to noisean.c by Richard D. McRoberts. */
|
||||
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG;
|
||||
error = CKTload(ckt);
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ static bool nooptran = TRUE;
|
|||
we firstly fill the static vars opstepsize, opfinaltime,
|
||||
and opramptime. Later from inp.c we call com_optran again and set the
|
||||
data in ft_curckt->ci_defTask.
|
||||
|
||||
com_optran is called from cp_init() as 'optran 1 1 1 100n 10u 0'.
|
||||
*/
|
||||
void com_optran(wordlist* wl) {
|
||||
wordlist* wltmp = wl;
|
||||
|
|
@ -177,8 +179,10 @@ void com_optran(wordlist* wl) {
|
|||
goto bugquit;
|
||||
}
|
||||
/* optran deselected by setting opstepsize to 0 */
|
||||
if (opstepsize == 0)
|
||||
if (opstepsize == 0) {
|
||||
nooptran = TRUE;
|
||||
fprintf(stdout, "Note: Optran is deselected");
|
||||
}
|
||||
|
||||
dataset = TRUE;
|
||||
if (errno == 0)
|
||||
|
|
@ -311,8 +315,8 @@ OPtran(CKTcircuit *ckt, int oldconverged)
|
|||
int redostep;
|
||||
#endif
|
||||
|
||||
/* if optran command has not been given (in .spiceinit or in .control section),
|
||||
we don' use optran */
|
||||
/* if optran command with step size 0 has been set in in .spiceinit or in .control section,
|
||||
we don't use optran */
|
||||
if (nooptran)
|
||||
return oldconverged;
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -386,18 +386,9 @@ SPan(CKTcircuit* ckt, int restart)
|
|||
}
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */
|
||||
|
||||
/* Tell the beginPlot routine what mode we're in */
|
||||
|
||||
// For now, let's keep this as IPC_ANAL_AC (TBD)
|
||||
g_ipc.anal_type = IPC_ANAL_AC;
|
||||
|
||||
/* Tell the code models what mode we're in */
|
||||
g_mif_info.circuit.anal_type = MIF_DC;
|
||||
g_mif_info.circuit.anal_init = MIF_TRUE;
|
||||
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
/* start at beginning */
|
||||
|
|
@ -475,40 +466,6 @@ SPan(CKTcircuit* ckt, int restart)
|
|||
else
|
||||
fprintf(stdout, "\n Linear circuit, option noopac given: no OP analysis\n");
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff */
|
||||
|
||||
/* Send the operating point results for Mspice compatibility */
|
||||
if (g_ipc.enabled)
|
||||
{
|
||||
/* Call CKTnames to get names of nodes/branches used by
|
||||
BeginPlot */
|
||||
/* Probably should free nameList after this block since
|
||||
called again... */
|
||||
error = CKTnames(ckt, &numNames, &nameList);
|
||||
if (error) return(error);
|
||||
|
||||
/* We have to do a beginPlot here since the data to return is
|
||||
* different for the DCOP than it is for the AC analysis.
|
||||
* Moreover the begin plot has not even been done yet at this
|
||||
* point...
|
||||
*/
|
||||
SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob,
|
||||
ckt->CKTcurJob->JOBname,
|
||||
NULL, IF_REAL,
|
||||
numNames, nameList, IF_REAL,
|
||||
&spPlot);
|
||||
txfree(nameList);
|
||||
|
||||
ipc_send_dcop_prefix();
|
||||
CKTdump(ckt, 0.0, spPlot);
|
||||
ipc_send_dcop_suffix();
|
||||
|
||||
SPfrontEnd->OUTendPlot(spPlot);
|
||||
}
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG;
|
||||
error = CKTload(ckt);
|
||||
if (error) return(error);
|
||||
|
|
@ -937,22 +894,8 @@ SPan(CKTcircuit* ckt, int restart)
|
|||
data->lstFreq = freq;
|
||||
}
|
||||
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
|
||||
|
||||
if (g_ipc.enabled)
|
||||
ipc_send_data_prefix(freq);
|
||||
|
||||
error = CKTspDump(ckt, freq, spPlot, job->SPdoNoise);
|
||||
|
||||
if (g_ipc.enabled)
|
||||
ipc_send_data_suffix();
|
||||
|
||||
/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
|
||||
#else
|
||||
error = CKTspDump(ckt, freq, spPlot, job->SPdoNoise);
|
||||
#endif
|
||||
if (error) {
|
||||
UPDATE_STATS(DOING_AC);
|
||||
tfree(internalNoiseAN);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ EXTRA_DIST = README examples icm xspice.c .gitignore \
|
|||
tlines/msline_common.c tlines/msline_common.h \
|
||||
tlines/tline_common.c tlines/tline_common.h
|
||||
|
||||
SUBDIRS = mif cm enh evt ipc idn cmpp icm verilog vhdl
|
||||
SUBDIRS = mif cm enh evt idn cmpp icm verilog vhdl
|
||||
|
||||
dist-hook:
|
||||
rm -f "$(distdir)/icm/makedefs"
|
||||
|
|
|
|||
|
|
@ -53,10 +53,6 @@ NON-STANDARD FEATURES
|
|||
#include "ngspice/evtproto.h"
|
||||
#include "ngspice/evtudn.h"
|
||||
|
||||
#include "ngspice/ipc.h"
|
||||
#include "ngspice/ipctiein.h"
|
||||
#include "ngspice/ipcproto.h"
|
||||
|
||||
#ifdef SHARED_MODULE
|
||||
/* global flag, TRUE if callback is used */
|
||||
extern bool wantevtdata;
|
||||
|
|
@ -76,13 +72,6 @@ static void EVTsharedsend_line(
|
|||
int mode); /* mode (op, dc, tran) we are in */
|
||||
#endif
|
||||
|
||||
static void EVTsend_line(
|
||||
int ipc_index, /* The index used in the dictionary */
|
||||
double step, /* The analysis step */
|
||||
void *node_value, /* The node value */
|
||||
int udn_index); /* The user-defined node index */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
EVTdump
|
||||
|
|
@ -129,250 +118,25 @@ void EVTdump(
|
|||
double step) /* The sweep step for a DCTRCURVE analysis, or */
|
||||
/* 0.0 for DCOP and TRAN */
|
||||
{
|
||||
static evtdump_dict_t *node_dict = NULL;
|
||||
static int num_send_nodes;
|
||||
|
||||
int i;
|
||||
int j;
|
||||
int num_nodes;
|
||||
int num_modified;
|
||||
int index;
|
||||
|
||||
char *name;
|
||||
int name_len;
|
||||
|
||||
Mif_Boolean_t firstcall;
|
||||
|
||||
Evt_Node_Data_t *node_data;
|
||||
|
||||
Evt_Node_t *rhsold;
|
||||
Evt_Node_t **head;
|
||||
Evt_Node_t *here;
|
||||
|
||||
Evt_Node_Info_t **node_table;
|
||||
|
||||
char buff[10000];
|
||||
|
||||
Mif_Boolean_t equal;
|
||||
|
||||
#ifdef SHARED_MODULE
|
||||
if((! g_ipc.enabled) && (!wantevtdata))
|
||||
if (!wantevtdata)
|
||||
return;
|
||||
if ((!g_ipc.enabled) && (wantevtdata)) {
|
||||
else {
|
||||
EVTshareddump(ckt, mode, step);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
/* Return immediately if IPC is not enabled */
|
||||
if(! g_ipc.enabled)
|
||||
return;
|
||||
(void)*ckt;
|
||||
(void)mode;
|
||||
(void)step;
|
||||
|
||||
/* Return immediately */
|
||||
return;
|
||||
#endif
|
||||
/* Get number of event-driven nodes */
|
||||
num_nodes = ckt->evt->counts.num_nodes;
|
||||
|
||||
/* Exit immediately if no event-driven nodes in circuit */
|
||||
if(num_nodes <= 0)
|
||||
return;
|
||||
|
||||
|
||||
/* Get pointers for fast access to event data */
|
||||
node_data = ckt->evt->data.node;
|
||||
node_table = ckt->evt->info.node_table;
|
||||
rhsold = node_data->rhsold;
|
||||
head = node_data->head;
|
||||
|
||||
|
||||
/* Determine if this is the first call */
|
||||
if(node_dict == NULL)
|
||||
firstcall = MIF_TRUE;
|
||||
else
|
||||
firstcall = MIF_FALSE;
|
||||
|
||||
|
||||
/* If this is the first call, get the dictionary info */
|
||||
if(firstcall) {
|
||||
|
||||
/* Allocate local data structure used to process nodes */
|
||||
node_dict = TMALLOC(evtdump_dict_t, num_nodes);
|
||||
|
||||
/* Loop through all nodes to determine which nodes should be sent. */
|
||||
/* Only nodes not within subcircuits qualify. */
|
||||
|
||||
num_send_nodes = 0;
|
||||
for(i = 0; i < num_nodes; i++) {
|
||||
|
||||
/* Get the name of the node. */
|
||||
name = node_table[i]->name;
|
||||
|
||||
/* If name is in a subcircuit, mark that node should not be sent */
|
||||
/* and continue to next node. */
|
||||
name_len = (int) strlen(name);
|
||||
for(j = 0; j < name_len; j++) {
|
||||
if(name[j] == ':')
|
||||
break;
|
||||
}
|
||||
if(j < name_len) {
|
||||
node_dict[i].send = MIF_FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Otherwise, fill in info in dictionary. */
|
||||
node_dict[i].send = MIF_TRUE;
|
||||
node_dict[i].ipc_index = num_send_nodes;
|
||||
node_dict[i].node_name_str = name;
|
||||
node_dict[i].udn_type_str = g_evt_udn_info[node_table[i]->udn_index]->name;
|
||||
|
||||
/* Increment the count of nodes to be sent. */
|
||||
num_send_nodes++;
|
||||
} /* end for */
|
||||
} /* end if first call */
|
||||
|
||||
|
||||
/* Exit if there are no nodes to be sent */
|
||||
if(num_send_nodes <= 0)
|
||||
return;
|
||||
|
||||
|
||||
/* If this is the first call, send the dictionary */
|
||||
if(firstcall) {
|
||||
ipc_send_evtdict_prefix();
|
||||
for(i = 0; i < num_nodes; i++) {
|
||||
if(node_dict[i].send) {
|
||||
sprintf(buff, "%d %s %s", node_dict[i].ipc_index,
|
||||
node_dict[i].node_name_str,
|
||||
node_dict[i].udn_type_str);
|
||||
ipc_send_line(buff);
|
||||
}
|
||||
}
|
||||
ipc_send_evtdict_suffix();
|
||||
}
|
||||
|
||||
/* If this is the first call, send the operating point solution */
|
||||
/* and return. */
|
||||
if(firstcall) {
|
||||
ipc_send_evtdata_prefix();
|
||||
for(i = 0; i < num_nodes; i++) {
|
||||
if(node_dict[i].send) {
|
||||
EVTsend_line(node_dict[i].ipc_index,
|
||||
step,
|
||||
rhsold[i].node_value,
|
||||
node_table[i]->udn_index);
|
||||
}
|
||||
}
|
||||
ipc_send_evtdata_suffix();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise, this must be DCTRCURVE or TRAN mode and we need to */
|
||||
/* send only stuff that has changed since the last call. */
|
||||
/* The determination of what to send is modeled after code in */
|
||||
/* EVTop_save() for DCTRCURVE and EVTaccept() for TRAN. */
|
||||
|
||||
if(mode == IPC_ANAL_DCTRCURVE) {
|
||||
/* Send data prefix */
|
||||
ipc_send_evtdata_prefix();
|
||||
/* Loop through event nodes */
|
||||
for(i = 0; i < num_nodes; i++) {
|
||||
/* If dictionary indicates this node should be sent */
|
||||
if(node_dict[i].send) {
|
||||
/* Locate end of node data */
|
||||
here = head[i];
|
||||
for(;;) {
|
||||
if(here->next)
|
||||
here = here->next;
|
||||
else
|
||||
break;
|
||||
}
|
||||
/* Compare entry at end of list to rhsold */
|
||||
g_evt_udn_info[node_table[i]->udn_index]->compare (
|
||||
rhsold[i].node_value,
|
||||
here->node_value,
|
||||
&equal);
|
||||
/* If value in rhsold is different, send it */
|
||||
if(!equal) {
|
||||
EVTsend_line(node_dict[i].ipc_index,
|
||||
step,
|
||||
rhsold[i].node_value,
|
||||
node_table[i]->udn_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Send data suffix and return */
|
||||
ipc_send_evtdata_suffix();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(mode == IPC_ANAL_TRAN) {
|
||||
/* Send data prefix */
|
||||
ipc_send_evtdata_prefix();
|
||||
/* Loop through list of nodes modified since last time */
|
||||
num_modified = node_data->num_modified;
|
||||
for(i = 0; i < num_modified; i++) {
|
||||
/* Get the index of the node modified */
|
||||
index = node_data->modified_index[i];
|
||||
/* If dictionary indicates this node should be sent */
|
||||
if(node_dict[index].send) {
|
||||
/* Scan through new events and send the data for each event */
|
||||
here = *(node_data->last_step[index]);
|
||||
while((here = here->next) != NULL) {
|
||||
EVTsend_line(node_dict[index].ipc_index,
|
||||
here->step,
|
||||
here->node_value,
|
||||
node_table[index]->udn_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Send data suffix and return */
|
||||
ipc_send_evtdata_suffix();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
EVTsend_line
|
||||
|
||||
This function formats the event node data and sends it to the IPC channel.
|
||||
*/
|
||||
|
||||
|
||||
static void EVTsend_line(
|
||||
int ipc_index, /* The index used in the dictionary */
|
||||
double step, /* The analysis step */
|
||||
void *node_value, /* The node value */
|
||||
int udn_index) /* The user-defined node index */
|
||||
{
|
||||
double dvalue;
|
||||
char *svalue;
|
||||
void *pvalue;
|
||||
int len;
|
||||
|
||||
/* Get the data to send */
|
||||
if(g_evt_udn_info[udn_index]->plot_val)
|
||||
g_evt_udn_info[udn_index]->plot_val (node_value, "", &dvalue);
|
||||
else
|
||||
dvalue = 0.0;
|
||||
|
||||
if(g_evt_udn_info[udn_index]->print_val)
|
||||
g_evt_udn_info[udn_index]->print_val (node_value, "", &svalue);
|
||||
else
|
||||
svalue = "";
|
||||
|
||||
if(g_evt_udn_info[udn_index]->ipc_val)
|
||||
g_evt_udn_info[udn_index]->ipc_val (node_value, &pvalue, &len);
|
||||
else {
|
||||
pvalue = NULL;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
/* Send it to the IPC channel */
|
||||
ipc_send_event(ipc_index, step, dvalue, svalue, pvalue, len);
|
||||
}
|
||||
|
||||
|
||||
#ifdef SHARED_MODULE
|
||||
static void EVTshareddump(
|
||||
CKTcircuit *ckt, /* The circuit structure */
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
#
|
||||
# JW 3/9/01 - had a go and makeing an autoconf script.
|
||||
|
||||
noinst_LTLIBRARIES = libipcxsp.la
|
||||
|
||||
libipcxsp_la_SOURCES = \
|
||||
ipcaegis.c \
|
||||
ipc.c \
|
||||
ipcsockets.c \
|
||||
ipcstdio.c \
|
||||
ipctiein.c
|
||||
|
||||
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include -I$(top_srcdir)/src/spicelib/devices
|
||||
AM_CFLAGS = $(STATIC)
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
|
@ -1,978 +0,0 @@
|
|||
/*============================================================================
|
||||
FILE IPC.c
|
||||
|
||||
MEMBER OF process XSPICE
|
||||
|
||||
Public Domain
|
||||
|
||||
Georgia Tech Research Corporation
|
||||
Atlanta, Georgia 30332
|
||||
PROJECT A-8503
|
||||
|
||||
AUTHORS
|
||||
|
||||
9/12/91 Steve Tynor
|
||||
|
||||
MODIFICATIONS
|
||||
|
||||
6/13/92 Bill Kuhn Added some comments
|
||||
|
||||
SUMMARY
|
||||
|
||||
Provides compatibility for the new SPICE simulator to both the MSPICE user
|
||||
interface and BCP (via ATESSE v.1 style AEGIS mailboxes) and the new ATESSE
|
||||
v.2 Simulator Interface and BCP (via Bsd Sockets).
|
||||
|
||||
The Interprocess Communications package provides functions
|
||||
called to receive XSPICE decks from the ATESSE Simulator Interface
|
||||
or Batch Control processes, and to return results to those
|
||||
processes. Functions callable from the simulator packages include:
|
||||
|
||||
ipc_initialize_server
|
||||
ipc_terminate_server
|
||||
ipc_get_line
|
||||
ipc_send_line
|
||||
ipc_send_data_prefix
|
||||
ipc_send_data_suffix
|
||||
ipc_send_dcop_prefix
|
||||
ipc_send_dcop_suffix
|
||||
ipc_send_evtdict_prefix
|
||||
ipc_send_evtdict_suffix
|
||||
ipc_send_evtdata_prefix
|
||||
ipc_send_evtdata_suffix
|
||||
ipc_send_errchk
|
||||
ipc_send_end
|
||||
ipc_send_boolean
|
||||
ipc_send_int
|
||||
ipc_send_double
|
||||
ipc_send_complex
|
||||
ipc_send_event
|
||||
ipc_flush
|
||||
|
||||
These functions communicate with a set of transport-level functions
|
||||
that implement the interprocess communications under one of
|
||||
the following protocol types determined by a compile-time option:
|
||||
|
||||
BSD UNIX Sockets
|
||||
HP/Apollo Mailboxes
|
||||
|
||||
For each transport protocol, the following functions are written:
|
||||
|
||||
ipc_transport_initialize_server
|
||||
ipc_transport_get_line
|
||||
ipc_transport_terminate_server
|
||||
ipc_transport_send_line
|
||||
|
||||
|
||||
|
||||
============================================================================*/
|
||||
|
||||
#include "ngspice/ngspice.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "ngspice/memory.h" /* NOTE: I think this is a Sys5ism (there is not man
|
||||
* page for it under Bsd, but it's in /usr/include
|
||||
* and it has a BSD copyright header. Go figure.
|
||||
*/
|
||||
|
||||
#include "ngspice/ipc.h"
|
||||
#include "ngspice/ipctiein.h"
|
||||
#include "ngspice/ipcproto.h"
|
||||
|
||||
|
||||
/*
|
||||
* Conditional compilation sanity check:
|
||||
*/
|
||||
#if !defined (IPC_AEGIS_MAILBOXES) && !defined (IPC_UNIX_SOCKETS)\
|
||||
&& !defined (IPC_DEBUG_VIA_STDIO)
|
||||
" compiler error - must specify a transport mechanism";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* static 'globals'
|
||||
*/
|
||||
|
||||
/* typedef unsigned char Buffer_Char_t; */
|
||||
typedef char Buffer_Char_t;
|
||||
|
||||
#define OUT_BUFFER_SIZE 1000
|
||||
#define MAX_NUM_RECORDS 200
|
||||
static int end_of_record_index [MAX_NUM_RECORDS];
|
||||
static int num_records;
|
||||
static Buffer_Char_t out_buffer [OUT_BUFFER_SIZE];
|
||||
static int fill_count;
|
||||
|
||||
static Ipc_Mode_t mode;
|
||||
static Ipc_Protocol_t protocol;
|
||||
static Ipc_Boolean_t end_of_deck_seen;
|
||||
static int batch_fd;
|
||||
|
||||
#define FMT_BUFFER_SIZE 80
|
||||
static char fmt_buffer [FMT_BUFFER_SIZE];
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
Ipc_Boolean_t
|
||||
kw_match (char *keyword, char *str)
|
||||
/*
|
||||
* returns IPC_TRUE if the first `strlen(keyword)' characters of `str' match
|
||||
* the ones in `keyword' - case sensitive
|
||||
*/
|
||||
{
|
||||
char *k = keyword;
|
||||
char *s = str;
|
||||
|
||||
/*
|
||||
* quit if we run off the end of either string:
|
||||
*/
|
||||
while (*s && *k) {
|
||||
if (*s != *k) {
|
||||
return IPC_FALSE;
|
||||
}
|
||||
s++;
|
||||
k++;
|
||||
}
|
||||
/*
|
||||
* if we get this far, it sould be because we ran off the end of the
|
||||
* keyword else we didn't match:
|
||||
*/
|
||||
return (*k == '\0');
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_initialize_server
|
||||
|
||||
This function creates the interprocess communication channel
|
||||
server mailbox or socket.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_initialize_server (
|
||||
char *server_name, /* Mailbox path or host/portnumber pair */
|
||||
Ipc_Mode_t m, /* Interactive or batch */
|
||||
Ipc_Protocol_t p ) /* Type of IPC protocol */
|
||||
/*
|
||||
* For mailboxes, `server_name' would be the mailbox pathname; for
|
||||
* sockets, this needs to be a host/portnumber pair. Maybe this should be
|
||||
* automatically generated by the routine...
|
||||
*/
|
||||
{
|
||||
Ipc_Status_t status;
|
||||
char batch_filename [1025];
|
||||
|
||||
mode = m;
|
||||
protocol = p;
|
||||
end_of_deck_seen = IPC_FALSE;
|
||||
|
||||
num_records = 0;
|
||||
fill_count = 0;
|
||||
|
||||
status = ipc_transport_initialize_server (server_name, m, p,
|
||||
batch_filename);
|
||||
|
||||
if (status != IPC_STATUS_OK) {
|
||||
fprintf (stderr, "ERROR: IPC: error initializing server\n");
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (mode == IPC_MODE_BATCH) {
|
||||
#ifdef IPC_AEGIS_MAILBOXES
|
||||
strcat (batch_filename, ".log");
|
||||
#endif
|
||||
batch_fd = open (batch_filename, O_WRONLY | O_CREAT, 0666);
|
||||
if (batch_fd < 0) {
|
||||
/* fprintf (stderr, "ERROR: IPC: Error opening batch output file: %s\n",batch_filename); */
|
||||
perror ("IPC");
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_terminate_server
|
||||
|
||||
This function deallocates the interprocess communication channel
|
||||
mailbox or socket.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_terminate_server (void)
|
||||
{
|
||||
return ipc_transport_terminate_server ();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_get_line
|
||||
|
||||
This function gets a SPICE deck input line from the interprocess
|
||||
communication channel. Any special control commands in the deck
|
||||
beginning with a ``>'' or ``#'' character are processed internally by
|
||||
this function and not returned to SPICE.
|
||||
*/
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_get_line (
|
||||
char *str, /* Text retrieved from IPC channel */
|
||||
int *len, /* Length of text string */
|
||||
Ipc_Wait_t wait ) /* Select blocking or non-blocking */
|
||||
/*
|
||||
* Reads one SPICE line from the connection. Strips any control lines
|
||||
* which cannot be interpretted by the simulator (e.g. >INQCON) and
|
||||
* processes them. If such a line is read, it is processed and the next
|
||||
* line is read. `ipc_get_line' does not return until a non-interceptable
|
||||
* line is read or end of file.
|
||||
*
|
||||
* If `wait' is IPC_NO_WAIT and there is no data available on the
|
||||
* connection, `ipc_get_line' returns IPC_STATUS_NO_DATA. If `wait' is
|
||||
* IPC_WAIT, `ipc_get_line' will not return until there is data available
|
||||
* or and end of file condition is reached or an error occurs.
|
||||
*
|
||||
* Intercepts and processes the following commands:
|
||||
* #RETURNI, #MINTIME, #VTRANS,
|
||||
* >PAUSE, >CONT, >STOP, >INQCON, >NETLIST, >ENDNET
|
||||
* Other > records are silently ignored.
|
||||
*
|
||||
* Intercepts old-style .TEMP card generated by MSPICE
|
||||
*
|
||||
* Returns:
|
||||
* IPC_STATUS_OK - for successful reads
|
||||
* IPC_STATUS_NO_DATA - when NO_WAIT and no data available
|
||||
* IPC_STATUS_END_OF_DECK - at end of deck (>ENDNET seen)
|
||||
* IPC_STATUS_ERROR - otherwise
|
||||
*/
|
||||
{
|
||||
Ipc_Status_t status;
|
||||
Ipc_Boolean_t need_another = IPC_TRUE;
|
||||
|
||||
do {
|
||||
|
||||
status = ipc_transport_get_line (str, len, wait);
|
||||
|
||||
switch (status) {
|
||||
case IPC_STATUS_NO_DATA:
|
||||
case IPC_STATUS_ERROR:
|
||||
need_another = IPC_FALSE;
|
||||
break;
|
||||
case IPC_STATUS_END_OF_DECK:
|
||||
assert (0); /* should never get this from the low-level get-line */
|
||||
status = IPC_STATUS_ERROR;
|
||||
need_another = IPC_FALSE;
|
||||
break;
|
||||
case IPC_STATUS_OK:
|
||||
/*
|
||||
* Got a good line - check to see if it's one of the ones we need to
|
||||
* intercept
|
||||
*/
|
||||
if (str[0] == '>') {
|
||||
if (kw_match (">STOP", str)) {
|
||||
ipc_handle_stop();
|
||||
} else if (kw_match (">PAUSE", str)) {
|
||||
/* assert (need_another); */
|
||||
/*
|
||||
* once more around the loop to do a blocking wait for the >CONT
|
||||
*/
|
||||
need_another = IPC_TRUE;
|
||||
wait = IPC_WAIT;
|
||||
} else if (kw_match (">INQCON", str)) {
|
||||
ipc_send_line (">ABRTABL");
|
||||
ipc_send_line (">PAUSABL");
|
||||
ipc_send_line (">KEEPABL");
|
||||
status = ipc_flush ();
|
||||
if (IPC_STATUS_OK != status) {
|
||||
need_another = IPC_FALSE;
|
||||
}
|
||||
} else if (kw_match (">ENDNET", str)) {
|
||||
end_of_deck_seen = IPC_TRUE;
|
||||
need_another = IPC_FALSE;
|
||||
status = IPC_STATUS_END_OF_DECK;
|
||||
} else {
|
||||
/* silently ignore */
|
||||
}
|
||||
} else if (str[0] == '#') {
|
||||
if (kw_match ("#RETURNI", str)) {
|
||||
ipc_handle_returni ();
|
||||
} else if (kw_match ("#MINTIME", str)) {
|
||||
double d1/*,d2*/;
|
||||
if (1 != sscanf (&str[8], "%lg", &d1)) {
|
||||
status = IPC_STATUS_ERROR;
|
||||
need_another = IPC_FALSE;
|
||||
} else {
|
||||
ipc_handle_mintime (d1);
|
||||
}
|
||||
} else if (kw_match ("#VTRANS", str)) {
|
||||
char *tok1;
|
||||
char *tok2;
|
||||
char *tok3;
|
||||
|
||||
tok1 = &str[8];
|
||||
for (tok2 = tok1; *tok2; tok2++) {
|
||||
if (isspace_c(*tok2)) {
|
||||
*tok2 = '\0';
|
||||
tok2++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(tok3 = tok2; *tok3; tok3++) {
|
||||
if(isspace_c(*tok3)) {
|
||||
*tok3 = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
ipc_handle_vtrans (tok1, tok2);
|
||||
} else {
|
||||
/* silently ignore */
|
||||
}
|
||||
} else if (str[0] == '.') {
|
||||
if (kw_match (".TEMP", str)) {
|
||||
/* don't pass .TEMP card to caller */
|
||||
printf("Old-style .TEMP card found - ignored\n");
|
||||
}
|
||||
else {
|
||||
/* pass all other . cards to the caller */
|
||||
need_another = IPC_FALSE;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Not a '>' or '#' record - let the caller deal with it
|
||||
*/
|
||||
need_another = IPC_FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* some unknown status value!
|
||||
*/
|
||||
assert (0);
|
||||
status = IPC_STATUS_ERROR;
|
||||
need_another = IPC_FALSE;
|
||||
break;
|
||||
}
|
||||
} while (need_another);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_flush
|
||||
|
||||
This function flushes the interprocess communication channel
|
||||
buffer contents.
|
||||
*/
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_flush (void)
|
||||
/*
|
||||
* Flush all buffered messages out the connection.
|
||||
*/
|
||||
{
|
||||
Ipc_Status_t status;
|
||||
int last = 0;
|
||||
/*int bytes;*/
|
||||
int i;
|
||||
|
||||
/* if batch mode */
|
||||
if (mode == IPC_MODE_BATCH) {
|
||||
|
||||
assert (batch_fd >= 0);
|
||||
|
||||
/* for number of records in buffer */
|
||||
for (i = 0; i < num_records; i++) {
|
||||
|
||||
/* write the records to the .log file */
|
||||
if ((end_of_record_index [i] - last) !=
|
||||
write (batch_fd, &out_buffer[last], (size_t) (end_of_record_index [i] - last))) {
|
||||
/* fprintf (stderr,"ERROR: IPC: Error writing to batch output file\n"); */
|
||||
perror ("IPC");
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* If the record is one of the batch simulation status messages, */
|
||||
/* send it over the ipc channel too */
|
||||
if( kw_match("#ERRCHK", &out_buffer[last]) ||
|
||||
kw_match(">ENDANAL", &out_buffer[last]) ||
|
||||
kw_match(">ABORTED", &out_buffer[last]) ) {
|
||||
|
||||
status = ipc_transport_send_line (&out_buffer[last],
|
||||
end_of_record_index [i] - last);
|
||||
if (IPC_STATUS_OK != status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
last = end_of_record_index [i];
|
||||
}
|
||||
|
||||
/* else, must be interactive mode */
|
||||
} else {
|
||||
/* send the full buffer over the ipc channel */
|
||||
status = ipc_transport_send_line (&out_buffer[0],
|
||||
end_of_record_index [num_records - 1]);
|
||||
if (IPC_STATUS_OK != status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* reset counts to zero and return */
|
||||
num_records = 0;
|
||||
fill_count = 0;
|
||||
return IPC_STATUS_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
Ipc_Status_t
|
||||
ipc_send_line_binary (
|
||||
char *str,
|
||||
int len )
|
||||
/*
|
||||
* Same as `ipc_send_line' except does not expect the str to be null
|
||||
* terminated. Sends exactly `len' characters. Use this for binary data
|
||||
* strings that may have embedded nulls.
|
||||
*
|
||||
* Modified by wbk to append newlines for compatibility with
|
||||
* ATESSE 1.0
|
||||
*
|
||||
*/
|
||||
{
|
||||
int length = len + 1;
|
||||
/*int diff;*/
|
||||
Ipc_Status_t status;
|
||||
|
||||
/*
|
||||
* If we can't add the whole str to the buffer, or if there are no more
|
||||
* record indices free, flush the buffer:
|
||||
*/
|
||||
if (((fill_count + length) >= OUT_BUFFER_SIZE) ||
|
||||
(num_records >= MAX_NUM_RECORDS)) {
|
||||
status = ipc_flush ();
|
||||
if (IPC_STATUS_OK != status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* make sure that the str will fit:
|
||||
*/
|
||||
if (length + fill_count > OUT_BUFFER_SIZE) {
|
||||
/* fprintf (stderr,"ERROR: IPC: String too long to fit in output buffer (> %d bytes) - truncated\n",OUT_BUFFER_SIZE); */
|
||||
length = OUT_BUFFER_SIZE - fill_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* finally, concatenate the str to the end of the buffer and add the newline:
|
||||
*/
|
||||
memcpy (&out_buffer[fill_count], str, (size_t) len);
|
||||
fill_count += len;
|
||||
|
||||
out_buffer[fill_count] = '\n';
|
||||
fill_count++;
|
||||
|
||||
end_of_record_index [num_records++] = fill_count;
|
||||
|
||||
return IPC_STATUS_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_line
|
||||
|
||||
This function sends a line of text over the interprocess
|
||||
communication channel.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_line (char *str ) /* The text to send */
|
||||
{
|
||||
int len;
|
||||
int send_len;
|
||||
|
||||
char *s;
|
||||
|
||||
Ipc_Status_t status= IPC_STATUS_OK;
|
||||
|
||||
|
||||
len = (int) strlen(str);
|
||||
|
||||
/* if short string, send it immediately */
|
||||
if(len < 80)
|
||||
status = ipc_send_line_binary (str, len);
|
||||
else {
|
||||
/* otherwise, we have to send it as multiple strings */
|
||||
/* because Mspice cannot handle things longer than 80 chars */
|
||||
s = str;
|
||||
while(len > 0) {
|
||||
if(len < 80)
|
||||
send_len = len;
|
||||
else
|
||||
send_len = 79;
|
||||
status = ipc_send_line_binary (str, send_len);
|
||||
if(status != IPC_STATUS_OK)
|
||||
break;
|
||||
s += send_len;
|
||||
len -= send_len;
|
||||
}
|
||||
}
|
||||
|
||||
return(status);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_data_prefix
|
||||
|
||||
This function sends a ``>DATAB'' line over the interprocess
|
||||
communication channel to signal that this is the beginning of a
|
||||
results dump for the current analysis point.
|
||||
*/
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_data_prefix (double time ) /* The analysis point for this data set */
|
||||
{
|
||||
char buffer[40];
|
||||
|
||||
sprintf (buffer, ">DATAB %.5E", time);
|
||||
return ipc_send_line (buffer);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_data_suffix
|
||||
|
||||
This function sends a ``>ENDDATA'' line over the interprocess
|
||||
communication channel to signal that this is the end of a results
|
||||
dump from a particular analysis point.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_data_suffix (void)
|
||||
{
|
||||
Ipc_Status_t status;
|
||||
|
||||
status = ipc_send_line (">ENDDATA");
|
||||
|
||||
if(status != IPC_STATUS_OK)
|
||||
return(status);
|
||||
|
||||
return(ipc_flush());
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_dcop_prefix
|
||||
|
||||
This function sends a ``>DCOPB'' line over the interprocess
|
||||
communication channel to signal that this is the beginning of a
|
||||
results dump from a DC operating point analysis.
|
||||
*/
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_dcop_prefix (void)
|
||||
{
|
||||
return ipc_send_line (">DCOPB");
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_dcop_suffix
|
||||
|
||||
This function sends a ``>ENDDATA'' line over the interprocess
|
||||
communication channel to signal that this is the end of a results
|
||||
dump from a particular analysis point.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_dcop_suffix (void)
|
||||
{
|
||||
Ipc_Status_t status;
|
||||
|
||||
status = ipc_send_line (">ENDDCOP");
|
||||
|
||||
if(status != IPC_STATUS_OK)
|
||||
return(status);
|
||||
|
||||
return(ipc_flush());
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_evtdict_prefix
|
||||
|
||||
This function sends a ``>EVTDICT'' line over the interprocess
|
||||
communication channel to signal that this is the beginning of an
|
||||
event-driven node dictionary.
|
||||
|
||||
The line is sent only if the IPC is configured
|
||||
for UNIX sockets, indicating use with the V2 ATESSE SI process.
|
||||
*/
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_evtdict_prefix (void)
|
||||
{
|
||||
#ifdef IPC_AEGIS_MAILBOXES
|
||||
return IPC_STATUS_OK;
|
||||
#else
|
||||
return ipc_send_line (">EVTDICT");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_evtdict_suffix
|
||||
|
||||
This function sends a ``>ENDDICT'' line over the interprocess
|
||||
communication channel to signal that this is the end of an
|
||||
event-driven node dictionary.
|
||||
|
||||
The line is sent only if the IPC is configured
|
||||
for UNIX sockets, indicating use with the V2 ATESSE SI process.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_evtdict_suffix (void)
|
||||
{
|
||||
#ifdef IPC_AEGIS_MAILBOXES
|
||||
return IPC_STATUS_OK;
|
||||
#else
|
||||
Ipc_Status_t status;
|
||||
|
||||
status = ipc_send_line (">ENDDICT");
|
||||
|
||||
if(status != IPC_STATUS_OK)
|
||||
return(status);
|
||||
|
||||
return(ipc_flush());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_evtdata_prefix
|
||||
|
||||
This function sends a ``>EVTDATA'' line over the interprocess
|
||||
communication channel to signal that this is the beginning of an
|
||||
event-driven node data block.
|
||||
|
||||
The line is sent only if the IPC is configured
|
||||
for UNIX sockets, indicating use with the V2 ATESSE SI process.
|
||||
*/
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_evtdata_prefix (void)
|
||||
{
|
||||
#ifdef IPC_AEGIS_MAILBOXES
|
||||
return IPC_STATUS_OK;
|
||||
#else
|
||||
return ipc_send_line (">EVTDATA");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_evtdata_suffix
|
||||
|
||||
This function sends a ``>ENDDATA'' line over the interprocess
|
||||
communication channel to signal that this is the end of an
|
||||
event-driven node data block.
|
||||
|
||||
The line is sent only if the IPC is configured
|
||||
for UNIX sockets, indicating use with the V2 ATESSE SI process.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_evtdata_suffix (void)
|
||||
{
|
||||
#ifdef IPC_AEGIS_MAILBOXES
|
||||
return IPC_STATUS_OK;
|
||||
#else
|
||||
Ipc_Status_t status;
|
||||
|
||||
status = ipc_send_line (">ENDDATA");
|
||||
|
||||
if(status != IPC_STATUS_OK)
|
||||
return(status);
|
||||
|
||||
return(ipc_flush());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_errchk
|
||||
|
||||
This function sends a ``\ERRCHK [GO|NOGO]'' message over the
|
||||
interprocess communication channel to signal that the initial
|
||||
parsing of the input deck has been completed and to indicate
|
||||
whether or not errors were detected.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_errchk(void)
|
||||
{
|
||||
char str[IPC_MAX_LINE_LEN+1];
|
||||
Ipc_Status_t status;
|
||||
|
||||
if(g_ipc.errchk_sent)
|
||||
return(IPC_STATUS_OK);
|
||||
|
||||
if(g_ipc.syntax_error)
|
||||
sprintf(str, "#ERRCHK NOGO");
|
||||
else
|
||||
sprintf(str, "#ERRCHK GO");
|
||||
|
||||
g_ipc.errchk_sent = IPC_TRUE;
|
||||
|
||||
status = ipc_send_line(str);
|
||||
if(status != IPC_STATUS_OK)
|
||||
return(status);
|
||||
|
||||
return(ipc_flush());
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_end
|
||||
|
||||
This function sends either an ``>ENDANAL'' or an ``>ABORTED'' message
|
||||
over the interprocess communication channel together with the
|
||||
total CPU time used to indicate whether or not the simulation
|
||||
completed normally.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_end(void)
|
||||
{
|
||||
char str[IPC_MAX_LINE_LEN+1];
|
||||
Ipc_Status_t status;
|
||||
|
||||
if(g_ipc.syntax_error || g_ipc.run_error)
|
||||
sprintf(str, ">ABORTED %.4f", g_ipc.cpu_time);
|
||||
else
|
||||
sprintf(str, ">ENDANAL %.4f", g_ipc.cpu_time);
|
||||
|
||||
status = ipc_send_line(str);
|
||||
if(status != IPC_STATUS_OK)
|
||||
return(status);
|
||||
|
||||
return(ipc_flush());
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
stuff_binary_v1 (
|
||||
double d1, double d2, /* doubles to be stuffed */
|
||||
int n, /* how many of d1, d2 ( 1 <= n <= 2 ) */
|
||||
char *buf, /* buffer to stuff to */
|
||||
int pos ) /* index at which to stuff */
|
||||
{
|
||||
union {
|
||||
float float_val[2];
|
||||
char ch[32];
|
||||
} trick;
|
||||
int i, j;
|
||||
|
||||
assert (protocol == IPC_PROTOCOL_V1);
|
||||
assert (sizeof(float) == 4);
|
||||
assert (sizeof(char) == 1);
|
||||
assert ((n >= 1) && (n <= 2));
|
||||
|
||||
trick.float_val[0] = (float)d1;
|
||||
if (n > 1) {
|
||||
trick.float_val[1] = (float)d2;
|
||||
}
|
||||
for (i = 0, j = pos; i < n * (int) sizeof(float); j++, i++)
|
||||
buf[j] = trick.ch[i];
|
||||
buf[0] = (char) ('A' + j - 1);
|
||||
return j;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
ipc_send_double
|
||||
|
||||
This function sends a double data value over the interprocess
|
||||
communication channel preceded by a character string that
|
||||
identifies the simulation variable.
|
||||
*/
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_double (
|
||||
char *tag, /* The node or instance */
|
||||
double value ) /* The data value to send */
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
switch (protocol) {
|
||||
case IPC_PROTOCOL_V1:
|
||||
strcpy (fmt_buffer, " "); /* save room for the length byte */
|
||||
strcat (fmt_buffer, tag);
|
||||
strcat (fmt_buffer, " ");
|
||||
|
||||
/* If talking to Mentor tools, must force upper case for Mspice 7.0 */
|
||||
strtoupper(fmt_buffer);
|
||||
|
||||
len = stuff_binary_v1 (value, 0.0, 1, fmt_buffer, (int) strlen(fmt_buffer));
|
||||
break;
|
||||
case IPC_PROTOCOL_V2:
|
||||
break;
|
||||
}
|
||||
return ipc_send_line_binary (fmt_buffer, len);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_complex
|
||||
|
||||
This function sends a complex data value over the interprocess
|
||||
communication channel preceded by a character string that
|
||||
identifies the simulation variable.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_complex (
|
||||
char *tag, /* The node or instance */
|
||||
Ipc_Complex_t value ) /* The data value to send */
|
||||
{
|
||||
int len=0;
|
||||
|
||||
switch (protocol) {
|
||||
case IPC_PROTOCOL_V1:
|
||||
strcpy (fmt_buffer, " "); /* save room for the length byte */
|
||||
strcat (fmt_buffer, tag);
|
||||
strcat (fmt_buffer, " ");
|
||||
|
||||
/* If talking to Mentor tools, must force upper case for Mspice 7.0 */
|
||||
strtoupper(fmt_buffer);
|
||||
|
||||
len = stuff_binary_v1 (value.real, value.imag, 2, fmt_buffer,
|
||||
(int) strlen(fmt_buffer));
|
||||
break;
|
||||
case IPC_PROTOCOL_V2:
|
||||
break;
|
||||
}
|
||||
return ipc_send_line_binary (fmt_buffer, len);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_send_event
|
||||
|
||||
This function sends data from an event-driven node over the interprocess
|
||||
communication channel. The data is sent only if the IPC is configured
|
||||
for UNIX sockets, indicating use with the V2 ATESSE SI process.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_send_event (
|
||||
int ipc_index, /* Index used in EVTDICT */
|
||||
double step, /* Analysis point or timestep (0.0 for DC) */
|
||||
double plot_val, /* The value for plotting purposes */
|
||||
char *print_val, /* The value for printing purposes */
|
||||
void *ipc_val, /* The binary representation of the node data */
|
||||
int len ) /* The length of the binary representation */
|
||||
{
|
||||
#ifdef IPC_AEGIS_MAILBOXES
|
||||
return IPC_STATUS_OK;
|
||||
#else
|
||||
char buff[OUT_BUFFER_SIZE];
|
||||
int i;
|
||||
int buff_len;
|
||||
char *buff_ptr;
|
||||
char *temp_ptr;
|
||||
float fvalue;
|
||||
|
||||
/* Report error if size of data is too big for IPC channel block size */
|
||||
if((len + (int) strlen(print_val) + 100) >= OUT_BUFFER_SIZE) {
|
||||
printf("ERROR - Size of event-driven data too large for IPC channel\n");
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Place the index into the buffer with a trailing space */
|
||||
sprintf(buff, "%d ", ipc_index);
|
||||
|
||||
assert(sizeof(float) == 4);
|
||||
assert(sizeof(int) == 4);
|
||||
|
||||
/* Put the analysis step bytes in */
|
||||
buff_len = (int) strlen(buff);
|
||||
buff_ptr = buff + buff_len;
|
||||
fvalue = (float)step;
|
||||
temp_ptr = (char *) &fvalue;
|
||||
for(i = 0; i < 4; i++) {
|
||||
*buff_ptr = temp_ptr[i];
|
||||
buff_ptr++;
|
||||
buff_len++;
|
||||
}
|
||||
|
||||
/* Put the plot value in */
|
||||
fvalue = (float)plot_val;
|
||||
temp_ptr = (char *) &fvalue;
|
||||
for(i = 0; i < 4; i++) {
|
||||
*buff_ptr = temp_ptr[i];
|
||||
buff_ptr++;
|
||||
buff_len++;
|
||||
}
|
||||
|
||||
/* Put the length of the binary representation in */
|
||||
temp_ptr = (char *) &len;
|
||||
for(i = 0; i < 4; i++) {
|
||||
*buff_ptr = temp_ptr[i];
|
||||
buff_ptr++;
|
||||
buff_len++;
|
||||
}
|
||||
|
||||
/* Put the binary representation bytes in last */
|
||||
temp_ptr = (char*) ipc_val;
|
||||
for(i = 0; i < len; i++)
|
||||
buff_ptr[i] = temp_ptr[i];
|
||||
buff_ptr += len;
|
||||
buff_len += len;
|
||||
|
||||
/* Put the print value in */
|
||||
strcpy(buff_ptr, print_val);
|
||||
buff_ptr += strlen(print_val);
|
||||
buff_len += (int) strlen(print_val);
|
||||
|
||||
/* Send the data to the IPC channel */
|
||||
return ipc_send_line_binary(buff, buff_len);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,309 +0,0 @@
|
|||
/*============================================================================
|
||||
FILE IPCaegis.c
|
||||
|
||||
MEMBER OF process XSPICE
|
||||
|
||||
Public Domain
|
||||
|
||||
Georgia Tech Research Corporation
|
||||
Atlanta, Georgia 30332
|
||||
PROJECT A-8503
|
||||
|
||||
AUTHORS
|
||||
|
||||
9/12/91 Steve Tynor
|
||||
|
||||
MODIFICATIONS
|
||||
|
||||
<date> <person name> <nature of modifications>
|
||||
|
||||
SUMMARY
|
||||
|
||||
Provides compatibility for the new XSPICE simulator to both the MSPICE user
|
||||
interface and BCP via ATESSE v.1 style AEGIS mailboxes.
|
||||
|
||||
INTERFACES
|
||||
|
||||
|
||||
REFERENCED FILES
|
||||
|
||||
None.
|
||||
|
||||
NON-STANDARD FEATURES
|
||||
|
||||
None.
|
||||
|
||||
============================================================================*/
|
||||
|
||||
#ifdef IPC_AEGIS_MAILBOXES
|
||||
|
||||
#include <assert.h>
|
||||
#include <apollo/base.h>
|
||||
#include <apollo/mbx.h>
|
||||
#include <apollo/error.h>
|
||||
#include "ngspice/memory.h"
|
||||
|
||||
#include "ngspice/ipc.h"
|
||||
|
||||
|
||||
typedef unsigned char Buffer_char_t;
|
||||
|
||||
static status_$t status;
|
||||
typedef enum {
|
||||
IPC_MBX_UNINITIALIZED,
|
||||
IPC_MBX_INITIALIZED,
|
||||
IPC_MBX_CONNECTED_TO_CLIENT,
|
||||
} Ipc_Mbx_State_t;
|
||||
|
||||
static void *mbx_handle;
|
||||
static Ipc_Mbx_State_t mbx_state = IPC_MBX_UNINITIALIZED;
|
||||
static mbx_$server_msg_t mbx_send_msg_buf;
|
||||
static mbx_$server_msg_t mbx_recieve_msg_buf;
|
||||
static mbx_$server_msg_t *mbx_ret_ptr;
|
||||
static int mbx_ret_len;
|
||||
static short mbx_chan;
|
||||
|
||||
#include "ngspice/ipcproto.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_transport_initialize_server
|
||||
|
||||
This function creates an Aegis mailbox, and if successful,
|
||||
calls ipc_get_line to wait for the first record sent which is
|
||||
assumed to be the batch output filename.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
Ipc_Status_t ipc_transport_initialize_server (server_name, m, p,
|
||||
batch_filename)
|
||||
char *server_name; /* The mailbox pathname */
|
||||
Ipc_Mode_t m; /* Mode - interactive or batch */
|
||||
Ipc_Protocol_t p; /* Protocol type */
|
||||
char *batch_filename; /* Batch filename returned */
|
||||
{
|
||||
int len;
|
||||
/* extern void *malloc(); */
|
||||
|
||||
assert (p == IPC_PROTOCOL_V1);
|
||||
|
||||
mbx_$create_server (server_name, strlen (server_name), mbx_$serv_msg_max,
|
||||
1, &mbx_handle, &status);
|
||||
|
||||
if (status.all != status_$ok) {
|
||||
fprintf (stderr,
|
||||
"ERROR: IPC: Error creating mailbox server \"%s\"\n",
|
||||
server_name);
|
||||
error_$print (status);
|
||||
mbx_state = IPC_MBX_UNINITIALIZED;
|
||||
return IPC_STATUS_ERROR;
|
||||
} else {
|
||||
mbx_state = IPC_MBX_INITIALIZED;
|
||||
/*
|
||||
* First record is the name of the batch filename - whether we're in
|
||||
* batch mode or not:
|
||||
*/
|
||||
return ipc_get_line (batch_filename, &len, IPC_WAIT);
|
||||
}
|
||||
/*
|
||||
* shouldn't get here
|
||||
*/
|
||||
assert (0);
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
Ipc_Status_t extract_msg (str, len)
|
||||
char *str;
|
||||
int *len;
|
||||
{
|
||||
*len = mbx_ret_len - mbx_$serv_msg_hdr_len;
|
||||
assert (*len >= 0);
|
||||
|
||||
/*
|
||||
* null terminate before copy:
|
||||
*/
|
||||
mbx_ret_ptr->data [*len] = '\0';
|
||||
strcpy (str, mbx_ret_ptr->data);
|
||||
|
||||
return IPC_STATUS_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_transport_get_line
|
||||
|
||||
This function reads data sent by a client over the mailbox
|
||||
channel. It also handles the initial opening of the
|
||||
mailbox channel when requested by a client.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
Ipc_Status_t ipc_transport_get_line (str, len, wait)
|
||||
char *str; /* The string text read from IPC channel */
|
||||
int *len; /* The length of str */
|
||||
Ipc_Wait_t wait; /* Blocking or non-blocking */
|
||||
{
|
||||
if (mbx_state == IPC_MBX_UNINITIALIZED) {
|
||||
fprintf (stderr,
|
||||
"ERROR: IPC: Attempted to read from non-initialized mailbox\n");
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
assert ((mbx_state == IPC_MBX_CONNECTED_TO_CLIENT) ||
|
||||
(mbx_state == IPC_MBX_INITIALIZED));
|
||||
|
||||
for (;;) {
|
||||
if (wait == IPC_WAIT) {
|
||||
mbx_$get_rec (mbx_handle, &mbx_recieve_msg_buf, mbx_$serv_msg_max,
|
||||
&mbx_ret_ptr, &mbx_ret_len, &status);
|
||||
} else {
|
||||
mbx_$get_conditional (mbx_handle, &mbx_recieve_msg_buf,
|
||||
mbx_$serv_msg_max, &mbx_ret_ptr, &mbx_ret_len,
|
||||
&status);
|
||||
if (status.all == mbx_$channel_empty) {
|
||||
return IPC_STATUS_NO_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
if (status.all != status_$ok) {
|
||||
fprintf (stderr, "ERROR: IPC: Error reading from mailbox\n");
|
||||
error_$print (status);
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
switch (mbx_ret_ptr->mt) {
|
||||
case mbx_$channel_open_mt:
|
||||
if (mbx_state == IPC_MBX_CONNECTED_TO_CLIENT) {
|
||||
/*
|
||||
* we're already connected to a client... refuse the connection
|
||||
*/
|
||||
mbx_send_msg_buf.mt = mbx_$reject_open_mt;
|
||||
} else {
|
||||
mbx_send_msg_buf.mt = mbx_$accept_open_mt;
|
||||
mbx_state = IPC_MBX_CONNECTED_TO_CLIENT;
|
||||
}
|
||||
mbx_send_msg_buf.cnt = mbx_$serv_msg_hdr_len;
|
||||
mbx_chan = mbx_ret_ptr->chan;
|
||||
mbx_send_msg_buf.chan = mbx_chan;
|
||||
|
||||
mbx_$put_rec (mbx_handle, &mbx_send_msg_buf, mbx_$serv_msg_hdr_len,
|
||||
&status);
|
||||
|
||||
if (status.all != status_$ok) {
|
||||
fprintf (stderr, "ERROR: IPC: Error writing to mailbox\n");
|
||||
error_$print (status);
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* check to see if there was a message buried in the open request:
|
||||
*/
|
||||
if (mbx_ret_len > mbx_$serv_msg_hdr_len) {
|
||||
return extract_msg (str, len);
|
||||
}
|
||||
break;
|
||||
case mbx_$eof_mt:
|
||||
mbx_chan = mbx_ret_ptr->chan;
|
||||
mbx_$deallocate(mbx_handle, mbx_chan, &status);
|
||||
|
||||
if (status.all != status_$ok) {
|
||||
fprintf (stderr, "ERROR: IPC: Error deallocating mailbox\n");
|
||||
error_$print (status);
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
mbx_state = IPC_MBX_INITIALIZED;
|
||||
return IPC_STATUS_EOF;
|
||||
break;
|
||||
case mbx_$data_mt:
|
||||
assert (mbx_state == IPC_MBX_CONNECTED_TO_CLIENT);
|
||||
return extract_msg (str, len);
|
||||
break;
|
||||
case mbx_$data_partial_mt:
|
||||
fprintf (stderr, "ERROR: IPC: Recieved partial data message - ignored\n");
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "ERROR: IPC: Bad message type (0x%x) recieved\n",
|
||||
mbx_ret_ptr->mt);
|
||||
}
|
||||
}
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_transport_terminate_server
|
||||
|
||||
This function calls ipc\_transport\_get\_line until it
|
||||
receives an EOF from the client, which concludes the
|
||||
communication.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Status_t ipc_transport_terminate_server ()
|
||||
{
|
||||
char buffer[300];
|
||||
int len;
|
||||
Ipc_Status_t status;
|
||||
|
||||
do {
|
||||
status = ipc_transport_get_line (buffer, &len, IPC_WAIT);
|
||||
} while ((status != IPC_STATUS_ERROR) &&
|
||||
(status != IPC_STATUS_EOF));
|
||||
return status;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
ipc_transport_send_line
|
||||
|
||||
This function sends a message to the current client through
|
||||
the mailbox channel.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Status_t ipc_transport_send_line (str, len)
|
||||
char *str; /* The bytes to send */
|
||||
int len; /* The number of bytes from str to send */
|
||||
{
|
||||
long cnt;
|
||||
|
||||
if (mbx_state != IPC_MBX_CONNECTED_TO_CLIENT) {
|
||||
fprintf (stderr,
|
||||
"ERROR: IPC: Attempted to write to non-open mailbox\n");
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
mbx_send_msg_buf.mt = mbx_$data_mt;
|
||||
if (mbx_$serv_msg_hdr_len + len > mbx_$serv_msg_max) {
|
||||
fprintf (stderr,
|
||||
"ERROR: IPC: send_line message too long - truncating\n");
|
||||
len = mbx_$serv_msg_max - mbx_$serv_msg_hdr_len;
|
||||
}
|
||||
|
||||
mbx_send_msg_buf.cnt = mbx_$serv_msg_hdr_len + len;
|
||||
mbx_send_msg_buf.chan = mbx_chan;
|
||||
memcpy (mbx_send_msg_buf.data, str, len);
|
||||
|
||||
cnt = mbx_send_msg_buf.cnt;
|
||||
mbx_$put_rec (mbx_handle, &mbx_send_msg_buf, cnt, &status);
|
||||
|
||||
if (status.all != status_$ok) {
|
||||
fprintf (stderr, "ERROR: IPC: Error writing to mailbox\n");
|
||||
error_$print (status);
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
return IPC_STATUS_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int intDummy1;
|
||||
|
||||
#endif /* IPC_AEGIS_MAILBOXES */
|
||||
|
|
@ -1,756 +0,0 @@
|
|||
/*=============================================================================
|
||||
|
||||
FILE IPCsockets.c
|
||||
|
||||
Public Domain
|
||||
|
||||
Georgia Tech Research Corporation
|
||||
Atlanta, Georgia 30332
|
||||
PROJECT A-8503
|
||||
|
||||
AUTHOR
|
||||
Stefan Roth July 1991
|
||||
|
||||
MODIFICATIONS
|
||||
none
|
||||
|
||||
SUMMARY
|
||||
Generic Interprocess Communication module
|
||||
Provides compatibility for the new SPICE simulator to both the MSPICE user
|
||||
interface and BCP (via ATESSE v.1 style AEGIS mailboxes) and the new ATESSE
|
||||
v.2 Simulator Interface and BCP (via BSD Sockets). This file contains the
|
||||
BSD sockets version.
|
||||
The Simulator is the server, while the SI and BCP will be the clients.
|
||||
|
||||
|
||||
INTERFACES
|
||||
|
||||
FILE ROUTINE CALLED
|
||||
|
||||
IPC.c ipc_get_line();
|
||||
|
||||
|
||||
REFERENCED FILES
|
||||
|
||||
Outputs to stderr.
|
||||
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
|
||||
DESCRIPTION OF FUNCTIONALITY:
|
||||
|
||||
Outline of Initialize_Server function:
|
||||
create socket;
|
||||
bind name to socket;
|
||||
getsockname;
|
||||
listen;
|
||||
sock_state = IPC_SOCK_INITIALIZED;
|
||||
return ipc_get_line ();
|
||||
|
||||
|
||||
Format of a message line:
|
||||
bytes description
|
||||
----- -------------------
|
||||
0 recognition character for beginning of line; value is BOL_CHAR.
|
||||
1-4 message length (not including bytes 0-4); 32 bits in htonl
|
||||
format;
|
||||
if value = -1, then EOF and socket should be closed.
|
||||
5-N+5 message body of length specified in bytes 1-4.
|
||||
|
||||
The bytes before the message body are the message header. The header
|
||||
length is specified as SOCK_MSG_HDR_LEN bytes.
|
||||
|
||||
|
||||
Outline of Get_Line function:
|
||||
read 5 characters;
|
||||
verify that first char is BOL_CHAR;
|
||||
interpret message length (N) from bytes 1-4;
|
||||
do error checking on message header bytes;
|
||||
read N characters as message body;
|
||||
do error checking on message body read;
|
||||
|
||||
|
||||
Outline of Send_Line function:
|
||||
write BOL_CHAR;
|
||||
write 4-byte message body length
|
||||
write message body (N bytes)
|
||||
do error checking after each write operation
|
||||
|
||||
|
||||
Outline of Terminate_Server function:
|
||||
Continue to read lines (with ipc_transport_get_line) and ignore
|
||||
them until socket EOF is reached;
|
||||
Close the socket.
|
||||
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "ngspice/ngspice.h"
|
||||
|
||||
#ifdef IPC_UNIX_SOCKETS
|
||||
|
||||
/*=== INCLUDE FILES ===*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ngspice/ipc.h"
|
||||
#include "ngspice/ipctiein.h"
|
||||
|
||||
|
||||
/*=== TYPE DEFINITIONS ===*/
|
||||
|
||||
typedef enum {
|
||||
IPC_SOCK_UNINITIALIZED,
|
||||
IPC_SOCK_INITIALIZED,
|
||||
IPC_SOCK_CONNECTED_TO_CLIENT
|
||||
} Ipc_Sock_State_t;
|
||||
|
||||
|
||||
/*=== LOCAL VARIABLES ===*/
|
||||
|
||||
static int sock_desc; /* socket descriptor */
|
||||
static int msg_stream; /* socket stream */
|
||||
static Ipc_Sock_State_t sock_state = IPC_SOCK_UNINITIALIZED;
|
||||
|
||||
|
||||
/*=== INCLUDE FILES ===*/
|
||||
|
||||
#include "ngspice/ipcproto.h"
|
||||
|
||||
/*=============================================================================
|
||||
|
||||
FUNCTION ipc_transport_initialize_server
|
||||
|
||||
AUTHORS
|
||||
|
||||
July 1991 Stefan Roth
|
||||
|
||||
MODIFICATIONS
|
||||
|
||||
NONE
|
||||
|
||||
SUMMARY
|
||||
|
||||
Creates and opens the BSD socket of the server. Listens for requests
|
||||
by a client and then reads the first line message.
|
||||
|
||||
INTERFACES
|
||||
|
||||
Called by: (IPC.c) ipc_initialize_server();
|
||||
|
||||
RETURNED VALUE
|
||||
|
||||
Ipc_Status_t - returns status of the socket connection.
|
||||
|
||||
GLOBAL VARIABLES
|
||||
|
||||
NONE
|
||||
|
||||
NON-STANDARD FEATURES
|
||||
|
||||
NONE
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_transport_initialize_server (
|
||||
char *server_name, /* not used */
|
||||
Ipc_Mode_t mode, /* not used */
|
||||
Ipc_Protocol_t protocol, /* IN - only used in assert */
|
||||
char *batch_filename ) /* OUT - returns a value */
|
||||
/* Note that unused parameters are required to maintain compatibility */
|
||||
/* with version 1 (mailboxes) functions of the same names. */
|
||||
{
|
||||
struct sockaddr_in server; /* Server specifications for socket*/
|
||||
socklen_t server_length; /* Size of server structure */
|
||||
int port_num; /* Port number converted from server_name */
|
||||
|
||||
NG_IGNORE(mode);
|
||||
NG_IGNORE(protocol);
|
||||
|
||||
/* assert (protocol == IPC_PROTOCOL_V2); */ /* allow v1 protocol - wbk */
|
||||
assert (sock_state == IPC_SOCK_UNINITIALIZED);
|
||||
|
||||
/* convert server_name (from atesse_xspice invocation line) to a port */
|
||||
/* number */
|
||||
port_num = atoi(server_name);
|
||||
if((port_num > 0) && (port_num < 1024)) {
|
||||
/* Reserved port number */
|
||||
perror ("ERROR: IPC Port numbers below 1024 are reserved");
|
||||
sock_state = IPC_SOCK_UNINITIALIZED;
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
|
||||
sock_desc = socket (AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (sock_desc < 0) {
|
||||
/* Unsuccessful socket opening */
|
||||
perror ("ERROR: IPC Creating socket");
|
||||
sock_state = IPC_SOCK_UNINITIALIZED;
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Socket opened successfully */
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_addr.s_addr = INADDR_ANY;
|
||||
server.sin_port = SOCKET_PORT;
|
||||
|
||||
server_length = sizeof (server);
|
||||
if (bind (sock_desc, (struct sockaddr *)&server, server_length)
|
||||
< 0) {
|
||||
fprintf (stderr, "ERROR: IPC: Bind unsuccessful\n");
|
||||
perror ("ERROR: IPC");
|
||||
sock_state = IPC_SOCK_UNINITIALIZED;
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (getsockname (sock_desc, (struct sockaddr *)&server, &server_length)
|
||||
< 0) {
|
||||
fprintf (stderr, "ERROR: IPC: getting socket name\n");
|
||||
perror ("ERROR: IPC");
|
||||
sock_state = IPC_SOCK_UNINITIALIZED;
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
fprintf (stderr, "Socket port %d.\n", ntohs(server.sin_port));
|
||||
|
||||
listen (sock_desc, 5);
|
||||
|
||||
sock_state = IPC_SOCK_INITIALIZED;
|
||||
|
||||
/* Socket ok to use now */
|
||||
|
||||
/*
|
||||
* First record is the name of the batch filename if we're in batch mode.
|
||||
*/
|
||||
|
||||
if(g_ipc.mode == IPC_MODE_BATCH) {
|
||||
int len;
|
||||
return ipc_get_line (batch_filename, &len, IPC_WAIT);
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return IPC_STATUS_OK;
|
||||
|
||||
} /* end ipc_transport_initialize_server */
|
||||
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
|
||||
FUNCTION bytes_to_integer
|
||||
|
||||
AUTHORS
|
||||
|
||||
July 1991 Stefan Roth
|
||||
|
||||
MODIFICATIONS
|
||||
|
||||
NONE
|
||||
|
||||
SUMMARY
|
||||
|
||||
Convert four bytes at START in the string STR
|
||||
to a 32-bit unsigned integer. The string is assumed
|
||||
to be in network byte order and the returned value
|
||||
is converted to host byte order (with ntohl).
|
||||
|
||||
INTERFACES
|
||||
|
||||
Local to this file.
|
||||
Called by: ipc_transport_get_line();
|
||||
|
||||
RETURNED VALUE
|
||||
|
||||
u_long - unsigned 32 bit integer
|
||||
|
||||
GLOBAL VARIABLES
|
||||
|
||||
NONE
|
||||
|
||||
NON-STANDARD FEATURES
|
||||
|
||||
NONE
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
/* FIXME,
|
||||
* this is seriously broken,
|
||||
* once it was probably based upon htonl(),
|
||||
* yet with broken types
|
||||
* then the game has changed and strtoul() was used
|
||||
* with a ascii representation of the length
|
||||
* (probably as a hacky workaround, because it proved unreliable)
|
||||
* but the buffer is not terminated properly
|
||||
* Fix this when needed, currently this functionality looks like
|
||||
* an unused ancient artefact
|
||||
* Fix it with regard to ipc_transport_get_line() and ipc_transport_send_line()
|
||||
* and in concert with the actual user at the other side of the socket
|
||||
*/
|
||||
static u_long
|
||||
bytes_to_integer (
|
||||
char *str, /* IN - string that contains the bytes to convert */
|
||||
int start ) /* IN - index into string where bytes are */
|
||||
{
|
||||
uint32_t u; /* Value to be returned */
|
||||
char buff[4]; /* Transfer str into buff to word align reqd data */
|
||||
int index; /* Index into str and buff for transfer */
|
||||
|
||||
/* Get the str+start character and cast it into a u_long and put
|
||||
the value through the network-to-host-short converter and store
|
||||
it in the variable u. */
|
||||
|
||||
index = 0;
|
||||
while (index < (int) sizeof(u)) {
|
||||
buff[index] = str[index+start];
|
||||
index++;
|
||||
}
|
||||
/* u = ntohl (*((u_long *) buff)); */
|
||||
u = (uint32_t) strtoul(buff, NULL, 10);
|
||||
|
||||
return u;
|
||||
} /* end bytes_to_integer */
|
||||
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
|
||||
FUNCTION handle_socket_eof
|
||||
|
||||
AUTHORS
|
||||
|
||||
July 1991 Stefan Roth
|
||||
|
||||
MODIFICATIONS
|
||||
|
||||
NONE
|
||||
|
||||
SUMMARY
|
||||
|
||||
Do processing when the socket reaches EOF or when a message from the
|
||||
client states that EOF has been reached.
|
||||
|
||||
INTERFACES
|
||||
|
||||
Local to this file.
|
||||
Called by: ipc_transport_get_line();
|
||||
|
||||
RETURNED VALUE
|
||||
|
||||
Ipc_Status_t - always IPC_STATUS_EOF
|
||||
|
||||
GLOBAL VARIABLES
|
||||
|
||||
NONE
|
||||
|
||||
NON-STANDARD FEATURES
|
||||
|
||||
NONE
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
|
||||
static Ipc_Status_t
|
||||
handle_socket_eof (void)
|
||||
{
|
||||
close (msg_stream);
|
||||
close (sock_desc);
|
||||
|
||||
sock_state = IPC_SOCK_UNINITIALIZED;
|
||||
|
||||
return IPC_STATUS_EOF;
|
||||
} /* handle_socket_eof */
|
||||
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
|
||||
FUNCTION read_sock
|
||||
|
||||
AUTHORS
|
||||
|
||||
July 1991 Stefan Roth
|
||||
|
||||
MODIFICATIONS
|
||||
|
||||
NONE
|
||||
|
||||
SUMMARY
|
||||
|
||||
Read N bytes from a socket. Only returns when the read had an error,
|
||||
when 0 bytes (EOF) could be read, or LENGTH bytes are read.
|
||||
|
||||
INTERFACES
|
||||
|
||||
Local to this file.
|
||||
Called by: ipc_transport_get_line();
|
||||
|
||||
RETURNED VALUE
|
||||
|
||||
int - Returns the total number of bytes read.
|
||||
|
||||
GLOBAL VARIABLES
|
||||
|
||||
NONE
|
||||
|
||||
NON-STANDARD FEATURES
|
||||
|
||||
NONE
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
|
||||
static int
|
||||
read_sock (
|
||||
int stream, /* IN - Socket stream */
|
||||
char *buffer, /* OUT - buffer to store incoming data */
|
||||
int length, /* IN - Number of bytes to be read */
|
||||
Ipc_Wait_t wait, /* IN - type of read operation */
|
||||
int flags ) /* IN - Original socket flags for blocking read */
|
||||
{
|
||||
int count; /* Number of bytes read with last `read` */
|
||||
int totalcount; /* total number of bytes read */
|
||||
char *buf2;
|
||||
|
||||
/* count = 0; */
|
||||
/* while (count < length) { */
|
||||
/* buffer[count] = 'x'; */
|
||||
/* count++; */
|
||||
/* } */
|
||||
count = (int) read (stream, buffer, (size_t) length);
|
||||
if (wait == IPC_NO_WAIT) {
|
||||
fcntl (stream, F_SETFL, flags); /* Revert to blocking read */
|
||||
}
|
||||
if ((count <= 0) || (count == length)) {
|
||||
/* If error or if read in reqd number of bytes: */
|
||||
return count;
|
||||
} else {
|
||||
/* Only got some of the bytes requested */
|
||||
totalcount = count;
|
||||
buf2 = &buffer[totalcount];
|
||||
length = length - count;
|
||||
while (length > 0) {
|
||||
count = (int) read (stream, buf2, (size_t) length);
|
||||
if (count <= 0) /* EOF or read error */
|
||||
break;
|
||||
totalcount = totalcount + count;
|
||||
buf2 = &buffer[totalcount];
|
||||
length = length - count;
|
||||
}
|
||||
if (length != 0) {
|
||||
fprintf (stderr, "WARNING: READ_SOCK read %d bytes instead of %d\n",
|
||||
totalcount, totalcount + length);
|
||||
}
|
||||
return totalcount;
|
||||
}
|
||||
} /* end read_sock */
|
||||
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
|
||||
FUNCTION ipc_transport_get_line
|
||||
|
||||
AUTHORS
|
||||
|
||||
July 1991 Stefan Roth
|
||||
|
||||
MODIFICATIONS
|
||||
|
||||
NONE
|
||||
|
||||
SUMMARY
|
||||
|
||||
Main function for reading one line from a socket. Requires that the
|
||||
socket be open. Lines are mostly SPICE code, but commands may also
|
||||
be embedded in the socket data and they are interpreted by this function.
|
||||
Therefore, this function may cause the socket to be closed.
|
||||
|
||||
INTERFACES
|
||||
|
||||
Called by: ipc_transport_terminate_server();
|
||||
(IPC.c) ipc_get_line();
|
||||
|
||||
RETURNED VALUE
|
||||
|
||||
Ipc_Status_t - returns status of the read operation
|
||||
|
||||
GLOBAL VARIABLES
|
||||
|
||||
NONE
|
||||
|
||||
NON-STANDARD FEATURES
|
||||
|
||||
NONE
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_transport_get_line (
|
||||
char *str, /* returns the result, null terminated */
|
||||
int *len, /* length of str passed IN and passed OUT */
|
||||
Ipc_Wait_t wait ) /* IN - wait or dont wait on incoming msg */
|
||||
{
|
||||
int count = 0; /* number of bytes read */
|
||||
int message_length; /* extracted from message header */
|
||||
|
||||
if (sock_state == IPC_SOCK_UNINITIALIZED) {
|
||||
fprintf (stderr,
|
||||
"ERROR: IPC: Attempted to read from uninitialized socket\n");
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
assert ((sock_state == IPC_SOCK_CONNECTED_TO_CLIENT) ||
|
||||
(sock_state == IPC_SOCK_INITIALIZED));
|
||||
|
||||
if (sock_state == IPC_SOCK_INITIALIZED) {
|
||||
/* We have an open socket but have not connected to a client. */
|
||||
/* Accept a connection from a client. */
|
||||
msg_stream = accept (sock_desc, (struct sockaddr *)0, (socklen_t*)0);
|
||||
|
||||
if (msg_stream == -1) {
|
||||
fprintf (stderr, "ERROR: IPC: Server accepting request\n");
|
||||
perror ("ERROR: IPC");
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
sock_state = IPC_SOCK_CONNECTED_TO_CLIENT;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* First read in the message header. */
|
||||
{
|
||||
int flags;
|
||||
flags = fcntl(msg_stream, F_GETFL, NULL); /* Blocking read mode */
|
||||
|
||||
if (wait == IPC_WAIT) {
|
||||
/* Block here and wait for the next message */
|
||||
count = read_sock (msg_stream, str, SOCK_MSG_HDR_LEN, wait, flags);
|
||||
if (count == 0) {
|
||||
/* EOF, will this ever happen? */
|
||||
/* fprintf (stderr, "WARNING: IPC: Reached eof on socket\n"); */
|
||||
return handle_socket_eof ();
|
||||
}
|
||||
} else if (wait == IPC_NO_WAIT) {
|
||||
/* Read message, but do not wait if none available. */
|
||||
|
||||
fcntl (msg_stream, F_SETFL, flags | O_NDELAY);
|
||||
count = read_sock (msg_stream, str, SOCK_MSG_HDR_LEN, wait, flags);
|
||||
|
||||
if (count == 0) {
|
||||
/* EOF, will this ever happen? */
|
||||
/* fprintf (stderr, "WARNING: IPC: Reached eof on socket\n"); */
|
||||
return handle_socket_eof ();
|
||||
} else if (count == -1) {
|
||||
if (errno == EWOULDBLOCK) {
|
||||
return IPC_STATUS_NO_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Serious problem, since it is not reading anything. */
|
||||
fprintf (stderr,
|
||||
"ERROR: IPC: invalid wait arg to ipc_transport_get_line\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Do more error checking on the read in values of the message header: */
|
||||
if (count == -1) {
|
||||
fprintf (stderr, "ERROR: IPC: Reading from socket\n");
|
||||
perror ("ERROR: IPC");
|
||||
return IPC_STATUS_ERROR;
|
||||
} else if (str[0] != BOL_CHAR) {
|
||||
fprintf (stderr,
|
||||
"ERROR: IPC: Did not find beginning of message header (%c)\n",
|
||||
str[0]);
|
||||
return IPC_STATUS_ERROR;
|
||||
} else if ((message_length = (int) bytes_to_integer (str, 1)) == -1) {
|
||||
/* fprintf (stderr, "WARNING: IPC: Reached eof on socket\n"); */
|
||||
return handle_socket_eof ();
|
||||
} else if (message_length == 0) {
|
||||
*len = 0;
|
||||
return IPC_STATUS_NO_DATA;
|
||||
|
||||
/* Invalid test... delete - wbk
|
||||
} else if (message_length > *len) {
|
||||
fprintf (stderr,
|
||||
"ERROR: IPC: Buffer (%d) is too short for message (%d)\n",
|
||||
*len, message_length);
|
||||
return IPC_STATUS_ERROR;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Now read in the message body. */
|
||||
/* Always block here since the message header was already read and */
|
||||
/* we must get the body. */
|
||||
|
||||
*len = message_length;
|
||||
count = read_sock (msg_stream, str, message_length, IPC_WAIT, 0);
|
||||
if (count == 0) {
|
||||
/* EOF, will this ever happen? */
|
||||
/* fprintf (stderr, */
|
||||
/* "WARNING: IPC: Reached eof in message body on socket\n");*/
|
||||
return handle_socket_eof ();
|
||||
} else if (count == -1) {
|
||||
fprintf (stderr, "ERROR: IPC: reading message body from socket\n");
|
||||
perror ("ERROR: IPC");
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Looks like we have a valid message here. Put in the string terminator. */
|
||||
*len = count;
|
||||
str[count] = '\0';
|
||||
|
||||
return IPC_STATUS_OK;
|
||||
|
||||
} /* end ipc_transport_get_line */
|
||||
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
|
||||
FUNCTION ipc_transport_send_line
|
||||
|
||||
AUTHORS
|
||||
|
||||
July 1991 Stefan Roth
|
||||
|
||||
MODIFICATIONS
|
||||
|
||||
NONE
|
||||
|
||||
SUMMARY
|
||||
Send a line of information. First sends a message header and
|
||||
then the actual message body.
|
||||
Error checking is done to make reasonably sure that the data was sent.
|
||||
|
||||
|
||||
INTERFACES
|
||||
|
||||
Called by: (IPC.c) ipc_flush ();
|
||||
|
||||
RETURNED VALUE
|
||||
|
||||
Ipc_Status_t - returns status of the send operation (typically
|
||||
IPC_STATUS_ERROR or IPC_STATUS_OK).
|
||||
|
||||
|
||||
GLOBAL VARIABLES
|
||||
|
||||
NONE
|
||||
|
||||
NON-STANDARD FEATURES
|
||||
|
||||
NONE
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_transport_send_line (
|
||||
char *str, /* IN - String to write */
|
||||
int len ) /* IN - Number of characters out of STR to write */
|
||||
{
|
||||
int count; /* Counts how many bytes were actually written */
|
||||
u_long u; /* 32-bit placeholder for transmission of LEN */
|
||||
char hdr_buff[5]; /* Buffer for building header message in */
|
||||
int i; /* Temporary counter */
|
||||
char *char_ptr; /* Pointer for int to bytes conversion */
|
||||
|
||||
if (sock_state != IPC_SOCK_CONNECTED_TO_CLIENT) {
|
||||
fprintf (stderr, "ERROR: IPC: Attempt to write to non-open socket\n");
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Write message body header with length: */
|
||||
hdr_buff[0] = BOL_CHAR;
|
||||
u = htonl ((uint32_t) len);
|
||||
char_ptr = (char *) &u;
|
||||
for(i = 0; i < 4; i++)
|
||||
hdr_buff[i+1] = char_ptr[i];
|
||||
|
||||
count = (int) write (msg_stream, hdr_buff, 5);
|
||||
if (count != 5) {
|
||||
fprintf (stderr, "ERROR: IPC: (%d) send line error 1\n", count);
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Write message body: */
|
||||
count = (int) write (msg_stream, str, (size_t) len);
|
||||
if (count != len) {
|
||||
fprintf (stderr, "ERROR: IPC: (%d) send line error 2\n", count);
|
||||
return IPC_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return IPC_STATUS_OK;
|
||||
} /* end ipc_transport_send_line */
|
||||
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
|
||||
FUNCTION ipc_transport_terminate_server
|
||||
|
||||
AUTHORS
|
||||
|
||||
July 1991 Stefan Roth
|
||||
|
||||
MODIFICATIONS
|
||||
|
||||
NONE
|
||||
|
||||
SUMMARY
|
||||
|
||||
This function reads all pending incoming messages and discards them.
|
||||
Reading continues until a read error occurs or EOF is reached, at which
|
||||
time the socket is closed.
|
||||
Note that this function does not actually close the socket. This is
|
||||
done in ipc_transport_get_line, which is called in this function.
|
||||
|
||||
In this function, the incoming line length is limited. See buffer below.
|
||||
|
||||
INTERFACES
|
||||
|
||||
Called by: (IPC.c) ipc_terminate_server();
|
||||
|
||||
RETURNED VALUE
|
||||
|
||||
Ipc_Status_t - returns status of last read operation (always
|
||||
IPC_STATUS_ERROR or IPC_STATUS_EOF).
|
||||
|
||||
GLOBAL VARIABLES
|
||||
|
||||
NONE
|
||||
|
||||
NON-STANDARD FEATURES
|
||||
|
||||
NONE
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
|
||||
Ipc_Status_t
|
||||
ipc_transport_terminate_server (void)
|
||||
{
|
||||
char buffer[17000]; /* temp buffer for incoming data */
|
||||
int len; /* placeholder var to as arg to function */
|
||||
Ipc_Status_t status; /* value to be returned from function */
|
||||
int max_size; /* Max length of buffer */
|
||||
|
||||
max_size = sizeof (buffer);
|
||||
do {
|
||||
len = max_size;
|
||||
status = ipc_transport_get_line (buffer, &len, IPC_WAIT);
|
||||
} while ((status != IPC_STATUS_ERROR) &&
|
||||
(status != IPC_STATUS_EOF));
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* IPC_UNIX_SOCKETS */
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Steve Tynor
|
||||
*
|
||||
* Generic Interprocess Communication module
|
||||
*
|
||||
* Used for debugging in absense of IPC interface.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ngspice/ngspice.h"
|
||||
|
||||
#ifdef IPC_DEBUG_VIA_STDIO
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include "ngspice/ipc.h"
|
||||
|
||||
#include "ngspice/ipcproto.h"
|
||||
|
||||
#include <assert.h> /* 12/1/97 jg */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
Ipc_Status_t ipc_transport_initialize_server (
|
||||
char *server_name,
|
||||
Ipc_Mode_t m,
|
||||
Ipc_Protocol_t p,
|
||||
char *batch_filename )
|
||||
{
|
||||
NG_IGNORE(server_name);
|
||||
NG_IGNORE(p);
|
||||
NG_IGNORE(batch_filename);
|
||||
|
||||
assert (m == IPC_MODE_INTERACTIVE);
|
||||
printf ("INITIALIZE_SERVER\n");
|
||||
return IPC_STATUS_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
Ipc_Status_t ipc_transport_get_line (
|
||||
char *str,
|
||||
int *len,
|
||||
Ipc_Wait_t wait )
|
||||
{
|
||||
NG_IGNORE(wait);
|
||||
|
||||
printf ("GET_LINE\n");
|
||||
fgets (str, 512, stdin);
|
||||
char *tmp = strchr(str, '\n');
|
||||
if (tmp)
|
||||
*tmp = '\0';
|
||||
*len = (int) strlen (str);
|
||||
return IPC_STATUS_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
Ipc_Status_t ipc_transport_send_line (
|
||||
char *str,
|
||||
int len )
|
||||
{
|
||||
int i;
|
||||
|
||||
printf ("SEND_LINE: /");
|
||||
for (i = 0; i < len; i++)
|
||||
putchar (str[i]);
|
||||
printf ("/\n");
|
||||
return IPC_STATUS_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
Ipc_Status_t ipc_transport_terminate_server (void)
|
||||
{
|
||||
return IPC_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
#endif /* IPC_DEBUG_VIA_STDIO */
|
||||
|
|
@ -1,520 +0,0 @@
|
|||
/*============================================================================
|
||||
FILE IPCtiein.c
|
||||
|
||||
MEMBER OF process XSPICE
|
||||
|
||||
Public Domain
|
||||
|
||||
Georgia Tech Research Corporation
|
||||
Atlanta, Georgia 30332
|
||||
PROJECT A-8503
|
||||
|
||||
AUTHORS
|
||||
|
||||
9/12/91 Bill Kuhn
|
||||
|
||||
MODIFICATIONS
|
||||
|
||||
<date> <person name> <nature of modifications>
|
||||
|
||||
SUMMARY
|
||||
|
||||
Provides a protocol independent interface between the simulator
|
||||
and the IPC method used to interface to CAE packages.
|
||||
|
||||
INTERFACES
|
||||
|
||||
g_ipc (global variable)
|
||||
|
||||
ipc_handle_stop()
|
||||
ipc_handle_returni()
|
||||
ipc_handle_mintime()
|
||||
ipc_handle_vtrans()
|
||||
ipc_send_stdout()
|
||||
ipc_send_stderr()
|
||||
ipc_send_std_files()
|
||||
ipc_screen_name()
|
||||
ipc_get_devices()
|
||||
ipc_free_devices()
|
||||
ipc_check_pause_stop()
|
||||
|
||||
REFERENCED FILES
|
||||
|
||||
None.
|
||||
|
||||
NON-STANDARD FEATURES
|
||||
|
||||
None.
|
||||
|
||||
============================================================================*/
|
||||
|
||||
|
||||
#define CONFIG
|
||||
|
||||
#include "ngspice/ngspice.h"
|
||||
#include "ngspice/inpdefs.h"
|
||||
#include "ngspice/gendefs.h"
|
||||
#include "ngspice/cktdefs.h"
|
||||
#include "bjt/bjtdefs.h"
|
||||
#include "jfet/jfetdefs.h"
|
||||
#include "mos1/mos1defs.h"
|
||||
#include "mos2/mos2defs.h"
|
||||
#include "mos3/mos3defs.h"
|
||||
#include "ngspice/mifproto.h"
|
||||
#include "ngspice/ipc.h"
|
||||
#include "ngspice/ipctiein.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Global variable g_ipc is used by the SPICE mods that take care of
|
||||
interprocess communications activities.
|
||||
*/
|
||||
|
||||
|
||||
Ipc_Tiein_t g_ipc = {
|
||||
IPC_FALSE, /* enabled */
|
||||
IPC_MODE_INTERACTIVE, /* mode */
|
||||
IPC_ANAL_DCOP, /* analysis mode */
|
||||
IPC_FALSE, /* parse_error */
|
||||
IPC_FALSE, /* run_error */
|
||||
IPC_FALSE, /* errchk_sent */
|
||||
IPC_FALSE, /* returni */
|
||||
0.0, /* mintime */
|
||||
0.0, /* lasttime */
|
||||
0.0, /* cpu time */
|
||||
NULL, /* send array */
|
||||
NULL, /* log file */
|
||||
{ /* vtrans struct */
|
||||
0, /* size */
|
||||
NULL, /* vsrc_name array */
|
||||
NULL, /* device_name array */
|
||||
},
|
||||
IPC_FALSE, /* stop analysis */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ipc_handle_stop
|
||||
|
||||
This function sets a flag in the g_ipc variable to signal that
|
||||
a stop message has been received over the IPC channel.
|
||||
*/
|
||||
|
||||
void ipc_handle_stop(void)
|
||||
{
|
||||
g_ipc.stop_analysis = IPC_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ipc_handle_returni
|
||||
|
||||
This function sets a flag in the g_ipc variable to signal that
|
||||
a message has been received over the IPC channel specifying that
|
||||
current values are to be returned in the results data sets.
|
||||
*/
|
||||
|
||||
void ipc_handle_returni(void)
|
||||
{
|
||||
g_ipc.returni = IPC_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ipc_handle_mintime
|
||||
|
||||
This function sets a value in the g_ipc variable that specifies
|
||||
how often data is to be returned as it is computed. If the
|
||||
simulator takes timestep backups, data may still be returned
|
||||
more often that that specified by 'mintime' so that glitches
|
||||
are not missed.
|
||||
*/
|
||||
|
||||
void ipc_handle_mintime(double time)
|
||||
{
|
||||
g_ipc.mintime = time;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ipc_handle_vtrans
|
||||
|
||||
This function processes arguments from a #VTRANS card received over
|
||||
the IPC channel. The data on the card specifies that a particular
|
||||
zero-valued voltage source name should be translated to the specified
|
||||
instance name for which it was setup to monitor currents.
|
||||
*/
|
||||
|
||||
void ipc_handle_vtrans(
|
||||
char *vsrc, /* The name of the voltage source to be translated */
|
||||
char *dev) /* The device name the vsource name should be translated to */
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
|
||||
|
||||
if(g_ipc.vtrans.size == 0) {
|
||||
g_ipc.vtrans.size = 1;
|
||||
g_ipc.vtrans.vsrc_name = TMALLOC(char *, 1);
|
||||
g_ipc.vtrans.device_name = TMALLOC(char *, 1);
|
||||
g_ipc.vtrans.vsrc_name[0] = MIFcopy(vsrc);
|
||||
g_ipc.vtrans.device_name[0] = MIFcopy(dev);
|
||||
}
|
||||
else {
|
||||
g_ipc.vtrans.size++;
|
||||
|
||||
size = g_ipc.vtrans.size;
|
||||
i = g_ipc.vtrans.size - 1;
|
||||
|
||||
g_ipc.vtrans.vsrc_name = TREALLOC(char *, g_ipc.vtrans.vsrc_name, size);
|
||||
g_ipc.vtrans.device_name = TREALLOC(char *, g_ipc.vtrans.device_name, size);
|
||||
g_ipc.vtrans.vsrc_name[i] = MIFcopy(vsrc);
|
||||
g_ipc.vtrans.device_name[i] = MIFcopy(dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ipc_send_stdout
|
||||
|
||||
This function sends the data written to stdout over the IPC channel.
|
||||
This stream was previously redirected to a temporary file during
|
||||
the simulation.
|
||||
*/
|
||||
|
||||
void ipc_send_stdout(void)
|
||||
{
|
||||
int c;
|
||||
int len;
|
||||
|
||||
char buf[IPC_MAX_LINE_LEN+1];
|
||||
|
||||
/* rewind the redirected stdout stream */
|
||||
rewind(stdout);
|
||||
|
||||
/* Begin reading from the top of file and send lines */
|
||||
/* over the IPC channel. */
|
||||
|
||||
/* Don't send newlines. Also, if line is > IPC_MAX_LINE_LEN chars */
|
||||
/* we must wrap it because Mspice can't handle it */
|
||||
|
||||
len = 0;
|
||||
while( (c=fgetc(stdout)) != EOF) {
|
||||
if(c != '\n') {
|
||||
buf[len] = (char) c;
|
||||
len++;
|
||||
}
|
||||
if((c == '\n') || (len == IPC_MAX_LINE_LEN)) {
|
||||
buf[len] = '\0';
|
||||
ipc_send_line(buf);
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
if(len > 0) {
|
||||
buf[len] = '\0';
|
||||
ipc_send_line(buf);
|
||||
}
|
||||
|
||||
/* Finally, rewind file again to discard the data already sent */
|
||||
rewind(stdout);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ipc_send_stderr
|
||||
|
||||
This function sends the data written to stderr over the IPC channel.
|
||||
This stream was previously redirected to a temporary file during
|
||||
the simulation.
|
||||
*/
|
||||
|
||||
void ipc_send_stderr(void)
|
||||
{
|
||||
int c;
|
||||
int len;
|
||||
|
||||
char buf[IPC_MAX_LINE_LEN+1];
|
||||
|
||||
/* rewind the redirected stderr stream */
|
||||
rewind(stderr);
|
||||
|
||||
/* Begin reading from the top of file and send lines */
|
||||
/* over the IPC channel. */
|
||||
|
||||
/* Don't send newlines. Also, if line is > IPC_MAX_LINE_LEN chars */
|
||||
/* we must wrap it because Mspice can't handle it */
|
||||
|
||||
len = 0;
|
||||
while( (c=fgetc(stderr)) != EOF) {
|
||||
if(c != '\n') {
|
||||
buf[len] = (char) c;
|
||||
len++;
|
||||
}
|
||||
if((c == '\n') || (len == IPC_MAX_LINE_LEN)) {
|
||||
buf[len] = '\0';
|
||||
ipc_send_line(buf);
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
if(len > 0) {
|
||||
buf[len] = '\0';
|
||||
ipc_send_line(buf);
|
||||
}
|
||||
|
||||
/* Finally, rewind file again to discard the data already sent */
|
||||
rewind(stderr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ipc_send_std_files
|
||||
|
||||
This function sends the data written to stdout and stderr over the
|
||||
IPC channel. These streams were previously redirected to temporary
|
||||
files during the simulation.
|
||||
*/
|
||||
|
||||
Ipc_Status_t ipc_send_std_files(void)
|
||||
{
|
||||
ipc_send_stdout();
|
||||
ipc_send_stderr();
|
||||
|
||||
return(ipc_flush());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ipc_screen_name
|
||||
|
||||
This function screens names of instances and nodes to limit the
|
||||
data returned over the IPC channel.
|
||||
*/
|
||||
|
||||
Ipc_Boolean_t ipc_screen_name(char *name, char *mapped_name)
|
||||
{
|
||||
char *endp;
|
||||
int i;
|
||||
int len;
|
||||
long l;
|
||||
|
||||
/* Return FALSE if name is in a subcircuit */
|
||||
for(i = 0; name[i] != '\0'; i++) {
|
||||
if(name[i] == ':')
|
||||
return(IPC_FALSE);
|
||||
}
|
||||
|
||||
/* Determine if name is numeric and what value is */
|
||||
l = strtol(name, &endp, 10);
|
||||
|
||||
/* If numeric */
|
||||
if(*endp == '\0') {
|
||||
/* Return FALSE if >100,000 -> added by ms_server in ATESSE 1.0 */
|
||||
if(l >= 100000)
|
||||
return(IPC_FALSE);
|
||||
/* Otherwise, copy name to mapped name and return true */
|
||||
else {
|
||||
strcpy(mapped_name,name);
|
||||
return(IPC_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* If node is an internal node from a semiconductor (indicated by a */
|
||||
/* trailing #collector, #source, ...), do not return its current. */
|
||||
/* Otherwise, map to upper case and eliminate trailing "#branch" if any. */
|
||||
for(i = 0; name[i]; i++) {
|
||||
if(name[i] == '#') {
|
||||
if(strcmp(name + i, "#branch") == 0)
|
||||
break;
|
||||
else
|
||||
return(IPC_FALSE);
|
||||
}
|
||||
else {
|
||||
if(islower_c(name[i]))
|
||||
mapped_name[i] = toupper_c(name[i]);
|
||||
else
|
||||
mapped_name[i] = name[i];
|
||||
}
|
||||
}
|
||||
mapped_name[i] = '\0';
|
||||
len = i;
|
||||
|
||||
/* If len != 8 or 6'th char not equal to $, then doesn't need vtrans */
|
||||
/* Otherwise, translate to device name that it monitors */
|
||||
if(len != 8)
|
||||
return(IPC_TRUE);
|
||||
else if(name[5] != '$')
|
||||
return(IPC_TRUE);
|
||||
else {
|
||||
/* Scan list of prefixes in VTRANS table and convert name */
|
||||
for(i = 0; i < g_ipc.vtrans.size; i++) {
|
||||
if(strncmp(mapped_name, g_ipc.vtrans.vsrc_name[i], 5) == 0) {
|
||||
strcpy(mapped_name, g_ipc.vtrans.device_name[i]);
|
||||
return(IPC_TRUE);
|
||||
}
|
||||
}
|
||||
return(IPC_TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ipc_get_devices
|
||||
|
||||
This function is used to setup the OUTinterface data structure that
|
||||
determines what instances will have data returned over the IPC channel.
|
||||
*/
|
||||
|
||||
|
||||
int ipc_get_devices(
|
||||
CKTcircuit *ckt, /* The circuit structure */
|
||||
char *device, /* The device name as it appears in the info struct */
|
||||
char ***names, /* Array of name strings to be built */
|
||||
double **modtypes) /* Array of types to be built */
|
||||
{
|
||||
int index;
|
||||
int num_instances;
|
||||
GENmodel *model;
|
||||
GENinstance *here;
|
||||
char *inst_name;
|
||||
int inst_name_len;
|
||||
int i;
|
||||
|
||||
BJTmodel *BJTmod;
|
||||
JFETmodel *JFETmod;
|
||||
MOS1model *MOS1mod;
|
||||
MOS2model *MOS2mod;
|
||||
MOS3model *MOS3mod;
|
||||
|
||||
/* Initialize local variables */
|
||||
num_instances = 0;
|
||||
|
||||
/* Get the index into the circuit structure linked list of models */
|
||||
index = INPtypelook(device);
|
||||
|
||||
/* Iterate through all models of this type */
|
||||
for(model = ckt->CKThead[index]; model; model = model->GENnextModel) {
|
||||
|
||||
/* Iterate through all instance of this model */
|
||||
for(here = model->GENinstances; here; here = here->GENnextInstance) {
|
||||
|
||||
/* Get the name of the instance */
|
||||
inst_name = here->GENname;
|
||||
inst_name_len = (int) strlen(inst_name);
|
||||
|
||||
/* Skip if it is a inside a subcircuit */
|
||||
for(i = 0; i < inst_name_len; i++)
|
||||
if(inst_name[i] == ':')
|
||||
break;
|
||||
if(i < inst_name_len)
|
||||
continue;
|
||||
|
||||
/* Otherwise, add the name to the list */
|
||||
num_instances++;
|
||||
if(num_instances == 1)
|
||||
*names = TMALLOC(char *, 1);
|
||||
else
|
||||
*names = TREALLOC(char *, *names, num_instances);
|
||||
(*names)[num_instances-1] = MIFcopy(inst_name);
|
||||
|
||||
/* Then get the type if it is a Q J or M */
|
||||
if(num_instances == 1)
|
||||
*modtypes = TMALLOC(double, 1);
|
||||
else
|
||||
*modtypes = TREALLOC(double, *modtypes, num_instances);
|
||||
|
||||
if(strcmp(device,"BJT") == 0) {
|
||||
BJTmod = (BJTmodel *) model;
|
||||
(*modtypes)[num_instances-1] = BJTmod->BJTtype;
|
||||
}
|
||||
else if(strcmp(device,"JFET") == 0) {
|
||||
JFETmod = (JFETmodel *) model;
|
||||
(*modtypes)[num_instances-1] = JFETmod->JFETtype;
|
||||
}
|
||||
else if(strcmp(device,"Mos1") == 0) {
|
||||
MOS1mod = (MOS1model *) model;
|
||||
(*modtypes)[num_instances-1] = MOS1mod->MOS1type;
|
||||
}
|
||||
else if(strcmp(device,"Mos2") == 0) {
|
||||
MOS2mod = (MOS2model *) model;
|
||||
(*modtypes)[num_instances-1] = MOS2mod->MOS2type;
|
||||
}
|
||||
else if(strcmp(device,"Mos3") == 0) {
|
||||
MOS3mod = (MOS3model *) model;
|
||||
(*modtypes)[num_instances-1] = MOS3mod->MOS3type;
|
||||
}
|
||||
else {
|
||||
(*modtypes)[num_instances-1] = 1.0;
|
||||
}
|
||||
|
||||
} /* end for all instances */
|
||||
} /* end for all models */
|
||||
|
||||
return(num_instances);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ipc_free_devices
|
||||
|
||||
This function frees temporary data created by ipc_get_devices().
|
||||
*/
|
||||
|
||||
|
||||
void ipc_free_devices(
|
||||
int num_items, /* Number of things to free */
|
||||
char **names, /* Array of name strings to be built */
|
||||
double *modtypes) /* Array of types to be built */
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < num_items; i++)
|
||||
{
|
||||
FREE(names[i]);
|
||||
names[i] = NULL;
|
||||
}
|
||||
|
||||
if(num_items > 0)
|
||||
{
|
||||
FREE(names);
|
||||
FREE(modtypes);
|
||||
|
||||
names = NULL;
|
||||
modtypes = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ipc_check_pause_stop
|
||||
|
||||
This function is called at various times during a simulation to check
|
||||
for incoming messages of the form >STOP or >PAUSE signaling that
|
||||
simulation should be stopped or paused. Processing of the messages
|
||||
is handled by ipc_get_line().
|
||||
*/
|
||||
|
||||
void ipc_check_pause_stop(void)
|
||||
{
|
||||
char buf[1025];
|
||||
int len;
|
||||
|
||||
/* If already seen stop analysis, don't call ipc_get_line, just return. */
|
||||
/* This is provided so that the function can be called multiple times */
|
||||
/* during the process of stopping */
|
||||
if(g_ipc.stop_analysis)
|
||||
return;
|
||||
|
||||
/* Otherwise do a non-blocking call to ipc_get_line() to check for messages. */
|
||||
/* We assume that the only possible messages at this point are >PAUSE */
|
||||
/* and >STOP, so we don't do anything with the returned text if any */
|
||||
ipc_get_line(buf, &len, IPC_NO_WAIT);
|
||||
}
|
||||
|
||||
|
|
@ -794,8 +794,6 @@ lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3
|
|||
<ClInclude Include="..\src\include\ngspice\inpmacs.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\inpptree.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\ipc.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\ipcproto.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\ipctiein.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\jobdefs.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\lsort.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\macros.h" />
|
||||
|
|
@ -2612,11 +2610,6 @@ lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3
|
|||
<ClCompile Include="..\src\xspice\evt\evtshared.c" />
|
||||
<ClCompile Include="..\src\xspice\evt\evttermi.c" />
|
||||
<ClCompile Include="..\src\xspice\idn\idndig.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipc.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipcaegis.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipcsockets.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipcstdio.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipctiein.c" />
|
||||
<ClCompile Include="..\src\xspice\mif\mif.c" />
|
||||
<ClCompile Include="..\src\xspice\mif\mifask.c" />
|
||||
<ClCompile Include="..\src\xspice\mif\mifbindCSC.c" />
|
||||
|
|
|
|||
|
|
@ -1011,8 +1011,6 @@ lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3
|
|||
<ClInclude Include="..\src\include\ngspice\inpmacs.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\inpptree.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\ipc.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\ipcproto.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\ipctiein.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\jobdefs.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\lsort.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\macros.h" />
|
||||
|
|
@ -2832,11 +2830,6 @@ lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3
|
|||
<ClCompile Include="..\src\xspice\evt\evtsetup.c" />
|
||||
<ClCompile Include="..\src\xspice\evt\evttermi.c" />
|
||||
<ClCompile Include="..\src\xspice\idn\idndig.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipc.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipcaegis.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipcsockets.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipcstdio.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipctiein.c" />
|
||||
<ClCompile Include="..\src\xspice\mif\mif.c" />
|
||||
<ClCompile Include="..\src\xspice\mif\mifask.c" />
|
||||
<ClCompile Include="..\src\xspice\mif\mifbindCSC.c" />
|
||||
|
|
|
|||
|
|
@ -1026,8 +1026,6 @@
|
|||
<ClInclude Include="..\src\include\ngspice\inpmacs.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\inpptree.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\ipc.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\ipcproto.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\ipctiein.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\jobdefs.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\lsort.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\macros.h" />
|
||||
|
|
@ -2847,11 +2845,6 @@
|
|||
<ClCompile Include="..\src\xspice\evt\evtsetup.c" />
|
||||
<ClCompile Include="..\src\xspice\evt\evttermi.c" />
|
||||
<ClCompile Include="..\src\xspice\idn\idndig.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipc.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipcaegis.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipcsockets.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipcstdio.c" />
|
||||
<ClCompile Include="..\src\xspice\ipc\ipctiein.c" />
|
||||
<ClCompile Include="..\src\xspice\mif\mif.c" />
|
||||
<ClCompile Include="..\src\xspice\mif\mifask.c" />
|
||||
<ClCompile Include="..\src\xspice\mif\mifbindCSC.c" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue