#include <stdio.h> #include <stdlib.h> #include "grid.h" int grid::makeGrid(vector<pin> &vp, int _width, int _height, int max_net) { int i,j; width=_width; height=_height; ge=(grid_element ***) malloc(sizeof(grid_element **)*4); if (!ge) return -1; gpv=(grid_prev_visited ***) malloc(sizeof(grid_element **)*4); if (!gpv) return -1; gc=(grid_cost ***) malloc(sizeof(grid_cost **)*4); if (!gc) return -1; for (i=0;i<4;i++) { ge[i]=(grid_element **) malloc(sizeof(grid_element*)*(height)); if (!ge[i]) return -1; gpv[i]=(grid_prev_visited **) malloc(sizeof(grid_element *)*height); if (!gpv[i]) return -1; gc[i]=(grid_cost **) malloc(sizeof(grid_cost *)*height); if (!gc[i]) return -1; for (j=0;j<height;j++) { ge[i][j]=(grid_element *) calloc(sizeof(grid_element)*(width),1); if (!ge[i][j]) return -1; gpv[i][j]=(grid_prev_visited *) calloc(sizeof(grid_prev_visited)*(width+1)/2,1); if (!gpv[i][j]) return -1; gc[i][j]=(grid_cost *) calloc(sizeof(grid_cost)*(width+1)/2,1); if (!gc[i][j]) return -1; } } cell c; for (i=0;i<vp.size();i++) { c.x=vp[i].x; c.y=vp[i].y-1; c.l=0; addCellToPath(c,-1); c.l=1; addCellToPath(c,-1); c.y++; addCellToPath(c,-1); c.l=0; addCellToPath(c,-1); c.y++; addCellToPath(c,-1); c.l=1; addCellToPath(c,-1); } net_costs.resize(max_net+1); for (i=0;i<=max_net;i++) net_costs[i]=0; return 0; } int grid::clearVisitedAndPrev() { unsigned int x,y,l; for (l=0;l<4;l++) { for (y=0;y<height;y++) { memset(gpv[l][y],0,sizeof(grid_prev_visited)*(width+1)/2); } } return 0; } /* void grid::setVisited(cell c) { if (c.x&0x01) { gpv[c.l][c.y][c.x/2].stuff|=0x08; } else { gpv[c.l][c.y][c.x/2].stuff|=0x80; } } */ int grid::cellCostAccurate(cell c) { routed_net *rn; int cost=0; for (rn=ge[c.l][c.y][c.x].rn;rn;rn=rn->next) { if (rn->net_id==-1) return 1<<30; cost+=net_costs[rn->net_id]; } return cost; } /* int grid::setPrev(cell c, cell nc, int dir) { if (c.x&0x01) { gpv[c.l][c.y][c.x/2].stuff&=0xF8; gpv[c.l][c.y][c.x/2].stuff|=dir; } else { gpv[c.l][c.y][c.x/2].stuff&=0x8F; gpv[c.l][c.y][c.x/2].stuff|=(dir<<4); } return 0; } */ cell grid::getPrev(cell c) { cell ret; int dir; if (c.x&0x01) { dir=gpv[c.l][c.y][c.x/2].stuff&0x07; } else { dir=(gpv[c.l][c.y][c.x/2].stuff&0x70)>>4; } if (dir==7) { ret.x=-1; ret.y=-1; ret.l=0; return ret; } // now we just need to work backwards from the direction switch (dir) { case 0: dir=2; break; case 1: dir=3; break; case 2: dir=0; break; case 3: dir=1; break; case 4: dir=5; break; case 5: dir=4; break; } if (!getNeighbor(c,dir,ret)) { fprintf(stderr,"getPrev failed bigtime!\n"); fprintf(stderr,"c=(%i,%i,%i) dir=%i\n", c.x,c.y,c.l,dir); exit(1); } return ret; } void grid::resetCost(cell c) { int t=cellCostAccurate(c); if (t<(1<<30)) { t=min((int)((float)t/cost_quantizer),14); } else t=15; if (c.x&0x01) { gc[c.l][c.y][c.x/2].cost&=0xF0; gc[c.l][c.y][c.x/2].cost|=t; } else { gc[c.l][c.y][c.x/2].cost&=0x0F; gc[c.l][c.y][c.x/2].cost|=(t<<4); } } void grid::addCellToPath(cell &c, int net) { routed_net *rn; // first check to see if this net is already here for (rn=ge[c.l][c.y][c.x].rn;rn && rn->net_id!=net;rn=rn->next); if (rn) return; // this net already exists rn=new routed_net; if (!rn) { fprintf(stderr,"addNetToPath: Out of Memory!\n"); exit(1); } rn->net_id=net; rn->next=ge[c.l][c.y][c.x].rn; ge[c.l][c.y][c.x].rn=rn; resetCost(c); } int grid::addNetToPath(list<cell> &lc, int net) { list<cell>::iterator lci; for (lci=lc.begin();lci!=lc.end();++lci) { addCellToPath(*lci,net); } return 0; } int grid::removeNetFromPath(list<cell> &lc, int net) { list<cell>::iterator lci; for (lci=lc.begin();lci!=lc.end();++lci) { routed_net *rn,**parent; parent=&ge[lci->l][lci->y][lci->x].rn; for (rn=*parent;rn && rn->net_id!=net;parent=&rn->next,rn=rn->next); if (!rn) { //fprintf(stderr,"removeNetFromPath: net %i not found" // "at cell (%i,%i,%i)\n", net,lci->x,lci->y,lci->l); } else { *parent=rn->next; delete rn; resetCost(*lci); } } return 0; } int grid::countNets(cell c) { int count=0; routed_net *rn; for (rn=ge[c.l][c.y][c.x].rn;rn;rn=rn->next,count++) if (rn->net_id==-1) count--; return count; } int grid::isPin(cell c) { routed_net *rn; for (rn=ge[c.l][c.y][c.x].rn;rn;rn=rn->next) if (rn->net_id==-1) return 1; return 0; } /* int grid::cellCost(cell c) { int l; if (c.x&0x1) { l=gc[c.l][c.y][c.x/2].cost&0x0f; } else { l=(gc[c.l][c.y][c.x/2].cost&0xf0)>>4; } return quantized_costs[l]; } */ // take the costs in the net_costs vector, and finds a good set of // 16 different costs to use with them, then insert those into the // quantize_costs array, go through every cell, and see what cost // should be used for it int grid::quantizeCosts() { // to find a good set of quantized costs, lets look through // all the cells quick like and find the max cost, then we // will just make even divisions around it int t; cell c; int max_cost=0; for (c.l=0;c.l<4;c.l++) { for (c.y=0;c.y<height;c.y++) { for (c.x=0;c.x<width;c.x++) { t=cellCostAccurate(c); if (t<(1<<30) && t>max_cost) max_cost=t; } } } // now that we have the max_cost, divide it by 16 and set // up the schedule fprintf(stderr,"quantizeCosts max_cost=%i\n",max_cost); if (max_cost<14) max_cost=14; // don't want a degenerate case cost_quantizer=((float)max_cost/14.0); for (t=0;t<15;t++) { quantized_costs[t]=(int)(((float)t)*cost_quantizer); //fprintf(stderr,"quantized_costs[%i]=%i\n",t,quantized_costs[t]); } quantized_costs[15]=1<<30; // now we need to go through every cell, and assign a shortcut // cost for it for (c.l=0;c.l<4;c.l++) { for (c.y=0;c.y<height;c.y++) { for (c.x=0;c.x<width;c.x++) { resetCost(c); //if (t>0) fprintf(stdout,"(%i,%i,%i) cost(t)=%i" // " stuff=%i\n", // c.x,c.y,c.l,t, // gc[c.l][c.y][c.x].cost); } } } return 0; }