home *** CD-ROM | disk | FTP | other *** search
- /* par.c - the actual placement and routine routines
- *
- * 12.Aug.87 jimmc Initial definition - placement routines
- * 14.Aug.87 jimmc More placement, routing routines
- * 3.Nov.87 jimmc Add rowdir
- * 6.Nov.87 jimmc Use XCALLOC macro
- * 18.Jan.88 jimmc lint cleanup
- * 27.Jan.88 jimmc Add feedthrough stuff
- * 29.Feb.88 jimmc Improve robustness when doing partial place/routes
- */
-
- #include <ctype.h>
- #include "network.h"
- #include "xalloc.h"
-
- #define SPLITCHAR '#'
-
- extern Nnet *NFindNet(), *NCreateNet();
- extern Nbox *NFindBox(), *NCreateBox();
- extern Nconn *NCreateConn();
- extern NIFreeConn();
- extern NClearNetConns(), NClearBoxConns();
- extern NLinkConnNet();
-
- extern char *index();
- extern char *strsav();
-
- extern Nbase *NCurBase;
- extern char Tflag[];
-
- #define HROW (NCurBase->rowdir=='H')
- #define vX cc[HROW?0:1]
- #define vY cc[HROW?1:0]
- /* if rows are horizontal, vX is X and vY is Y */
- #define NorE (HROW?N:E)
- #define SorW (HROW?S:W)
- #define NorEstr (HROW?"N":"E")
- #define SorWstr (HROW?"S":"W")
-
- extern int NPosConn();
- extern Nbox *NFindBox();
-
- static
- RUnmarkBox(box)
- Nbox *box;
- {
- box->parflags = 0;
- }
-
- int
- RIsFeedBox(box)
- Nbox *box;
- {
- if (index(box->name,SPLITCHAR)) return 1;
- return 0;
- }
-
- static
- RUnSplitBox(box)
- Nbox *box;
- {
- extern int NUnLinkConnNet();
-
- if (!index(box->name,SPLITCHAR)) return;
- NDoGroup(&(box->connlist),NUnLinkConnNet);
- NFreeGroup(&(box->connlist),NIFreeConn);
- }
-
- static
- RFreeSplitBox(box)
- Nbox *box;
- {
- if (!index(box->name,SPLITCHAR)) return;
- NIFreeBox(box);
- }
-
- static
- RSelBox(box,rownum)
- Nbox *box;
- {
- int i;
-
- if (box->parflags & ROWSET) return;
- box->rownum = rownum;
- box->parflags |= ROWSET;
- for (i=0; i<box->connlist.count; i++) {
- RSelBConn(box->connlist.d.conn[i],rownum);
- }
- }
-
- static
- RSelectBox(box) /* set the row number in a box */
- Nbox *box;
- {
- RSelBox(box,0); /* place this box in row 0 */
- }
-
- static
- RUnsetrowBox(box)
- Nbox *box;
- {
- box->row = 0;
- }
-
- static
- RSetrowBox(box) /* set a box into a row */
- Nbox *box;
- {
- Nrow *row, *RFindRow();
-
- if (box->row) return; /* nop if already set */
- row = RFindRow(NCurBase,box->rownum);
- if (!row) {
- printf("Can't find row %d for box %s\n",
- box->rownum, box->name);
- return;
- }
- box->row = row;
- insertp(&(row->boxlist),(char *)box);
- }
-
- static
- RSetrposBox(box)
- Nbox *box;
- {
- if (!box->row) return;
- box->origin.vY = box->row->pos;
- }
-
- static
- RClearOrderBox(box)
- Nbox *box;
- {
- box->parflags &= ~ORDERSET;
- }
-
- static
- ROrderCBox(box,side,negdir)
- Nbox *box;
- int side;
- int negdir;
- {
- Ngroup clist;
- int i,j;
- Nnet *net;
- Nconn *cp;
- int RCmpConn();
-
- NClearGroup(&clist);
- for (i=0; i<box->connlist.count; i++) {
- /* collect all conns on the side of interest */
- cp = box->connlist.d.conn[i];
- if (cp->side==side && cp->net && cp->net->connlist.count>1) {
- insertp(&clist,(char *)cp);
- }
- }
- if (clist.count==0) return;
- qsort((char *)clist.d.conn,clist.count,
- sizeof(clist.d.conn[0]),RCmpConn);
- for (i=0; i<clist.count; i++) { /* see if any nets set yet */
- net = clist.d.conn[i]->net;
- if (net->parflags & ORDERSET) break;
- }
- if (i>=clist.count) { /* no nets set yet */
- if (negdir) i=clist.count;
- else i=0;
- }
- for (j=i; j<clist.count; j++) { /* count up from i */
- ROrderNet(clist.d.conn[j]->net,0);
- }
- for (j=i-1; j>=0; j--) { /* count down from i */
- ROrderNet(clist.d.conn[j]->net,1);
- }
- if (clist.d.x) tfree((char *)clist.d.x);
- }
-
- static
- ROrderBox(box,negdir) /* sets orders in neighboring boxes */
- Nbox *box;
- int negdir; /* if set, expand in negative direction */
- {
- if (box->parflags & ORDERSET) return;
- box->parflags |= ORDERSET;
- if (negdir)
- box->rowpos = --(box->row->rowposmin);
- else
- box->rowpos = (box->row->rowposmax)++;
- ROrderCBox(box,NorE,negdir); /* order the north or east boxes */
- ROrderCBox(box,SorW,negdir); /* order the south or west boxes */
- }
-
- static int
- RCmpBox(b1,b2)
- Nbox **b1, **b2;
- {
- return (*b1)->rowpos - (*b2)->rowpos;
- }
-
- static
- RNetForceBox(box,side,pnforce,pncount)
- Nbox *box;
- int side; /* use only connectors on this side */
- int *pnforce; /* return value - total net force */
- int *pncount; /* return value - count of nets */
- {
- Ngroup clist;
- int i;
- int nforce, ncount;
- int sumnforce, sumncount;
- Nconn *cp, *conn;
- Nnet *net;
-
- NClearGroup(&clist);
- for (i=0; i<box->connlist.count; i++) {
- /* collect all conns on the side of interest */
- cp = box->connlist.d.conn[i];
- if (cp->side==side && cp->net && cp->net->connlist.count>1) {
- insertp(&clist,(char *)cp);
- }
- }
- sumnforce = 0;
- sumncount = 0;
- for (i=0; i<clist.count; i++) {
- conn = clist.d.conn[i];
- net = conn->net;
- RNetForceNet(net,conn,&nforce,&ncount);
- sumnforce += nforce;
- sumncount += ncount;
- }
- if (clist.d.x) tfree((char *)clist.d.x);
- *pnforce = sumnforce;
- *pncount = sumncount;
- }
-
- static
- RUnmarkNet(net)
- Nnet *net;
- {
- net->parflags = 0; /* clear flag bits */
- }
-
- static
- RSelNet(net,rownum)
- Nnet *net;
- int rownum;
- {
- int i;
-
- if (net->parflags & ROWSET) return;
- net->rownum = rownum;
- net->parflags |= ROWSET;
- for (i=0; i<net->connlist.count; i++) {
- RSelNConn(net->connlist.d.conn[i],rownum);
- }
- }
-
- static
- RUnsetrowNet(net)
- Nnet *net;
- {
- net->row = 0;
- }
-
- static
- RSetrowNet(net) /* set a net into a row */
- Nnet *net;
- {
- Nrow *row, *RFindRow();
-
- if (net->row) return; /* nop if already set */
- row = RFindRow(NCurBase,net->rownum);
- if (!row) {
- printf("Can't find row %d for net %s\n",
- net->rownum, net->name);
- return;
- }
- net->row = row;
- insertp(&(row->netlist),(char *)net);
- }
-
- static
- RUnSplitNet(net)
- Nnet *net;
- {
- char *splitp;
- extern int RUnSplitConn();
-
- splitp = index(net->name,SPLITCHAR);
- if (!splitp) return; /* not a split net */
- /* OK, it's one of ours, undo it */
- NDoGroup(&(net->connlist),RUnSplitConn);
- if (net->connlist.count!=0)
- fatalerr("net count!=0 for net %s", net->name);
- }
-
- static
- RFreeSplitNet(net)
- Nnet *net;
- {
- if (!index(net->name,SPLITCHAR)) return;
- NIFreeNet(net);
- }
-
- static
- RSplitNet(net)
- Nnet *net;
- {
- Nconn *conn;
- int cboxrow;
- int connside, connrow;
- int i;
- int minrow,maxrow;
- char namebuf[516];
- char *namebufcpy;
- Nnet *newnet;
- char *thisname, *lastname;
- Nbox *newbox;
- Nconn *newconn;
-
- minrow=maxrow=0;
- for (i=0; i<net->connlist.count; i++) {
- conn = net->connlist.d.conn[i];
- connside = conn->side; /* NSEW */
- cboxrow = conn->box->rownum;
- connrow = cboxrow+((connside==N||connside==E)?1:-1);
- if (i==0 || connrow<minrow) minrow=connrow;
- if (i==0 || connrow>maxrow) maxrow=connrow;
- }
- if (minrow==maxrow) return; /* all in one channel */
- lastname = "";
- for (i=minrow; i<=maxrow; i+=2) {
- namebufcpy = 0;
- sprintf(namebuf,"%s%c%s%d",net->name,SPLITCHAR,
- ((i<0)?"m":""),((i<0)?-i:i));
- newnet = NFindNet(NCurBase,namebuf);
- if (!newnet) {
- newnet = NCreateNet(strsav(namebuf),i);
- }
- thisname = newnet->name;
- if (i>minrow) {
- newbox = NFindBox(NCurBase,thisname);
- if (newbox) {
- newbox->rownum = i-1;
- } else {
- newbox = NCreateBox(strsav(namebuf),0,0,0,0,
- "",0,0,"",i-1,0);
- }
- newbox->parflags |= ROWSET;
- NFreeGroup(&(newbox->connlist),NIFreeConn);
- newconn = NCreateConn(strsav(newbox->name),
- strsav(thisname),
- 0,0,strsav(NorEstr),strsav(thisname));
- NLinkConnBox(newconn);
- newconn = NCreateConn(strsav(newbox->name),
- strsav(lastname),
- 0,0,strsav(SorWstr),strsav(lastname));
- NLinkConnBox(newconn);
- }
- lastname = thisname;
- }
- for (i=0; i<net->connlist.count; i++) {
- conn = net->connlist.d.conn[i];
- connside = conn->side; /* NSEW */
- cboxrow = conn->box->rownum;
- connrow = cboxrow+((connside==N||connside==E)?1:-1);
- sprintf(namebuf,"%s%c%s%d",conn->netname,SPLITCHAR,
- ((connrow<0)?"m":""),((connrow<0)?-connrow:connrow));
- namebufcpy = XALLOC(char,strlen(namebuf)+1);
- strcpy(namebufcpy,namebuf);
- tfree(conn->netname);
- conn->netname = namebufcpy;
- }
- }
-
- static
- RClearOrderNet(net)
- Nnet *net;
- {
- net->parflags &= ~ORDERSET;
- }
-
- static
- ROrderCNet(net,side,negdir)
- Nnet *net;
- int side;
- int negdir;
- {
- Ngroup clist;
- int i,j;
- Nbox *box;
- Nconn *cp;
-
- NClearGroup(&clist);
- for (i=0; i<net->connlist.count; i++) {
- /* collect all conns on the side of interest */
- cp = net->connlist.d.conn[i];
- if (cp->side==side && cp->box) {
- insertp(&clist,(char *)cp);
- }
- }
- if (clist.count==0) return;
- qsort((char *)clist.d.conn,clist.count,
- sizeof(clist.d.conn[0]),RCmpConn);
- for (i=0; i<clist.count; i++) { /* see if any boxes set yet */
- box = clist.d.conn[i]->box;
- if (box->parflags & ORDERSET) break;
- }
- if (i>=clist.count) { /* no boxes set yet */
- if (negdir) i=clist.count;
- else i=0;
- }
- for (j=i; j<clist.count; j++) { /* count up from i */
- ROrderBox(clist.d.conn[j]->box,0);
- }
- for (j=i-1; j>=0; j--) { /* count down from i */
- ROrderBox(clist.d.conn[j]->box,1);
- }
- if (clist.d.x) tfree((char *)clist.d.x);
- }
-
- static
- ROrderNet(net,negdir) /* sets orders in neighboring boxes */
- Nnet *net;
- int negdir; /* if set, expand in negative direction */
- {
- if (net->parflags & ORDERSET) return;
- net->parflags |= ORDERSET;
- if (negdir)
- net->rowpos = --(net->row->rowposmin);
- else
- net->rowpos = (net->row->rowposmax)++;
- ROrderCNet(net,SorW,negdir); /* order the boxes to our south or west */
- ROrderCNet(net,NorE,negdir); /* order the boxes to our north or east */
- }
-
- static
- RSpanNet(net) /* calculate the span for a net */
- Nnet *net;
- {
- int i;
- Nconn *conn;
- int max,min;
-
- max = min = 0;
- for (i=0; i<net->connlist.count; i++) {
- conn = net->connlist.d.conn[i];
- if (i==0 || conn->apos.vX > max) max=conn->apos.vX;
- if (i==0 || conn->apos.vX < min) min=conn->apos.vX;
- }
- net->maxpos = max;
- net->minpos = min;
- }
-
- static int
- RCmpNet(n1,n2)
- Nnet **n1, **n2;
- {
- return (*n1)->minpos - (*n2)->minpos;
- }
-
- static
- RNetForceNet(net,orgconn,pnforce,pncount)
- Nnet *net;
- Nconn *orgconn; /* the source connector to calculate the force from */
- int *pnforce; /* return value - total net force */
- int *pncount; /* return value - count of net runs */
- {
- int i;
- Nconn *conn;
- int orgx;
- int nforce;
- int ncount;
-
- orgx = orgconn->apos.vX;
- nforce = 0;
- ncount = 0;
- for (i=0; i<net->connlist.count; i++) {
- conn = net->connlist.d.conn[i];
- if (conn==orgconn) continue;
- nforce += conn->apos.vX - orgx;
- ncount++;
- }
- *pnforce = nforce;
- *pncount = ncount;
- }
-
- static
- RSetAngleNet(net)
- Nnet *net;
- {
- int i;
- Nconn *conn;
- int nconn, sconn, econn, wconn;
- int nsum, ssum, esum, wsum;
-
- if (net->connlist.count<=1) return;
- nconn = sconn = econn = wconn = 0;
- nsum = ssum = esum = wsum = 0;
- net->track = 0;
- for (i=0; i<net->connlist.count; i++) {
- conn = net->connlist.d.conn[i];
- switch (conn->side) {
- case N:
- nconn++;
- nsum += conn->apos.X;
- break;
- case S:
- sconn++;
- ssum += conn->apos.X;
- break;
- case E:
- econn++;
- esum += conn->apos.Y;
- break;
- case W:
- wconn++;
- wsum += conn->apos.Y;
- break;
- default: break;
- }
- }
- if (nconn>sconn) net->angle = 'S';
- else if (sconn>nconn) net->angle = 'N';
- else if (econn>wconn) net->angle = 'W';
- else if (wconn>econn) net->angle = 'E';
- else if (esum>wsum) net->angle = 'L'; /* leans to the left */
- else if (wsum>esum) net->angle = 'R';
- else if (nsum>ssum) net->angle = 'L';
- else if (ssum>nsum) net->angle = 'R';
- else net->angle = 0;
- }
-
- static
- RRouteNet(net)
- Nnet *net;
- {
- int i;
- Ntrack *track;
- Nconn *c1, *c2, *conn;
- int cpos;
- int NFreeGroupOnly();
-
- NFreeGroup(&(net->pathlist),NFreeGroupOnly);
- if (net->connlist.count<=1) return;
- track = net->track;
- NSetNet(net); /* so we can use NCeatePath below */
- cpos = track->pos;
- if (net->connlist.count==2) { /* common special case */
- c1 = net->connlist.d.conn[0];
- c2 = net->connlist.d.conn[1];
- if (net->minpos==net->maxpos) { /* no bends! */
- NCreatePath(c1->apos.X,c1->apos.Y);
- NCreatePath(c2->apos.X,c2->apos.Y);
- }
- else {
- NCreatePath(c1->apos.X,c1->apos.Y);
- if (HROW) {
- NCreatePath(c1->apos.X,cpos);
- NCreatePath(c2->apos.X,cpos);
- } else {
- NCreatePath(cpos,c1->apos.Y);
- NCreatePath(cpos,c2->apos.Y);
- }
- NCreatePath(c2->apos.X,c2->apos.Y);
- }
- }
- else { /* more than two points */
- if (HROW) {
- NCreate1Path(net->minpos,cpos,net->maxpos,cpos);
- for (i=0; i<net->connlist.count; i++) {
- conn = net->connlist.d.conn[i];
- NCreate1Path(conn->apos.X,conn->apos.Y,
- conn->apos.X,cpos);
- }
- } else {
- NCreate1Path(cpos,net->minpos,cpos,net->maxpos);
- for (i=0; i<net->connlist.count; i++) {
- conn = net->connlist.d.conn[i];
- NCreate1Path(conn->apos.X,conn->apos.Y,
- cpos,conn->apos.Y);
- }
- }
- }
- }
-
- static
- RUnSplitConn(conn)
- Nconn *conn;
- {
- char *nnend;
-
- if (!conn->box)
- NLinkConnBox(conn);
- nnend = index(conn->netname,SPLITCHAR);
- if (!nnend) return;
- if (conn->net)
- removep(&(conn->net->connlist),(char *)conn);
- /* remove from old (split) net */
- *nnend = 0; /* strip tail off name */
- if (!conn->box) return;
- if (!index(conn->box->name,SPLITCHAR)) {
- NLinkConnNet(conn); /* relink the net pointer */
- }
- }
-
- static
- RSelBConn(conn,rownum)
- Nconn *conn;
- int rownum;
- {
- if (!conn->net) return;
- switch (conn->side) {
- case E: case N:
- RSelNet(conn->net,rownum+1);
- break;
- case W: case S:
- RSelNet(conn->net,rownum-1);
- break;
- }
- }
-
- static
- RSelNConn(conn,rownum)
- Nconn *conn;
- int rownum;
- {
- if (!conn->box) return;
- switch (conn->side) {
- case E: case N:
- RSelBox(conn->box,rownum-1);
- break;
- case W: case S:
- RSelBox(conn->box,rownum+1);
- break;
- }
- }
-
- static int
- RCmpConn(c1,c2)
- Nconn **c1, **c2;
- {
- return (*c1)->pos.vX - (*c2)->pos.vX;
- }
-
- static
- Nrow *
- RFindRow(base,num)
- Nbase *base;
- int num;
- {
- int i;
-
- for (i=0; i<base->rowlist.count; i++) {
- if (base->rowlist.d.row[i]->rownum==num)
- return base->rowlist.d.row[i];
- }
- return 0;
- }
-
- static
- RSetflagRow(row)
- Nrow *row;
- {
- if (row->boxlist.count)
- row->parflags |= BOXROW;
- else
- row->parflags &= ~BOXROW;
- }
-
- static int
- RSizeRow(row)
- Nrow *row;
- {
- int i;
- int smax,s;
-
- if (!(row->parflags & BOXROW)) return 0; /* not a box row */
- smax=0;
- for (i=0; i<row->boxlist.count; i++) {
- s = row->boxlist.d.box[i]->size.vY;
- if (s>smax) smax=s;
- }
- row->size = smax;
- return smax;
- }
-
- static
- RClearOrderRow(row)
- Nrow *row;
- {
- row->rowposmin = row->rowposmax = 0;
- }
-
- static
- RSortRow(row) /* sorts the boxes in a row */
- Nrow *row;
- {
- if (!(row->parflags & BOXROW)) return;
- qsort((char *)row->boxlist.d.box,row->boxlist.count,
- sizeof(row->boxlist.d.box[0]),RCmpBox);
- /* sort according to rowpos */
- RNormalizeRow(row);
- }
-
- static
- RNormalizeRow(row)
- Nrow *row;
- {
- Nbox *box;
- int i,t;
-
- t = 0;
- for (i=0; i<row->boxlist.count; i++) {
- box = row->boxlist.d.box[i];
- box->origin.vX = t;
- t += NCurBase->rowposspace + box->size.vX;
- }
- row->length = t-NCurBase->rowposspace;
- }
-
- static
- RPositionRow(row,side)
- Nrow *row;
- int side; /* position based on connectors on this side */
- {
- if (!(row->parflags & BOXROW)) return;
- RBalanceRow(row,side);
- RSpreadRow(row,side);
- }
-
- static
- RBalanceRow(row,side) /* moves the row as a unit to a balanced position */
- Nrow *row;
- int side; /* position based on connectors on this side */
- {
- int i;
- Nbox *box;
- int nforce, ncount;
- int sumnforce, sumncount;
- int dist;
-
- sumnforce = 0;
- sumncount = 0;
- for (i=0; i<row->boxlist.count; i++) {
- box = row->boxlist.d.box[i];
- RNetForceBox(box,side,&nforce,&ncount);
- sumnforce += nforce;
- sumncount += ncount;
- }
- if (sumncount==0) return;
- dist = sumnforce/sumncount;
- if (dist<0) return;
- if (dist + row->length > NCurBase->maxrowlength)
- dist = NCurBase->maxrowlength - row->length;
- for (i=0; i<row->boxlist.count; i++) {
- box = row->boxlist.d.box[i];
- box->origin.vX += dist;
- NDoGroup(&(box->connlist),NPosConn);
- box->parflags &= ~POSITIONSET;
- }
- }
-
- static
- RSpreadRow(row,side)
- Nrow *row;
- int side; /* position based on connectors on this side */
- {
- int i;
- Nbox *box;
- int floor, ceil;
- int nforce, ncount;
- int dist;
- int j;
- Nbox *boxj;
- int tfloor;
-
- floor = 0;
- for (i=0; i<row->boxlist.count; i++) {
- box = row->boxlist.d.box[i];
- RNetForceBox(box,side,&nforce,&ncount);
- if (ncount==0) {
- floor += box->size.vX + NCurBase->rowposspace;
- /* raise floor, but place this box later */
- continue;
- }
- dist = nforce/ncount;
- if (dist>=0) break;
- if (box->origin.vX + dist < floor)
- box->origin.vX = floor;
- else
- box->origin.vX += dist;
- NDoGroup(&(box->connlist),NPosConn);
- floor = box->origin.vX + box->size.vX + NCurBase->rowposspace;
- box->parflags |= POSITIONSET;
- tfloor = box->origin.vX;
- for (j=i-1; j>=0; j--) {
- boxj = row->boxlist.d.box[j];
- if (boxj->parflags & POSITIONSET) break;
- tfloor -= boxj->size.vX + NCurBase->rowposspace;
- boxj->origin.vX = tfloor;
- boxj->parflags |= POSITIONSET;
- }
- }
- ceil = NCurBase->maxrowlength;
- for (i=row->boxlist.count-1; i>=0; i--) {
- box = row->boxlist.d.box[i];
- RNetForceBox(box,side,&nforce,&ncount);
- if (ncount==0) {
- ceil -= box->size.vX + NCurBase->rowposspace;
- continue;
- }
- dist = nforce/ncount;
- if (dist<=0) break;
- if (box->origin.vX + box->size.vX + dist > ceil)
- box->origin.vX = ceil - box->size.vX;
- else
- box->origin.vX += dist;
- NDoGroup(&(box->connlist),NPosConn);
- ceil = box->origin.vX - NCurBase->rowposspace;
- box->parflags |= POSITIONSET;
- tfloor = box->origin.vX + box->size.vX + NCurBase->rowposspace;
- for (j=i+1; j<row->boxlist.count; j++) {
- boxj = row->boxlist.d.box[j];
- if (boxj->parflags & POSITIONSET) break;
- boxj->origin.vX = tfloor;
- tfloor += boxj->size.vX + NCurBase->rowposspace;
- boxj->parflags |= POSITIONSET;
- }
- }
- }
-
- /* track routines */
-
- static Ntrack *
- RNewTrack(n)
- int n;
- {
- Ntrack *track;
-
- track = XCALLOC(Ntrack,1);
- track->n = n;
- track->netlist.count = track->netlist.alloc = 0;
- track->netlist.d.net = 0;
- return track;
- }
-
- static
- RUseTrack(track,net)
- Ntrack *track;
- Nnet *net;
- {
- track->parflags |= SPANSET;
- insertp(&(track->netlist),(char *)net);
- }
-
- static int /* returns angle of the net which is in the way, 0 if open */
- RUnAvailTrack(track,min,max)
- Ntrack *track;
- int min,max;
- {
- Nnet *net;
- int i;
-
- if (!(track->parflags & SPANSET)) return 0;
- for (i=0; i<track->netlist.count; i++) {
- net = track->netlist.d.net[i];
- if (min>=net->maxpos+NCurBase->trackspace) continue;
- if (max<=net->minpos-NCurBase->trackspace) continue;
- return net->angle; /* this net is in the way */
- }
- return 0;
- }
-
- static Ntrack *
- RFindTrack(row,min,max,netangle)
- Nrow *row;
- int min,max;
- int netangle;
- {
- int i;
- Ntrack *track, *lastavail;
- int trackangle;
-
- /* find the last row in which the route DOES NOT fit, then return the
- * next row after that! */
- lastavail = 0;
- for (i=row->tracklist.count-1; i>=0; i--) {
- track = row->tracklist.d.track[i];
- trackangle = RUnAvailTrack(track,min,max);
- if (!trackangle)
- lastavail = track;
- else
- if (trackangle==netangle) break;
- /* if angles are different, continue looking */
- }
- if (lastavail) return lastavail;
- return 0;
-
- #if 0 /* greedy algorithm - doesn't do quite what we want */
- for (i=0; i<row->tracklist.count; i++) {
- track = row->tracklist.d.track[i];
- if (!(RUnAvailTrack(track,min,max))) return track;
- }
- return 0;
- #endif
- }
-
- static
- RClearTrack(track)
- Ntrack *track;
- {
- NFreeGroupOnly(&(track->netlist));
- track->parflags = 0;
- }
-
- static
- RFreeTrack(track)
- Ntrack *track;
- {
- NFreeGroupOnly(&(track->netlist));
- tfree((char *)track);
- }
-
- static
- RChanSizeRow(row) /* calculate required number of tracks */
- Nrow *row;
- {
- int i;
- Nnet *net;
- Ntrack *track;
-
- if (row->parflags & BOXROW) return;
- NFreeGroup(&(row->tracklist),RFreeTrack);
- NDoGroup(&(row->netlist),RSpanNet); /* find span of each net */
- qsort((char *)row->netlist.d.net,row->netlist.count,
- sizeof(row->netlist.d.net[0]),RCmpNet);
- NDoGroup(&(row->netlist),RSetAngleNet);
- for (i=row->netlist.count-1; i>=0; i--) {
- net = row->netlist.d.net[i];
- if (net->connlist.count<=1) continue;
- switch (net->angle) {
- case 'W': case 'R': case 'S':
- break;
- default:
- continue;
- }
- track = RFindTrack(row,net->minpos,net->maxpos,net->angle);
- /* see where it can fit */
- if (!track) { /* have to make a new track */
- track = RNewTrack(row->tracklist.count);
- insertp(&(row->tracklist),(char *)track);
- }
- net->track = track;
- RUseTrack(track,net);
- }
- for (i=0; i<row->netlist.count; i++) {
- net = row->netlist.d.net[i];
- if (net->track || net->connlist.count<=1) continue;
- track = RFindTrack(row,net->minpos,net->maxpos,net->angle);
- /* see where it can fit */
- if (!track) { /* have to make a new track */
- track = RNewTrack(row->tracklist.count);
- insertp(&(row->tracklist),(char *)track);
- }
- net->track = track;
- RUseTrack(track,net);
- }
- row->size = NCurBase->trackspace * (row->tracklist.count+1);
- }
-
- static
- RRouteRow(row)
- Nrow *row;
- {
- int i;
- Ntrack *track;
-
- if (row->parflags & BOXROW) return;
- for (i=0; i<row->tracklist.count; i++) {
- track = row->tracklist.d.track[i];
- track->pos = row->pos + NCurBase->trackspace*(1+i);
- }
- NDoGroup(&(row->tracklist),RClearTrack); /* clear min/max */
- NDoGroup(&(row->netlist),RRouteNet); /* route all nets */
- }
-
- int
- RSelect(boxname) /* select rows for all boxes and nets */
- char *boxname;
- {
- Nbox *box;
-
- if (!NCurBase) {
- printf("no data to place\n");
- return 0;
- }
- NDoGroup(&(NCurBase->boxlist),RUnmarkBox);
- NDoGroup(&(NCurBase->netlist),RUnmarkNet);
-
- if (boxname) { /* see if preferred root for placement */
- box = NFindBox(NCurBase,boxname);
- if (box) RSelectBox(box);
- }
- NDoGroup(&(NCurBase->boxlist),RSelectBox); /* put in new row */
-
- return 1;
- }
-
- /* UnFeed removes any previously inserted feedthroughs */
- int
- RUnFeed()
- {
- if (!NCurBase) {
- printf("no data to place\n");
- return 0;
- }
- NDoGroup(&(NCurBase->boxlist),RUnSplitBox);
- NRDoGroup(&(NCurBase->boxlist),RFreeSplitBox);
- NDoGroup(&(NCurBase->netlist),RUnSplitNet);
- NRDoGroup(&(NCurBase->netlist),RFreeSplitNet);
- return 1;
- }
-
- int
- RFeed() /* make feedthroughs */
- {
-
- if (!NCurBase) {
- printf("no data to place\n");
- return 0;
- }
- NDoGroup(&(NCurBase->netlist),RSplitNet);
- /* divide nets up when spanning rows */
- NDoGroup(&(NCurBase->netlist),NClearNetConns);
- NDoGroup(&(NCurBase->connlist),NLinkConnNet);
- return 1;
- }
-
- int
- RReFeed() /* remove old feedthroughs and insert new */
- {
- if (!RUnFeed()) return 0;
- if (!RFeed()) return 0;
- return 1;
- }
-
- int
- RSpace() /* set the spacing for the rows, set one coord in boxes */
- {
- extern int NFreeRow();
- int rowmax=0;
- int rowmin=0;
- int r,rowcount;
- int i;
- int pos;
- Nrow *row;
-
- if (!NCurBase) {
- printf("no data to place\n");
- return 0;
- }
- NSetBase(NCurBase); /* so we can use NCreateRow */
- NFreeGroup(&(NCurBase->rowlist),NFreeRow); /* dump all old rows */
- NDoGroup(&(NCurBase->boxlist),RUnsetrowBox);
- NDoGroup(&(NCurBase->netlist),RUnsetrowNet);
- for (i=0; i<NCurBase->boxlist.count; i++) {
- r = NCurBase->boxlist.d.box[i]->rownum;
- if (i==0 || r>rowmax) rowmax=r;
- if (i==0 || r<rowmin) rowmin=r;
- }
- for (i=0; i<NCurBase->netlist.count; i++) {
- r = NCurBase->netlist.d.net[i]->rownum;
- if (r>rowmax) rowmax=r;
- if (r<rowmin) rowmin=r;
- }
- rowcount = rowmax-rowmin+1;
- for (i=0; i<rowcount; i++) {
- NCreateRow(i+rowmin,0,0); /* put in new rows */
- }
- NDoGroup(&(NCurBase->boxlist),RSetrowBox);
- NDoGroup(&(NCurBase->netlist),RSetrowNet);
- /* put all the boxes and nets into their rows */
- pos = 0;
- for (i=0; i<NCurBase->rowlist.count; i++) {
- row = NCurBase->rowlist.d.row[i];
- row->pos = pos;
- if (row->boxlist.count)
- row->parflags |= BOXROW;
- pos += NCurBase->interrowspace + RSizeRow(row);
- }
- NDoGroup(&(NCurBase->boxlist),RSetrposBox);
- NDoGroup(&(NCurBase->connlist),NPosConn);
- return 1;
- }
-
- static
- RSetPtrs() /* make sure pointers are set up (for incremental p/r) */
- {
- /* make sure box and net pointers to row are in */
- NDoGroup(&(NCurBase->boxlist),RSetrowBox);
- NDoGroup(&(NCurBase->netlist),RSetrowNet);
- NDoGroup(&(NCurBase->rowlist),RSetflagRow);
- }
-
- int
- ROrder(boxname) /* order the boxes in each row */
- char *boxname;
- {
- int i;
- Nbox *box;
-
- if (!NCurBase) {
- printf("no data to place\n");
- return 0;
- }
-
- RSetPtrs();
-
- /* now start the ordering within each row */
- NDoGroup(&(NCurBase->boxlist),RClearOrderBox);
- NDoGroup(&(NCurBase->netlist),RClearOrderNet);
- NDoGroup(&(NCurBase->rowlist),RClearOrderRow);
- /* clear out any previous ordering info */
-
- if (boxname) { /* see if preferred root for placement */
- box = NFindBox(NCurBase,boxname);
- if (box) ROrderBox(box,0);
- }
- for (i=0; i<NCurBase->boxlist.count; i++) {
- ROrderBox(NCurBase->boxlist.d.box[i],0);
- }
- NDoGroup(&(NCurBase->rowlist),RSortRow);
- NDoGroup(&(NCurBase->connlist),NPosConn);
- return 1;
- }
-
- int
- RPosition() /* position the boxes within each row */
- {
- int i;
- Nrow *row;
- int maxlength;
- int rowi;
-
- if (!NCurBase) {
- printf("no data to place\n");
- return 0;
- }
-
- RSetPtrs();
-
- NDoGroup(&(NCurBase->rowlist),RNormalizeRow);
- maxlength = -1;
- for (i=0; i<NCurBase->rowlist.count; i++) {
- row = NCurBase->rowlist.d.row[i];
- if (!(row->parflags & BOXROW)) continue;
- if (row->length > maxlength) {
- maxlength = row->length;
- rowi = i;
- }
- }
- NCurBase->maxrowlength = maxlength;
- for (i=rowi-1; i>=0; i--) {
- RPositionRow(NCurBase->rowlist.d.row[i],NorE);
- }
- for (i=rowi+1; i<NCurBase->rowlist.count; i++) {
- RPositionRow(NCurBase->rowlist.d.row[i],SorW);
- }
- return 1;
- }
-
- int
- RRoute() /* do the channel route */
- {
- int i;
- int t;
- Nrow *row;
-
- if (!NCurBase) {
- printf("no data to place\n");
- return 0;
- }
-
- RSetPtrs();
-
- NDoGroup(&(NCurBase->connlist),NPosConn);
- NDoGroup(&(NCurBase->rowlist),RChanSizeRow);
- /* calculate the channel size for each row */
- t = 0;
- for (i=0; i<NCurBase->rowlist.count; i++) {
- row = NCurBase->rowlist.d.row[i];
- row->pos = t;
- t += row->size;
- }
- NDoGroup(&(NCurBase->boxlist),RSetrposBox);
- NDoGroup(&(NCurBase->connlist),NPosConn);
- NDoGroup(&(NCurBase->rowlist),RRouteRow);
- /* do the actual channel routing */
- return 1;
- }
-
- RSpacepar(boxname) /* RSpace and the rest */
- char *boxname;
- {
- if (!RSpace()) return 0;
- if (!ROrder(boxname)) return 0;
- if (!RPosition()) return 0;
- if (!RRoute()) return 0;
- return 1;
- }
-
- RReFeedpar(boxname) /* RFeed and the rest */
- char *boxname;
- {
- if (!RReFeed()) return 0;
- if (!RSpacepar(boxname)) return 0;
- return 1;
- }
-
- Rpar(boxname) /* do it all */
- char *boxname;
- {
- if (!RSelect(boxname)) return 0;
- if (!RReFeedpar(boxname)) return 0;
- return 1;
- }
-
- /* end */
-