Merge branch 'master' into netgen-1.5
This commit is contained in:
commit
fb798d6ce7
|
|
@ -12,3 +12,5 @@ scripts/config.status
|
||||||
*~
|
*~
|
||||||
*.log
|
*.log
|
||||||
UPDATE_ME
|
UPDATE_ME
|
||||||
|
tcltk/netgen.sh
|
||||||
|
tcltk/netgen.tcl
|
||||||
|
|
|
||||||
|
|
@ -193,17 +193,19 @@ void flattenCell(char *name, int file)
|
||||||
if (Debug) Printf("Renaming %s to %s\n", tmp->name, tmpstr);
|
if (Debug) Printf("Renaming %s to %s\n", tmp->name, tmpstr);
|
||||||
FreeString(tmp->name);
|
FreeString(tmp->name);
|
||||||
tmp->name = strsave(tmpstr);
|
tmp->name = strsave(tmpstr);
|
||||||
#if OLDPREFIX
|
|
||||||
sprintf(tmpstr, "%s%s%s", ParentParams->instance.name, SEPARATOR,
|
|
||||||
tmp->instance.name);
|
|
||||||
#else
|
|
||||||
strcpy(tmpstr+prefixlength,tmp->instance.name);
|
|
||||||
#endif
|
|
||||||
FreeString(tmp->instance.name);
|
|
||||||
tmp->instance.name = strsave(tmpstr);
|
|
||||||
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
|
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
|
||||||
if (tmp->type == FIRSTPIN)
|
if ((tmp->type != NODE) && (tmp->instance.name != NULL)) {
|
||||||
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
|
#if OLDPREFIX
|
||||||
|
sprintf(tmpstr, "%s%s%s", ParentParams->instance.name, SEPARATOR,
|
||||||
|
tmp->instance.name);
|
||||||
|
#else
|
||||||
|
strcpy(tmpstr+prefixlength,tmp->instance.name);
|
||||||
|
#endif
|
||||||
|
FreeString(tmp->instance.name);
|
||||||
|
tmp->instance.name = strsave(tmpstr);
|
||||||
|
if (tmp->type == FIRSTPIN)
|
||||||
|
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* splice instance out of parent */
|
/* splice instance out of parent */
|
||||||
|
|
@ -470,17 +472,19 @@ int flattenInstancesOf(char *name, int fnum, char *instance)
|
||||||
if (Debug) Printf("Renaming %s to %s\n", tmp->name, tmpstr);
|
if (Debug) Printf("Renaming %s to %s\n", tmp->name, tmpstr);
|
||||||
FreeString(tmp->name);
|
FreeString(tmp->name);
|
||||||
tmp->name = strsave(tmpstr);
|
tmp->name = strsave(tmpstr);
|
||||||
#if OLDPREFIX
|
|
||||||
sprintf(tmpstr, "%s%s%s", ParentParams->instance.name, SEPARATOR,
|
|
||||||
tmp->instance.name);
|
|
||||||
#else
|
|
||||||
strcpy(tmpstr+prefixlength,tmp->instance.name);
|
|
||||||
#endif
|
|
||||||
FreeString(tmp->instance.name);
|
|
||||||
tmp->instance.name = strsave(tmpstr);
|
|
||||||
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
|
HashPtrInstall(tmp->name, tmp, &(ThisCell->objdict));
|
||||||
if (tmp->type == FIRSTPIN)
|
if ((tmp->type != NODE) && (tmp->instance.name != NULL)) {
|
||||||
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
|
#if OLDPREFIX
|
||||||
|
sprintf(tmpstr, "%s%s%s", ParentParams->instance.name, SEPARATOR,
|
||||||
|
tmp->instance.name);
|
||||||
|
#else
|
||||||
|
strcpy(tmpstr+prefixlength,tmp->instance.name);
|
||||||
|
#endif
|
||||||
|
FreeString(tmp->instance.name);
|
||||||
|
tmp->instance.name = strsave(tmpstr);
|
||||||
|
if (tmp->type == FIRSTPIN)
|
||||||
|
HashPtrInstall(tmp->instance.name, tmp, &(ThisCell->instdict));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do property inheritance */
|
/* Do property inheritance */
|
||||||
|
|
|
||||||
|
|
@ -5360,6 +5360,32 @@ PropertyMatch(struct objlist *ob1, int file1,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* WIP---Check for no-connect pins in merged devices on both sides. */
|
||||||
|
/* Both sides should either have no-connects marked, or neither. */
|
||||||
|
/* (Permutable pins may need to be handled correctly. . . */
|
||||||
|
for (tp1 = ob1, tp2 = ob2; (tp1 != NULL) && tp1->type >= FIRSTPIN &&
|
||||||
|
(tp2 != NULL) && tp2->type >= FIRSTPIN; tp1 = tp1->next, tp2 = tp2->next)
|
||||||
|
{
|
||||||
|
struct objlist *node1, *node2;
|
||||||
|
|
||||||
|
node1 = Circuit1->nodename_cache[tp1->node];
|
||||||
|
node2 = Circuit2->nodename_cache[tp2->node];
|
||||||
|
|
||||||
|
if (node1->instance.flags != node2->instance.flags)
|
||||||
|
{
|
||||||
|
Fprintf(stdout, " Parallelized instances disagree on pin connections.\n");
|
||||||
|
Fprintf(stdout, " Circuit1 instance %s pin %s connections are %s (%d)\n",
|
||||||
|
tp1->instance.name, node1->name,
|
||||||
|
(node1->instance.flags == 0) ? "tied together" : "no connects",
|
||||||
|
node1->instance.flags);
|
||||||
|
Fprintf(stdout, " Circuit2 instance %s pin %s connections are %s (%d)\n",
|
||||||
|
tp2->instance.name, node2->name,
|
||||||
|
(node2->instance.flags == 0) ? "tied together" : "no connects",
|
||||||
|
node2->instance.flags);
|
||||||
|
mismatches++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt to organize devices by series and parallel combination
|
// Attempt to organize devices by series and parallel combination
|
||||||
if (t1type == PROPERTY && t2type == PROPERTY)
|
if (t1type == PROPERTY && t2type == PROPERTY)
|
||||||
PropertySortAndCombine(obn1, tc1, obn2, tc2);
|
PropertySortAndCombine(obn1, tc1, obn2, tc2);
|
||||||
|
|
|
||||||
|
|
@ -1337,7 +1337,7 @@ void Node(char *name)
|
||||||
tp->name = strsave(name);
|
tp->name = strsave(name);
|
||||||
tp->type = NODE; /* internal node type */
|
tp->type = NODE; /* internal node type */
|
||||||
tp->model.class = NULL;
|
tp->model.class = NULL;
|
||||||
tp->instance.name = NULL;
|
tp->instance.flags = 0;
|
||||||
tp->node = -1; /* null node */
|
tp->node = -1; /* null node */
|
||||||
tp->next = NULL;
|
tp->next = NULL;
|
||||||
AddToCurrentCell (tp);
|
AddToCurrentCell (tp);
|
||||||
|
|
@ -3216,8 +3216,12 @@ int CombineParallel(char *model, int file)
|
||||||
pptr += pstr - (char *)2;
|
pptr += pstr - (char *)2;
|
||||||
|
|
||||||
for (ob2 = ob; ob2 && (ob2->type > FIRSTPIN || ob2 == ob); ob2 = ob2->next) {
|
for (ob2 = ob; ob2 && (ob2->type > FIRSTPIN || ob2 == ob); ob2 = ob2->next) {
|
||||||
if ((ob->node >= 0) && (nodecount[ob->node] == 1))
|
if ((ob2->node >= 0) && (nodecount[ob2->node] == 1))
|
||||||
|
{
|
||||||
|
nob = (tp->nodename_cache)[ob2->node];
|
||||||
|
nob->instance.flags = NO_CONNECT;
|
||||||
strcat(pptr, "_nc");
|
strcat(pptr, "_nc");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
sprintf(pptr, "_%d", ob2->node);
|
sprintf(pptr, "_%d", ob2->node);
|
||||||
pptr += strlen(pptr);
|
pptr += strlen(pptr);
|
||||||
|
|
@ -3290,7 +3294,7 @@ int CombineParallel(char *model, int file)
|
||||||
else {
|
else {
|
||||||
/* Find parallel device "ob" and append properties of */
|
/* Find parallel device "ob" and append properties of */
|
||||||
/* "sob" to it. If "ob" does not have properties, then */
|
/* "sob" to it. If "ob" does not have properties, then */
|
||||||
/* create a property record and set property "M" to 2. */
|
/* create a property record and set property "M" to 1. */
|
||||||
|
|
||||||
/* Find last non-property record of sob ( = pob) */
|
/* Find last non-property record of sob ( = pob) */
|
||||||
/* Find first property record of sob ( = spropfirst) */
|
/* Find first property record of sob ( = spropfirst) */
|
||||||
|
|
|
||||||
|
|
@ -975,7 +975,10 @@ struct objlist *CopyObjList(struct objlist *oldlist, unsigned char doforall)
|
||||||
newob->model.class = NULL;
|
newob->model.class = NULL;
|
||||||
else
|
else
|
||||||
newob->model.class = strsave(tmp->model.class);
|
newob->model.class = strsave(tmp->model.class);
|
||||||
newob->instance.name = (tmp->instance.name) ?
|
if (newob->type == NODE)
|
||||||
|
newob->instance.flags = tmp->instance.flags;
|
||||||
|
else
|
||||||
|
newob->instance.name = (tmp->instance.name) ?
|
||||||
strsave(tmp->instance.name) : NULL;
|
strsave(tmp->instance.name) : NULL;
|
||||||
}
|
}
|
||||||
newob->node = tmp->node;
|
newob->node = tmp->node;
|
||||||
|
|
@ -1095,8 +1098,8 @@ void FreeObject(struct objlist *ob)
|
||||||
FREE(ob->instance.props);
|
FREE(ob->instance.props);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else if (ob->type != NODE) {
|
||||||
/* All other records */
|
/* All other records except NODE, which uses this for flags */
|
||||||
if (ob->instance.name != NULL) FreeString(ob->instance.name);
|
if (ob->instance.name != NULL) FreeString(ob->instance.name);
|
||||||
}
|
}
|
||||||
if (ob->model.class != NULL) FreeString(ob->model.class);
|
if (ob->model.class != NULL) FreeString(ob->model.class);
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@
|
||||||
|
|
||||||
#define PROXY (0) /* Used in model.port record of ports */
|
#define PROXY (0) /* Used in model.port record of ports */
|
||||||
|
|
||||||
|
#define NO_CONNECT 1 /* Use in object list to flag an isolated net */
|
||||||
|
|
||||||
/* Lists of device properties. Order is defined at the time of */
|
/* Lists of device properties. Order is defined at the time of */
|
||||||
/* the cell definition; values are sorted at the time instances */
|
/* the cell definition; values are sorted at the time instances */
|
||||||
/* are read. */
|
/* are read. */
|
||||||
|
|
@ -160,6 +162,7 @@ struct objlist {
|
||||||
union {
|
union {
|
||||||
char *name; /* unique name for the instance, or */
|
char *name; /* unique name for the instance, or */
|
||||||
/* (string) value of property for properties */
|
/* (string) value of property for properties */
|
||||||
|
int flags; /* Used by NODE type to flag isolated net */
|
||||||
struct valuelist *props; /* Property record */
|
struct valuelist *props; /* Property record */
|
||||||
} instance;
|
} instance;
|
||||||
int node; /* the electrical node number of the port/node/pin */
|
int node; /* the electrical node number of the port/node/pin */
|
||||||
|
|
|
||||||
|
|
@ -1186,7 +1186,7 @@ skip_ends:
|
||||||
else if (CountPorts(model, filenum) != 2) {
|
else if (CountPorts(model, filenum) != 2) {
|
||||||
/* Modeled device: Make sure it has the right number of ports */
|
/* Modeled device: Make sure it has the right number of ports */
|
||||||
Fprintf(stderr, "Device \"%s\" has wrong number of ports for a "
|
Fprintf(stderr, "Device \"%s\" has wrong number of ports for a "
|
||||||
"resistor.\n");
|
"resistor.\n", model);
|
||||||
goto baddevice;
|
goto baddevice;
|
||||||
}
|
}
|
||||||
usemodel = 1;
|
usemodel = 1;
|
||||||
|
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# For installation, put this file (netgen.sh) in a standard executable path.
|
|
||||||
# Put startup script "netgen.tcl" and shared library "tclnetgen.so"
|
|
||||||
# in ${CAD_ROOT}/netgen/tcl/, with a symbolic link from file
|
|
||||||
# ".wishrc" to "netgen.tcl".
|
|
||||||
#
|
|
||||||
# This script starts irsim under the Tcl interpreter,
|
|
||||||
# reading commands from a special .wishrc script which
|
|
||||||
# launches irsim and retains the Tcl interactive interpreter.
|
|
||||||
|
|
||||||
# Parse for the argument "-c[onsole]". If it exists, run netgen
|
|
||||||
# with the TkCon console. Strip this argument from the argument list.
|
|
||||||
|
|
||||||
TKCON=true
|
|
||||||
BATCH=
|
|
||||||
GUI=
|
|
||||||
NETGEN_WISH=/usr/bin/wish
|
|
||||||
export NETGEN_WISH
|
|
||||||
|
|
||||||
# Hacks for Cygwin
|
|
||||||
if [ ${TERM:=""} = "cygwin" ]; then
|
|
||||||
export PATH="$PATH:/usr/lib"
|
|
||||||
export DISPLAY=${DISPLAY:=":0"}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Preserve quotes in arguments (thanks, Stackoverflow!)
|
|
||||||
arglist=''
|
|
||||||
for i in "$@" ; do
|
|
||||||
case $i in
|
|
||||||
-noc*) TKCON=;;
|
|
||||||
-bat*) BATCH=true; TKCON=;;
|
|
||||||
-gui) GUI=true; TKCON=;;
|
|
||||||
*) arglist="$arglist${arglist:+ }\"${i//\"/\\\"}\"";;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ $TKCON ]; then
|
|
||||||
|
|
||||||
exec /usr/local/lib/netgen/tcl/tkcon.tcl \
|
|
||||||
-eval "source /usr/local/lib/netgen/tcl/console.tcl" \
|
|
||||||
-slave "package require Tk; set argc $#; set argv [list $arglist]; \
|
|
||||||
source /usr/local/lib/netgen/tcl/netgen.tcl"
|
|
||||||
|
|
||||||
# Run the Python LVS manager GUI
|
|
||||||
|
|
||||||
elif [ $GUI ]; then
|
|
||||||
exec /usr/local/lib/netgen/python/lvs_manager.py $@
|
|
||||||
|
|
||||||
#
|
|
||||||
# Run the stand-in for wish (netgenexec), which acts exactly like "wish"
|
|
||||||
# except that it replaces ~/.wishrc with netgen.tcl. This executable is
|
|
||||||
# *only* needed when running without the console; the console itself is
|
|
||||||
# capable of sourcing the startup script.
|
|
||||||
#
|
|
||||||
|
|
||||||
else
|
|
||||||
exec /usr/local/lib/netgen/tcl/netgenexec -- "$@"
|
|
||||||
|
|
||||||
fi
|
|
||||||
753
tcltk/netgen.tcl
753
tcltk/netgen.tcl
|
|
@ -1,753 +0,0 @@
|
||||||
# Wishrc startup for ToolScript (netgen)
|
|
||||||
#
|
|
||||||
# For installation: Put this file and also tclnetgen.so into
|
|
||||||
# directory ${CAD_ROOT}/netgen/tcl/, and set the "load" line below
|
|
||||||
# to point to the location of tclnetgen.so. Also see comments
|
|
||||||
# in shell script "netgen.sh".
|
|
||||||
#
|
|
||||||
|
|
||||||
# Check namespaces for existence of other applications
|
|
||||||
set UsingMagic 0
|
|
||||||
set UsingXCircuit 0
|
|
||||||
set UsingIRSIM 0
|
|
||||||
set batchmode 0
|
|
||||||
set nlist [namespace children]
|
|
||||||
foreach i $nlist {
|
|
||||||
switch $i {
|
|
||||||
::magic { set UsingMagic 1 }
|
|
||||||
::xcircuit { set UsingXCircuit 1 }
|
|
||||||
::irsim { set UsingIRSIM 1 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# -lazy option not needed if stubs libraries are handled correctly
|
|
||||||
# load -lazy /usr/local/lib/netgen/tcl/tclnetgen.so
|
|
||||||
|
|
||||||
load /usr/local/lib/netgen/tcl/tclnetgen.so
|
|
||||||
|
|
||||||
#----------------------------------------------------------------
|
|
||||||
# Convert LVS list result into a JSON file
|
|
||||||
#----------------------------------------------------------------
|
|
||||||
|
|
||||||
proc netgen::convert_to_json {filename lvs_final} {
|
|
||||||
set pidx [string last . $filename]
|
|
||||||
set jsonname [string replace $filename $pidx end ".json"]
|
|
||||||
if {![catch {open $jsonname w} fjson]} {
|
|
||||||
puts $fjson "\["
|
|
||||||
# Outer list is of each cell compared
|
|
||||||
set clen [llength $lvs_final]
|
|
||||||
set cidx 0
|
|
||||||
foreach circuit $lvs_final {
|
|
||||||
incr cidx
|
|
||||||
puts $fjson " \{"
|
|
||||||
set nkeys [llength $circuit]
|
|
||||||
set kidx 0
|
|
||||||
foreach {key value} $circuit {
|
|
||||||
incr kidx 2
|
|
||||||
switch $key {
|
|
||||||
name {
|
|
||||||
puts $fjson " \"${key}\": \["
|
|
||||||
set cktval [lindex $value 0]
|
|
||||||
puts $fjson " \"${cktval}\","
|
|
||||||
set cktval [lindex $value 1]
|
|
||||||
puts $fjson " \"${cktval}\""
|
|
||||||
if {$kidx == $nkeys} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pins {
|
|
||||||
puts $fjson " \"${key}\": \["
|
|
||||||
puts $fjson " \["
|
|
||||||
set cktval [lindex $value 0]
|
|
||||||
foreach pin [lrange $cktval 0 end-1] {
|
|
||||||
puts $fjson " \"$pin\","
|
|
||||||
}
|
|
||||||
set pin [lindex $cktval end]
|
|
||||||
puts $fjson " \"$pin\""
|
|
||||||
puts $fjson " \], \["
|
|
||||||
set cktval [lindex $value 1]
|
|
||||||
foreach pin [lrange $cktval 0 end-1] {
|
|
||||||
puts $fjson " \"$pin\","
|
|
||||||
}
|
|
||||||
set pin [lindex $cktval end]
|
|
||||||
puts $fjson " \"$pin\""
|
|
||||||
puts $fjson " \]"
|
|
||||||
if {$kidx == $nkeys} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nets {
|
|
||||||
puts $fjson " \"${key}\": \["
|
|
||||||
set cktval [lindex $value 0]
|
|
||||||
puts $fjson " $cktval,"
|
|
||||||
set cktval [lindex $value 1]
|
|
||||||
puts $fjson " $cktval"
|
|
||||||
if {$kidx == $nkeys} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
devices {
|
|
||||||
puts $fjson " \"${key}\": \["
|
|
||||||
puts $fjson " \["
|
|
||||||
set cktval [lindex $value 0]
|
|
||||||
foreach dev [lrange $cktval 0 end-1] {
|
|
||||||
set devname [lindex $dev 0]
|
|
||||||
set devnum [lindex $dev 1]
|
|
||||||
puts $fjson " \[\"${devname}\", ${devnum}\],"
|
|
||||||
}
|
|
||||||
set dev [lindex $cktval end]
|
|
||||||
set devname [lindex $dev 0]
|
|
||||||
set devnum [lindex $dev 1]
|
|
||||||
puts $fjson " \[\"${devname}\", ${devnum} \]"
|
|
||||||
puts $fjson " \], \["
|
|
||||||
set cktval [lindex $value 1]
|
|
||||||
foreach dev [lrange $cktval 0 end-1] {
|
|
||||||
set devname [lindex $dev 0]
|
|
||||||
set devnum [lindex $dev 1]
|
|
||||||
puts $fjson " \[\"${devname}\", ${devnum} \],"
|
|
||||||
}
|
|
||||||
set dev [lindex $cktval end]
|
|
||||||
set devname [lindex $dev 0]
|
|
||||||
set devnum [lindex $dev 1]
|
|
||||||
puts $fjson " \[\"${devname}\", ${devnum} \]"
|
|
||||||
puts $fjson " \]"
|
|
||||||
if {$kidx == $nkeys} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goodnets -
|
|
||||||
badnets {
|
|
||||||
puts $fjson " \"${key}\": \["
|
|
||||||
set glen [llength $value]
|
|
||||||
set gidx 0
|
|
||||||
foreach group $value {
|
|
||||||
incr gidx
|
|
||||||
puts $fjson " \["
|
|
||||||
puts $fjson " \["
|
|
||||||
set cktval [lindex $group 0]
|
|
||||||
set nlen [llength $cktval]
|
|
||||||
set nidx 0
|
|
||||||
foreach net $cktval {
|
|
||||||
incr nidx
|
|
||||||
puts $fjson " \["
|
|
||||||
set netname [string map {"\\" "\\\\"} [lindex $net 0]]
|
|
||||||
puts $fjson " \"$netname\","
|
|
||||||
puts $fjson " \["
|
|
||||||
set netconn [lindex $net 1]
|
|
||||||
foreach fanout [lrange $netconn 0 end-1] {
|
|
||||||
set devname [lindex $fanout 0]
|
|
||||||
set pinname [lindex $fanout 1]
|
|
||||||
set count [lindex $fanout 2]
|
|
||||||
if {$count == {}} {set count 0}
|
|
||||||
puts $fjson " \[ \"$devname\", \"$pinname\", $count \],"
|
|
||||||
}
|
|
||||||
set fanout [lindex $netconn end]
|
|
||||||
set devname [lindex $fanout 0]
|
|
||||||
set pinname [lindex $fanout 1]
|
|
||||||
set count [lindex $fanout 2]
|
|
||||||
if {$count == {}} {set count 0}
|
|
||||||
puts $fjson " \[ \"$devname\", \"$pinname\", $count \]"
|
|
||||||
puts $fjson " \]"
|
|
||||||
if {$nidx == $nlen} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $fjson " \], \["
|
|
||||||
set cktval [lindex $group 1]
|
|
||||||
set nlen [llength $cktval]
|
|
||||||
set nidx 0
|
|
||||||
foreach net $cktval {
|
|
||||||
incr nidx
|
|
||||||
puts $fjson " \["
|
|
||||||
set netname [string map {"\\" "\\\\"} [lindex $net 0]]
|
|
||||||
puts $fjson " \"$netname\","
|
|
||||||
puts $fjson " \["
|
|
||||||
set netconn [lindex $net 1]
|
|
||||||
foreach fanout [lrange $netconn 0 end-1] {
|
|
||||||
set devname [lindex $fanout 0]
|
|
||||||
set pinname [lindex $fanout 1]
|
|
||||||
set count [lindex $fanout 2]
|
|
||||||
if {$count == {}} {set count 0}
|
|
||||||
puts $fjson " \[ \"$devname\", \"$pinname\", $count \],"
|
|
||||||
}
|
|
||||||
set fanout [lindex $netconn end]
|
|
||||||
set devname [lindex $fanout 0]
|
|
||||||
set pinname [lindex $fanout 1]
|
|
||||||
set count [lindex $fanout 2]
|
|
||||||
if {$count == {}} {set count 0}
|
|
||||||
puts $fjson " \[ \"$devname\", \"$pinname\", $count \]"
|
|
||||||
puts $fjson " \]"
|
|
||||||
if {$nidx == $nlen} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $fjson " \]"
|
|
||||||
if {$gidx == $glen} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if {$kidx == $nkeys} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goodelements -
|
|
||||||
badelements {
|
|
||||||
puts $fjson " \"${key}\": \["
|
|
||||||
set glen [llength $value]
|
|
||||||
set gidx 0
|
|
||||||
foreach group $value {
|
|
||||||
incr gidx
|
|
||||||
puts $fjson " \["
|
|
||||||
puts $fjson " \["
|
|
||||||
set cktval [lindex $group 0]
|
|
||||||
set ilen [llength $cktval]
|
|
||||||
set iidx 0
|
|
||||||
foreach inst $cktval {
|
|
||||||
incr iidx
|
|
||||||
puts $fjson " \["
|
|
||||||
set instname [string map {"\\" "\\\\"} [lindex $inst 0]]
|
|
||||||
puts $fjson " \"$instname\","
|
|
||||||
puts $fjson " \["
|
|
||||||
set instpins [lindex $inst 1]
|
|
||||||
foreach fanout [lrange $instpins 0 end-1] {
|
|
||||||
set pinname [lindex $fanout 0]
|
|
||||||
set count [lindex $fanout 1]
|
|
||||||
if {$count == {}} {set count 0}
|
|
||||||
puts $fjson " \[ \"$pinname\", $count \],"
|
|
||||||
}
|
|
||||||
set fanout [lindex $instpins end]
|
|
||||||
set pinname [lindex $fanout 0]
|
|
||||||
set count [lindex $fanout 1]
|
|
||||||
if {$count == {}} {set count 0}
|
|
||||||
puts $fjson " \[ \"$pinname\", $count \]"
|
|
||||||
puts $fjson " \]"
|
|
||||||
if {$iidx == $ilen} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $fjson " \], \["
|
|
||||||
set cktval [lindex $group 1]
|
|
||||||
set ilen [llength $cktval]
|
|
||||||
set iidx 0
|
|
||||||
foreach inst $cktval {
|
|
||||||
incr iidx
|
|
||||||
puts $fjson " \["
|
|
||||||
set instname [string map {"\\" "\\\\"} [lindex $inst 0]]
|
|
||||||
puts $fjson " \"$instname\","
|
|
||||||
puts $fjson " \["
|
|
||||||
set instpins [lindex $inst 1]
|
|
||||||
foreach fanout [lrange $instpins 0 end-1] {
|
|
||||||
set pinname [lindex $fanout 0]
|
|
||||||
set count [lindex $fanout 1]
|
|
||||||
if {$count == {}} {set count 0}
|
|
||||||
puts $fjson " \[ \"$pinname\", $count \],"
|
|
||||||
}
|
|
||||||
set fanout [lindex $instpins end]
|
|
||||||
set pinname [lindex $fanout 0]
|
|
||||||
set count [lindex $fanout 1]
|
|
||||||
if {$count == {}} {set count 0}
|
|
||||||
puts $fjson " \[ \"$pinname\", $count \]"
|
|
||||||
puts $fjson " \]"
|
|
||||||
if {$iidx == $ilen} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $fjson " \]"
|
|
||||||
if {$gidx == $glen} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if {$kidx == $nkeys} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
properties {
|
|
||||||
puts $fjson " \"${key}\": \["
|
|
||||||
set plen [llength $value]
|
|
||||||
set pidx 0
|
|
||||||
foreach instance $value {
|
|
||||||
incr pidx
|
|
||||||
puts $fjson " \["
|
|
||||||
set instnames [string map {"\\" "\\\\"} [lindex $instance 0]]
|
|
||||||
set instname0 [string map {"\\" "\\\\"} [lindex $instnames 0]]
|
|
||||||
puts $fjson " \["
|
|
||||||
puts $fjson " \"${instname0}\","
|
|
||||||
puts $fjson " \["
|
|
||||||
foreach property [lrange $instance 1 end-1] {
|
|
||||||
set prop0 [lindex $property 0]
|
|
||||||
set propname [lindex $prop0 0]
|
|
||||||
set propval [lindex $prop0 1]
|
|
||||||
puts $fjson " \[\"${propname}\", \"${propval}\"\],"
|
|
||||||
}
|
|
||||||
set property [lindex $instance end]
|
|
||||||
set prop0 [lindex $property 0]
|
|
||||||
set propname [lindex $prop0 0]
|
|
||||||
set propval [lindex $prop0 1]
|
|
||||||
puts $fjson " \[\"${propname}\", \"${propval}\"\]"
|
|
||||||
puts $fjson " \]"
|
|
||||||
puts $fjson " \],"
|
|
||||||
set instname1 [string map {"\\" "\\\\"} [lindex $instnames 1]]
|
|
||||||
puts $fjson " \["
|
|
||||||
puts $fjson " \"${instname1}\","
|
|
||||||
puts $fjson " \["
|
|
||||||
foreach property [lrange $instance 1 end-1] {
|
|
||||||
set prop1 [lindex $property 1]
|
|
||||||
set propname [lindex $prop1 0]
|
|
||||||
set propval [lindex $prop1 1]
|
|
||||||
puts $fjson " \[\"${propname}\", \"${propval}\"\],"
|
|
||||||
}
|
|
||||||
set property [lindex $instance end]
|
|
||||||
set prop1 [lindex $property 1]
|
|
||||||
set propname [lindex $prop1 0]
|
|
||||||
set propval [lindex $prop1 1]
|
|
||||||
puts $fjson " \[\"${propname}\", \"${propval}\"\]"
|
|
||||||
puts $fjson " \]"
|
|
||||||
puts $fjson " \]"
|
|
||||||
if {$pidx == $plen} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if {$kidx == $nkeys} {
|
|
||||||
puts $fjson " \]"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \],"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if {$cidx == $clen} {
|
|
||||||
puts $fjson " \}"
|
|
||||||
} else {
|
|
||||||
puts $fjson " \},"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
puts $fjson "\]"
|
|
||||||
}
|
|
||||||
close $fjson
|
|
||||||
}
|
|
||||||
|
|
||||||
#----------------------------------------------------------------
|
|
||||||
# Define the "lvs" command as a way of calling the netgen options
|
|
||||||
# for standard compare, essentially the same as the old "netcomp"
|
|
||||||
# standalone program.
|
|
||||||
#
|
|
||||||
# Use the "canonical" command to parse the file and cell names,
|
|
||||||
# although if the cells have not been read in yet, then the
|
|
||||||
# original syntax of filename or {filename cellname} is required.
|
|
||||||
#
|
|
||||||
# "args" is passed to verify and may therefore contain only the
|
|
||||||
# value "-list" or nothing. If "-list", then output is returned
|
|
||||||
# as a nested list.
|
|
||||||
#----------------------------------------------------------------
|
|
||||||
|
|
||||||
proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
|
||||||
set dolist 0
|
|
||||||
set dojson 0
|
|
||||||
foreach arg $args {
|
|
||||||
if {$arg == "-list"} {
|
|
||||||
puts stdout "Generating list result"
|
|
||||||
set dolist 1
|
|
||||||
set lvs_final {}
|
|
||||||
} elseif {$arg == "-json"} {
|
|
||||||
puts stdout "Generating JSON file result"
|
|
||||||
set dolist 1
|
|
||||||
set dojson 1
|
|
||||||
set lvs_final {}
|
|
||||||
} elseif {$arg == "-blackbox"} {
|
|
||||||
puts stdout "Treating empty subcircuits as black-box cells"
|
|
||||||
netgen::model blackbox on
|
|
||||||
} elseif {$arg == "-full"} {
|
|
||||||
puts stdout "Using full symmetry breaking method"
|
|
||||||
netgen::symmetry full
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Allow name1 or name2 to be a list of {filename cellname},
|
|
||||||
# A single <filename>, or any valid_cellname form if the
|
|
||||||
# file has already been read.
|
|
||||||
|
|
||||||
if {[catch {set flist1 [canonical $name1]}]} {
|
|
||||||
if {[llength $name1] == 2} {
|
|
||||||
set file1 [lindex $name1 0]
|
|
||||||
set cell1 [lindex $name1 1]
|
|
||||||
} else {
|
|
||||||
set file1 $name1
|
|
||||||
set cell1 $name1
|
|
||||||
}
|
|
||||||
puts stdout "Reading netlist file $file1"
|
|
||||||
set fnum1 [netgen::readnet $file1]
|
|
||||||
} else {
|
|
||||||
set cell1 [lindex $flist1 0]
|
|
||||||
set fnum1 [lindex $flist1 1]
|
|
||||||
set flist1 [canonical $fnum1]
|
|
||||||
set file1 [lindex $flist1 0]
|
|
||||||
}
|
|
||||||
|
|
||||||
if {[catch {set flist2 [canonical $name2]}]} {
|
|
||||||
if {[llength $name2] == 2} {
|
|
||||||
set file2 [lindex $name2 0]
|
|
||||||
set cell2 [lindex $name2 1]
|
|
||||||
} else {
|
|
||||||
set file2 $name2
|
|
||||||
set cell2 $name2
|
|
||||||
}
|
|
||||||
puts stdout "Reading netlist file $file2"
|
|
||||||
set fnum2 [netgen::readnet $file2]
|
|
||||||
} else {
|
|
||||||
set cell2 [lindex $flist2 0]
|
|
||||||
set fnum2 [lindex $flist2 1]
|
|
||||||
set flist2 [canonical $fnum2]
|
|
||||||
set file2 [lindex $flist2 0]
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$fnum1 == $fnum2} {
|
|
||||||
puts stderr "Both cells are in the same netlist: Cannot compare!"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
set clist1 [cells list $fnum1]
|
|
||||||
set cidx [lsearch -regexp $clist1 ^$cell1$]
|
|
||||||
if {$cidx < 0} {
|
|
||||||
puts stderr "Cannot find cell $cell1 in file $file1"
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
set cell1 [lindex $clist1 $cidx]
|
|
||||||
}
|
|
||||||
set clist2 [cells list $fnum2]
|
|
||||||
set cidx [lsearch -regexp $clist2 ^$cell2$]
|
|
||||||
if {$cidx < 0} {
|
|
||||||
puts stderr "Cannot find cell $cell2 in file $file2"
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
set cell2 [lindex $clist2 $cidx]
|
|
||||||
}
|
|
||||||
|
|
||||||
netgen::compare assign "$fnum1 $cell1" "$fnum2 $cell2"
|
|
||||||
|
|
||||||
if {[file exists $setupfile]} {
|
|
||||||
puts stdout "Reading setup file $setupfile"
|
|
||||||
# Instead of sourcing the setup file, run each line so we can
|
|
||||||
# catch individual errors and not let them halt the LVS process
|
|
||||||
set perrors 0
|
|
||||||
if {![catch {open $setupfile r} fsetup]} {
|
|
||||||
set sline 0
|
|
||||||
set command {}
|
|
||||||
while {[gets $fsetup line] >= 0} {
|
|
||||||
incr sline
|
|
||||||
append command $line "\n"
|
|
||||||
if {[info complete $command]} {
|
|
||||||
if {[catch {uplevel 1 [list namespace eval netgen $command]} msg]} {
|
|
||||||
set msg [string trimright $msg "\n"]
|
|
||||||
puts stderr "Error $setupfile:$sline (ignoring), $msg"
|
|
||||||
incr perrors
|
|
||||||
}
|
|
||||||
set command {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close $fsetup
|
|
||||||
} else {
|
|
||||||
puts stdout "Error: Cannot read the setup file $setupfile"
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$perrors > 0} {
|
|
||||||
puts stdout "Warning: There were errors reading the setup file"
|
|
||||||
}
|
|
||||||
} elseif {[string first nosetup $setupfile] < 0} {
|
|
||||||
netgen::permute default ;# transistors and resistors
|
|
||||||
netgen::property default
|
|
||||||
}
|
|
||||||
|
|
||||||
if {[string first nolog $logfile] < 0} {
|
|
||||||
puts stdout "Comparison output logged to file $logfile"
|
|
||||||
netgen::log file $logfile
|
|
||||||
|
|
||||||
netgen::log start
|
|
||||||
netgen::log echo off
|
|
||||||
set dolog true
|
|
||||||
} else {
|
|
||||||
set dolog false
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$dolist == 1} {
|
|
||||||
set endval [netgen::compare -list hierarchical "$fnum1 $cell1" "$fnum2 $cell2"]
|
|
||||||
} else {
|
|
||||||
set endval [netgen::compare hierarchical "$fnum1 $cell1" "$fnum2 $cell2"]
|
|
||||||
}
|
|
||||||
if {$endval == {}} {
|
|
||||||
netgen::log put "No cells in queue!\n"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set properr {}
|
|
||||||
set pinsgood 0
|
|
||||||
while {$endval != {}} {
|
|
||||||
if {$dolist == 1} {
|
|
||||||
netgen::run -list converge
|
|
||||||
} else {
|
|
||||||
netgen::run converge
|
|
||||||
}
|
|
||||||
netgen::log echo on
|
|
||||||
if {[verify equivalent]} {
|
|
||||||
# Resolve automorphisms by pin and property
|
|
||||||
if {$dolist == 1} {
|
|
||||||
netgen::run -list resolve
|
|
||||||
} else {
|
|
||||||
netgen::run resolve
|
|
||||||
}
|
|
||||||
set uresult [verify unique]
|
|
||||||
if {$uresult == 0} {
|
|
||||||
netgen::log put " Networks match locally but not globally.\n"
|
|
||||||
netgen::log put " Probably connections are swapped.\n"
|
|
||||||
netgen::log put " Check the end of logfile ${logfile} for implicated nodes.\n"
|
|
||||||
if {$dolist == 1} {
|
|
||||||
verify -list nodes
|
|
||||||
} else {
|
|
||||||
verify nodes
|
|
||||||
}
|
|
||||||
|
|
||||||
# Flatten the non-matching subcircuit (but not the top-level cells)
|
|
||||||
if {[netgen::print queue] != {}} {
|
|
||||||
netgen::log put " Flattening non-matched subcircuits $endval"
|
|
||||||
netgen::flatten class "[lindex $endval 0] $fnum1"
|
|
||||||
netgen::flatten class "[lindex $endval 1] $fnum2"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
# Match pins
|
|
||||||
netgen::log echo off
|
|
||||||
if {$dolist == 1} {
|
|
||||||
set result [equate -list pins "$fnum1 [lindex $endval 0]" \
|
|
||||||
"$fnum2 [lindex $endval 1]"]
|
|
||||||
} else {
|
|
||||||
set result [equate pins "$fnum1 [lindex $endval 0]" \
|
|
||||||
"$fnum2 [lindex $endval 1]"]
|
|
||||||
}
|
|
||||||
if {$result != 0} {
|
|
||||||
equate classes "$fnum1 [lindex $endval 0]" \
|
|
||||||
"$fnum2 [lindex $endval 1]"
|
|
||||||
}
|
|
||||||
set pinsgood $result
|
|
||||||
netgen::log echo on
|
|
||||||
}
|
|
||||||
if {$uresult == 2} {lappend properr [lindex $endval 0]}
|
|
||||||
} else {
|
|
||||||
# Flatten the non-matching subcircuit (but not the top-level cells)
|
|
||||||
if {[netgen::print queue] != {}} {
|
|
||||||
netgen::log put " Flattening non-matched subcircuits $endval"
|
|
||||||
netgen::flatten class "[lindex $endval 0] $fnum1"
|
|
||||||
netgen::flatten class "[lindex $endval 1] $fnum2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
netgen::log echo off
|
|
||||||
if {$dolist == 1} {
|
|
||||||
catch {lappend lvs_final $lvs_out}
|
|
||||||
set lvs_out {}
|
|
||||||
set endval [netgen::compare -list hierarchical]
|
|
||||||
} else {
|
|
||||||
set endval [netgen::compare hierarchical]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
netgen::log echo off
|
|
||||||
puts stdout "Result: " nonewline
|
|
||||||
netgen::log echo on
|
|
||||||
if {$pinsgood == 0} {
|
|
||||||
netgen::log put "The top level cell failed pin matching.\n"
|
|
||||||
} else {
|
|
||||||
verify only
|
|
||||||
}
|
|
||||||
if {$properr != {}} {
|
|
||||||
netgen::log put "The following cells had property errors: $properr\n"
|
|
||||||
}
|
|
||||||
if {$dolog} {
|
|
||||||
netgen::log end
|
|
||||||
}
|
|
||||||
puts stdout "LVS Done."
|
|
||||||
if {$dojson == 1} {
|
|
||||||
netgen::convert_to_json $logfile $lvs_final
|
|
||||||
} elseif {$dolist == 1} {
|
|
||||||
return $lvs_final
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# It is important to make sure no netgen commands overlap with Tcl built-in
|
|
||||||
# commands, because otherwise the namespace import will fail.
|
|
||||||
|
|
||||||
proc pushnamespace { name } {
|
|
||||||
|
|
||||||
set y [namespace eval ${name} info commands ::${name}::*]
|
|
||||||
set z [info commands]
|
|
||||||
|
|
||||||
foreach v $y {
|
|
||||||
regsub -all {\*} $v {\\*} i
|
|
||||||
set x [namespace tail $i]
|
|
||||||
if {[lsearch $z $x] < 0} {
|
|
||||||
namespace import $i
|
|
||||||
} else {
|
|
||||||
puts "Warning: ${name} command '$x' use fully-qualified name '$v'"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proc popnamespace { name } {
|
|
||||||
set z [info commands]
|
|
||||||
set l [expr [string length ${name}] + 5]
|
|
||||||
|
|
||||||
while {[set v [lsearch $z ${name}_tcl_*]] >= 0} {
|
|
||||||
set y [lindex $z $v]
|
|
||||||
set w [string range $y $l end]
|
|
||||||
interp alias {} ::$w {}
|
|
||||||
rename ::$y ::$w
|
|
||||||
puts "Info: replacing ::$w with ::$y"
|
|
||||||
}
|
|
||||||
namespace forget ::${name}::*
|
|
||||||
}
|
|
||||||
|
|
||||||
set auto_noexec 1 ;# don't EVER call UNIX commands w/o "shell" in front
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# Cross-Application section
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Setup IRSIM assuming that the Tcl version is installed.
|
|
||||||
# We do not need to rename procedure irsim to NULL because it is
|
|
||||||
# redefined in a script, which simply overwrites the original.
|
|
||||||
|
|
||||||
proc irsim { args } {
|
|
||||||
global CAD_ROOT
|
|
||||||
set irsimscript [glob -nocomplain ${CAD_ROOT}/irsim/tcl/irsim.tcl]
|
|
||||||
if { ${irsimscript} == {} } {
|
|
||||||
puts stderr "\"irsim\" requires Tcl-based IRSIM version 9.6 or newer."
|
|
||||||
puts stderr "Could not find script \"irsim.tcl\". If IRSIM is installed in a"
|
|
||||||
puts stderr "place other than CAD_ROOT (=${CAD_ROOT}), use the command"
|
|
||||||
puts stderr "\"source <path>/irsim.tcl\" before doing \"irsim\"."
|
|
||||||
} else {
|
|
||||||
source $irsimscript
|
|
||||||
eval {irsim} $args
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Setup Xcircuit assuming that the Tcl version is installed.
|
|
||||||
|
|
||||||
proc xcircuit { args } {
|
|
||||||
global CAD_ROOT
|
|
||||||
global argc
|
|
||||||
global argv
|
|
||||||
set xcircscript [glob -nocomplain ${CAD_ROOT}/xcircuit*/xcircuit.tcl]
|
|
||||||
if { ${xcircscript} == {} } {
|
|
||||||
puts stderr "\"xcircuit\" requires Tcl-based XCircuit version 3.1 or newer."
|
|
||||||
puts stderr "Could not find script \"xcircuit.tcl\". If XCircuit is installed in a"
|
|
||||||
puts stderr "place other than CAD_ROOT (=${CAD_ROOT}), use the command"
|
|
||||||
puts stderr "\"source <path>/xcircuit.tcl\"."
|
|
||||||
} else {
|
|
||||||
# if there are multiple installed versions, choose the highest version.
|
|
||||||
if {[llength $xcircscript] > 1} {
|
|
||||||
set xcircscript [lindex [lsort -decreasing -dictionary $xcircscript] 0]
|
|
||||||
}
|
|
||||||
set argv $args
|
|
||||||
set argc [llength $args]
|
|
||||||
uplevel #0 source $xcircscript
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Setup Magic assuming that the Tcl version is installed.
|
|
||||||
|
|
||||||
proc magic { args } {
|
|
||||||
global CAD_ROOT
|
|
||||||
global argc
|
|
||||||
global argv
|
|
||||||
set magicscript [glob -nocomplain ${CAD_ROOT}/magic/tcl/magic.tcl]
|
|
||||||
if { ${magicscript} == {} } {
|
|
||||||
puts stderr "\"magic\" requires Tcl-based Magic version 7.2 or newer."
|
|
||||||
puts stderr "Could not find script \"magic.tcl\". If Magic is installed in a"
|
|
||||||
puts stderr "place other than CAD_ROOT (=${CAD_ROOT}), use the command"
|
|
||||||
puts stderr "\"source <path>/magic.tcl\"."
|
|
||||||
} else {
|
|
||||||
set argv $args
|
|
||||||
set argc [llength $args]
|
|
||||||
uplevel #0 source $magicscript
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
|
||||||
# Have we called netgen from tkcon or a clone thereof? If so, set NetgenConsole
|
|
||||||
#----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
if {! $UsingMagic } {
|
|
||||||
if {[lsearch [interp aliases] tkcon] != -1} {
|
|
||||||
set NetgenConsole tkcon
|
|
||||||
wm withdraw .
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pushnamespace netgen
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
|
||||||
# For now, if we are standalone, pop down the default Tk window.
|
|
||||||
# Sometime later we may wish to provide a standalone GUI frontend in Tk
|
|
||||||
# to improve upon the original X11 "xnetgen" frontend. If so, its
|
|
||||||
# definitions would go below.
|
|
||||||
|
|
||||||
if {! $UsingMagic } {
|
|
||||||
if {[lsearch [interp aliases] tkcon] != -1} {
|
|
||||||
if {[string range [wm title .] 0 3] == "wish"} {
|
|
||||||
wm withdraw .
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
|
||||||
# No-console mode drops "--" in front of the argument list and "-noc"
|
|
||||||
# is retained, so remove them. Internally, the console will be determined
|
|
||||||
# by checking for a slave interpreter, so there is no need for any
|
|
||||||
# action here other than removing the argument.
|
|
||||||
|
|
||||||
if {[lindex $argv 0] == "--"} {
|
|
||||||
incr argc -1
|
|
||||||
set argv [lrange $argv 1 end]
|
|
||||||
}
|
|
||||||
|
|
||||||
if {[string range [lindex $argv 0] 0 3] == "-noc"} {
|
|
||||||
incr argc -1
|
|
||||||
set argv [lrange $argv 1 end]
|
|
||||||
}
|
|
||||||
|
|
||||||
if {[string range [lindex $argv 0] 0 3] == "-bat"} {
|
|
||||||
incr argc -1
|
|
||||||
set argv [lrange $argv 1 end]
|
|
||||||
set batchmode 1
|
|
||||||
}
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
|
||||||
# Anything on the command line is assumed to be a netgen command to evaluate
|
|
||||||
|
|
||||||
if {[catch {eval $argv}]} {
|
|
||||||
puts stdout "$errorInfo"
|
|
||||||
}
|
|
||||||
if {$batchmode == 1} {quit}
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
|
||||||
# Netgen start function drops back to interpreter after initialization & setup
|
|
||||||
Loading…
Reference in New Issue