int DCtrCurv(CKTcircuit *ckt, int restart) { TRCV *job = (TRCV *) ckt->CKTcurJob; int i; double *temp; int converged; int rcode; int vcode; int icode; int j; int error; IFuid varUid; IFuid *nameList; int numNames; int firstTime = 1; static runDesc *plot = NULL; #ifdef WANT_SENSE2 long save; #ifdef SENSDEBUG if (ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & DCSEN)) { printf("\nDC Sensitivity Results\n\n"); CKTsenPrint(ckt); } #endif #endif rcode = CKTtypelook("Resistor"); vcode = CKTtypelook("Vsource"); icode = CKTtypelook("Isource"); if (!restart && job->TRCVnestState >= 0) { /* continuing */ i = job->TRCVnestState; /* resume to work? saj*/ error = SPfrontEnd->OUTpBeginPlot (NULL, NULL, NULL, NULL, 0, 666, NULL, 666, &plot); goto resume; } ckt->CKTtime = 0; ckt->CKTdelta = job->TRCVvStep[0]; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT; ckt->CKTorder = 1; /* Save the state of the circuit */ for (j = 0; j < 7; j++) ckt->CKTdeltaOld[j] = ckt->CKTdelta; for (i = 0; i <= job->TRCVnestLevel; i++) { if (rcode >= 0) { /* resistances are in this version, so use them */ RESinstance *here; RESmodel *model; for (model = (RESmodel *)ckt->CKThead[rcode]; model; model = model->RESnextModel) for (here = model->RESinstances; here; here = here->RESnextInstance) if (here->RESname == job->TRCVvName[i]) { job->TRCVvElt[i] = (GENinstance *)here; job->TRCVvSave[i] = here->RESresist; job->TRCVgSave[i] = here->RESresGiven; job->TRCVvType[i] = rcode; here->RESresist = job->TRCVvStart[i]; here->RESresGiven = 1; CKTtemp(ckt); goto found; } } if (vcode >= 0) { /* voltage sources are in this version, so use them */ VSRCinstance *here; VSRCmodel *model; for (model = (VSRCmodel *)ckt->CKThead[vcode]; model; model = model->VSRCnextModel) for (here = model->VSRCinstances; here; here = here->VSRCnextInstance) if (here->VSRCname == job->TRCVvName[i]) { job->TRCVvElt[i] = (GENinstance *)here; job->TRCVvSave[i] = here->VSRCdcValue; job->TRCVgSave[i] = here->VSRCdcGiven; job->TRCVvType[i] = vcode; here->VSRCdcValue = job->TRCVvStart[i]; here->VSRCdcGiven = 1; goto found; } } if (icode >= 0) { /* current sources are in this version, so use them */ ISRCinstance *here; ISRCmodel *model; for (model = (ISRCmodel *)ckt->CKThead[icode]; model; model = model->ISRCnextModel) for (here = model->ISRCinstances; here; here = here->ISRCnextInstance) if (here->ISRCname == job->TRCVvName[i]) { job->TRCVvElt[i] = (GENinstance *)here; job->TRCVvSave[i] = here->ISRCdcValue; job->TRCVgSave[i] = here->ISRCdcGiven; job->TRCVvType[i] = icode; here->ISRCdcValue = job->TRCVvStart[i]; here->ISRCdcGiven = 1; goto found; } } if (!strcmp(job->TRCVvName[i], "temp")) { job->TRCVvSave[i] = ckt->CKTtemp; /* Saves the old circuit temperature */ job->TRCVvType[i] = TEMP_CODE; /* Set the sweep type code */ ckt->CKTtemp = job->TRCVvStart[i] + CONSTCtoK; /* Set the new circuit temp */ if (expr_w_temper) inp_evaluate_temper(); CKTtemp(ckt); goto found; } SPfrontEnd->IFerrorf (ERR_FATAL, "DCtrCurv: source / resistor %s not in circuit", job->TRCVvName[i]); return(E_NODEV); found:; } #ifdef HAS_PROGREP actval = job->TRCVvStart[job->TRCVnestLevel]; actdiff = job->TRCVvStart[job->TRCVnestLevel] - job->TRCVvStop[job->TRCVnestLevel]; #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); if (error) return(error); i = job->TRCVnestLevel; if (job->TRCVvType[i] == vcode) SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "v-sweep", UID_OTHER, NULL); else if (job->TRCVvType[i] == icode) SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "i-sweep", UID_OTHER, NULL); else if (job->TRCVvType[i] == TEMP_CODE) SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "temp-sweep", UID_OTHER, NULL); else if (job->TRCVvType[i] == rcode) SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "res-sweep", UID_OTHER, NULL); else SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "?-sweep", UID_OTHER, NULL); error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, ckt->CKTcurJob->JOBname, varUid, IF_REAL, numNames, nameList, IF_REAL, &plot); tfree(nameList); if (error) return(error); /* initialize CKTsoaCheck `warn' counters */ if (ckt->CKTsoaCheck) error = CKTsoaInit(); /* now have finished the initialization - can start doing hard part */ i = 0; resume: for (;;) { if (job->TRCVvType[i] == vcode) { /* voltage source */ if (SGN(job->TRCVvStep[i]) * (((VSRCinstance*)(job->TRCVvElt[i]))->VSRCdcValue - job->TRCVvStop[i]) > DBL_EPSILON * 1e+03) { i++; firstTime = 1; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT; if (i > job->TRCVnestLevel) break; goto nextstep; } } else if (job->TRCVvType[i] == icode) { /* current source */ if (SGN(job->TRCVvStep[i]) * (((ISRCinstance*)(job->TRCVvElt[i]))->ISRCdcValue - job->TRCVvStop[i]) > DBL_EPSILON * 1e+03) { i++; firstTime = 1; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT; if (i > job->TRCVnestLevel) break; goto nextstep; } } else if (job->TRCVvType[i] == rcode) { /* resistance */ if (SGN(job->TRCVvStep[i]) * (((RESinstance*)(job->TRCVvElt[i]))->RESresist - job->TRCVvStop[i]) > DBL_EPSILON * 1e+03) { i++; firstTime = 1; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT; if (i > job->TRCVnestLevel) break; goto nextstep; } } else if (job->TRCVvType[i] == TEMP_CODE) { /* temp sweep */ if (SGN(job->TRCVvStep[i]) * ((ckt->CKTtemp - CONSTCtoK) - job->TRCVvStop[i]) > DBL_EPSILON * 1e+03) { i++; firstTime = 1; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT; if (i > job->TRCVnestLevel) break; goto nextstep; } } while (--i >= 0) if (job->TRCVvType[i] == vcode) { /* voltage source */ ((VSRCinstance *)(job->TRCVvElt[i]))->VSRCdcValue = job->TRCVvStart[i]; } else if (job->TRCVvType[i] == icode) { /* current source */ ((ISRCinstance *)(job->TRCVvElt[i]))->ISRCdcValue = job->TRCVvStart[i]; } else if (job->TRCVvType[i] == TEMP_CODE) { ckt->CKTtemp = job->TRCVvStart[i] + CONSTCtoK; if (expr_w_temper) inp_evaluate_temper(); CKTtemp(ckt); } else if (job->TRCVvType[i] == rcode) { ((RESinstance *)(job->TRCVvElt[i]))->RESresist = job->TRCVvStart[i]; /* RESload() needs conductance as well */ ((RESinstance *)(job->TRCVvElt[i]))->RESconduct = 1 / (((RESinstance *)(job->TRCVvElt[i]))->RESresist); DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt); } /* Rotate state vectors. */ temp = ckt->CKTstates[ckt->CKTmaxOrder + 1]; for (j = ckt->CKTmaxOrder; j >= 0; j--) ckt->CKTstates[j + 1] = ckt->CKTstates[j]; ckt->CKTstate0 = temp; /* do operation */ #ifdef XSPICE /* gtri - begin - wbk - Do EVTop if event instances exist */ if (ckt->evt->counts.num_insts == 0) { /* If no event-driven instances, do what SPICE normally does */ #endif converged = NIiter(ckt, ckt->CKTdcTrcvMaxIter); if (converged != 0) { converged = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT, ckt->CKTdcMaxIter); if (converged != 0) return(converged); } #ifdef XSPICE } else { /* else do new algorithm */ /* first get the current step in the analysis */ if (job->TRCVvType[0] == vcode) { g_mif_info.circuit.evt_step = ((VSRCinstance *)(job->TRCVvElt[0]))->VSRCdcValue; } else if (job->TRCVvType[0] == icode) { g_mif_info.circuit.evt_step = ((ISRCinstance *)(job->TRCVvElt[0]))->ISRCdcValue; } else if (job->TRCVvType[0] == rcode) { g_mif_info.circuit.evt_step = ((RESinstance*)(job->TRCVvElt[0]->GENmodPtr))->RESresist; } else if (job->TRCVvType[0] == TEMP_CODE) { g_mif_info.circuit.evt_step = ckt->CKTtemp - CONSTCtoK; } /* if first time through, call EVTop immediately and save event results */ if (firstTime) { converged = EVTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT, ckt->CKTdcMaxIter, MIF_TRUE); EVTdump(ckt, IPC_ANAL_DCOP, g_mif_info.circuit.evt_step); EVTop_save(ckt, MIF_FALSE, g_mif_info.circuit.evt_step); if (converged != 0) return(converged); } /* else, call NIiter first with mode = MODEINITPRED */ /* to attempt quick analog solution. Then call all hybrids and call */ /* EVTop only if event outputs have changed, or if non-converged */ else { converged = NIiter(ckt, ckt->CKTdcTrcvMaxIter); EVTcall_hybrids(ckt); if ((converged != 0) || (ckt->evt->queue.output.num_changed != 0)) { converged = EVTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT, ckt->CKTdcMaxIter, MIF_FALSE); EVTdump(ckt, IPC_ANAL_DCTRCURVE, g_mif_info.circuit.evt_step); EVTop_save(ckt, MIF_FALSE, g_mif_info.circuit.evt_step); if (converged != 0) return(converged); } } } /* gtri - end - wbk - Do EVTop if event instances exist */ #endif ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITPRED; if (job->TRCVvType[0] == vcode) ckt->CKTtime = ((VSRCinstance *)(job->TRCVvElt[0]))->VSRCdcValue; else if (job->TRCVvType[0] == icode) ckt->CKTtime = ((ISRCinstance *)(job->TRCVvElt[0]))->ISRCdcValue; else if (job->TRCVvType[0] == rcode) ckt->CKTtime = ((RESinstance *)(job->TRCVvElt[0]))->RESresist; else if (job->TRCVvType[0] == TEMP_CODE) 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 && firstTime) { ipc_send_dcop_prefix(); CKTdump(ckt, 0.0, plot); ipc_send_dcop_suffix(); } /* gtri - end - wbk */ #endif #ifdef WANT_SENSE2 /* if (!ckt->CKTsenInfo) printf("sensitivity structure does not exist\n"); */ if (ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & DCSEN)) { int senmode; #ifdef SENSDEBUG if (job->TRCVvType[0] == vcode) { /* voltage source */ printf("Voltage Source Value : %.5e V\n", ((VSRCinstance*) (job->TRCVvElt[0]))->VSRCdcValue); } if (job->TRCVvType[0] == icode) { /* current source */ printf("Current Source Value : %.5e A\n", ((ISRCinstance*)(job->TRCVvElt[0]))->ISRCdcValue); } if (job->TRCVvType[0] == rcode) { /* resistance */ printf("Current Resistance Value : %.5e Ohm\n", ((RESinstance*)(job->TRCVvElt[0]->GENmodPtr))->RESresist); } if (job->TRCVvType[0] == TEMP_CODE) { /* Temperature */ printf("Current Circuit Temperature : %.5e C\n", ckt->CKTtemp - CONSTCtoK); } #endif senmode = ckt->CKTsenInfo->SENmode; save = ckt->CKTmode; ckt->CKTsenInfo->SENmode = DCSEN; error = CKTsenDCtran(ckt); if (error) return(error); ckt->CKTmode = save; ckt->CKTsenInfo->SENmode = senmode; } #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; memcpy(ckt->CKTstate1, ckt->CKTstate0, (size_t) ckt->CKTnumStates * sizeof(double)); } i = 0; nextstep:; if (job->TRCVvType[i] == vcode) { /* voltage source */ ((VSRCinstance*)(job->TRCVvElt[i]))->VSRCdcValue += job->TRCVvStep[i]; } else if (job->TRCVvType[i] == icode) { /* current source */ ((ISRCinstance*)(job->TRCVvElt[i]))->ISRCdcValue += job->TRCVvStep[i]; } else if (job->TRCVvType[i] == rcode) { /* resistance */ ((RESinstance*)(job->TRCVvElt[i]))->RESresist += job->TRCVvStep[i]; /* RESload() needs conductance as well */ ((RESinstance*)(job->TRCVvElt[i]))->RESconduct = 1 / (((RESinstance*)(job->TRCVvElt[i]))->RESresist); DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt); } else if (job->TRCVvType[i] == TEMP_CODE) { /* temperature */ ckt->CKTtemp += job->TRCVvStep[i]; if (expr_w_temper) inp_evaluate_temper(); CKTtemp(ckt); } if (SPfrontEnd->IFpauseTest()) { /* user asked us to pause, so save state */ job->TRCVnestState = i; return(E_PAUSE); } #ifdef HAS_PROGREP if (i == job->TRCVnestLevel) { actval += job->TRCVvStep[job->TRCVnestLevel]; SetAnalyse("dc", abs((int)(actval * 1000. / actdiff))); } #endif } /* all done, lets put everything back */ for (i = 0; i <= job->TRCVnestLevel; i++) if (job->TRCVvType[i] == vcode) { /* voltage source */ ((VSRCinstance*)(job->TRCVvElt[i]))->VSRCdcValue = job->TRCVvSave[i]; ((VSRCinstance*)(job->TRCVvElt[i]))->VSRCdcGiven = (job->TRCVgSave[i] != 0); } else if (job->TRCVvType[i] == icode) { /*current source */ ((ISRCinstance*)(job->TRCVvElt[i]))->ISRCdcValue = job->TRCVvSave[i]; ((ISRCinstance*)(job->TRCVvElt[i]))->ISRCdcGiven = (job->TRCVgSave[i] != 0); } else if (job->TRCVvType[i] == rcode) { /* Resistance */ ((RESinstance*)(job->TRCVvElt[i]))->RESresist = job->TRCVvSave[i]; /* RESload() needs conductance as well */ ((RESinstance*)(job->TRCVvElt[i]))->RESconduct = 1 / (((RESinstance*)(job->TRCVvElt[i]))->RESresist); ((RESinstance*)(job->TRCVvElt[i]))->RESresGiven = (job->TRCVgSave[i] != 0); DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt); } else if (job->TRCVvType[i] == TEMP_CODE) { ckt->CKTtemp = job->TRCVvSave[i]; if (expr_w_temper) inp_evaluate_temper(); CKTtemp(ckt); } SPfrontEnd->OUTendPlot (plot); return(OK); }
/* ARGSUSED */ int TFanal(CKTcircuit *ckt, int restart) /* forced restart flag */ { int size; int insrc = 0, outsrc = 0; double outputs[3]; IFvalue outdata; /* structure for output data vector, will point to * outputs vector above */ IFvalue refval; /* structure for 'reference' value (not used here) */ int error; int converged; int i; void *plotptr = NULL; /* pointer to out plot */ GENinstance *ptr = NULL; IFuid uids[3]; int Itype; int Vtype; char *name; #define tfuid (uids[0]) /* unique id for the transfer function output */ #define inuid (uids[1]) /* unique id for the transfer function input imp. */ #define outuid (uids[2]) /* unique id for the transfer function out. imp. */ /* first, find the operating point */ converged = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter); Itype = CKTtypelook("Isource"); Vtype = CKTtypelook("Vsource"); if(Itype != -1) { error = CKTfndDev(ckt,&Itype,&ptr, ((TFan*)ckt->CKTcurJob)->TFinSrc, (GENmodel *)NULL, (IFuid)NULL); if(error ==0) { ((TFan*)ckt->CKTcurJob)->TFinIsI = 1; ((TFan*)ckt->CKTcurJob)->TFinIsV = 0; } else { ptr = NULL; } } if( (Vtype != -1) && (ptr==NULL) ) { error = CKTfndDev(ckt,&Vtype,&ptr, ((TFan*)ckt->CKTcurJob)->TFinSrc, (GENmodel *)NULL, (IFuid)NULL); ((TFan*)ckt->CKTcurJob)->TFinIsV = 1; ((TFan*)ckt->CKTcurJob)->TFinIsI = 0; if(error !=0) { (*(SPfrontEnd->IFerror))(ERR_WARNING, "Transfer function source %s not in circuit", &(((TFan*)ckt->CKTcurJob)->TFinSrc)); ((TFan*)ckt->CKTcurJob)->TFinIsV = 0; return(E_NOTFOUND); } } size = SMPmatSize(ckt->CKTmatrix); for(i=0;i<=size;i++) { ckt->CKTrhs[i] = 0; } if(((TFan*)ckt->CKTcurJob)->TFinIsI) { ckt->CKTrhs[ptr->GENnode1] -= 1; ckt->CKTrhs[ptr->GENnode2] += 1; } else { insrc = CKTfndBranch(ckt,((TFan*)ckt->CKTcurJob)->TFinSrc); ckt->CKTrhs[insrc] += 1; } SMPsolve(ckt->CKTmatrix,ckt->CKTrhs,ckt->CKTrhsSpare); ckt->CKTrhs[0]=0; /* make a UID for the transfer function output */ (*(SPfrontEnd->IFnewUid))(ckt,&tfuid,(IFuid)NULL,"Transfer_function", UID_OTHER, NULL); /* make a UID for the input impedance */ (*(SPfrontEnd->IFnewUid))(ckt,&inuid,((TFan*)ckt->CKTcurJob)->TFinSrc, "Input_impedance", UID_OTHER, NULL); /* make a UID for the output impedance */ if(((TFan*)ckt->CKTcurJob)->TFoutIsI) { (*(SPfrontEnd->IFnewUid))(ckt,&outuid,((TFan*)ckt->CKTcurJob)->TFoutSrc ,"Output_impedance", UID_OTHER, NULL); } else { name = (char *) MALLOC(sizeof(char)*(strlen(((TFan*)ckt->CKTcurJob)->TFoutName)+22)); (void)sprintf(name,"output_impedance_at_%s", ((TFan*)ckt->CKTcurJob)->TFoutName); (*(SPfrontEnd->IFnewUid))(ckt,&outuid,(IFuid)NULL, name, UID_OTHER, NULL); } error = (*(SPfrontEnd->OUTpBeginPlot))(ckt,(void *)(ckt->CKTcurJob), ((TFan*)(ckt->CKTcurJob))->JOBname,(IFuid)NULL,(int)0,3, uids,IF_REAL,&plotptr); if(error) return(error); /*find transfer function */ if(((TFan*)ckt->CKTcurJob)->TFoutIsV) { outputs[0] = ckt->CKTrhs[((TFan*)ckt->CKTcurJob)->TFoutPos->number] - ckt->CKTrhs[((TFan*)ckt->CKTcurJob)->TFoutNeg->number] ; } else { outsrc = CKTfndBranch(ckt,((TFan*)ckt->CKTcurJob)->TFoutSrc); outputs[0] = ckt->CKTrhs[outsrc]; } /* now for input resistance */ if(((TFan*)ckt->CKTcurJob)->TFinIsI) { outputs[1] = ckt->CKTrhs[ptr->GENnode2] - ckt->CKTrhs[ptr->GENnode1]; } else { if(fabs(ckt->CKTrhs[insrc])<1e-20) { outputs[1]=1e20; } else { outputs[1] = -1/ckt->CKTrhs[insrc]; } } if(((TFan*)ckt->CKTcurJob)->TFoutIsI && (((TFan*)ckt->CKTcurJob)->TFoutSrc == ((TFan*)ckt->CKTcurJob)->TFinSrc)) { outputs[2]=outputs[1]; goto done; /* no need to compute output resistance when it is the same as the input */ } /* now for output resistance */ for(i=0;i<=size;i++) { ckt->CKTrhs[i] = 0; } if(((TFan*)ckt->CKTcurJob)->TFoutIsV) { ckt->CKTrhs[((TFan*)ckt->CKTcurJob)->TFoutPos->number] -= 1; ckt->CKTrhs[((TFan*)ckt->CKTcurJob)->TFoutNeg->number] += 1; } else { ckt->CKTrhs[outsrc] += 1; } SMPsolve(ckt->CKTmatrix,ckt->CKTrhs,ckt->CKTrhsSpare); ckt->CKTrhs[0]=0; if(((TFan*)ckt->CKTcurJob)->TFoutIsV) { outputs[2]= ckt->CKTrhs[((TFan*)ckt->CKTcurJob)->TFoutNeg->number] - ckt->CKTrhs[((TFan*)ckt->CKTcurJob)->TFoutPos->number]; } else { outputs[2] = 1/MAX(1e-20,ckt->CKTrhs[outsrc]); } done: outdata.v.numValue=3; outdata.v.vec.rVec=outputs; refval.rValue = 0; (*(SPfrontEnd->OUTpData))(plotptr,&refval,&outdata); (*(SPfrontEnd->OUTendPlot))(plotptr); return(OK); }
int sens_sens(CKTcircuit *ckt, int restart) { SENS_AN *sen_info = ((SENS_AN *) ckt->CKTcurJob); static int size; static double *delta_I, *delta_iI, *delta_I_delta_Y, *delta_iI_delta_Y; sgen *sg; static double freq; static int nfreqs; static int i; static SMPmatrix *delta_Y = NULL, *Y; static double step_size; double *E, *iE; IFvalue value, nvalue; double *output_values; IFcomplex *output_cvalues; double delta_var; int (*fn)( ); static int is_dc; int k, j, n; int num_vars, branch_eq; char *sen_data; char namebuf[513]; IFuid *output_names, freq_name; int bypass; int type; #ifndef notdef double *save_states[8]; #ifdef notdef for (sg = sgen_init(ckt, 0); sg; sgen_next(&sg)) { if (sg->is_instparam) printf("%s:%s:%s -> param %s\n", DEVices[sg->dev]->DEVpublic.name, sg->model->GENmodName, sg->instance->GENname, sg->ptable[sg->param].keyword); else printf("%s:%s:%s -> mparam %s\n", DEVices[sg->dev]->DEVpublic.name, sg->model->GENmodName, sg->instance->GENname, sg->ptable[sg->param].keyword); } #endif #ifdef ASDEBUG DEBUG(1) printf(">>> restart : %d\n", restart); #endif /* get to work */ restart = 1; if (restart) { freq = 0.0; is_dc = (sen_info->step_type == SENS_DC); nfreqs = count_steps(sen_info->step_type, sen_info->start_freq, sen_info->stop_freq, sen_info->n_freq_steps, &step_size); if (!is_dc) freq = sen_info->start_freq; error = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter); #ifdef notdef ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; #endif if (error) return error; size = spGetSize(ckt->CKTmatrix, 1); /* Create the perturbation matrix */ /* XXX check error return, '1' is complex -- necessary? * only in ac */ delta_Y = spCreate(size, !is_dc, &error); size += 1; /* Create an extra rhs */ delta_I = NEWN(double, size); delta_iI = NEWN(double, size); delta_I_delta_Y = NEWN(double, size); delta_iI_delta_Y = NEWN(double, size); num_vars = 0; for (sg = sgen_init(ckt, is_dc); sg; sgen_next(&sg)) { num_vars += 1; } if (!num_vars) return OK; /* XXXX Should be E_ something */ k = 0; output_names = NEWN(IFuid, num_vars); for (sg = sgen_init(ckt, is_dc); sg; sgen_next(&sg)) { if (!sg->is_instparam) { sprintf(namebuf, "%s:%s", sg->instance->GENname, sg->ptable[sg->param].keyword); } else if ((sg->ptable[sg->param].dataType & IF_PRINCIPAL) && sg->is_principle == 1) { sprintf(namebuf, "%s", sg->instance->GENname); } else { sprintf(namebuf, "%s_%s", sg->instance->GENname, sg->ptable[sg->param].keyword); } (*SPfrontEnd->IFnewUid)((GENERIC *) ckt, output_names + k, NULL, namebuf, UID_OTHER, NULL); k += 1; } if (is_dc) { type = IF_REAL; freq_name = NULL; } else { type = IF_COMPLEX; (*SPfrontEnd->IFnewUid)((GENERIC *) ckt, &freq_name, NULL, "frequency", UID_OTHER, NULL); } error = (*SPfrontEnd->OUTpBeginPlot)((GENERIC *) ckt, (GENERIC *) ckt->CKTcurJob, ckt->CKTcurJob->JOBname, freq_name, IF_REAL, num_vars, output_names, type, (GENERIC **) &sen_data); if (error) return error; FREE(output_names); if (is_dc) { output_values = NEWN(double, num_vars); output_cvalues = NULL; } else { output_values = NULL; output_cvalues = NEWN(IFcomplex, num_vars); if (sen_info->step_type != SENS_LINEAR) (*(SPfrontEnd->OUTattributes))((GENERIC *)sen_data, NULL, OUT_SCALE_LOG, NULL); } } else {
int ACan(CKTcircuit *ckt, int restart) { double freq; double freqTol; /* tolerence parameter for finding final frequency */ double startdTime; double startsTime; double startlTime; double startcTime; double startkTime; double startTime; int error; int numNames; IFuid *nameList; /* va: tmalloc'ed list of names */ IFuid freqUid; static void *acPlot = NULL; void *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_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 */ if(((ACAN*)ckt->CKTcurJob)->ACsaveFreq == 0 || restart) { if (((ACAN*)ckt->CKTcurJob)->ACnumberSteps < 1) ((ACAN*)ckt->CKTcurJob)->ACnumberSteps = 1; switch(((ACAN*)ckt->CKTcurJob)->ACstepType) { case DECADE: ((ACAN*)ckt->CKTcurJob)->ACfreqDelta = exp(log(10.0)/((ACAN*)ckt->CKTcurJob)->ACnumberSteps); break; case OCTAVE: ((ACAN*)ckt->CKTcurJob)->ACfreqDelta = exp(log(2.0)/((ACAN*)ckt->CKTcurJob)->ACnumberSteps); break; case LINEAR: if (((ACAN*)ckt->CKTcurJob)->ACnumberSteps-1 > 1) ((ACAN*)ckt->CKTcurJob)->ACfreqDelta = (((ACAN*)ckt->CKTcurJob)->ACstopFreq - ((ACAN*)ckt->CKTcurJob)->ACstartFreq)/ (((ACAN*)ckt->CKTcurJob)->ACnumberSteps-1); else /* Patch from: Richard McRoberts * This patch is for a rather pathological case: * a linear step with only one point */ ((ACAN*)ckt->CKTcurJob)->ACfreqDelta = 0; break; default: return(E_BADPARM); } #ifdef XSPICE /* gtri - begin - wbk - Call EVTop if event-driven instances exist */ if(ckt->evt->counts.num_insts != 0) { error = EVTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter, MIF_TRUE); EVTdump(ckt, IPC_ANAL_DCOP, 0.0); EVTop_save(ckt, MIF_TRUE, 0.0); } else #endif /* If no event-driven instances, do what SPICE normally does */ error = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter); if(error){ fprintf(stdout,"\nAC operating point failed -\n"); CKTncDump(ckt); return(error); } #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,(void*)ckt->CKTcurJob, ckt->CKTcurJob->JOBname,(IFuid)NULL,IF_REAL,numNames,nameList, IF_REAL,&acPlot); tfree(nameList); ipc_send_dcop_prefix(); CKTdump(ckt,(double)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); error = CKTnames(ckt,&numNames,&nameList); if(error) return(error); if (ckt->CKTkeepOpInfo) { /* Dump operating point. */ error = (*(SPfrontEnd->OUTpBeginPlot))(ckt, (void*)ckt->CKTcurJob, "AC Operating Point", (IFuid)NULL,IF_REAL,numNames,nameList, IF_REAL,&plot); if(error) return(error); CKTdump(ckt,(double)0,plot); (*(SPfrontEnd->OUTendPlot))(plot); plot = NULL; } (*(SPfrontEnd->IFnewUid))(ckt,&freqUid,(IFuid)NULL, "frequency", UID_OTHER, NULL); error = (*(SPfrontEnd->OUTpBeginPlot))(ckt, (void*)ckt->CKTcurJob, ckt->CKTcurJob->JOBname,freqUid,IF_REAL,numNames,nameList, IF_COMPLEX,&acPlot); tfree(nameList); if(error) return(error); if (((ACAN*)ckt->CKTcurJob)->ACstepType != LINEAR) { (*(SPfrontEnd->OUTattributes))((void *)acPlot,NULL, OUT_SCALE_LOG, NULL); } freq = ((ACAN*)ckt->CKTcurJob)->ACstartFreq; } else { /* continue previous analysis */ freq = ((ACAN*)ckt->CKTcurJob)->ACsaveFreq; ((ACAN*)ckt->CKTcurJob)->ACsaveFreq = 0; /* clear the 'old' frequency */ /* fix resume? saj*/ error = (*(SPfrontEnd->OUTpBeginPlot))(ckt, (void*)ckt->CKTcurJob, ckt->CKTcurJob->JOBname,freqUid,IF_REAL,numNames,nameList, IF_COMPLEX,&acPlot); /* saj*/ } switch(((ACAN*)ckt->CKTcurJob)->ACstepType) { case DECADE: case OCTAVE: freqTol = ((ACAN*)ckt->CKTcurJob)->ACfreqDelta * ((ACAN*)ckt->CKTcurJob)->ACstopFreq * ckt->CKTreltol; break; case LINEAR: freqTol = ((ACAN*)ckt->CKTcurJob)->ACfreqDelta * ckt->CKTreltol; break; default: return(E_BADPARM); } #ifdef XSPICE /* 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_AC; /* gtri - end - wbk */ #endif startTime = SPfrontEnd->IFseconds(); startdTime = ckt->CKTstat->STATdecompTime; startsTime = ckt->CKTstat->STATsolveTime; startlTime = ckt->CKTstat->STATloadTime; startcTime = ckt->CKTstat->STATcombineTime; startkTime = ckt->CKTstat->STATsyncTime; /* main loop through all scheduled frequencies */ while(freq <= ((ACAN*)ckt->CKTcurJob)->ACstopFreq+freqTol) { if( (*(SPfrontEnd->IFpauseTest))() ) { /* user asked us to pause via an interrupt */ ((ACAN*)ckt->CKTcurJob)->ACsaveFreq = freq; return(E_PAUSE); } ckt->CKTomega = 2.0 * M_PI *freq; /* Update opertating point, if variable 'hertz' is given */ if (ckt->CKTvarHertz) { #ifdef XSPICE /* Call EVTop if event-driven instances exist */ if(ckt->evt->counts.num_insts != 0) { error = EVTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter, MIF_TRUE); EVTdump(ckt, IPC_ANAL_DCOP, 0.0); EVTop_save(ckt, MIF_TRUE, 0.0); } else #endif // If no event-driven instances, do what SPICE normally does error = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter); if(error){ fprintf(stdout,"\nAC operating point failed -\n"); CKTncDump(ckt); return(error); } ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; error = CKTload(ckt); if(error) return(error); } ckt->CKTmode = (ckt->CKTmode&MODEUIC) | MODEAC; error = NIacIter(ckt); if (error) { ckt->CKTcurrentAnalysis = DOING_AC; ckt->CKTstat->STATacTime += SPfrontEnd->IFseconds() - startTime; ckt->CKTstat->STATacDecompTime += ckt->CKTstat->STATdecompTime - startdTime; ckt->CKTstat->STATacSolveTime += ckt->CKTstat->STATsolveTime - startsTime; ckt->CKTstat->STATacLoadTime += ckt->CKTstat->STATloadTime - startlTime; ckt->CKTstat->STATacCombTime += ckt->CKTstat->STATcombineTime - startcTime; ckt->CKTstat->STATacSyncTime += ckt->CKTstat->STATsyncTime - startkTime; return(error); } #ifdef WANT_SENSE2 if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode&ACSEN) ){ save = ckt->CKTmode; ckt->CKTmode=(ckt->CKTmode&MODEUIC)|MODEDCOP|MODEINITSMSIG; save1 = ckt->CKTsenInfo->SENmode; ckt->CKTsenInfo->SENmode = ACSEN; if(freq == ((ACAN*)ckt->CKTcurJob)->ACstartFreq){ ckt->CKTsenInfo->SENacpertflag = 1; } else{ ckt->CKTsenInfo->SENacpertflag = 0; } if(error = CKTsenAC(ckt)) return (error); ckt->CKTmode = save; ckt->CKTsenInfo->SENmode = save1; } #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) { ckt->CKTcurrentAnalysis = DOING_AC; ckt->CKTstat->STATacTime += SPfrontEnd->IFseconds() - startTime; ckt->CKTstat->STATacDecompTime += ckt->CKTstat->STATdecompTime - startdTime; ckt->CKTstat->STATacSolveTime += ckt->CKTstat->STATsolveTime - startsTime; ckt->CKTstat->STATacLoadTime += ckt->CKTstat->STATloadTime - startlTime; ckt->CKTstat->STATacCombTime += ckt->CKTstat->STATcombineTime - startcTime; ckt->CKTstat->STATacSyncTime += ckt->CKTstat->STATsyncTime - startkTime; return(error); } /* increment frequency */ switch(((ACAN*)ckt->CKTcurJob)->ACstepType) { case DECADE: case OCTAVE: /* inserted again 14.12.2001 */ #ifdef HAS_WINDOWS { double endfreq = ((ACAN*)ckt->CKTcurJob)->ACstopFreq; double startfreq = ((ACAN*)ckt->CKTcurJob)->ACstartFreq; endfreq = log(endfreq); if (startfreq == 0.0) startfreq = 1e-12; startfreq = log(startfreq); if (freq > 0.0) SetAnalyse( "ac", (log(freq)-startfreq) * 1000.0 / (endfreq-startfreq)); } #endif freq *= ((ACAN*)ckt->CKTcurJob)->ACfreqDelta; if(((ACAN*)ckt->CKTcurJob)->ACfreqDelta==1) goto endsweep; break; case LINEAR: #ifdef HAS_WINDOWS { double endfreq = ((ACAN*)ckt->CKTcurJob)->ACstopFreq; double startfreq = ((ACAN*)ckt->CKTcurJob)->ACstartFreq; SetAnalyse( "ac", (freq - startfreq)* 1000.0 / (endfreq-startfreq)); } #endif freq += ((ACAN*)ckt->CKTcurJob)->ACfreqDelta; if(((ACAN*)ckt->CKTcurJob)->ACfreqDelta==0) goto endsweep; break; default: return(E_INTERN); } } endsweep: (*(SPfrontEnd->OUTendPlot))(acPlot); acPlot = NULL; ckt->CKTcurrentAnalysis = 0; ckt->CKTstat->STATacTime += SPfrontEnd->IFseconds() - startTime; ckt->CKTstat->STATacDecompTime += ckt->CKTstat->STATdecompTime - startdTime; ckt->CKTstat->STATacSolveTime += ckt->CKTstat->STATsolveTime - startsTime; ckt->CKTstat->STATacLoadTime += ckt->CKTstat->STATloadTime - startlTime; ckt->CKTstat->STATacCombTime += ckt->CKTstat->STATcombineTime - startcTime; ckt->CKTstat->STATacSyncTime += ckt->CKTstat->STATsyncTime - startkTime; return(0); }
int NOISEan (CKTcircuit *ckt, int restart) { static Ndata *data; /* va, must be static, for continuation of * interrupted(Ctrl-C), longer lasting noise * analysis */ double realVal; double imagVal; int error; int posOutNode; int negOutNode; int step; IFuid freqUid; double freqTol; /* tolerence parameter for finding final frequency; hack */ int i, src_type; NOISEAN *job = (NOISEAN *) ckt->CKTcurJob; GENinstance *inst = CKTfndDev(ckt, job->input); posOutNode = (job->output) -> number; negOutNode = (job->outputRef) -> number; /* see if the source specified is AC */ { //bool ac_given = FALSE; int ac_given = FALSE; if (!inst || inst->GENmodPtr->GENmodType < 0) { SPfrontEnd->IFerrorf (ERR_WARNING, "Noise input source %s not in circuit", job->input); return E_NOTFOUND; } if (inst->GENmodPtr->GENmodType == CKTtypelook("Vsource")) { ac_given = ((VSRCinstance *)inst) -> VSRCacGiven; src_type = SV_VOLTAGE; } else if(inst->GENmodPtr->GENmodType == CKTtypelook("Isource")) { ac_given = ((ISRCinstance *)inst) -> ISRCacGiven; src_type = SV_CURRENT; } else { SPfrontEnd->IFerrorf (ERR_WARNING, "Noise input source %s is not of proper type", job->input); return E_NOTFOUND; } if (!ac_given) { SPfrontEnd->IFerrorf (ERR_WARNING, "Noise input source %s has no AC value", job->input); return E_NOACINPUT; } } if ( (job->NsavFstp == 0.0) || restart) { /* va, NsavFstp is double */ switch (job->NstpType) { case DECADE: job->NfreqDelta = exp(log(10.0)/ job->NnumSteps); break; case OCTAVE: job->NfreqDelta = exp(log(2.0)/ job->NnumSteps); break; case LINEAR: job->NfreqDelta = (job->NstopFreq - job->NstartFreq)/ (job->NnumSteps - 1); break; default: return(E_BADPARM); } /* error = DCop(ckt); */ error = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT, ckt->CKTdcMaxIter); if (error) return(error); /* Patch to noisean.c by Richard D. McRoberts. */ ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG; error = CKTload(ckt); if(error) return(error); data = TMALLOC(Ndata, 1); step = 0; data->freq = job->NstartFreq; data->outNoiz = 0.0; data->inNoise = 0.0; data->squared = cp_getvar("sqrnoise", CP_BOOL, NULL) ? 1 : 0; /* the current front-end needs the namelist to be fully declared before an OUTpBeginplot */ SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL); data->numPlots = 0; /* we don't have any plots yet */ error = CKTnoise(ckt,N_DENS,N_OPEN,data); if (error) return(error); /* * all names in the namelist have been declared. now start the * plot */ if (src_type == SV_VOLTAGE) fixme_inoise_type = data->squared ? SV_SQR_VOLTAGE_DENSITY : SV_VOLTAGE_DENSITY; else fixme_inoise_type = data->squared ? SV_SQR_CURRENT_DENSITY : SV_CURRENT_DENSITY; fixme_onoise_type = data->squared ? SV_SQR_VOLTAGE_DENSITY : SV_VOLTAGE_DENSITY; if (!data->squared) for (i = 0; i < data->numPlots; i++) data->squared_value[i] = ciprefix("inoise", data->namelist[i]) || ciprefix("onoise", data->namelist[i]); error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, data->squared ? "Noise Spectral Density Curves - (V^2 or A^2)/Hz" : "Noise Spectral Density Curves", freqUid, IF_REAL, data->numPlots, data->namelist, IF_REAL, &(data->NplotPtr)); if (error) return(error); if (job->NstpType != LINEAR) { SPfrontEnd->OUTattributes (data->NplotPtr, NULL, OUT_SCALE_LOG, NULL); } } else { /* we must have paused before. pick up where we left off */ step = (int)(job->NsavFstp); switch (job->NstpType) { case DECADE: case OCTAVE: data->freq = job->NstartFreq * exp (step * log (job->NfreqDelta)); break; case LINEAR: data->freq = job->NstartFreq + step * job->NfreqDelta; break; default: return(E_BADPARM); } job->NsavFstp = 0; data->outNoiz = job->NsavOnoise; data->inNoise = job->NsavInoise; /* saj resume rawfile fix*/ error = SPfrontEnd->OUTpBeginPlot (NULL, NULL, NULL, NULL, 0, 666, NULL, 666, &(data->NplotPtr)); /*saj*/ } switch (job->NstpType) { case DECADE: case OCTAVE: freqTol = job->NfreqDelta * job->NstopFreq * ckt->CKTreltol; break; case LINEAR: freqTol = job->NfreqDelta * ckt->CKTreltol; break; default: return(E_BADPARM); } data->lstFreq = data->freq; /* do the noise analysis over all frequencies */ while (data->freq <= job->NstopFreq + freqTol) { if(SPfrontEnd->IFpauseTest()) { job->NsavFstp = step; /* save our results */ job->NsavOnoise = data->outNoiz; /* up until now */ job->NsavInoise = data->inNoise; return (E_PAUSE); } ckt->CKTomega = 2.0 * M_PI * data->freq; ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEAC | MODEACNOISE; ckt->noise_input = inst; /* * solve the original AC system to get the transfer * function between the input and output */ NIacIter(ckt); realVal = ckt->CKTrhsOld [posOutNode] - ckt->CKTrhsOld [negOutNode]; imagVal = ckt->CKTirhsOld [posOutNode] - ckt->CKTirhsOld [negOutNode]; data->GainSqInv = 1.0 / MAX(((realVal*realVal) + (imagVal*imagVal)),N_MINGAIN); data->lnGainInv = log(data->GainSqInv); /* set up a block of "common" data so we don't have to * recalculate it for every device */ data->delFreq = data->freq - data->lstFreq; data->lnFreq = log(MAX(data->freq,N_MINLOG)); data->lnLastFreq = log(MAX(data->lstFreq,N_MINLOG)); data->delLnFreq = data->lnFreq - data->lnLastFreq; if ((job->NStpsSm != 0) && ((step % (job->NStpsSm)) == 0)) { data->prtSummary = TRUE; } else { data->prtSummary = FALSE; } /* data->outNumber = 1; */ data->outNumber = 0; /* the frequency will NOT be stored in array[0] as before; instead, * it will be given in refVal.rValue (see later) */ NInzIter(ckt,posOutNode,negOutNode); /* solve the adjoint system */ /* now we use the adjoint system to calculate the noise * contributions of each generator in the circuit */ error = CKTnoise(ckt,N_DENS,N_CALC,data); if (error) return(error); data->lstFreq = data->freq; /* update the frequency */ switch (job->NstpType) { case DECADE: case OCTAVE: data->freq *= job->NfreqDelta; break; case LINEAR: data->freq += job->NfreqDelta; break; default: return(E_INTERN); } step++; } error = CKTnoise(ckt,N_DENS,N_CLOSE,data); if (error) return(error); data->numPlots = 0; data->outNumber = 0; if (job->NstartFreq != job->NstopFreq) { error = CKTnoise(ckt,INT_NOIZ,N_OPEN,data); if (error) return(error); if (src_type == SV_VOLTAGE) fixme_inoise_type = data->squared ? SV_SQR_VOLTAGE : SV_VOLTAGE; else fixme_inoise_type = data->squared ? SV_SQR_CURRENT : SV_CURRENT; fixme_onoise_type = data->squared ? SV_SQR_VOLTAGE : SV_VOLTAGE; if (!data->squared) for (i = 0; i < data->numPlots; i++) data->squared_value[i] = ciprefix("inoise", data->namelist[i]) || ciprefix("onoise", data->namelist[i]); SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob, data->squared ? "Integrated Noise - V^2 or A^2" : "Integrated Noise", NULL, 0, data->numPlots, data->namelist, IF_REAL, &(data->NplotPtr)); error = CKTnoise(ckt,INT_NOIZ,N_CALC,data); if (error) return(error); error = CKTnoise(ckt,INT_NOIZ,N_CLOSE,data); if (error) return(error); } FREE(data); return(OK); }