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);
}
예제 #2
0
  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);
}