Package edu.byu.ece.rapidSmith.device

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

/*
* Copyright (c) 2010 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.*;
import java.util.*;

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

import edu.byu.ece.rapidSmith.device.helper.WireExpressions;
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 utility class creates and governs the translation of the wires enumeration value from its
* actual name.  This enumeration is done so that we can reduce the overhead of manipulating,
* comparing and storing strings.  Using integers is much more efficient.  This is a by-family enumeration
* of Xilinx FPGAs.  Each Xilinx FPGA family will require its own enumerator class.
* @author Chris Lavin
*/
public class WireEnumerator implements Serializable {

  private static final long serialVersionUID = 2388225105007691213L;

  /** A list of all wire names where the index value is the enumeration value */
  private String[] wireArray;
  /** An array used for conversion of wire name to wire enumeration */
  private HashMap<String,Integer> wireMap;
  /** An array used for conversion of wire enumeration to wire name */
  private WireType[] wireTypeArray;
  /** An array that returns the direction of a wire based on wire enumeration value */
  private WireDirection[] wireDirectionArray;
  /** Set of all pip sink wires */
  private HashSet<String> pipSinks;
  /** Set of all pip sink wires */
  private HashSet<String> pipSources;
  /** Keeps track of unique copy in memory */
  private static WireEnumerator singleton = null;
  /** Xilinx FPGA family name (virtex4, virtex5, ...) */
  private FamilyType familyType = null;

  private List<String> tokens;
 
  public static final String wireEnumeratorVersion = "0.2";
 
  /**
   * Constructor, does not initialize anything
   */
  public WireEnumerator(){
  }
 
  /**
   * This method will either return the currently loaded wire enumerator
   * if the wire enumerator exists in memory, or will return a new empty
   * wire enumerator.
   * @param familyType The base family type to be loaded.
   * @return A new wire enumerator or the currently matching loaded wire enumerator.
   */
  public static WireEnumerator getInstance(FamilyType familyType){
    if(singleton == null){
      return singleton = new WireEnumerator();
    }
   
    FamilyType baseFamilyType =
      PartNameTools.getBaseTypeFromFamilyType(singleton.familyType);
    familyType = PartNameTools.getBaseTypeFromFamilyType(familyType);
    if(!baseFamilyType.equals(familyType)){
      singleton = new WireEnumerator();
    }
    return singleton;
  }

  /**
   * Reads a line and splits it into parts.
   * @return The next line from the file, null if EOF.
   */
  private String readLine(BufferedReader br){
    String line = null;
    try{
      line = br.readLine();
    }
    catch(IOException e){
      MessageGenerator.briefErrorAndExit("Error parsing XDLRC file.");
    }
    if(line != null){
      tokens = split(line);
    }
    return line;
  }

  private static List<String> split(String line) {
    List<String> parts = new ArrayList<>();
    int startIndex = 0, endIndex;

    if (line.length() > 0 && line.charAt(0) == '\t') {
      parts.add("");
      startIndex = 1;
      while (line.length() > startIndex && line.charAt(startIndex) == '\t')
        startIndex++;
    }

    while (line.length() > startIndex) {
      endIndex = line.indexOf(" ", startIndex);
      if (endIndex == -1) {
        parts.add(line.substring(startIndex));
        break;
      } else if (endIndex != startIndex) {
        parts.add(line.substring(startIndex, endIndex));
      }
      startIndex = endIndex + 1;
    }

    return parts;
  }

