mirror of
https://github.com/RTimothyEdwards/netgen.git
synced 2026-08-22 22:17:22 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1322dbaf6 | ||
|
|
661157e041 | ||
|
|
77e5d70626 | ||
|
|
4098b7d5fd | ||
|
|
f860244700 | ||
|
|
66015511cb | ||
|
|
b3277ca53e | ||
|
|
00c2e74524 | ||
|
|
bdb8917327 | ||
|
|
95bce5dbd6 | ||
|
|
e15620257c | ||
|
|
7a947ee9be | ||
|
|
b5f188de42 | ||
|
|
ccbb286cf3 | ||
|
|
4809c02f79 | ||
|
|
af3982766e | ||
|
|
25c1f13e16 | ||
|
|
f0eec657a3 | ||
|
|
9d476bc25a | ||
|
|
5ed3fcb3f1 | ||
|
|
ab9659af17 |
+149
-22
@@ -3780,12 +3780,14 @@ void serial_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
|
||||
if (vl->key == NULL) continue;
|
||||
if (!strcmp(vl->key, "S"))
|
||||
sval = vl->value.ival;
|
||||
kl = (struct property *)HashLookup(vl->key, &(tp1->propdict));
|
||||
if (kl->merge == MERGE_SER_CRIT)
|
||||
if (vl->type == PROP_INTEGER)
|
||||
cval = (double)vl->value.ival;
|
||||
else
|
||||
cval = vl->value.dval;
|
||||
else {
|
||||
kl = (struct property *)HashLookup(vl->key, &(tp1->propdict));
|
||||
if (kl && (kl->merge == MERGE_SER_CRIT))
|
||||
if (vl->type == PROP_INTEGER)
|
||||
cval = (double)vl->value.ival;
|
||||
else
|
||||
cval = vl->value.dval;
|
||||
}
|
||||
}
|
||||
proplist[i].value = (double)sval * cval;
|
||||
proplist[i].idx = i;
|
||||
@@ -4224,9 +4226,9 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int serial)
|
||||
struct property *kl, *m_rec, **plist;
|
||||
struct valuelist ***vlist, *vl, *vl2, *newvlist;
|
||||
proplinkptr plink, ptop;
|
||||
int pcount, p, i, j, pmatch, ival, crit, ctype;
|
||||
int pcount, p, i, j, k, pmatch, ival, crit, ctype;
|
||||
double dval;
|
||||
static struct valuelist nullvl;
|
||||
static struct valuelist nullvl, dfltvl;
|
||||
char multiple[2];
|
||||
int changed = 0;
|
||||
|
||||
@@ -4336,9 +4338,37 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int serial)
|
||||
pmatch++;
|
||||
continue;
|
||||
}
|
||||
// TO-DO: If either value is missing, it takes kl->pdefault
|
||||
|
||||
// If either value is missing, it takes kl->pdefault
|
||||
// and must apply promotions if necessary.
|
||||
else if (vl == NULL || vl2 == NULL) continue;
|
||||
|
||||
else if (vl == NULL || vl2 == NULL) {
|
||||
if (vl == NULL) {
|
||||
if (kl->type != vlist[p][j]->type)
|
||||
PromoteProperty(kl, vl2);
|
||||
}
|
||||
else {
|
||||
if (kl->type != vlist[p][i]->type)
|
||||
PromoteProperty(kl, vl);
|
||||
}
|
||||
vl = &dfltvl;
|
||||
dfltvl.type = kl->type;
|
||||
switch (kl->type) {
|
||||
case PROP_STRING:
|
||||
dfltvl.value.string = kl->pdefault.string;
|
||||
break;
|
||||
case PROP_INTEGER:
|
||||
dfltvl.value.ival = kl->pdefault.ival;
|
||||
break;
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
dfltvl.value.ival = kl->pdefault.ival;
|
||||
break;
|
||||
case PROP_EXPRESSION:
|
||||
dfltvl.value.stack = kl->pdefault.stack;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Critical properties can be multiplied up by M (S) and do not
|
||||
// need to match. May want a more nuanced comparison, though.
|
||||
@@ -4953,6 +4983,52 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1,
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Dump a description of a device's serial/parallel network */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
void DumpNetwork(struct objlist *ob, int cidx)
|
||||
{
|
||||
struct valuelist *vl;
|
||||
struct objlist *tp;
|
||||
int i;
|
||||
|
||||
for (tp = ob; tp && (tp->type != PROPERTY); tp = tp->next)
|
||||
if ((tp > ob) && (tp->type == FIRSTPIN))
|
||||
return;
|
||||
|
||||
if (tp == NULL) return;
|
||||
|
||||
Fprintf(stdout, "Circuit %d instance %s network:\n", cidx, ob->instance.name);
|
||||
|
||||
for (; tp && (tp->type == PROPERTY); tp = tp->next) {
|
||||
for (i = 0;; i++) {
|
||||
vl = &(tp->instance.props[i]);
|
||||
if (vl->type == PROP_ENDLIST) break;
|
||||
if (!strcmp(vl->key, "_tag")) {
|
||||
Fprintf(stdout, "%s\n", vl->value.string);
|
||||
continue;
|
||||
}
|
||||
Fprintf(stdout, " %s = ", vl->key);
|
||||
switch(vl->type) {
|
||||
case PROP_STRING:
|
||||
Fprintf(stdout, "%s\n", vl->value.string);
|
||||
break;
|
||||
case PROP_INTEGER:
|
||||
Fprintf(stdout, "%d\n", vl->value.ival);
|
||||
break;
|
||||
case PROP_DOUBLE:
|
||||
case PROP_VALUE:
|
||||
Fprintf(stdout, "%g\n", vl->value.dval);
|
||||
break;
|
||||
case PROP_EXPRESSION:
|
||||
Fprintf(stdout, "(expression)\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Compare the properties of two objects. The passed values */
|
||||
/* ob1 and ob2 are pointers to the first entry (firstpin) of */
|
||||
@@ -4981,7 +5057,7 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
|
||||
struct property *kl1, *kl2;
|
||||
struct valuelist *vl1, *vl2;
|
||||
int t1type, t2type;
|
||||
int i, mismatches = 0;
|
||||
int i, mismatches = 0, checked_one;
|
||||
int rval = 1;
|
||||
char *inst1, *inst2;
|
||||
#ifdef TCL_NETGEN
|
||||
@@ -5073,8 +5149,18 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
|
||||
inst2 = ob2->instance.name;
|
||||
if (*inst2 == '/') inst2++;
|
||||
|
||||
checked_one = FALSE;
|
||||
while(1) {
|
||||
if (t1type != PROPERTY) {
|
||||
if ((t1type != PROPERTY) && (checked_one == TRUE)) {
|
||||
// t2 has more property records than t1, and they did not get
|
||||
// merged equally by PropertySortAndCombine().
|
||||
Fprintf(stdout, "Circuit 1 parallel/serial network does not match"
|
||||
" Circuit 2\n");
|
||||
DumpNetwork(ob1, 1);
|
||||
DumpNetwork(ob2, 2);
|
||||
mismatches++;
|
||||
}
|
||||
else if (t1type != PROPERTY) {
|
||||
// t1 has no properties. See if t2's properties are required
|
||||
// to be checked. If so, flag t2 instance as unmatched
|
||||
|
||||
@@ -5084,13 +5170,24 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
|
||||
if (vl2 == NULL) continue;
|
||||
if (vl2->key == NULL) continue;
|
||||
kl2 = (struct property *)HashLookup(vl2->key, &(tc2->propdict));
|
||||
if (kl2 != NULL) break; // Property is required
|
||||
if (kl2 != NULL) {
|
||||
// Allowed for one instance to be missing "M" or "S".
|
||||
if (strcasecmp(vl2->key, "M") && strcasecmp(vl2->key, "S"))
|
||||
break; // Property is required
|
||||
}
|
||||
}
|
||||
if (vl2->type != PROP_ENDLIST) {
|
||||
mismatches++;
|
||||
if (do_print) Fprintf(stdout, "Circuit 2 %s instance %s has no"
|
||||
" property match in circuit 1.\n",
|
||||
Circuit2->name, inst2);
|
||||
if (do_print) {
|
||||
if (vl2 && vl2->key)
|
||||
Fprintf(stdout, "Circuit 2 %s instance %s property"
|
||||
" \"%s\" has no match in circuit 1.\n",
|
||||
Circuit2->name, inst2, vl2->key);
|
||||
else
|
||||
Fprintf(stdout, "Circuit 2 %s instance %s has no"
|
||||
" property match in circuit 1.\n",
|
||||
Circuit2->name, inst2);
|
||||
}
|
||||
#ifdef TCL_NETGEN
|
||||
if (do_list) {
|
||||
mpair = PropertyList(NULL, vl2);
|
||||
@@ -5105,23 +5202,43 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
|
||||
else
|
||||
rval = 0;
|
||||
}
|
||||
else if ((t2type != PROPERTY) && (checked_one == TRUE)) {
|
||||
// t1 has more property records than t2, and they did not get
|
||||
// merged equally by PropertySortAndCombine().
|
||||
Fprintf(stdout, "Circuit 2 parallel/serial network does not match"
|
||||
" Circuit 1\n");
|
||||
DumpNetwork(ob1, 1);
|
||||
DumpNetwork(ob2, 2);
|
||||
mismatches++;
|
||||
}
|
||||
else if (t2type != PROPERTY) {
|
||||
// t2 has no properties. See if t1's properties are required
|
||||
// to be checked. If so, flag t1 instance as unmatched
|
||||
|
||||
mismatches++;
|
||||
for (i = 0;; i++) {
|
||||
vl1 = &(tp1->instance.props[i]);
|
||||
if (vl1->type == PROP_ENDLIST) break;
|
||||
if (vl1 == NULL) continue;
|
||||
if (vl1->key == NULL) continue;
|
||||
kl1 = (struct property *)HashLookup(vl1->key, &(tc1->propdict));
|
||||
if (kl1 != NULL) break; // Property is required
|
||||
if (kl1 != NULL) {
|
||||
// Allowed for one instance to be missing "M" or "S".
|
||||
if (strcasecmp(vl1->key, "M") && strcasecmp(vl1->key, "S"))
|
||||
break; // Property is required
|
||||
}
|
||||
}
|
||||
if (vl1->type != PROP_ENDLIST) {
|
||||
if (do_print) Fprintf(stdout, "Circuit 1 %s instance %s has no"
|
||||
" property match in Circuit 2.\n",
|
||||
Circuit1->name, inst1);
|
||||
mismatches++;
|
||||
if (do_print) {
|
||||
if (vl1 && vl1->key)
|
||||
Fprintf(stdout, "Circuit 1 %s instance %s property"
|
||||
" \"%s\" has no match in circuit 2.\n",
|
||||
Circuit1->name, inst1, vl1->key);
|
||||
else
|
||||
Fprintf(stdout, "Circuit 1 %s instance %s has no"
|
||||
" property match in circuit 2.\n",
|
||||
Circuit1->name, inst1);
|
||||
}
|
||||
#ifdef TCL_NETGEN
|
||||
if (do_list) {
|
||||
mpair = PropertyList(vl1, NULL);
|
||||
@@ -5171,6 +5288,7 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
|
||||
t1type = (tp1) ? tp1->type : 0;
|
||||
t2type = (tp2) ? tp2->type : 0;
|
||||
if ((t1type != PROPERTY) && (t2type != PROPERTY)) break;
|
||||
checked_one = TRUE;
|
||||
}
|
||||
|
||||
*retval = (rval < 0) ? rval : mismatches;
|
||||
@@ -6057,7 +6175,7 @@ int reorderpins(struct hashlist *p, int file)
|
||||
struct nlist *ptr;
|
||||
struct nlist *tc2 = Circuit2;
|
||||
struct objlist *ob, *ob2, *firstpin;
|
||||
int i, numports, *nodes;
|
||||
int i, numports, *nodes, unordered;
|
||||
char **names;
|
||||
|
||||
ptr = (struct nlist *)(p->ptr);
|
||||
@@ -6071,14 +6189,23 @@ int reorderpins(struct hashlist *p, int file)
|
||||
/* instances of both cells. */
|
||||
|
||||
numports = 0;
|
||||
unordered = 0;
|
||||
ob2 = tc2->cell;
|
||||
while (ob2 && ob2->type == PORT) {
|
||||
if (ob2->model.port < 0) {
|
||||
ob2->model.port = numports;
|
||||
unordered = 1;
|
||||
}
|
||||
numports++;
|
||||
ob2 = ob2->next;
|
||||
}
|
||||
nodes = (int *)CALLOC(numports, sizeof(int));
|
||||
names = (char **)CALLOC(numports, sizeof(char *));
|
||||
|
||||
if (unordered)
|
||||
Fprintf(stderr, "Ports of %s are unordered. "
|
||||
"Ordering will be arbitrary.", tc2->name);
|
||||
|
||||
for (ob = ptr->cell; ob != NULL; ) {
|
||||
if (ob->type == FIRSTPIN) {
|
||||
if ((*matchfunc)(ob->model.class, tc2->name)) {
|
||||
|
||||
@@ -193,6 +193,67 @@ static struct filestack *OpenFiles = NULL;
|
||||
|
||||
#define TOKEN_DELIMITER " \t\n\r"
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* TrimQuoted() --- */
|
||||
/* Remove spaces from inside single- or double-quoted strings. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void TrimQuoted(char *line)
|
||||
{
|
||||
char *qstart, *qend, *lptr;
|
||||
int slen;
|
||||
int changed;
|
||||
|
||||
/* Single-quoted entries */
|
||||
changed = TRUE;
|
||||
lptr = line;
|
||||
while (changed)
|
||||
{
|
||||
changed = FALSE;
|
||||
qstart = strchr(lptr, '\'');
|
||||
if (qstart)
|
||||
{
|
||||
qend = strchr(qstart + 1, '\'');
|
||||
if (qend && (qend > qstart)) {
|
||||
slen = strlen(lptr);
|
||||
for (lptr = qstart + 1; lptr < qend; lptr++) {
|
||||
if (*lptr == ' ') {
|
||||
memmove(lptr, lptr + 1, slen);
|
||||
qend--;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
lptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Double-quoted entries */
|
||||
changed = TRUE;
|
||||
lptr = line;
|
||||
while (changed)
|
||||
{
|
||||
changed = FALSE;
|
||||
qstart = strchr(lptr, '\"');
|
||||
if (qstart)
|
||||
{
|
||||
qend = strchr(qstart + 1, '\"');
|
||||
if (qend && (qend > qstart)) {
|
||||
slen = strlen(lptr);
|
||||
for (lptr = qstart + 1; lptr < qend; lptr++) {
|
||||
if (*lptr == ' ') {
|
||||
memmove(lptr, lptr + 1, slen);
|
||||
qend--;
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
lptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* GetNextLineNoNewline() */
|
||||
/* */
|
||||
@@ -233,6 +294,7 @@ int GetNextLineNoNewline()
|
||||
}
|
||||
linenum++;
|
||||
strcpy(linetok, line);
|
||||
TrimQuoted(linetok);
|
||||
|
||||
nexttok = strtok(linetok, TOKEN_DELIMITER);
|
||||
return 0;
|
||||
|
||||
+10
-2
@@ -3309,7 +3309,9 @@ int check_pin_nodes(struct objlist *ob1, struct objlist *ob2)
|
||||
pob = pob->next;
|
||||
}
|
||||
|
||||
if (nob->type > FIRSTPIN || pob->type > FIRSTPIN) return FALSE;
|
||||
if (nob && pob && (nob->type > FIRSTPIN || pob->type > FIRSTPIN))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -3486,7 +3488,13 @@ int CombineSerial(char *model, int file)
|
||||
/* only pointer to it. */
|
||||
for (obp = instlist[i][0]; obp->next->type > FIRSTPIN ||
|
||||
obp->next->type == PROPERTY; obp = obp->next);
|
||||
for (ob2 = obp; ob2->next != instlist[i][1]; ob2 = ob2->next);
|
||||
for (ob2 = obp; ob2 && ob2->next != instlist[i][1]; ob2 = ob2->next);
|
||||
|
||||
/* Device may have been moved by the above code. If so, look for */
|
||||
/* it from the beginning of the list. */
|
||||
if (ob2 == NULL)
|
||||
for (ob2 = tp->cell; ob2->next != instlist[i][1]; ob2 = ob2->next);
|
||||
|
||||
for (obs = ob2->next; obs->next && (obs->next->type > FIRSTPIN
|
||||
|| obs->next->type == PROPERTY); obs = obs->next);
|
||||
ob2->next = obs->next;
|
||||
|
||||
+2
-2
@@ -777,7 +777,7 @@ skip_ends:
|
||||
/* For ~/<path>, substitute tilde from $HOME */
|
||||
userpath = getenv("HOME");
|
||||
iname = (char *)MALLOC(strlen(userpath) + strlen(iptr));
|
||||
sprintf(fname, "%s%s", userpath, iptr + 1);
|
||||
sprintf(iname, "%s%s", userpath, iptr + 1);
|
||||
}
|
||||
else if (*iptr == '~') {
|
||||
/* For ~<user>/<path>, substitute tilde from getpwnam() */
|
||||
@@ -791,7 +791,7 @@ skip_ends:
|
||||
if (pathstart) {
|
||||
*pathstart = '/';
|
||||
iname = (char *)MALLOC(strlen(userpath) + strlen(pathstart) + 1);
|
||||
sprintf(fname, "%s%s", userpath, pathstart);
|
||||
sprintf(iname, "%s%s", userpath, pathstart);
|
||||
}
|
||||
else {
|
||||
/* Almost certainly an error, but make the substitution anyway */
|
||||
|
||||
+2
-2
@@ -22,8 +22,8 @@ tclnetgen${SHDLIB_EXT}: ${EXTRA_LIBS}
|
||||
@echo --- making netgen Tcl library \(tclnetgen${SHDLIB_EXT}\)
|
||||
${RM} tclnetgen${SHDLIB_EXT}
|
||||
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} \
|
||||
${LD_RUN_PATH} ${EXTRA_LIBS} ${LD_EXTRA_LIBS} -lc ${LIBS} \
|
||||
${LIB_SPECS} ${LDFLAGS}
|
||||
${LD_RUN_PATH} ${EXTRA_LIBS} ${LD_EXTRA_LIBS} \
|
||||
-lc ${LIBS} ${LIB_SPECS} ${LDFLAGS}
|
||||
|
||||
$(DESTDIR)${BINDIR}/netgen:
|
||||
${RM} $@
|
||||
|
||||
@@ -868,7 +868,6 @@ case $target in
|
||||
AC_DEFINE(i386)
|
||||
;;
|
||||
*darwin*)
|
||||
AC_DEFINE(macosx)
|
||||
if test "$CPP" = "cc -E" ; then
|
||||
CPPFLAGS="$CPPFLAGS -no-cpp-precomp"
|
||||
fi
|
||||
|
||||
+7
-2
@@ -529,8 +529,13 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||
} else {
|
||||
# Match pins
|
||||
netgen::log echo off
|
||||
set result [equate pins "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"]
|
||||
if {$dolist == 1} {
|
||||
set result [equate pins "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"]
|
||||
} else {
|
||||
set result [equate -list pins "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"]
|
||||
}
|
||||
if {$result != 0} {
|
||||
equate classes "$fnum1 [lindex $endval 0]" \
|
||||
"$fnum2 [lindex $endval 1]"
|
||||
|
||||
+1
-1
@@ -4071,7 +4071,7 @@ int Tclnetgen_Init(Tcl_Interp *interp)
|
||||
if (cadroot == NULL) cadroot = CAD_DIR;
|
||||
Tcl_SetVar(interp, "CAD_ROOT", cadroot, TCL_GLOBAL_ONLY);
|
||||
|
||||
Tcl_PkgProvide(interp, "Tclnetgen", "1.1");
|
||||
Tcl_PkgProvide(interp, "Tclnetgen", NETGEN_VERSION);
|
||||
|
||||
if ((consoleinterp = Tcl_GetMaster(interp)) == NULL)
|
||||
consoleinterp = interp;
|
||||
|
||||
Reference in New Issue
Block a user