`show' printed a device's vector parameter (a source's pulse/pwl/ac
coefficient list) one element at a time, calling askInstanceQuest for
every element. Two bugs made that catastrophic on a large chip:
* IFvalue val was uninitialised, so a query that did not set
v.numValue left `n' as stack garbage -- the element loop then ran
essentially forever.
* askInstanceQuest TMALLOCs the coefficient vector (vsrcask.c) on
every call and printvals()/printvals_old() never freed it, so the
listing leaked O(n^2) allocations -- tens of GB on a deck with many
stimulus sources.
Fix: memset val before the query and clamp n (kills the runaway loop),
and free the returned vector after use via a new free_if_vec() helper.
Verified: pulse coefficients still print correctly; show on MOS/BSIM4/
OSDI/vsource is unchanged and does not crash.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d5228e2461
commit
10276f9936
|
|
@ -908,23 +908,49 @@ bogus2(dgen *dg, IFparm *p, int i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Free the vector that askInstanceQuest/askModelQuest allocates for an
|
||||||
|
* IF_VECTOR parameter (e.g. a source's pulse/pwl/ac coefficient list, TMALLOC'd
|
||||||
|
* in vsrcask.c). The show param printers query per element, so without this
|
||||||
|
* the vector is re-allocated and leaked on every call -- O(n^2) and, for the
|
||||||
|
* long coefficient lists of stimulus sources, tens of GB. */
|
||||||
|
static void
|
||||||
|
free_if_vec(IFparm *p, IFvalue *val)
|
||||||
|
{
|
||||||
|
if (!(p->dataType & IF_VECTOR))
|
||||||
|
return;
|
||||||
|
switch ((p->dataType & IF_VARTYPES) & ~IF_VECTOR) {
|
||||||
|
case IF_FLAG:
|
||||||
|
case IF_INTEGER: tfree(val->v.vec.iVec); break;
|
||||||
|
case IF_REAL: tfree(val->v.vec.rVec); break;
|
||||||
|
case IF_COMPLEX: tfree(val->v.vec.cVec); break;
|
||||||
|
case IF_STRING: tfree(val->v.vec.sVec); break;
|
||||||
|
case IF_INSTANCE: tfree(val->v.vec.uVec); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
printvals(dgen *dg, IFparm *p, int i)
|
printvals(dgen *dg, IFparm *p, int i)
|
||||||
{
|
{
|
||||||
IFvalue val;
|
IFvalue val;
|
||||||
int n;
|
int n, error;
|
||||||
|
|
||||||
|
memset(&val, 0, sizeof(val)); /* avoid garbage v.numValue -> runaway loop */
|
||||||
|
|
||||||
if (dg->flags & DGEN_INSTANCE)
|
if (dg->flags & DGEN_INSTANCE)
|
||||||
ft_sim->askInstanceQuest
|
error = ft_sim->askInstanceQuest
|
||||||
(ft_curckt->ci_ckt, dg->instance, p->id, &val, &val);
|
(ft_curckt->ci_ckt, dg->instance, p->id, &val, &val);
|
||||||
else
|
else
|
||||||
ft_sim->askModelQuest
|
error = ft_sim->askModelQuest
|
||||||
(ft_curckt->ci_ckt, dg->model, p->id, &val, &val);
|
(ft_curckt->ci_ckt, dg->model, p->id, &val, &val);
|
||||||
|
|
||||||
if (p->dataType & IF_VECTOR)
|
if ((p->dataType & IF_VECTOR) && !error)
|
||||||
n = val.v.numValue;
|
n = val.v.numValue;
|
||||||
else
|
else
|
||||||
n = 1;
|
n = 1;
|
||||||
|
if (n < 0)
|
||||||
|
n = 0;
|
||||||
|
|
||||||
if (((p->dataType & IF_VARTYPES) & ~IF_VECTOR) == IF_COMPLEX)
|
if (((p->dataType & IF_VARTYPES) & ~IF_VECTOR) == IF_COMPLEX)
|
||||||
n *= 2;
|
n *= 2;
|
||||||
|
|
@ -934,6 +960,7 @@ printvals(dgen *dg, IFparm *p, int i)
|
||||||
fprintf(cp_out, " -");
|
fprintf(cp_out, " -");
|
||||||
else
|
else
|
||||||
fprintf(cp_out, " ");
|
fprintf(cp_out, " ");
|
||||||
|
free_if_vec(p, &val);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -992,6 +1019,7 @@ printvals(dgen *dg, IFparm *p, int i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_if_vec(p, &val);
|
||||||
return n - 1;
|
return n - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1002,6 +1030,10 @@ printvals_old(dgen *dg, IFparm *p, int i)
|
||||||
IFvalue val;
|
IFvalue val;
|
||||||
int n, error;
|
int n, error;
|
||||||
|
|
||||||
|
/* zero val: askInstanceQuest may leave it untouched on error, and a
|
||||||
|
* garbage v.numValue would make the caller's element loop run "forever" */
|
||||||
|
memset(&val, 0, sizeof(val));
|
||||||
|
|
||||||
if (dg->flags & DGEN_INSTANCE)
|
if (dg->flags & DGEN_INSTANCE)
|
||||||
error = ft_sim->askInstanceQuest
|
error = ft_sim->askInstanceQuest
|
||||||
(ft_curckt->ci_ckt, dg->instance, p->id, &val, &val);
|
(ft_curckt->ci_ckt, dg->instance, p->id, &val, &val);
|
||||||
|
|
@ -1009,10 +1041,12 @@ printvals_old(dgen *dg, IFparm *p, int i)
|
||||||
error = ft_sim->askModelQuest
|
error = ft_sim->askModelQuest
|
||||||
(ft_curckt->ci_ckt, dg->model, p->id, &val, &val);
|
(ft_curckt->ci_ckt, dg->model, p->id, &val, &val);
|
||||||
|
|
||||||
if (p->dataType & IF_VECTOR)
|
if ((p->dataType & IF_VECTOR) && !error)
|
||||||
n = val.v.numValue;
|
n = val.v.numValue;
|
||||||
else
|
else
|
||||||
n = 1;
|
n = 1;
|
||||||
|
if (n < 0)
|
||||||
|
n = 0;
|
||||||
|
|
||||||
if (((p->dataType & IF_VARTYPES) & ~IF_VECTOR) == IF_COMPLEX)
|
if (((p->dataType & IF_VARTYPES) & ~IF_VECTOR) == IF_COMPLEX)
|
||||||
n *= 2;
|
n *= 2;
|
||||||
|
|
@ -1022,6 +1056,7 @@ printvals_old(dgen *dg, IFparm *p, int i)
|
||||||
fprintf(cp_out, " -");
|
fprintf(cp_out, " -");
|
||||||
else
|
else
|
||||||
fprintf(cp_out, " ");
|
fprintf(cp_out, " ");
|
||||||
|
free_if_vec(p, &val);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1082,6 +1117,7 @@ printvals_old(dgen *dg, IFparm *p, int i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_if_vec(p, &val);
|
||||||
return n - 1;
|
return n - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue