Package edu.byu.ece.rapidSmith.device

Source Code of edu.byu.ece.rapidSmith.device.Device

/*
* Copyright (c) 2010-2011 Brigham Young University
*
* This file is part of the BYU RapidSmith Tools.
*
* BYU RapidSmith Tools is free software: you may redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* BYU RapidSmith Tools is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* A copy of the GNU General Public License is included with the BYU
* RapidSmith Tools. It can be found at doc/gpl2.txt. You may also
* get a copy of the license at <http://www.gnu.org/licenses/>.
*
*/
package edu.byu.ece.rapidSmith.device;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Stack;

import com.caucho.hessian.io.Deflation;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;

import edu.byu.ece.rapidSmith.design.Pin;
import edu.byu.ece.rapidSmith.device.helper.HashPool;
import edu.byu.ece.rapidSmith.device.helper.TileSinks;
import edu.byu.ece.rapidSmith.device.helper.TileSources;
import edu.byu.ece.rapidSmith.device.helper.TileWires;
import edu.byu.ece.rapidSmith.device.helper.WireArray;
import edu.byu.ece.rapidSmith.device.helper.WireArrayConnection;
import edu.byu.ece.rapidSmith.device.helper.WireHashMap;
import edu.byu.ece.rapidSmith.router.Node;
import edu.byu.ece.rapidSmith.util.FamilyType;
import edu.byu.ece.rapidSmith.util.FileTools;
import edu.byu.ece.rapidSmith.util.MessageGenerator;
import edu.byu.ece.rapidSmith.util.PartNameTools;

/**
* This is the main class that stores information about each Xilinx part.  It contains
* a 2D grid of Tiles which contain all the routing and primitive sites necessary for
* a placer and router.
* @author Chris Lavin
* Created on: Apr 22, 2010
*/
public class Device implements Serializable{
 
  //========================================================================//
  // Versions
  //========================================================================//
  /** Serializable Version */
  private static final long serialVersionUID = 6336619462392618775L;
  /** The current release of the tools */
  public static final String rapidSmithVersion = "0.5.2";
  /** This is the current device file version (saved in file to ensure proper compatibility) */
  public static final String deviceFileVersion = "0.4";
 
  //========================================================================//
  // Class Members
  //========================================================================//
  /** A static reference to eliminate duplicate Device objects in memory */
  private static Device singleton = null;
  /** Number of rows of tiles in the device */
  protected int rows;
  /** Number of columns of tiles in the device */
  protected int columns;
  /** A 2D array of all the tiles in the device */
  protected Tile[][] tiles;
  /** The Xilinx part name of the device (ie. xc4vfx12ff668, omits the speed grade) */
  protected String partName;
  /** Keeps track of all the primitive instances on the device */
  protected HashMap<String,PrimitiveSite> primitiveSites;
  /** Keeps track of which Wire objects have a corresponding PIPRouteThrough */
  protected HashMap<WireConnection,PIPRouteThrough> routeThroughMap;
  /** A Map between a tile name (string) and its actual reference */
  protected HashMap<String,Tile> tileMap;

  //========================================================================//
  // Objects that are Populated After Parsing
  //========================================================================//
  /** Created on demand when user calls getPrimitiveSiteIndex(), where the ArrayList index is the ordinal of the PrimitiveType */
  private ArrayList<PrimitiveSite[]> primitiveSiteIndex;
  /** Created on demand when user calls getCompatibleSites(), where the ArrayList index is the ordinal of the PrimitiveType */
  private ArrayList<PrimitiveSite[]> compatibleSiteIndex;
  /** A set of all TileTypes that have switch matrices in them */
  private HashSet<TileType> switchMatrixTypes;
 
  //========================================================================//
  // Object Pools - To remove duplicate objects, null afterwards
  //========================================================================//
  /** Keeps track of each unique Wire object in the device */
  protected HashPool<WireConnection> wirePool;
  /** Keeps track of each unique Wire[] object in the device */
  protected HashPool<WireArray> wireArrayPool;
  /** Keeps track of each unique WireConnection object in the device */
  protected HashPool<WireArrayConnection> wireConnectionPool;
  /** Keeps track of all PIPRouteThrough objects */
  protected HashPool<PIPRouteThrough> routeThroughPool;
  /** Keeps Track of all unique Sinks that exist in Tiles */
  protected HashPool<TileSinks> tileSinksPool;
  /** Keeps Track of all unique Sources Lists that exist in Tiles */
  protected HashPool<TileSources> tileSourcesPool;
  /** Keeps Track of all unique Wire Lists that exist in Tiles */
  protected HashPool<TileWires> tileWiresPool;
  /** Keeps track of all unique primitive pin HashMaps */
  protected HashPool<PrimitivePinMap> primitivePinPool;
 
  /**
   * Constructor, initializes all objects to new, except tile[][]
   */
  public Device(){
    // Class Members
    partName = null;
    primitiveSites = new HashMap<String,PrimitiveSite>();
    routeThroughMap = new HashMap<WireConnection,PIPRouteThrough>();
    switchMatrixTypes = null;
    primitiveSiteIndex = null;
   
    // Object Pools
    wirePool = new HashPool<WireConnection>();
    wireArrayPool = new HashPool<WireArray>();
    wireConnectionPool = new HashPool<WireArrayConnection>();
    routeThroughPool = new HashPool<PIPRouteThrough>();
    tileSinksPool = new HashPool<TileSinks>();
    tileSourcesPool = new HashPool<TileSources>();
    tileWiresPool = new HashPool<TileWires>();
    primitivePinPool = new HashPool<PrimitivePinMap>();
  }
 
  /**
   * This method is intended to only be called by a special method, util.FileTools.loadDevice().
   * This will either return a populated device of the same part if it already exists in memory
   * as the singleton instance or a new device ready to be populated from a file.
   * @param partName The part name of the device to get.
   * @return If no device has been loaded or the part names do not match the singleton instance, it
   * returns a new Device, otherwise it will return an existing copy of the device in memory.
   */
  public static Device getInstance(String partName){
    if(singleton == null || !partName.equals(singleton.getPartName())){
      singleton = new Device();
    }
    return singleton;
  }
 
  /**
   * Gets the corresponding wire enumerator object for this device.
   * @return The wire enumerator for this device.
   */
  public WireEnumerator getWireEnumerator(){
    return WireEnumerator.getInstance(getFamilyType());
  }
 
