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); }
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); }