diff --git a/src/com/xilinx/rapidwright/interchange/DeviceResourcesWriter.java b/src/com/xilinx/rapidwright/interchange/DeviceResourcesWriter.java index 209469c63..ba5d67480 100644 --- a/src/com/xilinx/rapidwright/interchange/DeviceResourcesWriter.java +++ b/src/com/xilinx/rapidwright/interchange/DeviceResourcesWriter.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2020-2022, Xilinx, Inc. - * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. + * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. * All rights reserved. * * Author: Chris Lavin, Xilinx Research Labs. @@ -23,30 +23,6 @@ package com.xilinx.rapidwright.interchange; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Queue; -import java.util.Set; -import java.util.TreeSet; - -import org.capnproto.MessageBuilder; -import org.capnproto.PrimitiveList; -import org.capnproto.PrimitiveList.Int; -import org.capnproto.StructList; -import org.capnproto.Text; -import org.capnproto.TextList; -import org.capnproto.Void; - import com.xilinx.rapidwright.design.Design; import com.xilinx.rapidwright.design.DesignTools; import com.xilinx.rapidwright.design.SiteInst; @@ -99,8 +75,37 @@ import com.xilinx.rapidwright.interchange.LogicalNetlist.Netlist; import com.xilinx.rapidwright.interchange.LogicalNetlist.Netlist.Direction; import com.xilinx.rapidwright.interchange.LogicalNetlist.Netlist.PropertyMap; +import com.xilinx.rapidwright.rwroute.RouterHelper; import com.xilinx.rapidwright.tests.CodePerfTracker; +import com.xilinx.rapidwright.timing.DelayModel; +import com.xilinx.rapidwright.timing.TimingModel; +import com.xilinx.rapidwright.timing.delayestimator.DelayEstimatorBase; +import com.xilinx.rapidwright.timing.delayestimator.InterconnectInfo; import com.xilinx.rapidwright.util.Pair; +import com.xilinx.rapidwright.util.Utils; +import org.capnproto.MessageBuilder; +import org.capnproto.PrimitiveList; +import org.capnproto.PrimitiveList.Int; +import org.capnproto.StructList; +import org.capnproto.Text; +import org.capnproto.TextList; +import org.capnproto.Void; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Queue; +import java.util.Set; +import java.util.TreeSet; public class DeviceResourcesWriter { private static StringEnumerator allStrings; @@ -109,6 +114,11 @@ public class DeviceResourcesWriter { private static HashMap tileTypes; private static HashMap siteTypes; + private static DelayEstimatorBase delayEstimator; + private static DelayModel intrasiteAndLogicDelayModel; + + private static final float PICSECONDS_TO_SECONDS = 1e-12f; + public static void populateSiteEnumerations(SiteInst siteInst, Site site) { if (!siteTypes.containsKey(siteInst.getSiteTypeEnum())) { if (site.getSiteTypeEnum() != siteInst.getSiteTypeEnum()) { @@ -277,6 +287,16 @@ public static void writeDeviceResourcesFile(String part, Device device, CodePerf design.setPartName(part); Series series = device.getSeries(); + delayEstimator = null; + if (series == Series.UltraScalePlus) { + // Timing model only supports UltraScalePlus currently + boolean useUTurnNodes = true; + delayEstimator = new DelayEstimatorBase(device, new InterconnectInfo(), useUTurnNodes, 0); + TimingModel timingModel = new TimingModel(design.getDevice()); + timingModel.build(); + intrasiteAndLogicDelayModel = timingModel.getDelayModel(); + } + t.start("populateEnums"); populateEnumerations(design, device); @@ -477,7 +497,7 @@ public static void writeDeviceResourcesFile(String part, Device device, CodePerf } t.stop().start("Cell <-> BEL pin map"); - EnumerateCellBelMapping.populateAllPinMappings(part, device, devBuilder, allStrings); + EnumerateCellBelMapping.populateAllPinMappings(part, device, devBuilder, allStrings, intrasiteAndLogicDelayModel); t.stop().start("Packages"); populatePackages(allStrings, device, devBuilder); @@ -629,8 +649,24 @@ public static void writeAllSiteTypesToBuilder(Design design, Device device, Devi for (int j=0; j < allSitePIPs.length; j++) { DeviceResources.Device.SitePIP.Builder spBuilder = spBuilders.get(j); SitePIP sitePIP = allSitePIPs[j]; - spBuilder.setInpin(allBELPins.getIndex(sitePIP.getInputPin())); - spBuilder.setOutpin(allBELPins.getIndex(sitePIP.getOutputPin())); + BELPin inputPin = sitePIP.getInputPin(); + spBuilder.setInpin(allBELPins.getIndex(inputPin)); + BELPin outputPin = sitePIP.getOutputPin(); + spBuilder.setOutpin(allBELPins.getIndex(outputPin)); + + // Write out delay of SitePIP + if (intrasiteAndLogicDelayModel != null) { + BELPin frBelPin = inputPin.getSourcePin(); + String frBelPinString = (frBelPin.isSitePort() ? "" : frBelPin.getBELName() + "/") + frBelPin.getName(); + BELPin toBelPin = outputPin.getSiteConns().get(0); + String toBelPinString = (toBelPin.isSitePort() ? "" : toBelPin.getBELName() + "/") + toBelPin.getName(); + Short delayPs = intrasiteAndLogicDelayModel.getIntraSiteDelay(siteInst.getSiteTypeEnum(), frBelPinString, toBelPinString); + if (delayPs != null && delayPs > 0) { + DeviceResources.Device.CornerModel.Builder delayBuilder = spBuilder.initDelay(); + DeviceResources.Device.CornerModelValues.Builder slowBuilder = delayBuilder.initSlow().initSlow(); + slowBuilder.initMax().setMax(delayPs * PICSECONDS_TO_SECONDS); + } + } } design.removeSiteInst(siteInst); @@ -688,6 +724,9 @@ public static Map writeAllTileTypesToBuilder(Design desig StructList.Builder tileTypesList = devBuilder.initTileTypeList(tileTypes.size()); Map tileTypeIndicies = new HashMap(); + Map slowMaxDelayIndices = new HashMap<>(); + // Make the zero index no delay + slowMaxDelayIndices.put(0f, 0); int i=0; for (Entry e : tileTypes.entrySet()) { @@ -772,10 +811,55 @@ public static Map writeAllTileTypesToBuilder(Design desig k++; } } + + if (delayEstimator != null) { + Node startNode = pip.getStartNode(); + if (!pip.getStartNode().isTied()) { + Node endNode = pip.getEndNode(); + boolean includeBase = true; + boolean includeDiscontinuity = false; + float delayPs = RouterHelper.computeNodeDelay(delayEstimator, endNode, includeBase, includeDiscontinuity); + delayPs += DelayEstimatorBase.getExtraDelay(endNode, DelayEstimatorBase.isLong(startNode)); + if (pip.isRouteThru()) { + if (Utils.isCLB(pip.getTile().getTileTypeEnum())) { + // Site port to cell + com.xilinx.rapidwright.device.SitePin fromSitePin = pip.getStartWire().getSitePin(); + String fromSitePinName = fromSitePin.getPinName(); + assert(fromSitePinName.matches("[A-H][1-6]")); + char lutLetter = fromSitePinName.charAt(0); + char pinNumber = fromSitePinName.charAt(1); + delayPs += intrasiteAndLogicDelayModel.getIntraSiteDelay(SiteTypeEnum.SLICEL, fromSitePinName, lutLetter + "6LUT/A" + pinNumber); + // Through cell + short belIdx = intrasiteAndLogicDelayModel.getBELIndex(lutLetter + "6LUT"); + delayPs += intrasiteAndLogicDelayModel.getLogicDelay(belIdx, "A" + pinNumber, "O6"); + // Cell to site port + com.xilinx.rapidwright.device.SitePin toSitePin = pip.getEndWire().getSitePin(); + String toSitePinName = toSitePin.getPinName(); + assert(toSitePinName.matches("[A-H](_O|MUX)")); + delayPs += intrasiteAndLogicDelayModel.getIntraSiteDelay(SiteTypeEnum.SLICEL, lutLetter + "6LUT/O6", toSitePinName); + } + } + if (delayPs != 0) { + int index = slowMaxDelayIndices.computeIfAbsent(delayPs, (v) -> slowMaxDelayIndices.size()); + pipBuilder.setTiming(index); + } + } + } } + i++; } + StructList.Builder pipTimingsBuilder = devBuilder.initPipTimings(slowMaxDelayIndices.size()); + for (Map.Entry e : slowMaxDelayIndices.entrySet()) { + float slowMaxDelayPs = e.getKey(); + int index = e.getValue(); + DeviceResources.Device.PIPTiming.Builder timingBuilder = pipTimingsBuilder.get(index); + DeviceResources.Device.CornerModel.Builder delayBuilder = timingBuilder.initInternalDelay(); + DeviceResources.Device.CornerModelValues.Builder slowBuilder = delayBuilder.initSlow().initSlow(); + slowBuilder.initMax().setMax(slowMaxDelayPs * PICSECONDS_TO_SECONDS); + } + return tileTypeIndicies; } @@ -843,11 +927,14 @@ public static void writeAllWiresAndNodesToBuilder(Device device, DeviceResources wireBuilder.setType(wire.getIntentCode().ordinal()); } + Map slowMaxDelayIndices = new HashMap<>(); + // Make the zero index no delay + slowMaxDelayIndices.put(0f, 0); + StructList.Builder nodeBuilders = devBuilder.initNodes(allNodes.size()); for (int i=0; i < allNodes.size(); i++) { DeviceResources.Device.Node.Builder nodeBuilder = nodeBuilders.get(i); - //Node node = allNodes.get(i); long nodeKey = allNodes.get(i); Node node = Node.getNode(device.getTile((int)(nodeKey >>> 32)), (int)(nodeKey & 0xffffffff)); Wire[] wires = node.getAllWiresInNode(); @@ -855,6 +942,28 @@ public static void writeAllWiresAndNodesToBuilder(Device device, DeviceResources for (int k=0; k < wires.length; k++) { wBuilders.set(k, allWires.getIndex(makeKey(wires[k].getTile(), wires[k].getWireIndex()))); } + + if (delayEstimator != null && !node.isTied()) { + boolean incldueBase = false; + boolean includeDiscontinuity = true; + float delayPs = RouterHelper.computeNodeDelay(delayEstimator, node, incldueBase, includeDiscontinuity); + if (delayPs != 0) { + int index = slowMaxDelayIndices.computeIfAbsent(delayPs, (v) -> slowMaxDelayIndices.size()); + nodeBuilder.setNodeTiming(index); + } + } + } + + StructList.Builder nodeTimingsBuilder = devBuilder.initNodeTimings(slowMaxDelayIndices.size()); + for (Map.Entry e : slowMaxDelayIndices.entrySet()) { + float slowMaxDelayPs = e.getKey(); + int index = e.getValue(); + DeviceResources.Device.NodeTiming.Builder timingBuilder = nodeTimingsBuilder.get(index); + // Delay represented as T = R * C where R = and C = 1e-12 (1 ps) + DeviceResources.Device.CornerModelValues.Builder resBuilder = timingBuilder.initResistance().initSlow().initSlow(); + resBuilder.initMax().setMax(slowMaxDelayPs); + DeviceResources.Device.CornerModelValues.Builder capBuilder = timingBuilder.initCapacitance().initSlow().initSlow(); + capBuilder.initMax().setMax(PICSECONDS_TO_SECONDS); } } private static void populatePackages(StringEnumerator allStrings, Device device, DeviceResources.Device.Builder devBuilder) { diff --git a/src/com/xilinx/rapidwright/interchange/EnumerateCellBelMapping.java b/src/com/xilinx/rapidwright/interchange/EnumerateCellBelMapping.java index f07697fbf..db36d01b9 100644 --- a/src/com/xilinx/rapidwright/interchange/EnumerateCellBelMapping.java +++ b/src/com/xilinx/rapidwright/interchange/EnumerateCellBelMapping.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, Xilinx, Inc. - * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. + * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. * All rights reserved. * * Author: Keith Rothman, Google, Inc. @@ -27,12 +27,17 @@ import java.util.AbstractMap; import java.util.ArrayList; import java.util.Comparator; +import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import com.xilinx.rapidwright.device.BEL; +import com.xilinx.rapidwright.device.BELPin; +import com.xilinx.rapidwright.timing.DelayModel; import org.capnproto.MessageBuilder; import org.capnproto.StructList; @@ -711,7 +716,14 @@ public static Map> createSiteMap(Device device) { return siteMap; } - public static void populateCellBelPin(StringEnumerator allStrings, Map> siteMap, CellBelMapping.Builder mapping, EDIFCell topLevelCell, EDIFCell cell, Design design) { + public static void populateCellBelPin(StringEnumerator allStrings, + Map> siteMap, + CellBelMapping.Builder mapping, + EDIFCell topLevelCell, + EDIFCell cell, + Design design, + DeviceResources.Device.Builder devBuilder, + DelayModel intrasiteAndLogicDelayModel) { mapping.setCell(allStrings.getIndex(cell.getName())); EDIFCellInst cellInst = new EDIFCellInst("test", cell, topLevelCell); Cell physCell = design.createCell("test", cellInst); @@ -733,6 +745,14 @@ public static void populateCellBelPin(StringEnumerator allStrings, Map pinDelays = (intrasiteAndLogicDelayModel != null) ? new ArrayList<>() : null; + for (Map.Entry possibleSite : entries) { SiteTypeEnum siteType = possibleSite.getKey(); String bel = possibleSite.getValue(); @@ -774,6 +794,41 @@ public static void populateCellBelPin(StringEnumerator allStrings, Map siteType2index = new EnumMap<>(SiteTypeEnum.class); + Map> siteType2belPin2index = new EnumMap<>(SiteTypeEnum.class); + + // First, re-parse the siteTypeList to extract site-type and bel-pin indices + StructList.Reader siteTypesReader = devBuilder.asReader().getSiteTypeList(); + int siteTypeIndex = 0; + for (DeviceResources.Device.SiteType.Reader st : siteTypesReader) { + SiteTypeEnum siteType = SiteTypeEnum.valueOf(allStrings.get(st.getName())); + siteType2index.put(siteType, siteTypeIndex++); + Map belPin2index = new HashMap<>(); + List siteList = siteMap.get(siteType); + Site site = siteList.get(0); + int belPinIndex = 0; + for (DeviceResources.Device.BELPin.Reader bpr : st.getBelPins()) { + String bel = allStrings.get(bpr.getBel()); + String pin = allStrings.get(bpr.getName()); + BELPin bp = site.getBELPin(bel, pin); + belPin2index.put(bp, belPinIndex++); + } + siteType2belPin2index.put(siteType, belPin2index); + } + + StructList.Builder pinDelaysBuilder = mapping.initPinsDelay(pinDelays.size()); + Iterator pinDelaysIt = pinDelaysBuilder.iterator(); + for (PinDelayEntry e : pinDelays) { + DeviceResources.Device.PinsDelay.Builder pd = pinDelaysIt.next(); + Map belPin2index = siteType2belPin2index.get(e.site); + pd.initFirstPin().setPin(belPin2index.get(e.firstPin)); + pd.initSecondPin().setPin(belPin2index.get(e.secondPin)); + pd.initCornerModel().initSlow().initSlow().initMax().setMax(e.delayPs * 1e-12f); + DeviceResources.Device.PinsDelayType type; + if (e.firstPin.isClock()) { + if (e.secondPin.isInput()) { + type = DeviceResources.Device.PinsDelayType.SETUP; + } else { + assert(e.secondPin.isOutput()); + type = DeviceResources.Device.PinsDelayType.CLK2Q; + } + } else { + type = DeviceResources.Device.PinsDelayType.COMB; + } + pd.setPinsDelayType(type); + pd.setSite(siteType2index.get(e.site)); + } + } } - public static void populateAllPinMappings(String part, Device device, DeviceResources.Device.Builder devBuilder, StringEnumerator allStrings) { + public static void populateAllPinMappings(String part, Device device, DeviceResources.Device.Builder devBuilder, StringEnumerator allStrings, DelayModel intrasiteAndLogicDelayModel) { Design design = new Design("top", part); EDIFLibrary prims = Design.getPrimitivesLibrary(design.getDevice().getName()); @@ -820,7 +923,7 @@ public static void populateAllPinMappings(String part, Device device, DeviceReso StructList.Builder cellMapping = devBuilder.initCellBelMap(count); for (EDIFCell cell : prims.getCells()) { if (!macroCells.contains(cell.getName())) { - populateCellBelPin(allStrings, siteMap, cellMapping.get(i), topLevelCell, cell, design); + populateCellBelPin(allStrings, siteMap, cellMapping.get(i), topLevelCell, cell, design, devBuilder, intrasiteAndLogicDelayModel); i += 1; } } @@ -844,7 +947,7 @@ public static void main(String[] args) throws IOException { MessageBuilder message = new MessageBuilder(); DeviceResources.Device.Builder devBuilder = message.initRoot(DeviceResources.Device.factory); - populateAllPinMappings(args[0], device, devBuilder, allStrings); + populateAllPinMappings(args[0], device, devBuilder, allStrings, null); t.stop().printSummary(); } diff --git a/src/com/xilinx/rapidwright/rwroute/RouterHelper.java b/src/com/xilinx/rapidwright/rwroute/RouterHelper.java index 0d69649f5..a1eed632e 100644 --- a/src/com/xilinx/rapidwright/rwroute/RouterHelper.java +++ b/src/com/xilinx/rapidwright/rwroute/RouterHelper.java @@ -580,13 +580,19 @@ public static LightweightRouteNode createRoutingNode(Node node, Map myCellMap) String s2 = ep2.getName(); // RAMB36E2 and RAMB18E2 have the same delay, only that RAMB18E2 will have less pins - short delay = 0; + Short delay = 0; if (s1.startsWith("CLKA")) { // for DSP, we need to look up in the text file // check order_a for A pin, order_b for B pin if (isBramOutPortA(s2)) { @@ -1051,7 +1051,7 @@ void determineLogicDelaysFromEDIFCellInsts(Map myCellMap) delay = intrasiteAndLogicDelayModel.getLogicDelay(belIdx, s1, s2, encodedConfig); } - if (delay < 0) { + if (delay == null) { continue; } @@ -1259,21 +1259,18 @@ else if (myCellName.startsWith("LUT") || myCellName.startsWith("RAM") || myCellN String outputPhysPin = c.getPhysicalPinMapping(ep2.getName()); - float myLogicDelay; + Short myLogicDelay; try { myLogicDelay = intrasiteAndLogicDelayModel.getLogicDelay(belIdx, physPin, outputPhysPin); } catch (IllegalArgumentException e) { continue; } - if (myLogicDelay < 0) { + if (myLogicDelay == null) { continue; } - float LOGIC_DELAY = 0.0f; - - LOGIC_DELAY = myLogicDelay; if (ep2.getName().startsWith("O")) { - logicDelay = LOGIC_DELAY; + logicDelay = myLogicDelay; //break; } @@ -1327,9 +1324,9 @@ else if (myCellName.startsWith("CARRY")) { encodedConfig = 0; } - float myLogicDelay = intrasiteAndLogicDelayModel.getLogicDelay( + Short myLogicDelay = intrasiteAndLogicDelayModel.getLogicDelay( belIdx, physPin, outputPhysPin, encodedConfig); - if (myLogicDelay < 0) { + if (myLogicDelay == null) { continue; } @@ -1506,10 +1503,13 @@ private void dspTimingFileExistenceWarning(String dspBlockFullHierName) { } float getCLKtoOutputDelay(String portName, int encodedConfig) { - float delay = 0; + short delay = 0; short belIdx = intrasiteAndLogicDelayModel.getBELIndex("RAMB36E2"); for (String clk : bramCLKPins) { - delay = Math.max(delay, intrasiteAndLogicDelayModel.getLogicDelay(belIdx, clk, portName, encodedConfig)); + Short newDelay = intrasiteAndLogicDelayModel.getLogicDelay(belIdx, clk, portName, encodedConfig); + if (newDelay != null) { + delay = (short) Math.max(delay, newDelay); + } } return delay; } diff --git a/src/com/xilinx/rapidwright/timing/TimingModel.java b/src/com/xilinx/rapidwright/timing/TimingModel.java index 0a560fcea..6dc949426 100644 --- a/src/com/xilinx/rapidwright/timing/TimingModel.java +++ b/src/com/xilinx/rapidwright/timing/TimingModel.java @@ -1631,9 +1631,11 @@ private void checkForIntrasiteDelay() { else { fromPinName += sourceBELPin.getName(); } - short tmpIntrasiteDelay = intrasiteAndLogicDelayModel.getIntraSiteDelay( + Short tmpIntrasiteDelay = intrasiteAndLogicDelayModel.getIntraSiteDelay( SiteTypeEnum.SLICEL, fromPinName, startPinInst.getName()); - intrasiteDelay += tmpIntrasiteDelay; + if (tmpIntrasiteDelay != null) { + intrasiteDelay += tmpIntrasiteDelay; + } } else if (startPinInst.getName().endsWith("_O")) { intrasiteDelay += INTRASITE_DELAY_LUT_OUTPUT_TO_O_SITEPIN; diff --git a/src/com/xilinx/rapidwright/timing/delayestimator/DelayEstimatorBase.java b/src/com/xilinx/rapidwright/timing/delayestimator/DelayEstimatorBase.java index 259745f68..3c80bfe4b 100644 --- a/src/com/xilinx/rapidwright/timing/delayestimator/DelayEstimatorBase.java +++ b/src/com/xilinx/rapidwright/timing/delayestimator/DelayEstimatorBase.java @@ -1,7 +1,7 @@ /* * * Copyright (c) 2021-2022, Xilinx, Inc. - * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. + * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. * All rights reserved. * * Author: Pongstorn Maidee, Xilinx Research Labs. @@ -119,6 +119,17 @@ public static short getExtraDelay(Node child, boolean longParent) { return 0; } + public short getDelayOf(Node exitNode, boolean includeBase, boolean includeDiscontinuity) { + TermInfo termInfo = getTermInfo(exitNode); + + // Don't put this in calcTimingGroupDelay because it is called many times to estimate delay. + if (includeBase && termInfo.ng == T.NodeGroupType.CLE_IN) { + return inputSitePinDelay.getOrDefault(exitNode.getWireName(), (short) 0); + } + + return calcNodeGroupDelay(termInfo.ng, termInfo.begin(), termInfo.end(), includeBase, includeDiscontinuity); + } + /** * Get delay of the node group of the given exit node. @@ -127,14 +138,7 @@ public static short getExtraDelay(Node child, boolean longParent) { * @return delay in ps */ public short getDelayOf(Node exitNode) { - TermInfo termInfo = getTermInfo(exitNode); - - // Don't put this in calcTimingGroupDelay because it is called many times to estimate delay. - if (termInfo.ng == T.NodeGroupType.CLE_IN) { - return inputSitePinDelay.getOrDefault(exitNode.getWireName(), (short) 0); - } - - return calcNodeGroupDelay(termInfo.ng, termInfo.begin(), termInfo.end()); + return getDelayOf(exitNode, true, true); } /** @@ -425,7 +429,20 @@ private void buildDistanceArrays(TimingModel tm) { * @return delay of the tg. When useUTurnNodes was set to false, return Short.MAX_VALUE/2 if the node graph is a U-turn. * to indicate the node graph should be ignored. */ - short calcNodeGroupDelay(T.NodeGroupType tg, short begLoc, short endLoc) { + short calcNodeGroupDelay(T.NodeGroupType tg, short begLoc, short endLoc, boolean includeBase, boolean includeDiscontinuity) { + short segDelay = (includeBase) ? calcNodeBaseDelay(tg) : 0; + short disDelay = (includeDiscontinuity) ? calcNodeDiscontinuityDelay(tg, begLoc, endLoc) : 0; + return (short) (segDelay + disDelay); + } + + short calcNodeBaseDelay(T.NodeGroupType tg) { + float k0 = K0.get(tg.orientation()).get(tg.type()); + float k1 = K1.get(tg.orientation()).get(tg.type()); + short l = L .get(tg.orientation()).get(tg.type()); + return (short) (k0 + k1 * l); + } + + short calcNodeDiscontinuityDelay(T.NodeGroupType tg, short begLoc, short endLoc) { int size = (tg.orientation() == T.Orientation.HORIZONTAL) ? numCol : numRow; short d = 0; List dArray = distArrays.get(tg.orientation()).get(tg.type()); @@ -451,11 +468,7 @@ short calcNodeGroupDelay(T.NodeGroupType tg, short begLoc, short endLoc) { } } - float k0 = K0.get(tg.orientation()).get(tg.type()); - float k1 = K1.get(tg.orientation()).get(tg.type()); float k2 = K2.get(tg.orientation()).get(tg.type()); - short l = L .get(tg.orientation()).get(tg.type()); - - return (short) (k0 + k1 * l + k2 * d); + return (short) (k2 * d); } } diff --git a/test/src/com/xilinx/rapidwright/interchange/TestCellBELMappings.java b/test/src/com/xilinx/rapidwright/interchange/TestCellBELMappings.java index 3cec807be..632a541b4 100644 --- a/test/src/com/xilinx/rapidwright/interchange/TestCellBELMappings.java +++ b/test/src/com/xilinx/rapidwright/interchange/TestCellBELMappings.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, Xilinx, Inc. - * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. + * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. * All rights reserved. * * Author: Chris Lavin, Xilinx Research Labs. @@ -40,7 +40,8 @@ public void testCellBELPinMappings() { MessageBuilder message = new MessageBuilder(); Device device = Device.getDevice(TestDeviceResources.TEST_DEVICE); DeviceResources.Device.Builder devBuilder = message.initRoot(DeviceResources.Device.factory); - EnumerateCellBelMapping.populateAllPinMappings(device.getName(), device, devBuilder, allStrings); + EnumerateCellBelMapping + .populateAllPinMappings(device.getName(), device, devBuilder, allStrings, null); boolean foundIDDRS = false; boolean foundIDDRR = false; diff --git a/test/src/com/xilinx/rapidwright/interchange/TestDeviceResources.java b/test/src/com/xilinx/rapidwright/interchange/TestDeviceResources.java index 805ab3795..00f9a7db5 100644 --- a/test/src/com/xilinx/rapidwright/interchange/TestDeviceResources.java +++ b/test/src/com/xilinx/rapidwright/interchange/TestDeviceResources.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, Xilinx, Inc. - * Copyright (c) 2022, Advanced Micro Devices, Inc. + * Copyright (c) 2022, 2024, Advanced Micro Devices, Inc. * All rights reserved. * * Author: Chris Lavin, Xilinx Research Labs. @@ -26,11 +26,17 @@ import java.io.IOException; import java.nio.file.Path; +import org.capnproto.MessageReader; +import org.capnproto.ReaderOptions; +import org.capnproto.TextList; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import com.xilinx.rapidwright.device.Device; import com.xilinx.rapidwright.tests.CodePerfTracker; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; public class TestDeviceResources { @@ -46,5 +52,54 @@ public void testDeviceResources(@TempDir Path tempDir) throws IOException { DeviceResourcesVerifier.verifyDeviceResources(capnProtoFile.toString(), TEST_DEVICE); } + @ParameterizedTest + @CsvSource({ + "xcau10p" + }) + public void testUltraScalePlusTiming(String deviceName, @TempDir Path tempDir) throws IOException { + Path capnProtoFile = tempDir.resolve(deviceName + ".device"); + Device device = Device.getDevice(deviceName); + DeviceResourcesWriter.writeDeviceResourcesFile( + deviceName, device, CodePerfTracker.SILENT, capnProtoFile.toString()); + + ReaderOptions readerOptions = new ReaderOptions(1024L * 1024L * 1024L * 64L, 64); + MessageReader readMsg = Interchange.readInterchangeFile(capnProtoFile.toString(), readerOptions); + DeviceResources.Device.Reader dReader = readMsg.getRoot(DeviceResources.Device.factory); + + Assertions.assertTrue(dReader.getPipTimings().size() > 1); + Assertions.assertTrue(dReader.getNodeTimings().size() > 1); + TextList.Reader sReader = dReader.getStrList(); + + // Check SitePIPs have at least one delay + int reached = 0; + for (DeviceResources.Device.SiteType.Reader st : dReader.getSiteTypeList()) { + String name = sReader.get(st.getName()).toString(); + if (!name.startsWith("SLICE")) { + continue; + } + for (DeviceResources.Device.SitePIP.Reader sp : st.getSitePIPs()) { + if (sp.hasDelay()) { + reached++; + break; + } + } + } + // {SLICEL,SLICEM} + Assertions.assertEquals(2, reached); + + // Check Cells have at least one delay + reached = 0; + for (DeviceResources.Device.CellBelMapping.Reader cb : dReader.getCellBelMap()) { + String name = sReader.get(cb.getCell()).toString(); + if (!name.startsWith("LUT")) { + continue; + } + if (cb.hasPinsDelay()) { + reached++; + } + } + // LUT[1-6] + Assertions.assertEquals(6, reached); + } }