From 701839915b93cc188bd8f13c0e3bad9343bd9bae Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Fri, 7 Jun 2024 13:02:02 -0600 Subject: [PATCH 01/18] DREAMPlaceFPGA API interface class Signed-off-by: Chris Lavin --- .../placer/dreamplacefpga/DREAMPlaceFPGA.java | 236 ++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java new file mode 100644 index 000000000..d923245b9 --- /dev/null +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2024, Advanced Micro Devices, Inc. + * All rights reserved. + * + * Author: Chris Lavin, AMD Research and Advanced Development. + * + * This file is part of RapidWright. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.xilinx.rapidwright.placer.dreamplacefpga; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import com.xilinx.rapidwright.design.Design; +import com.xilinx.rapidwright.interchange.DeviceResourcesExample; +import com.xilinx.rapidwright.interchange.DeviceResourcesWriter; +import com.xilinx.rapidwright.interchange.Interchange; +import com.xilinx.rapidwright.interchange.PhysNetlistReader; +import com.xilinx.rapidwright.tests.CodePerfTracker; +import com.xilinx.rapidwright.util.FileTools; + +/** + * Utility wrapper class to facilitate using DREAMPlaceFPGA as an external + * placer. + */ +public class DREAMPlaceFPGA { + + public static final String INTERCHANGE_NETLIST = "interchange_netlist"; + public static final String INTERCHANGE_DEVICE = "interchange_device"; + public static final String IO_PL = "io_pl"; + public static final String GPU = "gpu"; + public static final String NUM_BINS_X = "num_bins_x"; + public static final String NUM_BINS_Y = "num_bins_y"; + public static final String GLOBAL_PLACE_STAGES = "global_place_stages"; + public static final String TARGET_DENSITY = "target_density"; + public static final String DENSITY_WEIGHT = "density_weight"; + public static final String RANDOM_SEED = "random_seed"; + public static final String SCALE_FACTOR = "scale_factor"; + public static final String GLOBAL_PLACE_FLAG = "global_place_flag"; + public static final String PLACE_SOL = "place_sol"; + public static final String ROUTABILITY_OPT_FLAG = "routability_opt_flag"; + public static final String LEGALIZE_FLAG = "legalize_flag"; + public static final String DETAILED_PLACE_FLAG = "detailed_place_flag"; + public static final String DTYPE = "dtype"; + public static final String PLOT_FLAG = "plot_flag"; + public static final String NUM_THREADS = "num_threads"; + public static final String DETERMINISTIC_FLAG = "deterministic_flag"; + public static final String ENABLE_IF = "enable_if"; + public static final String ENABLE_SITE_ROUTING = "enable_site_routing"; + + public static final boolean GPU_DEFAULT = false; + public static final int NUM_BINS_X_DEFAULT = 512; + public static final int NUM_BINS_Y_DEFAULT = 512; + public static final String GLOBAL_PLACE_STAGES_DEFAULT = + "[\n{\"num_bins_x\" : 512," + + " \"num_bins_y\" : 512," + + " \"iteration\" : 2000," + + " \"learning_rate\" : 0.01," + + " \"wirelength\" : \"weighted_average\"," + + " \"optimizer\" : \"nesterov\"}\n]"; + public static final double TARGET_DENSITY_DEFAULT = 1.0; + public static final double DENSITY_WEIGHT_DEFAULT = 8e-5; + public static final int RANDOM_SEED_DEFAULT = 1000; + public static final double SCALE_FACTOR_DEFAULT = 1.0; + public static final boolean GLOBAL_PLACE_FLAG_DEFAULT = true; + public static final boolean ROUTABILITY_OPT_FLAG_DEFAULT = true; + public static final boolean LEGALIZE_FLAG_DEFAULT = true; + public static final boolean DETAILED_PLACE_FLAG_DEFAULT = false; + public static final String DTYPE_DEFAULT = "float32"; + public static final boolean PLOT_FLAG_DEFAULT = false; + public static final int NUM_THREADS_DEFAULT = 1; + public static final boolean DETERMINISTIC_FLAG_DEFAULT = true; + public static final boolean ENABLE_IF_DEFAULT = true; + public static final boolean ENABLE_SITE_ROUTING_DEFAULT = true; + + public static final String dreamPlaceFPGAExec = "python dreamplacefpga/Placer.py"; + + public static Map getSettingsMap() { + Map map = new HashMap<>(); + + map.put(GPU, GPU_DEFAULT); + map.put(NUM_BINS_X, NUM_BINS_X_DEFAULT); + map.put(NUM_BINS_Y, NUM_BINS_Y_DEFAULT); + map.put(GLOBAL_PLACE_STAGES, GLOBAL_PLACE_STAGES_DEFAULT); + map.put(TARGET_DENSITY, TARGET_DENSITY_DEFAULT); + map.put(DENSITY_WEIGHT, DENSITY_WEIGHT_DEFAULT); + map.put(RANDOM_SEED, RANDOM_SEED_DEFAULT); + map.put(SCALE_FACTOR, SCALE_FACTOR_DEFAULT); + map.put(GLOBAL_PLACE_FLAG, GLOBAL_PLACE_FLAG_DEFAULT); + map.put(ROUTABILITY_OPT_FLAG, ROUTABILITY_OPT_FLAG_DEFAULT); + map.put(LEGALIZE_FLAG, LEGALIZE_FLAG_DEFAULT); + map.put(DETAILED_PLACE_FLAG, DETAILED_PLACE_FLAG_DEFAULT); + map.put(DTYPE, DTYPE_DEFAULT); + map.put(PLOT_FLAG, PLOT_FLAG_DEFAULT); + map.put(NUM_THREADS, NUM_THREADS_DEFAULT); + map.put(DETERMINISTIC_FLAG, DETERMINISTIC_FLAG_DEFAULT); + map.put(ENABLE_IF, ENABLE_IF_DEFAULT); + map.put(ENABLE_SITE_ROUTING, ENABLE_SITE_ROUTING_DEFAULT); + + return map; + } + +// { +// "interchange_netlist" : "/group/zircon2/zhixiong/ispd2016/FPGA01/design.netlist", +// "interchange_device" : "/group/zircon2/zhixiong/RapidWright/device_interchange_files/xcvu095-ffva2104-2-e.device", +// "io_pl": "/group/zircon2/zhixiong/ispd2016/FPGA01/design.pl", +// "gpu" : 0, +// "num_bins_x" : 512, +// "num_bins_y" : 512, +// "global_place_stages" : [ +// {"num_bins_x" : 512, "num_bins_y" : 512, "iteration" : 2000, "learning_rate" : 0.01, "wirelength" : "weighted_average", "optimizer" : "nesterov"} +// ], +// "target_density" : 1.0, +// "density_weight" : 8e-5, +// "random_seed" : 1000, +// "scale_factor" : 1.0, +// "global_place_flag" : 1, +// "place_sol" : "/group/zircon2/zhixiong/DREAMPlaceFPGA/results_interchange/FPGA01.final.pl", +// "routability_opt_flag": 1, +// "legalize_flag" : 1, +// "detailed_place_flag" : 0, +// "dtype" : "float32", +// "plot_flag" : 0, +// "num_threads" : 1, +// "deterministic_flag" : 1, +// "enable_if" : 1, +// "enable_site_routing" : 1 +// } + + public static void writeJSONForDREAMPlaceFPGA(Path jsonPath, Map attributes) { + try (BufferedWriter bw = new BufferedWriter(new FileWriter(jsonPath.toFile()))) { + bw.write("{\n"); + boolean first = true; + for (Entry e : attributes.entrySet()) { + if (first) { + first = false; + } else { + bw.write(",\n"); + } + bw.write(" \"" + e.getKey() + "\""); + bw.write(" : "); + if (e.getValue() instanceof String && !e.getKey().equals(GLOBAL_PLACE_STAGES)) { + bw.write("\"" + e.getValue().toString() + "\""); + } else if (e.getValue() instanceof Boolean) { + bw.write((boolean) e.getValue() ? "1" : "0"); + } else { + bw.write(e.getValue().toString() + ""); + } + + } + bw.write("\n}\n"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + } + + public static Design placeDesign(Design design, Path workDir) { + // Create interchange netlist file + String interchangeRootFile = workDir.toString() + File.separator + "design"; + Interchange.writeDesignToInterchange(design, interchangeRootFile); + + // Create device file if it doesn't already exist + String deviceName = design.getDevice().getName(); + Path deviceFile = workDir.resolve(deviceName + ".device"); + if (!Files.exists(deviceFile)) { + try { + DeviceResourcesWriter.writeDeviceResourcesFile(design.getPartName(), design.getDevice(), + new CodePerfTracker("Create IF Device"), deviceFile.toString(), true); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + // Create JSON file for DREAMPlaceFPGA + Path jsonFile = workDir.resolve("design.json"); + Map settings = getSettingsMap(); + settings.put(INTERCHANGE_DEVICE, deviceFile.toString()); + settings.put(INTERCHANGE_NETLIST, interchangeRootFile + Interchange.LOG_NETLIST_EXT); + settings.put(PLACE_SOL, ""); + settings.put(IO_PL, ""); + writeJSONForDREAMPlaceFPGA(jsonFile, settings); + + // Run DREAMPlaceFPGA + String exec = dreamPlaceFPGAExec + " " + jsonFile.toString(); + boolean verbose = true; + String[] environ = null; + Integer exitCode = FileTools.runCommand(exec, verbose, environ, workDir.toFile()); + if (exitCode != 0) { + throw new RuntimeException("DREAMPlaceFPGA with code: " + exitCode); + } + + // Load placed result + Design placedDesign = null; + try { + placedDesign = PhysNetlistReader.readPhysNetlist(interchangeRootFile + Interchange.PHYS_NETLIST_EXT, + design.getNetlist()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + return placedDesign; + } + + public static void main(String[] args) { + if (args.length != 2 && args.length != 3) { + System.out.println("USAGE: [work_directory]"); + return; + } + Design input = Design.readCheckpoint(args[0]); + Path workDir = args.length == 3 ? Paths.get(args[2]) : Paths.get(System.getProperty("user.dir")); + Design placed = placeDesign(input, workDir); + placed.writeCheckpoint(args[1]); + } +} From 2b0698a3a5a632c93a6f979b30496842e4186b95 Mon Sep 17 00:00:00 2001 From: Chris Lavin Date: Fri, 7 Jun 2024 13:03:38 -0600 Subject: [PATCH 02/18] Removing comments Signed-off-by: Chris Lavin --- .../placer/dreamplacefpga/DREAMPlaceFPGA.java | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java index d923245b9..dcc5ac198 100644 --- a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -34,7 +34,6 @@ import java.util.Map.Entry; import com.xilinx.rapidwright.design.Design; -import com.xilinx.rapidwright.interchange.DeviceResourcesExample; import com.xilinx.rapidwright.interchange.DeviceResourcesWriter; import com.xilinx.rapidwright.interchange.Interchange; import com.xilinx.rapidwright.interchange.PhysNetlistReader; @@ -122,33 +121,6 @@ public static Map getSettingsMap() { return map; } -// { -// "interchange_netlist" : "/group/zircon2/zhixiong/ispd2016/FPGA01/design.netlist", -// "interchange_device" : "/group/zircon2/zhixiong/RapidWright/device_interchange_files/xcvu095-ffva2104-2-e.device", -// "io_pl": "/group/zircon2/zhixiong/ispd2016/FPGA01/design.pl", -// "gpu" : 0, -// "num_bins_x" : 512, -// "num_bins_y" : 512, -// "global_place_stages" : [ -// {"num_bins_x" : 512, "num_bins_y" : 512, "iteration" : 2000, "learning_rate" : 0.01, "wirelength" : "weighted_average", "optimizer" : "nesterov"} -// ], -// "target_density" : 1.0, -// "density_weight" : 8e-5, -// "random_seed" : 1000, -// "scale_factor" : 1.0, -// "global_place_flag" : 1, -// "place_sol" : "/group/zircon2/zhixiong/DREAMPlaceFPGA/results_interchange/FPGA01.final.pl", -// "routability_opt_flag": 1, -// "legalize_flag" : 1, -// "detailed_place_flag" : 0, -// "dtype" : "float32", -// "plot_flag" : 0, -// "num_threads" : 1, -// "deterministic_flag" : 1, -// "enable_if" : 1, -// "enable_site_routing" : 1 -// } - public static void writeJSONForDREAMPlaceFPGA(Path jsonPath, Map attributes) { try (BufferedWriter bw = new BufferedWriter(new FileWriter(jsonPath.toFile()))) { bw.write("{\n"); From ca0a4898d73147dde7fe118305be246afb356e4c Mon Sep 17 00:00:00 2001 From: Zhili Xiong Date: Tue, 11 Jun 2024 13:14:19 -0500 Subject: [PATCH 03/18] fix json default value, add out_of_context flag (#999) * disable routability_opt Signed-off-by: Zhili Xiong * fix result path and out_of_context flag Signed-off-by: Zhili Xiong --------- Signed-off-by: Zhili Xiong Co-authored-by: Zhili Xiong --- .../interchange/PhysicalNetlistToDcp.java | 2 +- .../placer/dreamplacefpga/DREAMPlaceFPGA.java | 32 ++++++++++++++----- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/com/xilinx/rapidwright/interchange/PhysicalNetlistToDcp.java b/src/com/xilinx/rapidwright/interchange/PhysicalNetlistToDcp.java index dd4851b94..e327cacb3 100644 --- a/src/com/xilinx/rapidwright/interchange/PhysicalNetlistToDcp.java +++ b/src/com/xilinx/rapidwright/interchange/PhysicalNetlistToDcp.java @@ -36,7 +36,7 @@ public class PhysicalNetlistToDcp { - private static final String MAKE_DCP_OUT_OF_CONTEXT = "--out_of_context"; + public static final String MAKE_DCP_OUT_OF_CONTEXT = "--out_of_context"; public static void main(String[] args) throws IOException { if (args.length != 4 && args.length != 5) { diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java index dcc5ac198..e3f192eb5 100644 --- a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -37,6 +37,7 @@ import com.xilinx.rapidwright.interchange.DeviceResourcesWriter; import com.xilinx.rapidwright.interchange.Interchange; import com.xilinx.rapidwright.interchange.PhysNetlistReader; +import com.xilinx.rapidwright.interchange.PhysicalNetlistToDcp; import com.xilinx.rapidwright.tests.CodePerfTracker; import com.xilinx.rapidwright.util.FileTools; @@ -84,12 +85,12 @@ public class DREAMPlaceFPGA { public static final int RANDOM_SEED_DEFAULT = 1000; public static final double SCALE_FACTOR_DEFAULT = 1.0; public static final boolean GLOBAL_PLACE_FLAG_DEFAULT = true; - public static final boolean ROUTABILITY_OPT_FLAG_DEFAULT = true; + public static final boolean ROUTABILITY_OPT_FLAG_DEFAULT = false; public static final boolean LEGALIZE_FLAG_DEFAULT = true; public static final boolean DETAILED_PLACE_FLAG_DEFAULT = false; public static final String DTYPE_DEFAULT = "float32"; public static final boolean PLOT_FLAG_DEFAULT = false; - public static final int NUM_THREADS_DEFAULT = 1; + public static final int NUM_THREADS_DEFAULT = 8; public static final boolean DETERMINISTIC_FLAG_DEFAULT = true; public static final boolean ENABLE_IF_DEFAULT = true; public static final boolean ENABLE_SITE_ROUTING_DEFAULT = true; @@ -149,7 +150,7 @@ public static void writeJSONForDREAMPlaceFPGA(Path jsonPath, Map } - public static Design placeDesign(Design design, Path workDir) { + public static Design placeDesign(Design design, Path workDir, boolean makeOutOfContext) { // Create interchange netlist file String interchangeRootFile = workDir.toString() + File.separator + "design"; Interchange.writeDesignToInterchange(design, interchangeRootFile); @@ -186,9 +187,14 @@ public static Design placeDesign(Design design, Path workDir) { // Load placed result Design placedDesign = null; + String interchangeResultFile = workDir.toString() + File.separator + "results/design/design"; try { - placedDesign = PhysNetlistReader.readPhysNetlist(interchangeRootFile + Interchange.PHYS_NETLIST_EXT, + placedDesign = PhysNetlistReader.readPhysNetlist(interchangeResultFile + Interchange.PHYS_NETLIST_EXT, design.getNetlist()); + if (makeOutOfContext) { + placedDesign.setAutoIOBuffers(false); + placedDesign.setDesignOutOfContext(true); + } } catch (IOException e) { throw new UncheckedIOException(e); } @@ -196,13 +202,23 @@ public static Design placeDesign(Design design, Path workDir) { } public static void main(String[] args) { - if (args.length != 2 && args.length != 3) { - System.out.println("USAGE: [work_directory]"); + // Usage: [--out_of_context] [work directory] + if (args.length < 2 || args.length > 4) { + System.out.println("USAGE: [" + + PhysicalNetlistToDcp.MAKE_DCP_OUT_OF_CONTEXT + "] [work directory]"); return; } Design input = Design.readCheckpoint(args[0]); - Path workDir = args.length == 3 ? Paths.get(args[2]) : Paths.get(System.getProperty("user.dir")); - Design placed = placeDesign(input, workDir); + + boolean makeOutOfContext = false; + if (args.length >= 3) { + if (args[2].equals(PhysicalNetlistToDcp.MAKE_DCP_OUT_OF_CONTEXT)) { + makeOutOfContext = true; + } + } + + Path workDir = args.length == 4 ? Paths.get(args[3]) : args.length == 3 && !makeOutOfContext ? Paths.get(args[2]) : Paths.get(System.getProperty("user.dir")); + Design placed = placeDesign(input, workDir, makeOutOfContext); placed.writeCheckpoint(args[1]); } } From 921cae6a9c30c7c48c7428911de90a5ac938c7a9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2024 10:28:45 -0700 Subject: [PATCH 04/18] [FileTools] Add getUserSpecificRapidWrightDataPath() Signed-off-by: Eddie Hung --- .../xilinx/rapidwright/util/FileTools.java | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/com/xilinx/rapidwright/util/FileTools.java b/src/com/xilinx/rapidwright/util/FileTools.java index 534c71042..c08e54bb8 100644 --- a/src/com/xilinx/rapidwright/util/FileTools.java +++ b/src/com/xilinx/rapidwright/util/FileTools.java @@ -1008,22 +1008,35 @@ public static String getRapidWrightPath() { return path; } - public static String getExecJarStoragePath() { - String rootPath = ""; + /** + * Gets and returns the path for storing user-specific RapidWright data. + * On Linux, this is overridden by the $XDG_DATA_HOME environment variable, defaulting to ~/.local/share + * On Windows, this is overridden by %APPDATA% environment variable + * @return A string containing this user-specific data path plus the "RapidWright" subdirectory (created + * if it does not exist). + */ + public static Path getUserSpecificRapidWrightDataPath() { + Path rootPath; if (isWindows()) { - rootPath = System.getenv("APPDATA"); + rootPath = Paths.get(System.getenv("APPDATA")); } else { - rootPath = System.getenv("XDG_DATA_HOME"); - if (rootPath == null || rootPath.length() == 0) { - rootPath = System.getenv("HOME") + File.separator + ".local" + File.separator + "share"; + String env = System.getenv("XDG_DATA_HOME"); + if (env == null || env.length() == 0) { + rootPath = Paths.get(System.getenv("HOME"), ".local", "share"); + } else { + rootPath = Paths.get(env); } // TODO for Mac OS, the default for XDG_DATA_HOME would be '~/Library/My App/' } - rootPath += File.separator + "RapidWright"; - makeDirs(rootPath); + rootPath = rootPath.resolve("RapidWright"); + makeDirs(rootPath.toString()); return rootPath; } + public static String getExecJarStoragePath() { + return getUserSpecificRapidWrightDataPath().toString(); + } + public static void updateAllDataFiles() { System.out.println("Updating all RapidWright data files (this may take several minutes)..."); for (String fileName : DataVersions.dataVersionMap.keySet()) { From 7a958a4430b4261bda28a44aba1dc9aabeec219c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2024 10:48:23 -0700 Subject: [PATCH 05/18] Use wrapper, use temp dir, store device in $XDG_DATA_HOME Signed-off-by: Eddie Hung --- .../placer/dreamplacefpga/DREAMPlaceFPGA.java | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java index e3f192eb5..7f1ab75db 100644 --- a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -95,7 +95,7 @@ public class DREAMPlaceFPGA { public static final boolean ENABLE_IF_DEFAULT = true; public static final boolean ENABLE_SITE_ROUTING_DEFAULT = true; - public static final String dreamPlaceFPGAExec = "python dreamplacefpga/Placer.py"; + public static final String dreamPlaceFPGAExec = "DREAMPlaceFPGA"; public static Map getSettingsMap() { Map map = new HashMap<>(); @@ -147,17 +147,24 @@ public static void writeJSONForDREAMPlaceFPGA(Path jsonPath, Map } catch (IOException e) { throw new UncheckedIOException(e); } - } public static Design placeDesign(Design design, Path workDir, boolean makeOutOfContext) { + boolean removeWorkDir = false; + if (workDir == null) { + workDir = Paths.get("DREAMPlaceFPGA" + FileTools.getUniqueProcessAndHostID()); + FileTools.makeDirs(workDir.toString()); + removeWorkDir = true; + } + // Create interchange netlist file String interchangeRootFile = workDir.toString() + File.separator + "design"; Interchange.writeDesignToInterchange(design, interchangeRootFile); // Create device file if it doesn't already exist String deviceName = design.getDevice().getName(); - Path deviceFile = workDir.resolve(deviceName + ".device"); + Path deviceDir = FileTools.getUserSpecificRapidWrightDataPath(); + Path deviceFile = deviceDir.resolve(deviceName + ".device"); if (!Files.exists(deviceFile)) { try { DeviceResourcesWriter.writeDeviceResourcesFile(design.getPartName(), design.getDevice(), @@ -171,13 +178,11 @@ public static Design placeDesign(Design design, Path workDir, boolean makeOutOfC Path jsonFile = workDir.resolve("design.json"); Map settings = getSettingsMap(); settings.put(INTERCHANGE_DEVICE, deviceFile.toString()); - settings.put(INTERCHANGE_NETLIST, interchangeRootFile + Interchange.LOG_NETLIST_EXT); - settings.put(PLACE_SOL, ""); - settings.put(IO_PL, ""); + settings.put(INTERCHANGE_NETLIST, workDir.relativize(Paths.get(interchangeRootFile + Interchange.LOG_NETLIST_EXT)).toString()); writeJSONForDREAMPlaceFPGA(jsonFile, settings); // Run DREAMPlaceFPGA - String exec = dreamPlaceFPGAExec + " " + jsonFile.toString(); + String exec = dreamPlaceFPGAExec + " " + workDir.relativize(jsonFile); boolean verbose = true; String[] environ = null; Integer exitCode = FileTools.runCommand(exec, verbose, environ, workDir.toFile()); @@ -198,6 +203,10 @@ public static Design placeDesign(Design design, Path workDir, boolean makeOutOfC } catch (IOException e) { throw new UncheckedIOException(e); } + + if (removeWorkDir) { + FileTools.deleteFolder(workDir.toString()); + } return placedDesign; } @@ -217,7 +226,9 @@ public static void main(String[] args) { } } - Path workDir = args.length == 4 ? Paths.get(args[3]) : args.length == 3 && !makeOutOfContext ? Paths.get(args[2]) : Paths.get(System.getProperty("user.dir")); + Path workDir = args.length == 4 ? Paths.get(args[3]) : + args.length == 3 && !makeOutOfContext ? Paths.get(args[2]) : + null; Design placed = placeDesign(input, workDir, makeOutOfContext); placed.writeCheckpoint(args[1]); } From f046dce0d36865740637de691bd332a039f200a2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2024 14:59:53 -0700 Subject: [PATCH 06/18] Add Workdir suffix Signed-off-by: Eddie Hung --- .../rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java index 7f1ab75db..1946ad92d 100644 --- a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -152,7 +152,7 @@ public static void writeJSONForDREAMPlaceFPGA(Path jsonPath, Map public static Design placeDesign(Design design, Path workDir, boolean makeOutOfContext) { boolean removeWorkDir = false; if (workDir == null) { - workDir = Paths.get("DREAMPlaceFPGA" + FileTools.getUniqueProcessAndHostID()); + workDir = Paths.get("DREAMPlaceFPGAWorkdir" + FileTools.getUniqueProcessAndHostID()); FileTools.makeDirs(workDir.toString()); removeWorkDir = true; } From 71a35204fdf29772b30a205df45e03be4f287f4e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 25 Oct 2024 15:28:03 -0700 Subject: [PATCH 07/18] Work with upstream bin/dreamplacefpga helper Signed-off-by: Eddie Hung --- .../placer/dreamplacefpga/DREAMPlaceFPGA.java | 51 +++++++++++++------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java index 1946ad92d..fa2c47419 100644 --- a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -29,13 +29,16 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.xilinx.rapidwright.design.Design; import com.xilinx.rapidwright.interchange.DeviceResourcesWriter; import com.xilinx.rapidwright.interchange.Interchange; +import com.xilinx.rapidwright.interchange.LogNetlistWriter; import com.xilinx.rapidwright.interchange.PhysNetlistReader; import com.xilinx.rapidwright.interchange.PhysicalNetlistToDcp; import com.xilinx.rapidwright.tests.CodePerfTracker; @@ -49,6 +52,7 @@ public class DREAMPlaceFPGA { public static final String INTERCHANGE_NETLIST = "interchange_netlist"; public static final String INTERCHANGE_DEVICE = "interchange_device"; + public static final String RESULT_DIR = "result_dir"; public static final String IO_PL = "io_pl"; public static final String GPU = "gpu"; public static final String NUM_BINS_X = "num_bins_x"; @@ -59,7 +63,6 @@ public class DREAMPlaceFPGA { public static final String RANDOM_SEED = "random_seed"; public static final String SCALE_FACTOR = "scale_factor"; public static final String GLOBAL_PLACE_FLAG = "global_place_flag"; - public static final String PLACE_SOL = "place_sol"; public static final String ROUTABILITY_OPT_FLAG = "routability_opt_flag"; public static final String LEGALIZE_FLAG = "legalize_flag"; public static final String DETAILED_PLACE_FLAG = "detailed_place_flag"; @@ -70,6 +73,7 @@ public class DREAMPlaceFPGA { public static final String ENABLE_IF = "enable_if"; public static final String ENABLE_SITE_ROUTING = "enable_site_routing"; + public static final String IO_PL_DEFAULT = ""; public static final boolean GPU_DEFAULT = false; public static final int NUM_BINS_X_DEFAULT = 512; public static final int NUM_BINS_Y_DEFAULT = 512; @@ -93,13 +97,15 @@ public class DREAMPlaceFPGA { public static final int NUM_THREADS_DEFAULT = 8; public static final boolean DETERMINISTIC_FLAG_DEFAULT = true; public static final boolean ENABLE_IF_DEFAULT = true; - public static final boolean ENABLE_SITE_ROUTING_DEFAULT = true; + public static final boolean ENABLE_SITE_ROUTING_DEFAULT = false; - public static final String dreamPlaceFPGAExec = "DREAMPlaceFPGA"; + // public static final String dreamPlaceFPGAExec = "DREAMPlaceFPGA"; + public static final String dreamPlaceFPGAExec = "dreamplacefpga"; public static Map getSettingsMap() { Map map = new HashMap<>(); + map.put(IO_PL, IO_PL_DEFAULT); map.put(GPU, GPU_DEFAULT); map.put(NUM_BINS_X, NUM_BINS_X_DEFAULT); map.put(NUM_BINS_Y, NUM_BINS_Y_DEFAULT); @@ -149,7 +155,7 @@ public static void writeJSONForDREAMPlaceFPGA(Path jsonPath, Map } } - public static Design placeDesign(Design design, Path workDir, boolean makeOutOfContext) { + public static Design placeDesign(Design design, Path workDir, boolean makeOutOfContext) throws IOException { boolean removeWorkDir = false; if (workDir == null) { workDir = Paths.get("DREAMPlaceFPGAWorkdir" + FileTools.getUniqueProcessAndHostID()); @@ -158,8 +164,9 @@ public static Design placeDesign(Design design, Path workDir, boolean makeOutOfC } // Create interchange netlist file - String interchangeRootFile = workDir.toString() + File.separator + "design"; - Interchange.writeDesignToInterchange(design, interchangeRootFile); + String inputLogNetlistName = "input" + Interchange.LOG_NETLIST_EXT; + String inputLogNetlistPath = workDir.resolve(inputLogNetlistName).toString(); + LogNetlistWriter.writeLogNetlist(design.getNetlist(), inputLogNetlistPath); // Create device file if it doesn't already exist String deviceName = design.getDevice().getName(); @@ -175,26 +182,38 @@ public static Design placeDesign(Design design, Path workDir, boolean makeOutOfC } // Create JSON file for DREAMPlaceFPGA - Path jsonFile = workDir.resolve("design.json"); - Map settings = getSettingsMap(); - settings.put(INTERCHANGE_DEVICE, deviceFile.toString()); - settings.put(INTERCHANGE_NETLIST, workDir.relativize(Paths.get(interchangeRootFile + Interchange.LOG_NETLIST_EXT)).toString()); - writeJSONForDREAMPlaceFPGA(jsonFile, settings); + // Path jsonFile = workDir.resolve("design.json"); + // Map settings = getSettingsMap(); + // settings.put(INTERCHANGE_DEVICE, deviceFile.toString()); + // settings.put(INTERCHANGE_NETLIST, workDir.relativize(Paths.get(inputRoot + Interchange.LOG_NETLIST_EXT)).toString()); + // settings.put(RESULT_DIR, workDir.toString()); + // writeJSONForDREAMPlaceFPGA(jsonFile, settings); // Run DREAMPlaceFPGA - String exec = dreamPlaceFPGAExec + " " + workDir.relativize(jsonFile); + // String exec = dreamPlaceFPGAExec + " " + workDir.relativize(jsonFile); + + // Run DREAMPlaceFPGA + List exec = new ArrayList<>(); + exec.add(dreamPlaceFPGAExec); + exec.add("-interchange_netlist"); + exec.add(inputLogNetlistName); + exec.add("-interchange_device"); + exec.add(deviceFile.toString()); + exec.add("-result_dir"); + exec.add("."); + boolean verbose = true; String[] environ = null; - Integer exitCode = FileTools.runCommand(exec, verbose, environ, workDir.toFile()); + Integer exitCode = FileTools.runCommand(exec.toArray(new String[0]), verbose, environ, workDir.toFile()); if (exitCode != 0) { throw new RuntimeException("DREAMPlaceFPGA with code: " + exitCode); } // Load placed result Design placedDesign = null; - String interchangeResultFile = workDir.toString() + File.separator + "results/design/design"; + String outputPhysNetlistPath = workDir.resolve("design/design.phys").toString(); try { - placedDesign = PhysNetlistReader.readPhysNetlist(interchangeResultFile + Interchange.PHYS_NETLIST_EXT, + placedDesign = PhysNetlistReader.readPhysNetlist(outputPhysNetlistPath, design.getNetlist()); if (makeOutOfContext) { placedDesign.setAutoIOBuffers(false); @@ -210,7 +229,7 @@ public static Design placeDesign(Design design, Path workDir, boolean makeOutOfC return placedDesign; } - public static void main(String[] args) { + public static void main(String[] args) throws IOException { // Usage: [--out_of_context] [work directory] if (args.length < 2 || args.length > 4) { System.out.println("USAGE: [" From 6bb89bc3b3b71358638c18a48bfdb83ee8b2e328 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 25 Oct 2024 19:02:29 -0700 Subject: [PATCH 08/18] DREAMPlaceFPGA.placeDesign() to take EDIFNetlist instead of DCP. Also call Design.routeSites() on result Signed-off-by: Eddie Hung --- .../placer/dreamplacefpga/DREAMPlaceFPGA.java | 39 ++++++++++++------- .../placer/TestDREAMPlaceFPGA.java | 26 +++++++++++++ 2 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java index fa2c47419..46e97a27e 100644 --- a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -36,6 +36,9 @@ import java.util.Map.Entry; import com.xilinx.rapidwright.design.Design; +import com.xilinx.rapidwright.device.Device; +import com.xilinx.rapidwright.edif.EDIFNetlist; +import com.xilinx.rapidwright.edif.EDIFTools; import com.xilinx.rapidwright.interchange.DeviceResourcesWriter; import com.xilinx.rapidwright.interchange.Interchange; import com.xilinx.rapidwright.interchange.LogNetlistWriter; @@ -102,6 +105,8 @@ public class DREAMPlaceFPGA { // public static final String dreamPlaceFPGAExec = "DREAMPlaceFPGA"; public static final String dreamPlaceFPGAExec = "dreamplacefpga"; + public static final String MAKE_DCP_OUT_OF_CONTEXT = PhysicalNetlistToDcp.MAKE_DCP_OUT_OF_CONTEXT; + public static Map getSettingsMap() { Map map = new HashMap<>(); @@ -155,7 +160,11 @@ public static void writeJSONForDREAMPlaceFPGA(Path jsonPath, Map } } - public static Design placeDesign(Design design, Path workDir, boolean makeOutOfContext) throws IOException { + public static Design placeDesign(EDIFNetlist netlist) throws IOException { + return placeDesign(netlist, null, false); + } + + public static Design placeDesign(EDIFNetlist netlist, Path workDir, boolean makeOutOfContext) throws IOException { boolean removeWorkDir = false; if (workDir == null) { workDir = Paths.get("DREAMPlaceFPGAWorkdir" + FileTools.getUniqueProcessAndHostID()); @@ -166,15 +175,16 @@ public static Design placeDesign(Design design, Path workDir, boolean makeOutOfC // Create interchange netlist file String inputLogNetlistName = "input" + Interchange.LOG_NETLIST_EXT; String inputLogNetlistPath = workDir.resolve(inputLogNetlistName).toString(); - LogNetlistWriter.writeLogNetlist(design.getNetlist(), inputLogNetlistPath); + LogNetlistWriter.writeLogNetlist(netlist, inputLogNetlistPath); // Create device file if it doesn't already exist - String deviceName = design.getDevice().getName(); + String partName = EDIFTools.getPartName(netlist); + Device device = netlist.getDevice(); Path deviceDir = FileTools.getUserSpecificRapidWrightDataPath(); - Path deviceFile = deviceDir.resolve(deviceName + ".device"); + Path deviceFile = deviceDir.resolve(device.getName() + ".device"); if (!Files.exists(deviceFile)) { try { - DeviceResourcesWriter.writeDeviceResourcesFile(design.getPartName(), design.getDevice(), + DeviceResourcesWriter.writeDeviceResourcesFile(partName, device, new CodePerfTracker("Create IF Device"), deviceFile.toString(), true); } catch (IOException e) { throw new UncheckedIOException(e); @@ -214,15 +224,18 @@ public static Design placeDesign(Design design, Path workDir, boolean makeOutOfC String outputPhysNetlistPath = workDir.resolve("design/design.phys").toString(); try { placedDesign = PhysNetlistReader.readPhysNetlist(outputPhysNetlistPath, - design.getNetlist()); - if (makeOutOfContext) { - placedDesign.setAutoIOBuffers(false); - placedDesign.setDesignOutOfContext(true); - } + netlist); } catch (IOException e) { throw new UncheckedIOException(e); } + if (makeOutOfContext) { + placedDesign.setAutoIOBuffers(false); + placedDesign.setDesignOutOfContext(true); + } + + placedDesign.routeSites(); + if (removeWorkDir) { FileTools.deleteFolder(workDir.toString()); } @@ -233,14 +246,14 @@ public static void main(String[] args) throws IOException { // Usage: [--out_of_context] [work directory] if (args.length < 2 || args.length > 4) { System.out.println("USAGE: [" - + PhysicalNetlistToDcp.MAKE_DCP_OUT_OF_CONTEXT + "] [work directory]"); + + MAKE_DCP_OUT_OF_CONTEXT + "] [work directory]"); return; } Design input = Design.readCheckpoint(args[0]); boolean makeOutOfContext = false; if (args.length >= 3) { - if (args[2].equals(PhysicalNetlistToDcp.MAKE_DCP_OUT_OF_CONTEXT)) { + if (args[2].equals(MAKE_DCP_OUT_OF_CONTEXT)) { makeOutOfContext = true; } } @@ -248,7 +261,7 @@ public static void main(String[] args) throws IOException { Path workDir = args.length == 4 ? Paths.get(args[3]) : args.length == 3 && !makeOutOfContext ? Paths.get(args[2]) : null; - Design placed = placeDesign(input, workDir, makeOutOfContext); + Design placed = placeDesign(input.getNetlist(), workDir, makeOutOfContext); placed.writeCheckpoint(args[1]); } } diff --git a/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java b/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java new file mode 100644 index 000000000..b7ba191de --- /dev/null +++ b/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java @@ -0,0 +1,26 @@ +package com.xilinx.rapidwright.placer; + +import com.xilinx.rapidwright.design.Design; +import com.xilinx.rapidwright.edif.EDIFNetlist; +import com.xilinx.rapidwright.placer.dreamplacefpga.DREAMPlaceFPGA; +import com.xilinx.rapidwright.support.RapidWrightDCP; +import com.xilinx.rapidwright.util.ReportRouteStatusResult; +import com.xilinx.rapidwright.util.VivadoTools; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class TestDREAMPlaceFPGA { + + @Test + public void testDREAMPlaceFPGAMain(@TempDir Path tempDir) throws IOException { + String inputDcp = RapidWrightDCP.getString("gnl_2_4_3_1.3_gnl_3000_07_3_80_80_placed.dcp"); + String outputDcp = tempDir.resolve("output.dcp").toString(); + DREAMPlaceFPGA.main(new String[]{inputDcp, outputDcp, tempDir.toString()}); + + ReportRouteStatusResult rrs = VivadoTools.reportRouteStatus(Paths.get(outputDcp)); + } +} From 83dfe673f096d6425ccdf93e955e27cb38824fa6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 25 Oct 2024 19:05:30 -0700 Subject: [PATCH 09/18] [TestDREAMPlaceFPGA] Test placing a gnl design Signed-off-by: Eddie Hung --- .../placer/TestDREAMPlaceFPGA.java | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java b/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java index b7ba191de..c0908f5d7 100644 --- a/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java +++ b/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java @@ -1,3 +1,25 @@ +/* + * Copyright (c) 2024, Advanced Micro Devices, Inc. + * All rights reserved. + * + * Author: Eddie Hung, Advanced Micro Devices, Inc. + * + * This file is part of RapidWright. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + package com.xilinx.rapidwright.placer; import com.xilinx.rapidwright.design.Design; @@ -6,6 +28,7 @@ import com.xilinx.rapidwright.support.RapidWrightDCP; import com.xilinx.rapidwright.util.ReportRouteStatusResult; import com.xilinx.rapidwright.util.VivadoTools; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -19,8 +42,31 @@ public class TestDREAMPlaceFPGA { public void testDREAMPlaceFPGAMain(@TempDir Path tempDir) throws IOException { String inputDcp = RapidWrightDCP.getString("gnl_2_4_3_1.3_gnl_3000_07_3_80_80_placed.dcp"); String outputDcp = tempDir.resolve("output.dcp").toString(); - DREAMPlaceFPGA.main(new String[]{inputDcp, outputDcp, tempDir.toString()}); + DREAMPlaceFPGA.main(new String[]{inputDcp, outputDcp, DREAMPlaceFPGA.MAKE_DCP_OUT_OF_CONTEXT, tempDir.toString()}); ReportRouteStatusResult rrs = VivadoTools.reportRouteStatus(Paths.get(outputDcp)); + Assertions.assertEquals(3465, rrs.routableNets); + Assertions.assertEquals(3465, rrs.unroutedNets); + Assertions.assertEquals(0, rrs.netsWithRoutingErrors); + } + + @Test + public void testDREAMPlaceFPGA(@TempDir Path tempDir) throws IOException { + boolean skipXdef = true; + Design design = RapidWrightDCP.loadDCP("gnl_2_4_3_1.3_gnl_3000_07_3_80_80_placed.dcp", skipXdef); + Assertions.assertTrue(design.getUsedSites().isEmpty()); + EDIFNetlist netlist = design.getNetlist(); + design = null; + + boolean makeOutOfContext = true; + design = DREAMPlaceFPGA.placeDesign(netlist, tempDir, makeOutOfContext); + + Path outputDcp = tempDir.resolve("output.dcp"); + design.writeCheckpoint(outputDcp); + boolean encrypted = !netlist.getEncryptedCells().isEmpty(); + ReportRouteStatusResult rrs = VivadoTools.reportRouteStatus(outputDcp, tempDir, encrypted); + Assertions.assertEquals(3465, rrs.routableNets); + Assertions.assertEquals(3465, rrs.unroutedNets); + Assertions.assertEquals(0, rrs.netsWithRoutingErrors); } } From c822bf93178d383e3934524b2b3cd9493fcc6944 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 25 Oct 2024 19:17:35 -0700 Subject: [PATCH 10/18] Add and use DREAMPlaceFPGA.isDREAMPlaceFPGAOnPath() Signed-off-by: Eddie Hung --- .../rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java | 8 ++++++++ .../com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java index 46e97a27e..de27199af 100644 --- a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -242,6 +242,14 @@ public static Design placeDesign(EDIFNetlist netlist, Path workDir, boolean make return placedDesign; } + /** + * Checks if dreamplacefpga is available on current PATH (uses unix 'which' or windows 'where'). + * @return true if yosys is on current PATH, false otherwise. + */ + public static boolean isDREAMPlaceFPGAOnPath() { + return FileTools.isExecutableOnPath(dreamPlaceFPGAExec); + } + public static void main(String[] args) throws IOException { // Usage: [--out_of_context] [work directory] if (args.length < 2 || args.length > 4) { diff --git a/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java b/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java index c0908f5d7..2e5dcfcb4 100644 --- a/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java +++ b/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java @@ -29,6 +29,7 @@ import com.xilinx.rapidwright.util.ReportRouteStatusResult; import com.xilinx.rapidwright.util.VivadoTools; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -40,6 +41,9 @@ public class TestDREAMPlaceFPGA { @Test public void testDREAMPlaceFPGAMain(@TempDir Path tempDir) throws IOException { + // Skip test if dreamplacefpga is not on PATH + Assumptions.assumeTrue(DREAMPlaceFPGA.isDREAMPlaceFPGAOnPath()); + String inputDcp = RapidWrightDCP.getString("gnl_2_4_3_1.3_gnl_3000_07_3_80_80_placed.dcp"); String outputDcp = tempDir.resolve("output.dcp").toString(); DREAMPlaceFPGA.main(new String[]{inputDcp, outputDcp, DREAMPlaceFPGA.MAKE_DCP_OUT_OF_CONTEXT, tempDir.toString()}); @@ -52,6 +56,9 @@ public void testDREAMPlaceFPGAMain(@TempDir Path tempDir) throws IOException { @Test public void testDREAMPlaceFPGA(@TempDir Path tempDir) throws IOException { + // Skip test if dreamplacefpga is not on PATH + Assumptions.assumeTrue(DREAMPlaceFPGA.isDREAMPlaceFPGAOnPath()); + boolean skipXdef = true; Design design = RapidWrightDCP.loadDCP("gnl_2_4_3_1.3_gnl_3000_07_3_80_80_placed.dcp", skipXdef); Assertions.assertTrue(design.getUsedSites().isEmpty()); From c374c0cdc3dfbdbc9506612d8955ebf0dc340e59 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 28 Oct 2024 10:21:14 -0700 Subject: [PATCH 11/18] Use Design.getSiteInsts() Signed-off-by: Eddie Hung --- test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java b/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java index 2e5dcfcb4..b08f1bd98 100644 --- a/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java +++ b/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java @@ -61,7 +61,7 @@ public void testDREAMPlaceFPGA(@TempDir Path tempDir) throws IOException { boolean skipXdef = true; Design design = RapidWrightDCP.loadDCP("gnl_2_4_3_1.3_gnl_3000_07_3_80_80_placed.dcp", skipXdef); - Assertions.assertTrue(design.getUsedSites().isEmpty()); + Assertions.assertTrue(design.getSiteInsts().isEmpty()); EDIFNetlist netlist = design.getNetlist(); design = null; From 489642c947b989c3a53c9ac2525695e31f151a03 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 28 Oct 2024 11:33:11 -0700 Subject: [PATCH 12/18] RuntimeException if netlist has no device Signed-off-by: Eddie Hung --- .../rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java index de27199af..9f063eac7 100644 --- a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -179,6 +179,9 @@ public static Design placeDesign(EDIFNetlist netlist, Path workDir, boolean make // Create device file if it doesn't already exist String partName = EDIFTools.getPartName(netlist); + if (partName == null) { + throw new RuntimeException("ERROR: Netlist has no part name"); + } Device device = netlist.getDevice(); Path deviceDir = FileTools.getUserSpecificRapidWrightDataPath(); Path deviceFile = deviceDir.resolve(device.getName() + ".device"); From ab53874c51ffb50ec3411f5222aefdd9a0e31e09 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 28 Oct 2024 11:33:27 -0700 Subject: [PATCH 13/18] Check for unplaced pins too Signed-off-by: Eddie Hung --- test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java b/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java index b08f1bd98..17d0d8e78 100644 --- a/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java +++ b/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java @@ -49,6 +49,7 @@ public void testDREAMPlaceFPGAMain(@TempDir Path tempDir) throws IOException { DREAMPlaceFPGA.main(new String[]{inputDcp, outputDcp, DREAMPlaceFPGA.MAKE_DCP_OUT_OF_CONTEXT, tempDir.toString()}); ReportRouteStatusResult rrs = VivadoTools.reportRouteStatus(Paths.get(outputDcp)); + Assertions.assertEquals(0, rrs.netsWithNoPlacedPins); Assertions.assertEquals(3465, rrs.routableNets); Assertions.assertEquals(3465, rrs.unroutedNets); Assertions.assertEquals(0, rrs.netsWithRoutingErrors); @@ -72,6 +73,7 @@ public void testDREAMPlaceFPGA(@TempDir Path tempDir) throws IOException { design.writeCheckpoint(outputDcp); boolean encrypted = !netlist.getEncryptedCells().isEmpty(); ReportRouteStatusResult rrs = VivadoTools.reportRouteStatus(outputDcp, tempDir, encrypted); + Assertions.assertEquals(0, rrs.netsWithNoPlacedPins); Assertions.assertEquals(3465, rrs.routableNets); Assertions.assertEquals(3465, rrs.unroutedNets); Assertions.assertEquals(0, rrs.netsWithRoutingErrors); From 311281c210c4cd617300f37dfe54ad03293ad500 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 29 Oct 2024 12:20:40 -0700 Subject: [PATCH 14/18] Do not check exact number of routable nets Signed-off-by: Eddie Hung --- .../rapidwright/placer/TestDREAMPlaceFPGA.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java b/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java index 17d0d8e78..c9be74111 100644 --- a/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java +++ b/test/src/com/xilinx/rapidwright/placer/TestDREAMPlaceFPGA.java @@ -50,8 +50,10 @@ public void testDREAMPlaceFPGAMain(@TempDir Path tempDir) throws IOException { ReportRouteStatusResult rrs = VivadoTools.reportRouteStatus(Paths.get(outputDcp)); Assertions.assertEquals(0, rrs.netsWithNoPlacedPins); - Assertions.assertEquals(3465, rrs.routableNets); - Assertions.assertEquals(3465, rrs.unroutedNets); + // DREAMPlaceFPGA does not appear to be deterministic across machines + // Assertions.assertEquals(3465, rrs.routableNets); + Assertions.assertTrue(rrs.routableNets > 3000); + Assertions.assertEquals(rrs.routableNets, rrs.unroutedNets); Assertions.assertEquals(0, rrs.netsWithRoutingErrors); } @@ -74,8 +76,10 @@ public void testDREAMPlaceFPGA(@TempDir Path tempDir) throws IOException { boolean encrypted = !netlist.getEncryptedCells().isEmpty(); ReportRouteStatusResult rrs = VivadoTools.reportRouteStatus(outputDcp, tempDir, encrypted); Assertions.assertEquals(0, rrs.netsWithNoPlacedPins); - Assertions.assertEquals(3465, rrs.routableNets); - Assertions.assertEquals(3465, rrs.unroutedNets); + // DREAMPlaceFPGA does not appear to be deterministic across machines + // Assertions.assertEquals(3465, rrs.routableNets); + Assertions.assertTrue(rrs.routableNets > 3000); + Assertions.assertEquals(rrs.routableNets, rrs.unroutedNets); Assertions.assertEquals(0, rrs.netsWithRoutingErrors); } } From 507a9f0081ee91f31d826a67fab0ab75a83c7d49 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 29 Oct 2024 13:20:08 -0700 Subject: [PATCH 15/18] Cleanup; remove unused json writer Signed-off-by: Eddie Hung --- .../placer/dreamplacefpga/DREAMPlaceFPGA.java | 129 ++---------------- 1 file changed, 14 insertions(+), 115 deletions(-) diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java index 9f063eac7..95bedcd43 100644 --- a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -53,117 +53,27 @@ */ public class DREAMPlaceFPGA { - public static final String INTERCHANGE_NETLIST = "interchange_netlist"; - public static final String INTERCHANGE_DEVICE = "interchange_device"; - public static final String RESULT_DIR = "result_dir"; - public static final String IO_PL = "io_pl"; - public static final String GPU = "gpu"; - public static final String NUM_BINS_X = "num_bins_x"; - public static final String NUM_BINS_Y = "num_bins_y"; - public static final String GLOBAL_PLACE_STAGES = "global_place_stages"; - public static final String TARGET_DENSITY = "target_density"; - public static final String DENSITY_WEIGHT = "density_weight"; - public static final String RANDOM_SEED = "random_seed"; - public static final String SCALE_FACTOR = "scale_factor"; - public static final String GLOBAL_PLACE_FLAG = "global_place_flag"; - public static final String ROUTABILITY_OPT_FLAG = "routability_opt_flag"; - public static final String LEGALIZE_FLAG = "legalize_flag"; - public static final String DETAILED_PLACE_FLAG = "detailed_place_flag"; - public static final String DTYPE = "dtype"; - public static final String PLOT_FLAG = "plot_flag"; - public static final String NUM_THREADS = "num_threads"; - public static final String DETERMINISTIC_FLAG = "deterministic_flag"; - public static final String ENABLE_IF = "enable_if"; - public static final String ENABLE_SITE_ROUTING = "enable_site_routing"; - - public static final String IO_PL_DEFAULT = ""; - public static final boolean GPU_DEFAULT = false; - public static final int NUM_BINS_X_DEFAULT = 512; - public static final int NUM_BINS_Y_DEFAULT = 512; - public static final String GLOBAL_PLACE_STAGES_DEFAULT = - "[\n{\"num_bins_x\" : 512," - + " \"num_bins_y\" : 512," - + " \"iteration\" : 2000," - + " \"learning_rate\" : 0.01," - + " \"wirelength\" : \"weighted_average\"," - + " \"optimizer\" : \"nesterov\"}\n]"; - public static final double TARGET_DENSITY_DEFAULT = 1.0; - public static final double DENSITY_WEIGHT_DEFAULT = 8e-5; - public static final int RANDOM_SEED_DEFAULT = 1000; - public static final double SCALE_FACTOR_DEFAULT = 1.0; - public static final boolean GLOBAL_PLACE_FLAG_DEFAULT = true; - public static final boolean ROUTABILITY_OPT_FLAG_DEFAULT = false; - public static final boolean LEGALIZE_FLAG_DEFAULT = true; - public static final boolean DETAILED_PLACE_FLAG_DEFAULT = false; - public static final String DTYPE_DEFAULT = "float32"; - public static final boolean PLOT_FLAG_DEFAULT = false; - public static final int NUM_THREADS_DEFAULT = 8; - public static final boolean DETERMINISTIC_FLAG_DEFAULT = true; - public static final boolean ENABLE_IF_DEFAULT = true; - public static final boolean ENABLE_SITE_ROUTING_DEFAULT = false; - - // public static final String dreamPlaceFPGAExec = "DREAMPlaceFPGA"; public static final String dreamPlaceFPGAExec = "dreamplacefpga"; public static final String MAKE_DCP_OUT_OF_CONTEXT = PhysicalNetlistToDcp.MAKE_DCP_OUT_OF_CONTEXT; - public static Map getSettingsMap() { - Map map = new HashMap<>(); - - map.put(IO_PL, IO_PL_DEFAULT); - map.put(GPU, GPU_DEFAULT); - map.put(NUM_BINS_X, NUM_BINS_X_DEFAULT); - map.put(NUM_BINS_Y, NUM_BINS_Y_DEFAULT); - map.put(GLOBAL_PLACE_STAGES, GLOBAL_PLACE_STAGES_DEFAULT); - map.put(TARGET_DENSITY, TARGET_DENSITY_DEFAULT); - map.put(DENSITY_WEIGHT, DENSITY_WEIGHT_DEFAULT); - map.put(RANDOM_SEED, RANDOM_SEED_DEFAULT); - map.put(SCALE_FACTOR, SCALE_FACTOR_DEFAULT); - map.put(GLOBAL_PLACE_FLAG, GLOBAL_PLACE_FLAG_DEFAULT); - map.put(ROUTABILITY_OPT_FLAG, ROUTABILITY_OPT_FLAG_DEFAULT); - map.put(LEGALIZE_FLAG, LEGALIZE_FLAG_DEFAULT); - map.put(DETAILED_PLACE_FLAG, DETAILED_PLACE_FLAG_DEFAULT); - map.put(DTYPE, DTYPE_DEFAULT); - map.put(PLOT_FLAG, PLOT_FLAG_DEFAULT); - map.put(NUM_THREADS, NUM_THREADS_DEFAULT); - map.put(DETERMINISTIC_FLAG, DETERMINISTIC_FLAG_DEFAULT); - map.put(ENABLE_IF, ENABLE_IF_DEFAULT); - map.put(ENABLE_SITE_ROUTING, ENABLE_SITE_ROUTING_DEFAULT); - - return map; - } - - public static void writeJSONForDREAMPlaceFPGA(Path jsonPath, Map attributes) { - try (BufferedWriter bw = new BufferedWriter(new FileWriter(jsonPath.toFile()))) { - bw.write("{\n"); - boolean first = true; - for (Entry e : attributes.entrySet()) { - if (first) { - first = false; - } else { - bw.write(",\n"); - } - bw.write(" \"" + e.getKey() + "\""); - bw.write(" : "); - if (e.getValue() instanceof String && !e.getKey().equals(GLOBAL_PLACE_STAGES)) { - bw.write("\"" + e.getValue().toString() + "\""); - } else if (e.getValue() instanceof Boolean) { - bw.write((boolean) e.getValue() ? "1" : "0"); - } else { - bw.write(e.getValue().toString() + ""); - } - - } - bw.write("\n}\n"); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - + /** + * Given a EDIFNetlist object, place it using DREAMPlaceFPGA. + * @param netlist EDIFNetlist object to be placed. + * @return Placed Design object. + * @throws IOException + */ public static Design placeDesign(EDIFNetlist netlist) throws IOException { return placeDesign(netlist, null, false); } + /** + * Given a EDIFNetlist object, place it using DREAMPlaceFPGA. + * @param netlist EDIFNetlist object to be placed. + * @param workDir Path to working directory (null to use a temporary directory which gets deleted on return) + * @return Placed Design object. + * @throws IOException + */ public static Design placeDesign(EDIFNetlist netlist, Path workDir, boolean makeOutOfContext) throws IOException { boolean removeWorkDir = false; if (workDir == null) { @@ -194,17 +104,6 @@ public static Design placeDesign(EDIFNetlist netlist, Path workDir, boolean make } } - // Create JSON file for DREAMPlaceFPGA - // Path jsonFile = workDir.resolve("design.json"); - // Map settings = getSettingsMap(); - // settings.put(INTERCHANGE_DEVICE, deviceFile.toString()); - // settings.put(INTERCHANGE_NETLIST, workDir.relativize(Paths.get(inputRoot + Interchange.LOG_NETLIST_EXT)).toString()); - // settings.put(RESULT_DIR, workDir.toString()); - // writeJSONForDREAMPlaceFPGA(jsonFile, settings); - - // Run DREAMPlaceFPGA - // String exec = dreamPlaceFPGAExec + " " + workDir.relativize(jsonFile); - // Run DREAMPlaceFPGA List exec = new ArrayList<>(); exec.add(dreamPlaceFPGAExec); @@ -223,7 +122,7 @@ public static Design placeDesign(EDIFNetlist netlist, Path workDir, boolean make } // Load placed result - Design placedDesign = null; + Design placedDesign; String outputPhysNetlistPath = workDir.resolve("design/design.phys").toString(); try { placedDesign = PhysNetlistReader.readPhysNetlist(outputPhysNetlistPath, From fe80bc9d30a503d8490dc45971f40b863239d02a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 8 Jan 2025 17:07:48 -0800 Subject: [PATCH 16/18] Restore JSON writer Signed-off-by: Eddie Hung --- .../placer/dreamplacefpga/DREAMPlaceFPGA.java | 116 +++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java index 95bedcd43..0c1006158 100644 --- a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -53,10 +53,113 @@ */ public class DREAMPlaceFPGA { + public static final String INTERCHANGE_NETLIST = "interchange_netlist"; + public static final String INTERCHANGE_DEVICE = "interchange_device"; + public static final String RESULT_DIR = "result_dir"; + public static final String IO_PL = "io_pl"; + public static final String GPU = "gpu"; + public static final String NUM_BINS_X = "num_bins_x"; + public static final String NUM_BINS_Y = "num_bins_y"; + public static final String GLOBAL_PLACE_STAGES = "global_place_stages"; + public static final String TARGET_DENSITY = "target_density"; + public static final String DENSITY_WEIGHT = "density_weight"; + public static final String RANDOM_SEED = "random_seed"; + public static final String SCALE_FACTOR = "scale_factor"; + public static final String GLOBAL_PLACE_FLAG = "global_place_flag"; + public static final String ROUTABILITY_OPT_FLAG = "routability_opt_flag"; + public static final String LEGALIZE_FLAG = "legalize_flag"; + public static final String DETAILED_PLACE_FLAG = "detailed_place_flag"; + public static final String DTYPE = "dtype"; + public static final String PLOT_FLAG = "plot_flag"; + public static final String NUM_THREADS = "num_threads"; + public static final String DETERMINISTIC_FLAG = "deterministic_flag"; + public static final String ENABLE_IF = "enable_if"; + public static final String ENABLE_SITE_ROUTING = "enable_site_routing"; + + public static final String IO_PL_DEFAULT = ""; + public static final boolean GPU_DEFAULT = false; + public static final int NUM_BINS_X_DEFAULT = 512; + public static final int NUM_BINS_Y_DEFAULT = 512; + public static final String GLOBAL_PLACE_STAGES_DEFAULT = + "[\n{\"num_bins_x\" : 512," + + " \"num_bins_y\" : 512," + + " \"iteration\" : 2000," + + " \"learning_rate\" : 0.01," + + " \"wirelength\" : \"weighted_average\"," + + " \"optimizer\" : \"nesterov\"}\n]"; + public static final double TARGET_DENSITY_DEFAULT = 1.0; + public static final double DENSITY_WEIGHT_DEFAULT = 8e-5; + public static final int RANDOM_SEED_DEFAULT = 1000; + public static final double SCALE_FACTOR_DEFAULT = 1.0; + public static final boolean GLOBAL_PLACE_FLAG_DEFAULT = true; + public static final boolean ROUTABILITY_OPT_FLAG_DEFAULT = false; + public static final boolean LEGALIZE_FLAG_DEFAULT = true; + public static final boolean DETAILED_PLACE_FLAG_DEFAULT = false; + public static final String DTYPE_DEFAULT = "float32"; + public static final boolean PLOT_FLAG_DEFAULT = false; + public static final int NUM_THREADS_DEFAULT = 8; + public static final boolean DETERMINISTIC_FLAG_DEFAULT = true; + public static final boolean ENABLE_IF_DEFAULT = true; + public static final boolean ENABLE_SITE_ROUTING_DEFAULT = false; + + // public static final String dreamPlaceFPGAExec = "DREAMPlaceFPGA"; public static final String dreamPlaceFPGAExec = "dreamplacefpga"; public static final String MAKE_DCP_OUT_OF_CONTEXT = PhysicalNetlistToDcp.MAKE_DCP_OUT_OF_CONTEXT; + public static Map getSettingsMap() { + Map map = new HashMap<>(); + + map.put(IO_PL, IO_PL_DEFAULT); + map.put(GPU, GPU_DEFAULT); + map.put(NUM_BINS_X, NUM_BINS_X_DEFAULT); + map.put(NUM_BINS_Y, NUM_BINS_Y_DEFAULT); + map.put(GLOBAL_PLACE_STAGES, GLOBAL_PLACE_STAGES_DEFAULT); + map.put(TARGET_DENSITY, TARGET_DENSITY_DEFAULT); + map.put(DENSITY_WEIGHT, DENSITY_WEIGHT_DEFAULT); + map.put(RANDOM_SEED, RANDOM_SEED_DEFAULT); + map.put(SCALE_FACTOR, SCALE_FACTOR_DEFAULT); + map.put(GLOBAL_PLACE_FLAG, GLOBAL_PLACE_FLAG_DEFAULT); + map.put(ROUTABILITY_OPT_FLAG, ROUTABILITY_OPT_FLAG_DEFAULT); + map.put(LEGALIZE_FLAG, LEGALIZE_FLAG_DEFAULT); + map.put(DETAILED_PLACE_FLAG, DETAILED_PLACE_FLAG_DEFAULT); + map.put(DTYPE, DTYPE_DEFAULT); + map.put(PLOT_FLAG, PLOT_FLAG_DEFAULT); + map.put(NUM_THREADS, NUM_THREADS_DEFAULT); + map.put(DETERMINISTIC_FLAG, DETERMINISTIC_FLAG_DEFAULT); + map.put(ENABLE_IF, ENABLE_IF_DEFAULT); + map.put(ENABLE_SITE_ROUTING, ENABLE_SITE_ROUTING_DEFAULT); + + return map; + } + + public static void writeJSONForDREAMPlaceFPGA(Path jsonPath, Map attributes) { + try (BufferedWriter bw = new BufferedWriter(new FileWriter(jsonPath.toFile()))) { + bw.write("{\n"); + boolean first = true; + for (Entry e : attributes.entrySet()) { + if (first) { + first = false; + } else { + bw.write(",\n"); + } + bw.write(" \"" + e.getKey() + "\""); + bw.write(" : "); + if (e.getValue() instanceof String && !e.getKey().equals(GLOBAL_PLACE_STAGES)) { + bw.write("\"" + e.getValue().toString() + "\""); + } else if (e.getValue() instanceof Boolean) { + bw.write((boolean) e.getValue() ? "1" : "0"); + } else { + bw.write(e.getValue().toString() + ""); + } + + } + bw.write("\n}\n"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + /** * Given a EDIFNetlist object, place it using DREAMPlaceFPGA. * @param netlist EDIFNetlist object to be placed. @@ -104,6 +207,17 @@ public static Design placeDesign(EDIFNetlist netlist, Path workDir, boolean make } } + // Create JSON file for DREAMPlaceFPGA + // Path jsonFile = workDir.resolve("design.json"); + // Map settings = getSettingsMap(); + // settings.put(INTERCHANGE_DEVICE, deviceFile.toString()); + // settings.put(INTERCHANGE_NETLIST, workDir.relativize(Paths.get(inputRoot + Interchange.LOG_NETLIST_EXT)).toString()); + // settings.put(RESULT_DIR, workDir.toString()); + // writeJSONForDREAMPlaceFPGA(jsonFile, settings); + + // Run DREAMPlaceFPGA + // String exec = dreamPlaceFPGAExec + " " + workDir.relativize(jsonFile); + // Run DREAMPlaceFPGA List exec = new ArrayList<>(); exec.add(dreamPlaceFPGAExec); @@ -122,7 +236,7 @@ public static Design placeDesign(EDIFNetlist netlist, Path workDir, boolean make } // Load placed result - Design placedDesign; + Design placedDesign = null; String outputPhysNetlistPath = workDir.resolve("design/design.phys").toString(); try { placedDesign = PhysNetlistReader.readPhysNetlist(outputPhysNetlistPath, From 5ae6c9c4c8b0093c199b17b21ec7bacee5854fcf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 8 Jan 2025 17:11:34 -0800 Subject: [PATCH 17/18] Restore use of JSON Signed-off-by: Eddie Hung --- .../placer/dreamplacefpga/DREAMPlaceFPGA.java | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java index 0c1006158..e1b72dc21 100644 --- a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -208,12 +208,12 @@ public static Design placeDesign(EDIFNetlist netlist, Path workDir, boolean make } // Create JSON file for DREAMPlaceFPGA - // Path jsonFile = workDir.resolve("design.json"); - // Map settings = getSettingsMap(); - // settings.put(INTERCHANGE_DEVICE, deviceFile.toString()); - // settings.put(INTERCHANGE_NETLIST, workDir.relativize(Paths.get(inputRoot + Interchange.LOG_NETLIST_EXT)).toString()); - // settings.put(RESULT_DIR, workDir.toString()); - // writeJSONForDREAMPlaceFPGA(jsonFile, settings); + Path jsonFile = workDir.resolve("design.json"); + Map settings = getSettingsMap(); + settings.put(INTERCHANGE_DEVICE, deviceFile.toString()); + settings.put(INTERCHANGE_NETLIST, inputLogNetlistName); + settings.put(RESULT_DIR, "."); + writeJSONForDREAMPlaceFPGA(jsonFile, settings); // Run DREAMPlaceFPGA // String exec = dreamPlaceFPGAExec + " " + workDir.relativize(jsonFile); @@ -221,12 +221,8 @@ public static Design placeDesign(EDIFNetlist netlist, Path workDir, boolean make // Run DREAMPlaceFPGA List exec = new ArrayList<>(); exec.add(dreamPlaceFPGAExec); - exec.add("-interchange_netlist"); - exec.add(inputLogNetlistName); - exec.add("-interchange_device"); - exec.add(deviceFile.toString()); - exec.add("-result_dir"); - exec.add("."); + exec.add("-json"); + exec.add(jsonFile.toString()); boolean verbose = true; String[] environ = null; @@ -236,7 +232,7 @@ public static Design placeDesign(EDIFNetlist netlist, Path workDir, boolean make } // Load placed result - Design placedDesign = null; + Design placedDesign; String outputPhysNetlistPath = workDir.resolve("design/design.phys").toString(); try { placedDesign = PhysNetlistReader.readPhysNetlist(outputPhysNetlistPath, From 36bc83335e013afd8ccdbfeb929256e4eeaff885 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 10 Jan 2025 16:24:39 -0800 Subject: [PATCH 18/18] Tidy up Signed-off-by: Eddie Hung --- .../rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java index e1b72dc21..1c4980a55 100644 --- a/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java +++ b/src/com/xilinx/rapidwright/placer/dreamplacefpga/DREAMPlaceFPGA.java @@ -215,9 +215,6 @@ public static Design placeDesign(EDIFNetlist netlist, Path workDir, boolean make settings.put(RESULT_DIR, "."); writeJSONForDREAMPlaceFPGA(jsonFile, settings); - // Run DREAMPlaceFPGA - // String exec = dreamPlaceFPGAExec + " " + workDir.relativize(jsonFile); - // Run DREAMPlaceFPGA List exec = new ArrayList<>(); exec.add(dreamPlaceFPGAExec);