Browse Source

Add PSPICE compatible ISWITCH

Translates iswitch either to csw or to aswitch models
pre-master-46
Holger Vogt 6 years ago
parent
commit
14ef4e74ec
  1. 201
      src/frontend/inpcom.c

201
src/frontend/inpcom.c

@ -7461,6 +7461,18 @@ static int rep_spar(char *inpar[4])
inpar[i] = tprintf("cntl_%s", strend); inpar[i] = tprintf("cntl_%s", strend);
tfree(strend); tfree(strend);
} }
else if ((t = strstr(tok, "ion")) != NULL) {
strend = copy(t + 1);
tfree(inpar[i]);
inpar[i] = tprintf("cntl_%s", strend);
tfree(strend);
}
else if ((t = strstr(tok, "ioff")) != NULL) {
strend = copy(t + 1);
tfree(inpar[i]);
inpar[i] = tprintf("cntl_%s", strend);
tfree(strend);
}
else if ((t = strstr(tok, "ron")) != NULL) { else if ((t = strstr(tok, "ron")) != NULL) {
strend = copy(t + 1); strend = copy(t + 1);
tfree(inpar[i]); tfree(inpar[i]);
@ -7549,13 +7561,13 @@ static bool del_models(struct vsmodels *vsmodel)
as1 %vd(DG GND) % gd(D S) aswn as1 %vd(DG GND) % gd(D S) aswn
.model aswn aswitch(cntl_off={0.49} cntl_on={0.55} r_off={1G} .model aswn aswitch(cntl_off={0.49} cntl_on={0.55} r_off={1G}
+ r_on={ 1 / (2 * M*(W / LE)*(KPN / 2) * 10) } log = TRUE) + r_on={ 1 / (2 * M*(W / LE)*(KPN / 2) * 10) } log = TRUE)
* replace vsitch part S_ST
* replace vswitch part S_ST
S1 D S DG GND S_ST S1 D S DG GND S_ST
.MODEL S_ST VSWITCH(VT = { 1.5 } VH = { 0.s }
.MODEL S_ST VSWITCH(VT = { 1.5 } VH = { 0.3 }
RON = { 1 / (2 * M*(W / LE)*(KPN / 2) * 10) } ROFF = { 1G }) RON = { 1 / (2 * M*(W / LE)*(KPN / 2) * 10) } ROFF = { 1G })
* by the classical voltage controlled ngspice switch * by the classical voltage controlled ngspice switch
S1 D S DG GND SWN S1 D S DG GND SWN
.MODEL S_ST SW(VT = { 1.5 } VH = { 0.s }
.MODEL S_ST SW(VT = { 1.5 } VH = { 0.3 }
RON = { 1 / (2 * M*(W / LE)*(KPN / 2) * 10) } ROFF = { 1G }) RON = { 1 / (2 * M*(W / LE)*(KPN / 2) * 10) } ROFF = { 1G })
switch parameter td is not yet supported switch parameter td is not yet supported
* replace & by && * replace & by &&
@ -8092,10 +8104,193 @@ static struct card *pspice_compat(struct card *oldcard)
} }
} }
del_models(modelsfound); del_models(modelsfound);
modelsfound = NULL;
/* if iswitch part s, replace
* W1 D S VC SWN
* .MODEL SWN ISWITCH ( ION = {0.55} IOFF = {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)
*
* if iswitch part s_st (short transition), don't replace instance, but only model
* replace
* W1 D S VC S_ST
* .MODEL S_ST ISWITCH(IT = { 1.5 } IH = { 0.2 }
RON = { 1 / (2 * M*(W / LE)*(KPN / 2) * 10) } ROFF = { 1G })
* by the classical current controlled ngspice switch
* W1 D S DG GND S_ST
* .MODEL S_ST CSW(IT = { 1.5 } IH = { 0.2 }
RON = { 1 / (2 * M*(W / LE)*(KPN / 2) * 10) } ROFF = { 1G })
* iswitch delay parameter td is not yet supported
* simple hierachy, as nested subcircuits are not allowed in PSPICE */
/* first scan: find the iswitch models, transform them and put them into a
* list */
bool have_it = FALSE, have_ih = FALSE;
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, "iswitch")) {
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("iswitch", str)) {
tfree(modname);
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 iswitch 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 iswitch model\n "
" %s\n",
card->line);
controlled_exit(1);
}
}
for (i = 0; i < 4; i++) {
equalptr[i] = skip_back_ws(equalptr[i], str);
while (*(equalptr[i]) != '(' && !isspace_c(*(equalptr[i])) &&
*(equalptr[i]) != ',')
(equalptr[i])--;
(equalptr[i])++;
}
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
/* iswitch defined without parens */
modpar[3] = copy(equalptr[3]);
/* check if we have parameters IT and IH */
for (i = 0; i < 4; i++) {
if (ciprefix("ih", modpar[i]))
have_ih = TRUE;
if (ciprefix("it", modpar[i]))
have_it = TRUE;
}
if (have_ih && have_it) {
/* replace iswitch by csw */
char* vs = strstr(card->line, "iswitch");
memmove(vs, " csw", 7);
}
else {
/* replace ION by cntl_on, IOFF by cntl_off, RON by r_on, and
* ROFF by r_off */
tfree(card->line);
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");
tfree(modname);
}
}
/* no need to continue if no vswitch is found */
if (!modelsfound)
return newcard;
/* no need to change the switch instances if switch csw is used */
if (have_ih && have_it)
return newcard;
/* second scan: find the switch instances s calling an iswitch 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;
}
else if (ciprefix(".endc", cut_line)) {
skip_control--;
continue;
}
else if (skip_control > 0) {
continue;
}
if (ciprefix(".subckt", cut_line)) {
subcktline = card;
nesting++;
}
if (ciprefix(".ends", cut_line))
nesting--;
if (ciprefix("w", cut_line)) {
/* check for the model name */
int i;
char* stoks[5];
for (i = 0; i < 5; i++)
stoks[i] = gettok_node(&cut_line);
/* rewrite w line and replace it if a model is found */
if ((nesting > 0) &&
find_a_model(modelsfound, stoks[4], subcktline->line)) {
tfree(card->line);
card->line = tprintf("a%s %%vnam(%s) %%gd(%s %s) a%s",
stoks[0], stoks[3], stoks[1], stoks[2],
stoks[4]);
}
/* if model is not within same subcircuit, search at top level */
else if (find_a_model(modelsfound, stoks[4], "top")) {
tfree(card->line);
card->line = tprintf("a%s %%vnam(%s) %%gd(%s %s) a%s",
stoks[0], stoks[3], stoks[1], stoks[2],
stoks[4]);
}
for (i = 0; i < 5; i++)
tfree(stoks[i]);
}
}
del_models(modelsfound);
return newcard; return newcard;
} }
/* do not modify oldcard address, insert everything after first line only */ /* do not modify oldcard address, insert everything after first line only */
static void pspice_compat_a(struct card *oldcard) static void pspice_compat_a(struct card *oldcard)
{ {

Loading…
Cancel
Save