  /**
   * Parses the XDLRC files for all the wire names in a device architecture.
   * @param fileNames The name of the XDLRC file to parse
   * @param outputFileName Name of the output wire enumerator file.
   */
  public void parseXDLRCFiles(ArrayList<String> fileNames, String outputFileName){
    SortedSet<String> wireSet = new TreeSet<>();
    WireExpressions wireExp = new WireExpressions();
    wireMap = new HashMap<>();
    pipSinks = new HashSet<>();
    pipSources = new HashSet<>();
    BufferedReader in;
    String line;
    int lineCount;
    int tileCount = 0;
    int pipCount = 0;
    HashSet<String> externalInpin = new HashSet<>();
    HashSet<String> externalOutpin = new HashSet<>();
   
    for(String fileName : fileNames){
   
      System.out.println(" WireEnumerator Parsing " + fileName);
      lineCount = 0;
      try {
        in = new BufferedReader(new FileReader(fileName));
        while((line = readLine(in)) != null){
          if (tokens.size() > 0 && tokens.get(0).equals("(primitive_defs"))
            break;
          if(tokens.size() > 1){
            switch (tokens.get(1)) {
              case "(pip":
                wireSet.add(tokens.get(3));
                pipSources.add(tokens.get(3));
                pipCount++;

                if (tokens.get(5).endsWith(")")) {
                  wireSet.add(tokens.get(5).substring(0, tokens.get(5).length() - 1));
                  pipSinks.add(tokens.get(5).substring(0, tokens.get(5).length() - 1));
                } else {
                  wireSet.add(tokens.get(5));
                  pipSinks.add(tokens.get(5));
                }
                break;
              case "(wire":
                if (tokens.get(2).charAt(tokens.get(2).length() - 1) == ')') {
                  wireSet.add(tokens.get(2).substring(0, tokens.get(2).length() - 1));
                } else {
                  wireSet.add(tokens.get(2));
                }
                break;
              case "(conn":
                if (tokens.get(3).charAt(tokens.get(3).length() - 1) == ')') {
                  wireSet.add(tokens.get(3).substring(0, tokens.get(3).length() - 1));
                } else {
                  wireSet.add(tokens.get(3));
                }
                break;
              case "(pinwire":
                if (tokens.get(3).equals("input")) {
                  externalInpin.add(tokens.get(4).substring(0, tokens.get(4).length() - 1));
                } else {
                  externalOutpin.add(tokens.get(4).substring(0, tokens.get(4).length() - 1));
                }
                break;
            }
          }
         
          // Read next line
          lineCount++;
          if(lineCount % 10000000 == 0){
            System.out.println("  Processing line number " + lineCount + " of file " + fileName);
          }
        }
        in.close();
      }
      catch (FileNotFoundException e) {
        System.out.println("Could not open file: " + fileName + " , does it exist?");
        System.exit(1);
      }
      catch (IOException e){
        System.out.println("Error reading file: " + fileName);
        System.exit(1);     
      }
    }
    System.out.println("  totalTiles = " + tileCount);
    System.out.println("  totalPIPs = " + pipCount);
   
    /*
     * After the XDLRC file is parsed, all of the wire names are given an enumeration
     * value in this method.  It then writes out the wire enumeration information to fileName.
     */
   
    int i = 0;

   
    // These don't need to be in there
    wireSet.remove("0");
    wireSet.remove("1");
   
    // Create Arrays
    wireArray = new String[wireSet.size()];
    wireDirectionArray = new WireDirection[wireSet.size()];
    wireTypeArray = new WireType[wireSet.size()];
   
    for(String str : wireSet){
      wireMap.put(str, i);
      wireArray[i] = str;
     
      if(externalInpin.contains(str) || externalOutpin.contains(str)){
        if(externalInpin.contains(str)){
          wireTypeArray[i] = WireType.SITE_SINK;
          wireDirectionArray[i] = WireDirection.EXTERNAL;
        }
        else if(externalOutpin.contains(str)) {
          wireTypeArray[i] = WireType.SITE_SOURCE;
          wireDirectionArray[i] = WireDirection.EXTERNAL;
        }
        else{
          System.out.println("This should never printout, WireEnumerator - parseXDLRC()");
        }
       
      }
      else {
        determineTypeAndDirection(str, i, wireExp);     
      }
      i++;
    }

    writeCompactEnumFile(outputFileName);
  }

  /**
   * Gets and returns the Xilinx FPGA family name (all lower case) that
   * corresponds to this instance of the wire enumerator.
   * @return The family name of this wire enumerator.
   */
  public String getFamilyName(){
    if(familyType == null) return null;
    return familyType.toString().toLowerCase();
  }
 
  /**
   * Gets and returns the family type enumeration that corresponds
   * to this instance of the wire enumerator
   * @return The family type of this wire enumerator.
   */
  public FamilyType getFamilyType(){
    return familyType;
  }
 
