summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuben Undheim <ruben.undheim@gmail.com>2016-10-06 18:22:14 +0200
committerRuben Undheim <ruben.undheim@gmail.com>2016-10-06 18:22:14 +0200
commit196d5accdbc60e0202cfe1c5fcf97d0ac8041293 (patch)
tree0791fc769bfbaebfc0566c0615fcb1ba70d5180d
parent43af338557967a9ee35034b0ff9b81193c5b809a (diff)
Squashed commit of the following:
commit 29152637176f5792c41fef6cff1c27e5ca45f071 Merge: 1dea2e4 779d968 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Mon Oct 3 15:45:47 2016 -0400 Merge branch 'master' into work commit 779d968f3f42ec96cff466664708d8f6f404e206 Author: Tim Edwards <tim@vivaldi.tim.linglan.net> Date: Mon Oct 3 15:45:45 2016 -0400 Update at Mon Oct 3 15:45:45 EDT 2016 by tim commit 1dea2e4195af18e2a0a2da4d6655a44959892bb1 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Mon Oct 3 15:40:21 2016 -0400 Eliminated three more situations causing DRC errors. One was a simple round-off error issue. Of the other two, (1) offset + stubroute was missing the obvious choice of putting the offset away from the obstruction to satisfy DRC spacing instead of closing up the gap, if the former is a smaller offset. This prevents offsets that are so large that they start to interfere with objects in the track in front of the offset; and (2) handled cases where stub routes were put in places they were not needed, due to conservative rules. Used an error box check to find out if tap geometry covers the whole stub route, and eliminated those that are. commit cef9befaec89df0d7bfeaab47a95a17760f98159 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Sun Oct 2 19:45:44 2016 -0400 Removed the artificial constraint of 64 pins per macro set by fixed arrays, replacing them with dynamically allocated arrays. commit 5eb661f9fe244b923ce5b5e95b9ce337d4220187 Merge: 4ba184d 83f6883 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Sun Oct 2 17:51:37 2016 -0400 Merge branch 'master' into work commit 83f68836236a6392624d4da87b049c7dcad259a9 Author: Tim Edwards <tim@vivaldi.tim.linglan.net> Date: Sun Oct 2 17:51:36 2016 -0400 Update at Sun Oct 2 17:51:35 EDT 2016 by tim commit 4ba184d41801e08c6078725e5485a5b50ed6303c Author: Tim Edwards <tim@opencircuitdesign.com> Date: Sun Oct 2 17:51:01 2016 -0400 Set a limit check on the number of pins on a LEF macro. Needs to be allocated so that limits are not required. commit 702ed859d58696bb110106a41b06ce6c4efd6d73 Merge: e52b6c7 ad9448d Author: Tim Edwards <tim@opencircuitdesign.com> Date: Thu Sep 1 11:44:12 2016 -0400 Merge branch 'master' into work commit ad9448dabcc2da8a88529a696dcdc28f987c1561 Author: Tim Edwards <tim@vivaldi.tim.linglan.net> Date: Thu Sep 1 11:44:12 2016 -0400 Update at Thu Sep 1 11:44:12 EDT 2016 by tim commit e52b6c781e206779e5e52b87397fc24d9038cdb2 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Thu Sep 1 11:39:12 2016 -0400 Update to the way that qrouter handles via offsets for processes whose track pitch is so tight that vias cannot be placed on adjacent tracks without causing a DRC violation. The previous code did not properly track via-to-via spacing on all layers for all interacting via combinations. The new code is much longer but more straightforward and easier to read. commit b719c16cd466c94e5c14a0d8d573218a24163fee Merge: 5cc65d4 ea1af0f Author: Tim Edwards <tim@opencircuitdesign.com> Date: Wed Aug 31 07:35:22 2016 -0400 Merge branch 'master' into work commit ea1af0f287a455ab0c8ed63943890518bc06be2b Author: Tim Edwards <tim@vivaldi.tim.linglan.net> Date: Wed Aug 31 07:35:21 2016 -0400 Update at Wed Aug 31 07:35:21 EDT 2016 by tim commit 5cc65d43953e5890df9c40e62624e628de373029 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Wed Aug 31 07:34:04 2016 -0400 Major update to separate the tap offset and stub route distances so that they can be applied separately. No functional change, only change is to the database structure. commit 22aa4966c0dc595dd70674923cce4a24cf9e7b92 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Tue Aug 30 22:48:12 2016 -0400 Corrected a very obscure error that caused stub routes to get confused by a nearby node on the same net and flip directions, causing the stub to be unconnected and probably cause a DRC error as well. Very rare occurrence, but fixed now anyway. commit c79f5dab18eeb64f82092fde6035b7c4faffe0c5 Merge: b6dcb22 b83d3f9 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Tue Aug 30 10:03:31 2016 -0400 Merge branch 'master' into work commit b83d3f99f78a15534bcfe075261f2ab0f0fb3d24 Author: Tim Edwards <tim@vivaldi.tim.linglan.net> Date: Tue Aug 30 10:03:31 2016 -0400 Update at Tue Aug 30 10:03:31 EDT 2016 by tim commit b6dcb22912735507f41cb11403d7dfb180bb7ba6 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Tue Aug 30 10:02:20 2016 -0400 Corrected problems caused by introducing the non-Tk qrouternullg, which caused the options and arguments processing to get screwed up. Replaced the optarg mechanism with a coded argument processing routine. commit bb94dd731eda59f8dfc6206a468da25fe97ec312 Merge: 198324d 5c7dc0c Author: Tim Edwards <tim@opencircuitdesign.com> Date: Sun Aug 28 21:56:26 2016 -0400 Merge branch 'master' into work commit 5c7dc0c628eff923ea3cc0e31f16eb85dffd44e0 Author: Tim Edwards <tim@vivaldi.tim.linglan.net> Date: Sun Aug 28 21:56:25 2016 -0400 Update at Sun Aug 28 21:56:25 EDT 2016 by tim commit 198324dcbbd92bc785ad0f62bfea92b2bbbafb7e Author: Tim Edwards <tim@opencircuitdesign.com> Date: Sun Aug 28 21:55:19 2016 -0400 Removed two more sources of DRC errors, where track-to-track via spacing violations on the same net (causing metal notch errors) were being ignored due to trivial errors in the code. commit 8d3f09d28e991f4ff5062a661bed40917ef0f493 Merge: 844babc 884a212 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Fri Aug 26 20:50:02 2016 -0400 Merge branch 'master' into work commit 884a2126abbb8011c9beb969aa9cf75cb1e7677e Author: Tim Edwards <tim@vivaldi.tim.linglan.net> Date: Fri Aug 26 20:50:00 2016 -0400 Update at Fri Aug 26 20:50:00 EDT 2016 by tim commit 844babcc275e0932d4df55bfe7796b79be6c6091 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Fri Aug 26 20:48:40 2016 -0400 Corrected the segment write-back and net rip-up routines, both of which failed to preserve specific directional blocking information at a grid point when placing or removing a routed net. commit 5ca264ddccb3bc8617f7c60a3c0667e3a422ab5e Author: Tim Edwards <tim@opencircuitdesign.com> Date: Tue Aug 23 11:17:47 2016 -0400 Minor correction to supress tkcon in -nog mode; in other words, the -nog mode implies -noc, since the console is Tk-based. commit 8cecc9b0a0fdb224bed2f3b7f6b0b6060900e5e2 Merge: 11f09aa c5fb6b0 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Tue Aug 23 11:12:21 2016 -0400 Merge branch 'master' into work commit c5fb6b0f4b10a5d736e02df09e8cbbc1ec94d645 Author: Tim Edwards <tim@vivaldi.tim.linglan.net> Date: Tue Aug 23 11:12:20 2016 -0400 Update at Tue Aug 23 11:12:20 EDT 2016 by tim commit 11f09aa12b79454f33416fa831f391f2847fb8ce Author: Tim Edwards <tim@opencircuitdesign.com> Date: Tue Aug 23 11:11:02 2016 -0400 Added new executable "qrouternullg" that does not invoke Tk or bring up a graphics window. Only lightly tested, but appears to work. Invoke with "qrouter -nog" (-nographics). commit 972d325bf51e4ca8e80479723d39d1941f2778ad Merge: 200aa1b 3f9e856 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Tue Jul 26 22:31:38 2016 -0400 Merge branch 'master' into work commit 3f9e8565f57f4e378cf2d9c26eb48b8d8ce945a3 Author: Tim Edwards <tim@vivaldi.tim.linglan.net> Date: Tue Jul 26 22:31:37 2016 -0400 Update at Tue Jul 26 22:31:37 EDT 2016 by tim commit 200aa1b38d31c4f941c66ef8e103eedc6d6971c9 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Tue Jul 26 22:29:55 2016 -0400 Discovered that a recent change to the startup sequence causes the graphics initialization to be skipped if qrouter is started with no arguments. This is unnecessary and merely prevents the graphic display in the fully interactive mode. The problem is now fixed. commit 2adf8a91081ce826cdfe0bf25cb51e8b7db32649 Merge: a846f11 ae3fbed Author: Tim Edwards <tim@opencircuitdesign.com> Date: Thu Jul 21 11:12:19 2016 -0400 Merge branch 'master' into work commit ae3fbedd0cad99f24789744a13cc17c3392db1e8 Author: Tim Edwards <tim@vivaldi.tim.linglan.net> Date: Thu Jul 21 11:12:18 2016 -0400 Update at Thu Jul 21 11:12:18 EDT 2016 by tim commit a846f1110a488d3b5cb254975c8b8219ccb2f875 Author: Tim Edwards <tim@opencircuitdesign.com> Date: Thu Jul 21 11:12:10 2016 -0400 Updated configure script to extract paths for Tcl/Tk lib and include files from the strings passed to the compiler and linker, so that the file checks are not disjoint from the contents of tclConfig.sh and tkConfig.sh. commit 919bed4585a8e7d78dc8c1410560fe2b57f4e25f Author: Tim Edwards <tim@opencircuitdesign.com> Date: Tue Jul 12 21:23:59 2016 -0400 Corrected an error found by Ting-Ru Lin in which FIXED nets in the NETS section are treated like those in SPECIALNETS, but since the syntax of NETS and SPECIALNETS is different, this results in a parsing error. commit b35c1615bb80000b449f07b691a0c323282bfd35 Merge: 993d188 fc1753c Author: Tim Edwards <tim@opencircuitdesign.com> Date: Tue Jul 12 09:09:19 2016 -0400 Merge branch 'master' into work commit fc1753c9238435e96a58fff6691cc37a126b43ce Author: Tim Edwards <tim@vivaldi.tim.linglan.net> Date: Tue Jul 12 09:09:17 2016 -0400 Update at Tue Jul 12 09:09:17 EDT 2016 by tim commit 993d188b69fe79905f8056626108feab91ff580f Author: Tim Edwards <tim@opencircuitdesign.com> Date: Tue Jul 12 09:08:45 2016 -0400 Changed the non-Tcl version to print the same version message at the top of the run as the Tcl version does.
-rw-r--r--Makefile.in26
-rw-r--r--VERSION2
-rwxr-xr-xconfigure19
-rw-r--r--configure.in19
-rw-r--r--def.c29
-rw-r--r--graphics.c2
-rw-r--r--lef.c51
-rw-r--r--maze.c110
-rw-r--r--node.c815
-rw-r--r--qconfig.c25
-rw-r--r--qrouter.c932
-rw-r--r--qrouter.h77
-rwxr-xr-xqrouter.sh.in28
-rw-r--r--qrouter.tcl.in2
-rw-r--r--qrouternullg.c49
-rw-r--r--tclqrouter.c4
16 files changed, 1530 insertions, 660 deletions
diff --git a/Makefile.in b/Makefile.in
index 34b22fa..8b0d257 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -40,9 +40,12 @@ OBJECTS2 := $(patsubst %.c,%.o,$(SOURCES2))
SOURCES3 = qrouterexec.c
OBJECTS3 := $(patsubst %.c,%.o,$(SOURCES3))
-SOURCES4 = main.c
+SOURCES4 = qrouternullg.c
OBJECTS4 := $(patsubst %.c,%.o,$(SOURCES4))
+SOURCES5 = main.c
+OBJECTS5 := $(patsubst %.c,%.o,$(SOURCES5))
+
BININSTALL = ${prefix}/bin
LIBINSTALL = ${prefix}/${QROUTER_LIB_DIR}
EXTRA_DEFS = -DQROUTER_PATH=\"${LIBINSTALL}\"
@@ -53,7 +56,8 @@ install: $(INSTALL_TARGET)
nointerp: qrouter$(EXEEXT)
-tcl: qrouter.sh qrouter.tcl qrouter$(SHDLIB_EXT) qrouterexec$(EXEEXT)
+tcl: qrouter.sh qrouter.tcl qrouter$(SHDLIB_EXT) qrouterexec$(EXEEXT) \
+ qrouternullg$(EXEEXT)
qrouter.tcl: qrouter.tcl.in
sed -e '/LIBDIR/s#LIBDIR#${LIBINSTALL}#' \
@@ -67,8 +71,8 @@ qrouter.sh: qrouter.sh.in
qrouter.sh.in > $@
chmod 0755 $@
-qrouter$(EXEEXT): $(OBJECTS) $(OBJECTS4)
- $(CC) $(LDFLAGS) $(OBJECTS) $(OBJECTS4) -o $@ $(LIBS) -lm
+qrouter$(EXEEXT): $(OBJECTS) $(OBJECTS5)
+ $(CC) $(LDFLAGS) $(OBJECTS) $(OBJECTS5) -o $@ $(LIBS) -lm
qrouter$(SHDLIB_EXT): $(OBJECTS) $(OBJECTS2)
$(RM) qrouter$(SHDLIB_EXT)
@@ -84,18 +88,26 @@ qrouterexec$(EXEEXT): $(OBJECTS3)
${LD_RUN_PATH} ${LDFLAGS} ${X_PRE_LIBS} -lX11 ${X_LIBS} \
${X_EXTRA_LIBS} ${LIBS} ${EXTRA_LIB_SPECS} -lm
+qrouternullg$(EXEEXT): $(OBJECTS4)
+ $(RM) qrouternullg$(EXEEXT)
+ $(CC) ${CFLAGS} ${CPPFLAGS} ${DEFS} ${EXTRA_DEFS} \
+ ${SOURCES4} ${INC_SPECS} -o $@ ${LIB_SPECS} \
+ ${LD_RUN_PATH} ${LDFLAGS} ${LIBS} ${EXTRA_LIB_SPECS} -lm
+
install-nointerp:
@echo "Installing qrouter"
$(INSTALL) -d $(DESTDIR)${BININSTALL}
$(INSTALL) qrouter $(DESTDIR)${BININSTALL}
-install-tcl: qrouter.sh qrouter.tcl qrouter$(SHDLIB_EXT) qrouterexec$(EXEEXT)
+install-tcl: qrouter.sh qrouter.tcl qrouter$(SHDLIB_EXT) \
+ qrouterexec$(EXEEXT) qrouternullg$(EXEEXT)
@echo "Installing qrouter"
$(INSTALL) -d $(DESTDIR)${BININSTALL}
$(INSTALL) -d $(DESTDIR)${LIBINSTALL}
$(INSTALL) qrouter.sh $(DESTDIR)${BININSTALL}/qrouter
$(INSTALL) qrouter$(SHDLIB_EXT) $(DESTDIR)${LIBINSTALL}
$(INSTALL) qrouterexec$(EXEEXT) $(DESTDIR)${LIBINSTALL}
+ $(INSTALL) qrouternullg$(EXEEXT) $(DESTDIR)${LIBINSTALL}
$(INSTALL) console.tcl $(DESTDIR)${LIBINSTALL}
$(INSTALL) tkcon.tcl $(DESTDIR)${LIBINSTALL}
$(INSTALL) qrouter.tcl $(DESTDIR)${LIBINSTALL}
@@ -108,7 +120,9 @@ clean:
$(RM) $(OBJECTS2)
$(RM) $(OBJECTS3)
$(RM) $(OBJECTS4)
+ $(RM) $(OBJECTS5)
$(RM) qrouterexec$(EXEEXT)
+ $(RM) qrouternullg$(EXEEXT)
$(RM) qrouter$(EXEEXT)
$(RM) qrouter$(SHDLIB_EXT)
$(RM) qrouter.tcl
@@ -119,7 +133,9 @@ veryclean:
$(RM) $(OBJECTS2)
$(RM) $(OBJECTS3)
$(RM) $(OBJECTS4)
+ $(RM) $(OBJECTS5)
$(RM) qrouterexec$(EXEEXT)
+ $(RM) qrouternullg$(EXEEXT)
$(RM) qrouter$(EXEEXT)
$(RM) qrouter$(SHDLIB_EXT)
$(RM) qrouter.tcl
diff --git a/VERSION b/VERSION
index 6232e7e..936003c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.3.46
+1.3.57
diff --git a/configure b/configure
index b67afd9..9cc1d40 100755
--- a/configure
+++ b/configure
@@ -4350,6 +4350,25 @@ if test $usingTcl ; then
. $tcl_config_sh
. $tk_config_sh
+ # Should probably trust the config file contents, but this configure
+ # file checks the Tcl and Tk include and lib directories. Since
+ # the config file doesn't separate out the libraries from the strings
+ # passed to the compiler/linker, do it manually here.
+ #
+ # Extract TCL_LIB_DIR from TCL_LIB_SPEC
+ # Extract TK_LIB_DIR from TK_LIB_SPEC
+ # Extract TCL_INC_DIR from TCL_INCLUDE_SPEC
+ # Extract TK_INC_DIR from TK_INCLUDE_SPEC
+ #
+ # These will be the defaults unless overridden by configure command line
+
+ tmpstr=${TCL_LIB_SPEC#*-L}
+ TCL_LIB_DIR=${tmpstr% -l*}
+ tmpstr=${TK_LIB_SPEC#*-L}
+ TK_LIB_DIR=${tmpstr% -l*}
+ TCL_INC_DIR=${TCL_INCLUDE_SPEC#*-I}
+ TK_INC_DIR=${TK_INCLUDE_SPEC#*-I}
+
if test "$TCL_VERSION" = "7.6" -a "$TK_VERSION" = "4.2" ; then
:
elif test "$TCL_VERSION" = "7.5" -a "$TK_VERSION" = "4.1" ; then
diff --git a/configure.in b/configure.in
index ef28b34..e5dfa44 100644
--- a/configure.in
+++ b/configure.in
@@ -428,6 +428,25 @@ if test $usingTcl ; then
. $tcl_config_sh
. $tk_config_sh
+ # Should probably trust the config file contents, but this configure
+ # file checks the Tcl and Tk include and lib directories. Since
+ # the config file doesn't separate out the libraries from the strings
+ # passed to the compiler/linker, do it manually here.
+ #
+ # Extract TCL_LIB_DIR from TCL_LIB_SPEC
+ # Extract TK_LIB_DIR from TK_LIB_SPEC
+ # Extract TCL_INC_DIR from TCL_INCLUDE_SPEC
+ # Extract TK_INC_DIR from TK_INCLUDE_SPEC
+ #
+ # These will be the defaults unless overridden by configure command line
+
+ tmpstr=${TCL_LIB_SPEC#*-L}
+ TCL_LIB_DIR=${tmpstr% -l*}
+ tmpstr=${TK_LIB_SPEC#*-L}
+ TK_LIB_DIR=${tmpstr% -l*}
+ TCL_INC_DIR=${TCL_INCLUDE_SPEC#*-I}
+ TK_INC_DIR=${TK_INCLUDE_SPEC#*-I}
+
if test "$TCL_VERSION" = "7.6" -a "$TK_VERSION" = "4.2" ; then
:
elif test "$TCL_VERSION" = "7.5" -a "$TK_VERSION" = "4.1" ; then
diff --git a/def.c b/def.c
index 20eee3f..a86cdfa 100644
--- a/def.c
+++ b/def.c
@@ -178,7 +178,7 @@ DefAddRoutes(FILE *f, float oscale, NET net, char special)
}
paintLayer = routeLayer;
- if (special)
+ if (special == (char)1)
{
/* SPECIALNETS has the additional width */
token = LefNextToken(f, TRUE);
@@ -719,9 +719,14 @@ DefReadNets(FILE *f, char *sname, float oscale, char special, int total)
case DEF_NETPROP_COVER:
// Treat fixed nets like specialnets: read them
// in as obstructions, and write them out as-is.
+ // Use special = 2 so it is treated like a
+ // specialnet but does not expect the specialnet
+ // syntax (unless it is, in fact, a specialnet
+ // entry).
while (token && (*token != ';'))
- token = DefAddRoutes(f, oscale, net, (u_char)1);
+ token = DefAddRoutes(f, oscale, net,
+ (special == (char)0) ? (char)2 : special);
break;
}
}
@@ -953,6 +958,16 @@ DefReadPins(FILE *f, char *sname, float oscale, int total)
gate->width = gate->height = 0;
curlayer = -1;
+ /* Pin record has one node; allocate memory for it */
+ gate->taps = (DSEG *)malloc(sizeof(DSEG));
+ gate->noderec = (NODE *)malloc(sizeof(NODE));
+ gate->netnum = (int *)malloc(sizeof(int));
+ gate->node = (char **)malloc(sizeof(char *));
+ gate->taps[0] = NULL;
+ gate->noderec[0] = NULL;
+ gate->netnum[0] = -1;
+ gate->node[0] = NULL;
+
/* Now do a search through the line for "+" entries */
/* And process each. */
@@ -1031,6 +1046,10 @@ DefReadPins(FILE *f, char *sname, float oscale, int total)
else {
LefError("Pin %s is defined outside of route layer area!\n",
pinname);
+ free(gate->taps);
+ free(gate->noderec);
+ free(gate->netnum);
+ free(gate->node);
free(gate);
}
@@ -1404,7 +1423,6 @@ DefReadComponents(FILE *f, char *sname, float oscale, int total)
gate->gatename = strdup(usename);
gate->gatetype = gateginfo;
}
-
/* Now do a search through the line for "+" entries */
/* And process each. */
@@ -1450,6 +1468,11 @@ DefReadComponents(FILE *f, char *sname, float oscale, int total)
gate->nodes = gateginfo->nodes;
gate->obs = (DSEG)NULL;
+ gate->taps = (DSEG *)malloc(gate->nodes * sizeof(DSEG));
+ gate->noderec = (NODE *)malloc(gate->nodes * sizeof(NODE));
+ gate->netnum = (int *)malloc(gate->nodes * sizeof(int));
+ gate->node = (char **)malloc(gate->nodes * sizeof(char *));
+
for (i = 0; i < gate->nodes; i++) {
/* Let the node names point to the master cell; */
/* this is just diagnostic; allows us, for */
diff --git a/graphics.c b/graphics.c
index 00ac450..cd7cb4a 100644
--- a/graphics.c
+++ b/graphics.c
@@ -232,7 +232,7 @@ map_obstruction()
for (x = 0; x < NumChannelsX[i]; x++) {
xspc = (x + 1) * spacing - hspc;
for (y = 0; y < NumChannelsY[i]; y++) {
- if (NODESAV(x, y, i) != NULL) {
+ if (NODEIPTR(x, y, i) != NULL) {
yspc = height - (y + 1) * spacing - hspc;
XFillRectangle(dpy, buffer, gc, xspc, yspc,
spacing, spacing);
diff --git a/lef.c b/lef.c
index e1db69a..3c51832 100644
--- a/lef.c
+++ b/lef.c
@@ -1512,12 +1512,32 @@ LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale)
rectList = LefReadGeometry(lefMacro, f, oscale);
- if (pinName != NULL) lefMacro->node[pinNum] = strdup(pinName);
-
if (pinNum >= 0) {
- lefMacro->taps[pinNum] = rectList;
- if (lefMacro->nodes <= pinNum)
+ int nodealloc, orignodes;
+
+ if (lefMacro->nodes <= pinNum) {
+ orignodes = lefMacro->nodes;
lefMacro->nodes = (pinNum + 1);
+ nodealloc = lefMacro->nodes / 10;
+ if (nodealloc > (orignodes / 10)) {
+ nodealloc++;
+ lefMacro->taps = (DSEG *)realloc(lefMacro->taps,
+ nodealloc * 10 * sizeof(DSEG));
+ lefMacro->noderec = (NODE *)realloc(lefMacro->noderec,
+ nodealloc * 10 * sizeof(NODE));
+ lefMacro->netnum = (int *)realloc(lefMacro->netnum,
+ nodealloc * 10 * sizeof(int));
+ lefMacro->node = (char **)realloc(lefMacro->node,
+ nodealloc * 10 * sizeof(char *));
+ }
+ }
+ lefMacro->taps[pinNum] = rectList;
+ lefMacro->noderec[pinNum] = NULL;
+ lefMacro->netnum[pinNum] = -1;
+ if (pinName != NULL)
+ lefMacro->node[pinNum] = strdup(pinName);
+ else
+ lefMacro->node[pinNum] = NULL;
}
else {
while (rectList) {
@@ -1765,8 +1785,20 @@ LefReadMacro(f, mname, oscale)
lefMacro->obs = (DSEG)NULL;
lefMacro->next = GateInfo;
lefMacro->nodes = 0;
+ lefMacro->orient = 0;
+ // Allocate memory for up to 10 pins initially
+ lefMacro->taps = (DSEG *)malloc(10 * sizeof(DSEG));
+ lefMacro->noderec = (NODE *)malloc(10 * sizeof(NODE));
+ lefMacro->netnum = (int *)malloc(10 * sizeof(int));
+ lefMacro->node = (char **)malloc(10 * sizeof(char *));
+ // Fill in 1st entry
+ lefMacro->taps[0] = NULL;
+ lefMacro->noderec[0] = NULL;
+ lefMacro->node[0] = NULL;
+ lefMacro->netnum[0] = -1;
GateInfo = lefMacro;
+
/* Initial values */
pinNum = 0;
has_size = FALSE;
@@ -2509,20 +2541,27 @@ LefRead(inName)
gateginfo->gatetype = NULL;
gateginfo->gatename = (char *)malloc(4);
strcpy(gateginfo->gatename, "pin");
- gateginfo->node[0] = strdup("pin");
gateginfo->width = 0.0;
gateginfo->height = 0.0;
gateginfo->placedX = 0.0;
gateginfo->placedY = 0.0;
gateginfo->nodes = 1;
+ gateginfo->taps = (DSEG *)malloc(sizeof(DSEG));
+ gateginfo->noderec = (NODE *)malloc(sizeof(NODE));
+ gateginfo->netnum = (int *)malloc(sizeof(int));
+ gateginfo->node = (char **)malloc(sizeof(char *));
+
grect = (DSEG)malloc(sizeof(struct dseg_));
grect->x1 = grect->x2 = 0.0;
grect->y1 = grect->y2 = 0.0;
grect->next = (DSEG)NULL;
- gateginfo->taps[0] = grect;
gateginfo->obs = (DSEG)NULL;
gateginfo->next = GateInfo;
+ gateginfo->taps[0] = grect;
+ gateginfo->noderec[0] = NULL;
+ gateginfo->netnum[0] = -1;
+ gateginfo->node[0] = strdup("pin");
GateInfo = gateginfo;
}
PinMacro = gateginfo;
diff --git a/maze.c b/maze.c
index 37420f4..be909ca 100644
--- a/maze.c
+++ b/maze.c
@@ -236,6 +236,7 @@ void clear_non_source_targets(NET net, POINT *pushlist)
void clear_target_node(NODE node)
{
int x, y, lay;
+ NODEINFO lnode;
DPOINT ntap;
PROUTE *Pr;
@@ -245,7 +246,8 @@ void clear_target_node(NODE node)
lay = ntap->layer;
x = ntap->gridx;
y = ntap->gridy;
- if ((lay < Pinlayers) && (NODELOC(x, y, lay) == (NODE)NULL))
+ if ((lay < Pinlayers) && (((lnode = NODEIPTR(x, y, lay)) == NULL)
+ || (lnode->nodeloc == NULL)))
continue;
Pr = &OBS2VAL(x, y, lay);
Pr->flags = 0;
@@ -257,10 +259,11 @@ void clear_target_node(NODE node)
x = ntap->gridx;
y = ntap->gridy;
- if (( (lay < Pinlayers)
- && NODESAV(x, y, lay) == (NODE)NULL)
- || NODESAV(x, y, lay) != node)
- continue;
+ if (lay < Pinlayers) {
+ lnode = NODEIPTR(x, y, lay);
+ if (lnode == NULL) continue;
+ if (lnode->nodesav != node) continue;
+ }
Pr = &OBS2VAL(x, y, lay);
Pr->flags = 0;
@@ -352,6 +355,7 @@ int set_node_to_net(NODE node, int newflags, POINT *pushlist, SEG bbox, u_char s
int x, y, lay, obsnet = 0;
int result = 0;
u_char found_one = (u_char)0;
+ NODEINFO lnode;
POINT gpoint;
DPOINT ntap;
PROUTE *Pr;
@@ -433,9 +437,11 @@ int set_node_to_net(NODE node, int newflags, POINT *pushlist, SEG bbox, u_char s
// Don't process extended areas if they coincide with other nodes.
- if ((lay < Pinlayers) && (NODESAV(x, y, lay) == (NODE)NULL
- || NODESAV(x, y, lay) != node))
- continue;
+ if (lay < Pinlayers) {
+ lnode = NODEIPTR(x, y, lay);
+ if (lnode == NULL) continue;
+ if (lnode->nodesav != node) continue;
+ }
Pr = &OBS2VAL(x, y, lay);
if (Pr->flags & PR_SOURCE) {
@@ -552,6 +558,7 @@ int set_route_to_net(NET net, ROUTE rt, int newflags, POINT *pushlist,
{
int x, y, lay;
int result = 0;
+ NODEINFO lnode;
POINT gpoint;
SEG seg;
NODE n2;
@@ -591,7 +598,8 @@ int set_route_to_net(NET net, ROUTE rt, int newflags, POINT *pushlist,
// If we found another node connected to the route,
// then process it, too.
- n2 = (lay >= Pinlayers) ? NULL : NODELOC(x, y, lay);
+ lnode = (lay >= Pinlayers) ? NULL : NODEIPTR(x, y, lay);
+ n2 = (lnode) ? lnode->nodeloc : NULL;
if ((n2 != (NODE)NULL) && (n2 != net->netnodes)) {
if (newflags == PR_SOURCE) clear_target_node(n2);
result = set_node_to_net(n2, newflags, pushlist, bbox, stage);
@@ -772,12 +780,13 @@ NETLIST find_colliding(NET net, int *ripnum)
/* */
/* If argument "restore" is TRUE, then at each node, restore */
/* the crossover cost by attaching the node back to the */
-/* NODELOC array. */
+/* Nodeinfo array. */
/*--------------------------------------------------------------*/
u_char ripup_net(NET net, u_char restore)
{
int thisnet, oldnet, x, y, lay, dir;
+ NODEINFO lnode;
NODE node;
ROUTE rt;
SEG seg;
@@ -805,10 +814,11 @@ u_char ripup_net(NET net, u_char restore)
// were routed over obstructions to reach off-grid
// taps are returned to obstructions.
- if ((lay >= Pinlayers) || NODESAV(x, y, lay) == (NODE)NULL) {
+ if ((lay >= Pinlayers) || ((lnode = NODEIPTR(x, y, lay)) == NULL)
+ || (lnode->nodesav == NULL)) {
dir = OBSVAL(x, y, lay) & PINOBSTRUCTMASK;
if (dir == 0)
- OBSVAL(x, y, lay) = 0;
+ OBSVAL(x, y, lay) = OBSVAL(x, y, lay) & BLOCKED_MASK;
else
OBSVAL(x, y, lay) = NO_NET | dir;
}
@@ -855,7 +865,7 @@ u_char ripup_net(NET net, u_char restore)
}
}
- // For each net node tap, restore the node pointer on NODELOC
+ // For each net node tap, restore the node pointer on Nodeinfo->nodeloc
// so that crossover costs are again applied to routes over this node
// tap.
@@ -865,8 +875,10 @@ u_char ripup_net(NET net, u_char restore)
lay = ntap->layer;
x = ntap->gridx;
y = ntap->gridy;
- if (lay < Pinlayers)
- NODELOC(x, y, lay) = NODESAV(x, y, lay);
+ if (lay < Pinlayers) {
+ lnode = NODEIPTR(x, y, lay);
+ if (lnode) lnode->nodeloc = lnode->nodesav;
+ }
}
}
}
@@ -916,7 +928,7 @@ int eval_pt(GRIDP *ept, u_char flags, u_char stage)
int thiscost = 0;
int netnum;
NODE node;
- NODEINFO nodeptr;
+ NODEINFO nodeptr, lnode;
NETLIST nl;
PROUTE *Pr, *Pt;
GRIDP newpt;
@@ -961,7 +973,7 @@ int eval_pt(GRIDP *ept, u_char flags, u_char stage)
// 2nd stage allows routes to cross existing routes
netnum = Pr->prdata.net;
if (stage && (netnum < MAXNETNUM)) {
- if ((newpt.lay < Pinlayers) && (nodeptr->nodesav != NULL))
+ if ((newpt.lay < Pinlayers) && nodeptr && (nodeptr->nodesav != NULL))
return 0; // But cannot route over terminals!
// Is net k in the "noripup" list? If so, don't route it */
@@ -981,7 +993,7 @@ int eval_pt(GRIDP *ept, u_char flags, u_char stage)
thiscost += ConflictCost;
}
else if (stage && (netnum == DRC_BLOCKAGE)) {
- if ((newpt.lay < Pinlayers) && (nodeptr->nodesav != NULL))
+ if ((newpt.lay < Pinlayers) && nodeptr && (nodeptr->nodesav != NULL))
return 0; // But cannot route over terminals!
// Position does not contain the net number, so we have to
@@ -1059,7 +1071,8 @@ int eval_pt(GRIDP *ept, u_char flags, u_char stage)
// so that routing over it could block it entirely.
if ((newpt.lay > 0) && (newpt.lay < Pinlayers)) {
- if ((node = NODELOC(newpt.x, newpt.y, newpt.lay - 1)) != (NODE)NULL) {
+ if (((lnode = NODEIPTR(newpt.x, newpt.y, newpt.lay - 1)) != (NODEINFO)NULL)
+ && ((node = lnode->nodeloc) != NULL)) {
Pt = &OBS2VAL(newpt.x, newpt.y, newpt.lay - 1);
if (!(Pt->flags & PR_TARGET) && !(Pt->flags & PR_SOURCE)) {
if (node->taps && (node->taps->next == NULL))
@@ -1083,7 +1096,8 @@ int eval_pt(GRIDP *ept, u_char flags, u_char stage)
}
}
if (((newpt.lay + 1) < Pinlayers) && (newpt.lay < Num_layers - 1)) {
- if ((node = NODELOC(newpt.x, newpt.y, newpt.lay + 1)) != (NODE)NULL) {
+ if (((lnode = NODEIPTR(newpt.x, newpt.y, newpt.lay + 1)) != (NODEINFO)NULL)
+ && ((node = lnode->nodeloc) != NULL)) {
Pt = &OBS2VAL(newpt.x, newpt.y, newpt.lay + 1);
if (!(Pt->flags & PR_TARGET) && !(Pt->flags & PR_SOURCE)) {
if (node->taps && (node->taps->next == NULL))
@@ -1160,11 +1174,14 @@ int eval_pt(GRIDP *ept, u_char flags, u_char stage)
void writeback_segment(SEG seg, int netnum)
{
double dist;
- int i, layer;
+ int i, layer, dir;
u_int sobs;
+ NODEINFO lnode;
if (seg->segtype == ST_VIA) {
- OBSVAL(seg->x1, seg->y1, seg->layer + 1) = netnum;
+ /* Preserve blocking information */
+ dir = OBSVAL(seg->x1, seg->y1, seg->layer + 1) & BLOCKED_MASK;
+ OBSVAL(seg->x1, seg->y1, seg->layer + 1) = netnum | dir;
if (needblock[seg->layer + 1] & VIABLOCKX) {
if ((seg->x1 < (NumChannelsX[seg->layer + 1] - 1)) &&
(OBSVAL(seg->x1 + 1, seg->y1, seg->layer + 1) & NETNUM_MASK) == 0)
@@ -1190,8 +1207,9 @@ void writeback_segment(SEG seg, int netnum)
layer = (seg->layer == 0) ? 0 : seg->layer - 1;
sobs = OBSVAL(seg->x1, seg->y1, seg->layer);
if (sobs & OFFSET_TAP) {
- dist = STUBVAL(seg->x1, seg->y1, seg->layer);
- if (sobs & STUBROUTE_EW) {
+ lnode = NODEIPTR(seg->x1, seg->y1, seg->layer);
+ dist = lnode->offset;
+ if (lnode->flags && NI_OFFSET_EW) {
if ((dist > 0) && (seg->x1 < (NumChannelsX[seg->layer] - 1))) {
OBSVAL(seg->x1 + 1, seg->y1, seg->layer) |= DRC_BLOCKAGE;
OBSVAL(seg->x1 + 1, seg->y1, seg->layer + 1) |= DRC_BLOCKAGE;
@@ -1201,7 +1219,7 @@ void writeback_segment(SEG seg, int netnum)
OBSVAL(seg->x1 - 1, seg->y1, seg->layer + 1) |= DRC_BLOCKAGE;
}
}
- else if (sobs & STUBROUTE_NS) {
+ else if (lnode->flags && NI_OFFSET_NS) {
if ((dist > 0) && (seg->y1 < (NumChannelsY[seg->layer] - 1))) {
OBSVAL(seg->x1, seg->y1 + 1, seg->layer) |= DRC_BLOCKAGE;
OBSVAL(seg->x1, seg->y1 + 1, seg->layer + 1) |= DRC_BLOCKAGE;
@@ -1215,7 +1233,8 @@ void writeback_segment(SEG seg, int netnum)
}
for (i = seg->x1; ; i += (seg->x2 > seg->x1) ? 1 : -1) {
- OBSVAL(i, seg->y1, seg->layer) = netnum;
+ dir = OBSVAL(i, seg->y1, seg->layer) & BLOCKED_MASK;
+ OBSVAL(i, seg->y1, seg->layer) = netnum | dir;
if (needblock[seg->layer] & ROUTEBLOCKY) {
if ((seg->y1 < (NumChannelsY[seg->layer] - 1)) &&
(OBSVAL(i, seg->y1 + 1, seg->layer) & NETNUM_MASK) == 0)
@@ -1236,8 +1255,9 @@ void writeback_segment(SEG seg, int netnum)
if (seg->y1 < (NumChannelsY[layer] - 1)) {
sobs = OBSVAL(i, seg->y1 + 1, layer);
if ((sobs & OFFSET_TAP) && !(sobs & ROUTED_NET)) {
- if (sobs & STUBROUTE_NS) {
- dist = STUBVAL(i, seg->y1 + 1, layer);
+ lnode = NODEIPTR(i, seg->y1 + 1, layer);
+ if (lnode->flags & NI_OFFSET_NS) {
+ dist = lnode->offset;
if (dist < 0) {
OBSVAL(i, seg->y1 + 1, layer) |= DRC_BLOCKAGE;
}
@@ -1247,8 +1267,9 @@ void writeback_segment(SEG seg, int netnum)
if (seg->y1 > 0) {
sobs = OBSVAL(i, seg->y1 - 1, layer);
if ((sobs & OFFSET_TAP) && !(sobs & ROUTED_NET)) {
- if (sobs & STUBROUTE_NS) {
- dist = STUBVAL(i, seg->y1 - 1, layer);
+ lnode = NODEIPTR(i, seg->y1 - 1, layer);
+ if (lnode->flags & NI_OFFSET_NS) {
+ dist = lnode->offset;
if (dist > 0) {
OBSVAL(i, seg->y1 - 1, layer) |= DRC_BLOCKAGE;
}
@@ -1258,7 +1279,8 @@ void writeback_segment(SEG seg, int netnum)
if (i == seg->x2) break;
}
for (i = seg->y1; ; i += (seg->y2 > seg->y1) ? 1 : -1) {
- OBSVAL(seg->x1, i, seg->layer) = netnum;
+ dir = OBSVAL(seg->x1, i, seg->layer) & BLOCKED_MASK;
+ OBSVAL(seg->x1, i, seg->layer) = netnum | dir;
if (needblock[seg->layer] & ROUTEBLOCKX) {
if ((seg->x1 < (NumChannelsX[seg->layer] - 1)) &&
(OBSVAL(seg->x1 + 1, i, seg->layer) & NETNUM_MASK) == 0)
@@ -1275,8 +1297,9 @@ void writeback_segment(SEG seg, int netnum)
if (seg->x1 < (NumChannelsX[layer] - 1)) {
sobs = OBSVAL(seg->x1 + 1, i, layer);
if ((sobs & OFFSET_TAP) && !(sobs & ROUTED_NET)) {
- if (sobs & STUBROUTE_EW) {
- dist = STUBVAL(seg->x1 + 1, i, layer);
+ lnode = NODEIPTR(seg->x1 + 1, i, layer);
+ if (lnode->flags & NI_OFFSET_EW) {
+ dist = lnode->offset;
if (dist < 0) {
OBSVAL(seg->x1 + 1, i, layer) |= DRC_BLOCKAGE;
}
@@ -1286,8 +1309,9 @@ void writeback_segment(SEG seg, int netnum)
if (seg->x1 > 0) {
sobs = OBSVAL(seg->x1 - 1, i, layer);
if ((sobs & OFFSET_TAP) && !(sobs & ROUTED_NET)) {
- if (sobs & STUBROUTE_EW) {
- dist = STUBVAL(seg->x1 - 1, i, layer);
+ lnode = NODEIPTR(seg->x1 - 1, i, layer);
+ if (lnode->flags & NI_OFFSET_EW) {
+ dist = lnode->offset;
if (dist > 0) {
OBSVAL(seg->x1 - 1, i, layer) |= DRC_BLOCKAGE;
}
@@ -1316,6 +1340,7 @@ void writeback_segment(SEG seg, int netnum)
int commit_proute(ROUTE rt, GRIDP *ept, u_char stage)
{
SEG seg, lseg;
+ NODEINFO lnode1, lnode2;
int lay2, rval;
int dx = -1, dy = -1, dl;
u_int netnum, netobs1, netobs2, dir1, dir2;
@@ -1853,6 +1878,9 @@ int commit_proute(ROUTE rt, GRIDP *ept, u_char stage)
netobs1 = OBSVAL(seg->x1, seg->y1, seg->layer);
netobs2 = OBSVAL(seg->x2, seg->y2, lay2);
+ lnode1 = (seg->layer < Pinlayers) ? NODEIPTR(seg->x1, seg->y1, seg->layer) : NULL;
+ lnode2 = (lay2 < Pinlayers) ? NODEIPTR(seg->x2, seg->y2, lay2) : NULL;
+
dir1 = netobs1 & PINOBSTRUCTMASK;
dir2 = netobs2 & PINOBSTRUCTMASK;
@@ -1898,8 +1926,8 @@ int commit_proute(ROUTE rt, GRIDP *ept, u_char stage)
if (lseg && ((lseg->segtype & (ST_VIA | ST_OFFSET_END)) ==
(ST_VIA | ST_OFFSET_END)))
if (seg->segtype != ST_VIA)
- if (((seg->x1 == seg->x2) && (dir1 & STUBROUTE_NS)) ||
- ((seg->y1 == seg->y2) && (dir1 & STUBROUTE_EW)))
+ if (((seg->x1 == seg->x2) && (lnode1->flags & NI_OFFSET_NS)) ||
+ ((seg->y1 == seg->y2) && (lnode1->flags & NI_OFFSET_EW)))
seg->segtype |= ST_OFFSET_START;
// Check if the route ends are offset. If so, add flags. The segment
@@ -1909,8 +1937,8 @@ int commit_proute(ROUTE rt, GRIDP *ept, u_char stage)
// the offset via, and does not extend past it.
if (dir1 & OFFSET_TAP) {
- if (((seg->x1 == seg->x2) && (dir1 & STUBROUTE_NS)) ||
- ((seg->y1 == seg->y2) && (dir1 & STUBROUTE_EW)))
+ if (((seg->x1 == seg->x2) && (lnode1->flags & NI_OFFSET_NS)) ||
+ ((seg->y1 == seg->y2) && (lnode1->flags & NI_OFFSET_EW)))
seg->segtype |= ST_OFFSET_START;
// An offset on a via needs to be applied to the previous route
@@ -1918,8 +1946,8 @@ int commit_proute(ROUTE rt, GRIDP *ept, u_char stage)
// in the same direction as the wire.
if (lseg && (seg->segtype & ST_VIA) && !(lseg->segtype & ST_VIA))
- if (((lseg->x1 == lseg->x2) && (dir2 & STUBROUTE_NS)) ||
- ((lseg->y1 == lseg->y2) && (dir2 & STUBROUTE_EW)))
+ if (((lseg->x1 == lseg->x2) && lnode2 && (lnode2->flags & NI_OFFSET_NS)) ||
+ ((lseg->y1 == lseg->y2) && lnode2 && (lnode2->flags & NI_OFFSET_EW)))
lseg->segtype |= ST_OFFSET_END;
}
diff --git a/node.c b/node.c
index 91b34b0..4cf0a84 100644
--- a/node.c
+++ b/node.c
@@ -327,6 +327,44 @@ void defineRouteTree(NET net)
}
/*--------------------------------------------------------------*/
+/* SetNodeinfo -- */
+/* Allocate a NODEINFO record and put it in the Nodeinfo */
+/* array at position (gridx, gridy, d->layer). Return the */
+/* pointer to the location. */
+/*--------------------------------------------------------------*/
+
+NODEINFO
+SetNodeinfo(int gridx, int gridy, int layer)
+{
+ NODEINFO *lnodeptr;
+
+ lnodeptr = &NODEIPTR(gridx, gridy, layer);
+ if (*lnodeptr == NULL) {
+ *lnodeptr = (NODEINFO)calloc(1, sizeof(struct nodeinfo_));
+ }
+ return *lnodeptr;
+}
+
+/*--------------------------------------------------------------*/
+/* FreeNodeinfo -- */
+/* Free a NODEINFO record at array Nodeinfo position */
+/* (gridx, gridy, d->layer). Set the position pointer to */
+/* NULL. */
+/*--------------------------------------------------------------*/
+
+void
+FreeNodeinfo(int gridx, int gridy, int layer)
+{
+ NODEINFO *lnodeptr;
+ lnodeptr = &NODEIPTR(gridx, gridy, layer);
+
+ if (*lnodeptr != NULL) {
+ free(*lnodeptr);
+ *lnodeptr = NULL;
+ }
+}
+
+/*--------------------------------------------------------------*/
/* print_nodes - show the nodes list */
/* ARGS: filename to print to
RETURNS: nothing
@@ -435,6 +473,7 @@ void
count_reachable_taps()
{
NODE node;
+ NODEINFO lnode;
GATE g;
DSEG ds;
int l, i, j;
@@ -444,15 +483,17 @@ count_reachable_taps()
for (l = 0; l < Num_layers; l++) {
for (j = 0; j < NumChannelsX[l] * NumChannelsY[l]; j++) {
- node = Nodeinfo[l][j].nodeloc;
- if (node != NULL) {
+ if (Nodeinfo[l][j]) {
+ node = Nodeinfo[l][j]->nodeloc;
+ if (node != NULL) {
- // Redundant check; if Obs has NO_NET set, then
- // Nodeinfo.nodeloc for that position should already
- // be NULL
+ // Redundant check; if Obs has NO_NET set, then
+ // Nodeinfo->nodeloc for that position should already
+ // be NULL
- if (!(Obs[l][j] & NO_NET))
- node->numtaps++;
+ if (!(Obs[l][j] & NO_NET))
+ node->numtaps++;
+ }
}
}
}
@@ -502,8 +543,9 @@ count_reachable_taps()
(OBSVAL(gridx, gridy, ds->layer)
& BLOCKED_MASK)
| (u_int)node->netnum;
- NODELOC(gridx, gridy, ds->layer) = node;
- NODESAV(gridx, gridy, ds->layer) = node;
+ lnode = SetNodeinfo(gridx, gridy, ds->layer);
+ lnode->nodeloc = node;
+ lnode->nodesav = node;
node->numtaps++;
}
}
@@ -520,9 +562,10 @@ count_reachable_taps()
/* cleanly within the tap geometry, then allow it. */
double dist, mindist;
- int dir, tapx, tapy, tapl;
+ int dir, mask, tapx, tapy, tapl;
/* Initialize mindist to a large value */
+ mask = 0;
mindist = PitchX[Num_layers - 1] + PitchY[Num_layers - 1];
dir = 0; /* Indicates no solution found */
@@ -572,7 +615,8 @@ count_reachable_taps()
(dy + deltay - EPS < ds->y2)) {
if (dist < fabs(mindist)) {
mindist = dist;
- dir = STUBROUTE_EW;
+ mask = STUBROUTE;
+ dir = NI_STUB_EW;
tapx = gridx;
tapy = gridy;
tapl = ds->layer;
@@ -588,7 +632,8 @@ count_reachable_taps()
(dy + deltay - EPS < ds->y2)) {
if (dist < fabs(mindist)) {
mindist = -dist;
- dir = STUBROUTE_EW;
+ mask = STUBROUTE;
+ dir = NI_STUB_EW;
tapx = gridx;
tapy = gridy;
tapl = ds->layer;
@@ -604,7 +649,8 @@ count_reachable_taps()
(dy - dist - deltay + EPS > ds->y1)) {
if (dist < fabs(mindist)) {
mindist = -dist;
- dir = STUBROUTE_NS;
+ mask = STUBROUTE;
+ dir = NI_STUB_NS;
tapx = gridx;
tapy = gridy;
tapl = ds->layer;
@@ -620,7 +666,8 @@ count_reachable_taps()
(dy + dist + deltay - EPS < ds->y2)) {
if (dist < fabs(mindist)) {
mindist = dist;
- dir = STUBROUTE_NS;
+ mask = STUBROUTE;
+ dir = NI_STUB_NS;
tapx = gridx;
tapy = gridy;
tapl = ds->layer;
@@ -636,7 +683,7 @@ count_reachable_taps()
}
/* Was a solution found? */
- if (dir != 0) {
+ if (mask != 0) {
// Grid position is clear for placing a via
Fprintf(stderr, "Tap position (%d, %d) appears to be"
@@ -646,10 +693,12 @@ count_reachable_taps()
OBSVAL(tapx, tapy, tapl) =
(OBSVAL(tapx, tapy, tapl) & BLOCKED_MASK)
- | dir | (u_int)node->netnum;
- NODELOC(tapx, tapy, tapl) = node;
- NODESAV(tapx, tapy, tapl) = node;
- STUBVAL(tapx, tapy, tapl) = dist;
+ | mask | (u_int)node->netnum;
+ lnode = SetNodeinfo(tapx, tapy, tapl);
+ lnode->nodeloc = node;
+ lnode->nodesav = node;
+ lnode->stub = dist;
+ lnode->flags |= dir;
node->numtaps++;
}
}
@@ -740,6 +789,7 @@ void check_variable_pitch(int l, int *hptr, int *vptr)
void create_obstructions_from_variable_pitch(void)
{
int l, vnum, hnum, x, y;
+ NODEINFO lnode;
for (l = 0; l < Num_layers; l++) {
@@ -764,20 +814,25 @@ void create_obstructions_from_variable_pitch(void)
// If the grid position itself is a node, don't restrict
// routing based on variable pitch.
- if (NODELOC(x, y, l) != NULL) continue;
+ if (((lnode = NODEIPTR(x, y, l)) != NULL) && (lnode->nodeloc != NULL))
+ continue;
// If there is a node in an adjacent grid then allow
// routing from that direction.
- if ((x > 0) && NODELOC(x - 1, y, l) != NULL)
+ if ((x > 0) && ((lnode = NODEIPTR(x - 1, y, l)) != NULL) &&
+ (lnode->nodeloc != NULL))
OBSVAL(x, y, l) = BLOCKED_MASK & ~BLOCKED_W;
- else if ((y > 0) && NODELOC(x , y - 1, l) != NULL)
+ else if ((y > 0) && ((lnode = NODEIPTR(x , y - 1, l)) != NULL) &&
+ (lnode->nodeloc != NULL))
OBSVAL(x, y, l) = BLOCKED_MASK & ~BLOCKED_S;
else if ((x < NumChannelsX[l] - 1)
- && NODELOC(x + 1, y, l) != NULL)
+ && ((lnode = NODEIPTR(x + 1, y, l)) != NULL) &&
+ (lnode->nodeloc != NULL))
OBSVAL(x, y, l) = BLOCKED_MASK & ~BLOCKED_E;
else if ((y < NumChannelsY[l] - 1)
- && NODELOC(x, y + 1, l) != NULL)
+ && ((lnode = NODEIPTR(x, y + 1, l)) != NULL) &&
+ (lnode->nodeloc != NULL))
OBSVAL(x, y, l) = BLOCKED_MASK & ~BLOCKED_N;
else
OBSVAL(x, y, l) = NO_NET;
@@ -791,7 +846,7 @@ void create_obstructions_from_variable_pitch(void)
/* disable_gridpos() --- */
/* Render the position at (x, y, lay) unroutable by */
/* setting its Obs[] entry to NO_NET and removing it from */
-/* the Nodeinfo.nodeloc and Nodeinfo.nodesav records. */
+/* the Nodeinfo->nodeloc and Nodeinfo->nodesav records. */
/*--------------------------------------------------------------*/
static void
@@ -800,18 +855,18 @@ disable_gridpos(int x, int y, int lay)
int apos = OGRID(x, y, lay);
Obs[lay][apos] = (u_int)(NO_NET | OBSTRUCT_MASK);
- Nodeinfo[lay][apos].nodeloc = NULL;
- Nodeinfo[lay][apos].nodesav = NULL;
- Nodeinfo[lay][apos].stub = 0.0;
+ if (Nodeinfo[lay][apos]) {
+ free(Nodeinfo[lay][apos]);
+ Nodeinfo[lay][apos] = NULL;
+ }
}
/*--------------------------------------------------------------*/
/* count_pinlayers()--- */
-/* Check which layers have non-NULL Nodeinfo.nodeloc, */
-/* Nodeinfo.nodesav, and Nodeinfo.stub entries. Then set */
-/* "Pinlayers" and free all the unused layers. This saves */
-/* a lot of memory, especially when the number of routing */
-/* layers becomes large. */
+/* Check which layers have non-NULL Nodeinfo entries. */
+/* Then set "Pinlayers" and free all the unused layers. */
+/* This saves a lot of memory, especially when the number */
+/* of routing layers becomes large. */
/*--------------------------------------------------------------*/
void
@@ -822,7 +877,7 @@ count_pinlayers(void)
Pinlayers = 0;
for (l = 0; l < Num_layers; l++) {
for (j = 0; j < NumChannelsX[l] * NumChannelsY[l]; j++) {
- if (Nodeinfo[l][j].nodesav != NULL) {
+ if (Nodeinfo[l][j]) {
Pinlayers = l + 1;
break;
}
@@ -850,9 +905,11 @@ check_obstruct(int gridx, int gridy, DSEG ds, double dx, double dy)
{
u_int *obsptr;
float dist;
+ NODEINFO lnode;
obsptr = &(OBSVAL(gridx, gridy, ds->layer));
dist = OBSINFO(gridx, gridy, ds->layer);
+ lnode = NODEIPTR(gridx, gridy, ds->layer);
// Grid point is inside obstruction + halo.
*obsptr |= NO_NET;
@@ -1315,9 +1372,10 @@ void expand_tap_geometry(void)
void create_obstructions_inside_nodes(void)
{
NODE node;
+ NODEINFO lnode;
GATE g;
DSEG ds;
- u_int dir, k;
+ u_int dir, mask, k;
int i, gridx, gridy;
double dx, dy;
float dist, xdist;
@@ -1383,7 +1441,8 @@ void create_obstructions_inside_nodes(void)
// Duplicate tap point, or pre-existing
// route. Don't re-process it if it is
// a duplicate.
- if (NODELOC(gridx, gridy, ds->layer) != NULL) {
+ if (((lnode = NODEIPTR(gridx, gridy, ds->layer)) != NULL)
+ && (lnode->nodeloc != NULL)) {
gridy++;
continue;
}
@@ -1413,6 +1472,7 @@ void create_obstructions_inside_nodes(void)
// of a tap rectangle corner can violate metal
// width rules, and so should declare a stub.
+ mask = 0;
dir = 0;
dist = 0.0;
xdist = 0.5 * LefGetRouteWidth(ds->layer);
@@ -1423,12 +1483,14 @@ void create_obstructions_inside_nodes(void)
if ((ds->x2 - dx) > (ds->y2 - dy)) {
// West-pointing stub
- dir = STUBROUTE_EW;
+ mask = STUBROUTE;
+ dir = NI_STUB_EW;
dist = ds->x2 - dx - 2.0 * xdist;
}
else {
// South-pointing stub
- dir = STUBROUTE_NS;
+ mask = STUBROUTE;
+ dir = NI_STUB_NS;
dist = ds->y2 - dy - 2.0 * xdist;
}
@@ -1438,12 +1500,14 @@ void create_obstructions_inside_nodes(void)
if ((ds->x2 - dx) > (dy - ds->y1)) {
// West-pointing stub
- dir = STUBROUTE_EW;
+ mask = STUBROUTE;
+ dir = NI_STUB_EW;
dist = ds->x2 - dx - 2.0 * xdist;
}
else {
// North-pointing stub
- dir = STUBROUTE_NS;
+ mask = STUBROUTE;
+ dir = NI_STUB_NS;
dist = ds->y1 - dy + 2.0 * xdist;
}
}
@@ -1454,12 +1518,14 @@ void create_obstructions_inside_nodes(void)
if ((dx - ds->x1) > (ds->y2 - dy)) {
// East-pointing stub
- dir = STUBROUTE_EW;
+ mask = STUBROUTE;
+ dir = NI_STUB_EW;
dist = ds->x1 - dx + 2.0 * xdist;
}
else {
// South-pointing stub
- dir = STUBROUTE_NS;
+ mask = STUBROUTE;
+ dir = NI_STUB_NS;
dist = ds->y2 - dy - 2.0 * xdist;
}
@@ -1469,12 +1535,14 @@ void create_obstructions_inside_nodes(void)
if ((dx - ds->x2) > (dy - ds->y1)) {
// East-pointing stub
- dir = STUBROUTE_EW;
+ mask = STUBROUTE;
+ dir = NI_STUB_EW;
dist = ds->x1 - dx + 2.0 * xdist;
}
else {
// North-pointing stub
- dir = STUBROUTE_NS;
+ mask = STUBROUTE;
+ dir = NI_STUB_NS;
dist = ds->y1 - dy + 2.0 * xdist;
}
}
@@ -1482,11 +1550,12 @@ void create_obstructions_inside_nodes(void)
OBSVAL(gridx, gridy, ds->layer)
= (OBSVAL(gridx, gridy, ds->layer)
- & BLOCKED_MASK) | (u_int)node->netnum | dir;
- NODELOC(gridx, gridy, ds->layer) = node;
- NODESAV(gridx, gridy, ds->layer) = node;
- STUBVAL(gridx, gridy, ds->layer) = dist;
-
+ & BLOCKED_MASK) | (u_int)node->netnum | mask;
+ lnode = SetNodeinfo(gridx, gridy, ds->layer);
+ lnode->nodeloc = node;
+ lnode->nodesav = node;
+ lnode->stub = dist;
+ lnode->flags |= dir;
}
else if ((orignet & NO_NET) && ((orignet & OBSTRUCT_MASK)
!= OBSTRUCT_MASK)) {
@@ -1500,9 +1569,7 @@ void create_obstructions_inside_nodes(void)
if (k & PINOBSTRUCTMASK) {
if ((k & ROUTED_NET_MASK) != (u_int)node->netnum) {
OBSVAL(gridx, gridy, ds->layer + 1) = NO_NET;
- NODELOC(gridx, gridy, ds->layer + 1) = (NODE)NULL;
- NODESAV(gridx, gridy, ds->layer + 1) = (NODE)NULL;
- STUBVAL(gridx, gridy, ds->layer + 1) = (float)0.0;
+ FreeNodeinfo(gridx, gridy, ds->layer + 1);
}
}
}
@@ -1547,9 +1614,10 @@ void create_obstructions_inside_nodes(void)
void create_obstructions_outside_nodes(void)
{
NODE node, n2;
+ NODEINFO lnode;
GATE g;
DSEG ds;
- u_int dir, k;
+ u_int dir, mask, k;
int i, gridx, gridy;
double dx, dy, deltax, deltay;
float dist, xdist;
@@ -1668,8 +1736,9 @@ void create_obstructions_outside_nodes(void)
// the obstruction to resolve the DRC error.
// Make sure we have marked this as a node.
- NODELOC(gridx, gridy, ds->layer) = node;
- NODESAV(gridx, gridy, ds->layer) = node;
+ lnode = SetNodeinfo(gridx, gridy, ds->layer);
+ lnode->nodeloc = node;
+ lnode->nodesav = node;
OBSVAL(gridx, gridy, ds->layer)
= (OBSVAL(gridx, gridy, ds->layer)
& BLOCKED_MASK) | (u_int)node->netnum;
@@ -1677,9 +1746,9 @@ void create_obstructions_outside_nodes(void)
if (orignet & OBSTRUCT_N) {
offd = -(sdisty - OBSINFO(gridx, gridy, ds->layer));
if (offd >= -offmaxy[ds->layer]) {
- STUBVAL(gridx, gridy, ds->layer) = offd;
- OBSVAL(gridx, gridy, ds->layer) |=
- (STUBROUTE_NS | OFFSET_TAP);
+ OBSVAL(gridx, gridy, ds->layer) |= OFFSET_TAP;
+ lnode->offset = offd;
+ lnode->flags |= NI_OFFSET_NS;
/* If position above has obstruction, then */
/* add up/down block to prevent vias. */
@@ -1695,9 +1764,9 @@ void create_obstructions_outside_nodes(void)
else if (orignet & OBSTRUCT_S) {
offd = sdisty - OBSINFO(gridx, gridy, ds->layer);
if (offd <= offmaxy[ds->layer]) {
- STUBVAL(gridx, gridy, ds->layer) = offd;
- OBSVAL(gridx, gridy, ds->layer) |=
- (STUBROUTE_NS | OFFSET_TAP);
+ OBSVAL(gridx, gridy, ds->layer) |= OFFSET_TAP;
+ lnode->offset = offd;
+ lnode->flags |= NI_OFFSET_NS;
/* If position above has obstruction, then */
/* add up/down block to prevent vias. */
@@ -1714,9 +1783,9 @@ void create_obstructions_outside_nodes(void)
else if (orignet & OBSTRUCT_E) {
offd = -(sdistx - OBSINFO(gridx, gridy, ds->layer));
if (offd >= -offmaxx[ds->layer]) {
- STUBVAL(gridx, gridy, ds->layer) = offd;
- OBSVAL(gridx, gridy, ds->layer) |=
- (STUBROUTE_EW | OFFSET_TAP);
+ OBSVAL(gridx, gridy, ds->layer) |= OFFSET_TAP;
+ lnode->offset = offd;
+ lnode->flags |= NI_OFFSET_EW;
/* If position above has obstruction, then */
/* add up/down block to prevent vias. */
@@ -1732,9 +1801,9 @@ void create_obstructions_outside_nodes(void)
else if (orignet & OBSTRUCT_W) {
offd = sdistx - OBSINFO(gridx, gridy, ds->layer);
if (offd <= offmaxx[ds->layer]) {
- STUBVAL(gridx, gridy, ds->layer) = offd;
- OBSVAL(gridx, gridy, ds->layer) |=
- (STUBROUTE_EW | OFFSET_TAP);
+ OBSVAL(gridx, gridy, ds->layer) |= OFFSET_TAP;
+ lnode->offset = offd;
+ lnode->flags |= NI_OFFSET_EW;
/* If position above has obstruction, then */
/* add up/down block to prevent vias. */
@@ -1802,18 +1871,22 @@ void create_obstructions_outside_nodes(void)
xdist = 0.5 * LefGetRouteWidth(ds->layer);
n2 = NULL;
- if (ds->layer > 0)
- n2 = NODELOC(gridx, gridy, ds->layer - 1);
- if (n2 == NULL)
- n2 = NODELOC(gridx, gridy, ds->layer);
-
+ if (ds->layer > 0) {
+ lnode = NODEIPTR(gridx, gridy, ds->layer - 1);
+ n2 = (lnode) ? lnode->nodeloc : NULL;
+ }
+ if (n2 == NULL) {
+ lnode = NODEIPTR(gridx, gridy, ds->layer);
+ n2 = (lnode) ? lnode->nodeloc : NULL;
+ }
else {
// Watch out for the case where a tap crosses
// over a different tap. Don't treat the tap
// on top as if it is not there!
NODE n3;
- n3 = NODELOC(gridx, gridy, ds->layer);
+ lnode = NODEIPTR(gridx, gridy, ds->layer);
+ n3 = (lnode) ? lnode->nodeloc : NULL;
if (n3 != NULL && n3 != node) n2 = n3;
}
@@ -1827,7 +1900,8 @@ void create_obstructions_outside_nodes(void)
// stub information will show how to adjust the
// route position to cleanly attach to the port.
- dir = STUBROUTE_X;
+ mask = STUBROUTE;
+ dir = NI_STUB_NS | NI_STUB_EW;
dist = 0.0;
if (((k & ROUTED_NET_MASK) != (u_int)node->netnum)
@@ -1851,7 +1925,8 @@ void create_obstructions_outside_nodes(void)
((k & OBSTRUCT_MASK) == OBSTRUCT_E)) {
dist = sdist - LefGetRouteKeepout(ds->layer);
if ((dx - ds->x2 + dist) < xdist) {
- dir = STUBROUTE_EW | OFFSET_TAP;
+ mask = OFFSET_TAP;
+ dir = NI_OFFSET_EW;
if ((ds->layer < Num_layers - 1) &&
(gridx > 0) &&
@@ -1865,7 +1940,8 @@ void create_obstructions_outside_nodes(void)
((k & OBSTRUCT_MASK) == OBSTRUCT_W)) {
dist = LefGetRouteKeepout(ds->layer) - sdist;
if ((ds->x1 - dx - dist) < xdist) {
- dir = STUBROUTE_EW | OFFSET_TAP;
+ mask = OFFSET_TAP;
+ dir = NI_OFFSET_EW;
if ((ds->layer < Num_layers - 1) &&
gridx <
@@ -1883,7 +1959,8 @@ void create_obstructions_outside_nodes(void)
((k & OBSTRUCT_MASK) == OBSTRUCT_N)) {
dist = sdist - LefGetRouteKeepout(ds->layer);
if ((dy - ds->y2 + dist) < xdist) {
- dir = STUBROUTE_NS | OFFSET_TAP;
+ mask = OFFSET_TAP;
+ dir = NI_OFFSET_NS;
if ((ds->layer < Num_layers - 1) &&
gridy <
@@ -1898,7 +1975,8 @@ void create_obstructions_outside_nodes(void)
((k & OBSTRUCT_MASK) == OBSTRUCT_S)) {
dist = LefGetRouteKeepout(ds->layer) - sdist;
if ((ds->y1 - dy - dist) < xdist) {
- dir = STUBROUTE_NS | OFFSET_TAP;
+ mask = OFFSET_TAP;
+ dir = NI_OFFSET_NS;
if ((ds->layer < Num_layers - 1) &&
(gridy > 0) &&
@@ -1909,7 +1987,7 @@ void create_obstructions_outside_nodes(void)
}
}
}
- // Otherwise, dir is left as STUBROUTE_X
+ // Otherwise, dir is left as NI_STUB_MASK
}
else {
@@ -1925,7 +2003,8 @@ void create_obstructions_outside_nodes(void)
if ((dy - ds->y2) <= xdist &&
(ds->y1 - dy) <= xdist) {
// Within reach of tap rectangle
- dir = STUBROUTE_EW;
+ mask = STUBROUTE;
+ dir = NI_STUB_EW;
dist = ds->x2 - dx;
if (dy < (ds->y2 - xdist) &&
dy > (ds->y1 + xdist)) {
@@ -1943,7 +2022,8 @@ void create_obstructions_outside_nodes(void)
if ((dy - ds->y2) <= xdist &&
(ds->y1 - dy) <= xdist) {
// Within reach of tap rectangle
- dir = STUBROUTE_EW;
+ mask = STUBROUTE;
+ dir = NI_STUB_EW;
dist = ds->x1 - dx;
if (dy < (ds->y2 - xdist) &&
dy > (ds->y1 + xdist)) {
@@ -1961,7 +2041,8 @@ void create_obstructions_outside_nodes(void)
if ((dx - ds->x2) <= xdist &&
(ds->x1 - dx) <= xdist) {
// Within reach of tap rectangle
- dir = STUBROUTE_NS;
+ mask = STUBROUTE;
+ dir = NI_STUB_NS;
dist = ds->y2 - dy;
if (dx < (ds->x2 - xdist) &&
dx > (ds->x1 + xdist)) {
@@ -1979,7 +2060,8 @@ void create_obstructions_outside_nodes(void)
if ((dx - ds->x2) <= xdist &&
(ds->x1 - dx) <= xdist) {
// Within reach of tap rectangle
- dir = STUBROUTE_NS;
+ mask = STUBROUTE;
+ dir = NI_STUB_NS;
dist = ds->y1 - dy;
if (dx < (ds->x2 - xdist) &&
dx > (ds->x1 + xdist)) {
@@ -1991,7 +2073,7 @@ void create_obstructions_outside_nodes(void)
}
}
- if (dir == STUBROUTE_X) {
+ if ((mask == STUBROUTE) && (dir == NI_STUB_MASK)) {
// Outside of pin at a corner. First, if one
// direction is too far away to connect to a
@@ -2000,14 +2082,16 @@ void create_obstructions_outside_nodes(void)
if (dx < ds->x1 - xdist || dx > ds->x2 + xdist) {
if (dy >= ds->y1 - xdist &&
dy <= ds->y2 + xdist) {
- dir = STUBROUTE_EW;
+ mask = STUBROUTE;
+ dir = NI_STUB_EW;
dist = (float)(((ds->x1 + ds->x2) / 2.0)
- dx);
}
}
else if (dy < ds->y1 - xdist ||
dy > ds->y2 + xdist) {
- dir = STUBROUTE_NS;
+ mask = STUBROUTE;
+ dir = NI_STUB_NS;
dist = (float)(((ds->y1 + ds->y2) / 2.0) - dy);
}
@@ -2015,37 +2099,165 @@ void create_obstructions_outside_nodes(void)
// to reach the pin by moving in any single
// direction. To be pedantic, we could define
// some jogged stub, but for now, we just call
- // the point unroutable (leave dir = STUBROUTE_X)
+ // the point unroutable (leave dir = NI_STUB_MASK)
+
+ // To do: Apply offset + stub
}
}
+ // Additional checks on stub routes
+
// Stub distances of <= 1/2 route width are
// unnecessary, so don't create them.
- if (dir == STUBROUTE_NS || dir == STUBROUTE_EW)
- if (fabs(dist) < (xdist + EPS)) {
+ if (mask == STUBROUTE && (dir == NI_STUB_NS
+ || dir == NI_STUB_EW) &&
+ (fabs(dist) < (xdist + EPS))) {
+ mask = 0;
+ dir = 0;
+ dist = 0.0;
+ }
+ else if (mask == STUBROUTE && (dir == NI_STUB_NS
+ || dir == NI_STUB_EW)) {
+ struct dseg_ de;
+ DSEG ds2;
+ u_char errbox = TRUE;
+
+ // Additional check: Sometimes the above
+ // checks put stub routes where they are
+ // not needed because the stub is completely
+ // covered by other tap geometry. Take the
+ // stub area and remove parts covered by
+ // other tap rectangles. If the entire
+ // stub is gone, then don't put a stub here.
+
+ if (dir == NI_STUB_NS) {
+ de.x1 = dx - xdist;
+ de.x2 = dx + xdist;
+ if (dist > 0) {
+ de.y1 = dy + xdist;
+ de.y2 = dy + dist;
+ }
+ else {
+ de.y1 = dy + dist;
+ de.y2 = dy - xdist;
+ }
+ }
+ if (dir == NI_STUB_EW) {
+ de.y1 = dy - xdist;
+ de.y2 = dy + xdist;
+ if (dist > 0) {
+ de.x1 = dx + xdist;
+ de.x2 = dx + dist;
+ }
+ else {
+ de.x1 = dx + dist;
+ de.x2 = dx - xdist;
+ }
+ }
+
+ // For any tap that overlaps the
+ // stub extension box, remove that
+ // part of the box.
+
+ for (ds2 = g->taps[i]; ds2; ds2 = ds2->next) {
+ if (ds2->layer != ds->layer) continue;
+
+ if (ds2->x1 <= de.x1 && ds2->x2 >= de.x2 &&
+ ds2->y1 <= de.y1 && ds2->y2 >= de.y2) {
+ errbox = FALSE; // Completely covered
+ break;
+ }
+
+ // Look for partial coverage. Note that any
+ // change can cause a change in the original
+ // two conditionals, so we have to keep
+ // evaluating those conditionals.
+
+ if (ds2->x1 < de.x2 && ds2->x2 > de.x1)
+ if (ds2->y1 < de.y2 && ds2->y2 > de.y1)
+ // if (ds2->x1 < de.x1 - EPS &&
+ if (ds2->x1 < de.x1 + EPS &&
+ ds2->x2 < de.x2 - EPS) {
+ de.x1 = ds2->x2;
+ if (ds2->x2 >= ds->x2) errbox = FALSE;
+ }
+
+ if (ds2->x1 < de.x2 && ds2->x2 > de.x1)
+ if (ds2->y1 < de.y2 && ds2->y2 > de.y1)
+ // if (ds2->x2 > de.x2 + EPS &&
+ if (ds2->x2 > de.x2 - EPS &&
+ ds2->x1 > de.x1 + EPS) {
+ de.x2 = ds2->x1;
+ if (ds2->x1 <= ds->x1) errbox = FALSE;
+ }
+
+ if (ds2->x1 < de.x2 && ds2->x2 > de.x1)
+ if (ds2->y1 < de.y2 && ds2->y2 > de.y1)
+ // if (ds2->y1 < de.y1 - EPS &&
+ if (ds2->y1 < de.y1 + EPS &&
+ ds2->y2 < de.y2 - EPS) {
+ de.y1 = ds2->y2;
+ if (ds2->y2 >= ds->y2) errbox = FALSE;
+ }
+
+ if (ds2->x1 < de.x2 && ds2->x2 > de.x1)
+ if (ds2->y1 < de.y2 && ds2->y2 > de.y1)
+ // if (ds2->y2 > de.y2 + EPS &&
+ if (ds2->y2 > de.y2 - EPS &&
+ ds2->y1 > de.y1 + EPS) {
+ de.y2 = ds2->y1;
+ if (ds2->y1 <= ds->y1) errbox = FALSE;
+ }
+ }
+
+ // If nothing is left of the stub box,
+ // then remove the stub.
+
+ if (errbox == FALSE) {
+ mask = 0;
dir = 0;
- dist = 0.0;
+ dist = 0;
}
+ }
+
+ lnode = SetNodeinfo(gridx, gridy, ds->layer);
- if ((k < Numnets) && (dir != STUBROUTE_X)) {
+ if ((k < Numnets) && (dir != NI_STUB_MASK)) {
OBSVAL(gridx, gridy, ds->layer)
= (OBSVAL(gridx, gridy, ds->layer)
- & BLOCKED_MASK) | (u_int)g->netnum[i] | dir;
- NODELOC(gridx, gridy, ds->layer) = node;
- NODESAV(gridx, gridy, ds->layer) = node;
+ & BLOCKED_MASK) | (u_int)g->netnum[i] | mask;
+ lnode->nodeloc = node;
+ lnode->nodesav = node;
+ lnode->flags |= dir;
}
else if ((OBSVAL(gridx, gridy, ds->layer)
& NO_NET) != 0) {
// Keep showing an obstruction, but add the
// direction info and log the stub distance.
- OBSVAL(gridx, gridy, ds->layer) |= dir;
+ OBSVAL(gridx, gridy, ds->layer) |= mask;
+ lnode->flags |= dir;
}
else {
OBSVAL(gridx, gridy, ds->layer)
- |= (dir | (g->netnum[i] & ROUTED_NET_MASK));
+ |= (mask | (g->netnum[i] & ROUTED_NET_MASK));
+ lnode->flags |= dir;
+ }
+ if ((mask & STUBROUTE) != 0) {
+ lnode->stub = dist;
+ }
+ else if (((mask & OFFSET_TAP) != 0) || (dist != 0.0)) {
+ lnode->offset = dist;
+ }
+
+ // Remove entries with NI_STUB_MASK---these
+ // are blocked-in taps that are not routable
+ // without causing DRC violations (formerly
+ // called STUBROUTE_X).
+
+ if (dir == NI_STUB_MASK) {
+ disable_gridpos(gridx, gridy, ds->layer);
}
- STUBVAL(gridx, gridy, ds->layer) = dist;
}
else if (epass == 0) {
@@ -2082,9 +2294,10 @@ void create_obstructions_outside_nodes(void)
// node record. This will probably need
// revisiting.
- if ((k & (STUBROUTE_X | OFFSET_TAP)) != 0)
+ if ((k & PINOBSTRUCTMASK) != 0)
disable_gridpos(gridx, gridy, ds->layer);
- else if (NODESAV(gridx, gridy, ds->layer) != NULL) {
+ else if ((lnode = NODEIPTR(gridx, gridy, ds->layer))
+ != NULL && (lnode->nodesav != NULL)) {
u_char no_offsets = TRUE;
int offset_net;
@@ -2102,9 +2315,11 @@ void create_obstructions_outside_nodes(void)
ds->layer, 0);
dist = ds->x2 - dx + xdist +
LefGetRouteSpacing(ds->layer);
- dir = (STUBROUTE_EW | OFFSET_TAP);
- STUBVAL(gridx, gridy, ds->layer) = dist;
- OBSVAL(gridx, gridy, ds->layer) |= dir;
+ mask = OFFSET_TAP;
+ dir = NI_OFFSET_EW;
+ OBSVAL(gridx, gridy, ds->layer) |= mask;
+ lnode->offset = dist;
+ lnode->flags |= dir;
no_offsets = FALSE;
if ((ds->layer < Num_layers - 1) &&
@@ -2124,9 +2339,11 @@ void create_obstructions_outside_nodes(void)
ds->layer, 0);
dist = ds->x1 - dx - xdist -
LefGetRouteSpacing(ds->layer);
- dir = (STUBROUTE_EW | OFFSET_TAP);
- STUBVAL(gridx, gridy, ds->layer) = dist;
- OBSVAL(gridx, gridy, ds->layer) |= dir;
+ mask = OFFSET_TAP;
+ dir = NI_OFFSET_EW;
+ OBSVAL(gridx, gridy, ds->layer) |= mask;
+ lnode->offset = dist;
+ lnode->flags |= dir;
no_offsets = FALSE;
if ((ds->layer < Num_layers - 1) &&
@@ -2147,9 +2364,11 @@ void create_obstructions_outside_nodes(void)
ds->layer, 1);
dist = ds->y2 - dy + xdist +
LefGetRouteSpacing(ds->layer);
- dir = (STUBROUTE_NS | OFFSET_TAP);
- STUBVAL(gridx, gridy, ds->layer) = dist;
- OBSVAL(gridx, gridy, ds->layer) |= dir;
+ mask = OFFSET_TAP;
+ dir = NI_OFFSET_NS;
+ OBSVAL(gridx, gridy, ds->layer) |= mask;
+ lnode->offset = dist;
+ lnode->flags |= dir;
no_offsets = FALSE;
if ((ds->layer < Num_layers - 1) &&
@@ -2169,9 +2388,11 @@ void create_obstructions_outside_nodes(void)
ds->layer, 1);
dist = ds->y1 - dy - xdist -
LefGetRouteSpacing(ds->layer);
- dir = (STUBROUTE_NS | OFFSET_TAP);
- STUBVAL(gridx, gridy, ds->layer) = dist;
- OBSVAL(gridx, gridy, ds->layer) |= dir;
+ mask = OFFSET_TAP;
+ dir = NI_OFFSET_NS;
+ OBSVAL(gridx, gridy, ds->layer) |= mask;
+ lnode->offset = dist;
+ lnode->flags |= dir;
no_offsets = FALSE;
if ((ds->layer < Num_layers - 1) &&
@@ -2204,35 +2425,40 @@ void create_obstructions_outside_nodes(void)
!= node->netnum) && ((othernet == 0) ||
(othernet == (u_int)node->netnum))) {
+ lnode = NODEIPTR(gridx, gridy, ds->layer);
xdist = 0.5 * LefGetViaWidth(ds->layer, ds->layer, 0);
if ((dy + xdist + LefGetRouteSpacing(ds->layer) >
ds->y1) && (dy + xdist < ds->y1)) {
if ((dx - xdist < ds->x2) &&
(dx + xdist > ds->x1) &&
- (STUBVAL(gridx, gridy, ds->layer)
+ (lnode == NULL || lnode->stub
== 0.0)) {
- STUBVAL(gridx, gridy, ds->layer) = ds->y1 - dy;
OBSVAL(gridx, gridy, ds->layer)
= (OBSVAL(gridx, gridy, ds->layer)
& BLOCKED_MASK) |
- node->netnum | STUBROUTE_NS;
- NODELOC(gridx, gridy, ds->layer) = node;
- NODESAV(gridx, gridy, ds->layer) = node;
+ node->netnum | STUBROUTE;
+ lnode = SetNodeinfo(gridx, gridy, ds->layer);
+ lnode->nodeloc = node;
+ lnode->nodesav = node;
+ lnode->stub = ds->y1 - dy;
+ lnode->flags |= NI_STUB_NS;
}
}
if ((dy - xdist - LefGetRouteSpacing(ds->layer) <
ds->y2) && (dy - xdist > ds->y2)) {
if ((dx - xdist < ds->x2) &&
(dx + xdist > ds->x1) &&
- (STUBVAL(gridx, gridy, ds->layer)
+ (lnode == NULL || lnode->stub
== 0.0)) {
- STUBVAL(gridx, gridy, ds->layer) = ds->y2 - dy;
OBSVAL(gridx, gridy, ds->layer)
= (OBSVAL(gridx, gridy, ds->layer)
& BLOCKED_MASK) |
- node->netnum | STUBROUTE_NS;
- NODELOC(gridx, gridy, ds->layer) = node;
- NODESAV(gridx, gridy, ds->layer) = node;
+ node->netnum | STUBROUTE;
+ lnode = SetNodeinfo(gridx, gridy, ds->layer);
+ lnode->nodeloc = node;
+ lnode->nodesav = node;
+ lnode->stub = ds->y2 - dy;
+ lnode->flags |= NI_STUB_NS;
}
}
@@ -2241,30 +2467,34 @@ void create_obstructions_outside_nodes(void)
ds->x1) && (dx + xdist < ds->x1)) {
if ((dy - xdist < ds->y2) &&
(dy + xdist > ds->y1) &&
- (STUBVAL(gridx, gridy, ds->layer)
+ (lnode == NULL || lnode->stub
== 0.0)) {
- STUBVAL(gridx, gridy, ds->layer) = ds->x1 - dx;
OBSVAL(gridx, gridy, ds->layer)
= (OBSVAL(gridx, gridy, ds->layer)
& BLOCKED_MASK) |
- node->netnum | STUBROUTE_EW;
- NODELOC(gridx, gridy, ds->layer) = node;
- NODESAV(gridx, gridy, ds->layer) = node;
+ node->netnum | STUBROUTE;
+ lnode = SetNodeinfo(gridx, gridy, ds->layer);
+ lnode->nodeloc = node;
+ lnode->nodesav = node;
+ lnode->stub = ds->x1 - dx;
+ lnode->flags |= NI_STUB_EW;
}
}
if ((dx - xdist - LefGetRouteSpacing(ds->layer) <
ds->x2) && (dx - xdist > ds->x2)) {
if ((dy - xdist < ds->y2) &&
(dy + xdist > ds->y1) &&
- (STUBVAL(gridx, gridy, ds->layer)
+ (lnode == NULL || lnode->stub
== 0.0)) {
- STUBVAL(gridx, gridy, ds->layer) = ds->x2 - dx;
OBSVAL(gridx, gridy, ds->layer)
= (OBSVAL(gridx, gridy, ds->layer)
& BLOCKED_MASK) |
- node->netnum | STUBROUTE_EW;
- NODELOC(gridx, gridy, ds->layer) = node;
- NODESAV(gridx, gridy, ds->layer) = node;
+ node->netnum | STUBROUTE;
+ lnode = SetNodeinfo(gridx, gridy, ds->layer);
+ lnode->nodeloc = node;
+ lnode->nodesav = node;
+ lnode->stub = ds->x2 - dx;
+ lnode->flags |= NI_STUB_EW;
}
}
}
@@ -2295,11 +2525,12 @@ void create_obstructions_outside_nodes(void)
void tap_to_tap_interactions(void)
{
+ NODEINFO lnode;
GATE g;
DSEG ds;
struct dseg_ de;
int mingridx, mingridy, maxgridx, maxgridy;
- int i, gridx, gridy, net, orignet, offset;
+ int i, gridx, gridy, net, orignet;
double dx, dy;
float dist;
@@ -2337,14 +2568,14 @@ void tap_to_tap_interactions(void)
orignet = OBSVAL(gridx, gridy, ds->layer);
if (orignet & OFFSET_TAP) {
- offset = orignet & PINOBSTRUCTMASK;
orignet &= ROUTED_NET_MASK;
if (orignet != net) {
dx = (gridx * PitchX[ds->layer]) + Xlowerbound;
dy = (gridy * PitchY[ds->layer]) + Ylowerbound;
- dist = STUBVAL(gridx, gridy, ds->layer);
+ lnode = NODEIPTR(gridx, gridy, ds->layer);
+ dist = (lnode) ? lnode->offset : 0.0;
/* "de" is the bounding box of a via placed */
/* at (gridx, gridy) and offset as specified. */
@@ -2355,11 +2586,11 @@ void tap_to_tap_interactions(void)
de.y1 = dy - deltay[ds->layer];
de.y2 = dy + deltay[ds->layer];
- if (offset == (STUBROUTE_NS | OFFSET_TAP)) {
+ if (lnode->flags & NI_OFFSET_NS) {
de.y1 += dist;
de.y2 += dist;
}
- else if (offset == (STUBROUTE_EW | OFFSET_TAP)) {
+ else if (lnode->flags & NI_OFFSET_EW) {
de.x1 += dist;
de.x2 += dist;
}
@@ -2402,6 +2633,7 @@ void tap_to_tap_interactions(void)
void
make_routable(NODE node)
{
+ NODEINFO lnode;
GATE g;
DSEG ds;
int i, gridx, gridy;
@@ -2432,8 +2664,9 @@ make_routable(NODE node)
if (orignet & NO_NET) {
OBSVAL(gridx, gridy, ds->layer) = g->netnum[i];
- NODELOC(gridx, gridy, ds->layer) = node;
- NODESAV(gridx, gridy, ds->layer) = node;
+ lnode = SetNodeinfo(gridx, gridy, ds->layer);
+ lnode->nodeloc = node;
+ lnode->nodesav = node;
return;
}
}
@@ -2465,10 +2698,11 @@ make_routable(NODE node)
void adjust_stub_lengths(void)
{
NODE node;
+ NODEINFO lnode;
GATE g;
DSEG ds, ds2;
struct dseg_ dt, de;
- int i, gridx, gridy, orignet;
+ int i, gridx, gridy, orignet, o;
double dx, dy, wx, wy, s;
float dist;
u_char errbox;
@@ -2523,13 +2757,24 @@ void adjust_stub_lengths(void)
gridy++;
continue;
}
+ lnode = NODEIPTR(gridx, gridy, ds->layer);
- // STUBROUTE_X are unroutable; leave them alone
- if ((orignet & PINOBSTRUCTMASK) == STUBROUTE_X) {
+ // Even if it's on the same net, we need to check
+ // if the stub is to this node, otherwise it is not
+ // an issue.
+ if (lnode->nodesav != node) {
gridy++;
continue;
}
+ // NI_STUB_MASK are unroutable; leave them alone
+ if (orignet & STUBROUTE) {
+ if ((lnode->flags & NI_OFFSET_MASK) == NI_OFFSET_MASK) {
+ gridy++;
+ continue;
+ }
+ }
+
// define a route box around the grid point
errbox = FALSE;
@@ -2538,24 +2783,24 @@ void adjust_stub_lengths(void)
dt.y1 = dy - wy;
dt.y2 = dy + wy;
- dist = STUBVAL(gridx, gridy, ds->layer);
-
// adjust the route box according to the stub
// or offset geometry, provided that the stub
// is longer than the route box.
if (orignet & OFFSET_TAP) {
- if (orignet & STUBROUTE_EW) {
+ dist = lnode->offset;
+ if (lnode->flags & NI_OFFSET_EW) {
dt.x1 += dist;
dt.x2 += dist;
}
- else if (orignet & STUBROUTE_NS) {
+ else if (lnode->flags & NI_OFFSET_NS) {
dt.y1 += dist;
dt.y2 += dist;
}
}
- else if (orignet & PINOBSTRUCTMASK) {
- if (orignet & STUBROUTE_EW) {
+ else if (orignet & STUBROUTE) {
+ dist = lnode->stub;
+ if (lnode->flags & NI_STUB_EW) {
if (dist > EPS) {
if (dx + dist > dt.x2)
dt.x2 = dx + dist;
@@ -2565,7 +2810,7 @@ void adjust_stub_lengths(void)
dt.x1 = dx + dist;
}
}
- else if (orignet & STUBROUTE_NS) {
+ else if (lnode->flags & NI_STUB_NS) {
if (dist > EPS) {
if (dy + dist > dt.y2)
dt.y2 = dy + dist;
@@ -2582,7 +2827,7 @@ void adjust_stub_lengths(void)
// check for DRC spacing interactions between
// the tap box and the route box
- if ((dt.y1 - ds->y2) > EPS && (dt.y1 - ds->y2) < s) {
+ if ((dt.y1 - ds->y2) > EPS && (dt.y1 - ds->y2) + EPS < s) {
if (ds->x2 > (dt.x1 - s) && ds->x1 < (dt.x2 + s)) {
de.y2 = dt.y1;
de.y1 = ds->y2;
@@ -2591,7 +2836,7 @@ void adjust_stub_lengths(void)
errbox = TRUE;
}
}
- else if ((ds->y1 - dt.y2) > EPS && (ds->y1 - dt.y2) < s) {
+ else if ((ds->y1 - dt.y2) > EPS && (ds->y1 - dt.y2) + EPS < s) {
if (ds->x2 > (dt.x1 - s) && ds->x1 < (dt.x2 + s)) {
de.y1 = dt.y2;
de.y2 = ds->y1;
@@ -2601,7 +2846,7 @@ void adjust_stub_lengths(void)
}
}
- if ((dt.x1 - ds->x2) > EPS && (dt.x1 - ds->x2) < s) {
+ if ((dt.x1 - ds->x2) > EPS && (dt.x1 - ds->x2) + EPS < s) {
if (ds->y2 > (dt.y1 - s) && ds->y1 < (dt.y2 + s)) {
de.x2 = dt.x1;
de.x1 = ds->x2;
@@ -2610,7 +2855,7 @@ void adjust_stub_lengths(void)
errbox = TRUE;
}
}
- else if ((ds->x1 - dt.x2) > EPS && (ds->x1 - dt.x2) < s) {
+ else if ((ds->x1 - dt.x2) > EPS && (ds->x1 - dt.x2) + EPS < s) {
if (ds->y2 > (dt.y1 - s) && ds->y1 < (dt.y2 + s)) {
de.x1 = dt.x2;
de.x2 = ds->x1;
@@ -2695,99 +2940,216 @@ void adjust_stub_lengths(void)
// makes contact without the stub. Moving the stub
// to another side should not create an error.
- // NOTE: Changed 4/29/13; direction of stub will
- // be changed even though it might create an error
- // in the other direction; it can't do worse.
- // But, the case should be re-run to check (to-do)
-
- // NOTE 2: Changed again 1/8/14; error box must
- // touch ds geometry.
- // Changed again 2/5/14: error box must touch
- // ds geometry by more than just a point. <=
- // changed to < and >= changed to >
+ // NOTE: error box must touch ds geometry, and by
+ // more than just a point.
+
+ // 8/31/2016:
+ // If DRC violations are created on two adjacent
+ // sides, then create both a stub route and a tap
+ // offset. Put the stub route in the preferred
+ // metal direction of the layer, and set the tap
+ // offset to prevent the DRC error in the other
+ // direction.
+ // 10/3/2016: The tap offset can be set either
+ // by moving toward the obstructing edge to
+ // remove the gap, or moving away from it to
+ // avoid the DRC spacing error. Choose the one
+ // that offsets by the smaller distance.
- /* if (de.x2 > dt.x2) { */
if ((de.x2 > dt.x2) && (de.y1 < ds->y2) &&
(de.y2 > ds->y1)) {
- if ((orignet & PINOBSTRUCTMASK) == 0) {
- OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE_EW;
- STUBVAL(gridx, gridy, ds->layer) = de.x2 - dx;
+ if ((orignet & STUBROUTE) == 0) {
+ OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE;
+ lnode->stub = de.x2 - dx;
+ lnode->flags |= NI_STUB_EW;
errbox = FALSE;
}
- else if ((orignet & PINOBSTRUCTMASK) == STUBROUTE_EW
- && (dist > 0)) {
- STUBVAL(gridx, gridy, ds->layer) = de.x2 - dx;
+ else if ((orignet & STUBROUTE)
+ && (lnode->flags & NI_STUB_EW)) {
+ // Beware, if dist > 0 then this reverses
+ // the stub. For U-shaped ports may need
+ // to have separate E and W stubs.
+ lnode->stub = de.x2 - dx;
errbox = FALSE;
}
- else if ((orignet & PINOBSTRUCTMASK) ==
- STUBROUTE_NS) {
- OBSVAL(gridx, gridy, ds->layer) &= ~STUBROUTE_NS;
- OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE_EW;
- STUBVAL(gridx, gridy, ds->layer) = de.x2 - dx;
- errbox = FALSE;
+ else if ((orignet & STUBROUTE)
+ && (lnode->flags & NI_STUB_NS)) {
+
+ // If preferred route direction is
+ // horizontal, then change the stub
+
+ OBSVAL(gridx, gridy, ds->layer) |= OFFSET_TAP;
+ if (LefGetRouteOrientation(ds->layer) == 1) {
+ lnode->flags = NI_OFFSET_NS | NI_STUB_EW;
+ // lnode->offset = lnode->stub; // ?
+ if (lnode->stub > 0) {
+ lnode->offset = de.y2 - dy - wy;
+ if (lnode->offset > s - lnode->offset)
+ lnode->offset -= s;
+ }
+ else {
+ lnode->offset = de.y1 - dy + wy;
+ if (-lnode->offset > s + lnode->offset)
+ lnode->offset += s;
+ }
+ lnode->stub = de.x2 - dx;
+ errbox = FALSE;
+ }
+ else {
+ // Add the offset
+ lnode->offset = de.x2 - dx - wx;
+ if (lnode->offset > s - lnode->offset)
+ lnode->offset -= s;
+ lnode->flags |= NI_OFFSET_EW;
+ errbox = FALSE;
+ }
}
}
- /* else if (de.x1 < dt.x1) { */
else if ((de.x1 < dt.x1) && (de.y1 < ds->y2) &&
(de.y2 > ds->y1)) {
- if ((orignet & PINOBSTRUCTMASK) == 0) {
- OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE_EW;
- STUBVAL(gridx, gridy, ds->layer) = de.x1 - dx;
+ if ((orignet & STUBROUTE) == 0) {
+ OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE;
+ lnode->stub = de.x1 - dx;
+ lnode->flags |= NI_STUB_EW;
errbox = FALSE;
}
- else if ((orignet & PINOBSTRUCTMASK) == STUBROUTE_EW
- && (dist < 0)) {
- STUBVAL(gridx, gridy, ds->layer) = de.x1 - dx;
+ else if ((orignet & STUBROUTE)
+ && (lnode->flags & NI_STUB_EW)) {
+ // Beware, if dist > 0 then this reverses
+ // the stub. For U-shaped ports may need
+ // to have separate E and W stubs.
+ lnode->stub = de.x1 - dx;
errbox = FALSE;
}
- else if ((orignet & PINOBSTRUCTMASK) ==
- STUBROUTE_NS) {
- OBSVAL(gridx, gridy, ds->layer) &= ~STUBROUTE_NS;
- OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE_EW;
- STUBVAL(gridx, gridy, ds->layer) = de.x1 - dx;
- errbox = FALSE;
+ else if ((orignet & STUBROUTE)
+ && (lnode->flags & NI_STUB_NS)) {
+
+ // If preferred route direction is
+ // horizontal, then change the stub
+
+ OBSVAL(gridx, gridy, ds->layer) |= OFFSET_TAP;
+ if (LefGetRouteOrientation(ds->layer) == 1) {
+ lnode->flags = NI_OFFSET_NS | NI_STUB_EW;
+ // lnode->offset = lnode->stub; // ?
+ if (lnode->stub > 0) {
+ lnode->offset = de.y2 - dy - wy;
+ if (lnode->offset > s - lnode->offset)
+ lnode->offset -= s;
+ }
+ else {
+ lnode->offset = de.y1 - dy + wy;
+ if (-lnode->offset > s + lnode->offset)
+ lnode->offset += s;
+ }
+ lnode->stub = de.x1 - dx;
+ errbox = FALSE;
+ }
+ else {
+ // Add the offset
+ lnode->offset = de.x1 - dx + wx;
+ if (-lnode->offset > s + lnode->offset)
+ lnode->offset += s;
+ lnode->flags |= NI_OFFSET_EW;
+ errbox = FALSE;
+ }
}
}
- /* else if (de.y2 > dt.y2) { */
else if ((de.y2 > dt.y2) && (de.x1 < ds->x2) &&
(de.x2 > ds->x1)) {
- if ((orignet & PINOBSTRUCTMASK) == 0) {
- OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE_NS;
- STUBVAL(gridx, gridy, ds->layer) = de.y2 - dy;
+ if ((orignet & STUBROUTE) == 0) {
+ OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE;
+ lnode->stub = de.y2 - dy;
+ lnode->flags |= NI_STUB_NS;
errbox = FALSE;
}
- else if ((orignet & PINOBSTRUCTMASK) == STUBROUTE_NS
- && (dist > 0)) {
- STUBVAL(gridx, gridy, ds->layer) = de.y2 - dy;
+ else if ((orignet & STUBROUTE)
+ && (lnode->flags & NI_STUB_NS)) {
+ // Beware, if dist > 0 then this reverses
+ // the stub. For C-shaped ports may need
+ // to have separate N and S stubs.
+ lnode->stub = de.y2 - dy;
errbox = FALSE;
}
- else if ((orignet & PINOBSTRUCTMASK) ==
- STUBROUTE_EW) {
- OBSVAL(gridx, gridy, ds->layer) &= ~STUBROUTE_EW;
- OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE_NS;
- STUBVAL(gridx, gridy, ds->layer) = de.y2 - dy;
- errbox = FALSE;
+ else if ((orignet & STUBROUTE)
+ && (lnode->flags & NI_STUB_EW)) {
+
+ // If preferred route direction is
+ // vertical, then change the stub
+
+ OBSVAL(gridx, gridy, ds->layer) |= OFFSET_TAP;
+ if (LefGetRouteOrientation(ds->layer) == 0) {
+ lnode->flags = NI_OFFSET_EW | NI_STUB_NS;
+ // lnode->offset = lnode->stub; // ?
+ if (lnode->stub > 0) {
+ lnode->offset = de.x2 - dx - wx;
+ if (lnode->offset > s - lnode->offset)
+ lnode->offset -= s;
+ }
+ else {
+ lnode->offset = de.x1 - dx + wx;
+ if (-lnode->offset > s + lnode->offset)
+ lnode->offset += s;
+ }
+ lnode->stub = de.y2 - dy;
+ errbox = FALSE;
+ }
+ else {
+ // Add the offset
+ lnode->offset = de.y2 - dy - wy;
+ if (lnode->offset > s - lnode->offset)
+ lnode->offset -= s;
+ lnode->flags |= NI_OFFSET_NS;
+ errbox = FALSE;
+ }
}
}
- /* else if (de.y1 < dt.y1) { */
else if ((de.y1 < dt.y1) && (de.x1 < ds->x2) &&
(de.x2 > ds->x1)) {
- if ((orignet & PINOBSTRUCTMASK) == 0) {
- OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE_NS;
- STUBVAL(gridx, gridy, ds->layer) = de.y1 - dy;
+ if ((orignet & STUBROUTE) == 0) {
+ OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE;
+ lnode->stub = de.y1 - dy;
+ lnode->flags |= NI_STUB_NS;
errbox = FALSE;
}
- else if ((orignet & PINOBSTRUCTMASK) == STUBROUTE_NS
- && (dist < 0)) {
- STUBVAL(gridx, gridy, ds->layer) = de.y1 - dy;
+ else if ((orignet & STUBROUTE)
+ && (lnode->flags & NI_STUB_NS)) {
+ // Beware, if dist > 0 then this reverses
+ // the stub. For C-shaped ports may need
+ // to have separate N and S stubs.
+ lnode->stub = de.y1 - dy;
errbox = FALSE;
}
- else if ((orignet & PINOBSTRUCTMASK) ==
- STUBROUTE_EW) {
- OBSVAL(gridx, gridy, ds->layer) &= ~STUBROUTE_EW;
- OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE_NS;
- STUBVAL(gridx, gridy, ds->layer) = de.y1 - dy;
- errbox = FALSE;
+ else if ((orignet & STUBROUTE)
+ && (lnode->flags & NI_STUB_EW)) {
+
+ // If preferred route direction is
+ // vertical, then change the stub
+
+ OBSVAL(gridx, gridy, ds->layer) |= OFFSET_TAP;
+ if (LefGetRouteOrientation(ds->layer) == 0) {
+ lnode->flags = NI_OFFSET_EW | NI_STUB_NS;
+ // lnode->offset = lnode->stub; // ?
+ if (lnode->stub > 0) {
+ lnode->offset = de.x2 - dx - wx;
+ if (lnode->offset > s - lnode->offset)
+ lnode->offset -= s;
+ }
+ else {
+ lnode->offset = de.x1 - dx + wx;
+ if (-lnode->offset > s + lnode->offset)
+ lnode->offset += s;
+ }
+ lnode->stub = de.y1 - dy + wy;
+ errbox = FALSE;
+ }
+ else {
+ // Add the offset
+ lnode->offset = de.y1 - dy + wy;
+ if (-lnode->offset > s + lnode->offset)
+ lnode->offset += s;
+ lnode->flags |= NI_OFFSET_NS;
+ errbox = FALSE;
+ }
}
}
@@ -2801,7 +3163,8 @@ void adjust_stub_lengths(void)
if (errbox == TRUE) {
// Unroutable position, so mark it unroutable
- OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE_X;
+ OBSVAL(gridx, gridy, ds->layer) |= STUBROUTE;
+ lnode->flags |= NI_STUB_MASK;
}
}
}
@@ -2911,7 +3274,7 @@ void
find_route_blocks()
{
GATE g;
- // DPOINT dp;
+ NODEINFO lnode;
DSEG ds;
struct dseg_ dt;
int i, gridx, gridy;
@@ -2951,8 +3314,9 @@ find_route_blocks()
gridy++;
}
while (dy < ds->y2 + s) {
- u = ((OBSVAL(gridx, gridy, ds->layer) &
- PINOBSTRUCTMASK) == STUBROUTE_EW) ? v : w;
+ lnode = NODEIPTR(gridx, gridy, ds->layer);
+ u = ((OBSVAL(gridx, gridy, ds->layer) & STUBROUTE)
+ && (lnode->flags & NI_STUB_EW)) ? v : w;
if (dy + EPS < ds->y2 - u)
block_route(gridx, gridy, ds->layer, NORTH);
if (dy - EPS > ds->y1 + u)
@@ -2984,8 +3348,9 @@ find_route_blocks()
gridy++;
}
while (dy < ds->y2 + s) {
- u = ((OBSVAL(gridx, gridy, ds->layer) &
- PINOBSTRUCTMASK) == STUBROUTE_EW) ? v : w;
+ lnode = NODEIPTR(gridx, gridy, ds->layer);
+ u = ((OBSVAL(gridx, gridy, ds->layer) & STUBROUTE)
+ && (lnode->flags & NI_STUB_EW)) ? v : w;
if (dy + EPS < ds->y2 - u)
block_route(gridx, gridy, ds->layer, NORTH);
if (dy - EPS > ds->y1 + u)
@@ -3017,8 +3382,9 @@ find_route_blocks()
gridx++;
}
while (dx < ds->x2 + s) {
- u = ((OBSVAL(gridx, gridy, ds->layer) &
- PINOBSTRUCTMASK) == STUBROUTE_NS) ? v : w;
+ lnode = NODEIPTR(gridx, gridy, ds->layer);
+ u = ((OBSVAL(gridx, gridy, ds->layer) & STUBROUTE)
+ && (lnode->flags & NI_STUB_NS)) ? v : w;
if (dx + EPS < ds->x2 - u)
block_route(gridx, gridy, ds->layer, EAST);
if (dx - EPS > ds->x1 + u)
@@ -3050,8 +3416,9 @@ find_route_blocks()
gridx++;
}
while (dx < ds->x2 + s) {
- u = ((OBSVAL(gridx, gridy, ds->layer) &
- PINOBSTRUCTMASK) == STUBROUTE_NS) ? v : w;
+ lnode = NODEIPTR(gridx, gridy, ds->layer);
+ u = ((OBSVAL(gridx, gridy, ds->layer) & STUBROUTE)
+ && (lnode->flags & NI_STUB_NS)) ? v : w;
if (dx + EPS < ds->x2 - u)
block_route(gridx, gridy, ds->layer, EAST);
if (dx - EPS > ds->x1 + u)
diff --git a/qconfig.c b/qconfig.c
index eb98f67..de963c8 100644
--- a/qconfig.c
+++ b/qconfig.c
@@ -416,7 +416,20 @@ int read_config(FILE *fconfig, int is_info)
gateinfo->height = darg2;
gateinfo->placedX = 0.0; // implicit cell origin
gateinfo->placedY = 0.0;
+ gateinfo->nodes = 0;
gateinfo->next = GateInfo; // prepend to linked gate list
+
+ // Allocate memory for up to 10 pins
+ gateinfo->taps = (DSEG *)malloc(10 * sizeof(DSEG));
+ gateinfo->noderec = (NODE *)malloc(10 * sizeof(NODE));
+ gateinfo->netnum = (int *)malloc(10 * sizeof(int));
+ gateinfo->node = (char **)malloc(10 * sizeof(char *));
+ // Initialize first entry
+ gateinfo->taps[0] = NULL;
+ gateinfo->noderec[0] = NULL;
+ gateinfo->netnum[0] = -1;
+ gateinfo->node[0] = NULL;
+
GateInfo = gateinfo;
}
@@ -447,6 +460,18 @@ int read_config(FILE *fconfig, int is_info)
drect->layer = 0;
drect->next = (DSEG)NULL;
CurrentPin++;
+
+ if (CurrentPin % 10 == 0) {
+ // Allocate memory for 10 more pins
+ gateinfo->taps = (DSEG *)realloc(gateinfo->taps,
+ (CurrentPin + 10) * sizeof(DSEG));
+ gateinfo->noderec = (NODE *)realloc(gateinfo->taps,
+ (CurrentPin + 10) * sizeof(NODE));
+ gateinfo->netnum = (int *)realloc(gateinfo->taps,
+ (CurrentPin + 10) * sizeof(int));
+ gateinfo->node = (char **)realloc(gateinfo->taps,
+ (CurrentPin + 10) * sizeof(char *));
+ }
}
if (OK == 0) {
diff --git a/qrouter.c b/qrouter.c
index e829913..67debc8 100644
--- a/qrouter.c
+++ b/qrouter.c
@@ -12,7 +12,7 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
-#include <getopt.h>
+#include <unistd.h>
#include "qrouter.h"
#include "qconfig.h"
@@ -38,7 +38,7 @@ u_char *RMask; // mask out best area to route
u_int *Obs[MAX_LAYERS]; // net obstructions in layer
PROUTE *Obs2[MAX_LAYERS]; // used for pt->pt routes on layer
float *Obsinfo[MAX_LAYERS]; // temporary array used for detailed obstruction info
-NODEINFO Nodeinfo[MAX_LAYERS]; // nodes and stub information is here. . .
+NODEINFO *Nodeinfo[MAX_LAYERS]; // nodes and stub information is here. . .
DSEG UserObs; // user-defined obstruction layers
u_char needblock[MAX_LAYERS];
@@ -176,49 +176,105 @@ runqrouter(int argc, char *argv[])
Filename[0] = 0;
DEFfilename[0] = 0;
- while ((i = getopt(argc, argv, "c:i:hk:fv:p:g:r:")) != -1) {
- switch (i) {
- case 'c':
- configfile = strdup(optarg);
- break;
- case 'v':
- Verbose = atoi(optarg);
- break;
- case 'i':
- infofile = strdup(optarg);
- break;
- case 'p':
- vddnet = strdup(optarg);
- break;
- case 'g':
- gndnet = strdup(optarg);
- break;
- case 'r':
- if (sscanf(optarg, "%d", &Scales.iscale) != 1) {
- Fprintf(stderr, "Bad resolution scalefactor \"%s\", "
+ /* Parse arguments */
+
+ for (i = 0; i < argc; i++) {
+ char optc, argsep = '\0';
+ char *optarg = NULL;
+
+ if (*argv[i] == '-') {
+
+ /* 1st pass---look for which options require an argument */
+ optc = *(argv[i] + 1);
+
+ switch (optc) {
+ case 'c':
+ case 'i':
+ case 'k':
+ case 'v':
+ case 'p':
+ case 'g':
+ case 'r':
+ argsep = *(argv[i] + 2);
+ if (argsep == '\0') {
+ i++;
+ if (i < argc) {
+ optarg = argv[i];
+ if (*optarg == '-') {
+ Fprintf(stderr, "Option -%c needs an argument.\n", optc);
+ Fprintf(stderr, "Option not handled.\n");
+ continue;
+ }
+ }
+ else {
+ Fprintf(stderr, "Option -%c needs an argument.\n", optc);
+ Fprintf(stderr, "Option not handled.\n");
+ continue;
+ }
+ }
+ else
+ optarg = argv[i] + 2;
+ }
+
+ /* Now handle each option individually */
+
+ switch (optc) {
+ case 'c':
+ configfile = strdup(optarg);
+ break;
+ case 'v':
+ Verbose = atoi(optarg);
+ break;
+ case 'i':
+ infofile = strdup(optarg);
+ break;
+ case 'p':
+ vddnet = strdup(optarg);
+ break;
+ case 'g':
+ gndnet = strdup(optarg);
+ break;
+ case 'r':
+ if (sscanf(optarg, "%d", &Scales.iscale) != 1) {
+ Fprintf(stderr, "Bad resolution scalefactor \"%s\", "
"integer expected.\n", optarg);
- Scales.iscale = 1;
- }
- break;
- case 'h':
- helpmessage();
- return 1;
- break;
- case 'f':
- forceRoutable = 1;
- break;
- case 'k':
- keepTrying = (u_char)atoi(optarg);
- break;
- default:
- Fprintf(stderr, "bad switch %d\n", i);
+ Scales.iscale = 1;
+ }
+ break;
+ case 'h':
+ helpmessage();
+ return 1;
+ break;
+ case 'f':
+ forceRoutable = 1;
+ break;
+ case 'k':
+ keepTrying = (u_char)atoi(optarg);
+ break;
+ case '\0':
+ /* Ignore '-' */
+ break;
+ case '-':
+ /* Ignore '--' */
+ break;
+ default:
+ Fprintf(stderr, "Bad option -%c, ignoring.\n", optc);
+ }
+ }
+ else {
+ /* Not an option or an option argument, so treat as a filename */
+ strcpy( Filename, argv[i] );
}
}
if (infofile != NULL)
infoFILEptr = fopen(infofile, "w" );
- else
+ else {
infoFILEptr = NULL;
+#ifndef TCL_QROUTER
+ fprintf(stdout, "Qrouter detail maze router version %s.%s\n", VERSION, REVISION);
+#endif
+ }
configFILEptr = fopen(configfile, "r");
@@ -302,19 +358,19 @@ runqrouter(int argc, char *argv[])
return 1;
}
- if (optind < argc) {
+ if (Filename[0] != '\0') {
- /* process remaining commandline strings */
+ /* process last non-option string */
- strcpy( Filename, argv[optind] );
dotptr = strrchr(Filename, '.');
if (dotptr != NULL) *dotptr = '\0';
sprintf(DEFfilename, "%s.def", Filename);
}
else if (readconfig) {
Fprintf(stdout, "No netlist file specified, continuing without.\n");
+
+ // Print help message but continue normally.
helpmessage();
- return 1;
}
Obs[0] = (u_int *)NULL;
@@ -334,7 +390,7 @@ runqrouter(int argc, char *argv[])
static void reinitialize()
{
- int i;
+ int i, j;
NETLIST nl;
NET net;
ROUTE rt;
@@ -347,6 +403,9 @@ static void reinitialize()
// Free up all of the matrices
for (i = 0; i < Pinlayers; i++) {
+ for (j = 0; j < NumChannelsX[i] * NumChannelsY[i]; j++)
+ if (Nodeinfo[i][j])
+ free(Nodeinfo[i][j]);
free(Nodeinfo[i]);
Nodeinfo[i] = NULL;
}
@@ -486,8 +545,8 @@ static int post_def_setup()
exit(5);
}
- Nodeinfo[i] = (NODEINFO)calloc(NumChannelsX[i] * NumChannelsY[i],
- sizeof(struct nodeinfo_));
+ Nodeinfo[i] = (NODEINFO *)calloc(NumChannelsX[i] * NumChannelsY[i],
+ sizeof(NODEINFO));
if (!Nodeinfo[i]) {
fprintf( stderr, "Out of memory 6.\n");
exit(6);
@@ -2203,10 +2262,12 @@ static int next_route_setup(struct routeinfo_ *iroute, u_char stage)
for (i = 0; i < Pinlayers; i++) {
for (j = 0; j < NumChannelsX[i] * NumChannelsY[i]; j++) {
- node = Nodeinfo[i][j].nodeloc;
- if (node != (NODE)NULL)
- if (node->netnum == iroute->net->netnum)
- Nodeinfo[i][j].nodeloc = (NODE)NULL;
+ if (Nodeinfo[i][j]) {
+ node = Nodeinfo[i][j]->nodeloc;
+ if (node != (NODE)NULL)
+ if (node->netnum == iroute->net->netnum)
+ Nodeinfo[i][j]->nodeloc = (NODE)NULL;
+ }
}
}
@@ -2254,6 +2315,7 @@ static int route_setup(struct routeinfo_ *iroute, u_char stage)
u_int netnum, dir;
int result, rval, unroutable;
NODE node;
+ NODEINFO lnode;
PROUTE *Pr;
// Make Obs2[][] a copy of Obs[][]. Convert pin obstructions to
@@ -2269,11 +2331,6 @@ static int route_setup(struct routeinfo_ *iroute, u_char stage)
Pr->prdata.net = netnum;
else
Pr->prdata.net = netnum & NETNUM_MASK;
- dir = netnum & PINOBSTRUCTMASK;
- if ((dir != 0) && ((dir & STUBROUTE_X) == STUBROUTE_X)) {
- if ((netnum & NETNUM_MASK) == iroute->net->netnum)
- Pr->prdata.net = 0; // STUBROUTE_X not routable
- }
} else {
Pr->flags = PR_COST; // This location is routable
Pr->prdata.cost = MAXRT;
@@ -2381,10 +2438,12 @@ static int route_setup(struct routeinfo_ *iroute, u_char stage)
for (i = 0; i < Pinlayers; i++) {
for (j = 0; j < NumChannelsX[i] * NumChannelsY[i]; j++) {
- iroute->nsrc = Nodeinfo[i][j].nodeloc;
- if (iroute->nsrc != (NODE)NULL)
- if (iroute->nsrc->netnum == iroute->net->netnum)
- Nodeinfo[i][j].nodeloc = (NODE)NULL;
+ if (Nodeinfo[i][j]) {
+ iroute->nsrc = Nodeinfo[i][j]->nodeloc;
+ if (iroute->nsrc != (NODE)NULL)
+ if (iroute->nsrc->netnum == iroute->net->netnum)
+ Nodeinfo[i][j]->nodeloc = (NODE)NULL;
+ }
}
}
@@ -2826,6 +2885,7 @@ static void cleanup_net(NET net)
{
SEG segf, segl, seg;
ROUTE rt, rt2;
+ NODEINFO lnode;
int lf, ll, lf2, ll2;
u_char fcheck, lcheck;
u_char xcheckf, ycheckf, xcheckl, ycheckl;
@@ -2858,7 +2918,8 @@ static void cleanup_net(NET net)
fcheck = TRUE;
// We're going to remove the contact so it can't be a tap
- if ((lf < Pinlayers) && (NODESAV(segf->x1, segf->y1, lf) != NULL))
+ if ((lf < Pinlayers) && ((lnode = NODEIPTR(segf->x1, segf->y1, lf)) != NULL)
+ && (lnode->nodesav != NULL))
fcheck = FALSE;
}
xcheckf = needblock[lf] & VIABLOCKX;
@@ -2866,7 +2927,8 @@ static void cleanup_net(NET net)
if (!xcheckf && !ycheckf) fcheck = FALSE;
// Move to the next-to-last segment
- for (segl = segf->next; segl && segl->next; segl = segl->next);
+ for (segl = segf->next; segl && segl->next && segl->next->next;
+ segl = segl->next);
if (segl && (segl->next != NULL) && (segl->next->segtype == ST_VIA)) {
if (segl->next->layer < segl->layer) {
@@ -2883,7 +2945,8 @@ static void cleanup_net(NET net)
lcheck = TRUE;
// We're going to remove the contact so it can't be a tap
- if ((ll < Pinlayers) && (NODESAV(segl->x1, segl->y1, ll) != NULL))
+ if ((ll < Pinlayers) && ((lnode = NODEIPTR(segl->x1, segl->y1, ll)) != NULL)
+ && (lnode->nodesav != NULL))
lcheck = FALSE;
}
xcheckl = needblock[ll] & VIABLOCKX;
@@ -2904,7 +2967,6 @@ static void cleanup_net(NET net)
if ((seg->layer == lf) || ((seg->layer + 1) == lf)) {
if (xcheckf && (seg->y1 == segf->y1) &&
(ABSDIFF(seg->x1, segf->x1) == 1)) {
- fcheck = FALSE;
if (seg->layer != segf->layer) {
// Adjacent vias are different types.
@@ -2935,7 +2997,6 @@ static void cleanup_net(NET net)
}
else if (ycheckf && (seg->x1 == segf->x1) &&
(ABSDIFF(seg->y1, segf->y1) == 1)) {
- fcheck = FALSE;
if (seg->layer != segf->layer) {
// Adjacent vias are different types.
// Deal with it by creating a route between
@@ -2970,7 +3031,6 @@ static void cleanup_net(NET net)
if ((seg->layer == ll) || ((seg->layer + 1) == ll)) {
if (xcheckl && (seg->y1 == segl->y1) &&
(ABSDIFF(seg->x1, segl->x1) == 1)) {
- lcheck = FALSE;
if (seg->layer != segl->layer) {
// Adjacent vias are different types.
@@ -3001,7 +3061,6 @@ static void cleanup_net(NET net)
}
else if (ycheckl && (seg->x1 == segl->x1) &&
(ABSDIFF(seg->y1, segl->y1) == 1)) {
- lcheck = FALSE;
if (seg->layer != segl->layer) {
// Adjacent vias are different types.
@@ -3058,6 +3117,7 @@ static void
emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
{
SEG seg, saveseg, lastseg, prevseg;
+ NODEINFO lnode, lnode1, lnode2;
ROUTE rt;
u_int dir1, dir2, tdir;
int layer;
@@ -3065,7 +3125,7 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
double dc;
int lastx = -1, lasty = -1, lastlay;
int horizontal;
- float offset1, offset2;
+ float offset1, offset2, stub, offset;
u_char cancel, segtype;
double invscale = (double)(1.0 / (double)iscale);
@@ -3076,28 +3136,105 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
fprintf(Cmd, ";\n- %s\n", net->netname);
}
- int viaOffsetX[MAX_LAYERS][2];
- int viaOffsetY[MAX_LAYERS][2];
-
- /* Compute via offsets, if needed for adjacent vias */
+ u_char viaCheckX[MAX_LAYERS];
+ u_char viaCheckY[MAX_LAYERS];
+ double viaOffsetX[MAX_LAYERS][3];
+ double viaOffsetY[MAX_LAYERS][3];
+
+ /* Compute via offsets, if needed for adjacent vias on different nets. */
+
+ /* A well-designed standard cell set should not have DRC errors */
+ /* between vias spaced on adjacent tracks. But not every standard */
+ /* cell set is well-designed. . . */
+
+ /* Example of offset measurements: */
+ /* viaOffsetX[layer][n]: layer is the base layer of the via, n is */
+ /* 0 for the via one layer below, 1 for the same via, and 2 for the */
+ /* via one layer above. Note that the n = 1 has interactions on two */
+ /* different metal layers. The maximum distance is used. */
+
+ /* viaCheckX[1] is 0 if all of viaOffsetX[1][0-2] is zero. This */
+ /* allows a quick determination if a check for neighboring vias */
+ /* is required. */
+ /* viaOffsetX[1][0] is the additional spacing above the grid width */
+ /* for via2-to-via1 (on metal2 only). */
+ /* viaOffsetX[1][1] is the additional spacing above the grid width */
+ /* for via2-to-via2 (maximum for metal2 and metal3) */
+ /* viaOffsetX[1][2] is the additional spacing above the grid width */
+ /* for via2-to-via3 (on metal3 only). */
+
+ viaOffsetX[0][0] = 0; // nothing below the 1st via
+ viaOffsetY[0][0] = 0;
+ viaOffsetX[Num_layers - 1][2] = 0; // nothing above the last via
+ viaOffsetY[Num_layers - 1][2] = 0;
for (layer = 0; layer < Num_layers - 1; layer++) {
+ double s1 = LefGetRouteSpacing(layer);
+ double s2 = LefGetRouteSpacing(layer + 1);
+ double p1x = PitchX[layer];
+ double p2x = PitchX[layer + 1];
+ double p1y = PitchY[layer];
+ double p2y = PitchY[layer + 1];
+ double w1x = LefGetViaWidth(layer, layer, 0);
+ double w1y = LefGetViaWidth(layer, layer, 1);
+ double w2x = LefGetViaWidth(layer, layer + 1, 0);
+ double w2y = LefGetViaWidth(layer, layer + 1, 1);
+
+ double w0x, w0y, w3x, w3y;
+
+ viaCheckX[layer] = 0;
+ viaCheckY[layer] = 0;
+
+ if (layer > 0) {
+
+ /* Space from via to (via - 1) */
+
+ w0x = LefGetViaWidth(layer - 1, layer, 0);
+ w0y = LefGetViaWidth(layer - 1, layer, 1);
+
+ dc = s1 + (w1x + w0x) / 2 - p1x;
+ viaOffsetX[layer][0] = (dc > 0.0) ? dc : 0.0;
+
+ dc = s1 + (w1y + w0y) / 2 - p1y;
+ viaOffsetY[layer][0] = (dc > 0.0) ? dc : 0.0;
+ }
+
+ /* Space from via to via (check both lower and upper metal layers) */
+
+ dc = s1 + w1x - p1x;
+ viaOffsetX[layer][1] = (dc > 0.0) ? dc : 0.0;
- dc = LefGetRouteSpacing(layer) + LefGetViaWidth(layer, layer, 1)
- - PitchY[layer] - EPS;
- viaOffsetY[layer][0] = (dc > 0.0) ? (int)((oscale * dc * 0.5) + 0.5) : 0;
+ dc = s2 + w2x - p2x;
+ if (dc < 0.0) dc = 0.0;
+ if (dc > viaOffsetX[layer][1]) viaOffsetX[layer][1] = dc;
- dc = LefGetRouteSpacing(layer) + LefGetViaWidth(layer, layer, 0)
- - PitchX[layer] - EPS;
- viaOffsetX[layer][0] = (dc > 0.0) ? (int)((oscale * dc * 0.5) + 0.5) : 0;
+ dc = s1 + w1y - p1y;
+ viaOffsetY[layer][1] = (dc > 0.0) ? dc : 0.0;
- dc = LefGetRouteSpacing(layer + 1) + LefGetViaWidth(layer, layer + 1, 1)
- - PitchY[layer + 1] - EPS;
- viaOffsetY[layer][1] = (dc > 0.0) ? (int)((oscale * dc * 0.5) + 0.5) : 0;
+ dc = s2 + w2y - p2y;
+ if (dc < 0.0) dc = 0.0;
+ if (dc > viaOffsetY[layer][1]) viaOffsetY[layer][1] = dc;
- dc = LefGetRouteSpacing(layer + 1) + LefGetViaWidth(layer, layer + 1, 0)
- - PitchX[layer + 1] - EPS;
- viaOffsetX[layer][1] = (dc > 0.0) ? (int)((oscale * dc * 0.5) + 0.5) : 0;
+ if (layer < Num_layers - 1) {
+
+ /* Space from via to (via + 1) */
+
+ w3x = LefGetViaWidth(layer + 1, layer, 0);
+ w3y = LefGetViaWidth(layer + 1, layer, 1);
+
+ dc = s2 + (w2x + w3x) / 2 - p2x;
+ viaOffsetX[layer][2] = (dc > 0.0) ? dc : 0.0;
+
+ dc = s2 + (w2y + w3y) / 2 - p2y;
+ viaOffsetY[layer][2] = (dc > 0.0) ? dc : 0.0;
+ }
+
+ if (viaOffsetX[layer][0] > 0 || viaOffsetX[layer][1] > 0 ||
+ viaOffsetX[layer][2] > 0)
+ viaCheckX[layer] = 1;
+ if (viaOffsetY[layer][0] > 0 || viaOffsetY[layer][1] > 0 ||
+ viaOffsetY[layer][2] > 0)
+ viaCheckY[layer] = 1;
}
Pathon = -1;
@@ -3123,26 +3260,25 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
seg->layer))
layer++;
- dir1 = OBSVAL(seg->x1, seg->y1, layer);
- dir1 &= PINOBSTRUCTMASK;
- if (dir1 && !(seg->segtype & (ST_OFFSET_START | ST_OFFSET_END))) {
+ lnode = (layer < Pinlayers) ? NODEIPTR(seg->x1, seg->y1, layer) : NULL;
+ stub = (lnode) ? lnode->stub : 0.0;
+ if (OBSVAL(seg->x1, seg->y1, layer) & STUBROUTE) {
if ((special == (u_char)0) && (Verbose > 2))
Fprintf(stdout, "Stub route distance %g to terminal"
- " at %d %d (%d)\n",
- STUBVAL(seg->x1, seg->y1, layer),
+ " at %d %d (%d)\n", stub,
seg->x1, seg->y1, layer);
dc = Xlowerbound + (double)seg->x1 * PitchX[layer];
x = (int)((REPS(dc)) * oscale);
- if (dir1 == STUBROUTE_EW)
- dc += STUBVAL(seg->x1, seg->y1, layer);
+ if (lnode->flags & NI_STUB_EW)
+ dc += stub;
x2 = (int)((REPS(dc)) * oscale);
dc = Ylowerbound + (double)seg->y1 * PitchY[layer];
y = (int)((REPS(dc)) * oscale);
- if (dir1 == STUBROUTE_NS)
- dc += STUBVAL(seg->x1, seg->y1, layer);
+ if (lnode->flags & NI_STUB_NS)
+ dc += stub;
y2 = (int)((REPS(dc)) * oscale);
- if (dir1 == STUBROUTE_EW) {
+ if (lnode->flags & NI_STUB_EW) {
horizontal = TRUE;
// If the gridpoint ahead of the stub has a route
@@ -3161,8 +3297,7 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
tdir = OBSVAL(seg->x1 + 1, seg->y1, layer);
if ((tdir & ROUTED_NET_MASK) ==
(net->netnum | ROUTED_NET)) {
- if (STUBVAL(seg->x1, seg->y1, layer) +
- LefGetRouteKeepout(layer) >= PitchX[layer]) {
+ if (stub + LefGetRouteKeepout(layer) >= PitchX[layer]) {
dc = Xlowerbound + (double)(seg->x1 + 1)
* PitchX[layer];
x2 = (int)((REPS(dc)) * oscale);
@@ -3173,8 +3308,7 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
tdir = OBSVAL(seg->x1 - 1, seg->y1, layer);
if ((tdir & ROUTED_NET_MASK) ==
(net->netnum | ROUTED_NET)) {
- if (-STUBVAL(seg->x1, seg->y1, layer) +
- LefGetRouteKeepout(layer) >= PitchX[layer]) {
+ if (-stub + LefGetRouteKeepout(layer) >= PitchX[layer]) {
dc = Xlowerbound + (double)(seg->x1 - 1)
* PitchX[layer];
x2 = (int)((REPS(dc)) * oscale);
@@ -3221,8 +3355,7 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
tdir = OBSVAL(seg->x1, seg->y1 + 1, layer);
if ((tdir & ROUTED_NET_MASK) ==
(net->netnum | ROUTED_NET)) {
- if (STUBVAL(seg->x1, seg->y1, layer) +
- LefGetRouteKeepout(layer) >= PitchY[layer]) {
+ if (stub + LefGetRouteKeepout(layer) >= PitchY[layer]) {
dc = Ylowerbound + (double)(seg->y1 + 1)
* PitchY[layer];
y2 = (int)((REPS(dc)) * oscale);
@@ -3233,8 +3366,7 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
tdir = OBSVAL(seg->x1, seg->y1 - 1, layer);
if ((tdir & ROUTED_NET_MASK) ==
(net->netnum | ROUTED_NET)) {
- if (-STUBVAL(seg->x1, seg->y1, layer) +
- LefGetRouteKeepout(layer) >= PitchY[layer]) {
+ if (-stub + LefGetRouteKeepout(layer) >= PitchY[layer]) {
dc = Ylowerbound + (double)(seg->y1 - 1)
* PitchY[layer];
y2 = (int)((REPS(dc)) * oscale);
@@ -3294,14 +3426,17 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
dir2 = 0;
if (seg->segtype & ST_OFFSET_START) {
- dir1 = OBSVAL(seg->x1, seg->y1, seg->layer) & PINOBSTRUCTMASK;
- if (dir1 == 0 && lastseg) {
+ dir1 = OBSVAL(seg->x1, seg->y1, seg->layer) & OFFSET_TAP;
+ if ((dir1 == 0) && lastseg) {
dir1 = OBSVAL(lastseg->x2, lastseg->y2, lastseg->layer)
- & PINOBSTRUCTMASK;
- offset1 = STUBVAL(lastseg->x2, lastseg->y2, lastseg->layer);
+ & OFFSET_TAP;
+ lnode1 = NODEIPTR(lastseg->x2, lastseg->y2, lastseg->layer);
+ offset1 = lnode1->offset;
+ }
+ else {
+ lnode1 = NODEIPTR(seg->x1, seg->y1, seg->layer);
+ offset1 = lnode1->offset;
}
- else
- offset1 = STUBVAL(seg->x1, seg->y1, seg->layer);
// Offset was calculated for vias; plain metal routes
// typically will need less offset distance, so subtract off
@@ -3328,14 +3463,17 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
}
}
if (seg->segtype & ST_OFFSET_END) {
- dir2 = OBSVAL(seg->x2, seg->y2, seg->layer) & PINOBSTRUCTMASK;
- if (dir2 == 0 && seg->next) {
+ dir2 = OBSVAL(seg->x2, seg->y2, seg->layer) & OFFSET_TAP;
+ if ((dir2 == 0) && seg->next) {
dir2 = OBSVAL(seg->next->x1, seg->next->y1, seg->next->layer) &
- PINOBSTRUCTMASK;
- offset2 = STUBVAL(seg->next->x1, seg->next->y1, seg->next->layer);
+ OFFSET_TAP;
+ lnode2 = NODEIPTR(seg->next->x1, seg->next->y1, seg->next->layer);
+ offset2 = lnode2->offset;
+ }
+ else {
+ lnode2 = NODEIPTR(seg->x2, seg->y2, seg->layer);
+ offset2 = lnode2->offset;
}
- else
- offset2 = STUBVAL(seg->x2, seg->y2, seg->layer);
// Offset was calculated for vias; plain metal routes
// typically will need less offset distance, so subtract off
@@ -3370,16 +3508,16 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
// config file and lefInfo.
dc = Xlowerbound + (double)seg->x1 * PitchX[layer];
- if (dir1 == (STUBROUTE_EW | OFFSET_TAP)) dc += offset1;
+ if ((dir1 & OFFSET_TAP) && (lnode1->flags & NI_OFFSET_EW)) dc += offset1;
x = (int)((REPS(dc)) * oscale);
dc = Ylowerbound + (double)seg->y1 * PitchY[layer];
- if (dir1 == (STUBROUTE_NS | OFFSET_TAP)) dc += offset1;
+ if ((dir1 & OFFSET_TAP) && (lnode1->flags & NI_OFFSET_NS)) dc += offset1;
y = (int)((REPS(dc)) * oscale);
dc = Xlowerbound + (double)seg->x2 * PitchX[layer];
- if (dir2 == (STUBROUTE_EW | OFFSET_TAP)) dc += offset2;
+ if ((dir2 & OFFSET_TAP) && (lnode2->flags & NI_OFFSET_EW)) dc += offset2;
x2 = (int)((REPS(dc)) * oscale);
dc = Ylowerbound + (double)seg->y2 * PitchY[layer];
- if (dir2 == (STUBROUTE_NS | OFFSET_TAP)) dc += offset2;
+ if ((dir2 & OFFSET_TAP) && (lnode2->flags & NI_OFFSET_NS)) dc += offset2;
y2 = (int)((REPS(dc)) * oscale);
segtype = seg->segtype & ~(ST_OFFSET_START | ST_OFFSET_END);
switch (segtype) {
@@ -3480,97 +3618,209 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
case ST_VIA:
rt->flags |= RT_OUTPUT;
if (special == (u_char)0) {
+ double viaoffx, viaoffy;
+ int vx = 0;
+ int vy = 0;
+ u_int tdirpp, tdirp, tdirn;
+ u_char viaNL, viaNM, viaNU;
+ u_char viaSL, viaSM, viaSU;
+ u_char viaEL, viaEM, viaEU;
+ u_char viaWL, viaWM, viaWU;
+
if (lastseg == NULL) {
// Make sure last position is valid
lastx = x;
lasty = y;
}
+
// Check for vias between adjacent but different nets
// that need position offsets to avoid a DRC spacing error
- if (viaOffsetX[layer][0] > 0) {
- if (seg->x1 > 0 && ((tdir = (OBSVAL(seg->x1 - 1,
- seg->y1, layer) & ROUTED_NET_MASK)) !=
- (net->netnum | ROUTED_NET)) &&
- (((tdir & (ROUTED_NET | NO_NET)) == ROUTED_NET))) {
- pathvia(Cmd, layer, x + viaOffsetX[layer][0],
- y, lastx, lasty, seg->x1, seg->y1, invscale);
- }
- else if ((seg->x1 < NumChannelsX[layer] - 1)
- && ((tdir = (OBSVAL(seg->x1 + 1, seg->y1, layer)
- & ROUTED_NET_MASK)) !=
- (net->netnum | ROUTED_NET)) &&
- (((tdir & (ROUTED_NET | NO_NET)) == ROUTED_NET))) {
- pathvia(Cmd, layer, x - viaOffsetX[layer][0],
- y, lastx, lasty, seg->x1, seg->y1, invscale);
- }
- else
- pathvia(Cmd, layer, x, y, lastx, lasty, seg->x1,
- seg->y1, invscale);
- }
- else if (viaOffsetY[layer][0] > 0) {
- if (seg->y1 > 0 && ((tdir = (OBSVAL(seg->x1,
- seg->y1 - 1, layer) & ROUTED_NET_MASK)) !=
- (net->netnum | ROUTED_NET)) &&
- (((tdir & (ROUTED_NET | NO_NET)) == ROUTED_NET))) {
- pathvia(Cmd, layer, x, y + viaOffsetY[layer][0],
- lastx, lasty, seg->x1, seg->y1, invscale);
- }
- else if ((seg->y1 < NumChannelsY[layer] - 1)
- && ((tdir = (OBSVAL(seg->x1, seg->y1 + 1,
- layer) & ROUTED_NET_MASK)) !=
- (net->netnum | ROUTED_NET)) &&
- (((tdir & (ROUTED_NET | NO_NET)) == ROUTED_NET))) {
- pathvia(Cmd, layer, x, y - viaOffsetY[layer][0],
- lastx, lasty, seg->x1, seg->y1, invscale);
- }
- else
- pathvia(Cmd, layer, x, y, lastx, lasty, seg->x1,
- seg->y1, invscale);
- }
- else if (viaOffsetX[layer][1] > 0) {
- if (seg->x1 > 0 && ((tdir = (OBSVAL(seg->x1 - 1,
- seg->y1, layer + 1) & ROUTED_NET_MASK)) !=
- (net->netnum | ROUTED_NET)) &&
- (((tdir & (ROUTED_NET | NO_NET)) == ROUTED_NET))) {
- pathvia(Cmd, layer, x + viaOffsetX[layer][1],
- y, lastx, lasty, seg->x1, seg->y1, invscale);
+ // viaCheckX[layer] indicates whether a check for
+ // vias is needed. If so, record what vias are to east
+ // and west.
+
+ if (viaCheckX[layer] > 0) {
+
+ viaEL = viaEM = viaEU = 0;
+ viaWL = viaWM = viaWU = 0;
+
+ // Check for via to west
+ if (seg->x1 > 0) {
+ tdir = OBSVAL(seg->x1 - 1, seg->y1, layer)
+ & ROUTED_NET_MASK;
+
+ if ((tdir & NO_NET == 0) && (tdir != 0) &&
+ (tdir != (net->netnum | ROUTED_NET))) {
+
+ if (layer < Num_layers - 1) {
+ tdirp = OBSVAL(seg->x1 - 1, seg->y1, layer + 1)
+ & ROUTED_NET_MASK;
+ if ((tdirp & NO_NET == 0) && (tdirp != 0) &&
+ (tdirp != (net->netnum | ROUTED_NET))) {
+
+ if (layer < Num_layers - 2) {
+ tdirpp = OBSVAL(seg->x1 - 1, seg->y1, layer + 2)
+ & ROUTED_NET_MASK;
+ if (tdirp == tdirpp) viaWU = 1;
+ }
+ }
+ if (tdir == tdirp) viaWM = 1;
+ }
+
+ if (layer > 0) {
+ tdirn = OBSVAL(seg->x1 - 1, seg->y1, layer - 1)
+ & ROUTED_NET_MASK;
+ if (tdir == tdirn) viaWL = 1;
+ }
+ }
}
- else if ((seg->x1 < NumChannelsX[layer + 1] - 1)
- && ((tdir = (OBSVAL(seg->x1 + 1, seg->y1,
- layer + 1) & ROUTED_NET_MASK)) !=
- (net->netnum | ROUTED_NET)) &&
- (((tdir & (ROUTED_NET | NO_NET)) == ROUTED_NET))) {
- pathvia(Cmd, layer, x - viaOffsetX[layer][1],
- y, lastx, lasty, seg->x1, seg->y1, invscale);
+
+ // Check for via to east
+ if (seg->x1 < NumChannelsX[layer] - 1) {
+ tdir = OBSVAL(seg->x1 + 1, seg->y1, layer)
+ & ROUTED_NET_MASK;
+
+ if ((tdir & NO_NET == 0) && (tdir != 0) &&
+ (tdir != (net->netnum | ROUTED_NET))) {
+
+ if (layer < Num_layers - 1) {
+ tdirp = OBSVAL(seg->x1 + 1, seg->y1, layer + 1)
+ & ROUTED_NET_MASK;
+ if ((tdirp & NO_NET == 0) && (tdirp != 0) &&
+ (tdirp != (net->netnum | ROUTED_NET))) {
+
+ if (layer < Num_layers - 2) {
+ tdirpp = OBSVAL(seg->x1 + 1, seg->y1, layer + 2)
+ & ROUTED_NET_MASK;
+ if (tdirp == tdirpp) viaEU = 1;
+ }
+ }
+ if (tdir == tdirp) viaEM = 1;
+ }
+
+ if (layer > 0) {
+ tdirn = OBSVAL(seg->x1 + 1, seg->y1, layer - 1)
+ & ROUTED_NET_MASK;
+ if (tdir == tdirn) viaEL = 1;
+ }
+ }
}
- else
- pathvia(Cmd, layer, x, y, lastx, lasty, seg->x1,
- seg->y1, invscale);
+
+ // Compute X offset
+ viaoffx = 0.0;
+
+ if (viaWL) viaoffx = viaOffsetX[layer][0];
+ else if (viaEL) viaoffx = -viaOffsetX[layer][0];
+
+ if (viaWM && viaOffsetX[layer][1] > viaoffx)
+ viaoffx = viaOffsetX[layer][1];
+ else if (viaEM && -viaOffsetX[layer][1] < viaoffx)
+ viaoffx = -viaOffsetX[layer][1];
+
+ if (viaWU && viaOffsetX[layer][2] > viaoffx)
+ viaoffx = viaOffsetX[layer][2];
+ else if (viaEU && -viaOffsetX[layer][2] < viaoffx)
+ viaoffx = -viaOffsetX[layer][2];
+
+ vx = (int)((REPS(viaoffx)) * oscale);
}
- else if (viaOffsetY[layer][1] > 0) {
- if (seg->y1 > 0 && ((tdir = (OBSVAL(seg->x1,
- seg->y1 - 1, layer + 1) & ROUTED_NET_MASK)) !=
- (net->netnum | ROUTED_NET)) &&
- (((tdir & (ROUTED_NET | NO_NET)) == ROUTED_NET))) {
- pathvia(Cmd, layer, x, y + viaOffsetY[layer][1],
- lastx, lasty, seg->x1, seg->y1, invscale);
+
+ // viaCheckY[layer] indicates whether a check for
+ // vias is needed. If so, record what vias are to north
+ // and south.
+
+ if (viaCheckY[layer] > 0) {
+
+ viaNL = viaNM = viaNU = 0;
+ viaSL = viaSM = viaSU = 0;
+
+ // Check for via to south
+ if (seg->y1 > 0) {
+ tdir = OBSVAL(seg->x1, seg->y1 - 1, layer)
+ & ROUTED_NET_MASK;
+
+ if (((tdir & NO_NET) == 0) && (tdir != 0) &&
+ (tdir != (net->netnum | ROUTED_NET))) {
+
+ if (layer < Num_layers - 1) {
+ tdirp = OBSVAL(seg->x1, seg->y1 - 1, layer + 1)
+ & ROUTED_NET_MASK;
+ if (((tdirp & NO_NET) == 0) && (tdirp != 0) &&
+ (tdirp != (net->netnum | ROUTED_NET))) {
+
+ if (layer < Num_layers - 2) {
+ tdirpp = OBSVAL(seg->x1, seg->y1 - 1, layer + 2)
+ & ROUTED_NET_MASK;
+ if (tdirp == tdirpp) viaSU = 1;
+ }
+ }
+ if (tdir == tdirp) viaSM = 1;
+ }
+
+ if (layer > 0) {
+ tdirn = OBSVAL(seg->x1, seg->y1 - 1, layer - 1)
+ & ROUTED_NET_MASK;
+ if (tdir == tdirn) viaSL = 1;
+ }
+ }
}
- else if ((seg->y1 < NumChannelsY[layer + 1] - 1)
- && ((tdir = (OBSVAL(seg->x1, seg->y1 + 1,
- layer + 1) & ROUTED_NET_MASK)) !=
- (net->netnum | ROUTED_NET)) &&
- (((tdir & (ROUTED_NET | NO_NET)) == ROUTED_NET))) {
- pathvia(Cmd, layer, x, y - viaOffsetY[layer][1],
- lastx, lasty, seg->x1, seg->y1, invscale);
+
+ // Check for via to north
+ if (seg->y1 < NumChannelsY[layer] - 1) {
+ tdir = OBSVAL(seg->x1, seg->y1 + 1, layer)
+ & ROUTED_NET_MASK;
+
+ if (((tdir & NO_NET) == 0) && (tdir != 0) &&
+ (tdir != (net->netnum | ROUTED_NET))) {
+
+ if (layer < Num_layers - 1) {
+ tdirp = OBSVAL(seg->x1, seg->y1 + 1, layer + 1)
+ & ROUTED_NET_MASK;
+ if (((tdirp & NO_NET) == 0) && (tdirp != 0) &&
+ (tdirp != (net->netnum | ROUTED_NET))) {
+
+ if (layer < Num_layers - 2) {
+ tdirpp = OBSVAL(seg->x1, seg->y1 + 1, layer + 2)
+ & ROUTED_NET_MASK;
+ if (tdirp == tdirpp) viaNU = 1;
+ }
+ }
+ if (tdir == tdirp) viaNM = 1;
+ }
+
+ if (layer > 0) {
+ tdirn = OBSVAL(seg->x1, seg->y1 + 1, layer - 1)
+ & ROUTED_NET_MASK;
+ if (tdir == tdirn) viaNL = 1;
+ }
+ }
}
- else
- pathvia(Cmd, layer, x, y, lastx, lasty, seg->x1,
- seg->y1, invscale);
+
+ // Compute Y offset
+ viaoffy = 0;
+
+ if (viaSL) viaoffy = viaOffsetY[layer][0];
+ else if (viaNL) viaoffy = -viaOffsetY[layer][0];
+
+ if (viaSM && viaOffsetY[layer][1] > viaoffy)
+ viaoffy = viaOffsetY[layer][1];
+ else if (viaNM && -viaOffsetY[layer][1] < viaoffy)
+ viaoffy = -viaOffsetY[layer][1];
+
+ if (viaSU && viaOffsetY[layer][2] > viaoffy)
+ viaoffy = viaOffsetY[layer][2];
+ else if (viaNU && -viaOffsetY[layer][2] < viaoffy)
+ viaoffy = -viaOffsetY[layer][2];
+
+ vy = (int)((REPS(viaoffy)) * oscale);
}
- else
- pathvia(Cmd, layer, x, y, lastx, lasty, seg->x1,
- seg->y1, invscale);
+
+ // via-to-via interactions are symmetric, so move each
+ // via half the distance (?)
+
+ pathvia(Cmd, layer, x + vx, y + vy, lastx, lasty,
+ seg->x1, seg->y1, invscale);
lastx = x;
lasty = y;
@@ -3594,30 +3844,165 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
if (special == (u_char)1 && Pathon != -1) Pathon = 0;
// Check last position for terminal offsets
- if (seg && ((seg != saveseg)
- || (seg->segtype & ST_WIRE))) {
+ if (seg && ((seg != saveseg) || (seg->segtype & ST_WIRE))) {
cancel = FALSE;
layer = seg->layer;
- dir2 = OBSVAL(seg->x2, seg->y2, layer);
- dir2 &= PINOBSTRUCTMASK;
- if (dir2 && !(seg->segtype & (ST_OFFSET_END | ST_OFFSET_START))) {
+ lnode = (layer < Pinlayers) ? NODEIPTR(seg->x2, seg->y2, layer) : NULL;
+
+ // Look for stub routes and offset taps
+ dir2 = OBSVAL(seg->x2, seg->y2, layer) & (STUBROUTE | OFFSET_TAP);
+
+ if ((dir2 & OFFSET_TAP) && (seg->segtype & ST_VIA) && prevseg) {
+
+ // Additional handling for offset taps. When a tap position
+ // is a via and is offset in the direction of the last
+ // route segment, then a DRC violation can be created if
+ // (1) the via is wider than the route width, and (2) the
+ // adjacent track position is another via or a bend in the
+ // route, and (3) the tap offset is large enough to create
+ // a spacing violation between the via and the adjacent via
+ // or perpendicular route. If these three conditions are
+ // satisfied, then generate a stub route the width of the
+ // via and one track pitch in length back toward the last
+ // track position.
+
+ // Problems only arise when the via width is larger than
+ // the width of the metal route leaving the via.
+
+ offset = lnode->offset;
+ if (LefGetViaWidth(seg->layer, lastseg->layer, 1 - horizontal) >
+ LefGetRouteWidth(lastseg->layer)) {
+
+ // Problems only arise when the last segment is exactly
+ // one track long.
+
+ if ((ABSDIFF(lastseg->x2, lastseg->x1) == 1) ||
+ (ABSDIFF(lastseg->y2, lastseg->y1) == 1)) {
+
+ if (prevseg->segtype & ST_VIA) {
+
+ dc = Xlowerbound + (double)seg->x1 * PitchX[layer];
+ x = (int)((REPS(dc)) * oscale);
+ dc = Ylowerbound + (double)seg->y1 * PitchY[layer];
+ y = (int)((REPS(dc)) * oscale);
+
+ dc = Xlowerbound + (double)prevseg->x1 * PitchX[layer];
+ x2 = (int)((REPS(dc)) * oscale);
+ dc = Ylowerbound + (double)prevseg->y1 * PitchY[layer];
+ y2 = (int)((REPS(dc)) * oscale);
+
+ // Setup is (via, 1 track route, via with offset)
+
+ if (prevseg->x1 != seg->x1) {
+ if ((PitchX[lastseg->layer] -
+ 0.5 * LefGetViaWidth(seg->layer, lastseg->layer, 1) -
+ 0.5 * LefGetViaWidth(prevseg->layer, lastseg->layer, 1) -
+ (prevseg->x1 - seg->x1) * offset)
+ < LefGetRouteSpacing(lastseg->layer)) {
+ if (special == (u_char)0) {
+ rt->flags |= RT_STUB;
+ net->flags |= NET_STUB;
+ }
+ else {
+ pathstart(Cmd, lastseg->layer, x, y,
+ (u_char)1, oscale, invscale, 1);
+ pathto(Cmd, x2, y2, 1, x, y, invscale);
+ lastx = x2;
+ lasty = y2;
+ }
+ }
+ }
+ else if (prevseg->y1 != seg->y1) {
+ if ((PitchY[lastseg->layer] -
+ 0.5 * LefGetViaWidth(seg->layer, lastseg->layer, 0) -
+ 0.5 * LefGetViaWidth(prevseg->layer, lastseg->layer, 0)
+ - (prevseg->y1 - seg->y1) * offset)
+ < LefGetRouteSpacing(lastseg->layer)) {
+ if (special == (u_char)0) {
+ rt->flags |= RT_STUB;
+ net->flags |= NET_STUB;
+ }
+ else {
+ pathstart(Cmd, lastseg->layer, x, y,
+ (u_char)1, oscale, invscale, 0);
+ pathto(Cmd, x2, y2, 0, x, y, invscale);
+ lastx = x2;
+ lasty = y2;
+ }
+ }
+ }
+ }
+ else { // Metal route bends at next track
+ if (prevseg->x1 != seg->x1) {
+ if ((PitchX[lastseg->layer] -
+ 0.5 * LefGetViaWidth(seg->layer, lastseg->layer, 1) -
+ 0.5 * LefGetRouteWidth(prevseg->layer) -
+ (prevseg->x1 - seg->x1) * offset)
+ < LefGetRouteSpacing(lastseg->layer)) {
+ if (special == (u_char)0) {
+ rt->flags |= RT_STUB;
+ net->flags |= NET_STUB;
+ }
+ else {
+ pathstart(Cmd, lastseg->layer, x, y,
+ (u_char)1, oscale, invscale, 1);
+ pathto(Cmd, x2, y2, 1, x, y, invscale);
+ lastx = x2;
+ lasty = y2;
+ }
+ }
+ }
+ else if (prevseg->y1 != seg->y1) {
+ if ((PitchY[lastseg->layer] -
+ 0.5 * LefGetViaWidth(seg->layer, lastseg->layer, 0) -
+ 0.5 * LefGetRouteWidth(prevseg->layer) -
+ (prevseg->y1 - seg->y1) * offset)
+ < LefGetRouteSpacing(lastseg->layer)) {
+ if (special == (u_char)0) {
+ rt->flags |= RT_STUB;
+ net->flags |= NET_STUB;
+ }
+ else {
+ pathstart(Cmd, lastseg->layer, x, y,
+ (u_char)1, oscale, invscale, 0);
+ pathto(Cmd, x2, y2, 0, x, y, invscale);
+ lastx = x2;
+ lasty = y2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // For stub routes, reset the path between terminals, since
+ // the stubs are not connected.
+ if (special == (u_char)1 && Pathon != -1) Pathon = 0;
+
+ // Handling of stub routes
+ if (dir2 & STUBROUTE) {
+ stub = lnode->stub;
if ((special == (u_char)0) && (Verbose > 2))
Fprintf(stdout, "Stub route distance %g to terminal"
" at %d %d (%d)\n",
- STUBVAL(seg->x2, seg->y2, layer),
- seg->x2, seg->y2, layer);
+ stub, seg->x2, seg->y2, layer);
dc = Xlowerbound + (double)seg->x2 * PitchX[layer];
+ if (lnode->flags & NI_OFFSET_EW)
+ dc += offset;
x = (int)((REPS(dc)) * oscale);
- if (dir2 == STUBROUTE_EW)
- dc += STUBVAL(seg->x2, seg->y2, layer);
+ if (lnode->flags & NI_STUB_EW)
+ dc += stub;
x2 = (int)((REPS(dc)) * oscale);
dc = Ylowerbound + (double)seg->y2 * PitchY[layer];
+ if (lnode->flags & NI_OFFSET_NS)
+ dc += offset;
y = (int)((REPS(dc)) * oscale);
- if (dir2 == STUBROUTE_NS)
- dc += STUBVAL(seg->x2, seg->y2, layer);
+ if (lnode->flags & NI_STUB_NS)
+ dc += stub;
y2 = (int)((REPS(dc)) * oscale);
- if (dir2 == STUBROUTE_EW) {
+ if (lnode->flags & NI_STUB_EW) {
horizontal = TRUE;
// If the gridpoint ahead of the stub has a route
@@ -3630,8 +4015,7 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
tdir = OBSVAL(seg->x2 + 1, seg->y2, layer);
if ((tdir & ROUTED_NET_MASK) ==
(net->netnum | ROUTED_NET)) {
- if (STUBVAL(seg->x1, seg->y2, layer) +
- LefGetRouteKeepout(layer) >= PitchX[layer]) {
+ if (stub + LefGetRouteKeepout(layer) >= PitchX[layer]) {
dc = Xlowerbound + (double)(seg->x2 + 1)
* PitchX[layer];
x2 = (int)((REPS(dc)) * oscale);
@@ -3642,8 +4026,7 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
tdir = OBSVAL(seg->x2 - 1, seg->y2, layer);
if ((tdir & ROUTED_NET_MASK) ==
(net->netnum | ROUTED_NET)) {
- if (-STUBVAL(seg->x2, seg->y2, layer) +
- LefGetRouteKeepout(layer) >= PitchX[layer]) {
+ if (-stub + LefGetRouteKeepout(layer) >= PitchX[layer]) {
dc = Xlowerbound + (double)(seg->x2 - 1)
* PitchX[layer];
x2 = (int)((REPS(dc)) * oscale);
@@ -3677,7 +4060,7 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
if (seg->x1 != seg->x2) cancel = TRUE;
}
}
- else {
+ else { /* lnode->flags & NI_STUB_EW implied */
horizontal = FALSE;
// If the gridpoint ahead of the stub has a route
@@ -3690,8 +4073,7 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
tdir = OBSVAL(seg->x2, seg->y2 + 1, layer);
if ((tdir & ROUTED_NET_MASK) ==
(net->netnum | ROUTED_NET)) {
- if (STUBVAL(seg->x2, seg->y2, layer) +
- LefGetRouteKeepout(layer) >= PitchY[layer]) {
+ if (stub + LefGetRouteKeepout(layer) >= PitchY[layer]) {
dc = Ylowerbound + (double)(seg->y2 + 1)
* PitchY[layer];
y2 = (int)((REPS(dc)) * oscale);
@@ -3702,8 +4084,7 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
tdir = OBSVAL(seg->x2, seg->y2 - 1, layer);
if ((tdir & ROUTED_NET_MASK) ==
(net->netnum | ROUTED_NET)) {
- if (-STUBVAL(seg->x1, seg->y2, layer) +
- LefGetRouteKeepout(layer) >= PitchY[layer]) {
+ if (-stub + LefGetRouteKeepout(layer) >= PitchY[layer]) {
dc = Ylowerbound + (double)(seg->y2 - 1)
* PitchY[layer];
y2 = (int)((REPS(dc)) * oscale);
@@ -3751,126 +4132,6 @@ emit_routed_net(FILE *Cmd, NET net, u_char special, double oscale, int iscale)
lasty = y2;
}
}
- else if (dir2 && (seg->segtype & ST_VIA) && prevseg) {
- // (seg->segtype & (ST_OFFSET_END | ST_OFFSET_START)) != 0
- // is implied.
- //
- // Additional handling for offset taps. When a tap position
- // is a via and is offset in the direction of the last
- // route segment, then a DRC violation can be created if
- // (1) the via is wider than the route width, and (2) the
- // adjacent track position is another via or a bend in the
- // route, and (3) the tap offset is large enough to create
- // a spacing violation between the via and the adjacent via
- // or perpendicular route. If these three conditions are
- // satisfied, then generate a stub route the width of the
- // via and one track pitch in length back toward the last
- // track position.
-
- // Problems only arise when the via width is larger than
- // the width of the metal route leaving the via.
-
- if (LefGetViaWidth(seg->layer, lastseg->layer, 1 - horizontal) >
- LefGetRouteWidth(lastseg->layer)) {
-
- // Problems only arise when the last segment is exactly
- // one track long.
-
- if ((ABSDIFF(lastseg->x2, lastseg->x1) == 1) ||
- (ABSDIFF(lastseg->y2, lastseg->y1) == 1)) {
-
- if (prevseg->segtype & ST_VIA) {
-
- dc = Xlowerbound + (double)seg->x1 * PitchX[layer];
- x = (int)((REPS(dc)) * oscale);
- dc = Ylowerbound + (double)seg->y1 * PitchY[layer];
- y = (int)((REPS(dc)) * oscale);
-
- dc = Xlowerbound + (double)prevseg->x1 * PitchX[layer];
- x2 = (int)((REPS(dc)) * oscale);
- dc = Ylowerbound + (double)prevseg->y1 * PitchY[layer];
- y2 = (int)((REPS(dc)) * oscale);
-
- // Setup is (via, 1 track route, via with offset)
-
- if (prevseg->x1 != seg->x1) {
- if ((PitchX[lastseg->layer] -
- 0.5 * LefGetViaWidth(seg->layer, lastseg->layer, 1) -
- 0.5 * LefGetViaWidth(prevseg->layer, lastseg->layer, 1) -
- (prevseg->x1 - seg->x1) *
- STUBVAL(seg->x2, seg->y2, seg->layer))
- < LefGetRouteSpacing(lastseg->layer)) {
- if (special == (u_char)0) {
- rt->flags |= RT_STUB;
- net->flags |= NET_STUB;
- }
- else {
- pathstart(Cmd, lastseg->layer, x, y,
- (u_char)1, oscale, invscale, 1);
- pathto(Cmd, x2, y2, 1, x, y, invscale);
- }
- }
- }
- else if (prevseg->y1 != seg->y1) {
- if ((PitchY[lastseg->layer] -
- 0.5 * LefGetViaWidth(seg->layer, lastseg->layer, 0) -
- 0.5 * LefGetViaWidth(prevseg->layer, lastseg->layer, 0)
- - (prevseg->y1 - seg->y1) *
- STUBVAL(seg->x2, seg->y2, seg->layer))
- < LefGetRouteSpacing(lastseg->layer)) {
- if (special == (u_char)0) {
- rt->flags |= RT_STUB;
- net->flags |= NET_STUB;
- }
- else {
- pathstart(Cmd, lastseg->layer, x, y,
- (u_char)1, oscale, invscale, 0);
- pathto(Cmd, x2, y2, 0, x, y, invscale);
- }
- }
- }
- }
- else { // Metal route bends at next track
- if (prevseg->x1 != seg->x1) {
- if ((PitchX[lastseg->layer] -
- 0.5 * LefGetViaWidth(seg->layer, lastseg->layer, 1) -
- 0.5 * LefGetRouteWidth(prevseg->layer) -
- (prevseg->x1 - seg->x1) *
- STUBVAL(seg->x2, seg->y2, seg->layer))
- < LefGetRouteSpacing(lastseg->layer)) {
- if (special == (u_char)0) {
- rt->flags |= RT_STUB;
- net->flags |= NET_STUB;
- }
- else {
- pathstart(Cmd, lastseg->layer, x, y,
- (u_char)1, oscale, invscale, 1);
- pathto(Cmd, x2, y2, 1, x, y, invscale);
- }
- }
- }
- else if (prevseg->y1 != seg->y1) {
- if ((PitchY[lastseg->layer] -
- 0.5 * LefGetViaWidth(seg->layer, lastseg->layer, 0) -
- 0.5 * LefGetRouteWidth(prevseg->layer) -
- (prevseg->y1 - seg->y1) *
- STUBVAL(seg->x2, seg->y2, seg->layer))
- < LefGetRouteSpacing(lastseg->layer)) {
- if (special == (u_char)0) {
- rt->flags |= RT_STUB;
- net->flags |= NET_STUB;
- }
- else {
- pathstart(Cmd, lastseg->layer, x, y,
- (u_char)1, oscale, invscale, 0);
- pathto(Cmd, x2, y2, 0, x, y, invscale);
- }
- }
- }
- }
- }
- }
- }
}
if (Pathon != -1) Pathon = 0;
@@ -4116,6 +4377,9 @@ static void helpmessage(void)
Fprintf(stdout, "\t-i <file>\t\t\tPrint route names and pitches and exit.\n");
Fprintf(stdout, "\t-p <name>\t\t\tSpecify global power bus name.\n");
Fprintf(stdout, "\t-g <name>\t\t\tSpecify global ground bus name.\n");
+ Fprintf(stdout, "\t-r <value>\t\t\tForce output resolution scale.\n");
+ Fprintf(stdout, "\t-f \t\t\tForce all pins to be routable.\n");
+ Fprintf(stdout, "\t-k <level>\t\t\tLevel of effort to keep trying.\n");
Fprintf(stdout, "\n");
}
#ifdef TCL_QROUTER
diff --git a/qrouter.h b/qrouter.h
index 343d644..2ed1b68 100644
--- a/qrouter.h
+++ b/qrouter.h
@@ -42,9 +42,6 @@ typedef unsigned long u_long;
/* Maximum number of route layers */
#define MAX_LAYERS 9
-/* Maximum number of pins in a gate */
-#define MAX_GATE_NODES 64
-
/* Cell name (and other names) max length */
#define MAX_NAME_LEN 1024
@@ -194,6 +191,11 @@ struct route_ {
u_char flags; // See below for flags
};
+/* Definitions for flags in struct route_ */
+
+#define RT_OUTPUT 0x1 // Route has been output
+#define RT_STUB 0x2 // Route has at least one stub route
+
/* Structure used to hold nodes, saved nodes, and stub/offset info */
typedef struct nodeinfo_ *NODEINFO;
@@ -201,13 +203,19 @@ typedef struct nodeinfo_ *NODEINFO;
struct nodeinfo_ {
NODE nodesav;
NODE nodeloc;
- float stub;
+ float stub; // Stub route to node
+ float offset; // Tap offset
+ u_char flags;
};
-/* Definitions for flags in struct route_ */
+/* Definitions for flags in stuct nodeinfo_ */
-#define RT_OUTPUT 0x1 // Route has been output
-#define RT_STUB 0x2 // Route has been output
+#define NI_STUB_NS 0x01 // Stub route north(+)/south(-)
+#define NI_STUB_EW 0x02 // Stub route east(+)/west(-)
+#define NI_STUB_MASK 0x03 // Stub route mask (N/S + E/W)
+#define NI_OFFSET_NS 0x04 // Tap offset north(+)/south(-)
+#define NI_OFFSET_EW 0x08 // Tap offset east(+)/west(-)
+#define NI_OFFSET_MASK 0x0c // Tap offset mask (N/S + E/W)
struct node_ {
NODE next;
@@ -230,14 +238,14 @@ typedef struct gate_ *GATE;
struct gate_ {
GATE next;
- char *gatename; // Name of instance
- GATE gatetype; // Pointer to macro record
- int nodes; // number of nodes on this gate
- char *node[MAX_GATE_NODES]; // names of the pins on this gate
- int netnum[MAX_GATE_NODES]; // net number connected to each pin
- NODE noderec[MAX_GATE_NODES]; // node record for each pin
- DSEG taps[MAX_GATE_NODES]; // list of gate node locations and layers
- DSEG obs; // list of obstructions in gate
+ char *gatename; // Name of instance
+ GATE gatetype; // Pointer to macro record
+ int nodes; // number of nodes on this gate
+ char **node; // names of the pins on this gate
+ int *netnum; // net number connected to each pin
+ NODE *noderec; // node record for each pin
+ DSEG *taps; // list of gate node locations and layers
+ DSEG obs; // list of obstructions in gate
double width, height;
double placedX;
double placedY;
@@ -310,12 +318,12 @@ struct routeinfo_ {
// The maximum number of nets must not overrun the area used by flags, so
// the maximum number of nets is 0x1fffff, or 2,097,151 nets
-#define PINOBSTRUCTMASK ((u_int)0xe0000000) // takes values from below
-#define STUBROUTE_NS ((u_int)0x20000000) // route north or south to reach terminal
-#define STUBROUTE_EW ((u_int)0x40000000) // route east or west to reach terminal
-#define STUBROUTE_X ((u_int)0x60000000) // diagonal---not routable
-#define OFFSET_TAP ((u_int)0x80000000) // position needs to be offset
-#define NO_NET ((u_int)0x10000000) // indicates a non-routable obstruction
+#define OFFSET_TAP ((u_int)0x80000000) // tap position needs to be offset
+#define STUBROUTE ((u_int)0x40000000) // route stub to reach terminal
+#define PINOBSTRUCTMASK ((u_int)0xc0000000) // either offset tap or stub route
+#define NO_NET ((u_int)0x20000000) // indicates a non-routable obstruction
+#define ROUTED_NET ((u_int)0x10000000) // indicates position occupied by a routed
+
#define BLOCKED_N ((u_int)0x08000000) // grid point cannot be routed from the N
#define BLOCKED_S ((u_int)0x04000000) // grid point cannot be routed from the S
#define BLOCKED_E ((u_int)0x02000000) // grid point cannot be routed from the E
@@ -323,23 +331,19 @@ struct routeinfo_ {
#define BLOCKED_U ((u_int)0x00800000) // grid point cannot be routed from top
#define BLOCKED_D ((u_int)0x00400000) // grid point cannot be routed from bottom
#define BLOCKED_MASK ((u_int)0x0fc00000)
-#define ROUTED_NET ((u_int)0x00200000) // indicates position occupied by a routed
- // net
-#define MAX_NETNUMS ((u_int)0x001fffff) // Maximum net number
+#define OBSTRUCT_MASK ((u_int)0x0000000f) // with NO_NET, directional obstruction
+#define OBSTRUCT_N ((u_int)0x00000008) // Tells where the obstruction is
+#define OBSTRUCT_S ((u_int)0x00000004) // relative to the grid point. Nodeinfo
+#define OBSTRUCT_E ((u_int)0x00000002) // offset contains distance to grid point
+#define OBSTRUCT_W ((u_int)0x00000001)
+#define MAX_NETNUMS ((u_int)0x003fffff) // Maximum net number
-#define NETNUM_MASK ((u_int)0x101fffff) // Mask for the net number field
+#define NETNUM_MASK ((u_int)0x203fffff) // Mask for the net number field
// (includes NO_NET)
-#define ROUTED_NET_MASK ((u_int)0x103fffff) // Mask for the net number field
+#define ROUTED_NET_MASK ((u_int)0x303fffff) // Mask for the net number field
// (includes NO_NET and ROUTED_NET)
#define DRC_BLOCKAGE (NO_NET | ROUTED_NET) // Special case
-// Definitions used along with the NO_NET bit.
-#define OBSTRUCT_MASK ((u_int)0x0000000f) // Tells where obstruction is
-#define OBSTRUCT_N ((u_int)0x00000008) // relative to the grid point.
-#define OBSTRUCT_S ((u_int)0x00000004) // Stub[] contains distance of
-#define OBSTRUCT_E ((u_int)0x00000002) // obstruction to grid point.
-#define OBSTRUCT_W ((u_int)0x00000001)
-
// Map and draw modes
#define MAP_NONE 0x0 // No map (blank background)
#define MAP_OBSTRUCT 0x1 // Make a map of obstructions and pins
@@ -389,13 +393,10 @@ extern u_char *RMask;
extern u_int *Obs[MAX_LAYERS]; // obstructions by layer, y, x
extern PROUTE *Obs2[MAX_LAYERS]; // working copy of Obs
extern float *Obsinfo[MAX_LAYERS]; // temporary detailed obstruction info
-extern NODEINFO Nodeinfo[MAX_LAYERS]; // stub route distances to pins and
+extern NODEINFO *Nodeinfo[MAX_LAYERS]; // stub route distances to pins and
// pointers to node structures.
-#define NODEIPTR(x, y, l) (&(Nodeinfo[l][OGRID(x, y, l)]))
-#define NODESAV(x, y, l) (Nodeinfo[l][OGRID(x, y, l)].nodesav)
-#define NODELOC(x, y, l) (Nodeinfo[l][OGRID(x, y, l)].nodeloc)
-#define STUBVAL(x, y, l) (Nodeinfo[l][OGRID(x, y, l)].stub)
+#define NODEIPTR(x, y, l) (Nodeinfo[l][OGRID(x, y, l)])
#define OBSINFO(x, y, l) (Obsinfo[l][OGRID(x, y, l)])
#define OBSVAL(x, y, l) (Obs[l][OGRID(x, y, l)])
#define OBS2VAL(x, y, l) (Obs2[l][OGRID(x, y, l)])
diff --git a/qrouter.sh.in b/qrouter.sh.in
index 8380122..12bab42 100755
--- a/qrouter.sh.in
+++ b/qrouter.sh.in
@@ -26,18 +26,35 @@ fi
# Also, if "-i", "-h", or "-c" is specified, then this is
# a batch-mode operation and the console should be ignored.
TKCON=true
+NULLG=
+ARGS=""
for i in $@ ; do
case $i in
-noc*)
TKCON=
- shift
;;
- -i* | -h* | -c* )
+ -nog*)
+ NULLG=true
TKCON=
;;
+ -c*)
+ TKCON=
+ ARGS="$ARGS $i"
+ ;;
+ -i* | -h*)
+ NULLG=true
+ TKCON=
+ ARGS="$ARGS $i"
+ ;;
+ *)
+ ARGS="$ARGS $i"
+ ;;
esac
done
+set -- junk $ARGS
+shift
+
if [ $TKCON ]; then
exec ${loclibdir}/tkcon.tcl \
@@ -52,6 +69,9 @@ else
# *only* needed when running without the console; the console itself is
# capable of sourcing the startup script.
#
- exec ${loclibdir}/qrouterexec -- $@
-
+ if [ $NULLG ]; then
+ exec ${loclibdir}/qrouternullg -- $@
+ else
+ exec ${loclibdir}/qrouterexec -- $@
+ fi
fi
diff --git a/qrouter.tcl.in b/qrouter.tcl.in
index 98e254a..61a1509 100644
--- a/qrouter.tcl.in
+++ b/qrouter.tcl.in
@@ -155,7 +155,7 @@ proc qrouter::lowerconsole {} {
consoledown
}
-puts stdout "Qrouter detail maze router version VERSION.REVISION"
+puts stdout "Qrouter detail maze router version VERSION.REVISION.T"
set autoquit 0
set autoroute 0
diff --git a/qrouternullg.c b/qrouternullg.c
new file mode 100644
index 0000000..4c6313e
--- /dev/null
+++ b/qrouternullg.c
@@ -0,0 +1,49 @@
+/*----------------------------------------------------------------------*/
+/* qrouternullg.c */
+/*----------------------------------------------------------------------*/
+
+#include <stdio.h>
+
+#include <tcl.h>
+
+/*----------------------------------------------------------------------*/
+/* Application initiation. This is exactly like the AppInit routine */
+/* for "tclsh", minus the cruft, but with "tcl_rcFileName" set to */
+/* "qrouter.tcl" instead of "~/.tclshrc". */
+/*----------------------------------------------------------------------*/
+
+int
+qrouter_AppInit(interp)
+ Tcl_Interp *interp;
+{
+ if (Tcl_Init(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /* This is where we replace the home ".wishrc" file with */
+ /* qrouter's startup script. */
+
+ Tcl_SetVar(interp, "tcl_rcFileName", QROUTER_PATH "/qrouter.tcl",
+ TCL_GLOBAL_ONLY);
+
+ /* Additional variable can be used to tell if qrouter is in non- */
+ /* graphics mode. */
+ Tcl_SetVar(interp, "no_graphics_mode", "true", TCL_GLOBAL_ONLY);
+
+ return TCL_OK;
+}
+
+/*----------------------------------------------------------------------*/
+/* The main procedure; replacement for "tclsh". */
+/*----------------------------------------------------------------------*/
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ Tcl_Main(argc, argv, qrouter_AppInit);
+ return 0;
+}
+
+/*----------------------------------------------------------------------*/
diff --git a/tclqrouter.c b/tclqrouter.c
index b54854d..7a36311 100644
--- a/tclqrouter.c
+++ b/tclqrouter.c
@@ -577,9 +577,9 @@ qrouter_start(ClientData clientData, Tcl_Interp *interp,
/* which is not handled by runqrouter(), and source the */
/* script <name> between runqrouter() and read_def(). */
- argv = (char **)malloc(objc * sizeof(char *));
+ argv = (char **)malloc((objc - 1) * sizeof(char *));
argc = 0;
- for (i = 0; i < objc; i++) {
+ for (i = 1; i < objc; i++) {
if (!strcmp(Tcl_GetString(objv[i]), "-s"))
scriptfile = strdup(Tcl_GetString(objv[++i]));
else