Compare commits

...

2 Commits

Author SHA1 Message Date
Holger Vogt d5ef8a3660 Remove all entries connected to IPC, an outdated (>30 years)
method to link ngspice to a now defunct controller (ATESSE).
2025-10-21 11:18:22 +02:00
Holger Vogt 8e0622434f Improve comments, add note to user. 2025-10-20 16:07:19 +02:00
26 changed files with 61 additions and 3395 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
/*

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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