Merge branch 'pre-master-46' into bt_dev
This commit is contained in:
commit
a75ecd77dc
|
|
@ -530,7 +530,9 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
|
|||
char *dir_name = ngdirname(filename ? filename : ".");
|
||||
|
||||
startTime = seconds();
|
||||
/* inp_source() called with fp: load from file, */
|
||||
/* Parsing the circuit 2.
|
||||
This is the next major step:
|
||||
inp_source() called with fp: load circuit netlist from file, */
|
||||
/* called with *fp == NULL and intfile: we want to load circuit from circarray */
|
||||
if (fp || intfile) {
|
||||
deck = inp_readall(fp, dir_name, filename, comfile, intfile, &expr_w_temper);
|
||||
|
|
@ -931,7 +933,9 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
|
|||
}
|
||||
}
|
||||
|
||||
/* Now expand subcircuit macros and substitute numparams.*/
|
||||
/* Parsing the circuit 4.
|
||||
This is the next major step:
|
||||
Expand subcircuit macros and substitute numparams.*/
|
||||
if (!cp_getvar("nosubckt", CP_BOOL, NULL, 0))
|
||||
if ((deck->nextcard = inp_subcktexpand(deck->nextcard)) == NULL) {
|
||||
line_free(realdeck, TRUE);
|
||||
|
|
@ -985,8 +989,11 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
|
|||
continue;
|
||||
/* Only truncated .model lines */
|
||||
if (ciprefix(".model", tc->line)) {
|
||||
fprintf(fdo, "%6d %.100s ...\n",
|
||||
fprintf(fdo, "%6d %.100s ",
|
||||
tc->linenum, tc->line);
|
||||
if (strlen(tc->line) > 100)
|
||||
fprintf(fdo, " ... (truncated)");
|
||||
fprintf(fdo, "\n");
|
||||
}
|
||||
else {
|
||||
fprintf(fdo, "%6d %s\n",
|
||||
|
|
@ -1084,7 +1091,9 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
|
|||
if (newcompat.hs || newcompat.spe)
|
||||
rem_unused_mos_models(deck->nextcard);
|
||||
#endif
|
||||
/* now load deck into ft_curckt -- the current circuit. */
|
||||
/* Parsing the circuit 5.
|
||||
This is the next major step:
|
||||
load deck into ft_curckt -- the current circuit. */
|
||||
if(inp_dodeck(deck, tt, wl_first, FALSE, options, filename) != 0)
|
||||
return 1;
|
||||
|
||||
|
|
@ -1411,6 +1420,10 @@ inp_dodeck(
|
|||
*---------------------------------------------------*/
|
||||
if (!noparse) {
|
||||
startTime = seconds();
|
||||
/* Parsing the circuit 6.
|
||||
This is the next major step:
|
||||
Input a single deck, and return a pointer to the circuit.
|
||||
Parse all models and instances */
|
||||
ckt = if_inpdeck(deck, &tab);
|
||||
ft_curckt->FTEstats->FTESTATnetParseTime = seconds() - startTime;
|
||||
/* if .probe, rename the current measurement node vcurr_ */
|
||||
|
|
|
|||
|
|
@ -1054,6 +1054,10 @@ struct card *inp_readall(FILE *fp, const char *dir_name, const char* file_name,
|
|||
/* set the members of the compatibility structure */
|
||||
set_compat_mode();
|
||||
|
||||
/* Parsing the circuit 3.
|
||||
This is the next major step:
|
||||
Reading the netlist line by line, handle .include and .lib,
|
||||
line continuation and upper/lower casing */
|
||||
rv = inp_read(fp, 0, dir_name, file_name, comfile, intfile);
|
||||
cc = rv.cc;
|
||||
|
||||
|
|
@ -1241,8 +1245,11 @@ struct card *inp_readall(FILE *fp, const char *dir_name, const char* file_name,
|
|||
continue;
|
||||
/* Only truncated .model lines */
|
||||
if (ciprefix(".model", t->line)) {
|
||||
fprintf(fd, "%6d %.100s ...\n",
|
||||
fprintf(fd, "%6d %.100s ",
|
||||
t->linenum, t->line);
|
||||
if (strlen(t->line) > 100)
|
||||
fprintf(fd, " ... (truncated)");
|
||||
fprintf(fd, "\n");
|
||||
}
|
||||
else {
|
||||
fprintf(fd, "%6d %s\n",
|
||||
|
|
@ -1602,11 +1609,8 @@ static struct inp_read_t inp_read(FILE* fp, int call_depth, const char* dir_name
|
|||
char* tmpstr = copy(nexttok(buffer));
|
||||
wl_append_word(&sourceinfo, &sourceinfo, tmpstr);
|
||||
|
||||
/* Add source of netlist data, for use in verbose error messages.
|
||||
Set the compatibility mode flag to 1, if pslt is read. */
|
||||
/* Set the compatibility mode flag to 1, if pslt is read. */
|
||||
for (tmpcard = newcard; tmpcard; tmpcard = tmpcard->nextcard) {
|
||||
/* skip *include */
|
||||
tmpcard->linesource = tmpstr;
|
||||
if (compset)
|
||||
tmpcard->compmod = 1;
|
||||
else
|
||||
|
|
@ -9038,7 +9042,7 @@ static void inp_check_syntax(struct card *deck)
|
|||
acline = nexttok(acline);
|
||||
if (!acline) {
|
||||
fprintf(stderr, "Error in line %s\n", cut_line);
|
||||
fprintf(stderr, " Not enough parameters\n");
|
||||
fprintf(stderr, " Not enough parameters for %c source\n", *cut_line);
|
||||
fprintf(stderr,
|
||||
" line no. %d from file %s\n",
|
||||
card->linenum_orig, card->linesource);
|
||||
|
|
|
|||
|
|
@ -339,9 +339,9 @@ printres(char *name)
|
|||
ft_curckt->ci_ckt->CKTstat->devTimes[i]/(double)(ft_curckt->ci_ckt->CKTstat->devCounts[i])
|
||||
);
|
||||
}
|
||||
yy = TRUE;
|
||||
}
|
||||
yy = TRUE;
|
||||
|
||||
|
||||
#ifdef CIDER
|
||||
/* begin cider integration */
|
||||
if (!name || eq(name, "circuit") || eq(name, "task"))
|
||||
|
|
|
|||
|
|
@ -93,8 +93,9 @@ static int finddev(CKTcircuit *ckt, char *name, GENinstance **devptr, GENmodel *
|
|||
/* espice fix integration */
|
||||
static int finddev_special(CKTcircuit *ckt, char *name, GENinstance **devptr, GENmodel **modptr, int *device_or_model);
|
||||
|
||||
/* Input a single deck, and return a pointer to the circuit. */
|
||||
|
||||
/* Input a single deck, and return a pointer to the circuit.
|
||||
Parse all models in function INPpas1, instances (devices) in INPpas2,
|
||||
consider initial conditions (INPpas3), and shunt capacitors (INPpas4). */
|
||||
CKTcircuit *
|
||||
if_inpdeck(struct card *deck, INPtables **tab)
|
||||
{
|
||||
|
|
@ -162,16 +163,23 @@ if_inpdeck(struct card *deck, INPtables **tab)
|
|||
|
||||
ft_curckt->ci_curTask = ft_curckt->ci_defTask;
|
||||
|
||||
/* Parse the .model lines. Enter the model into the global model table modtab. */
|
||||
modtab = NULL;
|
||||
modtabhash = NULL;
|
||||
/* Parse .model lines, put them into 'tab' */
|
||||
/* Parsing the circuit 7.
|
||||
This is the next major step:
|
||||
Parse the .model lines.
|
||||
Enter the model into the global model table modtab
|
||||
and into the corresponding hash table modtabhash.
|
||||
The role of 'tab' is unclear (not used any more?). */
|
||||
INPpas1(ckt, deck->nextcard, *tab);
|
||||
/* store the new model table in the current circuit */
|
||||
/* store the new model tables in the current circuit */
|
||||
ft_curckt->ci_modtab = modtab;
|
||||
ft_curckt->ci_modtabhash = modtabhash;
|
||||
|
||||
/* Scan through the instance lines and parse the circuit. */
|
||||
/* Parsing the circuit 8.
|
||||
This is the next major step:
|
||||
Scan through the instance lines and parse the circuit.
|
||||
Set up the circuit matrix. */
|
||||
INPpas2(ckt, deck->nextcard, *tab, ft_curckt->ci_defTask);
|
||||
#ifdef XSPICE
|
||||
if (!Evtcheck_nodes(ckt, *tab)) {
|
||||
|
|
|
|||
|
|
@ -97,11 +97,10 @@ struct bxx_buffer;
|
|||
static void finishLine(struct bxx_buffer *dst, char *src, char *scname);
|
||||
static int settrans(char *formal, int flen, char *actual, const char *subname);
|
||||
static char *gettrans(const char *name, const char *name_end, bool *isglobal);
|
||||
static int numnodes(const char *line, struct subs *subs, wordlist const *modnames);
|
||||
static int numnodes(const char *line);
|
||||
static int numdevs(char *s);
|
||||
static wordlist *modtranslate(struct card *deck, char *subname, wordlist *new_modnames);
|
||||
static void devmodtranslate(struct card *deck, char *subname, wordlist * const orig_modnames);
|
||||
static int inp_numnodes(char c);
|
||||
|
||||
/* hash table to store the global nodes
|
||||
* For now its use is limited to avoid double entries in global_nodes[] */
|
||||
|
|
@ -1384,9 +1383,11 @@ translate(struct card *deck, char *formal, int flen, char *actual, char *scname,
|
|||
tfree(name);
|
||||
bxx_putc(&buffer, ' ');
|
||||
|
||||
/* Next iterate over all nodes (netnames) found and translate them. */
|
||||
nnodes = numnodes(c->line, subs, modnames);
|
||||
/* Next iterate over all nodes (netnames) found and translate them.
|
||||
* Ignore controlling nodes as they get special treatment for POLY.
|
||||
*/
|
||||
|
||||
nnodes = numnodes(c->line);
|
||||
while (--nnodes >= 0) {
|
||||
name = gettok_node(&s);
|
||||
if (name == NULL) {
|
||||
|
|
@ -1476,13 +1477,7 @@ translate(struct card *deck, char *formal, int flen, char *actual, char *scname,
|
|||
tfree(name);
|
||||
bxx_putc(&buffer, ' ');
|
||||
|
||||
/* FIXME anothet hack: if no models found for m devices, set number of nodes to 4 */
|
||||
if (!modnames && *(c->line) == 'm')
|
||||
nnodes = get_number_terminals(c->line);
|
||||
else if (*(c->line) == 'n')
|
||||
nnodes = get_number_terminals(c->line);
|
||||
else
|
||||
nnodes = numnodes(c->line, subs, modnames);
|
||||
nnodes = numnodes(c->line);
|
||||
while (--nnodes >= 0) {
|
||||
name = gettok_node(&s);
|
||||
if (name == NULL) {
|
||||
|
|
@ -1692,91 +1687,23 @@ gettrans(const char *name, const char *name_end, bool *isglobal)
|
|||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/*-------------------------------------------------------------------*/
|
||||
/* Control nodes for E and G sources are not counted as they vary in
|
||||
* the case of POLY. The count returned by get_number_terminals() includes
|
||||
* devices for K (mutual inductors) and W (current-controlled switch).
|
||||
*/
|
||||
|
||||
static int
|
||||
numnodes(const char *line, struct subs *subs, wordlist const *modnames)
|
||||
numnodes(const char *line)
|
||||
{
|
||||
/* gtri - comment - wbk - 10/23/90 - Do not modify this routine for */
|
||||
/* 'A' type devices since the callers will not know how to find the */
|
||||
/* nodes even if they know how many there are. Modify the callers */
|
||||
/* instead. */
|
||||
/* gtri - end - wbk - 10/23/90 */
|
||||
char c;
|
||||
int n;
|
||||
|
||||
line = skip_ws(line);
|
||||
|
||||
c = tolower_c(*line);
|
||||
|
||||
if (c == 'x') { /* Handle this ourselves. */
|
||||
const char *xname_e = skip_back_ws(strchr(line, '\0'), line);
|
||||
const char *xname = skip_back_non_ws(xname_e, line);
|
||||
for (; subs; subs = subs->su_next)
|
||||
if (eq_substr(xname, xname_e, subs->su_name))
|
||||
return subs->su_numargs;
|
||||
/*
|
||||
* number of nodes not known so far.
|
||||
* lets count the nodes ourselves,
|
||||
* assuming `buf' looks like this:
|
||||
* xname n1 n2 ... nn subname
|
||||
*/
|
||||
{
|
||||
int nodes = -2;
|
||||
while (*line) {
|
||||
nodes++;
|
||||
line = skip_ws(skip_non_ws(line));
|
||||
}
|
||||
return (nodes);
|
||||
}
|
||||
}
|
||||
/* if we use option skywaterpdk, MOS has four nodes. Required if number of devices is large */
|
||||
if (ft_skywaterpdk && c == 'm')
|
||||
return 4;
|
||||
|
||||
n = inp_numnodes(c);
|
||||
|
||||
/* Added this code for variable number of nodes on certain devices. */
|
||||
/* The consequence of this code is that the value returned by the */
|
||||
/* inp_numnodes(c) call must be regarded as "maximum number of nodes */
|
||||
/* for a given device type. */
|
||||
/* Paolo Nenzi Jan-2001 */
|
||||
|
||||
/* If model names equal node names, this code will fail! */
|
||||
if ((c == 'm') || (c == 'p') || (c == 'q') || (c == 'd')) { /* IF this is a mos, cpl, bjt or diode */
|
||||
char *s = nexttok(line); /* Skip the instance name */
|
||||
int gotit = 0;
|
||||
int i = 0;
|
||||
|
||||
while ((i <= n) && (*s) && !gotit) {
|
||||
char *t = gettok_node(&s); /* get nodenames . . . */
|
||||
const wordlist *wl;
|
||||
for (wl = modnames; wl; wl = wl->wl_next)
|
||||
if (model_name_match(t, wl->wl_word)) {
|
||||
gotit = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
tfree(t);
|
||||
}
|
||||
|
||||
/* Note: node checks must be done on #_of_node-1 because the */
|
||||
/* "while" cycle increments the counter even when a model is */
|
||||
/* recognized. This code may be better! */
|
||||
|
||||
if ((i < 4) && ((c == 'm') || (c == 'q'))) {
|
||||
fprintf(cp_err, "Error: too few nodes for MOS or BJT: %s\n", line);
|
||||
return (0);
|
||||
}
|
||||
if ((i < 5) && (c == 'p')) {
|
||||
fprintf(cp_err, "Error: too few nodes for CPL: %s\n", line);
|
||||
return (0);
|
||||
}
|
||||
return (i-1); /* compensate the unnecessary increment in the while cycle */
|
||||
} else {
|
||||
/* for all other elements */
|
||||
return (n);
|
||||
switch (*line) {
|
||||
case 'e':
|
||||
case 'g':
|
||||
case 'w':
|
||||
return 2;
|
||||
case 'k':
|
||||
return 0;
|
||||
}
|
||||
return get_number_terminals((char *)line);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2286,78 +2213,3 @@ devmodtranslate(struct card *s, char *subname, wordlist * const orig_modnames)
|
|||
|
||||
bxx_free(&buffer);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* inp_numnodes returns the maximum number of nodes (netnames) attached
|
||||
* to the component.
|
||||
* This is a spice-dependent thing. It should probably go somewhere
|
||||
* else, but... Note that we pretend that dependent sources and mutual
|
||||
* inductors have more nodes than they really do...
|
||||
*----------------------------------------------------------------------*/
|
||||
static int
|
||||
inp_numnodes(char c)
|
||||
{
|
||||
if (isupper_c(c))
|
||||
c = tolower_c(c);
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '.':
|
||||
case 'x':
|
||||
case '*':
|
||||
case '$':
|
||||
return (0);
|
||||
|
||||
case 'b':
|
||||
return (2);
|
||||
case 'c':
|
||||
return (2);
|
||||
case 'd':
|
||||
return (3);
|
||||
case 'e':
|
||||
return (2); /* changed from 4 to 2 by SDB on 4.22.2003 to enable POLY */
|
||||
case 'f':
|
||||
return (2);
|
||||
case 'g':
|
||||
return (2); /* changed from 4 to 2 by SDB on 4.22.2003 to enable POLY */
|
||||
case 'h':
|
||||
return (2);
|
||||
case 'i':
|
||||
return (2);
|
||||
case 'j':
|
||||
return (3);
|
||||
case 'k':
|
||||
return (0);
|
||||
case 'l':
|
||||
return (2);
|
||||
case 'm':
|
||||
return (7); /* This means that 7 is the maximun number of nodes */
|
||||
case 'o':
|
||||
return (4);
|
||||
case 'p':
|
||||
return (18);/* 16 lines + 2 gnd is the maximum number of nodes for CPL */
|
||||
case 'q':
|
||||
return (5);
|
||||
case 'r':
|
||||
return (2);
|
||||
case 's':
|
||||
return (4);
|
||||
case 't':
|
||||
return (4);
|
||||
case 'u':
|
||||
return (3);
|
||||
case 'v':
|
||||
return (2);
|
||||
case 'w':
|
||||
return (2); /* change 3 to 2 here to fix w bug, NCF 1/31/95 */
|
||||
case 'y':
|
||||
return (4);
|
||||
case 'z':
|
||||
return (3);
|
||||
|
||||
default:
|
||||
fprintf(cp_err, "Warning: unknown device type: %c\n", c);
|
||||
return (2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1490,7 +1490,10 @@ int main(int argc, char **argv)
|
|||
gotone = FALSE; // Re-use
|
||||
|
||||
if (tempfile && (!err || !ft_batchmode)) {
|
||||
/* Copy the input file name for becoming another file search path */
|
||||
/* Parsing the circuit 1.
|
||||
This is the next major step:
|
||||
Source the input file, then parse the data and create the circuit.
|
||||
Copy the input file name for becoming another file search path */
|
||||
if (inp_spsource(tempfile, FALSE, dname, FALSE) != 0) {
|
||||
fprintf(stderr, " Simulation interrupted due to error!\n\n");
|
||||
if (ft_stricterror || (oflag && !cp_getvar("interactive", CP_BOOL, NULL, 0)))
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@ Author: 1985 Thomas L. Quarles
|
|||
#include "inppas1.h"
|
||||
|
||||
/*
|
||||
* The first pass of the circuit parser just looks for '.model' lines
|
||||
*/
|
||||
|
||||
The first pass of the circuit parser just looks for '.model' lines,
|
||||
and sticks model into model table tab. */
|
||||
void INPpas1(CKTcircuit *ckt, struct card *deck, INPtables * tab)
|
||||
{
|
||||
struct card *current;
|
||||
|
|
|
|||
|
|
@ -1340,7 +1340,9 @@ wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR
|
|||
/* Wait until everything is settled */
|
||||
WaitForIdle();
|
||||
|
||||
/* Go to main() */
|
||||
/* Parsing the command line.
|
||||
This is the next major step:
|
||||
Go to main() for reading the start command line and preparing the simulator. */
|
||||
nReturnCode = xmain(argc, argv);
|
||||
|
||||
THE_END:
|
||||
|
|
|
|||
|
|
@ -124,6 +124,9 @@ ENHtranslate_poly(
|
|||
l1->linenum = d->linenum;
|
||||
l2->linenum = d->linenum;
|
||||
|
||||
l1->linesource = copy("internal");
|
||||
l2->linesource = copy("internal");
|
||||
|
||||
/* Create the translated cards */
|
||||
d->error = two2three_translate(d->line, &(l1->line), &(l2->line));
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ AUTHORS
|
|||
|
||||
Pwl with time input and smoothing: pwlts
|
||||
9 Sep 2022 Holger Vogt
|
||||
10 Oct 2025 Holger Vogt
|
||||
|
||||
SUMMARY
|
||||
|
||||
|
|
@ -211,6 +212,46 @@ void cm_pwlts(ARGS) /* structure holding parms,
|
|||
y[0] = 2. * y[1] - y[2];
|
||||
y[size - 1] = 2. * y[size - 2] - y[size - 3];
|
||||
}
|
||||
|
||||
/* See if input_domain is absolute...if so, test against */
|
||||
/* breakpoint segments for violation of 50% rule... */
|
||||
if (PARAM(fraction) == MIF_FALSE) {
|
||||
if ( 3 < size ) {
|
||||
for (i=1; i<(size-2); i++) {
|
||||
/* Test for overlap...0.999999999 factor is to */
|
||||
/* prevent floating point problems with comparison. */
|
||||
if ( (test1 = x[i+1] - x[i]) <
|
||||
(test2 = 0.999999999 * (2.0 * input_domain)) ) {
|
||||
cm_message_send(limit_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add permanent breakpoints */
|
||||
if (PARAM(fraction) == MIF_FALSE) {
|
||||
for (i=1; i<size-1; i++) {
|
||||
if (x[i] - input_domain <= 0)
|
||||
continue;
|
||||
cm_analog_set_perm_bkpt(x[i] - input_domain);
|
||||
cm_analog_set_perm_bkpt(x[i]);
|
||||
cm_analog_set_perm_bkpt(x[i] + input_domain);
|
||||
}
|
||||
}
|
||||
else {
|
||||
double dtlo, dthi, dt;
|
||||
for (i=1; i<size-1; i++) {
|
||||
dtlo = x[i] - x[i-1];
|
||||
dthi = x[i+1] - x[i];
|
||||
dt = ((dtlo >= dthi) ? dthi : dtlo) * input_domain;
|
||||
if (x[i] - dt <= 0)
|
||||
continue;
|
||||
cm_analog_set_perm_bkpt(x[i] - dt);
|
||||
cm_analog_set_perm_bkpt(x[i]);
|
||||
cm_analog_set_perm_bkpt(x[i] + dt);
|
||||
}
|
||||
}
|
||||
|
||||
/* debug printout
|
||||
for (i = 0; i < size; i++)
|
||||
fprintf(stderr, "%e ", y[i]);
|
||||
|
|
@ -229,22 +270,6 @@ void cm_pwlts(ARGS) /* structure holding parms,
|
|||
|
||||
}
|
||||
|
||||
/* See if input_domain is absolute...if so, test against */
|
||||
/* breakpoint segments for violation of 50% rule... */
|
||||
if (PARAM(fraction) == MIF_FALSE) {
|
||||
if ( 3 < size ) {
|
||||
for (i=1; i<(size-2); i++) {
|
||||
/* Test for overlap...0.999999999 factor is to */
|
||||
/* prevent floating point problems with comparison. */
|
||||
if ( (test1 = x[i+1] - x[i]) <
|
||||
(test2 = 0.999999999 * (2.0 * input_domain)) ) {
|
||||
cm_message_send(limit_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Retrieve x_input value as current simulation time. */
|
||||
x_input = TIME;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue