Merge branch 'pre-master-45' into bt_dev

This commit is contained in:
Brian Taylor 2025-05-11 14:17:40 -07:00
commit 91f20af48f
13 changed files with 154 additions and 139 deletions

View File

@ -1283,6 +1283,13 @@ struct card *inp_readall(FILE *fp, const char *dir_name, const char* file_name,
return cc;
}
static char *skip_token(char *s)
{
s = skip_ws(s); /* Advance past space chars. */
s = skip_non_ws(s); /* Skip over token. */
return skip_ws(s);
}
static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name,
const char* file_name, bool comfile, bool intfile)
@ -1420,8 +1427,8 @@ static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name
/* now handle .title statement */
if (ciprefix(".title", buffer)) {
char* s;
s = skip_non_ws(buffer); /* skip over .title */
s = skip_ws(s); /* advance past space chars */
s = skip_token(buffer);
/* only the last title line remains valid */
tfree(new_title);
@ -2800,13 +2807,11 @@ static void inp_fix_macro_param_func_paren_io(struct card *card)
if (ciprefix(".subckt", card->line) || ciprefix("x", card->line)) {
/* remove () */
str_ptr = skip_non_ws(card->line);
// skip over .subckt, instance name
str_ptr = skip_ws(str_ptr);
if (ciprefix(".subckt", card->line)) {
str_ptr = skip_non_ws(str_ptr); // skip over subckt name
str_ptr = skip_ws(str_ptr);
}
str_ptr = skip_token(card->line); // Skip over .subckt.
if (ciprefix(".subckt", card->line))
str_ptr = skip_token(str_ptr); // Skip over subckt name.
if (*str_ptr == '(') {
*str_ptr = ' ';
while (*str_ptr != '\0') {
@ -2824,8 +2829,8 @@ static void inp_fix_macro_param_func_paren_io(struct card *card)
if (ciprefix(".para", card->line)) {
bool is_func = FALSE;
str_ptr = skip_non_ws(card->line); // skip over .param
str_ptr = skip_ws(str_ptr);
str_ptr = skip_token(card->line); // skip over .param
while (!isspace_c(*str_ptr) && *str_ptr != '=') {
if (*str_ptr == '(')
is_func = TRUE;
@ -2874,13 +2879,8 @@ static char *get_subckt_model_name(char *line)
{
char *name, *end_ptr;
name = skip_non_ws(line); // eat .subckt|.model
name = skip_ws(name);
name = skip_token(line); // Eat .subckt or .model
end_ptr = skip_non_ws(name);
return copy_substring(name, end_ptr);
}
@ -2890,23 +2890,16 @@ static char *get_model_name(char *line, int num_terminals)
char *beg_ptr, *end_ptr;
int i = 0;
beg_ptr = skip_non_ws(line); /* eat device name */
beg_ptr = skip_ws(beg_ptr);
for (i = 0; i < num_terminals; i++) { /* skip the terminals */
beg_ptr = skip_non_ws(beg_ptr);
beg_ptr = skip_ws(beg_ptr);
}
beg_ptr = skip_token(line); // Eat device name.
for (i = 0; i < num_terminals; i++)
beg_ptr = skip_token(beg_ptr); // Eat terminal.
if (*line == 'r') /* special dealing for r models */
if ((*beg_ptr == '+') || (*beg_ptr == '-') ||
isdigit_c(*beg_ptr)) { /* looking for a value before model */
beg_ptr = skip_non_ws(beg_ptr); /* skip the value */
beg_ptr = skip_ws(beg_ptr);
beg_ptr = skip_token(beg_ptr); /* Skip the value, */
}
end_ptr = skip_non_ws(beg_ptr);
return copy_substring(beg_ptr, end_ptr);
}
@ -2918,12 +2911,8 @@ static char *get_model_type(char *line)
if (!ciprefix(".model", line))
return NULL;
beg_ptr = skip_non_ws(line); /* eat .model */
beg_ptr = skip_ws(beg_ptr);
beg_ptr = skip_non_ws(beg_ptr); /* eat model name */
beg_ptr = skip_ws(beg_ptr);
beg_ptr = skip_token(line); /* Eat .model */
beg_ptr = skip_token(beg_ptr); /* Eat model name. */
return gettok_noparens(&beg_ptr);
}
@ -3655,8 +3644,8 @@ static char *inp_fix_subckt(struct names *subckt_w_params, char *s)
if (equal &&
(!strstr(s, "params:") || !isspace_c(s[-1]))) {
/* get subckt name (ptr1 will point to name) */
ptr1 = skip_non_ws(s);
ptr1 = skip_ws(ptr1);
ptr1 = skip_token(s);
for (ptr2 = ptr1; *ptr2 && !isspace_c(*ptr2) && !isquote(*ptr2);
ptr2++)
;
@ -4275,8 +4264,8 @@ static void inp_fix_inst_calls_for_numparam(
continue;
if (d) {
char *subckt_line = d->line;
subckt_line = skip_non_ws(subckt_line);
subckt_line = skip_ws(subckt_line);
subckt_line = skip_token(subckt_line);
int num_subckt_params = inp_get_params(subckt_line,
subckt_param_names, subckt_param_values);
@ -4385,8 +4374,7 @@ static void inp_get_func_from_line(struct function_env *env, char *line)
struct function *function;
/* skip `.func' */
line = skip_non_ws(line);
line = skip_ws(line);
line = skip_token(line);
/* get function name */
end = line;
@ -5501,8 +5489,7 @@ static void inp_add_params_to_subckt(
if (!strstr(subckt_line, "params:")) {
new_line = tprintf("%s params: %s", subckt_line, param_ptr);
subckt_name = skip_non_ws(subckt_line);
subckt_name = skip_ws(subckt_name);
subckt_name = skip_token(subckt_line);
end_ptr = skip_non_ws(subckt_name);
add_name(subckt_w_params, copy_substring(subckt_name, end_ptr));
}
@ -7867,9 +7854,7 @@ static void inp_fix_temper_in_param(struct card *deck)
controlled_exit(EXIT_FAILURE);
}
lhs_b = skip_non_ws(curr_line); // eat .param
lhs_b = skip_ws(lhs_b);
lhs_b = skip_token(curr_line); // Eat .param.
lhs_e = skip_back_ws(equal_ptr, curr_line);
/* skip if this is a function already */
@ -8094,9 +8079,7 @@ static void inp_fix_agauss_in_param(struct card *deck, char *fcn)
controlled_exit(EXIT_FAILURE);
}
lhs_b = skip_non_ws(curr_line); // eat .param
lhs_b = skip_ws(lhs_b);
lhs_b = skip_token(curr_line); // Eat .param.
lhs_e = skip_back_ws(equal_ptr, curr_line);
/* skip if this is a function already */
@ -8332,10 +8315,8 @@ static void inp_quote_params(struct card *c, struct card *end_c,
char *s = curr_line;
for (j = 0; j < num_terminals + 1; j++) {
s = skip_non_ws(s);
s = skip_ws(s);
}
for (j = 0; j < num_terminals + 1; j++)
s = skip_token(s);
while ((s = ya_search_identifier(
s, deps[i].param_name, curr_line)) != NULL) {
@ -8403,7 +8384,6 @@ static void inp_quote_params(struct card *c, struct card *end_c,
}
}
/* VDMOS special:
Check for 'vdmos' in .model line.
check if 'pchan', then add p to vdmos and ignore 'pchan'.
@ -8429,16 +8409,17 @@ static int inp_vdmos_model(struct card *deck)
curr_line = card->line;
if (ciprefix(".model", curr_line)) {
cut_line = search_plain_identifier(curr_line, "vdmos");
if (cut_line) {
cut_line = skip_token(curr_line);
cut_line = skip_token(cut_line);
if (!strncmp(cut_line, "vdmos", 5)) {
/* A VDMOS model line, may be vdmosn or vdmosp if re-input. */
wl_append_word(&wl, &wl, copy_substring(curr_line, cut_line));
wlb = wl;
if (search_plain_identifier(cut_line, "pchan")) {
if (search_plain_identifier(cut_line, "pchan") ||
cut_line[5] == 'p') {
wl_append_word(NULL, &wl, copy("vdmosp ("));
}
else if (search_plain_identifier(cut_line, "nchan")) {
wl_append_word(NULL, &wl, copy("vdmosn ("));
}
else {
wl_append_word(NULL, &wl, copy("vdmosn ("));
}
@ -9199,9 +9180,10 @@ static struct modellist *inp_find_model_1(
struct nscope *scope, const char *name)
{
struct modellist *p = scope->models;
for (; p; p = p->next)
for (; p; p = p->next) {
if (model_name_match(name, p->modelname))
break;
}
return p;
}

View File

@ -583,11 +583,18 @@ doit(struct card *deck, wordlist *modnames) {
scale = 1;
error = 0;
/* Second pass: do the replacements. */
/* Second pass: do the replacements.
Check if binning is used for .model inside of the subcircuit.
Reduce .model lines to the one with appropriate w and l.
(Inspired by Skywater PDK with excessive use of binning (161 bins)
in the subcircuit referencing a MOS device) */
do { /* while (!error && numpasses-- && gotone) */
struct card *c = deck;
struct card *prev_of_c = NULL;
bool foundmodel = FALSE;
gotone = FALSE;
for (; c; prev_of_c = c, c = c->nextcard) {
if (ciprefix(invoke, c->line)) { /* found reference to .subckt (i.e. component with refdes X) */
@ -597,16 +604,13 @@ doit(struct card *deck, wordlist *modnames) {
gotone = TRUE;
t = tofree = s = copy(c->line); /* s & t hold copy of component line */
/* make scname point to first non-whitepace chars after refdes invocation
* e.g. if invocation is Xreference, *scname = reference
*/
/* scname contains the refdes Xname */
tofree2 = scname = gettok(&s);
/*scname += strlen(invoke); */
while ((*scname == ' ') || (*scname == '\t') || (*scname == ':'))
scname++;
/* Now set s to point to last non-space chars in line (i.e.
* the name of the model invoked
/* Now set s to point to last non-space chars in the x line (i.e.
* the name of the model invoked)
*/
while (*s)
s++;
@ -617,38 +621,47 @@ doit(struct card *deck, wordlist *modnames) {
s--;
s++;
/* iterate through .subckt list and look for .subckt name invoked */
/* Iterate through .subckt list and look for .subckt name
corresponding to the subckt name extracted from the x line */
for (sss = subs; sss; sss = sss->su_next)
if (eq(sss->su_name, s))
break;
/* At this point, sss points to the .subckt invoked,
* and scname points to the netnames
* involved.
/* At this point,
* c is the card with the x line.
* scname points to the netname of the x line involved.
* s is the subckt name extracted from the x line.
* sss points to the subcircuit referenced by the x line
* sss->su_def is the contents of the subcircuit.
*/
/* If no .subckt is found, don't complain -- this might be an
* instance of a subckt that is defined above at higher level.
*/
if (sss) {
// tprint(sss->su_def);
/* copy of the contents between .subckt and .ends */
struct card *su_deck = inp_deckcopy(sss->su_def);
/* If we have modern PDKs, we have to reduce the amount of memory required.
We try to reduce the models to the one really used.
Otherwise su_deck is full of unused binning models.*/
Otherwise su_deck is full of unused binning models.
c->w > 0 and c->l > 0 point to an x line with given w and l
(typically a call to a MOS device). */
if ((newcompat.hs || newcompat.spe) && c->w > 0 && c->l > 0) {
/* extract wmin, wmax, lmin, lmax */
struct card* new_deck = su_deck;
struct card* enter_su_deck = su_deck;
struct card* prev = NULL;
while (su_deck) {
/* find a .model line */
if (!ciprefix(".model", su_deck->line)) {
prev = su_deck;
su_deck = su_deck->nextcard;
continue;
}
/* check if line contains wmin, wmax, lmin, lmax
if available, extract its values,
if not, go to next line */
char* curr_line = su_deck->line;
float fwmin, fwmax, flmin, flmax;
char *wmin = strstr(curr_line, " wmin=");
@ -716,32 +729,39 @@ doit(struct card *deck, wordlist *modnames) {
su_deck = su_deck->nextcard;
continue;
}
/* check if x line's w and l are withing the limites of wmin, wmax, lmin, lmax */
float csl = (float)scale * c->l;
/* scale by nf */
float csw = (float)scale * c->w / c->nf;
/*fprintf(stdout, "Debug: nf = %f\n", c->nf);*/
if (csl >= flmin && csl < flmax && csw >= fwmin && csw < fwmax) {
/* use the current .model card */
/* if within the limits, use the current .model card */
prev = su_deck;
su_deck = su_deck->nextcard;
foundmodel = TRUE;
continue;
}
else {
/* if not within the limits,
delete the .model line not fitting the device */
struct card* tmpcard = su_deck->nextcard;
line_free_x(prev->nextcard, FALSE);
su_deck = prev->nextcard = tmpcard;
}
}
su_deck = new_deck;
/* go back to the first card of su_deck */
su_deck = enter_su_deck;
}
if (!su_deck) {
fprintf(stderr, "\nError: Could not find a model for device %s in subcircuit %s\n",
scname, sss->su_name);
if (!foundmodel && (newcompat.hs || newcompat.spe) && c->w > 0 && c->l > 0) {
fprintf(stderr, "\nError: Could not find a model\n"
" for device %s in transistor subcircuit %s\n", scname, sss->su_name);
fprintf(stderr, " with w = %.3g and l = %.3g\n\n", c->w, c->l);
controlled_exit(1);
}
foundmodel = FALSE;
struct card *rest_of_c = c->nextcard;
/* Now we have to replace this line with the
@ -782,8 +802,8 @@ doit(struct card *deck, wordlist *modnames) {
tfree(tofree);
tfree(tofree2);
}
}
} /* if (ciprefix(invoke, c->line)) */
} /* for (; c; prev_of_c = c, c = c->nextcard) */
} while (!error && numpasses-- && gotone);

View File

@ -12,15 +12,15 @@ Copyright 1992 Regents of the University of California. All rights reserved.
/* ARGSUSED */
int
CKTdltNod(CKTcircuit *ckt, CKTnode *node)
CKTdltNod(CKTcircuit* ckt, CKTnode* node)
{
return CKTdltNNum(ckt, node->number);
}
int
CKTdltNNum(CKTcircuit *ckt, int num)
CKTdltNNum(CKTcircuit* ckt, int num)
{
CKTnode *n, *prev, *node, *sprev;
CKTnode* n, * prev, * node, * sprev;
int error;
if (!ckt->prev_CKTlastNode->number || num <= ckt->prev_CKTlastNode->number) {
@ -28,32 +28,33 @@ CKTdltNNum(CKTcircuit *ckt, int num)
controlled_exit(EXIT_FAILURE);
}
prev = NULL;
node = NULL;
prev = NULL;
node = NULL;
sprev = NULL;
for (n = ckt->CKTnodes; n; n = n->next) {
if (n->number == num) {
node = n;
sprev = prev;
}
prev = n;
if (n->number == num) {
node = n;
sprev = prev;
}
prev = n;
}
if (!node)
return OK;
return OK;
ckt->CKTmaxEqNum -= 1;
if (!sprev) {
ckt->CKTnodes = node->next;
} else {
sprev->next = node->next;
ckt->CKTnodes = node->next;
}
else {
sprev->next = node->next;
}
if (node == ckt->CKTlastNode)
ckt->CKTlastNode = sprev;
ckt->CKTlastNode = sprev;
error = SPfrontEnd->IFdelUid (ckt, node->name, UID_SIGNAL);
error = SPfrontEnd->IFdelUid(ckt, node->name, UID_SIGNAL);
tfree(node);
return error;

View File

@ -145,9 +145,9 @@ MOS1noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
N_GAIN, inst->MOS1dNodePrime, inst->MOS1sNodePrime,
(double) 0.0);
if (newcompat.s3) {
noizDens[MOS1FLNOIZ] *= model->MOS1fNcoef *
noizDens[MOS1FLNOIZ] *= inst->MOS1m * model->MOS1fNcoef *
exp(model->MOS1fNexp *
log(MAX(fabs(inst->MOS1cd), N_MINLOG))) /
log(MAX(fabs(inst->MOS1cd / inst->MOS1m), N_MINLOG))) /
(data->freq *
inst->MOS1w *
(inst->MOS1l - 2 * model->MOS1latDiff) *
@ -155,18 +155,18 @@ MOS1noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
} else {
switch (model->MOS1nlev) {
case 0:
noizDens[MOS1FLNOIZ] *= model->MOS1fNcoef *
noizDens[MOS1FLNOIZ] *= inst->MOS1m * model->MOS1fNcoef *
exp(model->MOS1fNexp *
log(MAX(fabs(inst->MOS1cd), N_MINLOG))) /
log(MAX(fabs(inst->MOS1cd / inst->MOS1m), N_MINLOG))) /
(data->freq *
(inst->MOS1l - 2 * model->MOS1latDiff) *
(inst->MOS1l - 2 * model->MOS1latDiff) *
sqrt(coxSquared));
break;
case 1:
noizDens[MOS1FLNOIZ] *= model->MOS1fNcoef *
noizDens[MOS1FLNOIZ] *= inst->MOS1m * model->MOS1fNcoef *
exp(model->MOS1fNexp *
log(MAX(fabs(inst->MOS1cd), N_MINLOG))) /
log(MAX(fabs(inst->MOS1cd / inst->MOS1m), N_MINLOG))) /
(data->freq *
inst->MOS1w *
(inst->MOS1l - 2 * model->MOS1latDiff) *
@ -174,7 +174,7 @@ MOS1noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
break;
case 2: case 3:
noizDens[MOS1FLNOIZ] *= model->MOS1fNcoef *
inst->MOS1gm * inst->MOS1gm /
inst->MOS1gm * inst->MOS1gm / inst->MOS1m /
(pow(data->freq, model->MOS1fNexp) *
inst->MOS1w *
(inst->MOS1l - 2 * model->MOS1latDiff) *

View File

@ -34,7 +34,7 @@ MOS2load(GENmodel *inModel, CKTcircuit *ckt)
double GateBulkOverlapCap;
double GateDrainOverlapCap;
double GateSourceOverlapCap;
double OxideCap;
double OxideCap, unscaledOxideCap;
double SourceSatCur;
double arg;
double cbhat;
@ -144,8 +144,8 @@ MOS2load(GENmodel *inModel, CKTcircuit *ckt)
here->MOS2m * EffectiveLength;
Beta = here->MOS2tTransconductance * here->MOS2w *
here->MOS2m/EffectiveLength;
OxideCap = model->MOS2oxideCapFactor * EffectiveLength *
here->MOS2m * here->MOS2w;
unscaledOxideCap = model->MOS2oxideCapFactor * EffectiveLength * here->MOS2w;
OxideCap = unscaledOxideCap*here->MOS2m;
if(SenCond){
@ -599,7 +599,7 @@ next1: if(vbs <= -3*vt) {
/*XXX constant per device */
factor = 0.125*model->MOS2narrowFactor*2.0*M_PI*EPSSIL/
OxideCap*EffectiveLength;
unscaledOxideCap*EffectiveLength;
/*XXX constant per device */
eta = 1.0+factor;
vbin = here->MOS2tVbi*model->MOS2type+factor*phiMinVbs;
@ -664,7 +664,7 @@ next1: if(vbs <= -3*vt) {
1e4 /*(cm**2/m**2)*/;
cdonco = -(gamasd*dsrgdb+dgddvb*sarg1)+factor;
xn = 1.0+cfs/OxideCap*here->MOS2m*
xn = 1.0+cfs/unscaledOxideCap*
here->MOS2w*EffectiveLength+cdonco;
tmp = vt*xn;

View File

@ -134,9 +134,9 @@ MOS2noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
N_GAIN, inst->MOS2dNodePrime, inst->MOS2sNodePrime,
(double) 0.0);
if (newcompat.s3) {
noizDens[MOS2FLNOIZ] *= model->MOS2fNcoef *
noizDens[MOS2FLNOIZ] *= inst->MOS2m * model->MOS2fNcoef *
exp(model->MOS2fNexp *
log(MAX(fabs(inst->MOS2cd), N_MINLOG))) /
log(MAX(fabs(inst->MOS2cd / inst->MOS2m), N_MINLOG))) /
(data->freq *
inst->MOS2w *
(inst->MOS2l - 2 * model->MOS2latDiff) *
@ -144,18 +144,18 @@ MOS2noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
} else {
switch (model->MOS2nlev) {
case 0:
noizDens[MOS2FLNOIZ] *= model->MOS2fNcoef *
noizDens[MOS2FLNOIZ] *= inst->MOS2m * model->MOS2fNcoef *
exp(model->MOS2fNexp *
log(MAX(fabs(inst->MOS2cd), N_MINLOG))) /
log(MAX(fabs(inst->MOS2cd / inst->MOS2m), N_MINLOG))) /
(data->freq *
(inst->MOS2l - 2 * model->MOS2latDiff) *
(inst->MOS2l - 2 * model->MOS2latDiff) *
model->MOS2oxideCapFactor);
break;
case 1:
noizDens[MOS2FLNOIZ] *= model->MOS2fNcoef *
noizDens[MOS2FLNOIZ] *= inst->MOS2m * model->MOS2fNcoef *
exp(model->MOS2fNexp *
log(MAX(fabs(inst->MOS2cd), N_MINLOG))) /
log(MAX(fabs(inst->MOS2cd / inst->MOS2m), N_MINLOG))) /
(data->freq *
inst->MOS2w *
(inst->MOS2l - 2 * model->MOS2latDiff) *
@ -163,7 +163,7 @@ MOS2noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
break;
case 2: case 3:
noizDens[MOS2FLNOIZ] *= model->MOS2fNcoef *
inst->MOS2gm * inst->MOS2gm /
inst->MOS2gm * inst->MOS2gm / inst->MOS2m /
(pow(data->freq, model->MOS2fNexp) *
inst->MOS2w *
(inst->MOS2l - 2 * model->MOS2latDiff) *

View File

@ -134,9 +134,9 @@ MOS3noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
N_GAIN, inst->MOS3dNodePrime, inst->MOS3sNodePrime,
(double) 0.0);
if (newcompat.s3) {
noizDens[MOS3FLNOIZ] *= model->MOS3fNcoef *
noizDens[MOS3FLNOIZ] *= inst->MOS3m * model->MOS3fNcoef *
exp(model->MOS3fNexp *
log(MAX(fabs(inst->MOS3cd), N_MINLOG))) /
log(MAX(fabs(inst->MOS3cd / inst->MOS3m), N_MINLOG))) /
(data->freq *
(inst->MOS3w - 2 * model->MOS3widthNarrow) *
(inst->MOS3l - 2 * model->MOS3latDiff) *
@ -144,18 +144,18 @@ MOS3noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
} else {
switch (model->MOS3nlev) {
case 0:
noizDens[MOS3FLNOIZ] *= model->MOS3fNcoef *
noizDens[MOS3FLNOIZ] *= inst->MOS3m * model->MOS3fNcoef *
exp(model->MOS3fNexp *
log(MAX(fabs(inst->MOS3cd), N_MINLOG))) /
log(MAX(fabs(inst->MOS3cd / inst->MOS3m), N_MINLOG))) /
(data->freq *
(inst->MOS3l - 2 * model->MOS3latDiff) *
(inst->MOS3l - 2 * model->MOS3latDiff) *
model->MOS3oxideCapFactor);
break;
case 1:
noizDens[MOS3FLNOIZ] *= model->MOS3fNcoef *
noizDens[MOS3FLNOIZ] *= inst->MOS3m * model->MOS3fNcoef *
exp(model->MOS3fNexp *
log(MAX(fabs(inst->MOS3cd), N_MINLOG))) /
log(MAX(fabs(inst->MOS3cd / inst->MOS3m), N_MINLOG))) /
(data->freq *
(inst->MOS3w - 2 * model->MOS3widthNarrow) *
(inst->MOS3l - 2 * model->MOS3latDiff) *
@ -163,7 +163,7 @@ MOS3noise(int mode, int operation, GENmodel * genmodel, CKTcircuit * ckt,
break;
case 2: case 3:
noizDens[MOS3FLNOIZ] *= model->MOS3fNcoef *
inst->MOS3gm * inst->MOS3gm /
inst->MOS3gm * inst->MOS3gm / inst->MOS3m /
(pow(data->freq, model->MOS3fNexp) *
(inst->MOS3w - 2 * model->MOS3widthNarrow) *
(inst->MOS3l - 2 * model->MOS3latDiff) *

View File

@ -94,12 +94,11 @@ MOS9noise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt,
NevalSrc(&noizDens[MOS9FLNOIZ], NULL, ckt,
N_GAIN,inst->MOS9dNodePrime, inst->MOS9sNodePrime,
(double)0.0);
noizDens[MOS9FLNOIZ] *= model->MOS9fNcoef *
noizDens[MOS9FLNOIZ] *= inst->MOS9m * model->MOS9fNcoef *
exp(model->MOS9fNexp *
log(MAX(fabs(inst->MOS9cd),N_MINLOG))) /
log(MAX(fabs(inst->MOS9cd / inst->MOS9m),N_MINLOG))) /
(data->freq *
(inst->MOS9w - 2*model->MOS9widthNarrow) *
inst->MOS9m *
(inst->MOS9l - 2*model->MOS9latDiff) *
model->MOS9oxideCapFactor * model->MOS9oxideCapFactor);
lnNdens[MOS9FLNOIZ] =

View File

@ -65,7 +65,7 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
&& here->VSRCcoeffs[4] != 0.0
? here->VSRCcoeffs[4] : ckt->CKTstep;
PW = here->VSRCfunctionOrder > 5
&& here->VSRCcoeffs[5] != 0.0
&& here->VSRCcoeffs[5] >= 0.0
? here->VSRCcoeffs[5] : ckt->CKTfinalTime;
PER = here->VSRCfunctionOrder > 6
&& here->VSRCcoeffs[6] != 0.0

View File

@ -112,7 +112,7 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
&& here->VSRCcoeffs[4] != 0.0
? here->VSRCcoeffs[4] : ckt->CKTstep;
PW = here->VSRCfunctionOrder > 5
&& here->VSRCcoeffs[5] != 0.0
&& here->VSRCcoeffs[5] >= 0.0
? here->VSRCcoeffs[5] : ckt->CKTfinalTime;
PER = here->VSRCfunctionOrder > 6
&& here->VSRCcoeffs[6] != 0.0

View File

@ -149,12 +149,18 @@ create_model(CKTcircuit *ckt, INPmodel *modtmp, INPtables *tab)
if (p) {
char *value;
INPgetTok(&line, &value, 1);
modtmp->INPmodfast->defaults =
wl_cons(copy(parm),
wl_cons(value,
modtmp->INPmodfast->defaults));
INPgetTok(&line, &value, 1);
if (p->dataType & IF_SET) {
modtmp->INPmodfast->defaults =
wl_cons(copy(parm),
wl_cons(value, modtmp->INPmodfast->defaults));
} else {
fprintf(stderr,
"Ignoring attempt to set a default "
"for read-only instance parameter %s in:\n %s\n",
p->keyword, modtmp->INPmodLine->line);
}
} else {
double dval;
@ -286,6 +292,7 @@ INPgetModBin(CKTcircuit *ckt, char *name, INPmodel **model, INPtables *tab, char
for (modtmp = modtab; modtmp; modtmp = modtmp->INPnextModel) {
/* exact: 1, with binning extension .[0-9]: 2*/
if (model_name_match(name, modtmp->INPmodName) < 2)
continue;
@ -328,8 +335,8 @@ INPgetModBin(CKTcircuit *ckt, char *name, INPmodel **model, INPtables *tab, char
*model = modtmp;
return NULL;
}
fprintf(stderr, "Warning: no model found for w=%.3e and l=%.3e\n", w, l);
}
return NULL;
}

View File

@ -4,7 +4,7 @@
* an Icarus Verilog simulation (libvvp.so).
* Licensed on the same terms as Ngspice.
*
* Copyright (c) 2024 Giles Atkinson
* Copyright (c) 2024-2025 Giles Atkinson
*/
#include <stdio.h>
@ -18,6 +18,12 @@
#include "coroutine_shim.h"
#ifdef _MSC_VER
#include "../../../visualc/src/include/ngspice/config.h"
#else
#include "ngspice/config.h" // For NGSPICELIBDIR
#endif
#include "ngspice/cmtypes.h" // For Digital_t
#include "ngspice/cosim.h"

View File

@ -342,7 +342,7 @@ else
if $fh > 0
fclose $fh
else
echo Can not find bulid file $msvcfile
echo Can not find build file $msvcfile
quit
end