Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
//bool
//do_measure(
//    char *what,   /*in: analysis type*/
//    bool chk_only /*in: TRUE if checking for "autostop", FALSE otherwise*/
//)
int
do_measure(
           char *what,   /*in: analysis type*/
           int chk_only /*in: TRUE if checking for "autostop", FALSE otherwise*/
)
{
    struct line *meas_card, *meas_results = NULL, *end = NULL, *newcard;
    char        *line, *an_name, *an_type, *resname, *meastype, *str_ptr, out_line[1000];
    int         ok = 0;
    int         fail;
    int         num_failed = 0;
    double      result = 0;
//    bool        first_time = TRUE;
//    bool        measures_passed;
    int        first_time = TRUE;
    int        measures_passed;
    wordlist    *measure_word_list;
    int         precision = measure_get_precision();

#ifdef HAS_PROGREP
    if (!chk_only)
        SetAnalyse("meas", 0);
#endif

    an_name = strdup(what); /* analysis type, e.g. "tran" */
    strtolower(an_name);
    measure_word_list = NULL;
    measures_passed = TRUE;

    /* don't allow .meas if batchmode is set by -b and -r rawfile given */
    if (ft_batchmode && rflag) {
        fprintf(cp_err, "\nNo .measure possible in batch mode (-b) with -r rawfile set!\n");
        fprintf(cp_err, "Remove rawfile and use .print or .plot or\n");
        fprintf(cp_err, "select interactive mode (optionally with .control section) instead.\n\n");
        return (measures_passed);
    }

    /* don't allow autostop if no .meas commands are given in the input file */
    if ((cp_getvar("autostop", CP_BOOL, NULL)) && (ft_curckt->ci_meas == NULL)) {
        fprintf(cp_err, "\nWarning: No .meas commands found!\n");
        fprintf(cp_err, "  Option autostop is not available, ignored!\n\n");
        cp_remvar("autostop");
        return (FALSE);
    }

    /* Evaluating the linked list of .meas cards, assembled from the input deck
       by fcn inp_spsource() in inp.c:575.
       A typical .meas card will contain:
       parameter        value
       nameof card      .meas(ure)
       analysis type    tran        only tran available currently
       result name      myout       defined by user
       measurement type trig|delay|param|expr|avg|mean|max|min|rms|integ(ral)|when

       The measurement type determines how to continue the .meas card.
       param|expr are skipped in first pass through .meas cards and are treated in second pass,
       all others are treated in fcn get_measure2() (com_measure2.c).
       */

    /* first pass through .meas cards: evaluate everything except param|expr */
    for (meas_card = ft_curckt->ci_meas; meas_card != NULL; meas_card = meas_card->li_next) {
        line = meas_card->li_line;

        txfree(gettok(&line)); /* discard .meas */

        an_type = gettok(&line);
        resname = gettok(&line);
        meastype = gettok(&line);

        if (chkAnalysisType(an_type) != TRUE) {
            if (!chk_only) {
                fprintf(cp_err, "Error: unrecognized analysis type '%s' for the following .meas statement on line %d:\n", an_type, meas_card->li_linenum);
                fprintf(cp_err, "       %s\n", meas_card->li_line);
            }

            txfree(an_type);
            txfree(resname);
            txfree(meastype);
            continue;
        }
        /* print header before evaluating first .meas line */
        else if (first_time) {
            first_time = FALSE;

            if (!chk_only && strcmp(an_type, "tran") == 0) {
                fprintf(stdout, "\n  Measurements for Transient Analysis\n\n");
            }
        }

        /* skip param|expr measurement types for now -- will be done after other measurements */
        if (strncmp(meastype, "param", 5) == 0 || strncmp(meastype, "expr", 4) == 0)
            continue;

        /* skip .meas line, if analysis type from line and name of analysis performed differ */
        if (strcmp(an_name, an_type) != 0) {
            txfree(an_type);
            txfree(resname);
            txfree(meastype);
            continue;
        }

        /* New way of processing measure statements using common code
           in fcn get_measure2() (com_measure2.c)*/
        out_line[0] = '\0';
        measure_word_list = measure_parse_line(meas_card->li_line);
        if (measure_word_list) {
            fail = get_measure2(measure_word_list, &result, out_line, chk_only);
            if (fail) {
                measures_passed = FALSE;
                if (!chk_only)
                    fprintf(stderr, " %s failed!\n\n", meas_card->li_line);
                num_failed++;
                if (chk_only) {
                    /* added for speed - cleanup last parse and break */
                    txfree(an_type);
                    txfree(resname);
                    txfree(meastype);
                    wl_free(measure_word_list);
                    break;
                }
            } else {
                if (!chk_only)
                    nupa_add_param(resname, result);
            }
            wl_free(measure_word_list);
        } else {
            measures_passed = FALSE;
            num_failed++;
        }

        if (!chk_only) {
            newcard          = alloc(struct line);
            newcard->li_line = strdup(out_line);
            newcard->li_next = NULL;

            if (meas_results == NULL) {
                meas_results = end = newcard;
            } else {
                end->li_next = newcard;
                end          = newcard;
            }
        }

        txfree(an_type);
        txfree(resname);
        txfree(meastype);

    } /* end of for loop (first pass through .meas lines) */
Esempio n. 4
0
int
CKTop (CKTcircuit * ckt, long int firstmode, long int continuemode,
       int iterlim)
{
  int converged;
#ifdef HAS_WINDOWS
        SetAnalyse("op", 0);
#endif
ckt->CKTmode = firstmode;

  if (!ckt->CKTnoOpIter){
#ifdef XSPICE
/* gtri - begin - wbk - add convergence problem reporting flags */
      if ((ckt->CKTnumGminSteps <= 0) && (ckt->CKTnumSrcSteps <= 0))
          ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;
      else
	ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
/* gtri - end - wbk - add convergence problem reporting flags */
#endif
      converged = NIiter (ckt, iterlim);
    } else {
      converged = 1;		/* the 'go directly to gmin stepping' option */
	}


  if (converged != 0)
    {
      /* no convergence on the first try, so we do something else */
      /* first, check if we should try gmin stepping */

      if (ckt->CKTnumGminSteps >= 1){
		if (ckt->CKTnumGminSteps == 1)
			converged = dynamic_gmin(ckt, firstmode, continuemode, iterlim);
		else
			converged = spice3_gmin(ckt, firstmode, continuemode, iterlim);
	}
	if (!converged)		/* If gmin-stepping worked... move out */
		return (0);

	/* ... otherwise try stepping sources ...
	 * now, we'll try source stepping - we scale the sources
	 * to 0, converge, then start stepping them up until they
	 * are at their normal values
	 */

	if (ckt->CKTnumSrcSteps >= 1){
		if (ckt->CKTnumSrcSteps == 1) 
			converged = gillespie_src(ckt, firstmode, continuemode, iterlim);
		else
			converged = spice3_src(ckt, firstmode, continuemode, iterlim);
	}
#ifdef XSPICE
/* gtri - begin - wbk - add convergence problem reporting flags */
	    ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
/* gtri - end - wbk - add convergence problem reporting flags */
#endif

      }
      return (converged);
    
}
Esempio n. 5
0
void INPpas2(CKTcircuit *ckt, card * data, INPtables * tab, TSKtask *task)
{

    card *current;
    char c;
    char *groundname = "0";
    char *gname;
    CKTnode *gnode;
    int error;			/* used by the macros defined above */
#ifdef HAS_PROGREP
    int linecount = 0, actcount = 0;
#endif

#ifdef TRACE
    /* SDB debug statement */
    printf("Entered INPpas2 . . . .\n");
#endif

#ifdef XSPICE
    if (!ckt->CKTadevFlag) ckt->CKTadevFlag = 0;
#endif

    error = INPgetTok(&groundname, &gname, 1);
    if (error)
	data->error =
	    INPerrCat(data->error,
		      INPmkTemp
		      ("can't read internal ground node name!\n"));

    error = INPgndInsert(ckt, &gname, tab, &gnode);
    if (error && error != E_EXISTS)
	data->error =
	    INPerrCat(data->error,
		      INPmkTemp
		      ("can't insert internal ground node in symbol table!\n"));
    
#ifdef TRACE 
    printf("Examining this deck:\n");
    for (current = data; current != NULL; current = current->nextcard) {
      printf("%s\n", current->line);
    }
    printf("\n");
#endif


#ifdef HAS_PROGREP
    for (current = data; current != NULL; current = current->nextcard)
        linecount++;
#endif

    for (current = data; current != NULL; current = current->nextcard) {

#ifdef TRACE
	/* SDB debug statement */
	printf("In INPpas2, examining card %s . . .\n", current->line);
#endif

#ifdef HAS_PROGREP
   if (linecount > 0) {     
        SetAnalyse( "Circuit2", (int) (1000.*actcount/linecount));
        actcount++;
   }
#endif

	c = *(current->line);
	if(islower(c))
	    c = (char) toupper(c);

	switch (c) {

	case ' ':
	    /* blank line (space leading) */
	case '\t':
	    /* blank line (tab leading) */
	    break;

#ifdef XSPICE
	    /* gtri - add - wbk - 10/23/90 - add case for 'A' devices */

	case 'A':   /* Aname <cm connections> <mname> */
	    MIF_INP2A(ckt, tab, current);
	    ckt->CKTadevFlag = 1; /* an 'A' device is requested */
	    break;

	  /* gtri - end - wbk - 10/23/90 */
#endif

	case 'R':
	    /* Rname <node> <node> [<val>][<mname>][w=<val>][l=<val>] */
	    INP2R(ckt, tab, current);
	    break;

	case 'C':
	    /* Cname <node> <node> <val> [IC=<val>] */
	    INP2C(ckt, tab, current);
	    break;

	case 'L':
	    /* Lname <node> <node> <val> [IC=<val>] */
	    INP2L(ckt, tab, current);
	    break;

	case 'G':
	    /* Gname <node> <node> <node> <node> <val> */
	    INP2G(ckt, tab, current);
	    break;

	case 'E':
	    /* Ename <node> <node> <node> <node> <val> */
	    INP2E(ckt, tab, current);
	    break;

	case 'F':
	    /* Fname <node> <node> <vname> <val> */
	    INP2F(ckt, tab, current);
	    break;

	case 'H':
	    /* Hname <node> <node> <vname> <val> */
	    INP2H(ckt, tab, current);
	    break;

	case 'D':
	    /* Dname <node> <node> <model> [<val>] [OFF] [IC=<val>] */
	    INP2D(ckt, tab, current);
	    break;

	case 'J':
	    /* Jname <node> <node> <node> <model> [<val>] [OFF]
               [IC=<val>,<val>] */
	    INP2J(ckt, tab, current);
	    break;

	case 'Z':
	    /* Zname <node> <node> <node> <model> [<val>] [OFF] 
	       [IC=<val>,<val>] */
	    INP2Z(ckt, tab, current);
	    break;

	case 'M':
	    /* Mname <node> <node> <node> <node> <model> [L=<val>]
	       [W=<val>] [AD=<val>] [AS=<val>] [PD=<val>]
	       [PS=<val>] [NRD=<val>] [NRS=<val>] [OFF] 
	       [IC=<val>,<val>,<val>] */
	    INP2M(ckt, tab, current);
	    break;
#ifdef  NDEV   
	case 'N':
	    /* Nname [<node>...]  [<mname>] */
	    INP2N(ckt, tab, current);
	    break;
#endif
	case 'O':
	    /* Oname <node> <node> <node> <node> <model>
	       [IC=<val>,<val>,<val>,<val>] */
	    INP2O(ckt, tab, current);
	    break;

	case 'V':
	    /* Vname <node> <node> [ [DC] <val>] [AC [<val> [<val> ] ] ]
	       [<tran function>] */
	    INP2V(ckt, tab, current);
	    break;

	case 'I':
	    /* Iname <node> <node> [ [DC] <val>] [AC [<val> [<val> ] ] ]
	       [<tran function>] */
	    INP2I(ckt, tab, current);
	    break;

	case 'Q':
	    /* Qname <node> <node> <node> [<node>] <model> [<val>] [OFF]
	       [IC=<val>,<val>] */
	    INP2Q(ckt, tab, current, gnode);
	    break;

	case 'T':
	    /* Tname <node> <node> <node> <node> [TD=<val>] 
	       [F=<val> [NL=<val>]][IC=<val>,<val>,<val>,<val>] */
	    INP2T(ckt, tab, current);
	    break;

	case 'S':
	    /* Sname <node> <node> <node> <node> [<modname>] [IC] */
	    INP2S(ckt, tab, current);
	    break;

	case 'W':
	    /* Wname <node> <node> <vctrl> [<modname>] [IC] */
	    /* CURRENT CONTROLLED SWITCH */
	    INP2W(ckt, tab, current);
	    break;

	case 'U':
	    /* Uname <node> <node> <model> [l=<val>] [n=<val>] */
	    INP2U(ckt, tab, current);
	    break;

	/* Kspice addition - saj */
	case 'P': 
	    /* Pname <node> <node> ... <gnd> <node> <node> ... <gnd> [<modname>] */
	    /* R=<vector> L=<matrix> G=<vector> C=<matrix> len=<val> */
	    INP2P(ckt, tab, current);
	    break;
	case 'Y':   
	    /* Yname <node> <node> R=<val> L=<val> G=<val> C=<val> len=<val> */
	    INP2Y(ckt, tab, current);
	    break;
	/* end Kspice */

	case 'K':
	    /* Kname Lname Lname <val> */
	    INP2K(ckt, tab, current);
	    break;

	case '*': case '$':
	    /* *<anything> - a comment - ignore */
	    break;

	case 'B':
	    /* Bname <node> <node> [V=expr] [I=expr] */
	    /* Arbitrary source. */
	    INP2B(ckt, tab, current);
	    break;

	case '.':   /* .<something> Many possibilities */
	    if (INP2dot(ckt,tab,current,task,gnode))
	    return;
	    break;

	case '\0':
	    break;

	default:
	    /* the un-implemented device */
	    LITERR(" unknown device type - error \n");
	    break;
	}
  }

    return;
}