  /**
   * Initializes the tile array and wire pool.  This is done after the tile dimensions have
   * been parsed from the .xdlrc file.
   */
  protected void createTileArray(){
    tiles = new Tile[this.rows][this.columns];
    for(int i=0; i < this.rows; i++){
      for(int j=0; j < this.columns; j++){
        tiles[i][j] = new Tile();
        tiles[i][j].setColumn(j);
        tiles[i][j].setRow(i);
      }
    }
  }

  /**
   * Checks if this wire is RouteThrough.
   * @param w The wire to test.
   * @return True if the wire is a routeThrough, false otherwise.
   */
  public boolean isRouteThrough(WireConnection w){
    return routeThroughMap.get(w) != null;
  }
 
  //========================================================================//
  // Getter and Setter Methods
  //========================================================================//
  /**
   * Gets the external wire enumeration on the instance pin.
   * @param pin The pin to get the external name from.
   * @return The wire enumeration of the internal pin on the instance primitive of pin.
   */
  public Integer getPrimitiveExternalPin(Pin pin){
    // Check the Pin Mapping patch for proper external pin name mapping
    String extName = PinMappingPatch.getPinMapping(pin.getInstance().getType(), pin.getName());
    if(extName != null){
      return WireEnumerator.getInstance(getFamilyType()).getWireEnum(extName);
    }
   
    Integer extPin = pin.getInstance().getPrimitiveSite().getExternalPinWireEnum(pin.getName());
    if(extPin != null){
      return extPin;
    }
   
    return null;
  }
 
  /**
   * This will creating a routing node from the pin given.
   * @param pin The pin to create the routing node from.
   * @return A new node populated with the pin's tile and wire. The parent
   * field is null and level is zero.
   */
  public Node getNodeFromPin(Pin pin){
    Integer wire = getPrimitiveExternalPin(pin);
    if(wire == null) return null;
    return new Node(pin.getTile(), wire, null, 0);
  }
 
  /**
   * This will creating a routing node from the pin given.
   * @param pin The pin to create the routing node from.
   * @return A new node populated with the pin's tile and wire. The parent
   * field is null and level is zero.
   */
  public Node getNodeFromPin(Pin pin, Node parent, int level){
    Integer wire = getPrimitiveExternalPin(pin);
    if(wire == null) return null;
    return new Node(pin.getTile(), wire, parent, level);
  }
 
  /**
   * Gets the PIPRouteThrough object for a wire.
   * @param w The wire which has a corresponding PIPRouteThrough
   * @return The PIPRouteThrough or null if it does not exist.
   */
  public PIPRouteThrough getRouteThrough(WireConnection w){
    return routeThroughMap.get(w);
  }
 
  /**
   * Gets the current tile in the device based on absolute row and column indices
   * @param row The absolute row index (0 starting at top)
   * @param column The absolute column index (0 starting at the left)
   * @return The tile specified by row and column, if the indices are out of bounds it returns null
   */
  public Tile getTile(int row, int column){
    if(row < 0 || column < 0 || row > this.rows-1 || column > this.columns-1){
      return null;
    }
    return tiles[row][column];
  }
 
  /**
   * This will get a Tile by its name using a HashMap.
   * @param tile The name of the tile to get.
   * @return The tile with the name tile, or null if it does not exist.
   */
  public Tile getTile(String tile){
    return tileMap.get(tile);
  }

  /**
   * Each tile in a device can be referenced by a unique integer which is a combination
   * of its row and column index.  This will get and return the tile with the unique index
   * provided.
   * @param uniqueTileNumber The unique tile number of the tile to get.
   * @return The tile with the uniqueTileNumber, or null if none exists.
   */
  public Tile getTile(int uniqueTileNumber){
    int row = uniqueTileNumber / columns;
    int col = uniqueTileNumber % columns;
    return getTile(row,col);
  }
 
  /**
   * This gets and returns a primitive site on the device by name.
   * @param name Name of the primitive site to get.
   * @return The primitive site with the name, or null if none exists.
   */
  public PrimitiveSite getPrimitiveSite(String name){
    return this.primitiveSites.get(name);
  }
 
  /**
   * A method to get the corresponding primitive site for current in a different tile.
   * For example in a Virtex 4, there are 4 slices in a CLB tile, when moving a hard macro
   * the current slice must go in the same spot in a new CLB tile
   * @param current The current primitive site of the instance.
   * @param newSiteTile The tile of the new proposed site.
   * @return The corresponding site in tile newSite, or null if no corresponding site exists.
   */
  public static PrimitiveSite getCorrespondingPrimitiveSite(PrimitiveSite current, PrimitiveType type, Tile newSiteTile){
    if(newSiteTile == null){
      //MessageGenerator.briefError("ERROR: Bad input to Device.getCorrespondingPrimitiveSite(), newSiteTile==null");
      return null;
    }
    if(newSiteTile.getPrimitiveSites() == null){
      return null;
    }
   
    PrimitiveSite[] ps = current.tile.getPrimitiveSites();
    int idx = -1;
    for(int i=0; i < ps.length; i++){
      if(current.equals(ps[i])){
        idx = i;
        break;
      }
    }
   
    if(idx==-1 || idx >= newSiteTile.getPrimitiveSites().length){
      return null;
    }
    PrimitiveSite newSite = newSiteTile.getPrimitiveSites()[idx];
    if(!newSite.isCompatiblePrimitiveType(type)){
      return null;
    }
    return newSite;
  }

  /**
   * This will take a sink Pin from a design net and determine the
   * final switch matrix and node or wire which the signal must be routed
   * through in order to reach the sink pin.
   * @param pin The sink pin to find a switch matrix for.
   * @return A node (a unique tile and wire) of where the signal must be
   * routed to reach the sink pin. Returns null, if none exists.
   */
  public Node getSwitchMatrixSink(Pin pin){
    int extPin = getPrimitiveExternalPin(pin);
    Tile tile = pin.getInstance().getTile();
    SinkPin sp = tile.getSinks().get(extPin);
    if(sp == null) return null;
    int y = sp.switchMatrixTileOffset;
    int x = y >> 16;
    y = (y << 16) >> 16;
    Node n = new Node(getTile(tile.getRow()+y, tile.getColumn()+x),sp.switchMatrixSinkWire,null,0);
    return n;
  }
 