  /**
   * Given the wire name, it determines the WireDirection of the wire.
   * @param wireName Name of the wire
   * @param wire The enumeration value of the wire
   */
  private void determineTypeAndDirection(String wireName, int wire, WireExpressions wireExp){
    // Determine Direction
    wireDirectionArray[wire] = wireExp.getWireDirection(wireName);
   
    // Determine Type
    wireTypeArray[wire] = wireExp.getWireType(wireName);
  }
 
  /**
   * Save class members to a file.  Used to save this class to a file.  Should be used with
   * the corresponding method readCompactEnumFile().
   * @param fileName Name of the file to be created.
   * @return True if successful, false otherwise.
   */
  public boolean writeCompactEnumFile(String fileName){
    try{
      Hessian2Output hos = FileTools.getOutputStream(fileName);
     
      //=======================================================//
      /* public static final String wireEnumeratorVersion;     */
      //=======================================================//
      hos.writeString(wireEnumeratorVersion);
     
      //=======================================================//
      /* private HashMap<String,Integer> wireMap;              */
      //=======================================================//
           // We'll rebuild this from wireArray

      //=======================================================//
      /* private String[] wireArray;                           */
      //=======================================================//
      if(!FileTools.writeStringArray(hos, wireArray)){
        System.out.println("Failed to write out wireArray.");
        return false;
      }

      //=======================================================//
      /* private WireType[] wireTypeArray;                     */
      /* private WireDirection[] wireDirectionArray;           */
      //=======================================================//     
      int[] wireAttributes = new int[wireArray.length];
      for(int i=0; i < wireAttributes.length; i++){
        wireAttributes[i] = (getWireDirection(i).ordinal() << 16) + getWireType(i).ordinal();
      }
      if(!FileTools.writeIntArray(hos, wireAttributes)){
        System.out.println("Failed to write out wireAttributes.");
        return false;
      }
     
      //=======================================================//
      /* private HashSet<String> pipWireNames;                 */
      //=======================================================//
      int[] pips = new int[pipSources.size()];
      int j=0;
      for(String s : pipSources){
        pips[j] = getWireEnum(s);
        j++;
      }
      if(!FileTools.writeIntArray(hos, pips)){
        System.out.println("Failed to write out pipWires.");
        return false;
      }

      pips = new int[pipSinks.size()];
      j=0;
      for(String s : pipSinks){
        pips[j] = getWireEnum(s);
        j++;
      }
      if(!FileTools.writeIntArray(hos, pips)){
        System.out.println("Failed to write out pipWires.");
        return false;
      }

      hos.close();
    } catch (IOException e){
      MessageGenerator.briefErrorAndExit("Error writing to file: " + fileName);
    }
   
    return true;
  }
 
