Package edu.byu.ece.rapidSmith.design.parser

Source Code of edu.byu.ece.rapidSmith.design.parser.DesignParser

/*
* 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.design.parser;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import edu.byu.ece.rapidSmith.design.Attribute;
import edu.byu.ece.rapidSmith.design.Design;
import edu.byu.ece.rapidSmith.design.Instance;
import edu.byu.ece.rapidSmith.design.Module;
import edu.byu.ece.rapidSmith.design.ModuleInstance;
import edu.byu.ece.rapidSmith.design.Net;
import edu.byu.ece.rapidSmith.design.NetType;
import edu.byu.ece.rapidSmith.design.PIP;
import edu.byu.ece.rapidSmith.design.Pin;
import edu.byu.ece.rapidSmith.design.PinType;
import edu.byu.ece.rapidSmith.design.Port;
import edu.byu.ece.rapidSmith.device.Device;
import edu.byu.ece.rapidSmith.device.PrimitiveSite;
import edu.byu.ece.rapidSmith.device.PrimitiveType;
import edu.byu.ece.rapidSmith.device.Tile;
import edu.byu.ece.rapidSmith.device.Utils;
import edu.byu.ece.rapidSmith.device.WireEnumerator;
import edu.byu.ece.rapidSmith.util.MessageGenerator;
import edu.byu.ece.rapidSmith.util.StringPool;

public class DesignParser{
  public static String CFG = "cfg";
  public static String VCC = "vcc";
  public static String VDD = "vdd";
  public static String GND = "gnd";
  public static String PIP = "pip";
  public static String NET = "net";
  public static String LOAD = "load";
  public static String WIRE = "wire";
  public static String PORT = "port";
  public static String INST = "inst";
  public static String INPIN = "inpin";
  public static String INOUT = "inout";
  public static String POWER = "power";
  public static String PLACED = "placed";
  public static String BONDED = "bonded";
  public static String GROUND = "ground";
  public static String MODULE = "module";
  public static String ENDMODULE = "endmodule";
  public static String DESIGN = "design";
  public static String OUTPIN = "outpin";
  public static String DRIVER = "driver";
  public static String UNPLACED = "unplaced";
  public static String UNBONDED = "unbonded";
  public static String INSTANCE = "instance";
  public static String COMMA = ",";
  public static String SEMICOLON = ";";
  public static String PIP0 = "->";
  public static String PIP1 = "=-";
  public static String PIP2 = "=>";
  public static String PIP3 = "==";
 
  private Design design;
 
  /**
   * @return the design
   */
  public Design getDesign(){
    return design;
  }

  /**
   * @param design the design to set
   */
  public void setDesign(Design design){
    this.design = design;
  }

  private BufferedInputStream reader;
 
  private String fileName;
 
  private ParserState state;
 
  private int lineNumber;
 
  /** A unique set of strings used to avoid duplicate strings in memory */
  private StringPool pool;
 
  Net currNet = null;
  Instance currInstance = null;
  Module currModule = null;
  PIP currPIP = null;
  Pin currPin = null;
  String currModuleAnchorName = null;
  String currModuleInstanceName = null;
  Device dev = null;
  WireEnumerator we = null;
  HashMap<String, Pin> modPinMap = null;
  ArrayList<String> portNames = null;
  ArrayList<String> portInstanceNames = null;
  ArrayList<String> portPinNames = null;
 
  public DesignParser(String fileName){
    this.fileName = fileName;

    try{
      reader = new BufferedInputStream(new FileInputStream(fileName));
    }
    catch(FileNotFoundException e){
      e.printStackTrace();
      MessageGenerator.briefErrorAndExit("XDL Design Parser ERROR: Could not find XDL file: " + fileName);
    }
  } 
 
  private void expect(String expectedString, String token, ParserState state){
    if(!expectedString.equals(token)){
      new Exception().printStackTrace();
      MessageGenerator.briefErrorAndExit("Parsing Error: Expected token: " + expectedString +
          ", encountered: " + token + " on line: " + lineNumber + " in parser state: " + state.toString());
    }
  }
 
  public Design parseXDL(){
    pool = new StringPool();
    lineNumber = 1;
    state = ParserState.BEGIN_DESIGN;
    char[] buffer = new char[8192];
    try{
      int ch = -1;
      int prev = -1;
      int idx = 0;
      boolean inComment = false;
      while((ch = reader.read()) != -1){
        if(ch == '\n') lineNumber++;
        if(inComment){
          if((prev == '\r' || prev == '\n') && (ch != '\r' && ch != '\n')){
            inComment = false;
            idx = 0;
          }
          else{
            prev = ch;
            continue;
          }
        }
        //System.out.println("ch["+idx+"]=" + ch + "(" + (char) + ch +")");
        switch(ch){
          case ',':
            if(state.equals(ParserState.ATTRIBUTE)){
              buffer[idx++] = (char) ch;
              break;
            }
          case ' ':
          case '"':
            if(state.equals(ParserState.ATTRIBUTE) && prev == '\\'){
              buffer[idx++] = (char) ch;
              break;
            }
          case '\n':
          case '\r':
          case '\t':
            if(idx > 0){
              parseToken(new String(buffer,0, idx));
              idx = 0;
            }
            break;
          case '#':
            if(prev == '\r' || prev == '\n' || prev == -1){
              inComment = true;
              break;
            }
          default:
            buffer[idx++] = (char) ch;
        }
        prev = ch;
      }
    }
    catch(IOException e){
      e.printStackTrace();
      MessageGenerator.briefErrorAndExit("ERROR: IOException while reading XDL file: " + fileName);
    }
    return design;
  }
 
  /**
   * This is the parser state machine that decides how the token created from
   * parseXDL should be applied to the design.  It does some amount of error
   * checking but is not full proof.
   * @param token The token to parse into the design.
   */
  private void parseToken(String token){
    //System.out.println(lineNumber + "<" + token + ">");
    switch(state){
      case BEGIN_DESIGN:
        expect(DESIGN, token, ParserState.BEGIN_DESIGN);
        state = ParserState.DESIGN_NAME;
        break;
      case DESIGN_NAME:
        design.setName(pool.getUnique(token));
        state = ParserState.PART_NAME;
        break;
      case PART_NAME:
        if(design.isHardMacro()){
          if(token.endsWith(";")){
            state = ParserState.XDL_STATEMENT;
            token = token.substring(0, token.length()-1);
          }
          else{
            state = ParserState.CFG_STRING;
          }
        }
        else{
          state = ParserState.NCD_VERSION;         
        }
        design.setPartName(pool.getUnique(token));
        we = design.getWireEnumerator();
        dev = design.getDevice();
        break;
      case NCD_VERSION:
        design.setNCDVersion(pool.getUnique(token));
        state = ParserState.CFG_STRING;
        break;
      case CFG_STRING:
        if(token.equals(CFG)) state = ParserState.ATTRIBUTE;
        else if(token.equals(SEMICOLON)){
          if(currModule != null){
            state = ParserState.MODULE_STATEMENT;
          }
          else{
            state = ParserState.XDL_STATEMENT;                   
          }
        }
        else expect("cfg or ;", token, ParserState.CFG_STRING);
        break;
      case ATTRIBUTE:
        if(token.equals(SEMICOLON)){
          currInstance = null;
          currNet = null;

          if(currModule != null){
            state = ParserState.MODULE_STATEMENT;
          }
          else{
            currInstance = null;
            currNet = null;
            state = ParserState.XDL_STATEMENT;                   
          }
        }
        else if(token.equals(COMMA) && currNet != null){
          state = ParserState.NET_STATEMENT;
        }
        else{
          Attribute attribute = createAttribute(token);
          if(currInstance != null) currInstance.addAttribute(attribute);
          else if(currNet != null){
            currNet.addAttribute(attribute);
            if(attribute.getPhysicalName().equals("_MACRO")){
                ModuleInstance mi = design.getModuleInstance(attribute.getValue());
                currNet.setModuleInstance(mi);
                mi.addNet(currNet);
                Module module = mi.getModule();
                currNet.setModuleTemplate(module);
                currNet.setModuleTemplateNet(module.getNet(currNet.getName().replaceFirst(mi.getName() + "/", "")));
              }
          }
          else if(currModule != null) currModule.addAttribute(attribute);
          else design.addAttribute(attribute);
        }
        break;
      case XDL_STATEMENT:
        if(token.equals(INST)|| token.equals(INSTANCE)){
          currInstance = new Instance();
          state = ParserState.INSTANCE_NAME;
        }
        else if(token.equals(NET)){
          currNet = new Net();
          state = ParserState.NET_NAME;
        }
        else if(token.equals(MODULE)){
          currModule = new Module();
          modPinMap = new HashMap<String, Pin>();
          portNames = new ArrayList<String>();
          portInstanceNames = new ArrayList<String>();
          portPinNames = new ArrayList<String>();
          state = ParserState.MODULE_NAME;
        }
        else if(token.equals(ENDMODULE)){
          state = ParserState.END_MODULE_NAME;
        }
        else{
          expect("inst, net, module or endmodule", token, ParserState.XDL_STATEMENT);
        }
        break;
      case INSTANCE_NAME:
        currInstance.setName(pool.getUnique(token));
        currInstance.setDesign(design);
        if(currModule == null){
          design.addInstance(currInstance);
        }
        else{
          currModule.addInstance(currInstance);
          currInstance.setModuleTemplate(currModule);
          if(currInstance.getName().equals(currModuleAnchorName)){
            currModule.setAnchor(currInstance);
          }
        }
        state = ParserState.INSTANCE_TYPE;
        break;
      case INSTANCE_TYPE:
          PrimitiveType t = Utils.createPrimitiveType(token);
          if(t == null){
            MessageGenerator.briefErrorAndExit("XDL Design Parser Error in file: "+ fileName +", Failed parsing Instance type: \"" + token + "\"");
          }
          currInstance.setType(t);
          state = ParserState.INSTANCE_PLACED;
        break;
      case INSTANCE_PLACED:
        if(token.equals(PLACED)) state = ParserState.INSTANCE_TILE;
        else if(token.equals(UNPLACED)) state = ParserState.INSTANCE_BONDED;
        else expect("placed or unplaced", token, ParserState.INSTANCE_PLACED);
        break;
      case INSTANCE_TILE:
        Tile tile = dev.getTile(token);
        if(tile == null){
          MessageGenerator.briefErrorAndExit("XDL Design Parser Error in file: "+ fileName +", Invalid tile " +
              token + " on line " + lineNumber);
        }
        state = ParserState.INSTANCE_SITE;
        break;
      case INSTANCE_SITE:
        PrimitiveSite site = dev.getPrimitiveSite(token);
        if(site == null){
          MessageGenerator.briefErrorAndExit("XDL Design Parser Error in file: "+ fileName +", Invalid primitive site " +
              token + " on line " + lineNumber);
        }
        if(currModule != null){
          currInstance.setSite(dev.getPrimitiveSite(token));
        }else{
          currInstance.place(dev.getPrimitiveSite(token));         
        }
        state = ParserState.MODULE_INSTANCE_TOKEN;
        break;
      case INSTANCE_BONDED:
        if(token.equals(COMMA)){
          state = ParserState.MODULE_INSTANCE_TOKEN;
        }
        else if(token.equals(CFG)){
          state = ParserState.ATTRIBUTE;
        }
        else if(token.equals(MODULE)){
          state = ParserState.MODULE_INSTANCE_NAME;
        }
        else if(token.equals(BONDED)){
          currInstance.setBonded(true);
          state = ParserState.MODULE_INSTANCE_TOKEN;
        }
        else if(token.equals(UNBONDED)){
          currInstance.setBonded(false);
          state = ParserState.MODULE_INSTANCE_TOKEN;
        }
        else{
          expect("bonded, unbonded or ,", token, ParserState.INSTANCE_BONDED);
        }
        break;
      case MODULE_INSTANCE_TOKEN:
        if(token.equals(CFG)) state = ParserState.ATTRIBUTE;
        else if(token.equals(MODULE)) state = ParserState.MODULE_INSTANCE_NAME;
        else expect("cfg or module", token, ParserState.MODULE_INSTANCE_TOKEN);
        break;
      case MODULE_INSTANCE_NAME:
        currModuleInstanceName = pool.getUnique(token);
        state = ParserState.MODULE_TEMPLATE_NAME;
        break;
      case MODULE_TEMPLATE_NAME:
        currInstance.setModuleTemplate(design.getModule(token));
        state = ParserState.MODULE_TEMPLATE_INSTANCE_NAME;
        break;
      case MODULE_TEMPLATE_INSTANCE_NAME:
        currInstance.setModuleTemplateInstance(currInstance.getModuleTemplate().getInstance(token));
        ModuleInstance moduleInstance = design.addInstanceToModuleInstances(currInstance, currModuleInstanceName);
        if(currInstance.getModuleTemplateInstance().equals(currInstance.getModuleTemplate().getAnchor())){
          moduleInstance.setAnchor(currInstance);
        }
        state = ParserState.CFG_STRING;
        break;
      case NET_NAME:
        currNet.setName(pool.getUnique(token));
        if(currModule == null) design.addNet(currNet);
        else currModule.addNet(currNet);
        state = ParserState.NET_TYPE;
        break;
      case NET_TYPE:
        if(token.equals(COMMA) || token.equals(WIRE)){
          currNet.setType(NetType.WIRE);
        }
        else if(token.equals(CFG)){
          state = ParserState.ATTRIBUTE;
          break;
        }
        else if(token.equals(GND) || token.equals(GROUND)){
          currNet.setType(NetType.GND);
        }
        else if(token.equals(VCC) || token.equals(POWER)){
          currNet.setType(NetType.VCC);
        }
        else if(token.equals(INPIN)){
          currPin = new Pin();
          currPin.setIsOutputPin(false);
          currNet.addPin(currPin);
          state = ParserState.PIN_INSTANCE_NAME;
          break;
        }
        else if(token.equals(OUTPIN)){
          currPin = new Pin();
          currPin.setIsOutputPin(true);
          if(currNet.getSource() != null){
            MessageGenerator.briefErrorAndExit("XDL Design Parser Error in file: "+ fileName +", The net " +
              currNet.getName() + " has two or more outpins (line " +
              lineNumber + ")");
          }
          currNet.addPin(currPin);
          state = ParserState.PIN_INSTANCE_NAME;
          break;
        }
        else if(token.equals(INOUT)){
          currPin = new Pin();
          currPin.setPinType(PinType.INOUT);
          currNet.addPin(currPin);
          state = ParserState.PIN_INSTANCE_NAME;
          break;
        }
        else{
          expect("wire, vcc or power, gnd or ground or ,",token, ParserState.NET_TYPE);
        }
        state = ParserState.NET_STATEMENT;
        break;
      case NET_STATEMENT:
        if(token.equals(PIP)){
          currPIP = new PIP();
          currNet.addPIP(currPIP);
          state = ParserState.PIP_TILE;
        }
        else if(token.equals(INPIN)){
          currPin = new Pin();
          currPin.setIsOutputPin(false);
          currNet.addPin(currPin);
          state = ParserState.PIN_INSTANCE_NAME;
        }
        else if(token.equals(OUTPIN)){
          currPin = new Pin();
          currPin.setIsOutputPin(true);
          if(currNet.getSource() != null){
            MessageGenerator.briefErrorAndExit("XDL Design Parser Error in file: "+ fileName +", The net " +
              currNet.getName() + " has two or more outpins (line " +
              lineNumber + ")");
          }
          currNet.addPin(currPin);
          state = ParserState.PIN_INSTANCE_NAME;
        }
        else if(token.equals(INOUT)){
          currPin = new Pin();
          currPin.setPinType(PinType.INOUT);
          currNet.addPin(currPin);
          state = ParserState.PIN_INSTANCE_NAME;
          break;
        }
        else if(token.equals(SEMICOLON)){
          state = ParserState.XDL_STATEMENT;
        }
        else if(token.equals(CFG)){
          state = ParserState.ATTRIBUTE;
        }
        break;
      case PIN_INSTANCE_NAME:
        Instance inst;
        if(currModule == null) inst = design.getInstance(token);
        else inst = currModule.getInstance(token);
        if(inst == null){
          MessageGenerator.briefErrorAndExit("ERROR: Could not find instance " +
            token + " on line " + lineNumber);
        }
        currPin.setInstance(inst);
        inst.addToNetList(currNet);
        state = ParserState.PIN_NAME;
        break;
      case PIN_NAME:
        currPin.setPinName(pool.getUnique(token));
        currPin.getInstance().addPin(currPin);
        if(currModule != null){
            modPinMap.put(currPin.getInstanceName() + currPin.getName(), currPin);
        }
        state = ParserState.NET_STATEMENT;
        break;
      case PIP_TILE:
        Tile pipTile = dev.getTile(token);
        if(pipTile == null){
          MessageGenerator.briefErrorAndExit("Invalid tile " +
              token + " on line " + lineNumber);
        }
        currPIP.setTile(pipTile);
        state = ParserState.PIP_WIRE0;
        break;
      case PIP_WIRE0:
        int wire0 = we.getWireEnum(token);
        if(wire0 == -1) {
          MessageGenerator.briefErrorAndExit("ERROR: Invalid wire: " +
              token + " found on line " + lineNumber);
        }
        currPIP.setStartWire(wire0);
        state = ParserState.PIP_CONN_TYPE;
        break;
      case PIP_CONN_TYPE:
        if(token.equals(PIP0) || token.equals(PIP1) || token.equals(PIP2) || token.equals(PIP3)){
          state = ParserState.PIP_WIRE1;
        }
        else{
          expect("->, =-, ==, or =>", token, ParserState.PIP_CONN_TYPE);
        }
        break;
      case PIP_WIRE1:
        int wire1 = we.getWireEnum(token);
        if(wire1 == -1) {
          MessageGenerator.briefErrorAndExit("XDL Design Parser Error in file: "+ fileName +", Invalid wire: " +
              token + " found on line " + lineNumber);
        }
        currPIP.setEndWire(wire1);
        state = ParserState.NET_STATEMENT;
        break;
      case MODULE_NAME:
        currModule.setName(pool.getUnique(token));
        state = ParserState.MODULE_ANCHOR_NAME;
        break;
      case MODULE_ANCHOR_NAME:
        currModuleAnchorName = pool.getUnique(token);
        state = ParserState.CFG_STRING;
        break;
      case MODULE_STATEMENT:
        if(token.equals(PORT)){
          state = ParserState.PORT_NAME;
        }
        if(token.equals(INST)|| token.equals(INSTANCE)){
          currInstance = new Instance();
          state = ParserState.INSTANCE_NAME;
        }
        else if(token.equals(NET)){
          currNet = new Net();
          state = ParserState.NET_NAME;
        }
        else if(token.equals(ENDMODULE)){
          state = ParserState.END_MODULE_NAME;
        }
        break;
      case PORT_NAME:
        portNames.add(pool.getUnique(token));
        state = ParserState.PORT_INSTANCE_NAME;
        break;
      case PORT_INSTANCE_NAME:
        portInstanceNames.add(pool.getUnique(token));
        state = ParserState.PORT_PIN_NAME;
        break;
      case PORT_PIN_NAME:
        portPinNames.add(pool.getUnique(token));
        state = ParserState.END_PORT;
        break;
      case END_PORT:
        expect(SEMICOLON, token, ParserState.END_PORT);
        state = ParserState.MODULE_STATEMENT;
        break;
      case END_MODULE_NAME:
        if(!currModule.getName().equals(token)){
          MessageGenerator.briefErrorAndExit("XDL Design Parser Error in file: "+ fileName +", Mismatched module names: " +
            currModule.getName() + " and " + token + " at line: " + lineNumber);
        }
        state = ParserState.END_MODULE;
        break;
      case END_MODULE:
        expect(SEMICOLON, token, ParserState.END_MODULE);
        design.addModule(currModule);
        for(int i = 0; i <portNames.size(); i++){
          String key = portInstanceNames.get(i) + portPinNames.get(i);
          currModule.addPort(new Port(portNames.get(i), modPinMap.get(key)));
        }
        portNames = null;
        portInstanceNames = null;
        portPinNames = null;
        modPinMap = null;
        currModuleAnchorName = null;
        currModule = null;
        state = ParserState.XDL_STATEMENT;
        break;
    }
  }
 
  /**
   * This method will take a string and parse it into the 3-part attribute.  It
   * detects escaped colons ('\:') and includes them as part of the logicalName if
   * present.
   * @param attribute The original token string found from parsing the XDL file.
   * @return A new attribute object populated from the string attribute.
   */
  private Attribute createAttribute(String attribute){
      int break1 = attribute.indexOf(':');
      int break2 = attribute.indexOf(':', break1 + 1);
      while(attribute.charAt(break2-1) == '\\'){
        break2 = attribute.indexOf(':', break2 + 1);
      }
      String physicalName = pool.getUnique(attribute.substring(0, break1));
      String logicalName = pool.getUnique(attribute.substring(break1 + 1, break2));
      String value = pool.getUnique(attribute.substring(break2 + 1, attribute.length()));
    return new Attribute(physicalName, logicalName, value);
  }
}
TOP

Related Classes of edu.byu.ece.rapidSmith.design.parser.DesignParser

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.