  /**
   * This will return a set of all unique TileTypes which are considered
   * to have a switch matrix or routing switch box in them.
   * @return A set of all TileTypes which have a switch matrix in them.
   */
  public HashSet<TileType> getSwitchMatrixTypes(){
    if(switchMatrixTypes == null){
      switchMatrixTypes = new HashSet<TileType>();
      switchMatrixTypes.add(TileType.INT);
      switchMatrixTypes.add(TileType.INT_R);
      switchMatrixTypes.add(TileType.INT_L);
      switchMatrixTypes.add(TileType.INT_SO);
      switchMatrixTypes.add(TileType.INT_SO_DCM0);
    }
    return switchMatrixTypes;
  }
 
  /**
   * Gets and returns the number of rows of tiles in this device.
   * @return the number of rows of tiles in the device.
   */
  public int getRows(){
    return rows;
  }

  /**
   * Sets the number of rows of tiles this device has.
   * @param rows the number of rows of tiles to set in the device.
   */
  protected void setRows(int rows){
    this.rows = rows;
  }

  /**
   * Gets and returns the number of columns of tiles in this device.
   * @return the number of columns of tiles in the device.
   */
  public int getColumns(){
    return columns;
  }

  /**
   * Sets the number of columns of tiles this device has.
   * @param columns the number of columns of tiles to set in the device
   */
  protected void setColumns(int columns){
    this.columns = columns;
  }

  /**
   * Gets and returns this device's 2D array of tiles that define
   * the layout of the FPGA.
   * @return the tiles of this device.
   */
  public Tile[][] getTiles(){
    return tiles;
  }

  /**
   * Gets and return the partName (includes package but not speed grade)
   * of this device (ex: xc4vfx12ff668).
   * @return the partName The part name of this device.
   */
  public String getPartName(){
    return PartNameTools.removeSpeedGrade(partName);
  }

  /**
   * Gets and returns the all lower case exact Xilinx family type for this 
   * device (ex: qvirtex4 instead of virtex4). DO NOT use exact family
   * methods if it is to be used for accessing device or wire enumeration
   * files as RapidSmith does not generate files for devices that have
   * XDLRC compatible files. 
   * @return The exact Xilinx family type for this device.
   */
  public FamilyType getExactFamilyType(){
    return PartNameTools.getExactFamilyTypeFromPart(partName);
  }
 
  /**
   * Gets and returns the base family type for this device. This
   * ensures compatibility with all RapidSmith files. For differentiating
   * family types (qvirtex4 rather than virtex4) use getExactFamilyType().
   * @return The base family type of the part for this device.
   */
  public FamilyType getFamilyType(){
    return PartNameTools.getFamilyTypeFromPart(partName);
  }
 
  /**
   * Sets the part name of this device.  This part name should only have the package
   * information but not speed grade (ex: xc4vfx12ff668).
   * @param partName the partName to set.
   */
  protected void setPartName(String partName){
    this.partName = partName;
  }

  /**
   * Gets and returns the HashMap of name to primitive site mappings for this device.
   * @return The map of name to primitive site mappings for this device.
   */
  public HashMap<String, PrimitiveSite> getPrimitiveSites(){
    return primitiveSites;
  }

  /**
   * Gets and returns the HashMap of name to Tile mappings for this device.
   * @return The tile mappings of name to Tile object for this device.
   */
  public HashMap<String, Tile> getTileMap(){
    return tileMap;
  }

  /**
   * Gets and returns the PIP route through map for this device.
   * @return The mappings between wires and PIP route throughs.
   */
  public HashMap<WireConnection, PIPRouteThrough> getRouteThroughMap(){
    return routeThroughMap;
  }

  /**
   * This method will get (create if null) a data structure which stores all
   * of the device's primitive sites by type.  To get all of the primitive
   * sites of a particular type, use the PrimitiveType.ordinal() method to
   * get the representative integer and use that value to index into the
   * ArrayList.  This will return an array of all primitive sites of that
   * same type. 
   * @return The data structure which stores all of the primitive sites
   * separated by type.
   */
  public ArrayList<PrimitiveSite[]> getPrimitiveSiteIndex(){
    if(primitiveSiteIndex == null){
      createPrimitiveSiteIndex();
    }
    return primitiveSiteIndex;
  }
 
  /**
   * This method will get (create if null) a data structure which stores all
   * of the compatible primitive sites for each primitive type.  To get all
   * the compatible primitive sites of a particular type, use the
   * PrimitiveType.ordinal() method to get the representative integer and use
   * that value to index into the ArrayList.  This will return an array of
   * all compatible primitive sites of that same type. 
   * @return The data structure which stores all compatible primitive sites
   * for each primitive type.
   */
  public ArrayList<PrimitiveSite[]> getCompatibleSiteIndex(){
    if(compatibleSiteIndex == null){
      createCompatibleSiteIndex();
    }
    return compatibleSiteIndex;
  }
 
  /**
   * This method will get all primitive sites with the same base type as
   * that passed as a parameter type.  This does not get all
   * compatible sites for the PrimitiveType type as a SLICEL request would
   * only return all SLICEL type sites and no SLICEM types which can also
   * be a valid site for SLICELs.
   * @param type The types of sites to retrieve.
   * @return An array of primitive sites with the same Primitive type as type.
   */
  public PrimitiveSite[] getAllPrimitiveSitesOfType(PrimitiveType type){
    return getPrimitiveSiteIndex().get(type.ordinal());
  }
 
