mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-23 14:37:42 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9148edde69 | ||
|
|
bb07a84ae1 | ||
|
|
d753e2c208 | ||
|
|
bd3b88de4a | ||
|
|
668aa38340 | ||
|
|
d99bffa74f | ||
|
|
7ce3b1dcd8 | ||
|
|
366821fe7f |
+26
-18
@@ -3337,18 +3337,11 @@ void PropertyOptimize(struct objlist *ob, struct nlist *tp)
|
||||
vlist = (struct valuelist ***)CALLOC(pcount, sizeof(struct valuelist **));
|
||||
if (m_rec == NULL)
|
||||
vlist[0] = (struct valuelist **)CALLOC(icount, sizeof(struct valuelist *));
|
||||
pcount = 1;
|
||||
|
||||
while (ptop != NULL) {
|
||||
if (ptop->prop == m_rec) {
|
||||
plist[0] = m_rec;
|
||||
vlist[0] = (struct valuelist **)CALLOC(icount,
|
||||
plist[ptop->prop->idx] = ptop->prop;
|
||||
vlist[ptop->prop->idx] = (struct valuelist **)CALLOC(icount,
|
||||
sizeof(struct valuelist *));
|
||||
}
|
||||
else {
|
||||
plist[pcount] = ptop->prop;
|
||||
vlist[pcount++] = (struct valuelist **)CALLOC(icount,
|
||||
sizeof(struct valuelist *));
|
||||
}
|
||||
plink = ptop;
|
||||
FREE(ptop);
|
||||
ptop = plink->next;
|
||||
@@ -3377,6 +3370,17 @@ void PropertyOptimize(struct objlist *ob, struct nlist *tp)
|
||||
i++;
|
||||
}
|
||||
|
||||
// Check for "M" records with type double and promote them to integer
|
||||
for (i = 0; i < icount; i++) {
|
||||
vl = vlist[0][i];
|
||||
if (vl != NULL) {
|
||||
if (vl->type == PROP_DOUBLE) {
|
||||
vl->type = PROP_INTEGER;
|
||||
vl->value.ival = (int)(vl->value.dval + 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now combine records with same properties by summing M.
|
||||
for (i = 0; i < icount - 1; i++) {
|
||||
for (j = 1; j < icount; j++) {
|
||||
@@ -3482,13 +3486,13 @@ void PropertyOptimize(struct objlist *ob, struct nlist *tp)
|
||||
vlist[0][j] = &nullvl; // Mark this position
|
||||
if (crit >= 0) {
|
||||
vl = vlist[crit][i];
|
||||
if (ctype == MERGE_ADD_CRIT) {
|
||||
if ((vl != NULL) && (ctype == MERGE_ADD_CRIT)) {
|
||||
if (vl->type == PROP_INTEGER)
|
||||
vl->value.ival += vlist[crit][j]->value.ival;
|
||||
else if (vl->type == PROP_DOUBLE)
|
||||
vl->value.dval += vlist[crit][j]->value.dval;
|
||||
}
|
||||
else { /* MERGE_PAR_CRIT */
|
||||
else if (vl != NULL) { /* MERGE_PAR_CRIT */
|
||||
if (vl->type == PROP_INTEGER) {
|
||||
double di = vl->value.ival;
|
||||
double dj = vlist[crit][j]->value.ival;
|
||||
@@ -3508,7 +3512,7 @@ void PropertyOptimize(struct objlist *ob, struct nlist *tp)
|
||||
else if (vlist[0][i]->value.ival > 0) {
|
||||
if (crit >= 0) {
|
||||
vl = vlist[crit][i];
|
||||
if (ctype == MERGE_ADD_CRIT) {
|
||||
if ((vl != NULL) && (ctype == MERGE_ADD_CRIT)) {
|
||||
if (vl->type == PROP_INTEGER)
|
||||
vl->value.ival += vlist[0][j]->value.ival *
|
||||
vlist[crit][j]->value.ival;
|
||||
@@ -3516,7 +3520,7 @@ void PropertyOptimize(struct objlist *ob, struct nlist *tp)
|
||||
vl->value.dval += (double)vlist[0][j]->value.ival *
|
||||
vlist[crit][j]->value.dval;
|
||||
}
|
||||
else { /* MERGE_PAR_CRIT */
|
||||
else if (vl != NULL) { /* MERGE_PAR_CRIT */
|
||||
if (vl->type == PROP_INTEGER) {
|
||||
double d = (double)vlist[crit][j]->value.ival /
|
||||
(double)vlist[0][j]->value.ival;
|
||||
@@ -4547,13 +4551,13 @@ int EquivalenceNodes(char *name1, int file1, char *name2, int file2)
|
||||
/* database. */
|
||||
/*------------------------------------------------------*/
|
||||
|
||||
int IgnoreClass(char *name, int file)
|
||||
int IgnoreClass(char *name, int file, unsigned char type)
|
||||
{
|
||||
struct IgnoreList *newIgnore;
|
||||
|
||||
if ((file == -1) && (Circuit1 != NULL) && (Circuit2 != NULL)) {
|
||||
IgnoreClass(name, Circuit1->file);
|
||||
IgnoreClass(name, Circuit2->file);
|
||||
IgnoreClass(name, Circuit1->file, type);
|
||||
IgnoreClass(name, Circuit2->file, type);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4563,9 +4567,13 @@ int IgnoreClass(char *name, int file)
|
||||
newIgnore->class = (char *)MALLOC(1 + strlen(name));
|
||||
strcpy(newIgnore->class, name);
|
||||
newIgnore->file = file;
|
||||
newIgnore->type = type;
|
||||
|
||||
/* Remove existing classes from database */
|
||||
ClassDelete(name, file);
|
||||
if (type == IGNORE_CLASS)
|
||||
ClassDelete(name, file);
|
||||
else
|
||||
RemoveShorted(name, file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ extern int PermuteForget(char *model, int filenum, char *pin1, char *pin2);
|
||||
extern int EquivalenceElements(char *name1, int file1, char *name2, int file2);
|
||||
extern int EquivalenceNodes(char *name1, int file1, char *name2, int file2);
|
||||
extern int EquivalenceClasses(char *name1, int file1, char *name2, int file2);
|
||||
extern int IgnoreClass(char *name, int file);
|
||||
extern int IgnoreClass(char *name, int file, unsigned char type);
|
||||
extern int MatchPins(struct nlist *tp1, struct nlist *tp2);
|
||||
|
||||
extern int CreateCompareQueue(char *, int, char *, int);
|
||||
|
||||
+23
-8
@@ -1212,6 +1212,10 @@ void CellDefNoCase(char *name, int file)
|
||||
CurrentCell->flags |= CELL_NOCASE;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Return 0 if class 'name' is not being ignored (per the 'ignore' */
|
||||
/* command); 1 if it is ignored, and 2 if shorted instances should be */
|
||||
/* ignored. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
int IsIgnored(char *name, int file)
|
||||
@@ -1223,7 +1227,7 @@ int IsIgnored(char *name, int file)
|
||||
{
|
||||
if ((file == -1) || (ilist->file == -1) || (file == ilist->file))
|
||||
if ((*matchfunc)(ilist->class, nptr))
|
||||
return 1;
|
||||
return ilist->type; /* IGNORE_CLASS or IGNORE_SHORTED */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1361,10 +1365,6 @@ void Instance(char *model, char *instancename)
|
||||
return;
|
||||
}
|
||||
fnum = CurrentCell->file;
|
||||
if (IsIgnored(model, fnum)) {
|
||||
Printf("Class '%s' instanced in input but is being ignored.\n", model);
|
||||
return;
|
||||
}
|
||||
instanced_cell = LookupCellFile(model, fnum);
|
||||
if (instanced_cell == NULL) {
|
||||
Printf("Attempt to instance undefined model '%s'\n", model);
|
||||
@@ -1504,7 +1504,7 @@ char *Cell(char *inststr, char *model, ...)
|
||||
struct objlist *namedporthead, *namedportp, *namedlisthead, *namedlistp;
|
||||
int portnum, portlist, done;
|
||||
char namedport[512]; /* tmp buffers */
|
||||
int filenum;
|
||||
int filenum, itype, samenode;
|
||||
|
||||
static char *instancename = NULL;
|
||||
char *instnameptr;
|
||||
@@ -1517,7 +1517,7 @@ char *Cell(char *inststr, char *model, ...)
|
||||
filenum = CurrentCell->file;
|
||||
|
||||
if (Debug) Printf(" calling cell: %s\n",model);
|
||||
if (IsIgnored(model, filenum)) {
|
||||
if ((itype = IsIgnored(model, filenum)) == IGNORE_CLASS) {
|
||||
Printf("Class '%s' instanced in input but is being ignored.\n", model);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1600,6 +1600,21 @@ char *Cell(char *inststr, char *model, ...)
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
/* Check for shorted pins */
|
||||
if ((itype == IGNORE_SHORTED) && (head != NULL)) {
|
||||
unsigned char shorted = (unsigned char)1;
|
||||
for (tp = head->next; tp; tp = tp->next) {
|
||||
if (strcasecmp(head->name, tp->name))
|
||||
shorted = (unsigned char)0;
|
||||
break;
|
||||
}
|
||||
if (shorted == (unsigned char)1) {
|
||||
Printf("Instance of '%s' is shorted, ignoring.\n", model);
|
||||
FreeObject(head);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (inststr == NULL) {
|
||||
if (instancename != NULL)
|
||||
FreeString(instancename);
|
||||
@@ -1992,7 +2007,7 @@ struct objlist *LinkProperties(char *model, struct keyvalue *topptr)
|
||||
else
|
||||
filenum = CurrentCell->file;
|
||||
|
||||
if (IsIgnored(model, filenum)) {
|
||||
if (IsIgnored(model, filenum) == IGNORE_CLASS) {
|
||||
Printf("Class '%s' instanced in input but is being ignored.\n", model);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+66
-1
@@ -340,6 +340,71 @@ void CellRehash(char *name, char *newname, int file)
|
||||
|
||||
struct nlist *OldCell;
|
||||
|
||||
int removeshorted(struct hashlist *p, int file)
|
||||
{
|
||||
struct nlist *ptr;
|
||||
struct objlist *ob, *lob, *nob, *tob;
|
||||
unsigned char shorted;
|
||||
|
||||
ptr = (struct nlist *)(p->ptr);
|
||||
|
||||
if ((file != -1) && (ptr->file != file)) return;
|
||||
|
||||
lob = NULL;
|
||||
for (ob = ptr->cell; ob != NULL;) {
|
||||
nob = ob->next;
|
||||
if ((ob->type == FIRSTPIN) && (ob->model.class != NULL)) {
|
||||
if ((*matchfunc)(ob->model.class, OldCell->name)) {
|
||||
shorted = (unsigned char)1;
|
||||
for (tob = nob; tob->type > FIRSTPIN; tob = tob->next) {
|
||||
if (tob->node != ob->node) {
|
||||
shorted = (unsigned char)0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shorted == (unsigned char)0) {
|
||||
lob = ob;
|
||||
ob = nob;
|
||||
continue;
|
||||
}
|
||||
HashDelete(ob->instance.name, &(ptr->instdict));
|
||||
while (1) {
|
||||
FreeObjectAndHash(ob, ptr);
|
||||
ob = nob;
|
||||
if (ob == NULL) break;
|
||||
nob = ob->next;
|
||||
if (ob->type != PROPERTY && ob->type <= FIRSTPIN) break;
|
||||
}
|
||||
if (lob == NULL)
|
||||
ptr->cell = ob;
|
||||
else
|
||||
lob->next = ob;
|
||||
}
|
||||
else {
|
||||
lob = ob;
|
||||
ob = nob;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lob = ob;
|
||||
ob = nob;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove shorted instances of class "class" from the database */
|
||||
|
||||
void RemoveShorted(char *class, int file)
|
||||
{
|
||||
if (file == -1)
|
||||
OldCell = LookupCell(class);
|
||||
else
|
||||
OldCell = LookupCellFile(class, file);
|
||||
|
||||
if (OldCell == NULL) return;
|
||||
RecurseCellFileHashTable(removeshorted, file);
|
||||
}
|
||||
|
||||
int deleteclass(struct hashlist *p, int file)
|
||||
{
|
||||
struct nlist *ptr;
|
||||
@@ -360,7 +425,7 @@ int deleteclass(struct hashlist *p, int file)
|
||||
ob = nob;
|
||||
if (ob == NULL) break;
|
||||
nob = ob->next;
|
||||
if (ob->type <= FIRSTPIN) break;
|
||||
if (ob->type != PROPERTY && ob->type <= FIRSTPIN) break;
|
||||
}
|
||||
if (lob == NULL)
|
||||
ptr->cell = ob;
|
||||
|
||||
@@ -159,9 +159,16 @@ extern struct objlist *LastPlaced;
|
||||
struct IgnoreList {
|
||||
char *class;
|
||||
int file;
|
||||
unsigned char type;
|
||||
struct IgnoreList *next;
|
||||
};
|
||||
|
||||
/* Types used by IgnoreList above */
|
||||
|
||||
#define IGNORE_NONE (unsigned char)0
|
||||
#define IGNORE_CLASS (unsigned char)1
|
||||
#define IGNORE_SHORTED (unsigned char)2
|
||||
|
||||
/* Record structure for handling pin permutations in a cell */
|
||||
/* Linked list structure allows multiple permutations per cell. */
|
||||
|
||||
|
||||
+53
-8
@@ -42,6 +42,20 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
// Global storage for parameters from .PARAM
|
||||
struct hashdict spiceparams;
|
||||
|
||||
// Check if a token represents a numerical value (with
|
||||
// units) or an expression. This is basically a hack
|
||||
// to see if it either passes StringIsValue() or is
|
||||
// enclosed in braces. Probably should attempt to
|
||||
// parse the expression, to be pedantic. Not sure all
|
||||
// expressions have to be in braces.
|
||||
|
||||
int StringIsValueOrExpression(char *token)
|
||||
{
|
||||
if (StringIsValue(token)) return TRUE;
|
||||
else if (*token == '{') return TRUE;
|
||||
else return FALSE;
|
||||
}
|
||||
|
||||
void SpiceSubCell(struct nlist *tp, int IsSubCell)
|
||||
{
|
||||
struct objlist *ob;
|
||||
@@ -956,7 +970,7 @@ skip_ends:
|
||||
|
||||
/* Get capacitor value (if present), save as property "value" */
|
||||
if (nexttok != NULL) {
|
||||
if (StringIsValue(nexttok)) {
|
||||
if (StringIsValueOrExpression(nexttok)) {
|
||||
AddProperty(&kvlist, "value", nexttok);
|
||||
SpiceTokNoNewline();
|
||||
}
|
||||
@@ -984,7 +998,7 @@ skip_ends:
|
||||
if ((eqptr = strchr(model, ']')) != NULL)
|
||||
*eqptr = '\0';
|
||||
}
|
||||
else if (StringIsValue(nexttok)) {
|
||||
else if (StringIsValueOrExpression(nexttok)) {
|
||||
// Suport for value passed to modeled capacitor
|
||||
AddProperty(&kvlist, "value", nexttok);
|
||||
}
|
||||
@@ -1050,7 +1064,7 @@ skip_ends:
|
||||
/* Get resistor value (if present); save as property "value" */
|
||||
|
||||
if (nexttok != NULL) {
|
||||
if (StringIsValue(nexttok)) {
|
||||
if (StringIsValueOrExpression(nexttok)) {
|
||||
AddProperty(&kvlist, "value", nexttok);
|
||||
SpiceTokNoNewline();
|
||||
}
|
||||
@@ -1077,7 +1091,7 @@ skip_ends:
|
||||
if ((eqptr = strchr(model, ']')) != NULL)
|
||||
*eqptr = '\0';
|
||||
}
|
||||
else if (StringIsValue(nexttok)) {
|
||||
else if (StringIsValueOrExpression(nexttok)) {
|
||||
// Suport for value passed to modeled resistor
|
||||
AddProperty(&kvlist, "value", nexttok);
|
||||
}
|
||||
@@ -1277,7 +1291,7 @@ skip_ends:
|
||||
/* Get inductance value (if present); save as property "value" */
|
||||
|
||||
if (nexttok != NULL) {
|
||||
if (StringIsValue(nexttok)) {
|
||||
if (StringIsValueOrExpression(nexttok)) {
|
||||
AddProperty(&kvlist, "value", nexttok);
|
||||
SpiceTokNoNewline();
|
||||
}
|
||||
@@ -1368,7 +1382,7 @@ skip_ends:
|
||||
*eqptr = '\0';
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
else if (StringIsValue(nexttok)) {
|
||||
else if (StringIsValueOrExpression(nexttok)) {
|
||||
AddProperty(&kvlist, "value", nexttok);
|
||||
SpiceTokNoNewline();
|
||||
}
|
||||
@@ -1422,7 +1436,7 @@ skip_ends:
|
||||
*eqptr = '\0';
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
else if (StringIsValue(nexttok)) {
|
||||
else if (StringIsValueOrExpression(nexttok)) {
|
||||
AddProperty(&kvlist, "value", nexttok);
|
||||
SpiceTokNoNewline();
|
||||
}
|
||||
@@ -1485,7 +1499,7 @@ skip_ends:
|
||||
*eqptr = '\0';
|
||||
AddProperty(&kvlist, nexttok, eqptr + 1);
|
||||
}
|
||||
else if (StringIsValue(nexttok)) {
|
||||
else if (StringIsValueOrExpression(nexttok)) {
|
||||
AddProperty(&kvlist, "value", nexttok);
|
||||
SpiceTokNoNewline();
|
||||
}
|
||||
@@ -1516,6 +1530,8 @@ skip_ends:
|
||||
|
||||
else if (toupper(nexttok[0]) == 'X') { /* subcircuit instances */
|
||||
char instancename[100], subcktname[100];
|
||||
int itype;
|
||||
|
||||
instancename[99] = '\0';
|
||||
subcktname[99] = '\0';
|
||||
|
||||
@@ -1588,6 +1604,34 @@ skip_ends:
|
||||
if (scan->next != NULL) scan = scan->next;
|
||||
tail->next = NULL;
|
||||
|
||||
/* Check for ignored class */
|
||||
|
||||
if ((itype = IsIgnored(subcktname, filenum)) == IGNORE_CLASS) {
|
||||
Printf("Class '%s' instanced in input but is being ignored.\n", model);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for shorted pins */
|
||||
|
||||
if ((itype == IGNORE_SHORTED) && (head != NULL)) {
|
||||
unsigned char shorted = (unsigned char)1;
|
||||
struct portelement *p;
|
||||
for (p = head->next; p; p = p->next) {
|
||||
if (strcasecmp(head->name, p->name))
|
||||
shorted = (unsigned char)0;
|
||||
break;
|
||||
}
|
||||
if (shorted == (unsigned char)1) {
|
||||
Printf("Instance of '%s' is shorted, ignoring.\n", subcktname);
|
||||
while (head) {
|
||||
p = head->next;
|
||||
FREE(head);
|
||||
head = p;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create cell name and revise instance name based on the cell name */
|
||||
/* For clarity, if "instancename" does not contain the cellname, */
|
||||
/* then prepend the cellname to the instance name. HOWEVER, if any */
|
||||
@@ -1644,6 +1688,7 @@ skip_ends:
|
||||
}
|
||||
|
||||
/* nexttok is now NULL, scan->name points to class */
|
||||
|
||||
Instance(subcktname, instancename);
|
||||
pobj = LinkProperties(subcktname, kvlist);
|
||||
ReduceExpressions(pobj, NULL, CurrentCell, TRUE);
|
||||
|
||||
+10
-3
@@ -2518,10 +2518,10 @@ _netcmp_ignore(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||
{
|
||||
char *options[] = {
|
||||
"class", NULL
|
||||
"class", "shorted", NULL
|
||||
};
|
||||
enum OptionIdx {
|
||||
CLASS_IDX
|
||||
CLASS_IDX, SHORTED_IDX
|
||||
};
|
||||
int result, index;
|
||||
int file = -1;
|
||||
@@ -2542,7 +2542,14 @@ _netcmp_ignore(ClientData clientData,
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "[class] valid_cellname");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
IgnoreClass(name, file);
|
||||
switch (index) {
|
||||
case CLASS_IDX:
|
||||
IgnoreClass(name, file, IGNORE_CLASS);
|
||||
break;
|
||||
case SHORTED_IDX:
|
||||
IgnoreClass(name, file, IGNORE_SHORTED);
|
||||
break;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user