ostream &print (ostream &o, CNet *self) { CDRGrid::iterator coord; int x, y, z, layer; coord = self->_drgrid->origin; o << " +"; for (x = 1; x <= self->_drgrid->X; x++) o << "-"; o << "+\n"; for (y = 1; y <= self->_drgrid->Y; y++) { o << " |"; for (x = 0; x < self->_drgrid->X; x++) { layer = 0; for (z = 1; z < self->_drgrid->Z; z++) { coord.set (x, self->_drgrid->Y - y, z); if (coord.node().data.owner == self) layer = z + 1; } if (layer) o << (char)('A' + layer - 1); else o << ' '; } o << "|\n"; } o << " +"; for (x = 0; x < self->_drgrid->X; x++) o << "-"; o << "+\n"; return (o); }
CDRGrid::iterator &CTerm::lowest (void) { list<CDRGrid::iterator>::iterator itNode, itLowest; CDRGrid::iterator Top; int lowpri; itNode = nodes.begin (); itLowest = itNode; if ( !(*itNode).z() ) lowpri = (*itNode).pri (); else lowpri = INT_MAX; // Find the lowest priority node above the terminals. for (; itNode != nodes.end (); itNode++) { if ( !(*itNode).z() ) { Top = *itNode; Top.top (); if (Top.pri() < lowpri) { itLowest = itNode; lowpri = Top.pri (); } } } return (*itLowest); }
ostream &operator<< (ostream &o, CMatrixPri &self) { CDRGrid::iterator coord; int x, y, z; o << "cleared := " << self.cleared << "\n" << "offset := " << self.offset << "\n" << "delta := " << self.delta << "\n"; coord = self._drgrid->origin; for (z = 1; z < self._drgrid->Z; z++) { o << " (layer) z := " << z << "\n"; for (y = 1; y <= self._drgrid->Y; y++) { o << " "; for (x = 0; x < self._drgrid->X; x++) { o << setw(5) << (int)(self[ coord.set (x, self._drgrid->Y - y, z)]); } o << "\n"; } } return (o); }
void CMatrixPri::findfree (int index, CNet &net) { CDRGrid::iterator coord; int radius, i, j, cx, cy; bool freed; CNet *other; freed = false; radius = 0; cx = _drgrid->x(index); cy = _drgrid->y(index); coord = _drgrid->origin; // Check for blocked upper nodes. other = (*_drgrid->nodes)[index].data.owner; if ( ! (*_drgrid->nodes)[index].data.obstacle && ((other == NULL) || (other == &net)) ) return; cdebug << "Looking for an escape!\n" << "\n"; while (!freed) { radius += 1; for (i = cx - radius; i < cx + radius + 1; i++) { for (j = cy - radius; j < cy + radius + 1; j++) { // Proccess only nodes of the ring. // if ( (i > cx - radius) || (i < cx + radius) ) continue; // if ( (j > cy - radius) || (j < cy + radius) ) continue; coord.set (i,j,2); // Check if we are outside. if (coord.outside()) continue; other = (*_drgrid->nodes)[coord].data.owner; if ( ( ! (*_drgrid->nodes)[coord].data.obstacle ) && ((other == NULL) || (other == &net)) ) { if (!freed) cdebug << "Escape found at " << coord << "\n"; freed = true; } (*this)[ coord.set(i,j,1) ] = (char)1; (*this)[ coord.set(i,j,2) ] = (char)1; } } } cdebug << "Escape radius := " << radius << "\n"; }
void CRBox::mbksave (string &name) throw (except_done) { int x, y, z, mX, mY, mZ, pitch, spaceVIA; bool inseg; CRect rect; CDRGrid::iterator coord; CNode *node; CNet *pNextNet, *pNet, *pNetTop, *pNetBot; MBK::phseg_list seg; MBK::phvia_list via; MNet::iterator itNet, endNet; if (!loaded) { cerr << hwarn ("") << "\n The MBK figure has not been loaded into the grid yet, nothing" << "\n to save at this point.\n"; return; } if (insave) throw except_done (); insave = true; cmess2 << "\n"; cmess1 << " o Dumping routing grid.\n"; mX = drgrid->X; mY = drgrid->Y; mZ = drgrid->Z; coord = drgrid->origin; // A reference to show the grid real origin. MBK::phref_list ref; ref.FIGNAME = MBK::namealloc("ref_ref"); ref.NAME = MBK::namealloc("nero.grid.origin"); ref.XREF = xoffsetgrid; ref.YREF = yoffsetgrid; ref.USER = NULL; ref.NEXT = NULL; fig->addphref ( ref ); ref.NAME = MBK::namealloc("nero.grid.limit"); ref.XREF += D::X_GRID * (mX-1); ref.YREF += D::Y_GRID * (mY-1); fig->addphref ( ref ); // Horizontal planes loop in both directions. for (z = 1; z < mZ; z++) { // Loop for horizontal segments. for (y = 0; y < mY; y++) { inseg = false; pNet = NULL; for (x = 0; x < mX; x++) { node = & ( coord.set(x,y,z).node() ); pNextNet = node->data.owner; if (inseg && (pNextNet != pNet)) { // We are changing of segment owner. // Dump the current one. if (seg.X1 < seg.X2) { // This is not a "dot" segment (i.e a VIA). fig->addphseg (seg,pNet->external,ischip); } else if (z % 2) { char layer = seg.LAYER; seg.LAYER = MBK::layer2TALU (seg.LAYER); fig->addphseg (seg,false,ischip); seg.LAYER = layer; } // Force segment restarting. inseg = false; } pNet = pNextNet; if (pNet) { if (!inseg) { // We encounter the left edge of a segment. inseg = true; seg.X1 = xoffsetgrid + x * D::X_GRID; seg.Y1 = yoffsetgrid + y * D::Y_GRID; seg.Y2 = yoffsetgrid + y * D::Y_GRID; seg.NAME = MBK::namealloc(pNet->name.c_str ()); seg.WIDTH = MBK::env.z2width (z); if (pNet->external && !ischip) seg.LAYER = MBK::env.z2calu (z); else seg.LAYER = MBK::env.z2alu (z); } // Update the right edge. seg.X2 = xoffsetgrid + x * D::X_GRID; } else { if (inseg) { // Dump the current one. if (seg.X1 < seg.X2) { // This is not a "dot" segment (i.e a VIA). fig->addphseg (seg,pNet->external,ischip); } else if (z % 2) { char layer = seg.LAYER; seg.LAYER = MBK::layer2TALU (seg.LAYER); fig->addphseg (seg,false,ischip); seg.LAYER = layer; } } // We encounter the right edge of a segment. inseg = false; } } // End of "x" loop. if (inseg) { // This segment touch the AB. if (seg.X1 < seg.X2) { // This is not a "dot" segment (i.e a VIA). fig->addphseg (seg,pNet->external,ischip); } else if (z % 2 ) { char layer = seg.LAYER; seg.LAYER = MBK::layer2TALU (seg.LAYER); fig->addphseg (seg,false,ischip); seg.LAYER = layer; } } } // End of "y" loop (horizontal segments). // Loop for vertical segments. for (x = 0; x < mX; x++) { inseg = false; pNet = NULL; for (y = 0; y < mY; y++) { node = & ( coord.set(x,y,z).node() ); pNextNet = node->data.owner; if (inseg && (pNextNet != pNet)) { // We are changing of segment owner. // Dump the current one. if (seg.Y1 < seg.Y2) { // This is not a "dot" segment (i.e a VIA). fig->addphseg (seg,pNet->external,ischip); } else if (! (z % 2)) { char layer = seg.LAYER; seg.LAYER = MBK::layer2TALU (seg.LAYER); fig->addphseg (seg,false,ischip); seg.LAYER = layer; } // Force segment restarting. inseg = false; } pNet = pNextNet; if (pNet) { if (!inseg) { // We encounter the left edge of a segment. inseg = true; seg.X1 = xoffsetgrid + x * D::X_GRID; seg.X2 = xoffsetgrid + x * D::X_GRID; seg.Y1 = yoffsetgrid + y * D::Y_GRID; seg.NAME = MBK::namealloc(pNet->name.c_str ()); seg.WIDTH = MBK::env.z2width (z); if (pNet->external && !ischip) seg.LAYER = MBK::env.z2calu (z); else seg.LAYER = MBK::env.z2alu (z); } // Update the right edge. seg.Y2 = yoffsetgrid + y * D::Y_GRID; } else { if (inseg) { // Dump the current one. if (seg.Y1 < seg.Y2) { // This is not a "dot" segment (i.e a VIA). fig->addphseg (seg,pNet->external,ischip); } else if (! (z % 2)) { char layer = seg.LAYER; seg.LAYER = MBK::layer2TALU (seg.LAYER); fig->addphseg (seg,false,ischip); seg.LAYER = layer; } } // We encounter the right edge of a segment. inseg = false; } } // End of "y" loop. if (inseg) { // This segment touch the AB. if (seg.Y1 < seg.Y2) { // This is not a "dot" segment (i.e a VIA). fig->addphseg (seg,pNet->external,ischip); } else if (! (z % 2)) { char layer = seg.LAYER; seg.LAYER = MBK::layer2TALU (seg.LAYER); fig->addphseg (seg,false,ischip); seg.LAYER = layer; } } } // End of "x" loop (vertical segments). } // End of "z" loop (planes). via.DX = 0; via.DY = 0; // Plane loop for VIAs. for (z = 1; z < mZ; z++) { // Track loop for VIAs. if (z >= drgrid->zupper) pitch = 1; else pitch = 1; if (z % 2) { // z=1 (ALU2) : horizontal tracks. for (y = 1; y < mY; y += pitch) { for (x = 0, spaceVIA = 2; x < mX; x++, spaceVIA++) { // Bottom node. pNetBot = NULL; node = & ( coord.set(x,y,z-1).node() ); if ( !coord.isnodehole() && coord.inside() ) pNetBot = node->data.owner; // Top node. pNetTop = NULL; node = & ( coord.set(x,y,z).node() ); if ( !coord.isnodehole() && coord.inside() ) pNetTop = node->data.owner; // Are the top & bottom nodes belonging to the same net ? if ( (pNetBot != NULL) && (pNetBot == pNetTop) ) { if (spaceVIA < pitch) continue; via.TYPE = MBK::env.z2via (z); via.XVIA = xoffsetgrid + x * D::X_GRID; via.YVIA = yoffsetgrid + y * D::Y_GRID; via.NAME = MBK::namealloc(pNetTop->name.c_str ()); fig->addphvia (via); spaceVIA = 0; } } } } else { // z=2 (ALU3) : vertical tracks. for (x = 1; x < mX; x += pitch) { for (y = 0, spaceVIA = 2; y < mY; y++, spaceVIA++) { // Bottom node. pNetBot = NULL; node = & ( coord.set(x,y,z-1).node() ); if ( !coord.isnodehole() && coord.inside() ) pNetBot = node->data.owner; // Top node. pNetTop = NULL; node = & ( coord.set(x,y,z).node() ); if ( !coord.isnodehole() && coord.inside() ) pNetTop = node->data.owner; // Are the top & bottom nodes belonging to the same net ? if ( (pNetBot != NULL) && (pNetBot == pNetTop) ) { if (spaceVIA < pitch) continue; via.TYPE = MBK::env.z2via (z); via.XVIA = xoffsetgrid + x * D::X_GRID; via.YVIA = yoffsetgrid + y * D::Y_GRID; via.NAME = MBK::namealloc(pNetTop->name.c_str ()); fig->addphvia (via); spaceVIA = 0; } } } } } // Special case of nets with only one terminal. endNet = nets.end (); for (itNet = nets.begin(); itNet != endNet; itNet++) { if (!itNet->second->external) continue; if (itNet->second->size != 1) continue; if (itNet->second->terms[0]->rects.size() < 1) continue; rect = itNet->second->terms[0]->rects.front (); seg.X1 = xoffsetgrid + rect.x1 * D::X_GRID; seg.X2 = xoffsetgrid + rect.x2 * D::X_GRID; seg.Y1 = yoffsetgrid + rect.y1 * D::Y_GRID; seg.Y2 = yoffsetgrid + rect.y2 * D::Y_GRID; seg.NAME = MBK::namealloc(itNet->second->name.c_str ()); seg.WIDTH = MBK::env.z2width (0); seg.LAYER = MBK::env.z2calu (0); fig->addphseg (seg,itNet->second->external,ischip); } // Add powers lines. if ( !ischip ) powers[MBK::CALU1]->dump (fig); cmess1 << " o Saving MBK figure \"" << name << "\".\n"; fig->phfig.saveas (name); }
void CRBox::mbkload (MBK::CFig *mbkfig , int z , int zup , int rtype , bool halfpitch , bool xhalfpitch , bool yhalfpitch , bool rotate , set<string>* subNetList ) { MBK::MIns::iterator itIns, endInstances, endOrphans; MBK::MLosig::iterator endSig; MBK::MLosig::iterator sig; long mX, mY, mZ, x, y, zz, xadjust, yadjust, yoffsetslice; long XRW1, YRW1, XRW2, YRW2; bool use_global; long northPad, southPad, eastPad, westPad; long xoffsettrack, yoffsettrack; MBK::chain_list *pChain; MBK::locon_list *pLocon; MBK::phcon_list *pPhcon; MBK::losig_list *pSig; MBK::phseg_list *pSeg, flatSeg; MBK::phvia_list *pVIA; MBK::phfig_list *pModel; MBK::CXRect *rect; MBK::CIns *pIns; CNet *pNet; string sig_name, term_name, ins_name; CDRGrid::iterator coord; CNode *node; cmess1 << "\n"; cmess1 << " o Loading design into grid...\n"; ischip = false; fig = mbkfig; endInstances = fig->instances.end (); endOrphans = fig->orphans.end (); endSig = fig->lofig.signals.end (); northPad = 0; southPad = 0; westPad = 0; eastPad = 0; xoffsettrack = 0; yoffsettrack = 0; // Half pitch offset. if ( halfpitch ) { xoffsettrack = D::X_GRID / 2; yoffsettrack = D::Y_GRID / 2; } else if ( xhalfpitch ) { xoffsettrack = D::X_GRID / 2; } else if ( yhalfpitch ) { yoffsettrack = D::Y_GRID / 2; } // Search for pads. for (itIns = fig->instances.begin(); itIns != endInstances; itIns++) { pModel = itIns->second->getmodel (); if ( MBK::IsPxLib(pModel) ) { switch ( itIns->second->phins->TRANSF ) { case NOSYM: ischip = true; if ( northPad == 0 ) { cmess2 << " o North pad found.\n"; northPad = pModel->YAB2 - pModel->YAB1 - MBK::SCALE(15); } break; case SYM_Y: ischip = true; if ( southPad == 0 ) { cmess2 << " o South pad found.\n"; southPad = pModel->YAB2 - pModel->YAB1 - MBK::SCALE(15); } break; case ROT_P: ischip = true; if ( eastPad == 0 ) { cmess2 << " o East pad found.\n"; eastPad = pModel->YAB2 - pModel->YAB1 - MBK::SCALE(15); } break; case SY_RP: ischip = true; if ( westPad == 0 ) { cmess2 << " o West pad found.\n"; westPad = pModel->YAB2 - pModel->YAB1 - MBK::SCALE(15); } break; default: cerr << hwarn ("") << " Pad " << itIns->second->phins->INSNAME << " have an invalid orientation.\n"; break; } } } //southPad = northPad = westPad = eastPad = MBK::SCALE(50); //westPad = MBK::SCALE(100); // Default Routing Widow size : the AB. XRW1 = fig->XAB1 () + westPad; YRW1 = fig->YAB1 () + southPad; XRW2 = fig->XAB2 () - eastPad; YRW2 = fig->YAB2 () - northPad; // Find the a seed cell (one either from sxlib or dp_sxlib to // track adjust the grid). for (itIns = fig->instances.begin(); ; itIns++) { if (itIns == endInstances) { xadjust = xoffsettrack; yadjust = yoffsettrack; yoffsetslice = 0; cout << hwarn ("") << " Unable to found a seed cell (i.e. belonging to either\n" << " sxlib or dp_sxlib) grid could be misplaced.\n"; break; } pModel = itIns->second->getmodel (); if ( !MBK::IsPxLib(pModel) ) { cmess2 << " o Using seed cell \"" << itIns->first << "\" (model \"" << pModel->NAME << "\").\n"; xadjust = abs((itIns->second->phins->XINS - XRW1) % D::X_GRID ) + xoffsettrack; yadjust = abs((itIns->second->phins->YINS - YRW1) % D::Y_GRID ) + yoffsettrack; yoffsetslice = abs((itIns->second->phins->YINS - YRW1) % D::Y_SLICE) + YRW1; break; } } xoffsetgrid = XRW1 + xadjust; yoffsetgrid = YRW1 + yadjust; cmess2 << " o Grid offset : (" << MBK::UNSCALE(xoffsetgrid) << "," << MBK::UNSCALE(yoffsetgrid) << ")" << " [adjust (" << MBK::UNSCALE(xadjust) << "," << MBK::UNSCALE(yadjust) << ")]\n"; // Compute the routing grid size. mX = (XRW2 - XRW1) / D::X_GRID + ((xadjust==0)?1:0); mY = (YRW2 - YRW1) / D::Y_GRID + ((yadjust==0)?1:0); mZ = z; // Is the design a complete chip. if (ischip) cmess2 << " o Design have pads, treated as a complete chip.\n"; // Selecting the whether to use global routing. use_global = (mX + mY) > (2 * D::GLOBAL_HP); if (rtype == D::ROUTING_CHOOSE) { if (use_global) { cmess2 << " o Big design, global routing enabled.\n"; rglobal = true; if (z < 5) { cmess2 << " - Forcing 4 routing layers.\n"; mZ = 5; } } else { cmess2 << " o Small design, global routing disabled.\n"; rglobal = false; } } else { if (rtype == D::ROUTING_GLOBAL) { rglobal = true; if (!use_global) { cout << hwarn ("") << " You have enabled global routing on a small design,\n" << " this will waste upper routing layers.\n"; } } if (rtype == D::ROUTING_LOCAL ) { rglobal = false; if (use_global) { cout << hwarn ("") << " You have disabled global routing on a big design,\n" << " this will slow down the routing.\n"; } } } cmess2 << " o Allocating grid size [" << mX << "," << mY << "," << mZ << "].\n"; float mXf = mX; float mYf = mY; float mZf = mZ; float overflow = INT_MAX; if ( mXf * mYf * mZf >= overflow ) { cerr << herr("") << " Internal routing grid capacity exceeded :\n" << " More than " << INT_MAX << "nodes (INT_MAX).\n"; throw except_done(); } // Allocating the routing grid. drgrid = new CDRGrid (xoffsetgrid, yoffsetgrid, mX, mY, mZ, zup); rect = new MBK::CXRect (drgrid); cmess2 << " o Loading external terminals.\n"; // Browse layout for terminals. for (pPhcon = fig->phfig.fig->PHCON; pPhcon != NULL; pPhcon = pPhcon->NEXT) { if (fig->lofig.signals.find(pPhcon->NAME) == endSig) { cerr << hwarn ("") << " The terminal \"" << pPhcon->NAME << "\" at (" << MBK::UNSCALE (pPhcon->XCON) << "," << MBK::UNSCALE (pPhcon->YCON) << ") layer " << MBK::layer2a (pPhcon->LAYER) << "\n" << " do not not belong to any logical signal : ignored.\n"; continue; } pNet = getnet (pPhcon->NAME); term_name = "external."; term_name += pPhcon->NAME; flatSeg.X1 = pPhcon->XCON; flatSeg.Y1 = pPhcon->YCON; flatSeg.X2 = pPhcon->XCON; flatSeg.Y2 = pPhcon->YCON; flatSeg.WIDTH = MBK::env.layer2width (pPhcon->LAYER); flatSeg.LAYER = pPhcon->LAYER; flatSeg.NAME = pPhcon->NAME; rect->setSeg (flatSeg); if ( rect->isInGrid() ) { pNet->newaccess ( term_name , rect->grid , MBK::env.layer2z (pPhcon->LAYER) ); } else { cerr << hwarn ("") << " The terminal \"" << pPhcon->NAME << "\" at (" << MBK::UNSCALE (pPhcon->XCON) << "," << MBK::UNSCALE (pPhcon->YCON) << ") layer " << MBK::layer2a (pPhcon->LAYER) << "\n" << " is outside the routing grid : ignored.\n"; } } cmess2 << " o Finding obstacles.\n"; // Browse father for obstacles (powers are obstacles) and already // routed or partially routed signals. for (pSeg = fig->phfig.fig->PHSEG; pSeg != NULL; pSeg = pSeg->NEXT) { // There must not be obstacle in the father! if (MBK::isobs (pSeg->LAYER)) { cerr << hwarn ("") << " An obstacle has been found at design top level, ignored.\n"; continue; } // Power grid. if (MBK::ISVDD (pSeg->NAME) || MBK::ISVSS (pSeg->NAME)) { if (pSeg->LAYER != MBK::CALU1) { rect->setSeg (*pSeg); //cerr << "+ Top power obstacle\n" << rect; if ( rect->isInGrid() ) drgrid->nodes->obstacle (rect->grid, MBK::env.layer2z (pSeg->LAYER)); } continue; } // Unnamed signals : ignored. if (pSeg->NAME == NULL) { cerr << hwarn ("") << " An unnamed segment has been found at design top level, ignored.\n"; continue; } // Partially routed signals. sig = fig->lofig.signals.find(pSeg->NAME); if ( sig == endSig) { cerr << hwarn ("") << " The segment \"" << pSeg->NAME << "\" at (" << MBK::UNSCALE (pSeg->X1) << "," << MBK::UNSCALE (pSeg->Y1) << ") (" << MBK::UNSCALE (pSeg->X2) << "," << MBK::UNSCALE (pSeg->Y2) << ") layer " << MBK::layer2a (pSeg->LAYER) << "\n" << " do not not belong to any logical signal : ignored."; continue; } pNet = getnet (getsigname(sig->second)); if ( !pNet->fixed ) { cmess2 << " o Signal " << pNet->name << " is assumed to be routed.\n"; pNet->fixed = true; } rect->setSeg (*pSeg); if ( rect->isInGrid() ) { //pNet->newaccess ( pSeg->NAME // , rect->grid // , MBK::env.layer2z (pSeg->LAYER) // ); //cerr << "+ Net obstacle\n" << rect; drgrid->nodes->obstacle (rect->grid, MBK::env.layer2z (pSeg->LAYER)); } else { cerr << hwarn ("") << " The segment \"" << pSeg->NAME << "\" at (" << MBK::UNSCALE (pSeg->X1) << "," << MBK::UNSCALE (pSeg->Y1) << ") (" << MBK::UNSCALE (pSeg->X2) << "," << MBK::UNSCALE (pSeg->Y2) << ") layer " << MBK::layer2a (pSeg->LAYER) << "\n" << " is outside the routing grid : ignored."; } } // Browse for obstacle VIAs. for (pVIA = fig->phfig.fig->PHVIA; pVIA != NULL; pVIA = pVIA->NEXT) { // Only power VIAs must be obstacles. if ( (! MBK::ISVDD (pVIA->NAME)) && (! MBK::ISVSS (pVIA->NAME))) { pNet = getnet (pVIA->NAME); if ( pNet && !pNet->fixed ) continue; } for (x = 0; x < 2; x++) { switch (x) { case 0: flatSeg.LAYER = MBK::topVIALayer (pVIA->TYPE); break; case 1: flatSeg.LAYER = MBK::bottomVIALayer (pVIA->TYPE); break; } if (flatSeg.LAYER == MBK::CALU1) continue; long xVIAshrink = 0; if (pVIA->DX) { xVIAshrink = (pVIA->DX - MBK::SCALE(3)) / 2; } flatSeg.X1 = pVIA->XVIA - xVIAshrink; flatSeg.X2 = pVIA->XVIA + xVIAshrink; flatSeg.Y1 = pVIA->YVIA; flatSeg.Y2 = pVIA->YVIA; flatSeg.WIDTH = pVIA->DY; rect->setSeg (flatSeg); //cerr << "+ Top VIA obstacle (" // << MBK::UNSCALE(pVIA->XVIA) << "," // << MBK::UNSCALE(pVIA->YVIA) << ") " // << MBK::layer2a(flatSeg.LAYER) << endl; //cerr << rect; if ( rect->isInGrid() ) drgrid->nodes->obstacle (rect->grid, MBK::env.layer2z (flatSeg.LAYER)); } } // Browse instances & orphans for obstacles. for (itIns = fig->instances.begin(); ; itIns++) { if (itIns == endInstances) itIns = fig->orphans.begin (); if (itIns == endOrphans ) break; pModel = itIns->second->getmodel (); cdebug << "+ - \"" << itIns->first << "\" (model \"" << pModel->NAME << "\").\n"; // Find the obstacles in the current instance : // 1. - TALUx segments. // 2. - Power Terminals (vdd & vss), in CALUx layers & not CALU1. for (pSeg = pModel->PHSEG; pSeg != NULL; pSeg = pSeg->NEXT) { if ( MBK::isobs (pSeg->LAYER) || (( MBK::ISVDD (pSeg->NAME) || MBK::ISVSS (pSeg->NAME)) && MBK::isCALU (pSeg->LAYER) && (pSeg->LAYER != MBK::CALU1))) { itIns->second->flatseg (flatSeg, *pSeg); rect->setSeg (flatSeg); //cerr << "+ Instance obstacle (" << flatSeg.X1 << "," << flatSeg.Y1 << ")" // << MBK::layer2a(flatSeg.LAYER) << endl; if ( rect->isInGrid() ) drgrid->nodes->obstacle (rect->grid, MBK::env.layer2z (pSeg->LAYER)); if ( !MBK::ISVDD (pSeg->NAME) && !MBK::ISVSS (pSeg->NAME) ) fig->addphseg ( flatSeg, true, ischip ); } } } cmess2 << " o Loading nets into grid.\n"; // Process the signals. for (pSig = fig->LOSIG (); pSig != NULL; pSig = pSig->NEXT) { sig_name = MBK::getsigname (pSig); cdebug << "+ - Signal \"" << sig_name << "\".\n"; // Do not process power nets. // Temporary disabled. //if ( (MBK::ISVDD ((char*)sig_name.c_str ()) != 0) // || (MBK::ISVSS ((char*)sig_name.c_str ()) != 0)) continue; // In the case of external terminals, override the signal name by // the terminal name. pChain = (MBK::chain_list*)(MBK::getptype (pSig->USER, LOFIGCHAIN)->DATA); for (; pChain != NULL; pChain = pChain->NEXT) { pLocon = (MBK::locon_list *)(pChain->DATA); if (pLocon->TYPE == EXTERNAL) { sig_name = pLocon->NAME; break;; } } pNet = getnet (sig_name); // Process each terminal of the signal. pChain = (MBK::chain_list*)(MBK::getptype (pSig->USER, LOFIGCHAIN)->DATA); for (; pChain != NULL; pChain = pChain->NEXT) { pLocon = (MBK::locon_list *)(pChain->DATA); if (pLocon->TYPE == EXTERNAL) { pNet->external = true; continue; } ins_name = ((MBK::loins_list*)(pLocon->ROOT))->INSNAME; pIns = fig->instances[ins_name]; term_name = ins_name + "." + pLocon->NAME; cdebug << "+ I.T : " << term_name << " " << pIns->model->NAME << ".\n"; // Find physical segments / CA of the terminal. for (pSeg = pIns->model->PHSEG; pSeg != NULL; pSeg = pSeg->NEXT) { if (!MBK::isCALU (pSeg->LAYER)) continue; if (pLocon->NAME != pSeg->NAME) continue; pIns->flatseg (flatSeg, *pSeg); rect->setSeg (flatSeg); if ( MBK::IsPxLib(pIns->model) && ( (pLocon->NAME == MBK::namealloc("pad" )) || (pLocon->NAME == MBK::namealloc("vddi")) || (pLocon->NAME == MBK::namealloc("vssi")) || (pLocon->NAME == MBK::namealloc("vdde")) || (pLocon->NAME == MBK::namealloc("vsse")) ) ) { flatSeg.NAME = (char*)sig_name.c_str(); fig->addphseg (flatSeg,true,false); continue; } if ( (MBK::ISVDD ((char*)sig_name.c_str ()) != 0) || (MBK::ISVSS ((char*)sig_name.c_str ()) != 0)) continue; if (rect->isInGrid()) { if ( pNet->fixed ) { drgrid->nodes->obstacle (rect->grid, MBK::env.layer2z (pSeg->LAYER)); } else { pNet->newaccess ( term_name , rect->grid , MBK::env.layer2z (pSeg->LAYER) ); } } else { //if ( MBK::IsPxLib(pModel) ) { // flatSeg.NAME = (char*)sig_name.c_str(); // fig->addphseg (flatSeg,true,false); //} else { cerr << hwarn ("") << " The connector segment \"" << pSeg->NAME << "\" at (" << MBK::UNSCALE (pSeg->X1) << "," << MBK::UNSCALE (pSeg->Y1) << ") (" << MBK::UNSCALE (pSeg->X2) << "," << MBK::UNSCALE (pSeg->Y2) << ") layer " << MBK::layer2a (pSeg->LAYER) << "\n" << " is outside of the grid : ignored."; } //} } } // End of "pChain" (terminal) loop. // Reorder terminals (nearest). pNet->order (); pNet->lockalone (rglobal); cdebug << "+ " << pNet->bb << ".\n"; } // End of "pSig" (signal) loop. // Restrict routed nets to the subNetList. if ( subNetList ) { for ( MNet::iterator it=nets.begin() ; it != nets.end() ; it++ ) { if ( subNetList->find(it->first) != subNetList->end() ) { cmess2 << " o Restricting nets to route.\n"; cmess2 << " - \"" << it->first << "\".\n"; } else it->second->fixed = true; } } // Allocate the net scheduler. cmess2 << " o Allocating the net scheduler.\n"; netsched = new CASimple (&nets, drgrid); // Rebuild the power grid from the instances. if ( !ischip ) { cmess2 << " o Reading power grid.\n"; powers[MBK::CALU1] = new MBK::CPowers ( fig , xadjust - xoffsettrack , yoffsetslice , C_HORIZONTAL , MBK::ALU1 , D::WIDTH_VDD ); } // Forbid the use of the edges of the routing box (only allow // peripheral terminals). coord = drgrid->origin; // Left & Right vertical edges. if ( xadjust == 0 ) { for (x = 0; x < mX; x += mX - 1) { for (y = 0; y < mY; y++) { for (zz = 1; zz < mZ; zz++) { node = &( coord.set(x,y,zz).node() ); if ( !node->terminal() ) node->data.obstacle = true; } } } } // Bottom & top horizontal edges. if ( yadjust == 0 ) { for (y = 0; y < mY; y += mY - 1) { for (x = 0; x < mX; x++) { for (zz = 1; zz < mZ; zz++) { node = &( coord.set(x,y,zz).node() ); if ( !node->terminal() ) node->data.obstacle = true; } } } } // On routing level above zupper (ALU4), use only half of the tracks. for (zz = zup; zz < mZ; zz++) { switch ((zz+rotate) % 2) { case 0: // Vertical tracks. for (x = 2; x < mX; x += 2) { for (y = 1; y < mY - 1; y++) { node = &( coord.set(x,y,zz).node() ); if ( !node->terminal() ) node->data.obstacle = true; } } break; case 1: // Horizontal tracks. for (y = 2; y < mY; y += 2) { for (x = 1; x < mX; x++) { node = &( coord.set(x,y,zz).node() ); if ( !node->terminal() ) node->data.obstacle = true; } } break; } } // This flag ensure that a figure has been successfully loaded. loaded = true; delete rect; }
void CTerm::lockalone (bool global) { CDRGrid::iterator coord; CDRGrid::iterator coord2; int z, i; bool adjust; if (nodes.size() != 1) return; coord = nodes.back (); coord2 = coord; CDRGrid* drgrid = coord._drgrid; if ( (coord.z() > 0) && !global ) return; if ( coord.onAB()) return; //cerr << "+ locking lone terminal : " << coord.node().data.owner->name // << " at " << coord // << endl; // All terminal case, eat up z=1 (ALU2) if not already took. if (coord.z() == 0) { // Go to z=1 (ALU2). //cerr << "+ locking z=1 " << coord << endl; newaccess ( coord.x() , coord.y() , 1 , coord.node().getid() , coord.node().data.owner ); coord2.top(); } if (!global) return; if (coord.z() < 2) { // Go to z=2 (ALU3). //cerr << "+ locking z=2 " << coord2 << endl; newaccess ( coord2.x() , coord2.y() , 2 , coord.node().getid() , coord.node().data.owner ); } if ( drgrid->Z < 3 ) return; // Global terminal : when zupper=4, find the nearest VIA on the // double pitch grid. // Is the terminal in ALU3 (or less). if ( (coord.z() < 3) && (coord.zupper () == 4) ) { if ( coord2.y() % 2 ) { // We are not on the double pitch grid. Try to go there. // Look for up and down grid node. adjust = true; for (i = 0; i < 3; i++) { switch (i) { case 0: coord2.dy (+1); break; case 1: coord2.dy (-2); break; } // Neither node are accessibles, we are probably doomed ... if (i == 2) { coord2.dy (+1); adjust = false; break; } if (coord2.inside()) { if ( !coord2.node().data.obstacle && ( (coord2.node().data.owner == NULL ) || (coord2.node().data.owner == coord.node().data.owner) ) ) { break; } } } if (adjust) { // Adjust to the double grid pitch to z=2 (ALU3). //cerr << "+ locking z=2 (ADJUST) " << coord2 << endl; newaccess ( coord2.x() , coord2.y() , 2 , coord.node().getid() , coord.node().data.owner ); } } } if ( drgrid->Z < 4 ) return; if (coord.z() < 4) { // Go to z=3 (ALU3). //cerr << "+ locking z=3 " << coord2 << endl; newaccess ( coord2.x() , coord2.y() , 3 , coord.node().getid() , coord.node().data.owner ); } }
CNode *CTerm::newaccess (int x, int y, int z, int ident, CNet *net) throw (dup_term, bad_grab, merge_term) { list<CDRGrid::iterator>::iterator itNode; CDRGrid::iterator coord; CNode *pNode; coord = net->_drgrid->origin; coord.set (x, y, z); pNode = &coord.node (); if ((z == 0) && coord.isnodehole()) { pNode = &coord.addnode (); } if (pNode->data.owner) { // Check if the node has already been took by another terminal. if (pNode->data.owner != net) throw bad_grab ( pNode->data.owner->terms[pNode->getid()]->name , net->name , coord.x() , coord.y() , coord.z() , 0 , pNode->data.pri , pNode->terminal() , pNode->data.ident ); // Check if the node belongs to another terminal of this net. // If so, send a merging exception to CNet::newaccess (). if (pNode->getid () != ident) throw merge_term ( pNode->getid() , pNode->data.owner->terms[pNode->getid()]->name , pNode->data.owner->terms[ident]->name , net->name , coord.x() , coord.y() , coord.z() ); return (NULL); } // Check if the node is already in the list (this should never appens !) for (itNode = nodes.begin (); itNode != nodes.end (); itNode++) { if (*itNode == coord) { throw dup_term (name, *itNode); } } pNode->data.owner = net; pNode->data.obstacle = false; pNode->setid (ident); nodes.push_back (coord); return (pNode); }