  /**
   * This method will get all compatible primitive sites for a particular
   * primitive type in this device.  For example, a SLICEL can be placed at
   * all SLICEL sites AND all SLICEM sites.  If the type given were SLICEL,
   * this method would return an array of all SLICEL and SLICEM sites.
   * @param type The type for which to find compatible primitive sites.
   * @return An array of compatible sites suitable for placement of a
   * primitive of type type.
   */
  public PrimitiveSite[] getAllCompatibleSites(PrimitiveType type){
    int size = 0;
    // Check if there are sites of the given type
    ArrayList<PrimitiveSite[]> compatibleList = new ArrayList<PrimitiveSite[]>();
    PrimitiveSite[] match = getAllPrimitiveSitesOfType(type);
    if(match != null){
      size += match.length;
      compatibleList.add(match);
    }
   
    // Check for other compatible site types
    PrimitiveType[] compatibleTypes = PrimitiveSite.compatibleTypesArray[getFamilyType().ordinal()].get(type);
    if(compatibleTypes != null){
      for(PrimitiveType compatibleType : compatibleTypes){
        match = getAllPrimitiveSitesOfType(compatibleType);
        if(match != null){
          size += match.length;
          compatibleList.add(match);
        }
      }
    }
   
    // If there are no compatible sites, return null
    if(compatibleList.size() == 0){
      return null;
    }
    int i = 0;
    PrimitiveSite[] newArray = new PrimitiveSite[size];
    for(PrimitiveSite[] sites : compatibleList){
      for(PrimitiveSite site : sites){
        newArray[i] = site;
        i++;
      }
    }
    return newArray;
  }
 
 
  /**
   * Gets and returns an array of all primitive sites of the given primitive type.
   * @param type The primitive type of the site to get.
   * @return An array of all primitive sites in the device with primitive type type.
   */
  public PrimitiveSite[] getAllSitesOfType(PrimitiveType type){
    return getPrimitiveSiteIndex().get(type.ordinal());
  }
 
 
  //========================================================================//
  // Object Population Methods
  //========================================================================//
  /**
   * This will create a data structure which organizes all primitive sites by types.
   * The outer ArrayList uses the PrimitiveType.ordinal() value as the index for
   * each type of primitive site.
   */
  private void createPrimitiveSiteIndex(){
    ArrayList<ArrayList<PrimitiveSite>> tmp = new ArrayList<ArrayList<PrimitiveSite>>(PrimitiveType.values().length);
    for(int i = 0; i < PrimitiveType.values().length; i++){
      tmp.add(new ArrayList<PrimitiveSite>());
    }
     
    for(int i=0; i < this.rows; i++){
      for(int j=0; j < this.columns; j++){
        PrimitiveSite[] sites = tiles[i][j].getPrimitiveSites();
        if(sites == null) continue;
        for(PrimitiveSite site : sites){
          tmp.get(site.getType().ordinal()).add(site);
        }
      }
    }
   
    ArrayList<PrimitiveSite[]> index = new ArrayList<PrimitiveSite[]>();
    for(ArrayList<PrimitiveSite> list : tmp){
      if(list.size() == 0){
        index.add(null);
      }
      else{
        PrimitiveSite[] tmpArray = new PrimitiveSite[list.size()];
        index.add(list.toArray(tmpArray));
      }
    }
    this.primitiveSiteIndex = index;
  }
 
  /**
   * This will create a data structure which finds all compatible primitive
   * sites for a given primitive type.  It populates the compatibleSiteIndex
   * where the outer ArrayList uses the PrimitiveType.ordinal() value as
   * the index of the type to get the compatible sites.
   */
  private void createCompatibleSiteIndex(){
    int size = 0;
    compatibleSiteIndex = new ArrayList<PrimitiveSite[]>(PrimitiveType.values().length);
   
    // For each primitive type
    for(PrimitiveType type: PrimitiveType.values()){
      // Check if there are sites of the given type
      ArrayList<PrimitiveSite[]> compatibleList = new ArrayList<PrimitiveSite[]>();
      PrimitiveSite[] match = getAllPrimitiveSitesOfType(type);
      if(match != null){
        size += match.length;
        compatibleList.add(match);
      }
     
      // Check for other compatible site types
      PrimitiveType[] compatibleTypes = PrimitiveSite.compatibleTypesArray[getFamilyType().ordinal()].get(type);
      if(compatibleTypes != null){
        for(PrimitiveType compatibleType : compatibleTypes){
          match = getAllPrimitiveSitesOfType(compatibleType);
          if(match != null){
            size += match.length;
            compatibleList.add(match);
          }
        }
      }
     
      // If there are no compatible sites, return null
      if(compatibleList.size() == 0){
        compatibleSiteIndex.set(type.ordinal(), null);
        continue;
      }
      int j = 0;
      PrimitiveSite[] newArray = new PrimitiveSite[size];
      for(PrimitiveSite[] sites : compatibleList){
        for(PrimitiveSite site : sites){
          newArray[j] = site;
          j++;
        }
      }
      compatibleSiteIndex.set(type.ordinal(), newArray);
    }   
  }
 
 
 
  /**
   * This method populated the tile map after parsing is complete.
   * @param map A map necessary to make a link between names of tiles and objects.
   */
  protected void populateTileMap(HashMap<String,Integer> map){
    tileMap = new HashMap<String, Tile>();
    for(String name : map.keySet()){
      Integer tileAddr = map.get(name);
      int row = tileAddr >> 16;
      int col = tileAddr & 0xFFFF;
      Tile t = tiles[row][col];
      tileMap.put(name, t);
    }
  }

  /**
   * This method is used to rebuild the tile map when loading the device
   * from a device file.
   */
  private void reconstructTileMap(){
    tileMap = new HashMap<String, Tile>();
    for(Tile[] tileArray : tiles){
      for(Tile t : tileArray){
        tileMap.put(t.getName(), t);
      }
    }
  }
 
