Browse Source

re-write vswitch transformation code:

first scan: check for each .model with vswitch
second scan: check for switch instances
(s lines) using the models
pre-master-46
Holger Vogt 8 years ago
parent
commit
7b6cd86a62
  1. 24
      examples/p-to-n-examples/switch-invs.lib
  2. 41
      examples/p-to-n-examples/switch-oscillators_inc.cir
  3. 189
      src/frontend/inpcom.c

24
examples/p-to-n-examples/switch-invs.lib

@ -19,7 +19,7 @@ C2 out vdd 0.1p
* sw like a CMOS inverter * sw like a CMOS inverter
.subckt inverter In Out VDD DGND .subckt inverter In Out VDD DGND
sp out vdd vdd in swswitch sp out vdd vdd in swswitch
*Rl out 0 10k
Rin in 0 1e9
Cl out dgnd 0.1p Cl out dgnd 0.1p
C2 out vdd 0.1p C2 out vdd 0.1p
sn out dgnd in dgnd swswitch sn out dgnd in dgnd swswitch
@ -31,7 +31,7 @@ sn out dgnd in dgnd swswitch
* sw like a CMOS inverter with PSPICE VSWITCH * sw like a CMOS inverter with PSPICE VSWITCH
.subckt invertervs In Out VDD DGND .subckt invertervs In Out VDD DGND
sp out vdd vdd in swn sp out vdd vdd in swn
*Rl out 0 10k
Rin in 0 1e9
Cl out dgnd 0.1p Cl out dgnd 0.1p
C2 out vdd 0.1p C2 out vdd 0.1p
sn out dgnd in dgnd swn sn out dgnd in dgnd swn
@ -43,12 +43,30 @@ sn out dgnd in dgnd swn
* sw like a CMOS inverter with PSPICE VSWITCH * sw like a CMOS inverter with PSPICE VSWITCH
.subckt invertervs2 In Out VDD DGND .subckt invertervs2 In Out VDD DGND
sp out vdd vdd in swn sp out vdd vdd in swn
*Rl out 0 10k
Rin in 0 1e9
Cl out dgnd 0.1p Cl out dgnd 0.1p
C2 out vdd 0.1p C2 out vdd 0.1p
sn out dgnd in dgnd swn sn out dgnd in dgnd swn
.MODEL SWN VSWITCH ( VON = 1.1 VOFF = 0.9 RON=1k ROFF=1e12 ) .MODEL SWN VSWITCH ( VON = 1.1 VOFF = 0.9 RON=1k ROFF=1e12 )
.ends invertervs2 .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

41
examples/p-to-n-examples/switch-oscillators_inc.cir

@ -8,34 +8,35 @@ plot V(Osc_out)
rusage rusage
.endc .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 VDD VDD2 0 DC 3
VMEASURE VDD2 VDD dc 0 VMEASURE VDD2 VDD dc 0
cvdd vdd 0 1e-18 cvdd vdd 0 1e-18
XX18 Osc_out N001 VDD 0 inverter
XX1 N017 N001 VDD 0 invertervs
XX2 N001 N002 VDD 0 inverter 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 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 .include switch-invs.lib

189
src/frontend/inpcom.c

