diff --git a/src/com/xilinx/rapidwright/examples/PartRetargeter.java b/src/com/xilinx/rapidwright/examples/PartRetargeter.java new file mode 100644 index 000000000..0568e0e3d --- /dev/null +++ b/src/com/xilinx/rapidwright/examples/PartRetargeter.java @@ -0,0 +1,68 @@ +/* + * + * 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.examples; + +import java.util.Arrays; + +import com.xilinx.rapidwright.design.Design; +import com.xilinx.rapidwright.device.Device; +import com.xilinx.rapidwright.device.Part; +import com.xilinx.rapidwright.device.PartNameTools; + +/** + * Allows an existing DCP (placed and/or routed) to be retargeted to another + * part and optionally be relocated to another SLR. This works only for specific + * devices such as a VU3P to a VU9P, for example since they have floorplan + * compatible SLRs. + */ +public class PartRetargeter { + + public static void main(String[] args) { + if (args.length != 4) { + System.out.println("USAGE: "); + System.exit(1); + } + Part targetPart = PartNameTools.getPart(args[2]); + if (targetPart == null) { + throw new RuntimeException("ERROR: Unrecognized part '" + args[2] + "'"); + } + Device targetDevice = Device.getDevice(targetPart); + + int targetSLR = Integer.parseInt(args[3]); + if (targetSLR < 0 || targetSLR >= targetDevice.getNumOfSLRs()) { + throw new RuntimeException("ERROR: Invalid SLR index '" + args[3] + "', should be one of " + + Arrays.toString(targetDevice.getSLRs())); + } + int tileXOffset = 0; + int tileYOffset = targetSLR * (targetDevice.getMasterSLR().getNumOfClockRegionRows() + * targetPart.getSeries().getCLEHeight()); + + Design d = Design.readCheckpoint(args[0]); + boolean result = d.retargetPart(targetPart, tileXOffset, tileYOffset); + if (!result) { + System.err.println("WARNING: Incomplete relocation of design."); + } + d.writeCheckpoint(args[1]); + } +} diff --git a/test/src/com/xilinx/rapidwright/design/TestDesign.java b/test/src/com/xilinx/rapidwright/design/TestDesign.java index 4178bc834..29fc0738f 100644 --- a/test/src/com/xilinx/rapidwright/design/TestDesign.java +++ b/test/src/com/xilinx/rapidwright/design/TestDesign.java @@ -39,6 +39,9 @@ import com.xilinx.rapidwright.device.BEL; import com.xilinx.rapidwright.device.Device; +import com.xilinx.rapidwright.device.PIP; +import com.xilinx.rapidwright.device.Part; +import com.xilinx.rapidwright.device.PartNameTools; import com.xilinx.rapidwright.device.Series; import com.xilinx.rapidwright.device.Site; import com.xilinx.rapidwright.device.SitePIP; @@ -59,6 +62,7 @@ import com.xilinx.rapidwright.util.JobQueue; import com.xilinx.rapidwright.util.LocalJob; import com.xilinx.rapidwright.util.ParallelismTools; +import com.xilinx.rapidwright.util.VivadoToolsHelper; /** * Test that we can write a DCP file and read it back in. We currently don't have a way to check designs for equality, @@ -440,4 +444,60 @@ public void testPlaceIOB(String partName, String pkgPin) { : design.getNet(ibufInst.getName() + "/O"); Assertions.assertEquals(siteInst.getNetFromSiteWire("DOUT"), dout); } + + private void ensureDesignInSLR(Design d, int expectedSLR) { + for (SiteInst si : d.getSiteInsts()) { + Assertions.assertEquals(expectedSLR, si.getTile().getSLR().getId()); + } + for (Net n : d.getNets()) { + for (PIP p : n.getPIPs()) { + Assertions.assertEquals(expectedSLR, p.getTile().getSLR().getId()); + } + } + } + + /** + * Tests relocating and retargeting a Picoblaze design from a vu3p to each of + * the three SLRs in a vu9p since all of the SLRs between the devices are + * relocation compatible. + * + * @param tempDir Temp directory to write out results. + */ + @Test + public void testRetargetPart(@TempDir Path tempDir) { + String targetPartName = "xcvu9p-flgb2104-2-i"; + Part targetPart = PartNameTools.getPart(targetPartName); + Device targetDevice = Device.getDevice(targetPart); + for (int slr = 0; slr < targetDevice.getNumOfSLRs(); slr++) { + Design d = RapidWrightDCP.loadDCP("picoblaze_ooc_X10Y235.dcp"); + Part origPart = d.getPart(); + assert (d.getDevice().getName().equals("xcvu3p")); + int tileDX = 0; + int tileDY = slr * targetDevice.getMasterSLR().getNumOfClockRegionRows() + * targetPart.getSeries().getCLEHeight(); + Assertions.assertTrue(d.retargetPart(targetPart, tileDX, tileDY)); + Path output = tempDir.resolve("retarget_" + slr + ".dcp"); + + Assertions.assertEquals(targetPartName, d.getPartName()); + ensureDesignInSLR(d, slr); + + d.writeCheckpoint(output); + + Design d2 = Design.readCheckpoint(output); + + Assertions.assertEquals(targetPartName, d2.getPartName()); + ensureDesignInSLR(d2, slr); + + // Try reversing the process to see if we get the original + d2.retargetPart(origPart, tileDX * -1, tileDY * -1); + assert (d2.getDevice().getName().equals(origPart.getDevice())); + ensureDesignInSLR(d2, 0); + + // Just do a single sanity check that it opens ok in Vivado + if (slr == 1 && FileTools.isVivadoOnPath()) { + VivadoToolsHelper.assertFullyRouted(output); + } + } + + } }