  /**
   * This method will iterate through all of the sink pins of the device and determine
   * which switch matrix and wire node a routed path must pass through in order to
   * arrive at the sink.
   * @param we The corresponding wire enumerator for this device.
   */
  public void populateSinkPins(WireEnumerator we){
    HashSet<Integer> setOfExternalPrimitivePins = new HashSet<Integer>();
    HashSet<TileType> switchMatrixTileTypes = getSwitchMatrixTypes();
    int watchDog = 0;
   
    for(String wire : we.getWires()) {
      int w = we.getWireEnum(wire);
      if(we.getWireType(w).equals(WireType.SITE_SINK)){
        setOfExternalPrimitivePins.add(w);
      }
    }
   
    for(Tile[] tileArray : tiles){
      for (Tile tile : tileArray) {
        // Only get the switch box tiles
        if (switchMatrixTileTypes.contains(tile.getType())) {
          if(tile.getWireHashMap() == null) continue;
          for(Integer wire : tile.getWireHashMap().keySet()){
            if(we.getWireType(wire).equals(WireType.INT_SINK)){
              int currINTSinkWire = wire;
              boolean debug = false;
              if(tile.getName().equals("INT_X12Y1") && currINTSinkWire == we.getWireEnum("IMUX_B18")){
                debug = false;
              }
              // There should only be one wire that leaves the tile
              for (WireConnection w : tile.getWireHashMap().get(wire)) {
                if(w.getColumnOffset() != 0 || w.getRowOffset() != 0){
                 
                  Stack<Tile> tileStack = new Stack<Tile>();
                  Stack<WireConnection> wireStack = new Stack<WireConnection>();
                  HashSet<Node> visited = new HashSet<Node>();
                  tileStack.push(tile);
                  wireStack.push(new WireConnection(wire,0,0,true));
                  if(debug) System.out.println("PUSH: " + tile + " " + we.getWireName(wire));
                  watchDog = 0;
                  while (!tileStack.isEmpty() && watchDog < 100) {
                    watchDog++;
                    Tile t1 = tileStack.pop();
                    WireConnection w1 = wireStack.pop();
                    if(debug) System.out.println("  POP: " + t1 + " " + we.getWireName(w1.getWire()));
                    WireConnection[] connections = t1.getWireHashMap().get(w1.getWire());
                    if(connections == null || visited.contains(new Node(t1,w1.getWire(),null,0))){
                      continue;
                    }
                    for (WireConnection wire2 : connections) {
                      if(setOfExternalPrimitivePins.contains(wire2.getWire())){
                        SinkPin found = wire2.getTile(t1).getSinks().get(wire2.getWire());
                        int xOffset = (tile.getColumn() - wire2.getTile(t1).getColumn());
                        int yOffset = (tile.getRow() - wire2.getTile(t1).getRow());
                       
                        if(found == null){
                          /*System.out.println("Null Sink: " + wire2.getTile(this, t1) + " " + we.getWireName(wire2.getWire()));
                          for(Integer sink : wire2.getTile(this, t1).getSinks().keySet()){
                            System.out.println("  " + we.getWireName(sink));
                          }
                          System.out.println("SOURCES: ");
                          for(Integer source : wire2.getTile(this, t1).getSources()){
                            System.out.println("  " + we.getWireName(source));
                          }*/
                          continue;
                        }
                       
                        found.switchMatrixSinkWire = currINTSinkWire;
                        found.switchMatrixTileOffset = (xOffset << 16) | (yOffset & 0xFFFF);

                        if(debug) System.out.println("  FOUND: " + wire2.getTile(t1) + " " + we.getWireName(wire2.getWire()) +" xOffset="+ xOffset + " yOffset=" + yOffset);
                       
                        if(debug) System.out.println("  SECOND: " + wire2.getTile(t1) + " " + we.getWireName(wire2.getWire()));
                        if(!visited.contains(new Node(t1,w1.getWire(),null,0))) {
                          tileStack.push(wire2.getTile(t1));
                          wireStack.push(wire2);                         
                        }
                      }
                      else if(wire2.getTile(t1) != null && !switchMatrixTileTypes.contains(wire2.getTile(t1).getType())){
                        if(debug) System.out.println("  POTENTIAL: " + wire2.getTile(t1) + " " + we.getWireName(wire2.getWire()));
                        if(!visited.contains(new Node(t1,w1.getWire(),null,0))) {
                          tileStack.push(wire2.getTile(t1));
                          wireStack.push(wire2);                         
                        }                     
                      }
                    }
                    visited.add(new Node(t1,w1.getWire(),null,0));
                  }
                  tileStack.clear();
                  wireStack.clear();
                }
              }
            }
          }
        }
      }
    }
  }
 
  //========================================================================//
  // Object Compact Methods
  //========================================================================//
  /**
   * This finds all of the unique tile sink HashMaps.  This must be done at the
   * end of parsing all the tiles because in order to get the switch matrix
   * sink wires, we must have a full routing map in place.
   */
  protected void removeDuplicateTileSinks(WireEnumerator we){
    for(int i=0; i < this.rows; i++){
      for(int j=0; j < this.columns; j++){
        tiles[i][j].setSinks(tileSinksPool.add(new TileSinks(tiles[i][j].getSinks())).sinks);
      }
    }
  }
 
  /**
   * This function helps reduce memory footprint of the design parser by looking for duplicate
   * objects after each tile object is created.
   */
  protected void incrementalRemoveDuplicateTileResources(Tile t, WireEnumerator we){
    // Check Sources
    t.setSources(tileSourcesPool.add(new TileSources(t.getSources())).sources);

    // Check Wires
    t.setWireHashMap(tileWiresPool.add(new TileWires(t.getWireHashMap())).wires);
    if(t.getWireHashMap() != null) removeDuplicateWireArrays(t);
  }

  protected void removeDuplicateWireArrays(Tile t){
    for(Integer key : t.getWires()){
      WireArray unique = wireArrayPool.add(new WireArray(t.getWireConnections(key)));
      t.getWireHashMap().put(key, unique.array);
    }
  }
 
  protected void removeDuplicatePrimitivePinMaps(){
    for(PrimitiveSite p : primitiveSites.values()){
      PrimitivePinMap map = new PrimitivePinMap(p.getPins());
      p.setPins(primitivePinPool.add(map).pins);     
    }
  }
 
  protected void createWireConnectionEnumeration(){
    for(int i=0; i < getRows(); i++){
      for(int j=0; j < getColumns(); j++){
        if(tiles[i][j].getWireHashMap() == null) continue;
        for(Integer wire : tiles[i][j].getWires()){
          WireArrayConnection tmp =
            new WireArrayConnection(wire,wireArrayPool.getEnumerationValue(new WireArray(tiles[i][j].getWireConnections(wire))));
          wireConnectionPool.add(tmp);
        }
      }
    }
  }
 
  public void debugPoolCounts(){
    System.out.println("\n");
      MessageGenerator.printHeader("Unique Object Counts");
    debugPrintUniquePoolCount(wirePool, "Wires");
    debugPrintUniquePoolCount(wireArrayPool, "Wire[]s");
    debugPrintUniquePoolCount(wireConnectionPool, "WireConnections");
    debugPrintUniquePoolCount(routeThroughPool, "PIPRouteThroughs");
    debugPrintUniquePoolCount(tileSinksPool, "TileSinks");
    debugPrintUniquePoolCount(tileSourcesPool, "TileSources");
    debugPrintUniquePoolCount(tileWiresPool, "TileWires");
    debugPrintUniquePoolCount(primitivePinPool, "PrimitivePinMap");
  }
 
  private void debugPrintUniquePoolCount(@SuppressWarnings("rawtypes") HashPool p, String name){
    System.out.printf("%10d : Unique %s\n",p.getEnumerations().size(),name);
  }
 
