diff --git a/examples/p-to-n-examples/switch-invs.lib b/examples/p-to-n-examples/switch-invs.lib index 1cc598b3f..4a1eaaf26 100644 --- a/examples/p-to-n-examples/switch-invs.lib +++ b/examples/p-to-n-examples/switch-invs.lib @@ -19,7 +19,7 @@ C2 out vdd 0.1p * sw like a CMOS inverter .subckt inverter In Out VDD DGND sp out vdd vdd in swswitch -*Rl out 0 10k +Rin in 0 1e9 Cl out dgnd 0.1p C2 out vdd 0.1p sn out dgnd in dgnd swswitch @@ -31,7 +31,7 @@ sn out dgnd in dgnd swswitch * sw like a CMOS inverter with PSPICE VSWITCH .subckt invertervs In Out VDD DGND sp out vdd vdd in swn -*Rl out 0 10k +Rin in 0 1e9 Cl out dgnd 0.1p C2 out vdd 0.1p sn out dgnd in dgnd swn @@ -43,12 +43,30 @@ sn out dgnd in dgnd swn * sw like a CMOS inverter with PSPICE VSWITCH .subckt invertervs2 In Out VDD DGND sp out vdd vdd in swn -*Rl out 0 10k +Rin in 0 1e9 Cl out dgnd 0.1p C2 out vdd 0.1p sn out dgnd in dgnd swn .MODEL SWN VSWITCH ( VON = 1.1 VOFF = 0.9 RON=1k ROFF=1e12 ) .ends invertervs2 +* sw like a CMOS inverter with PSPICE VSWITCH +.subckt invertervs3 In Out VDD DGND +sp out vdd vdd in swn2 +Rin in 0 1e9 +Cl out dgnd 0.1p +C2 out vdd 0.1p +sn out dgnd in dgnd swn2 +.ends invertervs3 +.MODEL SWN2 VSWITCH ( VON = 1.1 VOFF = 0.9 RON=1k ROFF=1e12 ) +* sw like a CMOS inverter with PSPICE VSWITCH +.subckt invertervs4 In Out VDD DGND +sp out vdd vdd in swn +Rin in 0 1e9 +Cl out dgnd 0.1p +C2 out vdd 0.1p +sn out dgnd in dgnd swn +.MODEL SWN VSWITCH ( VON = 1.1 VOFF = 0.9 RON=2k ROFF=1e12 ) +.ends invertervs4 diff --git a/examples/p-to-n-examples/switch-oscillators_inc.cir b/examples/p-to-n-examples/switch-oscillators_inc.cir index 49ebbc78d..f8f867b57 100644 --- a/examples/p-to-n-examples/switch-oscillators_inc.cir +++ b/examples/p-to-n-examples/switch-oscillators_inc.cir @@ -8,34 +8,35 @@ plot V(Osc_out) rusage .endc -.ic v(osc_out)=0.25 -.tran 10n 80n 50p ; -*.tran 100p 80n 50p uic ;for BSIM4 -.option method=gear maxord=3 +.ic v(N017)=0.25 +.tran 50p 40n 50p uic +*.option method=gear maxord=3 VDD VDD2 0 DC 3 VMEASURE VDD2 VDD dc 0 cvdd vdd 0 1e-18 -XX18 Osc_out N001 VDD 0 inverter +XX1 N017 N001 VDD 0 invertervs XX2 N001 N002 VDD 0 inverter -XX3 N002 N003 VDD 0 inverter -XX4 N003 N004 VDD 0 inverter -XX5 N004 N005 VDD 0 inverter -XX6 N005 N006 VDD 0 inverter -XX7 N006 N007 VDD 0 invertervs2 -XX8 N007 N008 VDD 0 inverter -XX9 N008 N009 VDD 0 inverter -XX10 N009 N010 VDD 0 inverter -XX11 N010 N011 VDD 0 invertervs +XX3 N002 N003 VDD 0 invertervs +XX4 N003 N004 VDD 0 invertervs2 +XX5 N004 N005 VDD 0 invertervs3 +XX6 N005 N006 VDD 0 invertervs4 +XX7 N006 N007 VDD 0 inverter +XX8 N007 N008 VDD 0 invertervs +XX9 N008 N009 VDD 0 invertervs2 +XX10 N009 N010 VDD 0 invertervs3 +XX11 N010 N011 VDD 0 invertervs4 XX12 N011 N012 VDD 0 inverter -XX13 N012 N013 VDD 0 inverter -XX14 N013 N014 VDD 0 inverter -XX15 N014 N015 VDD 0 inverter -XX16 N015 N016 VDD 0 inverter -XX17 N016 Osc_out VDD 0 inverter - +XX13 N012 N013 VDD 0 invertervs +XX14 N013 N014 VDD 0 invertervs2 +XX15 N014 N015 VDD 0 invertervs3 +XX16 N015 N016 VDD 0 invertervs4 +XX17 N016 N017 VDD 0 inverter + +* amplify +XX18 N017 Osc_out VDD 0 invertervs3 .include switch-invs.lib diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index cd8ab27c3..faf16dc3b 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -6670,10 +6670,12 @@ insert_new_model(struct vsmodels *vsmodel, char *name, char *subcktline) x->nextmodel = vsmodel ? vsmodel->nextmodel : NULL; x->modelname = copy(name); x->subcktline = copy(subcktline); - if (vsmodel) - vsmodel->nextmodel = x; + if (vsmodel) + vsmodel->nextmodel = x; + else + vsmodel = x; - return x; + return vsmodel; } /* find the model */ @@ -6923,12 +6925,75 @@ pspice_compat(struct card *oldcard) * .MODEL SWN VSWITCH ( VON = {0.55} VOFF = {0.49} RON={1/(2*M*(W/LE)*(KPN/2)*10)} ROFF={1G} ) * by * a1 %v(DG) %gd(D S) swa -* .MODEL SWA aswitch(cntl_off=0.49 cntl_on=0.55 r_off=1G r_on={1/(2*M*(W/LE)*(KPN/2)*10)} log=TRUE) */ - for (card = newcard; card; card = card->nextcard) { +* .MODEL SWA aswitch(cntl_off=0.49 cntl_on=0.55 r_off=1G r_on={1/(2*M*(W/LE)*(KPN/2)*10)} log=TRUE) + +* simple hierachy, as nested subcircuits are not allowed in PSPICE */ + + /* first scan: find the vswitch models, transform them and put them into a list */ + for (card = newcard; card; card = card->nextcard) { + char *str; + static struct card *subcktline = NULL; + static int nesting = 0; + char *cut_line = card->line; + if (ciprefix(".subckt", cut_line)) { + subcktline = card; + nesting++; + } + if (ciprefix(".ends", cut_line)) + nesting--; + + if (ciprefix(".model", card->line) && strstr(card->line, "vswitch")) { + char *modpar[4]; + char *modname; + int i; + + card->line = str = inp_remove_ws(card->line); + str = nexttok(str); /* throw away '.model' */ + INPgetNetTok(&str, &modname, 0); /* model name */ + if (!ciprefix("vswitch", str)) + continue; + /* we have to find 4 parameters, identified by '=', separated by spaces */ + char *equalptr[4]; + equalptr[0] = strstr(str, "="); + if (!equalptr[0]) { + fprintf(stderr, "Error: not enough parameters in vswitch model\n %s\n", card->line); + controlled_exit(1); + } + for (i = 1; i < 4; i++) { + equalptr[i] = strstr(equalptr[i - 1] + 1, "="); + if (!equalptr[i]) { + fprintf(stderr, "Error: not enough parameters in vswitch model\n %s\n", card->line); + controlled_exit(1); + } + } + for (i = 0; i < 4; i++) { + equalptr[i] = skip_back_ws(equalptr[i], str); + equalptr[i] = skip_back_non_ws(equalptr[i], str); + } + for (i = 0; i < 3; i++) + modpar[i] = copy_substring(equalptr[i], equalptr[i + 1] - 1); + if (strrchr(equalptr[3], ')')) + modpar[3] = copy_substring(equalptr[3], strrchr(equalptr[3], ')')); + else + /* vswitch defined without parens */ + modpar[3] = copy(equalptr[3]); + tfree(card->line); + /* replace VON by cntl_on, VOFF by cntl_off, RON by r_on, and ROFF by r_off */ + rep_spar(modpar); + card->line = tprintf(".model a%s aswitch(%s %s %s %s log=TRUE)", + modname, modpar[0], modpar[1], modpar[2], modpar[3]); + for (i = 0; i < 4; i++) + tfree(modpar[i]); + if (nesting > 0) + modelsfound = insert_new_model(modelsfound, modname, subcktline->line); + else + modelsfound = insert_new_model(modelsfound, modname, "top"); + } + } + /* second scan: find the switch instances s calling a vswitch model and transform them */ + for (card = newcard; card; card = card->nextcard) { static struct card *subcktline = NULL; static int nesting = 0; - char *newline = NULL; - bool vsfound = FALSE; char *cut_line = card->line; if (*cut_line == '*') continue; @@ -6951,155 +7016,27 @@ pspice_compat(struct card *oldcard) if (ciprefix(".ends", cut_line)) nesting--; - if (ciprefix("s", cut_line)) { - /* check for the model name */ - int i; - struct card *modcard; - char *stoks[6]; - for (i = 0; i < 6; i++) - stoks[i] = gettok(&cut_line); - /* rewrite s line, but do the replacement only, if a vswitch is found */ - newline = tprintf("a%s %%vd(%s %s) %%gd(%s %s) a%s", - stoks[0], stoks[3], stoks[4], stoks[1], stoks[2], stoks[5]); - /* find the corresponding model */ - if (nesting > 0) - /* inside of subckt, only same level */ - /* check if we already had the .model line defined */ - if (find_a_model(modelsfound, stoks[5], subcktline->line)) - vsfound = TRUE; - else { - for (modcard = subcktline; ; modcard = modcard->nextcard) { - char *str; - if (ciprefix(".ends", modcard->line)) - break; - if (ciprefix(".model", modcard->line) && strstr(modcard->line, stoks[5]) && strstr(modcard->line, "vswitch")) { - char *modpar[4]; - modcard->line = str = inp_remove_ws(modcard->line); - str = nexttok(str); /* throw away '.model' */ - str = nexttok(str); /* throw away 'modname' */ - if (!ciprefix("vswitch", str)) - goto next_loop; -#ifndef XSPICE - else { - fprintf(stderr, "Error: vswitch device requires XSPICE \n"); - controlled_exit(1); - } -#endif - /* we have to find 4 parameters, identified by '=', separated by spaces */ - char *equalptr[4]; - equalptr[0] = strstr(str, "="); - if (!equalptr[0]) { - fprintf(stderr, "Error: not enough parameters in vswitch model\n %s\n", modcard->line); - controlled_exit(1); - } - for (i = 1; i < 4; i++) { - equalptr[i] = strstr(equalptr[i - 1] + 1, "="); - if (!equalptr[i]) { - fprintf(stderr, "Error: not enough parameters in vswitch model\n %s\n", modcard->line); - controlled_exit(1); - } - } - for (i = 0; i < 4; i++) { - equalptr[i] = skip_back_ws(equalptr[i], str); - equalptr[i] = skip_back_non_ws(equalptr[i], str); - } - for (i = 0; i < 3; i++) - modpar[i] = copy_substring(equalptr[i], equalptr[i + 1] - 1); - if (strrchr(equalptr[3], ')')) - modpar[3] = copy_substring(equalptr[3], strrchr(equalptr[3], ')')); - else - /* vswitch defined without parens */ - modpar[3] = copy(equalptr[3]); - tfree(modcard->line); - /* .model is now in modcard, tokens in modpar, call to s in card, tokens in stoks */ - /* rewrite .model line (modcard->li_line already freed in inp_remove_ws()) - Replace VON by cntl_on, VOFF by cntl_off, RON by r_on, and ROFF by r_off */ - rep_spar(modpar); - modcard->line = tprintf(".model a%s aswitch(%s %s %s %s log=TRUE)", - stoks[5], modpar[0], modpar[1], modpar[2], modpar[3]); - for (i = 0; i < 4; i++) - tfree(modpar[i]); - modelsfound = insert_new_model(modelsfound, stoks[5], subcktline->line); - vsfound = TRUE; - break; - } - } - } - if(!vsfound) - /* at top level only or if no model is found at sub-level */ - /* check if we already had the .model line defined */ - if (find_a_model(modelsfound, stoks[5], "top")) - vsfound = TRUE; - else { - for (modcard = newcard; modcard; modcard = modcard->nextcard) { - static int inesting = 0; - char *str; - if (ciprefix(".subckt", modcard->line)) { - inesting++; - } - if (ciprefix(".ends", modcard->line)) - inesting--; - if ((inesting == 0) && ciprefix(".model", modcard->line) && strstr(modcard->line, stoks[5]) && strstr(modcard->line, "vswitch")) { - char *delstr; - char *modpar[4]; - delstr = str = inp_remove_ws(modcard->line); - str = nexttok(str); /* throw away '.model' */ - str = nexttok(str); /* throw away 'modname' */ - if (!ciprefix("vswitch", str)) - goto next_loop; -#ifndef XSPICE - else { - fprintf(stderr, "Error: vswitch device requires XSPICE \n"); - controlled_exit(1); - } -#endif - /* we have to find 4 parameters, identified by '=', separated by spaces */ - char *equalptr[4]; - equalptr[0] = strstr(str, "="); - if (!equalptr[0]) { - fprintf(stderr, "Error: not enough parameters in vswitch model\n %s\n", modcard->line); - controlled_exit(1); - } - for (i = 1; i < 4; i++) { - equalptr[i] = strstr(equalptr[i - 1] + 1, "="); - if (!equalptr[i]) { - fprintf(stderr, "Error: not enough parameters in vswitch model\n %s\n", modcard->line); - controlled_exit(1); - } - } - for (i = 0; i < 4; i++) { - equalptr[i] = skip_back_ws(equalptr[i], str); - equalptr[i] = skip_back_non_ws(equalptr[i], str); - } - for (i = 0; i < 3; i++) - modpar[i] = copy_substring(equalptr[i], equalptr[i + 1] - 1); - modpar[3] = copy_substring(equalptr[3], strrchr(equalptr[3], ')')); - - /* .model is now in modcard, tokens in modpar, call to s in card, tokens in stoks */ - /* rewrite .model line (already freed in inp_remove_ws()) - Replace VON by cntl_on, VOFF by cntl_off, RON by r_on, and ROFF by r_off */ - rep_spar(modpar); - modcard->line = tprintf(".model a%s aswitch ( %s %s %s %s log=TRUE )", - stoks[5], modpar[0], modpar[1], modpar[2], modpar[3]); - for (i = 0; i < 4; i++) - tfree(modpar[i]); - modelsfound = insert_new_model(modelsfound, stoks[5], "top"); - vsfound = TRUE; - } - } - } - for (i = 0; i < 6; i++) - tfree(stoks[i]); - } - if (vsfound) { - /* we have found a corresponding vswitch model, so do the replacement of the instance line */ - tfree(card->line); - card->line = copy(newline); - vsfound = FALSE; - } - next_loop: - /* jump to here if no vswitch model has been found */ - tfree(newline); + if (ciprefix("s", cut_line)) { + /* check for the model name */ + int i; + char *stoks[6]; + for (i = 0; i < 6; i++) + stoks[i] = gettok(&cut_line); + /* rewrite s line and replace it if a model is found */ + if (find_a_model(modelsfound, stoks[5], subcktline->line)) { + tfree(card->line); + card->line = tprintf("a%s %%vd(%s %s) %%gd(%s %s) a%s", + stoks[0], stoks[3], stoks[4], stoks[1], stoks[2], stoks[5]); + } + /* if model is not within same subcircuit, search at top level */ + else if (find_a_model(modelsfound, stoks[5], "top")) { + tfree(card->line); + card->line = tprintf("a%s %%vd(%s %s) %%gd(%s %s) a%s", + stoks[0], stoks[3], stoks[4], stoks[1], stoks[2], stoks[5]); + } + for (i = 0; i < 6; i++) + tfree(stoks[i]); + } } del_models(modelsfound);