diff --git a/examples/loop/vreg.cir b/examples/loop/vreg.cir new file mode 100644 index 000000000..a5a2df99e --- /dev/null +++ b/examples/loop/vreg.cir @@ -0,0 +1,31 @@ +* simple voltage regulator example + +Mout out pgate vdd vdd p1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=100 +R1 out fb 33.3K +R2 fb vss 66.7K + +Mp1 mir mir vdd vdd p1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=2 +Mp2 pgate mir vdd vdd p1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=2 + +M1 pgate set tail vss n1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=10 +M2 mir fbinj tail vss n1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=10 + +Mb1 tail bn vss vss n1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=4 +Mb0 bn bn vss vss n1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p m=4 +Ib vss bn 1u + +Vloop fb fbinj DC 0 + +Vset set vss DC 1.2 AC 1 +Vvdd vdd vss DC 3.3 +Vvss vss 0 DC 0 + +Iload out vss DC 10e-3 PWL 1n 10e-3 2n 9e-3 + +.model n1 nmos level=49 version=3.3.0 tox=3.5n nch=2.4e17 nsub=5e16 vth0=0.6 +.model p1 pmos level=49 version=3.3.0 tox=3.5n nch=2.5e17 nsub=5e16 vth0=-0.7 + + +.loop M2/Gate DEC 10 1 10e9 insrc="Vset" outpos="out" outneg="vss" dir=-1 refnode="set" +.ac dec 10 1 1e9 +.tran 1n 10u diff --git a/src/frontend/commands.c b/src/frontend/commands.c index 1bae97fd2..b780dc1db 100644 --- a/src/frontend/commands.c +++ b/src/frontend/commands.c @@ -300,6 +300,14 @@ struct comm spcp_coms[] = { "[.pss line args] : Do a periodic state analysis." } , /* SP */ #endif +#ifdef WITH_LOOPANA +/* F.B.: Loop stability analysis */ + { "loop", com_loop, TRUE, TRUE, + { 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS, + NULL, + "[.loop line args] : Do a loop stability analysis." } , +#endif + { "ac", com_ac, TRUE, TRUE, { 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS, NULL, @@ -759,6 +767,14 @@ struct comm nutcp_coms[] = { NULL, "[.pss line args] : Do a periodic steady state analysis." } , /* SP */ +#endif +#ifdef WITH_LOOPANA +/* F.B.: Loop stability analysis */ + { "loop", NULL, TRUE, TRUE, + { 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS, + NULL, + "[.loop line args] : Do a loop stability analysis." } , +/* SP */ #endif { "ac", NULL, TRUE, TRUE, { 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS, diff --git a/src/frontend/runcoms.c b/src/frontend/runcoms.c index ecd74c570..968f33aea 100644 --- a/src/frontend/runcoms.c +++ b/src/frontend/runcoms.c @@ -186,6 +186,14 @@ com_pss(wordlist *wl) /* SP */ #endif +#ifdef WITH_LOOPANA +/* F.B. Loop stability analysis */ +void +com_loop(wordlist *wl) +{ + dosim("loop", wl); +} +#endif static int dosim( char *what, /* in: command diff --git a/src/frontend/runcoms.h b/src/frontend/runcoms.h index 714239e50..3bbdf518b 100644 --- a/src/frontend/runcoms.h +++ b/src/frontend/runcoms.h @@ -16,6 +16,9 @@ void com_tran(wordlist *wl); /* SP: Stady State Analysis */ void com_pss(wordlist *wl); /* SP */ +#ifdef WITH_LOOPANA +void com_loop(wordlist *wl); +#endif void com_sens(wordlist *wl); void com_disto(wordlist *wl); void com_noise(wordlist *wl); diff --git a/src/spicelib/analysis/loopan.c b/src/spicelib/analysis/loopan.c index 2555cabb5..ce8ecdae8 100644 --- a/src/spicelib/analysis/loopan.c +++ b/src/spicelib/analysis/loopan.c @@ -151,13 +151,25 @@ LOOPpreset(CKTcircuit *ckt, JOB *anal) return E_NOTFOUND; } /* now break the loop at terminal termidx */ + { + char probename[32]; + sprintf(probename, "probe_%d", termidx); + error = SPfrontEnd->IFnewUid (ckt, &eltUid, inst->GENname, + probename, UID_INSTANCE, NULL); + } + if(error) return(error); + probesrc = CKTfndDev(ckt, eltUid); + if (probesrc && probesrc->GENmodPtr->GENmodType >= 0) + { + /* probe already inserted, nothing to do except to free eltUid ? */ + printf("Loop analysis: The probe was already in place\n"); + } + else + { printf("Loop analysis: Break the loop at device '%s' terminal '%s'\n", inst->GENname, dev->termNames[termidx]); node = CKTnum2nod(ckt, GENnode(inst)[termidx]); error = CKTmkVolt(ckt, &nodeinj, inst->GENname, "loopinj"); if(error) return(error); - error = SPfrontEnd->IFnewUid (ckt, &eltUid, inst->GENname, - "probe", UID_INSTANCE, NULL); - if(error) return(error); error = SPfrontEnd->IFnewUid (ckt, &modUid, inst->GENname, "probemod", UID_MODEL, NULL); if(error) return(error); @@ -176,7 +188,8 @@ LOOPpreset(CKTcircuit *ckt, JOB *anal) error = CKTbindNode(ckt,probesrc,job->LOOPdirection==2 ? 2 : 2 ,node); if(error) return(error); error = CKTbindNode(ckt,inst,termidx+1,nodeinj); /* bindNode counts from 1 ! */ - ptemp.rValue = 0; + if(error) return(error); + } job->LOOPprobeSrc = probesrc->GENname; job->LOOPportnameGiven = 0; /* don't mess if LOOPpreset is called a second time */ job->LOOPportnumGiven = 0; /* idem */