  //========================================================================//
  // Reading Writing Methods from/to Compact File
  //========================================================================//
  private static void debugWritingSize(Hessian2Output hos, FileOutputStream fos,
      String variableName, Long[] locations){
    try {
      hos.flush();
      locations[0] = fos.getChannel().position();
      System.out.printf("%10d bytes : %s\n",(locations[0]-locations[1]),variableName);
      locations[1] = locations[0];
    } catch (IOException e) {
      return;
    }
   
  }
 
  /**
   * This function is used to write a compact version of the device to a file. The file can
   * only be read by using the corresponding function readDeviceFromCompactFile().
   * @param fileName Name of the file to create and store data for the device in the compact format
   * @return True if operation is successful, false otherwise.
   */
  public boolean writeDeviceToCompactFile(String fileName){
    // Update tile references to the device
    for(Tile[] tiles : getTiles()){
      for(Tile tile : tiles){
        tile.setDevice(this);
      }
    }
    try{   
      FileOutputStream fos = new FileOutputStream(fileName);
      Hessian2Output h2os = new Hessian2Output(fos);
      Deflation deflate = new Deflation();
      Hessian2Output hos = deflate.wrap(h2os);
     
      /* DEBUG */ Long[] locations = new Long[2];
      /* DEBUG */ locations[1] = fos.getChannel().position();
      /* DEBUG */ System.out.println("\n");
      MessageGenerator.printHeader("File Usage Statistics");

      //=======================================================//
      /* public static final String deviceFileVersion;         */
      //=======================================================//
      hos.writeString(deviceFileVersion);     
      /* DEBUG */ debugWritingSize(hos,fos,"deviceFileVersion",locations);
     
      //=======================================================//
      /* public int tileRows;                                  */
      //=======================================================//
      hos.writeInt(rows);     
      /* DEBUG */ debugWritingSize(hos,fos,"tileRows",locations);

      //=======================================================//
      /* public int tileColumns;                               */
      //=======================================================//
      hos.writeInt(columns);
      /* DEBUG */ debugWritingSize(hos,fos,"tileColumns",locations);

      //=======================================================//
      /* - wirePool -                                          */
      //=======================================================//
      hos.writeInt(wirePool.getEnumerations().size());
      for(WireConnection w : wirePool.getEnumerations()){
        int mask = w.isPIP() ? 0x80000000 : 0x0;
        hos.writeInt(mask | (w.getWire()));       
        hos.writeInt((w.getRowOffset() << 16) | (w.getColumnOffset() & 0xFFFF));
      }
      /* DEBUG */ debugWritingSize(hos,fos,"wirePool",locations);
     
      //=======================================================//
      /* - wireArrayPool -                                     */
      //=======================================================//
      hos.writeInt(wireArrayPool.getEnumerations().size());
      for(WireArray wireArray : wireArrayPool.getEnumerations()){
        hos.writeInt(wireArray.array.length);
        /*if(wireArray.array.length > 128){
          System.out.println("Bad Assumption");
          System.exit(1);
        }*/
        for(WireConnection w : wireArray.array){
          hos.writeInt(wirePool.getEnumerationValue(w));
        }
      }
      /* DEBUG */ debugWritingSize(hos,fos,"wireArrayPool",locations);

      //=======================================================//
      /* - wireConnectionPool -                                */
      //=======================================================//
      hos.writeInt(wireConnectionPool.getEnumerations().size());
      for(WireArrayConnection wc : wireConnectionPool.getEnumerations()){
        hos.writeInt(wc.wire);
        hos.writeInt(wc.wireArrayEnum);
      }
      /* DEBUG */ debugWritingSize(hos,fos,"wireConnectionPool",locations);           
     
      //=======================================================//
      /* - tileSinksPool -                                     */
      //=======================================================//
      hos.writeInt(tileSinksPool.getEnumerations().size());
      for(TileSinks s : tileSinksPool.getEnumerations()){
        hos.writeInt(s.sinks.size());
        for(Integer key: s.sinks.keySet()) {
          SinkPin sp = s.sinks.get(key);
          hos.writeInt(key);
          hos.writeInt(sp.switchMatrixSinkWire);
          hos.writeInt(sp.switchMatrixTileOffset);
        }
      }
      /* DEBUG */ debugWritingSize(hos,fos,"tileSinksPool",locations);
     
      //=======================================================//
      /* - tileSourcesPool -                                   */
      //=======================================================//
      hos.writeInt(tileSourcesPool.getEnumerations().size());
      for(TileSources s : tileSourcesPool.getEnumerations()){
        FileTools.writeIntArray(hos, s.sources);
      }
      /* DEBUG */ debugWritingSize(hos,fos,"tileSourcesPool",locations);
     
      //=======================================================//
      /* - tileWiresPool -                                     */
      //=======================================================//
      hos.writeInt(tileWiresPool.getEnumerations().size());
      for(TileWires tw : tileWiresPool.getEnumerations()){
        FileTools.writeWireHashMap(hos, tw.wires, wireArrayPool, wireConnectionPool);
      }
      /* DEBUG */ debugWritingSize(hos,fos,"tileWiresPool",locations);
     
      //=======================================================//
      /* public Tile[][] tiles;                                */
      //=======================================================//
      int index = 0;
      String[] tileNames = new String[rows*columns];
      int[] tileTypes = new int[rows*columns];
      int[] tileSinks = new int[rows*columns];
      int[] tileSources = new int[rows*columns];
      int[] tileWires = new int[rows*columns];
      int[] primitiveSitesCount = new int[rows*columns];
      for(Tile[] tileArray : tiles){
        for(Tile t : tileArray){
          // Name
          tileNames[index] = t.getName();
          // Type
          tileTypes[index] = t.getType().ordinal();
          // Sinks
          tileSinks[index] = tileSinksPool.getEnumerationValue(new TileSinks(t.getSinks()));
          // Sources
          tileSources[index] = tileSourcesPool.getEnumerationValue(new TileSources(t.getSources()));
          // Wires
          tileWires[index] = tileWiresPool.getEnumerationValue(new TileWires(t.getWireHashMap()));
          // PrimitiveSites Count
          primitiveSitesCount[index] = t.getPrimitiveSites() == null 0 : t.getPrimitiveSites().length;
          index++;
        }
      }
      FileTools.writeStringArray(hos, tileNames);
      FileTools.writeIntArray(hos, tileTypes);
      FileTools.writeIntArray(hos, tileSinks);
      FileTools.writeIntArray(hos, tileSources);
      FileTools.writeIntArray(hos, tileWires);
      FileTools.writeIntArray(hos, primitiveSitesCount);
      /* DEBUG */ debugWritingSize(hos,fos,"tiles[][]",locations);

      //=======================================================//
      /* public String partName;                               */
      //=======================================================//
      //FileTools.writeString(dos, partName);
      hos.writeString(partName);
      /* DEBUG */ debugWritingSize(hos,fos,"partName",locations);

      //=======================================================//
      /* - primitivePinPool -                                  */
      //=======================================================//
      hos.writeInt(primitivePinPool.getEnumerations().size());
      for(PrimitivePinMap map : primitivePinPool.getEnumerations()){
        FileTools.writeHashMap(hos, map.pins);
      }
      /* DEBUG */ debugWritingSize(hos,fos,"primitivePinPool",locations);
     
      //=======================================================//
      /* public HashMap<String,Primitive> primitives;          */
      //=======================================================//   
      hos.writeInt(primitiveSites.values().size());
      for(Tile[] tileArray : tiles){
        for(Tile t : tileArray){
          if(t.getPrimitiveSites() != null){
            for(PrimitiveSite p : t.getPrimitiveSites()){
              FileTools.writePrimitiveSite(hos, p, this, primitivePinPool);
            }
          }
        }
      }
      /* DEBUG */ debugWritingSize(hos,fos,"primitives",locations);
     
      //=======================================================//
      /* public HashMap<Wire,PIPRouteThrough> routeThroughMap; */
      //=======================================================//
      hos.writeInt(routeThroughMap.size());
      for(WireConnection w : routeThroughMap.keySet()){
        PIPRouteThrough p = routeThroughMap.get(w);
        hos.writeInt(p.getType().ordinal());
        hos.writeInt(p.getInWire());
        hos.writeInt(p.getOutWire());
        hos.writeInt(wirePool.getEnumerationValue(w));
      }
      /* DEBUG */ debugWritingSize(hos,fos,"routeThroughMap",locations);     
      /* DEBUG */ System.out.println("------------------------------------------");     
      /* DEBUG */ System.out.printf("%10d bytes : %s\n\n",(fos.getChannel().position()),"Total");
     
      hos.close();
      fos.close();
    }
    catch (IOException e){
      return false;
    }   
    return true;
  }
 
