diff --git a/src/main/java/edu/byu/ece/rapidSmith/design/subsite/CellDesign.java b/src/main/java/edu/byu/ece/rapidSmith/design/subsite/CellDesign.java index e8a02532..214688d1 100644 --- a/src/main/java/edu/byu/ece/rapidSmith/design/subsite/CellDesign.java +++ b/src/main/java/edu/byu/ece/rapidSmith/design/subsite/CellDesign.java @@ -806,6 +806,35 @@ public void addVivadoConstraint(XdcConstraint constraint) { } vivadoConstraints.add(constraint); } + + /** + * Creates a map from port cells to the sites the cells are constrained to be placed on according to the + * imported constraints.xdc. + * @return the map from port cells to their sites + */ + public Map getPortConstraintMap() { + Map portConstraintMap = new HashMap<>(); + if (vivadoConstraints == null) + return portConstraintMap; + + for (XdcConstraint constraint : vivadoConstraints) { + if (constraint.getPackagePinConstraint() == null) + continue; + + // Get the port cell + Cell portCell = this.getCell(constraint.getPackagePinConstraint().getPortName()); + assert(portCell.isPort()); + + // Get the package pin's site + Site site = device.getSite(constraint.getPackagePinConstraint().getPinName()); + assert(site != null); + + // Add to the port map + portConstraintMap.put(portCell, site); + } + + return portConstraintMap; + } /** * Creates and returns a deep copy of the current CellDesign. diff --git a/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/VivadoCheckpoint.java b/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/VivadoCheckpoint.java index 9bc56509..0d65d7cf 100644 --- a/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/VivadoCheckpoint.java +++ b/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/VivadoCheckpoint.java @@ -24,10 +24,7 @@ import java.util.Map; import java.util.Set; -import edu.byu.ece.rapidSmith.design.subsite.BelRoutethrough; -import edu.byu.ece.rapidSmith.design.subsite.CellDesign; -import edu.byu.ece.rapidSmith.design.subsite.CellLibrary; -import edu.byu.ece.rapidSmith.design.subsite.CellPin; +import edu.byu.ece.rapidSmith.design.subsite.*; import edu.byu.ece.rapidSmith.device.Bel; import edu.byu.ece.rapidSmith.device.BelPin; import edu.byu.ece.rapidSmith.device.Device; diff --git a/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/VivadoInterface.java b/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/VivadoInterface.java index c2eb48ff..b29543c6 100644 --- a/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/VivadoInterface.java +++ b/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/VivadoInterface.java @@ -96,8 +96,10 @@ public static VivadoCheckpoint loadRSCP (String rscp, boolean storeAdditionalInf design.setImplementationMode(mode); // parse the constraints into RapidSmith - parseConstraintsXDC(design, rscpPath.resolve("constraints.xdc").toString()); - + String constraintsFile = rscpPath.resolve("constraints.xdc").toString(); + XdcConstraintsInterface constraintsInterface = new XdcConstraintsInterface(design, device); + constraintsInterface.parseConstraintsXDC(constraintsFile); + // re-create the placement and routing information String placementFile = rscpPath.resolve("placement.rsc").toString(); XdcPlacementInterface placementInterface = new XdcPlacementInterface(design, device); @@ -117,42 +119,7 @@ public static VivadoCheckpoint loadRSCP (String rscp, boolean storeAdditionalInf return vivadoCheckpoint; } - - /** - * Loads Vivado constraints into the specified {@link CellDesign}. For now, these constraints are - * loaded as two strings, a command and a list of arguments. There is no attempt right now to - * intelligently handle these constraints, and they are included so the user has access to them. - * TODO: Update how we handle constraints files to make them easier to move - * - * @param design {@link CellDesign} - * @param constraintPath File location of the constraints file. Typically rscpDirectory/constraints.rsc is the constraints file. - */ - private static void parseConstraintsXDC(CellDesign design, String constraintPath) { - - try (BufferedReader br = new BufferedReader(new FileReader(constraintPath))) { - - String line = null; - // add the design constraints to the design - while ((line = br.readLine()) != null) { - - String trimmed = line.trim(); - - // Skip commented lines - if (trimmed.startsWith("#") || trimmed.length() < 1) - continue; - - // assuming a space after the command TODO: make sure this assumption is correct - int index = trimmed.indexOf(" "); - String command = trimmed.substring(0, index); - String options = trimmed.substring(index + 1); - design.addVivadoConstraint(new XdcConstraint(command, options)); - } - - } catch (IOException e) { - throw new Exceptions.ParseException(e); - } - } - + /** * Export the RapidSmith2 design into an existing TINCR checkpoint file. * @@ -185,36 +152,12 @@ public static void writeTCP(String tcpDirectory, CellDesign design, Device devic EdifInterface.writeEdif(edifOut, design); // write constraints.xdc - writeConstraintsXdc(design, Paths.get(tcpDirectory, "constraints.xdc").toString()); - + String constraintsOut = Paths.get(tcpDirectory, "constraints.xdc").toString(); + XdcConstraintsInterface constraintsInterface = new XdcConstraintsInterface(design, device); + constraintsInterface.writeConstraintsXdc(constraintsOut); + // write design.info String partInfoOut = Paths.get(tcpDirectory, "design.info").toString(); DesignInfoInterface.writeInfoFile(partInfoOut, design.getPartName()); } - - /** - * Reads the Vivado constraints from the specified {@link CellDesign} and creates a - * constraints.xdc file representing the constraints. The file is written to the newly - * created TINCR checkpoint. - * - * @param design {@link CellDesign} - * @param xdcOut Constraints.xdc file path - * @throws IOException - */ - private static void writeConstraintsXdc(CellDesign design, String xdcOut) throws IOException { - - try (BufferedWriter fileout = new BufferedWriter (new FileWriter(xdcOut))) { - - LocalDateTime time = LocalDateTime.now(); - - fileout.write(String.format("##############################################################\n" - + "# Generated by RapidSmith v.2.0 on %02d/%02d/%02d at %02d:%02d:%02d\n" - + "##############################################################\n\n", - time.getMonthValue(), time.getDayOfMonth(), time.getYear(), time.getHour(), time.getMinute(), time.getSecond())); - - for (XdcConstraint constraint : design.getVivadoConstraints()) { - fileout.write(constraint + "\n"); - } - } - } } // END CLASS diff --git a/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/XdcConstraint.java b/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/XdcConstraint.java index 8cd8647e..bed83922 100644 --- a/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/XdcConstraint.java +++ b/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/XdcConstraint.java @@ -20,6 +20,9 @@ package edu.byu.ece.rapidSmith.interfaces.vivado; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * This class holds design constraints found in the constraints.xdc file. * TODO: Make these constraints easier to work with @@ -30,10 +33,21 @@ public final class XdcConstraint { private final String command; private final String options; - - public XdcConstraint(String command, String options){ + private final String comment; + private XdcConstraintPackagePin constraintPackagePin; + private static final Pattern patternPackagePin = Pattern.compile("\\s*set_property\\s+.*PACKAGE_PIN\\s+(\\w+)\\s+.*\\[\\s*get_ports*\\s+\\{?\\s*([^{}\\s]+)\\s*}?\\s*].*$"); + + public XdcConstraint(String command, String options, String comment){ this.command = command; this.options = options; + this.comment = comment; + + // Set the package pin if this constraint includes one. + String constraint = command + " " + options; + Matcher matcher = patternPackagePin.matcher(constraint); + if (matcher.find()) { + constraintPackagePin = new XdcConstraintPackagePin(matcher.group(1), matcher.group(2)); + } } /** @@ -49,12 +63,49 @@ public String getCommandName() { public String getOptions() { return options; } + + /** + * @return the comment of the XDC constraint. null if there is no comment. + */ + public String getComment() { return comment; } /** * Formats the XDC constraint and returns it as a string. */ @Override public String toString(){ - return command + " " + options; + return (comment != null) ? command + " " + options + " " + comment : command + " " + options; + } + + /** + * @return The XDC pin package constraint instance + */ + public XdcConstraintPackagePin getPackagePinConstraint() { + return constraintPackagePin; + } + + public class XdcConstraintPackagePin { + + private String pinName; + private String portName; + + XdcConstraintPackagePin(String pinName, String portName) { + this.pinName = pinName; + this.portName = portName; + } + + /** + * @return The name of the pin that the net is constrained to (eg. D7) + */ + public String getPinName() { + return pinName; + } + + /** + * @return The name of the port that is constrained to a pin. + */ + public String getPortName() { + return portName; + } } } diff --git a/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/XdcConstraintsInterface.java b/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/XdcConstraintsInterface.java new file mode 100644 index 00000000..4484edd8 --- /dev/null +++ b/src/main/java/edu/byu/ece/rapidSmith/interfaces/vivado/XdcConstraintsInterface.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018 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 . + */ + +package edu.byu.ece.rapidSmith.interfaces.vivado; + +import edu.byu.ece.rapidSmith.design.subsite.*; +import edu.byu.ece.rapidSmith.device.*; + +import java.io.*; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +/** + * This class is used for parsing XDC constraint files and adding them into a RS2 design. + * + * @author Dallon Glick, Dr. Jeffrey Goeders, Thomas Townsend + * + */ +public class XdcConstraintsInterface { + private final CellDesign design; + private final Device device; + + public XdcConstraintsInterface(CellDesign design, Device device) { + this.design = design; + this.device = device; + } + + /** + * Parses a single line from constraints.xdc, makes an XdcConstraint, and adds it to the design. + * @param line the constraint line to parse + */ + private void parseConstraintsLine(String line) { + int optIdx = line.indexOf(" "); + int cmntIdx = line.indexOf("#"); + String command = line.substring(0, optIdx); + String options = (cmntIdx != -1) ? line.substring(optIdx + 1, cmntIdx).trim() : line.substring(optIdx + 1).trim(); + String comment = (cmntIdx != -1) ? line.substring(cmntIdx) : null; + design.addVivadoConstraint(new XdcConstraint(command, options, comment)); + } + + /** + * Loads Vivado constraints into the specified {@link CellDesign}. For now, these constraints are + * loaded as two strings, a command and a list of arguments. For package pin constraints, the pin and corresponding + * port is saved. Otherwise, there is no attempt right now to intelligently handle these constraints, and they are + * included so the user has access to them. + * TODO: Update how we handle constraints files to make them easier to move + * @param xdcFile constraints.xdc file + * @throws IOException + */ + public void parseConstraintsXDC(String xdcFile) throws IOException { + LineNumberReader br = new LineNumberReader(new BufferedReader(new FileReader(xdcFile))); + String line; + + while ((line = br.readLine()) != null) { + String trimmed = line.trim(); + + // Skip empty and comment lines + if (trimmed.length() < 1 || trimmed.startsWith("#")) + continue; + + parseConstraintsLine(trimmed); + } + + br.close(); + } + + /** + * Reads the Vivado constraints from the {@link CellDesign} and creates a + * constraints.xdc file representing the constraints. The file is written to the newly + * created TINCR checkpoint. + * + * @param xdcOut Constraints.xdc file path + * @throws IOException + */ + public void writeConstraintsXdc(String xdcOut) throws IOException { + try (BufferedWriter fileout = new BufferedWriter (new FileWriter(xdcOut))) { + LocalDateTime time = LocalDateTime.now(); + + fileout.write(String.format("##############################################################\n" + + "# Generated by RapidSmith v.2.0 on %02d/%02d/%02d at %02d:%02d:%02d\n" + + "##############################################################\n\n", + time.getMonthValue(), time.getDayOfMonth(), time.getYear(), time.getHour(), time.getMinute(), time.getSecond())); + + if (design.getVivadoConstraints() != null) { + for (XdcConstraint constraint : design.getVivadoConstraints()) { + fileout.write(constraint + "\n"); + } + } + } + } +}