@ -6672,8 +6672,10 @@ insert_new_model(struct vsmodels *vsmodel, char *name, char *subcktline)
x->subcktline = copy(subcktline); x->subcktline = copy(subcktline);
if (vsmodel) if (vsmodel)
vsmodel->nextmodel = x; vsmodel->nextmodel = x;
else
vsmodel = x;
return x;
return vsmodel;
} }
/* find the model */ /* find the model */
@ -6923,27 +6925,16 @@ 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} ) * .MODEL SWN VSWITCH ( VON = {0.55} VOFF = {0.49} RON={1/(2*M*(W/LE)*(KPN/2)*10)} ROFF={1G} )
* by * by
* a1 %v(DG) %gd(D S) swa * 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) */
* .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) { for (card = newcard; card; card = card->nextcard) {
char *str;
static struct card *subcktline = NULL; static struct card *subcktline = NULL;
static int nesting = 0; static int nesting = 0;
char *newline = NULL;
bool vsfound = FALSE;
char *cut_line = card->line; char *cut_line = card->line;
if (*cut_line == '*')
continue;
// exclude any command inside .control ... .endc
if (ciprefix(".control", cut_line)) {
skip_control++;
continue;
}
else if (ciprefix(".endc", cut_line)) {
skip_control--;
continue;
}
else if (skip_control > 0) {
continue;
}
if (ciprefix(".subckt", cut_line)) { if (ciprefix(".subckt", cut_line)) {
subcktline = card; subcktline = card;
nesting++; nesting++;
@ -6951,51 +6942,27 @@ pspice_compat(struct card *oldcard)
if (ciprefix(".ends", cut_line)) if (ciprefix(".ends", cut_line))
nesting--; 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")) {
if (ciprefix(".model", card->line) && strstr(card->line, "vswitch")) {
char *modpar[4]; char *modpar[4];
modcard->line = str = inp_remove_ws(modcard->line);
char *modname;
int i;
card->line = str = inp_remove_ws(card->line);
str = nexttok(str); /* throw away '.model' */ str = nexttok(str); /* throw away '.model' */
str = nexttok(str); /* throw away 'modname' */
INPgetNetTok(&str, &modname, 0); /* model name */
if (!ciprefix("vswitch", str)) if (!ciprefix("vswitch", str))
goto next_loop;
#ifndef XSPICE
else {
fprintf(stderr, "Error: vswitch device requires XSPICE \n");
controlled_exit(1);
}
#endif
continue;
/* we have to find 4 parameters, identified by '=', separated by spaces */ /* we have to find 4 parameters, identified by '=', separated by spaces */
char *equalptr[4]; char *equalptr[4];
equalptr[0] = strstr(str, "="); equalptr[0] = strstr(str, "=");
if (!equalptr[0]) { if (!equalptr[0]) {
fprintf(stderr, "Error: not enough parameters in vswitch model\n %s\n", modcard->line);
fprintf(stderr, "Error: not enough parameters in vswitch model\n %s\n", card->line);
controlled_exit(1); controlled_exit(1);
} }
for (i = 1; i < 4; i++) { for (i = 1; i < 4; i++) {
equalptr[i] = strstr(equalptr[i - 1] + 1, "="); equalptr[i] = strstr(equalptr[i - 1] + 1, "=");
if (!equalptr[i]) { if (!equalptr[i]) {
fprintf(stderr, "Error: not enough parameters in vswitch model\n %s\n", modcard->line);
fprintf(stderr, "Error: not enough parameters in vswitch model\n %s\n", card->line);
controlled_exit(1); controlled_exit(1);
} }
} }
@ -7010,96 +6977,66 @@ pspice_compat(struct card *oldcard)
else else
/* vswitch defined without parens */ /* vswitch defined without parens */
modpar[3] = copy(equalptr[3]); 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 */
tfree(card->line);
/* replace VON by cntl_on, VOFF by cntl_off, RON by r_on, and ROFF by r_off */
rep_spar(modpar); 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]);
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++) for (i = 0; i < 4; i++)
tfree(modpar[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 (nesting > 0)
modelsfound = insert_new_model(modelsfound, modname, subcktline->line);
else
modelsfound = insert_new_model(modelsfound, modname, "top");
} }
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);
/* 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 *cut_line = card->line;
if (*cut_line == '*')
continue;
// exclude any command inside .control ... .endc
if (ciprefix(".control", cut_line)) {
skip_control++;
continue;
} }
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);
else if (ciprefix(".endc", cut_line)) {
skip_control--;
continue;
} }
else if (skip_control > 0) {
continue;
} }
for (i = 0; i < 4; i++) {
equalptr[i] = skip_back_ws(equalptr[i], str);
equalptr[i] = skip_back_non_ws(equalptr[i], str);
if (ciprefix(".subckt", cut_line)) {
subcktline = card;
nesting++;
} }
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], ')'));
if (ciprefix(".ends", cut_line))
nesting--;
/* .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;
}
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++) for (i = 0; i < 6; i++)
tfree(stoks[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);
} }
del_models(modelsfound); del_models(modelsfound);

Loading…
Cancel
Save