PCB part 9 of 10
Andreas Nowatzyk
agn at cmu-cs-unh.ARPA
Wed Aug 14 08:31:02 AEST 1985
#
# type sh /usru0/agn/pcb/distr/../usenet/part9 to unpack this archive.
#
echo extracting pupdate.c...
cat >pupdate.c <<'!E!O!F!'
/***************************************************************\
* *
* PCB program *
* *
* Reverse Engineering and Patch Department *
* *
* (c) 1985 A. Nowatzyk *
* *
\***************************************************************/
#include <stdio.h>
#include "pparm.h"
#include "pcdst.h"
extern rot_m[4][4]; /* rotation matrix (in pplace) */
FILE *fwantread (), *fwantwrite ();
extern float scalef; /* scale factor */
static int brutal; /* =1 remove old stuff */
P_list () /* list internal structures */
{
static char *mtext[] = {
"Type file",
"Component file",
"Netlist" };
switch (menu (mtext, 3)) {
case 0:
TY_list ();
break;
case 1:
CP_list ();
break;
case 2:
NL_list ();
break;
}
}
/*ARGSUSED*/
P_update (ctx) /* update internal structures */
int ctx;
{
static char *mtext[] = {
"Type file",
"Component file",
"Netupdate" };
if (V.cnet)
deseln (V.cnet);
switch (menu (mtext, 3)) {
case 0:
TY_update ();
break;
case 1:
CP_update ();
break;
case 2:
NL_update ();
break;
}
return net_sel (START);
}
TY_list () /* list type file */
{
FILE *opf, *fwantwrite ();
static char *ptype[] = { "GND", "Vcc", "Vee", "Vtt" };
char fname[80];
register int i, j, k;
register struct pin *pin;
float cf = 1.0 / rsun;
opf = fwantwrite (".", "test.ty", fname, "Type def. output file:", 1);
if (!opf) {
err_msg ("File open problem");
return;
}
Ferr_msg ("Busy: Listing types");
fputs ("*types:\n", opf);
for (i = 0; i < V.nty; i++) {
if (!strcmp (TY[i].name, DELETED))
continue;
fprintf (opf, "%s:\n", TY[i].name);
if (TY[i].cif) { /* external cif-symbol */
j = TY[i].cif - 1;
fprintf (opf, "EXTcif: %d\n", CIF[j].symn);
fprintf (opf, "Box: %.3f,%.3f\n",
(float) TY[i].x * cf, (float) TY[i].y * cf);
do {
if (CIF[j].blk)
fprintf (opf, "Block: %.3f,%.3f %.3f,%.3f\n",
(float) CIF[j].xl * cf, (float) CIF[j].yl * cf,
(float) CIF[j].xh * cf, (float) CIF[j].yh * cf );}
while (CIF[j++].flg);
}
for (pin = TY[i].p, j = 1; TY[i].np >= j; pin++, j++) {
if (k = pin -> p)
fprintf (opf, "%.3f,%.3f\t%s\n",
(float) (pin -> x) * cf, (float) (pin -> y) * cf,
ptype[--k]);
else
fprintf (opf, "%.3f,%.3f\tpin%d\n",
(float) (pin -> x) * cf, (float) (pin -> y) * cf, j);
}
fputs ("\n", opf);
}
fclose (opf);
err_msg ("Done");
beep ();
}
CP_list () /* list component file */
{
FILE *opf, *fwantwrite ();
char fname[80];
register int i;
float cf = 1.0 / rsun;
opf = fwantwrite (".", "test.cp", fname, "Component output file:", 1);
if (!opf) {
err_msg ("File open problem");
return;
}
Ferr_msg ("Busy: Listing components");
fputs ("*components:\n", opf);
for (i = 0; i < V.ncp; i++) {
if (!strcmp (CP[i].name, DELETED))
continue;
if (CP[i].unplaced)
fprintf (opf, "%s\t%s\t\t; ** unplaced **\n",
CP[i].name, CP[i].ty -> name);
else
fprintf (opf, "%s\t%s\t%.3f,%.3f\t%d\n",
CP[i].name, CP[i].ty -> name, (float) CP[i].x * cf,
(float) CP[i].y * cf, CP[i].r);
}
fclose (opf);
err_msg ("Done");
beep ();
}
static int nl_type; /* 0: Multiwire 1: DP */
static FILE *opf;
NL_list () /* list netlist */
{
FILE *fwantwrite ();
char fname[80];
register int i;
if (!placed) {
err_msg ("Place components first");
return;
}
opf = fwantwrite (".", "test.nl", fname, "Netlist output file:", 1);
if (!opf) {
err_msg ("File open problem");
return;
}
Ferr_msg ("Busy: Printing Netlist");
nl_type = NH[0].name[0] != '#'; /* decide on format */
if (nl_type)
fputs ("DPnetlist:\n", opf);
else
fputs ("Cnetlist:\n", opf);
pnt_net (&V.GND, 1); /* print special nets */
pnt_net (&V.VCC, 1);
pnt_net (&V.VEE, 1);
pnt_net (&V.VTT, 1);
for (i = 0; i < V.nnh; i++) /* print normal nets */
pnt_net (&NH[i], 0);
fclose (opf);
err_msg ("Done");
beep ();
}
pnt_net (net, sp) /* print a net */
struct nlhd *net;
int sp;
{
register int i;
register struct nlst *p;
static int nc; /* net counter for MW-format */
if (!(net -> l)) /* skip empty nets */
return;
nc++;
if (sp) /* reset net counter */
nc = 0;
for (p = net -> lp, i = 0; p; p = p -> n, i++) {/* scan net */
if (!(i & 7)) { /* denote net */
if (nl_type) { /* DP-type names */
if (sp) {
if (i)
fputc ('\n', opf);
fprintf (opf, "!%s\\", net -> name);}
else if (!i)
fprintf (opf, "%s\\", net -> name);}
else { /* Multi-wire names */
if (i)
fputc ('\n', opf);
if (sp)
fprintf (opf, "C%s\t", net -> name);
else
fprintf (opf, "%d\t", nc);
}
}
fprintf (opf, " %s-%d", CP[p -> c -> cpi].name, p -> c -> pn + 1);
}
fputc ('\n', opf);
}
static struct type new_ty; /* temporary place for a type def */
static struct pin *new_pin = 0;
static struct cif *new_cif = 0;
static int npn_max = 100, ncf_max = 50, lcnt, cif_cnt;
static FILE *inp;
TY_update ()
/**************************************************************************\
* *
* Update type file: *
* The stored type definitions are compared those supplied by the *
* file. Updates will be made only if the particular type is not in use. *
* *
\**************************************************************************/
{
char fname[80], *flgs, buf[80];
register int i;
float getfloat ();
inp = fwantread (".", "test.ty", fname, "New type definition file:");
if (!inp) {
err_msg ("Open failed");
return;
}
scalef = getfloat ("Scale factor for pin coordinates", 0.01, 100.0, 1.0);
brutal = getbool ("Brutal update", 0);
fgets (buf, inp_lnl, inp);
if (strncmp (buf, "*types:", 7)) {
printf ("Type-def file doesn't start with '*types:'");
err_msg ("Format error");
beep ();
fclose (inp);
return;
}
flgs = (char *) malloc (sizeof (char) * tymax);
for (i = 0; i < V.nty; flgs[i++] = 0);
lcnt = 1; /* reset line counter */
Ferr_msg ("Busy: type update");
while (i = get_ty ()) {
if (i < 0)
printf ("Skipping defective type definition\n");
else {
for (i = 0; i < V.nty; i++) /* try to find old def */
if (!strncmp (TY[i].name, new_ty.name, nmmax))
break;
if (i >= V.nty) {
printf ("Adding '%s'\n", new_ty.name);
add_TY (); /* add new type */
flgs[V.nty - 1] = 1;}
else {
if (flgs[i]) {
printf ("Line%d: '%s' multiply defined\n",
lcnt, new_ty.name);
continue;
}
flgs[i] = 1; /* this entry is referenced */
if (neq_TY (&TY[i])) {
if (replace_TY (&TY[i]))
printf ("New definition for '%s' loaded\n",
new_ty.name);
else
printf ("Cannot update '%s': in use\n",
new_ty.name);
}
}
}
}
for (i = 0; i <V.nty; i++)
if (!flgs[i] && strcmp (DELETED, TY[i].name)) {
strncpy (buf, TY[i].name, nmmax);
if (del_TY (&TY[i]))
printf ("Type '%s' deleted\n", buf);
else
printf ("Cannot delete '%s': in use\n", buf);
}
free (flgs); /* clean up & exit */
fclose (inp);
err_msg ("Done");
beep ();
}
get_ty () /* get a new type */
{
char buf[inp_lnl], nm[nmmax + 2], ga[nmmax + 2];
register int j, k, ix, iy, error = 0;
int i;
float x, y, x1, y1;
static char pln[4][4] = {"GND", "VCC", "VEE", "VBB"};
if(!fgets (buf, inp_lnl, inp))
return 0; /* no more types */
rms (buf);
lcnt++; /* count lines for error msg */
for (j = 0; (j < nmmax) && (buf[j] != ':'); j++)
new_ty.name[j] = buf[j];
if (buf[j] == ':') {
if (buf[j + 1] != '\0')
printf ("Line %d: warning: garbage ignored\n", lcnt);
new_ty.name[j] = '\0'; }
else
if (buf[j + 1] != ':')
printf ("Line %d: warning: missing ':'\n", lcnt);
new_ty.x = 0;
new_ty.y = 0;
new_ty.np = 0;
new_ty.cif = 0;
new_ty.p = nil;
cif_cnt = 0;
while (fgets (buf, inp_lnl, inp)) { /* read type body */
rms (buf);
lcnt++; /* count lines */
if (!strncmp (buf, "EXTCIF: ", 8)) { /*** EXTCIF ***/
j = sscanf (&buf[8], "%d", &i);
if (j != 1 || i < ex_cifL || i > ex_cifH || new_ty.cif) {
printf ("Line %d: illegal 'EXTcif'\n", lcnt);
error = 1;}
else {
if (!new_cif) /* need to allocate cif tab */
new_cif = (struct cif *) malloc
(sizeof (struct cif) * ncf_max);
else if (cif_cnt >= ncf_max) { /* too small */
ncf_max += 10 + ncf_max / 2;
new_cif = (struct cif *) realloc
(new_cif, sizeof (struct cif) * ncf_max);
}
new_cif[cif_cnt].symn = i;
new_cif[cif_cnt].flg = 0;
new_cif[cif_cnt].blk = 0;
new_ty.cif = 1;
}}
else if (!strncmp (buf, "BOX: ", 5)) { /*** BOX ***/
j = sscanf (&buf[5], "%f %f", &x, &y);
if (j != 2 || x < 0 || y < 0) {
printf ("Line %d: invalid 'Box' statement\n", lcnt);
error = 1;}
else {
ix = x * rsun * scalef + 0.5;
iy = y * rsun * scalef + 0.5;
if (new_ty.x < ix) new_ty.x = ix;
if (new_ty.y < iy) new_ty.y = iy;
}}
else if (!strncmp (buf, "BLOCK: ", 7)) { /*** BLOCK ***/
j = sscanf (&buf[7], "%f %f %f %f", &x, &y, &x1, &y1);
ix = x1 * rsun * scalef + 0.5;
iy = y1 * rsun * scalef + 0.5;
if (j != 4 || x < 0 || x1 < 0 || y < 0 || y1 < 0 ||
x > x1 || y > y1 || !new_ty.cif ||
ix > new_ty.x || iy > new_ty.y) {
printf ("Line %d: invalid 'Block' statement\n", lcnt);
error = 1;}
else {
if (new_cif[cif_cnt].blk) { /* need additional record */
new_cif[cif_cnt].flg = 1;
if (cif_cnt >= ncf_max) {
ncf_max += 10 + ncf_max / 2;
new_cif = (struct cif *) realloc
(new_cif, sizeof (struct cif) * ncf_max);
}
new_cif[++cif_cnt].flg = 0;
new_cif[cif_cnt].symn = new_cif[0].symn;
}
new_cif[cif_cnt].blk = 1;
new_cif[cif_cnt].xh = ix;
new_cif[cif_cnt].yh = iy;
new_cif[cif_cnt].xl = x * rsun * scalef + 0.5;
new_cif[cif_cnt].yl = y * rsun * scalef + 0.5;
}}
else { /*** normal pin statement ***/
j = sscanf (buf, "%f %f %s %s", &x, &y, nm, ga);
if (buf[0] == '\0')
break; /* end of one definition */
k = 0; /* default type */
switch (j) {
case 1:
printf ("Line %d: missing y - line ignored\n", lcnt);
error = 1;
break;
case 4:
printf ("Line %d: grabage '%s..' ignored\n", lcnt, ga);
error = 1;
break;
case 3:
for (k = 0; k < 4; ++k)
if (!strncmp (pln[k], nm, nmmax))
break;
k = (k + 1) % 5;
case 2:
if (!new_pin)
new_pin = (struct pin *) malloc (
sizeof (struct pin) * npn_max);
else if (new_ty.np >= npn_max) {
npn_max += 10 + npn_max / 2;
new_pin = (struct pin *) realloc (new_pin,
sizeof (struct pin) * npn_max);
}
new_ty.p = new_pin;
ix = x * rsun * scalef + 0.5;
iy = y * rsun * scalef + 0.5;
if (new_ty.x < ix) new_ty.x = ix;
if (new_ty.y < iy) new_ty.y = iy;
new_pin[new_ty.np].x = ix;
new_pin[new_ty.np].y = iy;
new_pin[new_ty.np++].p = k;
}
}
}
if (new_ty.y > new_ty.x)
printf ("Warning for '%s': y>x (text is aligned to the x-axis)\n",
new_ty.name);
return error ? -1 : 1;
}
add_TY () /* add new type definition */
{
register int i;
if (V.ncif + cif_cnt >= cifmax)
err ("EXTcif table too small: increase 'cifmax'", cifmax, 0, 0, 0);
if (V.npn + new_ty.np > pnmax)
err ("Pin table too small: increase 'pnmax'", pnmax, 0, 0, 0);
if (V.nty > tymax)
err ("Type table too small: increase 'tymax'", tymax, 0, 0, 0);
new_ty.p = &PN[V.npn]; /* adjust pointer and index */
if (new_ty.cif)
new_ty.cif = V.ncif + 1;
TY[V.nty++] = new_ty; /* enter type */
for (i = 0; i < new_ty.np; i++) /* copy pins */
PN[V.npn++] = new_pin[i];
if (new_ty.cif) { /* copy cif records */
for (i = 0; i <= cif_cnt; i++)
CIF[V.ncif++] = new_cif[i];
}
}
neq_TY (old)
struct type *old;
/************************************************************************\
* *
* .NE. types: *
* This function comapres 2 type definitions and returns a '1' if they *
* differ. The primary reason of difference is printed. *
* *
* Note: the second type is hardwired to 'new_ty' *
* *
\************************************************************************/
{
register int i, j;
if (new_ty.np != old -> np) {
printf ("Type '%s' - number of pins: old=%d new=%d\n",
new_ty.name, old -> np, new_ty.np);
return 1;
}
for (i = 0; i < new_ty.np; i++) {
if (new_pin[i].x != (old -> p)[i].x ||
new_pin[i].y != (old -> p)[i].y ) {
printf ("Type '%s' - pin%d has new position\n", new_ty.name, ++i);
return 1;
}
if (new_pin[i].p != (old -> p)[i].p) {
printf ("Type '%s' - pin%d has new type\n", new_ty.name, ++i);
return 1;
}
}
if (!new_ty.cif != !old -> cif) {
printf ("Type '%s' - type: old=%s new=%s\n", new_ty.name,
old -> cif ? "EXTcif" : "normal",
new_ty.cif ? "EXTcif" : "normal");
return 1;
}
if (new_ty.cif) {
i = 0;
j = old -> cif - 1;
do {
if (new_cif[i].symn != CIF[j].symn) {
printf ("Type '%s' - CIF number: old=%d new=%d\n",
new_ty.name, CIF[j].symn, new_cif[i].symn);
return 1;
}
if (new_cif[i].blk != CIF[j].blk) {
printf ("Type '%s' - different number of blocks\n",
new_ty.name);
return 1;
}
if (new_cif[i].blk && (
new_cif[i].xl != CIF[j].xl ||
new_cif[i].xh != CIF[j].xh ||
new_cif[i].yl != CIF[j].yl ||
new_cif[i].yh != CIF[j].yh )) {
printf ("Type '%s' - different block dimensions\n",
new_ty.name);
return 1;
}
j++;}
while (new_cif[i++].flg);
}
return 0; /* they match */
}
replace_TY (old)
struct type *old;
/**************************************************************************\
* *
* Replace a type definition: *
* The old type definition <old> is replaced by the new one in "new_ty". *
* A '1' is returned if the operation succeeds. A returned '0' indicates *
* that the type old type is in use and that no change was made. *
* *
\**************************************************************************/
{
register int i, j, new_p = 0, new_c = 0;
register struct pin *p;
for (i = 0; i < V.ncp; i++)
if (CP[i].ty == old) { /* is in use! */
if (brutal) {
printf ("Deleting component '%s'\n", CP[i].name);
del_CP (&CP[i]);}
else
return 0;
}
if (old -> np < new_ty.np)
new_p = 1; /* re-allocate pins */
j = 0; /* count old CIF records */
if (old -> cif) {
i = old -> cif - 1;
do j++;
while (CIF[i++].flg);
}
if (cif_cnt > j || !old -> cif)
new_c = 1; /* re-allocate cif stuff */
if (new_c && V.ncif + cif_cnt > cifmax)
err ("EXTcif table too small: increase 'cifmax'", cifmax, 0, 0, 0);
if (new_p && V.npn + new_ty.np > pnmax)
err ("Pin table too small: increase 'pnmax'", pnmax, 0, 0, 0);
new_ty.p = new_p ? &PN[V.npn] : old -> p;
/* adjust pointer and index */
if (new_ty.cif)
new_ty.cif = new_c ? V.ncif + 1 : old -> cif;
*old = new_ty; /* enter type */
if (new_p) { /* copy pins */
for (i = 0; i < new_ty.np; i++)
PN[V.npn++] = new_pin[i];}
else {
for (i = 0, p = new_ty.p; i < new_ty.np; i++)
*(p++) = new_pin[i];
}
if (new_ty.cif) { /* copy cif records */
for (i = 0, j = new_ty.cif - 1; i <= cif_cnt; i++)
CIF[j++] = new_cif[i];
if (new_c)
V.ncif = j;
}
return 1;
}
del_TY (old)
struct type *old;
/*************************************************************\
* *
* Delete a type definition: *
* The type definition will be made inaccessable (the input *
* filter 'rms' does not pass lower case characters. The *
* space is not freed! A returned '0' indicates that the *
* delete failed because the Type definition is in use. *
* *
\*************************************************************/
{
register int i;
for (i = 0; i < V.ncp; i++)
if (CP[i].ty == old) /* is in use! */
return 0;
strcpy (old -> name, DELETED); /* Note: lower case letters */
return 1;
}
static struct comp new_cp;
CP_update () /* update component file */
{
char buf[80], *flgs;
float getfloat ();
register int i;
inp = fwantread (".", "test.cp", buf, "Component definition file:");
if (!inp) {
err_msg ("open failed");
return;
}
fgets (buf, inp_lnl, inp);
if (strncmp (buf, "*components:", 12)) {
err_msg ("Format error");
printf ("Component-def file doesn't start with '*components:'\n");
beep ();
fclose (inp);
return;
}
scalef = getfloat ("Scale factor for componnet coordinates",
0.01, 100.0, 1.0);
brutal = getbool ("Brutal update", 0);
flgs = (char *) malloc (sizeof (char) * cpmax);
for (i = 0; i < V.ncp; flgs[i++] = 0);
lcnt = 1; /* reset line counter */
Ferr_msg ("Busy: updating components");
while (i = get_CP ()) {
if (i < 0) {
printf ("Defect component skipped\n");
continue;
}
for (i = 0; i < V.ncp; i++)
if (!strncmp (CP[i].name, new_cp.name, nmmax))
break;
if (i >= V.ncp) { /* add new component */
printf ("Adding '%s'\n", new_cp.name);
add_CP ();
flgs[V.ncp - 1] = 1;}
else {
if (flgs[i]) {
printf ("Line %d: '%s' multiple defined\n",
lcnt, new_cp.name);
continue;
}
flgs[i] = 1; /* flag reference */
if (neq_CP (&CP[i])) {
if (replace_CP (&CP[i]))
printf ("New definition for '%s' loaded\n", new_cp.name);
else
printf ("Cannot update '%s': in use\n", new_cp.name);
}
}
}
for (i = 0; i <V.ncp; i++)
if (!flgs[i] && strcmp (CP[i].name, DELETED)) {
strncpy (buf, CP[i].name, nmmax);
if (del_CP (&CP[i]))
printf ("Component '%s' deleted\n", buf);
else
printf ("Cannot delete '%s': in use\n", buf);
}
placed = 0; /* revaluate net location */
free (flgs); /* clean up & exit */
fclose (inp);
err_msg ("Done");
beep ();
}
get_CP ()
/*********************************************************************\
* *
* Get a new component *
* A returned '-1' indicates a some trouble, '1' success and '0' EOF *
* *
\*********************************************************************/
{
char buf[inp_lnl], t[nmmax + 2];
float x, y;
register int i, j;
int r;
if (!fgets (buf, inp_lnl, inp))
return 0; /* done */
rms (buf);
lcnt++; /* count lines */
j = sscanf (buf, "%s %s %f %f %d", new_cp.name, t, &x, &y, &r);
if (j != 5 && j != 2) { /*** argument check ***/
printf ("Line %d error: invalid argument count\n", lcnt);
return -1;
}
for (i = 0; i < V.nty; i++) /*** get type ***/
if (!strncmp (t, TY[i].name, nmmax))
break;
if (i >= V.nty) {
printf ("Line %d error: undefined Type '%s'\n", lcnt, t);
return -1;
}
new_cp.ty = &TY[i];
new_cp.unplaced = 1; /* not yet placed */
if (5 == j) { /* explicily placed component */
if ((r < 0) || (r > 3)) {
printf ("Line %d error: invalid rotation - line ignored\n",lcnt);
return -1;
}
new_cp.x = rsun * x * scalef + 0.5;
new_cp.y = rsun * y * scalef + 0.5;
new_cp.r = r;
new_cp.unplaced = 0; /* a wild assumption ... */
}
return 1;
}
add_CP ()
/**********************************************************************\
* *
* Try to add a new component *
* The only error condition is lack of table space. If the componnet *
* does not fit, it will handled as unplaced. *
* *
\**********************************************************************/
{
register int i;
if (V.ncp >= cpmax)
err ("Component table too small: increase 'cpmax'", cpmax, 0, 0, 0);
if (V.nch + new_cp.ty -> np > chmax)
err ("Component hole table too small: increase 'chmax'", chmax,0,0,0);
for (i = new_cp.ty -> np; i;) { /* allocate holes */
CH[V.nch].x = 0;
CH[V.nch].y = 0;
CH[V.nch].pn = --i;
CH[V.nch].cpi = V.ncp;
CH[V.nch++].n = nil;
}
CP[V.ncp++] = new_cp; /* insert component */
if (!new_cp.unplaced) { /* try to make it happen */
CP[V.ncp - 1].unplaced = 1;
i = new_cp.r;
if (!C_place (&CP[V.ncp - 1], new_cp.x, new_cp.y, i))
printf ("Line %d: cannot place '%s' - kept as unplaced\n",
lcnt, new_cp.name);
}
CH_update ();
}
neq_CP (old)
struct comp *old;
/************************************************************************\
* *
* .NE. new component *
* a '1' is returned if the new componet "new_cp" differs from <old>. *
* The first difference is printed. *
* *
\************************************************************************/
{
if (new_cp.ty != old -> ty) {
printf ("Component '%s' - type difference: old='%s' new='%s'\n",
new_cp.name, old -> ty -> name, new_cp.ty -> name);
return 1;
}
if (!new_cp.unplaced && old -> unplaced) {
printf ("Component '%s' - status difference: old is unplaced\n",
new_cp.name);
return 1;
}
if (!new_cp.unplaced && (
new_cp.x != old -> x ||
new_cp.y != old -> y ||
new_cp.r != old -> r )) {
printf ("Component '%s' - different position\n", new_cp.name);
return 1;
}
return 0; /* they match */
}
replace_CP (old)
struct comp *old;
/**************************************************************************\
* *
* Try to replace a component *
* If the componnet has connections to any net, the replace attempt will *
* have no effect and a '0' is returned. A '1' indicates a successfull *
* replacement, but the new component may be 'unplaced' *
* *
\**************************************************************************/
{
register int i, j, own, cc;
register struct hole *hp, *hp1;
struct nlhd *net;
own = ((int) old - (int) CP) / sizeof (struct comp); /* get own index */
for (i = V.nch, hp = CH; i; i--, hp++) /* 'use' check */
if (hp -> n && hp -> cpi == own) {
if (brutal) {
net = hp -> n -> nlp;
printf ("Deleting net '%s'\n", net -> name);
del_NH (net);}
else
return 0; /* component is referenced */
}
/***** ready to replace it *****/
if (!(old -> unplaced)) { /* un-place component first */
if (!C_unplace (old))
err ("replace_CP: unplace failed with no nets", own, 0, 0, 0);
}
cc = V.nch + new_cp.ty -> np - old -> ty -> np;
/* expected new hole count */
if (cc > chmax)
err ("Hole table too small: increase 'chmax'", chmax, 0, 0, cc);
for (i = new_cp.ty -> np, j = V.nch, hp = CH; i && j; j--, hp++)
if (hp -> cpi == own) { /* found a pin */
hp -> x = 0;
hp -> y = 0;
hp -> pn = --i;
hp -> n = nil; /* x, y and n should not change here */
}
if (i) { /* need to allocate more pins */
while (i) {
CH[V.nch].x = 0;
CH[V.nch].y = 0;
CH[V.nch].pn = --i;
CH[V.nch].cpi = own;
CH[V.nch++].n = nil;
}}
else if (j) { /* there may be dangling pins */
for (hp1 = hp; j; j--, hp++) {
if (hp -> cpi != own)
*(hp1++) = *hp;
else
V.nch--;
}
}
if (cc != V.nch) /* something went wrong */
err ("remove_CP: inconsistent hole count", cc, V.nch, own, 0);
*old = new_cp; /* insert new component */
if (!new_cp.unplaced) { /* try to make it happen */
old -> unplaced = 1;
i = new_cp.r;
if (!C_place (old, new_cp.x, new_cp.y, i))
printf ("Line %d: cannot place '%s' - kept as unplaced\n",
lcnt, new_cp.name);
}
CH_update ();
return 1; /* success ! */
}
del_CP (old)
struct comp *old;
/*******************************************************************\
* *
* Delete component: *
* The holes for the componen <old> are removed and the CP entry *
* is marked as deleted iff <old> is not in use. '1' indicates *
* sucessfull deletion and '0' signals that no delete took place. *
* The as in 'del_TY' the space is not freed (so far). *
* *
\*******************************************************************/
{
register int i, j, own, cc;
register struct hole *hp, *hp1;
struct nlhd *net;
own = ((int) old - (int) CP) / sizeof (struct comp); /* get own index */
for (i = V.nch, hp = CH; i; i--, hp++) /* 'use' check */
if (hp -> n && hp -> cpi == own) {
if (brutal) {
net = hp -> n -> nlp;
printf ("Deleting net '%s'\n", net -> name);
del_NH (net);}
else
return 0; /* component is referenced */
}
/***** ready to delete it *****/
if (!(old -> unplaced)) { /* un-place component first */
if (!C_unplace (old))
err ("del_CP: unplace failed with no nets", own, 0, 0, 0);
}
cc = V.nch - old -> ty -> np; /* expected new hole count */
for (j = V.nch, hp1 = hp = CH; j; j--, hp++) {
if (hp -> cpi != own)
*(hp1++) = *hp;
else
V.nch--;
}
if (cc != V.nch) /* something went wrong */
err ("del_CP: inconsistent hole count", cc, V.nch, own, 0);
strcpy (old -> name, DELETED); /* make it inaccessable */
old -> ty = 0; /* free types */
old -> unplaced = 0; /* do not fool place functions */
CH_update ();
return 1; /* all set */
}
static int mode; /* =0: Multiwire =1: DP netlist */
static struct nlhd new_nh; /* temprary net list head */
static struct hole **new_ht = 0;/* temporary hole table */
static int ht_max = 100; /* max size of new_ht */
static int ht_cnt; /* allocation counter */
static struct nlhd *power_n; /* != 0 : power net processing */
static int net_cnt; /* net counter (MW format) */
NL_update () /* update netlist */
{
char buf[80];
float getfloat ();
register int i, err = 0;
register struct nlst *p, *q;
inp = fwantread (".", "test.nl", buf, "Netlist file:");
if (!inp) {
err_msg ("Open failed");
return;
}
mode = 0; /* assume 'Multiwire' mode */
fgets (buf, inp_lnl, inp);
if (strncmp (buf, "Cnetlist:", 9) &&
(mode = 1, strncmp (buf, "DPnetlist:", 10))) {
err_msg ("Format error");
printf ("Component-def file doesn't start with '*components:'\n");
beep ();
fclose (inp);
return;
}
for (i = 0; i < V.nnh; NH[i++].ref = 0); /* clear ref-flags */
for (p = V.GND.lp; p; p = p -> n) /* clear GND net */
p -> mk = 0;
for (p = V.VCC.lp; p; p = p -> n) /* clear VCC net */
p -> mk = 0;
for (p = V.VEE.lp; p; p = p -> n) /* clear VEE net */
p -> mk = 0;
for (p = V.VTT.lp; p; p = p -> n) /* clear VTT net */
p -> mk = 0;
new_nh.x1 = xmax; /* initialize prototype */
new_nh.y1 = ymax;
new_nh.x2 = 0;
new_nh.y2 = 0;
new_nh.f = 0;
new_nh.l = 0;
new_nh.lp = 0;
new_nh.ref = 1;
net_cnt = 0; /* reset MW net counter */
lcnt = 1; /* reset line counter */
Ferr_msg ("Busy: updating Netlist");
while (i = get_NH ()) {
if (i < 0) {
printf ("Invalid net: skipped\n");
err = 1; /* prevent delete phase */
continue;
}
i = ident_NH (); /* identify net */
if (i < 0) { /* add new net */
printf ("Adding net '%s'\n", new_nh.name);
add_NH ();}
else {
if (ref_chk ()) {
printf ("Line %d: '%s' shorted to other net\n",
lcnt, new_nh.name);
continue;
}
if (neq_NH (&NH[i]))
replace_NH ();
}
}
if (err)
printf ("Not deleting old net because of earlier errors\n");
else {
for (i = 0; i <V.nch; i++)
if (!NH[i].ref && NH[i].l) {
printf ("Net '%s' deleted\n", NH[i].name);
del_NH (&NH[i]);
}
for (q = 0, p = V.GND.lp; p;) {
if (!(p -> mk)) { /* remove node */
printf ("Removing GND connection '%s-%d'\n",
CP[p -> c -> cpi].name, p -> c -> pn + 1);
if (q)
q -> n = p -> n; /* unlink it */
else
V.GND.lp = p -> n;
p -> n = V.enll;
V.enll = p;
p -> c -> n = 0;
V.GND.l--;
p = (q) ? q : V.GND.lp;}
else {
q = p;
p = p -> n;
}
}
for (q = 0, p = V.VCC.lp; p;) {
if (!(p -> mk)) { /* remove node */
printf ("Removing VCC connection '%s-%d'\n",
CP[p -> c -> cpi].name, p -> c -> pn + 1);
if (q)
q -> n = p -> n; /* unlink it */
else
V.VCC.lp = p -> n;
p -> n = V.enll;
V.enll = p;
p -> c -> n = 0;
V.VCC.l--;
p = (q) ? q : V.VCC.lp;}
else {
q = p;
p = p -> n;
}
}
for (q = 0, p = V.VEE.lp; p;) {
if (!(p -> mk)) { /* remove node */
printf ("Removing VEE connection '%s-%d'\n",
CP[p -> c -> cpi].name, p -> c -> pn + 1);
if (q)
q -> n = p -> n; /* unlink it */
else
V.VEE.lp = p -> n;
p -> n = V.enll;
V.enll = p;
p -> c -> n = 0;
V.VEE.l--;
p = (q) ? q : V.VEE.lp;}
else {
q = p;
p = p -> n;
}
}
for (q = 0, p = V.VTT.lp; p;) {
if (!(p -> mk)) { /* remove node */
printf ("Removing VTT connection '%s-%d'\n",
CP[p -> c -> cpi].name, p -> c -> pn + 1);
if (q)
q -> n = p -> n; /* unlink it */
else
V.VTT.lp = p -> n;
p -> n = V.enll;
V.enll = p;
p -> c -> n = 0;
V.VTT.l--;
p = (q) ? q : V.VTT.lp;}
else {
q = p;
p = p -> n;
}
}
}
flush_stat ();
placed = 0; /* reevaluate net loactions */
for (i = 0, nettgo = 0; i < V.nnh; i++)
nettgo += !NH[i].f && NH[i].l; /* count unfinished nets */
nets_msg (nettgo);
fclose (inp);
err_msg ("Done");
beep ();
}
get_NH ()
/*************************************************************\
* *
* Get a net: *
* returns: 1: a correct net was read into "new_NH/new_NL" *
* 0: EOF was encountered *
* -1: the net description was in error *
* *
\*************************************************************/
{
char buf[inp_lnl];
register int i, j, ntc = 0;
int k;
static int preload = 0;
ht_cnt = 0; /* reset node count */
do {
if (!preload) {
if (!fgets (buf, inp_lnl, inp))
return mode ? 0 : ntc; /* end of file */
rms (buf);
lcnt++;
}
preload = 0; /* hack for Multiwre cont. records */
if (mode) {
/*******************************************************************\
* *
* DP netlist reader *
* *
* Warning: I am too tired to completly rewrite the reader now, so *
* there is the limitation that a net has to fit into the *
* line buffer (buf). *
* *
\*******************************************************************/
for (j = 0; buf[j] && buf[j] != '\\'; j++);
if (j && !buf[j]) {
printf ("Line %d error: DP-name without '\\'\n", lcnt);
return -1;
}
if (!j)
continue; /* skip empty lines */
if (buf[0] == '!') {/* power net (gnd, vcc, vee, vtt) */
if (!strncmp ("GND", &buf[1], 3))
power_n = &V.GND;
else if (!strncmp ("VCC", &buf[1], 3))
power_n = &V.VCC;
else if (!strncmp ("VTT", &buf[1], 3))
power_n = &V.VTT;
else if (!strncmp ("VEE", &buf[1], 3))
power_n = &V.VEE;
else {
printf ("Line %d error: unknown power net\n", lcnt);
return -1;
}
strcpy (new_nh.name, power_n -> name); /* for err-msg only */
} else { /* normal net */
power_n = nil;
buf[j] = 0;
strncpy (new_nh.name, buf, nmmax);
}
for (j++; (j < inp_lnl) && (buf[j] != '\0'); ++j)
if (buf[j] == ' ') {
if (add_NL (&buf[j + 1]))
return -1; /* some error in net */
}
if (!power_n)
return 1; /* net completed */
continue; /* hide power-nets */
}
if (buf[0] == 'C') { /* Multiwire net list processing */
j = 3;
if (!strncmp ("GND", &buf[1], 3))
power_n = &V.GND;
else if (!strncmp ("VCC", &buf[1], 3))
power_n = &V.VCC;
else if (!strncmp ("VTT", &buf[1], 3))
power_n = &V.VTT;
else if (!strncmp ("VEE", &buf[1], 3))
power_n = &V.VEE;
else
continue; /* normal comment */
strcpy (new_nh.name, power_n -> name);
} else {
power_n = nil;
if (!sscanf (buf, "%d", &k)) {
printf ("Line %d error: invalid net number\n", lcnt);
return - 1;}
else if (k == -1) /* Multiwire end ? */
return 0;
else if ((k < net_cnt) || (k <= 0)) {
printf ("Line %d error: net number %d out of sequence\n",
lcnt, k);
return -1;}
else {
if (k > net_cnt + 1)
printf("Line %d warning: net %d missing, next is %d\n",
lcnt, net_cnt + 1, k);
if (k > net_cnt) { /* start a new net */
if (ntc) {
preload = 1;
return 1; /* got a net */
}
ntc = 1;
sprintf (new_nh.name, "#%d", net_cnt = k);
}
}
j = 0;
}
for (j++; (j < inp_lnl) && (buf[j] != '\0'); ++j)
if (buf[j] == ' ') {
if (add_NL (&buf[j + 1]))
return -1; /* some error in net */
}
} while (1);
return -1; /* keep lint happy */
}
add_NL (s) /* add a node to a net list */
char *s;
{
register int i, j, l, x, y, r;
int k, x1, y1;
struct hole *hp, *fndh ();
struct nlst *p, *deq_NL ();
struct nlhd *net;
for (i = 0; s[i] != '-'; ++i) /* isolate component name */
if ((s[i] == '\0') || (i > nmmax)) {
printf ("Line %d error: missing pin number\n", lcnt);
return 1;
}
s[i] = '\0'; /* terminate string temporarily */
for (j = 0; j < V.ncp; j++) /* find componet definition */
if (!strncmp (s, CP[j].name, nmmax))
break;
if (j >= V.ncp) {
printf ("Line %d error: reference to undefined component\n", lcnt);
return 1;
}
if ((!sscanf (&s[i + 1], "%d", &k)) || (k <= 0) || (k > CP[j].ty -> np)) {
printf("Line %d error: '%s-%d': pin-number out of range\n", lcnt,s,k);
return 1;
} /* check pin number */
--k; /* pin number must start at 0 */
if ((CP[j].ty -> p + k) -> p)
printf ("Line %d warning: '%s-%d' is a power/gnd pin\n", lcnt, s,k+1);
s[i] = '*'; /* this is a hack (as usual) */
if (CP[j].unplaced) { /* need direct search */
hp = nil;
for (l = 0; l < V.nch; l++)
if (CH[j].cpi == j && CH[j].pn == k) {
hp = &CH[l];
break;
}
} else {
x = (CP[j].ty -> p + k) -> x; /* locate hole entry in CH */
y = (CP[j].ty -> p + k) -> y;
r = CP[j].r;
x1 = CP[j].x + rot_m[r][0] * x + rot_m[r][1] * y;
y1 = CP[j].y + rot_m[r][2] * x + rot_m[r][3] * y;
hp = fndh (x1, y1);
}
if (hp == nil)
err ("add_NL: failed to find hole", x1, y1, x, y);
if (power_n) {
/************************************************************************\
* *
* New power net handler: *
* *
* case a: touching the old & correct powernet -> mark node *
* case b: touching an old & !correct powernet -> move node, mark it *
* case c: touching an old net (!power) -> delete old net, add a power *
* node, mark it *
* case d: touching an new net (!power) -> serious error *
* case e: pin is in no net -> add a power node, mark it *
* *
\************************************************************************/
if (hp -> n) { /* case a-d */
net = hp -> n -> nlp;
if (net == power_n) { /*** CASE A ***/
if (hp -> n -> mk)
printf ("Line %d: multiple '%s' connection\n",
lcnt, power_n -> name); /* no need to abort */
hp -> n -> mk = 1;
return 0;
}
if (net < &NH[0] || net > &NH[V.nnh - 1]) { /*** CASE B ***/
if (pcb[y1][x1] & vec)
err ("add_NL: power net with trace", x1, y1, lcnt, 0);
if (hp -> n -> mk) {
printf ("Line %d: '%s' to '%s' short\n", lcnt,
hp -> n -> nlp -> name, power_n -> name);
return 1;
}
if (net -> lp == hp -> n) /* first in old list */
net -> lp = hp -> n -> n;
else {
for (p = net -> lp; p; p = p -> n)
if (p -> n == hp -> n) { /* found predecessor */
p -> n = hp -> n -> n;
break;
}
if (p)
err ("add_NL: unlink failed - ptr error",
x1, y1, lcnt, 0);
}
hp -> n -> n = power_n -> lp;
power_n -> lp = hp -> n; /* linked in new net */
hp -> n -> nlp = power_n;
hp -> n -> mk = 1;
power_n -> l++; /* update net length */
net -> l--;
return 0;
}
if (hp -> n -> nlp -> ref) { /*** CASE D ***/
printf ("Line %d: Error - net '%s' shorted to '%d'\n",
lcnt, hp -> n -> nlp -> name, power_n -> name);
return 1;
}
del_NH (hp -> n -> nlp); /*** CASE C ***/
}
/*** CASE E + (C cont) ***/
p = deq_NL (); /* get an NL - node */
p -> c = hp; /* add node to power net */
p -> n = power_n -> lp;
p -> nlp = power_n;
power_n -> lp = p;
p -> mk = 1;
hp -> n = p;
power_n -> l++; /* update net length */
p -> mk = 1; /* mark it */
return 0;
}
if (!new_ht) /* need to allocate space */
new_ht = (struct hole **) malloc (sizeof (struct hole *) * ht_max);
else if (ht_max <= ht_cnt) {
ht_max += 50;
new_ht = (struct hole **) realloc (new_ht,
sizeof (struct hole *) * ht_max);
}
for (i = 0; i < ht_cnt; i++)
if (new_ht[i] == hp) {
printf ("Line %d: multiple node in net\n", lcnt);
return 1;
}
new_ht[ht_cnt++] = hp; /* remember hole */
return 0;
}
ident_NH ()
/*********************************************************\
* *
* Identify the new net: *
* the first match is reported. '-1' indicates no match *
* *
\*********************************************************/
{
register int i;
for (i = 0; i < ht_cnt; i++)
if (new_ht[i] -> n)
return ((int) (new_ht[i] -> n -> nlp) - (int) NH) /
sizeof (struct nlhd);
return -1;
}
ref_chk ()
/************************************************************************\
* *
* reference check: *
* a '1' is return if the new net has a node in common with a net that *
* is already referenced. '0' is returned otherwise. *
* *
\************************************************************************/
{
register int i;
for (i = 0; i < ht_cnt; i++)
if (new_ht[i] -> n && new_ht[i] -> n -> nlp -> ref)
return 1;
return 0;
}
neq_NH (net)
struct nlhd *net;
/*************************************************************\
* *
* .NE. old net: *
* A '1' is return if the new net differs from the old one. *
* *
\*************************************************************/
{
register int i;
register struct nlst *p;
if (net -> l != ht_cnt)
return 1; /* different length */
for (p = net -> lp; p; p = p -> n)
p -> mk = 0; /* clear marks of old net */
for (i = 0; i < ht_cnt; i++) {
if (!(new_ht[i] -> n) || new_ht[i] -> n -> nlp != net)
return 1; /* referes to different net */
new_ht[i] -> n -> mk = 1;
}
for (p = net -> lp; p; p = p -> n)
if (!(p -> mk))
err ("new_NH: ptr screw up in internal structure",
((int) net - (int) NH) / sizeof (struct nlhd), lcnt, 0, 0);
net -> ref = 1; /* sucessfully referenced */
return 0; /* nets match */
}
replace_NH ()
/*******************************************\
* *
* Replace the old net(s) with the new one *
* *
\*******************************************/
{
register int i;
printf ("The new net '%s' replaces", new_nh.name);
for (i = 0; i < ht_cnt; i++)
if (new_ht[i] -> n) { /* delete the old nets */
printf (" '%s'", new_ht[i] -> n -> nlp -> name);
del_NH (new_ht[i] -> n -> nlp);
}
printf ("\n");
add_NH ();
}
add_NH () /* add new net */
{
register int i, j;
register struct nlst *p;
for (i = 0; i < V.nnh; i++) /* look for a old header */
if (!NH[i].l)
break;
if (i >= V.nnh) { /* not found: add new entry */
if (V.nnh >= nhmax)
err ("Net table too small: increase 'nhmax'", nhmax, 0,0,0);
i = V.nnh++;
}
NH[i] = new_nh; /* copy prototype */
NH[i].l = ht_cnt;
for (j = 0; j < ht_cnt; j++) { /* add nodes */
p = deq_NL ();
p -> n = NH[i].lp;
NH[i].lp = p;
p -> c = new_ht[j];
p -> nlp = &NH[i];
p -> mk = 0;
new_ht[j] -> n = p;
}
}
del_NH (net) /* delete net */
struct nlhd *net;
{
register int x, y;
register struct nlst *p, *q;
int delh (), delv ();
if (!(net -> l))
err ("del_NH: deleting deleted net ???",
((int) net - (int) NH) / sizeof (struct nlhd), lcnt, 0, 0);
wthf = delh; /* renmove old geometry */
wtvf = delv;
for (p = net -> lp; p; p = p -> n) {
q = p;
x = p -> c -> x;
y = p -> c -> y;
wtrace (x, y, vec);
ckgp (x, y, s1b);
ckgp (x, y, s2b);
p -> c -> n = 0; /* free holes */
}
q -> n = V.enll; /* enter nodes to free list */
V.enll = net -> lp;
net -> lp = 0;
net -> ref = 0;
net -> l = 0; /* net gone !! */
}
!E!O!F!
#
# type sh /usru0/agn/pcb/distr/../usenet/part9 to unpack this archive.
#
echo extracting patr.c...
cat >patr.c <<'!E!O!F!'
/***************************************************************\
* *
* PCB program *
* *
* Auto router section *
* *
* (c) 1985 A. Nowatzyk *
* *
\***************************************************************/
#include "pparm.h"
#include "pcdst.h"
#include "pleer.h"
#include <stdio.h>
#define netmax 50 /* max. net length */
#define ratio 3 /* ratio for filter */
#define pxsb s1b /* prefere x side bit */
#define pysb s2b /* prefere y side bit */
#define lmax 96 /* max length for filter */
#define bbox 16 /* bounding box for local route */
#define maxtry1 0 /* limit for N_route (see def) */
#define maxtry2 1 /* limit for N_route (see def) */
#define maxtry3 3 /* limit for N_route (see def) */
#define new_p1 0 /* use sorted segments in pass2 */
struct sntl { /* sorted net list */
struct nlhd *p; /* pointer to net */
int c; /* cost for this net */
};
static struct ssegl { /* sorted segment list */
struct nlhd *p; /* pointer to net */
int c; /* cost for this net */
int xs, ys; /* start coordinates */
int xe, ye; /* end coordinates */
} *SSEGL;
static int sseglc; /* count of nets */
autor()
/*****************************************************************\
* *
* Auto Router *
* *
* The Auto router uses several phases: *
* 1) use 'filter' no via-holes, 2 direction changes only *
* 2) use full router on level 0 *
* 3) use full router on level 1 *
* 4) use full router on level 2 *
* 5) use full router on level 3 *
* *
* *
\*****************************************************************/
{
register struct sntl *snl, *s;
register int i, j, k;
int netc_key (), seg_key (), segc, netc, max_nl;
Ferr_msg ("Preparing autoroute");
snl = (struct sntl *) malloc (V.nnh * sizeof (*snl));
segc = 0; /* count segments and nets */
netc = 0;
max_nl = 0;
for ((s = snl, j = i = 0); i < V.nnh; i++)/* evaluate nets */
if (NH[i].l > 1 && !(NH[i].f)) {
netc++;
k = NH[i].l;
if (k > max_nl)
max_nl = k;
segc += k - 1;
s -> p = &NH[i];
s -> c = net_cst (&NH[i]);
j++;
s++;
}
qsort (snl, j, sizeof (*snl), netc_key);/* sort nets */
SSEGL = (struct ssegl *) malloc (sizeof (struct ssegl) * segc);
printf ("%4d nets with %5d segments needs to be routed\n", netc, segc);
Ferr_msg ("Autoroute: pass 1");
netc = segc = 0;
for ((s = snl, i = 0); i < j; (s++, i++)){/* try routing */
segc += P_route (s -> p);
netc += s -> p -> f;
}
qsort (SSEGL, sseglc, sizeof (struct ssegl), seg_key);
printf ("\tPass1: %4d nets, %5d segments routed\n", netc, segc);
Ferr_msg ("Autoroute: pass 2");
netc = segc = 0;
set_rtps (0);
#ifdef new_p2
for (i = 0; i < sseglc; i++) /* try routing segments */
if (!(SSEGL[i].p -> f)) {
if (V.cnet != SSEGL[i].p) {
if (V.cnet)
deseln (V.cnet); /* deselect current net */
selnet (SSEGL[i].p); /* select net */
}
segc += s_route (SSEGL[i].xs, SSEGL[i].ys,
SSEGL[i].xe, SSEGL[i].ye);
netc += SSEGL[i].p -> f = cchk (SSEGL[i].p);
}
if (V.cnet)
deseln (V.cnet);
#else
for ((s = snl, i = 0); i < j; (s++, i++))/* try routing */
if (!(s -> p -> f)) {
segc += N_route (s -> p, 0, 0, 0, V.BSX, V.BSY);
netc += s -> p -> f;
}
#endif
free (SSEGL);
printf ("\tPass2: %4d nets, %5d segments routed\n", netc, segc);
Ferr_msg ("Autoroute: pass 3");
netc = segc = 0;
set_rtps (1);
for ((s = snl, i = 0); i < j; (s++, i++))/* try routing */
if (!(s -> p -> f)) {
segc += N_route (s -> p, maxtry1, 0, 0, V.BSX, V.BSY);
netc += s -> p -> f;
}
printf ("\tPass3: %4d nets, %5d segments routed\n", netc, segc);
Ferr_msg ("Autoroute: pass 4");
netc = segc = 0;
set_rtps (2);
for ((s = snl, i = 0); i < j; (s++, i++))/* try routing */
if (!(s -> p -> f)) {
segc += N_route (s -> p, maxtry2, 0, 0, V.BSX, V.BSY);
netc += s -> p -> f;
}
printf ("\tPass4: %4d nets, %5d segments routed\n", netc, segc);
Ferr_msg ("Autoroute: pass 5");
netc = segc = 0;
set_rtps (3);
for ((s = snl, i = 0); i < j; (s++, i++))/* try routing */
if (!(s -> p -> f)) {
segc += N_route (s -> p, maxtry3, 0, 0, V.BSX, V.BSY);
netc += s -> p -> f;
}
printf ("\tPass5: %4d nets, %5d segments routed\n", netc, segc);
free (snl); /* free memory */
Ferr_msg ("Saving result");
save (0);
Ferr_msg ("Done");
}
netc_key (a, b) /* sort key for nets */
struct sntl *a, *b;
{
return ((a -> c > b -> c) - (a -> c < b -> c));
}
seg_key (a, b) /* sort key for segments */
struct ssegl *a, *b;
{
return ((a -> c > b -> c) - (a -> c < b -> c));
}
net_cst (net) /* net cost function */
struct nlhd *net;
/**************************************************************\
* *
* This function determins the order of rout - attempts. Nets *
* with a low cost are routed first. *
* *
\**************************************************************/
{
int c, dx, dy;
dx = abs (net -> x1 - net -> x2);
dy = abs (net -> y1 - net -> y2);
c = 500 * abs (dx - dy);
c /= (dx + dy); /* prefere square nets */
c += net -> l * 100; /* large nets later */
c += (dx + dy) * 2; /* long nets later (significat) */
return (c);
}
filter (x1, y1, x2, y2) /* look for promissing candiates */
int x1, y1, x2, y2;
/****************************************************************\
* *
* This code is obsolete, but it is kept because it runs faster *
* for simple cases than the full router in pleer.c *
* *
\****************************************************************/
{
int i, j;
i = abs (x1 - x2);
j = abs (y1 - y2);
if ((i + j) > lmax)
return (0); /* invalid length */
if (i > ratio * j) {
if (x1 < x2)
return (tryx (x1, y1, x2 - x1, y2 - y1, pxsb));
else
return (tryx (x2, y2, x1 - x2, y1 - y2, pxsb));
}
if (i * ratio < j) {
if (y1 < y2)
return (tryy (x1, y1, y2 - y1, x2 - x1, pysb));
else
return (tryy (x2, y2, y1 - y2, x1 - x2, pysb));
}
return (0); /* invalid ratio */
}
tryx (x, y, l, o, b) /* try to route a wire (X) */
int x, y, l, o, b;
{
int i, l1, l2, c1, c2, c3, t;
char *p, *p1, *p2, *p3;
t = ahb | b | fb | selb; /* test bits */
if (o >= 0) {
p2 = p1 = &pcb[y - 1][x + 2];
l1 = l - 2;
c2 = c3 = 0;
for (i = (-1); i < o + bbox; i++) {
c1 = 1; /* assume space for wire */
p = p1;
for (l2 = (abs(o-i) > 2) ? l1 - abs(o-i) : l1 - 2; l2 >= 0; l2--)
/* check space */
if (*(p++) & t) {
c1 = 0;
break;
}
if (c1 & c2 & c3) { /* looks good so far */
if (cmplx(x, y, --i, l, o, b))
return (1);
break;
}
c3 = c2;
c2 = c1;
p3 = p2;
p2 = p1;
p1 += xmax;
if (i > 1) {
if ((*p3 & t) || (*(++p3) & t) || (*p1 & t) || (*(p1-1) & t))
break;
p1++;
l1--;
}
}
p1 = &pcb[y][x + 2]; /* ok, try other side next */
l1 = l - 2;
c2 = c3 = 0;
for (i = 0; i > -bbox; i--) {
c1 = 1; /* assume space for wire */
p = p1;
for (l2 = ((o-i) > 2) ? l1 - (o-i) : l1 - 2; l2 >= 0; l2--)
/* check space */
if (*(p++) & t) {
c1 = 0;
break;
}
if (c1 & c2 & c3) { /* looks good so far */
if (cmplx(x, y, ++i, l, o, b))
return (1);
break;
}
c3 = c2;
c2 = c1;
p3 = p2;
p2 = p1;
p1 -= xmax;
if (i < -1) {
if ((*p3 & t) || (*(++p3) & t) || (*p1 & t) || (*(p1-1) & t))
break;
p1++;
l1--;
}
}}
else { /* same thing, but reversed order */
p1 = &pcb[y + 1][x + 2];
l1 = l - 2;
c2 = c3 = 0;
for (i = 1; i > o - bbox; i--) {
c1 = 1; /* assume space for wire */
p = p1;
for (l2 = (abs(o-i) > 2) ? l1 - abs(o-i) : l1 - 2; l2 >= 0; l2--)
/* check space */
if (*(p++) & t) {
c1 = 0;
break;
}
if (c1 & c2 & c3) { /* looks good so far */
if (cmplx(x, y, ++i, l, o, b))
return (1);
break;
}
c3 = c2;
c2 = c1;
p3 = p2;
p2 = p1;
p1 -= xmax;
if (i < -1) {
if ((*p3 & t) || (*(++p3) & t) || (*p1 & t) || (*(p1-1) & t))
break;
p1++;
l1--;
}
}
p1 = &pcb[y][x + 2]; /* ok, try other side */
l1 = l - 2;
c2 = c3 = 0;
for (i = 0; i < bbox; i++) {
c1 = 1; /* assume space for wire */
p = p1;
for (l2 = ((i-o) > 2) ? l1 - (i-o) : l1 - 2; l2 >= 0; l2--)
/* check space */
if (*(p++) & t) {
c1 = 0;
break;
}
if (c1 & c2 & c3) { /* looks good so far */
if (cmplx(x, y, --i, l, o, b))
return (1);
break;
}
c3 = c2;
c2 = c1;
p3 = p2;
p2 = p1;
p1 += xmax;
if (i > 1) {
if ((*p3 & t) || (*(++p3) & t) || (*p1 & t) || (*(p1-1) & t))
break;
p1++;
l1--;
}
}
}
return (0); /* no success */
}
cmplx (x, y, po, l, o, b) /* complete try (x) */
int x, y, po, l, o, b;
{
int i, d, t;
char *p;
t = ahb | b | fb | selb;
d = o - po; /* get displacement */
if (d) { /* check last segment */
if (d > 0) { /* down segment */
if (d > 1) { /* deserves attention */
d--;
p = &pcb[y + o - 3][x + l - 1];
for (i = d; i > 0; (p -= xmax, i--))
if ((*p & t) || (*(--p) & t) ||
(*(p + 2 * xmax) & t) || (*(p + 3 * xmax) & t))
return (0); /* fail */
color (b | selb, b | selb);
plt (x + l, y + o, x + l - d, y + o - d);
l -= d + 1; }
else {
color (b | selb, b | selb);
pxl (x + l, y + o);
l--; /* just cheat on length */
} }
else { /* up segment */
d = (-d);
if (d > 1) { /* need attention */
d--;
p = &pcb[y + o + 3][x + l - 1];
for (i = d; i > 0; (p += xmax, i--))
if ((*p & t) || (*(--p) & t) ||
(*(p - 2 * xmax) & t) || (*(p - 3 * xmax) & t))
return (0);/* fail */
color (b | selb, b | selb);
plt (x + l, y + o, x + l - d, y + o + d);
l -= d + 1; }
else {
color (b | selb, b | selb);
pxl (x + l, y + o);
l--; /* cheat on length */
}
} }
else
color (b | selb, b | selb);
if (abs (po) > 1) {
plt (x, y, x + abs (po), y + po);
plt (x + abs (po) + 1, y + po, x + l, y + po); }
else {
if (po)
pxl (x, y);
plt (x + abs (po), y + po, x + l, y + po);
}
return (1); /* success */
}
tryy (x, y, l, o, b) /* try to route a wire (Y) */
int x, y, l, o, b;
{
int i, l1, l2, c1, c2, c3, t;
char *p, *p1, *p2, *p3;
t = ahb | b | fb | selb; /* test bits */
if (o >= 0) {
p2 = p1 = &pcb[y + 2][x - 1];
l1 = l - 2;
c2 = c3 = 0;
for (i = (-1); i < o + bbox; i++) {
c1 = 1; /* assume space for wire */
p = p1;
for (l2 = (abs(o-i) > 2) ? l1 - abs(o-i) : l1 - 2; l2 >= 0; l2--){
/* check space */
if (*p & t) {
c1 = 0;
break;
}
p += xmax;
}
if (c1 & c2 & c3) { /* looks good so far */
if (cmply(x, y, --i, l, o, b))
return (1);
break;
}
c3 = c2;
c2 = c1;
p3 = p2;
p2 = p1;
++p1;
if (i > 1) {
if ((*p3 & t) || (*(p3 + xmax) & t) ||
(*p1 & t) || (*(p1 - xmax) & t))
break;
p1 += xmax;
l1--;
}
}
p1 = &pcb[y + 2][x]; /* ok, try other side next */
l1 = l - 2;
c2 = c3 = 0;
for (i = 0; i > -bbox; i--) {
c1 = 1; /* assume space for wire */
p = p1;
for (l2 = ((o-i) > 2) ? l1 - (o-i) : l1 - 2; l2 >= 0; l2--) {
/* check space */
if (*p & t) {
c1 = 0;
break;
}
p += xmax;
}
if (c1 & c2 & c3) { /* looks good so far */
if (cmply(x, y, ++i, l, o, b))
return (1);
break;
}
c3 = c2;
c2 = c1;
p3 = p2;
p2 = p1;
--p1;
if (i < -1) {
if ((*p3 & t) || (*(p3 + xmax) & t) ||
(*p1 & t) || (*(p1 - xmax) & t))
break;
p1 += xmax;
l1--;
}
}}
else { /* same thing, but reversed order */
p1 = &pcb[y + 2][x + 1];
l1 = l - 2;
c2 = c3 = 0;
for (i = 1; i > o - bbox; i--) {
c1 = 1; /* assume space for wire */
p = p1;
for (l2 = (abs(o-i) > 2) ? l1 - abs(o-i) : l1 - 2; l2 >= 0; l2--){
/* check space */
if (*p & t) {
c1 = 0;
break;
}
p += xmax;
}
if (c1 & c2 & c3) { /* looks good so far */
if (cmply(x, y, ++i, l, o, b))
return (1);
break;
}
c3 = c2;
c2 = c1;
p3 = p2;
p2 = p1;
--p1;
if (i < -1) {
if ((*p3 & t) || (*(p3 + xmax) & t) ||
(*p1 & t) || (*(p1 - xmax) & t))
break;
p1 += xmax;
l1--;
}
}
p1 = &pcb[y + 2][x]; /* ok, try other side */
l1 = l - 2;
c2 = c3 = 0;
for (i = 0; i < bbox; i++) {
c1 = 1; /* assume space for wire */
p = p1;
for (l2 = ((i-o) > 2) ? l1 - (i-o) : l1 - 2; l2 >= 0; l2--) {
/* check space */
if (*p & t) {
c1 = 0;
break;
}
p += xmax;
}
if (c1 & c2 & c3) { /* looks good so far */
if (cmply(x, y, --i, l, o, b))
return (1);
break;
}
c3 = c2;
c2 = c1;
p3 = p2;
p2 = p1;
++p1;
if (i > 1) {
if ((*p3 & t) || (*(p3 + xmax) & t) ||
(*p1 & t) || (*(p1 - xmax) & t))
break;
p1 += xmax;
l1--;
}
}
}
return (0); /* no success */
}
cmply (x, y, po, l, o, b) /* complete try (x) */
int x, y, po, l, o, b;
{
int i, d, t;
char *p;
t = ahb | b | fb | selb;
d = o - po; /* get displacement */
if (d) { /* check last segment */
if (d > 0) { /* down segment */
if (d > 1) { /* deserves attention */
d--;
p = &pcb[y + l - 1][x + o - 3];
for (i = d; i > 0; (p--, i--))
if ((*p & t) || (*(p -= xmax) & t) ||
(*(p + 2) & t) || (*(p + 3) & t))
return (0);/* fail */
color (b | selb, b | selb);
plt (x + o, y + l, x + o - d, y + l - d);
l -= d + 1; }
else {
color (b | selb, b | selb);
pxl (x + o, y + l);
l--; /* just cheat on length */
} }
else { /* up segment */
d = (-d);
if (d > 1) { /* need attention */
d--;
p = &pcb[y + l - 1][x + o + 3];
for (i = d; i > 0; (p++, i--))
if ((*p & t) || (*(p -= xmax) & t) ||
(*(p - 2) & t) || (*(p - 3) & t))
return (0);/* fail */
color (b | selb, b | selb);
plt (x + o, y + l, x + o + d, y + l - d);
l -= d + 1; }
else {
color (b | selb, b | selb);
pxl (x + o, y + l);
l--; /* cheat on length */
}
} }
else
color (b | selb, b | selb);
if (abs (po) > 1) {
plt (x, y, x + po, y + abs (po));
plt (x + po, y + abs (po) + 1, x + po, y + l); }
else {
if (po)
pxl (x, y);
plt (x + po, y + abs (po), x + po, y + l);
}
return (1); /* success */
}
/***************************************\
* *
* Local stuff for N_route and P_route *
* *
\***************************************/
struct htab { /* hole table */
int x, y; /* coordinate */
int snn; /* subnet number */
};
struct clst { /* connection list */
struct htab *s, *d; /* pointer to holes */
int c; /* cost (= length) or 0 */
};
ct_key (a, b)
struct clst *a, *b;
{
return ((a -> c > b -> c) - (a -> c < b -> c));
}
static int s1, s2, nh; /* current subnet (for Nr_cup) */
static struct htab *htp; /* hole table pointer */
Nr_cup (x, y) /* dumb update function */
int x, y;
{
int i;
struct htab *h;
if (pcb[y][x] & ishb)
return (0); /* don't care */
for ((h = htp, i = 0); i < nh; (h++, i++))
if (h -> x == x && h -> y == y)
h -> snn = s1;
return (0);
}
N_route (net, max, xl, yl, xh, yh)
struct nlhd *net;
int max;
int xl, yl, xh, yh;
/*******************************************************************\
* *
* Net-route: This routine tries to route an entire net. A minimal *
* spanning tree - approach is used, but if this does not succeed, *
* all possible routes are tried. This may take some time for long *
* nets. <max> is a limit on the number of attempts to connect 2 *
* subnets. *
* N_route updates the connectivity flag in the net-list header. *
* The number of successfully routed segments is returned. *
* *
* <x/y-h/l> defines a subarea for net parts. *
* *
\*******************************************************************/
{
int i, j, k, l, ct_key (), Nr_cup (), no_seg;
struct htab *h1, *h2;
struct clst *c0, *c1, *c2, *clp;
struct nlst *p;
if (V.cnet)
deseln (V.cnet); /* deselect current net */
if (net -> l < 2)
return (0); /* trivial nets always succeed */
if (selnet (net)) { /* select net */
deseln (net);
return (0); /* net is already done */
}
no_seg = 0;
#ifdef debug
if(net == testbp) {
Ferr_msg ("Break");
i = 0; /* set breakpoint here */
}
#endif
nh = net -> l; /* (max) number of holes in net */
htp = (struct htab *) malloc (nh * sizeof (*htp));
clp = (struct clst *) malloc (nh * (nh - 1) * sizeof (*clp) / 2);
nh = 0; /* count hole in area of interest */
for (h1 = htp, p = net -> lp; p; p = p -> n) {
/* scan holes of net */
h1 -> x = p -> c -> x;
h1 -> y = p -> c -> y;
if (h1 -> x >= xl && h1 -> x <= xh &&
h1 -> y >= yl && h1 -> y <= yh ) {
h1 -> snn = p -> mk;
h1++;
nh++;
}
}
if (nh < 2) { /* nothing to do */
free (htp);
free (clp);
deseln (net);
return 0;
}
k = 0; /* number of possible connections*/
c0 = clp;
for ((i = 1, h1 = htp); i < nh; (i++, h1++))
for ((j = i + 1, h2 = htp + i); j <= nh; (j++, h2++))
if (h1 -> snn != h2 -> snn) {
/* pre-select segment orientation */
if (abs (h1 -> x - h2 -> x) > abs (h1 -> y - h2 -> y)) {
if (h1 -> x > h2 -> x) {
c0 -> d = h1;
c0 -> s = h2;}
else {
c0 -> s = h1;
c0 -> d = h2;
}}
else {
if (h1 -> y > h2 -> y) {
c0 -> d = h1;
c0 -> s = h2;}
else {
c0 -> s = h1;
c0 -> d = h2;
}
}
c0 -> c = abs (h1 -> x - h2 -> x) + abs (h1 -> y - h2 -> y);
c0++;
k++;
}
qsort (clp, k, sizeof (*clp), ct_key);
#ifdef debug
if (ttt) {
c0 = clp;
for (i = 0; i < k; (c0++, i++))
printf ("%2d: s=%3d,%3d (%3d) d=%3d,%3d (%3d) c=%d\n", i,
c0 -> s -> x, c0 -> s -> y, c0 -> s -> snn,
c0 -> d -> x, c0 -> d -> y, c0 -> d -> snn, c0 -> c);
}
#endif
for ((i = 0, c0 = clp); i < k; i++)
(c0++) -> c = 0; /* re-use cost as retry count */
for ((i = 0, c0 = clp); i < k; (c0++, i++)) {
/* try to connect the subnets */
if (c0 -> c > max) /* max. try count exceeded ? */
continue;
s1 = c0 -> s -> snn;
s2 = c0 -> d -> snn;
if ((s1 != s2) && /* try to join */
s_route (c0 -> s -> x, c0 -> s -> y, c0 -> d -> x, c0 -> d -> y)){
#ifdef debug
if (ttt) printf("connected subnet %d to %d\n", s1, s2);
#endif
no_seg++;
wtvf = nil; /* update conectivity information*/
wthf = Nr_cup;
wtrace (c0 -> s -> x, c0 -> s -> y, vec);
c1 = c2 = c0 + 1;
l = k;
for (j = i + 1; j < k; (c1++, j++)) {
if (s1 != c1 -> s -> snn || s1 != c1 -> d -> snn) {
/* viable connection */
c2 -> s = c1 -> s;
c2 -> d = c1 -> d;
c2 -> c = c1 -> c;
c2++;}
else
l--;
}
k = l;}
else {
#ifdef debug
if (ttt)
printf ("failed to connect %d to %d\n", s1, s2);
#endif
c1 = c0 + 1;
for (j = i + 1; j < k; (c1++, j++))
if ((s1 == c1 -> s -> snn && s2 == c1 -> d -> snn) ||
(s2 == c1 -> s -> snn && s1 == c1 -> d -> snn))
(c1 -> c)++;
}
#ifdef debug
if (ttt) {
c1 = c0 +1;
Ferr_msg ("test");
for(l = i + 1; l < k; (c1++, l++))
printf ("%2d: s=%3d,%3d (%3d) d=%3d,%3d (%3d) c=%d\n", l,
c1 -> s -> x, c1 -> s -> y, c1 -> s -> snn,
c1 -> d -> x, c1 -> d -> y, c1 -> d -> snn, c1 -> c);
}
#endif
}
j = htp -> snn;
h1 = htp + 1;
for (i = 1; i < nh;(h1++, i++))/* more than one subnet left? */
if (h1 -> snn != j)
break;
/* net done ? */
net -> f = (i >= nh && nh == net -> l) || cchk (net);
deseln (net);
free (clp); /* free memory */
free (htp);
return (no_seg);
}
P_route (net)
struct nlhd *net;
/*********************************************************************\
* *
* Primitive-route: This routine tries to route the *trivial* parts *
* of a net. A minimal spanning tree approch is used. This code *
* should run on empty nets only. It is intended to be used in *
* a pre-routing phase of the auto-router. Multiple connections *
* may result on a partially completed net. This routine is *
* faster than N_route. *
* *
* The parts of the MST that are not routed are saved to the tot_mst *
* structure. You understand that this side-effect is used *
* by 'autor', so do not call P_route elsewhere. *
* *
\*********************************************************************/
{
int i, j, k, l, ct_key (), no_seg;
struct htab *h1, *h2;
struct clst *c0, *c1, *c2, *clp;
struct nlst *p;
int dx, dy;
int ttc = 0; /* test count (check MST) */
if (V.cnet)
deseln (V.cnet); /* deselect current net */
if (net -> l < 2)
return (0); /* trivial nets always succeed */
no_seg = 0;
if (selnet (net)) { /* select net */
deseln (net);
return (0); /* net is already done */
}
nh = net -> l; /* number of holes in net */
htp = (struct htab *) malloc (nh * sizeof (*htp));
clp = (struct clst *) malloc (nh * (nh - 1) * sizeof (*clp) / 2);
i = 0; /* count subnets */
for ((h1 = htp, p = net -> lp); p; (h1++, p = p -> n)) {
/* scan holes of net */
h1 -> x = p -> c -> x;
h1 -> y = p -> c -> y;
h1 -> snn = p -> mk;
}
k = 0; /* number of possible connections*/
c0 = clp;
for ((i = 1, h1 = htp); i < nh; (i++, h1++))
for ((j = i + 1, h2 = htp + i); j <= nh; (j++, h2++)) {
/* pre-select segment orientation */
if (abs (h1 -> x - h2 -> x) > abs (h1 -> y - h2 -> y)) {
if (h1 -> x > h2 -> x) {
c0 -> d = h1;
c0 -> s = h2;}
else {
c0 -> s = h1;
c0 -> d = h2;
}}
else {
if (h1 -> y > h2 -> y) {
c0 -> d = h1;
c0 -> s = h2;}
else {
c0 -> s = h1;
c0 -> d = h2;
}
}
/* get cost (length) of this segment */
c0 -> c = abs (h1 -> x - h2 -> x) + abs (h1 -> y - h2 -> y);
c0++;
k++;
}
qsort (clp, k, sizeof (*clp), ct_key);
for ((i = 0, c0 = clp); i < k; (c0++, i++)) {
/* try to connect the subnets */
s1 = c0 -> s -> snn;
s2 = c0 -> d -> snn;
if (s1 != s2) { /* try connection */
ttc++; /* count MST edges */
if (filter (c0 -> s -> x, c0 -> s -> y,
c0 -> d -> x, c0 -> d -> y ))
no_seg++;
else { /* add segments to SSEGL */
SSEGL[sseglc].p = net;
/************************************************\
* *
* Segment list cost function: small cost first *
* *
\************************************************/
dx = abs (c0 -> s -> x - c0 -> d -> x);
dy = abs (c0 -> s -> y - c0 -> d -> y);
SSEGL[sseglc].c = c0 -> c * 2 + /* long segments later */
(100 * abs (dx - dy)) / abs (dx + dy); /* square bonus */
SSEGL[sseglc].xs = c0 -> s -> x;
SSEGL[sseglc].ys = c0 -> s -> y;
SSEGL[sseglc].xe = c0 -> d -> x;
SSEGL[sseglc].ye = c0 -> d -> y;
sseglc++;
}
for ((j = 0, h1 = htp); j < nh; (j++, h1++))
if (h1 -> snn == s2)
h1 -> snn = s1; /* subnet s2 is gone */
c0 -> d -> snn = s1;
c1 = c2 = c0 + 1;
l = k;
for (j = i + 1; j < k; (c1++, j++)) {
if (s1 != c1 -> s -> snn || s1 != c1 -> d -> snn) {
/* viable connection */
c2 -> s = c1 -> s;
c2 -> d = c1 -> d;
c2++;}
else
l--;
}
k = l;
}
}
net -> f = cchk (net); /* net done ? */
if(ttc > (net->l -1))
err("P_route: not MST", ttc, net -> l,
(int) (net - NH) / sizeof(NH[0]), 0);
free (clp); /* free memory */
free (htp);
deseln (net);
return (no_seg);
}
!E!O!F!
More information about the Comp.sources.unix
mailing list