Java tutorial
/* * Copyright (c) 2016 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 3 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/LICENSE.GPL3.TXT. You may * also get a copy of the license at <http://www.gnu.org/licenses/>. */ package edu.byu.ece.rapidSmith.interfaces.ise; import edu.byu.ece.rapidSmith.RSEnvironment; import edu.byu.ece.rapidSmith.design.*; import edu.byu.ece.rapidSmith.design.xdl.*; import edu.byu.ece.rapidSmith.device.*; import edu.byu.ece.rapidSmith.util.Exceptions.ParseException; import org.antlr.v4.runtime.ANTLRFileStream; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTreeWalker; import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; /** * */ public final class XDLReader { public XdlDesign readDesign(Path xdlFile) throws IOException { XDLLexer lexer = new XDLLexer(new ANTLRFileStream(xdlFile.toString())); XDLParser parser = new XDLParser(new CommonTokenStream(lexer)); XDLParser.DesignContext design = parser.design(); ParseTreeWalker walker = new ParseTreeWalker(); DesignListener listener = new DesignListener(); walker.walk(listener, design); return listener.design; } private static class DesignListener extends XDLParserBaseListener { XdlDesign design; private CfgState cfgState; private Device device; private XdlNet currNet = null; private XdlInstance currInstance = null; private XdlModule currModule = null; private String currModuleAnchorName = null; private HashMap<String, XdlPin> modulePinMap = null; private ArrayList<String> portNames = null; private ArrayList<String> portInstanceNames = null; private ArrayList<String> portPinNames = null; @Override public void enterDesign(XDLParser.DesignContext ctx) { String name = stripQuotes(ctx.name.getText()); String partName = ctx.part.getText(); device = RSEnvironment.defaultEnv().getDevice(partName); if (device == null) throw new ParseException("unsupported device: " + partName); design = new XdlDesign(name, partName); cfgState = CfgState.DESIGN; } @Override public void exitDesign(XDLParser.DesignContext ctx) { cfgState = null; } @Override public void enterStd_design(XDLParser.Std_designContext ctx) { design.setNCDVersion(ctx.version.getText().intern()); // TODO replace with version } @Override public void enterInst(XDLParser.InstContext ctx) { String name = stripQuotes(ctx.name.getText()).intern(); String typeName = stripQuotes(ctx.type.getText()); SiteType type = SiteType.valueOf(device.getFamily(), typeName); currInstance = new XdlInstance(name, type); currInstance.setDesign(design); if (currModule == null) { design.addInstance(currInstance); } else { currModule.addInstance(currInstance); currInstance.setModuleTemplate(currModule); if (currInstance.getName().equals(currModuleAnchorName)) currModule.setAnchor(currInstance); } cfgState = CfgState.INSTANCE; } @Override public void exitInst(XDLParser.InstContext ctx) { currInstance = null; cfgState = CfgState.DESIGN; } @Override public void enterPlacement(XDLParser.PlacementContext ctx) { if (ctx.UNPLACED() != null) { if (ctx.bonded == null) { currInstance.setBonded(null); // TODO change bonded to internal } else if (ctx.bonded.getType() == XDLParser.BONDED) { currInstance.setBonded(true); } else { assert ctx.bonded.getType() == XDLParser.UNBONDED; currInstance.setBonded(false); } } else { assert ctx.PLACED() != null; String siteName = ctx.site.getText(); Site site = device.getSite(siteName); if (site == null) throw new ParseException("no such site on device: " + siteName); // TODO add check against tile site.setType(currInstance.getType()); if (currModule == null) { currInstance.place(site); switch (site.getBondedType()) { case BONDED: currInstance.setBonded(true); break; case UNBONDED: currInstance.setBonded(false); break; case INTERNAL: currInstance.setBonded(null); break; default: throw new AssertionError("illegal enum value"); } } else { currInstance.setSiteUnsafe(site); } } } @Override public void enterModule_info(XDLParser.Module_infoContext ctx) { String miName = stripQuotes(ctx.mi.getText()).intern(); String moduleName = stripQuotes(ctx.module_name.getText()); XdlModule module = design.getModule(moduleName); if (module == null) throw new ParseException("unknown module: " + moduleName); currInstance.setModuleTemplate(module); String templateName = stripQuotes(ctx.instance.getText()); XdlInstance templateInstance = module.getInstance(templateName); currInstance.setModuleTemplateInstance(templateInstance); XdlModuleInstance mi = design.addInstanceToModuleInstances(currInstance, miName); if (templateInstance.equals(module.getAnchor())) { mi.setAnchor(currInstance); } } @Override public void enterNet(XDLParser.NetContext ctx) { String name = stripQuotes(ctx.name.getText()).intern(); NetType type; if (ctx.type != null) { switch (ctx.type.getType()) { case XDLParser.VCC: type = NetType.VCC; break; case XDLParser.GND: type = NetType.GND; break; case XDLParser.WIRE: type = NetType.WIRE; break; default: throw new ParseException("illegal net type"); } } else { type = NetType.WIRE; } currNet = new XdlNet(name, type); if (currModule == null) design.addNet(currNet); else currModule.addNet(currNet); } @Override public void exitNet(XDLParser.NetContext ctx) { currNet = null; cfgState = CfgState.DESIGN; } @Override public void enterPin(XDLParser.PinContext ctx) { XdlPin pin; String instName = stripQuotes(ctx.instance.getText()); XdlInstance inst; inst = getPinInstance(instName); String name = ctx.name.getText().intern(); switch (ctx.direction.getType()) { // Note: old code had an inout option, no special handling though case XDLParser.INPIN: pin = new XdlPin(false, name, inst); break; case XDLParser.OUTPIN: if (currNet.getSource() != null) { throw new ParseException("net " + currNet.getName() + " has two or more output pins"); } pin = new XdlPin(true, name, inst); break; default: throw new ParseException("illegal pin direction"); } // save the pin name for later connecting it to a port if (currModule != null) modulePinMap.put(inst.getName() + name, pin); currNet.addPin(pin); inst.addToNetList(currNet); } private XdlInstance getPinInstance(String instName) { XdlInstance inst; if (currModule == null) { inst = design.getInstance(instName); } else { inst = currModule.getInstance(instName); } if (inst == null) throw new ParseException("unrecognized instance: " + instName); return inst; } @Override public void enterPip(XDLParser.PipContext ctx) { String tileName = ctx.tile.getText(); Tile tile = device.getTile(tileName); if (tile == null) throw new ParseException("unrecognized tile: " + tileName); WireEnumerator we = device.getWireEnumerator(); Wire sourceWire = getWireSafe(we, tile, ctx.source.getText()); Wire sinkWire = getWireSafe(we, tile, ctx.source.getText()); PIP pip = new PIP(sourceWire, sinkWire); currNet.addPIP(pip); } private Wire getWireSafe(WireEnumerator we, Tile tile, String wireName) { Integer wireEnum = we.getWireEnum(wireName); if (wireEnum == null) throw new ParseException("unrecognized wire: " + wireName); return new TileWire(tile, wireEnum); } @Override public void enterAttribute(XDLParser.AttributeContext ctx) { XdlAttribute attr = makeAttribute(ctx); switch (cfgState) { case DESIGN: design.addAttribute(attr); break; case INSTANCE: currInstance.addAttribute(attr); break; case NET: currNet.addAttribute(attr); if (attr.getPhysicalName().equals("_MACRO")) { setNetModuleInstance(attr); } break; case MODULE: currModule.addAttribute(attr); } } private static XdlAttribute makeAttribute(XDLParser.AttributeContext ctx) { String physicalName = ctx.physical.getText().intern(); String logicalName = ctx.logical.getText().intern(); String value = ctx.attribute_value().getText().intern(); return new XdlAttribute(physicalName, logicalName, value); } private void setNetModuleInstance(XdlAttribute attr) { XdlModuleInstance mi = design.getModuleInstance(attr.getValue()); currNet.setModuleInstance(mi); mi.addNet(currNet); XdlModule module = mi.getModule(); currNet.setModuleTemplate(module); String moduleNetName = currNet.getName().replaceFirst(mi.getName() + "/", ""); currNet.setModuleTemplateNet(module.getNet(moduleNetName)); } @Override public void enterModule(XDLParser.ModuleContext ctx) { currModule = new XdlModule(); modulePinMap = new HashMap<>(); portNames = new ArrayList<>(); portInstanceNames = new ArrayList<>(); portPinNames = new ArrayList<>(); cfgState = CfgState.MODULE; currModule.setName(stripQuotes(ctx.name.getText()).intern()); currModuleAnchorName = stripQuotes(ctx.anchor.getText()); } @Override public void exitModule(XDLParser.ModuleContext ctx) { int numPorts = portNames.size(); for (int i = 0; i < numPorts; i++) { String key = portInstanceNames.get(i) + portPinNames.get(i); XdlPort port = new XdlPort(portNames.get(i), modulePinMap.get(key)); currModule.addPort(port); } currModule = null; modulePinMap = null; portNames = null; portInstanceNames = null; portPinNames = null; cfgState = CfgState.DESIGN; } @Override public void enterPort(XDLParser.PortContext ctx) { portNames.add(stripQuotes(ctx.name.getText()).intern()); portInstanceNames.add(stripQuotes(ctx.inst_name.getText()).intern()); portPinNames.add(stripQuotes(ctx.inst_pin.getText()).intern()); } private static String stripQuotes(String str) { if (str.charAt(0) == '"' && str.charAt(str.length() - 1) == '"') return str.substring(1, str.length() - 1); return str; } private enum CfgState { DESIGN, INSTANCE, NET, MODULE } } }