  public boolean readCompactEnumFile(String fileName, FamilyType familyType){
    // Set the family name for this wire enumerator
    this.familyType = familyType;
   
    try {
      Hessian2Input his = FileTools.getInputStream(fileName);
      
      //=======================================================//
      /* public static final String wireEnumeratorVersion;     */
      //=======================================================//
      String check = his.readString();
//      if(!check.equals(wireEnumeratorVersion)){
//        MessageGenerator.briefErrorAndExit("Error, the current version " +
//          "of RAPIDSMITH is not compatible with the wire enumerator " +
//          "file(s) present on this installation.  Delete the 'device' " +
//          "directory and run the Installer again to regenerate new wire" +
//          " enumerator files.\nCurrent RAPIDSMITH wire enumerator file " +
//          "version: " + wireEnumeratorVersion +", existing device file " +
//          "version: " + check + ".");
//      }
     
      //=======================================================//
      /* private String[] wireArray;                           */
      //=======================================================//
      wireArray = FileTools.readStringArray(his);

      //=======================================================//
      /* private HashMap<String,Integer> wireMap;              */
      //=======================================================//
      wireMap = new HashMap<>();
      for(int i=0; i < wireArray.length; i++){
        wireMap.put(wireArray[i], i);
      }
     
      //=======================================================//
      /* private WireType[] wireTypeArray;                     */
      /* private WireDirection[] wireDirectionArray;           */
      //=======================================================//     
      int[] wireAttributes = FileTools.readIntArray(his);
      wireDirectionArray = new WireDirection[wireAttributes.length];
      wireTypeArray = new WireType[wireAttributes.length];
      WireDirection[] directions = WireDirection.values();
      WireType[] types = WireType.values();
      for(int i=0; i < wireAttributes.length; i++){
        wireDirectionArray[i] =  directions[0x0000FFFF & (wireAttributes[i] >> 16)];
        wireTypeArray[i] = types[0x0000FFFF & wireAttributes[i]];
      }
     
      //=======================================================//
      /* private HashSet<String> pipSources;                 */
      //=======================================================//
      pipSources = new HashSet<>();
      for(int i : FileTools.readIntArray(his)){
        pipSources.add(wireArray[i]);
      }

      if (check.equals("0.2")) {
        //=======================================================//
      /* private HashSet<String> pipSinks;                 */
        //=======================================================//
        pipSinks = new HashSet<>();
        for (int i : FileTools.readIntArray(his)) {
          pipSinks.add(wireArray[i]);
        }
      }
      his.close();
    } catch (FileNotFoundException e){
      MessageGenerator.briefErrorAndExit("Error: could not find file: " + fileName);
    } catch (IOException e){
      MessageGenerator.briefErrorAndExit("Error reading in compactEnum file.");
    }
    return true;
  }
   
  //========================================================================//
  // Lookup Methods
  //========================================================================//   
  /**
   * Gets and returns the unique wire's integer enumeration based on name
   * @param name Name of the wire to get enumeration for
   * @return The enumeration value or -1 for a bad wire name.
   */
  public int getWireEnum(String name){
    if(this.wireMap.containsKey(name)){
      return this.wireMap.get(name);     
    }
    return -1;
  }
 
  /**
   * Gets a wire's name based on its enumeration value
   * @param wire The wire's enumeration of the wire name to be returned
   * @return The string representation (XDL) of the wire name
   */
  public String getWireName(int wire){
    return wireArray[wire];
  }
 
  /**
   * Returns the WireType based on the wire's enumeration value. WireTypes are generally DOUBLE, HEX, PENT,...
   * @param wire The wire to get the WireType for
   * @return The WireType of the wire
   */
  public WireType getWireType(int wire){
    return wireTypeArray[wire];
  }
 
  /**
   * Returns the WireDirection based on the wire's enumeration value.
   * @param wire The wire to get the WireDirection for
   * @return The WireDirection of the wire
   */
  public WireDirection getWireDirection(int wire){
    return wireDirectionArray[wire];
  }
 
  /**
   * Checks if a particular wire is the source of a PIP
   * @param wire The name of the wire to check if it is a PIP
   * @return True if the wire is the source of a PIP, false otherwise.
   */
  public boolean isPIPSourceWire(String wire){
    return pipSources.contains(wire);
  }
  public boolean isPIPSourceWire(int wire){
    return pipSources.contains(getWireName(wire));
  }

  /**
   * Checks if a particular wire is the sink of a PIP
   * @param wire The name of the wire to check if it is a PIP
   * @return True if the wire is the sink of a PIP, false otherwise.
   */
  public boolean isPIPSinkWire(String wire){
    return pipSinks.contains(wire);
  }
  public boolean isPIPSinkWire(int wire){
    return pipSinks.contains(getWireName(wire));
  }

  public boolean isPIPWire(String wire) {
    return isPIPSinkWire(wire) || isPIPSourceWire(wire);
  }

  public boolean isPIPWire(int wire) {
    return isPIPSinkWire(wire) || isPIPSourceWire(wire);
  }

  public String[] getWires() {
    return wireArray;
  }
 
  public static void main(String[] args){
    if(args.length != 1){
      MessageGenerator.briefMessageAndExit("USAGE: <partname>");
    }
    WireEnumerator we = FileTools.loadWireEnumerator(args[0]);
    for (int i = 0; i < we.wireArray.length; i++) {
      System.out.println(i + " " + we.wireArray[i]);
    }
  }
}
TOP

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

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.