diff --git a/src/com/xilinx/rapidwright/edif/EDIFPort.java b/src/com/xilinx/rapidwright/edif/EDIFPort.java index 8ce8377b5..886a96b28 100644 --- a/src/com/xilinx/rapidwright/edif/EDIFPort.java +++ b/src/com/xilinx/rapidwright/edif/EDIFPort.java @@ -1,7 +1,7 @@ /* * * Copyright (c) 2017-2022, Xilinx, Inc. - * Copyright (c) 2022, Advanced Micro Devices, Inc. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. * All rights reserved. * * Author: Chris Lavin, Xilinx Research Labs. @@ -260,7 +260,12 @@ public void exportEDIF(OutputStream os, EDIFWriteLegalNameCache cache, boolea os.write(EXPORT_CONST_INDENT); os.write(EXPORT_CONST_PORT_BEGIN); if (width > 1) os.write(EXPORT_CONST_ARRAY_BEGIN); - exportEDIFName(os, cache); + if (isBus()) { + exportEDIFBusName(os, cache); + } else { + exportEDIFName(os, cache); + } + if (width > 1) { os.write(' '); os.write(Integer.toString(width).getBytes(StandardCharsets.UTF_8)); @@ -278,6 +283,17 @@ public void exportEDIF(OutputStream os, EDIFWriteLegalNameCache cache, boolea os.write('\n'); } + /** + * Writes out valid EDIF syntax the name and/or rename of this port to the + * provided output writer. + * + * @param os The stream to export the EDIF syntax to. + * @throws IOException + */ + public void exportEDIFBusName(OutputStream os, EDIFWriteLegalNameCache cache) throws IOException { + exportSomeEDIFName(os, getName(), cache.getEDIFRename(busName)); + } + /** * @return the parentCell */ diff --git a/src/com/xilinx/rapidwright/edif/EDIFPortInst.java b/src/com/xilinx/rapidwright/edif/EDIFPortInst.java index 9686908e0..16cabc49e 100644 --- a/src/com/xilinx/rapidwright/edif/EDIFPortInst.java +++ b/src/com/xilinx/rapidwright/edif/EDIFPortInst.java @@ -1,7 +1,7 @@ /* * * Copyright (c) 2017-2022, Xilinx, Inc. - * Copyright (c) 2022, Advanced Micro Devices, Inc. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. * All rights reserved. * * Author: Chris Lavin, Xilinx Research Labs. @@ -278,7 +278,7 @@ public void writeEDIFExport(OutputStream os, byte[] indent, EDIFWriteLegalNameCa } else { os.write(EXPORT_CONST_MEMBER); - os.write(cache.getLegalEDIFName(getPort().getName())); + os.write(cache.getLegalEDIFName(getPort().getBusName(true))); os.write(' '); os.write(Integer.toString(index).getBytes(StandardCharsets.UTF_8)); os.write(')'); diff --git a/test/src/com/xilinx/rapidwright/edif/TestEDIFNetlist.java b/test/src/com/xilinx/rapidwright/edif/TestEDIFNetlist.java index 8bc38a965..19ad515df 100644 --- a/test/src/com/xilinx/rapidwright/edif/TestEDIFNetlist.java +++ b/test/src/com/xilinx/rapidwright/edif/TestEDIFNetlist.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2021-2022, Xilinx, Inc. - * Copyright (c) 2022, Advanced Micro Devices, Inc. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. * All rights reserved. * * Author: Chris Lavin, Xilinx Research Labs. @@ -32,15 +32,16 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import com.xilinx.rapidwright.design.Design; import com.xilinx.rapidwright.device.Device; import com.xilinx.rapidwright.device.IOStandard; import com.xilinx.rapidwright.device.Part; import com.xilinx.rapidwright.device.PartNameTools; +import com.xilinx.rapidwright.edif.compare.EDIFNetlistComparator; import com.xilinx.rapidwright.support.RapidWrightDCP; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; class TestEDIFNetlist { @@ -287,4 +288,43 @@ public void testMigrateCellsAndSubCells(boolean uniquify) { Assertions.assertEquals(dstLibrary.getCells().size(), 1); } } + + @Test + public void testBussedPortNamingCollision(@TempDir Path path) { + final EDIFNetlist origNetlist = EDIFTools.createNewNetlist("test"); + + EDIFCell top = origNetlist.getTopCell(); + + EDIFCellInst ff = top.createChildCellInst("ff", Design.getPrimitivesLibrary().getCell("FDRE")); + origNetlist.getHDIPrimitivesLibrary().addCell(ff.getCellType()); + + String portName = "unfortunate_name"; + + // Create two ports, one single-bit and another bussed with the same root name + EDIFPort port0 = top.createPort(portName, EDIFDirection.INOUT, 1); + EDIFPort port1 = top.createPort(portName + "[1:0]", EDIFDirection.INOUT, 2); + + EDIFNet net0 = top.createNet("net0"); + net0.createPortInst(port0); + net0.createPortInst("D", ff); + + EDIFNet net1 = top.createNet("net1"); + net1.createPortInst(port1, 1); + net1.createPortInst("R", ff); + + Path tempFile = path.resolve("test.edf"); + origNetlist.exportEDIF(tempFile); + + // Check using EDIFNetlistComparator + EDIFNetlist testNetlist = EDIFTools.readEdifFile(tempFile); + EDIFNetlistComparator comparer = new EDIFNetlistComparator(); + Assertions.assertEquals(0, comparer.compareNetlists(origNetlist, testNetlist)); + + // Perform explicit check of port widths + EDIFCell testTopCell = testNetlist.getTopCell(); + EDIFPort testPort0 = testTopCell.getNet(net0.getName()).getPortInst(null, portName).getPort(); + Assertions.assertEquals(port0.getWidth(), testPort0.getWidth()); + EDIFPort testPort1 = testTopCell.getNet(net1.getName()).getPortInst(null, portName + "[0]").getPort(); + Assertions.assertEquals(port1.getWidth(), testPort1.getWidth()); + } }