  /**
   * This reads from the compact device file to populate all of the essential variables of this
   * device.  It can only be used to read files generated with the writeDeviceToCompactFile() method.
   * @param fileName The name of the compact device file
   * @return True if operation was successful, false otherwise.
   */
  public boolean readDeviceFromCompactFile(String fileName){
    try {
      Hessian2Input his = FileTools.getInputStream(fileName);
      int size;
     
      //=======================================================//
      /* public static final String deviceFileVersion;         */
      //=======================================================//
      String check = his.readString();
      if(!check.equals(deviceFileVersion)){
        MessageGenerator.briefErrorAndExit("Error, the current version " +
          "of RAPIDSMITH is not compatible with the device " +
          "file(s) present on this installation.  Delete the 'device' " +
          "directory and run the Installer again to regenerate new " +
          "device files.\nCurrent RAPIDSMITH device file " +
          "version: " + deviceFileVersion +", existing device file " +
          "version: " + check + ".");
      }
     
      //=======================================================//
      /* public int tileRows;                                  */
      //=======================================================//
      rows = his.readInt();
     
      //=======================================================//
      /* public int tileColumns;                               */
      //=======================================================//
      columns = his.readInt();

      //=======================================================//
      /* - wirePool -                                          */
      //=======================================================//
      WireConnection[] wires = new WireConnection[his.readInt()];
      for(int i=0; i < wires.length; i++){
        int part1 = his.readInt();
        int part2 = his.readInt();
        wires[i] = new WireConnection(0x7FFFFFFF&part1,part2 >> 16,(part2 << 16) >> 16,(part1 & 0x80000000) == 0x80000000);
      }

      //=======================================================//
      /* - wireArrayPool -                                     */
      //=======================================================//
      size = his.readInt();
      ArrayList<WireConnection[]> wireArrays = new ArrayList<WireConnection[]>(size);
      for(int i=0; i < size; i++){
        int len = his.readInt();
        WireConnection[] tmp = new WireConnection[len];
        for(int j=0; j < len; j++){
          tmp[j] = wires[his.readInt()];
        }
        wireArrays.add(tmp);
      }
     
      //Create a set of Integer objects to avoid duplication
      Integer[] allInts = new Integer[getFamilyWireCount(fileName)];
      for (int i = 0; i < allInts.length; i++) {
        allInts[i] = new Integer(i);
      }
     
      //=======================================================//
      /* - wireConnectionPool -                                */
      //=======================================================//
      size = his.readInt();
      ArrayList<WireArrayConnection> wireConnections = new ArrayList<WireArrayConnection>();
      for(int i=0; i < size; i++){
        wireConnections.add(new WireArrayConnection(his.readInt(),his.readInt()));
      }
     
      //=======================================================//
      /* - tileSinksPool -                                     */
      //=======================================================//
      size = his.readInt();
      ArrayList<HashMap<Integer,SinkPin>> sinks = new ArrayList<HashMap<Integer,SinkPin>>();
      for(int i=0; i < size; i++){
        int length = his.readInt();
        HashMap<Integer,SinkPin> tmp = new HashMap<Integer,SinkPin>();
        for(int j = 0; j < length; j++){
          tmp.put(allInts[his.readInt()], new SinkPin(his.readInt(),his.readInt()));
        }
        sinks.add(tmp);
      }
     
      //=======================================================//
      /* - tileSourcesPool -                                   */
      //=======================================================//
      size = his.readInt();
      ArrayList<int[]> sources = new ArrayList<int[]>();
      for(int i=0; i < size; i++){
        sources.add(FileTools.readIntArray(his));
      }
     
      //=======================================================//
      /* - tileWiresPool -                                     */
      //=======================================================//
      size = his.readInt();
      ArrayList<WireHashMap> wireMaps = new ArrayList<WireHashMap>(size);
      for(int i=0; i < size; i++){
        wireMaps.add(FileTools.readWireHashMap(his,wireArrays,wireConnections));
      }
     
      //=======================================================//
      /* public Tile[][] tiles;                                */
      //=======================================================//
      createTileArray();
      tileMap = new HashMap<String, Tile>();
      String[] tileNames = FileTools.readStringArray(his);
      int[] tileTypes = FileTools.readIntArray(his);
      int[] tileSinks = FileTools.readIntArray(his);
      int[] tileSources = FileTools.readIntArray(his);
      int[] tileWires = FileTools.readIntArray(his);
      int[] primitiveSiteCount = FileTools.readIntArray(his);
      TileType[] typeValues = TileType.values();
      int index = 0;
      for(Tile[] tileArray : tiles){
        for(Tile t : tileArray){
          // Name
          t.setName(tileNames[index]);
          // Type
          t.setType(typeValues[tileTypes[index]]);
          // Sinks
          t.setSinks(sinks.get(tileSinks[index]));
          // Sources
          t.setSources(sources.get(tileSources[index]));
          // Wires
          t.setWireHashMap(wireMaps.get(tileWires[index]));

          // Populate tileMap
          tileMap.put(tileNames[index], t);
         
          // Populate Device reference
          t.setDevice(this);
         
          index++;
        }
      }

      //=======================================================//
      /* public String partName;                               */
      //=======================================================//
      partName = his.readString();
     
      //=======================================================//
      /* - primitivePinPool -                                  */
      //=======================================================//
      size = his.readInt();
      ArrayList<HashMap<String,Integer>> primitivePinMaps = new ArrayList<HashMap<String,Integer>>();
      for(int i=0; i < size; i++){
        primitivePinMaps.add(FileTools.readHashMap(his, allInts));
      }
     
      //=======================================================//
      /* public HashMap<String,Primitive> primitives;          */
      //=======================================================//   
      size = his.readInt();
      PrimitiveType[] typeValues2 = PrimitiveType.values();
      int idx = 0;
      int zeros = 0;
      for(Tile[] tileArray : tiles){
        for(Tile t : tileArray){
          if(primitiveSiteCount[idx] == 0){
            t.setPrimitiveSites(null);
            zeros++;
          }
          else{
            PrimitiveSite[] p = new PrimitiveSite[primitiveSiteCount[idx]];
            for(int i = 0; i < primitiveSiteCount[idx]; i++){
              p[i] = FileTools.readPrimitiveSite(his, this, primitivePinMaps, typeValues2);
              primitiveSites.put(p[i].getName(), p[i]);
            }
            t.setPrimitiveSites(p);
          }
          idx++;
        }
      }

      //=======================================================//
      /* public HashMap<Wire,PIPRouteThrough> routeThroughMap; */
      //=======================================================//
      size = his.readInt();
      for(int i=0; i < size; i++){
        PIPRouteThrough prt = new PIPRouteThrough(typeValues2[his.readInt()],his.readInt(),his.readInt());
        routeThroughMap.put(wires[his.readInt()], prt);
      }

      //=======================================================//
      /* - populateDeviceTileMap -                             */
      //=======================================================//
      reconstructTileMap();
     
      his.close();
    }
    catch (FileNotFoundException e){
      return false;
    }
    catch (IOException e){
      return false;
    }
   
    return true;
  }
 
  /**
   * This method is used only for debugging purposes.
   * @param fileName Name of the debugging file.
   */
  public void writeToDebugFile(String fileName, WireEnumerator we){
    String nl = System.getProperty("line.separator");
    try{
      BufferedWriter bw = new BufferedWriter(new FileWriter(fileName));
      bw.write(this.partName + nl);
     
      WireConnection[] wires = new WireConnection[routeThroughMap.keySet().size()];
      wires = routeThroughMap.keySet().toArray(wires);
      Arrays.sort(wires);
      for(WireConnection w : wires){
        bw.write("RT: " + w.toString(we) + " " + getRouteThrough(w).toString(we) + nl);
      }
     
      for(Tile[] tileArray : tiles){
        for(Tile t : tileArray){
          bw.write("Tile: " + t.getName() + " " + t.getColumn() + " " + t.getRow() + " " + nl);
         
          // Primitive Sites
          if(t.getPrimitiveSites() != null){
            for(PrimitiveSite ps : t.getPrimitiveSites()){
              bw.write("  PrimitiveSite: " + ps.toString() + " " + ps.getType() + nl);
              HashMap<String,Integer> tmp = ps.getPins();
              String[] keys = new String[tmp.size()];
              keys = tmp.keySet().toArray(keys);
              Arrays.sort(keys);
              for(String key : keys){
                bw.write("    " + key + " " + we.getWireName(tmp.get(key)) + nl);
              }
            }           
          }
         
          // Sinks
          HashMap<Integer, SinkPin> tmp = t.getSinks();
          Integer[] keys = new Integer[tmp.size()];
          keys = tmp.keySet().toArray(keys);
          Arrays.sort(keys);
          for(Integer key : keys){
            if(key == -1){
              bw.write("  Sink: -1" + nl);
            }
            else{
              bw.write("  Sink: " + we.getWireName(key) + " ");
              if(tmp.get(key).switchMatrixSinkWire == -1){
                bw.write("-1" + nl);
              }
              else{
                bw.write(tmp.get(key).toString(we) + nl);
              }
            }
          }
         
          // Sources
          int[] srcKeys = t.getSources();
          if(srcKeys != null){
            Arrays.sort(srcKeys);
            for(int key : srcKeys){
              bw.write("  Source: " + we.getWireName(key) + nl);
            }
          }
         
          // Wires
          WireHashMap tmp2 = t.getWireHashMap();
          if(tmp2 != null){
            Integer[] wireKeys = new Integer[tmp2.size()];
            wireKeys = tmp2.keySet().toArray(wireKeys);
            Arrays.sort(wireKeys);
            for(Integer key : wireKeys){
              bw.write("  Wire: " + we.getWireName(key) + nl);
              WireConnection[] connections = tmp2.get(key);
              Arrays.sort(connections);
              for(WireConnection w : connections){
                bw.write("    -> " + w.toString(we) + nl);
              }
            }
          }
        }
      }
      bw.close();
    }
    catch(IOException e){
      MessageGenerator.briefErrorAndExit("Error writing device debug file");
    }
  }
 
  private int getFamilyWireCount(String fileName){
    // Return a large number.  We don't actually need the right number, just
    // a sufficiently large number.  Largest devices tap out at under 70k wires
    // so 100k should be plenty big without being onerous.  The alternative
    // is to load the WireEnumerator and query it.
    return 200000;
  }
}
TOP

Related Classes of edu.byu.ece.rapidSmith.device.Device

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.